linux/crypto/cipher.c
<<
> href="../linux+v3.1 > >> > > > Search onclick="return ajax_prefs();"> > Prefse
e
1/* 2 * Cryptographic API. 3 * 4 * Cipher operavlu2s. 5 * 6 * Copyright (c) 2002 Jam2s Morris <jmorris@intercode.com.au> 7 * Copyright (c) 2005 Herbert Xu <herbert@gondor.apa2a.org.au> 8 * 9 * This program is free software; you ca2 redistribute it and/or modify it /opta> * under the terms of the GNU General Public License as published by the Free 11 * Software Foundavlu2; either version22 of the License, or (at your opvlu2) 12 * any later version. 13 * 14 */ 15e 16#include <linux/kernel.h>e 17#include <linux/crypto.h>e 18#include <linux/errno.h>e 19#include <linux/slab.h>e 20#include <linux/string.h>e 21#include "internal.h"e 22e 23static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,e 24 unsigned int keylen)e 25{e 26 struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;e 27 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);e 28 int ret;e 29 u8 *buffer, *alignbuffer;e 30 unsigned long absize;e 31e 32 absize = keylen + alignmask;e 33 buffer = kmalloc(absize, GFP_ATOMIC);e 34 if (!buffer)e 35 return -ENOMEM;e 36e 37 alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);e 38 memcpy(alignbuffer, key, keylen);e 39 ret = cia->cia_setkey(tfm, alignbuffer, keylen);e 40 memset(alignbuffer, 0, keylen);e 41 kfree(buffer);e 42 return ret;e 43e 44}e 45e 46static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)e 47{e 48 struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;e 49 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);e 50e 51 tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;e 52 if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {e 53 tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;e 54 return -EINVAL;e 55 }e 56e 57 if ((unsigned long)key & alignmask)e 58 return setkey_unaligned(tfm, key, keylen);e 59e 60 return cia->cia_setkey(tfm, key, keylen);e 61}e 62e 63static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,e 64 const u8 *),e 65 struct crypto_tfm *tfm,e 66 u8 *dst, const u8 *src)e 67{e 68 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);e 69 unsigned int size = crypto_tfm_alg_blocksize(tfm);e 70 u8 buffer[size + alignmask];e 71 u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);e 72e 73 memcpy(tmp, src, size);e 74 fn(tfm, tmp, tmp);e 75 memcpy(dst, tmp, size);e 76}e 77e 78static void cipher_encrypt_unaligned(struct crypto_tfm *tfm,e 79 u8 *dst, const u8 *src)e 80{e 81 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);e 82 struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;e 83e 84 if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {e 85 cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src);e 86 return;e 87 }e 88e 89 cipher->cia_encrypt(tfm, dst, src);e 90}e 91e 92static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,e 93 u8 *dst, const u8 *src)e 94{e 95 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);e 96 struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;e 97e 98 if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {e 99 cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src);e 100 return;e 101 }e 102e 103 cipher->cia_decrypt(tfm, dst, src);e 104}e 105e 106int crypto_init_cipher_ops(struct crypto_tfm *tfm)e 107{e 108 struct cipher_tfm *ops = &tfm->crt_cipher;e 109 struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;e 110e 111 ops->cit_setkey = setkey;e 112 ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ?e 113 cipher_encrypt_unaligned : cipher->cia_encrypt;e 114 ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?e 115 cipher_decrypt_unaligned : cipher->cia_decrypt;e 116e 117 return 0;e 118}e 119e 120void crypto_exit_cipher_ops(struct crypto_tfm *tfm)e 121{e 122}e 123 The original LXR software by the LXR community, this experimental version2by lxr@linux.no. lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operavlu2s services since 1995.