Blame view
crypto/cipher.c
3.26 KB
1da177e4c
|
1 2 3 4 5 6 |
/* * Cryptographic API. * * Cipher operations. * * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
c774e93e2
|
7 |
* Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> |
1da177e4c
|
8 9 10 |
* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free |
d150975bc
|
11 |
* Software Foundation; either version 2 of the License, or (at your option) |
1da177e4c
|
12 13 14 |
* any later version. * */ |
f1ddcaf33
|
15 |
|
1da177e4c
|
16 17 18 |
#include <linux/kernel.h> #include <linux/crypto.h> #include <linux/errno.h> |
791b4d5f7
|
19 |
#include <linux/slab.h> |
1da177e4c
|
20 |
#include <linux/string.h> |
1da177e4c
|
21 |
#include "internal.h" |
1da177e4c
|
22 |
|
791b4d5f7
|
23 24 |
static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) |
ca7c39385
|
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
{ struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); int ret; u8 *buffer, *alignbuffer; unsigned long absize; absize = keylen + alignmask; buffer = kmalloc(absize, GFP_ATOMIC); if (!buffer) return -ENOMEM; alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(alignbuffer, key, keylen); ret = cia->cia_setkey(tfm, alignbuffer, keylen); |
068171767
|
40 |
memset(alignbuffer, 0, keylen); |
ca7c39385
|
41 42 43 44 |
kfree(buffer); return ret; } |
1da177e4c
|
45 46 47 |
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; |
ca7c39385
|
48 |
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); |
560c06ae1
|
49 |
tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; |
1da177e4c
|
50 51 52 |
if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; |
ca7c39385
|
53 54 55 56 57 58 |
} if ((unsigned long)key & alignmask) return setkey_unaligned(tfm, key, keylen); return cia->cia_setkey(tfm, key, keylen); |
1da177e4c
|
59 |
} |
f28776a36
|
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, const u8 *), struct crypto_tfm *tfm, u8 *dst, const u8 *src) { unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); unsigned int size = crypto_tfm_alg_blocksize(tfm); u8 buffer[size + alignmask]; u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); memcpy(tmp, src, size); fn(tfm, tmp, tmp); memcpy(dst, tmp, size); } static void cipher_encrypt_unaligned(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src); return; } cipher->cia_encrypt(tfm, dst, src); } static void cipher_decrypt_unaligned(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src); return; } cipher->cia_decrypt(tfm, dst, src); } |
1da177e4c
|
102 103 |
int crypto_init_cipher_ops(struct crypto_tfm *tfm) { |
1da177e4c
|
104 |
struct cipher_tfm *ops = &tfm->crt_cipher; |
f28776a36
|
105 |
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; |
1da177e4c
|
106 107 |
ops->cit_setkey = setkey; |
f28776a36
|
108 109 110 111 |
ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ? cipher_encrypt_unaligned : cipher->cia_encrypt; ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ? cipher_decrypt_unaligned : cipher->cia_decrypt; |
1da177e4c
|
112 |
|
f1ddcaf33
|
113 |
return 0; |
1da177e4c
|
114 |
} |