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/dev/cgd_crypto.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 /* $NetBSD: cgd_crypto.c,v 1.9 2008/04/28 20:23:46 martin Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Roland C. Dowdeswell.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  *  Crypto Framework For cgd.c
   34  *
   35  *      This framework is temporary and awaits a more complete
   36  *      kernel wide crypto implementation.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c,v 1.9 2008/04/28 20:23:46 martin Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 
   46 #include <dev/cgd_crypto.h>
   47 
   48 #ifdef DIAGNOSTIC
   49 #define DIAGPANIC(x)    panic x
   50 #else
   51 #define DIAGPANIC(x)
   52 #endif
   53 
   54 /*
   55  * The general framework provides only one generic function.
   56  * It takes the name of an algorith and returns a struct cryptfuncs *
   57  * for it.  It is up to the initialisation routines of the algorithm
   58  * to check key size and block size.
   59  */
   60 
   61 extern struct cryptfuncs cgd_AES_funcs;
   62 extern struct cryptfuncs cgd_3des_funcs;
   63 extern struct cryptfuncs cgd_BF_funcs;
   64 
   65 struct cryptfuncs *
   66 cryptfuncs_find(const char *alg)
   67 {
   68 
   69         if (!strcmp("aes-cbc", alg))
   70                 return &cgd_AES_funcs;
   71         if (!strcmp("3des-cbc", alg))
   72                 return &cgd_3des_funcs;
   73         if (!strcmp("blowfish-cbc", alg))
   74                 return &cgd_BF_funcs;
   75         return NULL;
   76 }
   77 
   78 typedef void    (*cipher_func)(void *, void *, const void *, size_t);
   79 
   80 void
   81 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
   82         struct uio *dstuio, struct uio *srcuio);
   83 
   84 /*
   85  * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
   86  * it over two struct uio's.  It presumes that the cipher function
   87  * that is passed to it keeps the IV state between calls.
   88  *
   89  * We assume that the caller has ensured that each segment is evenly
   90  * divisible by the block size, which for the cgd is a valid assumption.
   91  * If we were to make this code more generic, we might need to take care
   92  * of this case, either by issuing an error or copying the data.
   93  */
   94 
   95 void
   96 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
   97     struct uio *dstuio, struct uio *srcuio)
   98 {
   99         struct iovec    *dst;
  100         struct iovec    *src;
  101         int              dstnum;
  102         int              dstoff = 0;
  103         int              srcnum;
  104         int              srcoff = 0;
  105 
  106         dst = dstuio->uio_iov;
  107         dstnum = dstuio->uio_iovcnt;
  108         src = srcuio->uio_iov;
  109         srcnum = srcuio->uio_iovcnt;
  110         for (;;) {
  111                 int       l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
  112                 u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
  113                 u_int8_t *s = (u_int8_t *)src->iov_base + srcoff;
  114 
  115                 cipher(privdata, d, s, l);
  116 
  117                 dstoff += l;
  118                 srcoff += l;
  119                 /*
  120                  * We assume that {dst,src} == {dst,src}->iov_len,
  121                  * because it should not be possible for it not to be.
  122                  */
  123                 if (dstoff == dst->iov_len) {
  124                         dstoff = 0;
  125                         dstnum--;
  126                         dst++;
  127                 }
  128                 if (srcoff == src->iov_len) {
  129                         srcoff = 0;
  130                         srcnum--;
  131                         src++;
  132                 }
  133                 if (!srcnum || !dstnum)
  134                         break;
  135         }
  136 }
  137 
  138 /*
  139  *  AES Framework
  140  */
  141 
  142 #include <crypto/rijndael/rijndael-api-fst.h>
  143 
  144 cfunc_init      cgd_cipher_aes_init;
  145 cfunc_destroy   cgd_cipher_aes_destroy;
  146 cfunc_cipher    cgd_cipher_aes_cbc;
  147 
  148 struct cryptfuncs cgd_AES_funcs = {
  149         cgd_cipher_aes_init,
  150         cgd_cipher_aes_destroy,
  151         cgd_cipher_aes_cbc,
  152 };
  153 
  154 /*
  155  * NOTE: we do not store the blocksize in here, because it is not
  156  *       variable [yet], we hardcode the blocksize to 16 (128 bits).
  157  */
  158 
  159 struct aes_privdata {
  160         keyInstance     ap_enckey;
  161         keyInstance     ap_deckey;
  162 };
  163 
  164 struct aes_encdata {
  165         keyInstance     *ae_key;        /* key for this direction */
  166         u_int8_t         ae_iv[16];     /* Initialization Vector */
  167 };
  168 
  169 static void     aes_cbc_enc_int(void *, void *, const void *, size_t);
  170 static void     aes_cbc_dec_int(void *, void *, const void *, size_t);
  171 
  172 void *
  173 cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize)
  174 {
  175         struct  aes_privdata *ap;
  176 
  177         if (!blocksize)
  178                 return NULL;
  179         if (keylen != 128 && keylen != 192 && keylen != 256)
  180                 return NULL;
  181         if (*blocksize == (size_t)-1)
  182                 *blocksize = 128;
  183         if (*blocksize != 128)
  184                 return NULL;
  185         ap = malloc(sizeof(*ap), M_DEVBUF, 0);
  186         if (!ap)
  187                 return NULL;
  188         rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
  189         rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
  190         return ap;
  191 }
  192 
  193 void
  194 cgd_cipher_aes_destroy(void *data)
  195 {
  196         struct aes_privdata *apd = data;
  197 
  198         (void)memset(apd, 0, sizeof(*apd));
  199         free(apd, M_DEVBUF);
  200 }
  201 
  202 void
  203 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
  204 {
  205         struct aes_encdata      *ae = privdata;
  206         cipherInstance           cipher;
  207 
  208         rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
  209         rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
  210         (void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
  211 }
  212 
  213 void
  214 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
  215 {
  216         struct aes_encdata      *ae = privdata;
  217         cipherInstance           cipher;
  218 
  219         rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
  220         rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
  221         (void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16);
  222 }
  223 
  224 void
  225 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
  226     struct uio *srcuio, void *iv, int dir)
  227 {
  228         struct aes_privdata     *apd = privdata;
  229         struct aes_encdata       encd;
  230 
  231         (void)memcpy(encd.ae_iv, iv, 16);
  232         switch (dir) {
  233         case CGD_CIPHER_ENCRYPT:
  234                 encd.ae_key = &apd->ap_enckey;
  235                 cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
  236                 break;
  237         case CGD_CIPHER_DECRYPT:
  238                 encd.ae_key = &apd->ap_deckey;
  239                 cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
  240                 break;
  241         default:
  242                 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
  243         }
  244 }
  245 
  246 /*
  247  * 3DES Framework
  248  */
  249 
  250 #include <crypto/des/des.h>
  251 
  252 cfunc_init      cgd_cipher_3des_init;
  253 cfunc_destroy   cgd_cipher_3des_destroy;
  254 cfunc_cipher    cgd_cipher_3des_cbc;
  255 
  256 struct cryptfuncs cgd_3des_funcs = {
  257         cgd_cipher_3des_init,
  258         cgd_cipher_3des_destroy,
  259         cgd_cipher_3des_cbc,
  260 };
  261 
  262 struct c3des_privdata {
  263         des_key_schedule        cp_key1;
  264         des_key_schedule        cp_key2;
  265         des_key_schedule        cp_key3;
  266 };
  267 
  268 static void     c3des_cbc_enc_int(void *, void *, const void *, size_t);
  269 static void     c3des_cbc_dec_int(void *, void *, const void *, size_t);
  270 
  271 struct c3des_encdata {
  272         des_key_schedule        *ce_key1;
  273         des_key_schedule        *ce_key2;
  274         des_key_schedule        *ce_key3;
  275         u_int8_t                ce_iv[8];
  276 };
  277 
  278 void *
  279 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
  280 {
  281         struct  c3des_privdata *cp;
  282         int     error = 0;
  283         des_cblock *block;
  284 
  285         if (!blocksize)
  286                 return NULL;
  287         if (*blocksize == (size_t)-1)
  288                 *blocksize = 64;
  289         if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
  290                 return NULL;
  291         cp = malloc(sizeof(*cp), M_DEVBUF, 0);
  292         if (!cp)
  293                 return NULL;
  294         block = __UNCONST(key);
  295         error  = des_key_sched(block, cp->cp_key1);
  296         error |= des_key_sched(block + 1, cp->cp_key2);
  297         error |= des_key_sched(block + 2, cp->cp_key3);
  298         if (error) {
  299                 (void)memset(cp, 0, sizeof(*cp));
  300                 free(cp, M_DEVBUF);
  301                 return NULL;
  302         }
  303         return cp;
  304 }
  305 
  306 void
  307 cgd_cipher_3des_destroy(void *data)
  308 {
  309         struct c3des_privdata *cp = data;
  310 
  311         (void)memset(cp, 0, sizeof(*cp));
  312         free(cp, M_DEVBUF);
  313 }
  314 
  315 static void
  316 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
  317 {
  318         struct  c3des_encdata *ce = privdata;
  319 
  320         des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
  321             *ce->ce_key3, (des_cblock *)ce->ce_iv, 1);
  322         (void)memcpy(ce->ce_iv, (const u_int8_t *)dst + (len - 8), 8);
  323 }
  324 
  325 static void
  326 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
  327 {
  328         struct  c3des_encdata *ce = privdata;
  329 
  330         des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
  331             *ce->ce_key3, (des_cblock *)ce->ce_iv, 0);
  332         (void)memcpy(ce->ce_iv, (const u_int8_t *)src + (len - 8), 8);
  333 }
  334 
  335 void
  336 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
  337         struct uio *srcuio, void *iv, int dir)
  338 {
  339         struct  c3des_privdata *cp = privdata;
  340         struct  c3des_encdata ce;
  341 
  342         (void)memcpy(ce.ce_iv, iv, 8);
  343         ce.ce_key1 = &cp->cp_key1;
  344         ce.ce_key2 = &cp->cp_key2;
  345         ce.ce_key3 = &cp->cp_key3;
  346         switch (dir) {
  347         case CGD_CIPHER_ENCRYPT:
  348                 cgd_cipher_uio_cbc(&ce, c3des_cbc_enc_int, dstuio, srcuio);
  349                 break;
  350         case CGD_CIPHER_DECRYPT:
  351                 cgd_cipher_uio_cbc(&ce, c3des_cbc_dec_int, dstuio, srcuio);
  352                 break;
  353         default:
  354                 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
  355         }
  356 }
  357 
  358 /*
  359  * Blowfish Framework
  360  */
  361 
  362 #include <crypto/blowfish/blowfish.h>
  363 
  364 cfunc_init      cgd_cipher_bf_init;
  365 cfunc_destroy   cgd_cipher_bf_destroy;
  366 cfunc_cipher    cgd_cipher_bf_cbc;
  367 
  368 struct cryptfuncs cgd_BF_funcs = {
  369         cgd_cipher_bf_init,
  370         cgd_cipher_bf_destroy,
  371         cgd_cipher_bf_cbc,
  372 };
  373 
  374 static void     bf_cbc_enc_int(void *, void *, const void *, size_t);
  375 static void     bf_cbc_dec_int(void *, void *, const void *, size_t);
  376 
  377 struct bf_privdata {
  378         BF_KEY  bp_key;
  379 };
  380 
  381 struct bf_encdata {
  382         BF_KEY          *be_key;
  383         u_int8_t         be_iv[8];
  384 };
  385 
  386 void *
  387 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
  388 {
  389         struct  bf_privdata *bp;
  390 
  391         if (!blocksize)
  392                 return NULL;
  393         if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
  394                 return NULL;
  395         if (*blocksize == (size_t)-1)
  396                 *blocksize = 64;
  397         if (*blocksize != 64)
  398                 return NULL;
  399         bp = malloc(sizeof(*bp), M_DEVBUF, 0);
  400         if (!bp)
  401                 return NULL;
  402         BF_set_key(&bp->bp_key, keylen / 8, key);
  403         return bp;
  404 }
  405 
  406 void
  407 cgd_cipher_bf_destroy(void *data)
  408 {
  409         struct  bf_privdata *bp = data;
  410 
  411         (void)memset(bp, 0, sizeof(*bp));
  412         free(bp, M_DEVBUF);
  413 }
  414 
  415 void
  416 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
  417 {
  418         struct  bf_encdata *be = privdata;
  419 
  420         BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
  421         (void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
  422 }
  423 
  424 void
  425 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
  426 {
  427         struct  bf_encdata *be = privdata;
  428 
  429         BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
  430         (void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8);
  431 }
  432 
  433 void
  434 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
  435     struct uio *srcuio, void *iv, int dir)
  436 {
  437         struct  bf_privdata *bp = privdata;
  438         struct  bf_encdata be;
  439 
  440         (void)memcpy(be.be_iv, iv, 8);
  441         be.be_key = &bp->bp_key;
  442         switch (dir) {
  443         case CGD_CIPHER_ENCRYPT:
  444                 cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
  445                 break;
  446         case CGD_CIPHER_DECRYPT:
  447                 cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
  448                 break;
  449         default:
  450                 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
  451         }
  452 
  453 }

Cache object: 52b08948744018bbe54ce8ca0bb15199


[ 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.