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

Cache object: d31c828262772faba244ae195cf59386


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