Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/crypto/cipher.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us