The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/cipher.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
  120 void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
  121 {
  122 }

Cache object: c4dbc7baeedc6723c23ee5f872c62912


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.