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/via/padlock_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  * Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    3  * Copyright (c) 2004 Mark R V Murray
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*      $OpenBSD: via.c,v 1.3 2004/06/15 23:36:55 deraadt Exp $ */
   29 /*-
   30  * Copyright (c) 2003 Jason Wright
   31  * Copyright (c) 2003, 2004 Theo de Raadt
   32  * All rights reserved.
   33  *
   34  * Permission to use, copy, modify, and distribute this software for any
   35  * purpose with or without fee is hereby granted, provided that the above
   36  * copyright notice and this permission notice appear in all copies.
   37  *
   38  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   39  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   40  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   41  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   42  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   43  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   44  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __FBSDID("$FreeBSD: releng/6.4/sys/crypto/via/padlock_cipher.c 162429 2006-09-19 11:06:15Z pjd $");
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/kernel.h>
   53 #include <sys/module.h>
   54 #include <sys/malloc.h>
   55 #include <sys/libkern.h>
   56 #include <sys/uio.h>
   57 
   58 #include <opencrypto/cryptodev.h>
   59 #include <crypto/rijndael/rijndael.h>
   60 
   61 #include <crypto/via/padlock.h>
   62 
   63 #define PADLOCK_ROUND_COUNT_AES128      10
   64 #define PADLOCK_ROUND_COUNT_AES192      12
   65 #define PADLOCK_ROUND_COUNT_AES256      14
   66 
   67 #define PADLOCK_ALGORITHM_TYPE_AES      0
   68 
   69 #define PADLOCK_KEY_GENERATION_HW       0
   70 #define PADLOCK_KEY_GENERATION_SW       1
   71 
   72 #define PADLOCK_DIRECTION_ENCRYPT       0
   73 #define PADLOCK_DIRECTION_DECRYPT       1
   74 
   75 #define PADLOCK_KEY_SIZE_128    0
   76 #define PADLOCK_KEY_SIZE_192    1
   77 #define PADLOCK_KEY_SIZE_256    2
   78 
   79 MALLOC_DECLARE(M_PADLOCK);
   80 
   81 static __inline void
   82 padlock_cbc(void *in, void *out, size_t count, void *key, union padlock_cw *cw,
   83     void *iv)
   84 {
   85 #ifdef __GNUCLIKE_ASM
   86         /* The .byte line is really VIA C3 "xcrypt-cbc" instruction */
   87         __asm __volatile(
   88                 "pushf                          \n\t"
   89                 "popf                           \n\t"
   90                 "rep                            \n\t"
   91                 ".byte  0x0f, 0xa7, 0xd0"
   92                         : "+a" (iv), "+c" (count), "+D" (out), "+S" (in)
   93                         : "b" (key), "d" (cw)
   94                         : "cc", "memory"
   95                 );
   96 #endif
   97 }
   98 
   99 static void
  100 padlock_cipher_key_setup(struct padlock_session *ses, caddr_t key, int klen)
  101 {
  102         union padlock_cw *cw;
  103         int i;
  104 
  105         cw = &ses->ses_cw;
  106         if (cw->cw_key_generation == PADLOCK_KEY_GENERATION_SW) {
  107                 /* Build expanded keys for both directions */
  108                 rijndaelKeySetupEnc(ses->ses_ekey, key, klen);
  109                 rijndaelKeySetupDec(ses->ses_dkey, key, klen);
  110                 for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
  111                         ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
  112                         ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
  113                 }
  114         } else {
  115                 bcopy(key, ses->ses_ekey, klen);
  116                 bcopy(key, ses->ses_dkey, klen);
  117         }
  118 }
  119 
  120 int
  121 padlock_cipher_setup(struct padlock_session *ses, struct cryptoini *encini)
  122 {
  123         union padlock_cw *cw;
  124 
  125         if (encini->cri_klen != 128 && encini->cri_klen != 192 &&
  126             encini->cri_klen != 256) {
  127                 return (EINVAL);
  128         }
  129 
  130         cw = &ses->ses_cw;
  131         bzero(cw, sizeof(*cw));
  132         cw->cw_algorithm_type = PADLOCK_ALGORITHM_TYPE_AES;
  133         cw->cw_key_generation = PADLOCK_KEY_GENERATION_SW;
  134         cw->cw_intermediate = 0;
  135         switch (encini->cri_klen) {
  136         case 128:
  137                 cw->cw_round_count = PADLOCK_ROUND_COUNT_AES128;
  138                 cw->cw_key_size = PADLOCK_KEY_SIZE_128;
  139 #ifdef HW_KEY_GENERATION
  140                 /* This doesn't buy us much, that's why it is commented out. */
  141                 cw->cw_key_generation = PADLOCK_KEY_GENERATION_HW;
  142 #endif
  143                 break;
  144         case 192:
  145                 cw->cw_round_count = PADLOCK_ROUND_COUNT_AES192;
  146                 cw->cw_key_size = PADLOCK_KEY_SIZE_192;
  147                 break;
  148         case 256:
  149                 cw->cw_round_count = PADLOCK_ROUND_COUNT_AES256;
  150                 cw->cw_key_size = PADLOCK_KEY_SIZE_256;
  151                 break;
  152         }
  153         if (encini->cri_key != NULL) {
  154                 padlock_cipher_key_setup(ses, encini->cri_key,
  155                     encini->cri_klen);
  156         }
  157 
  158         arc4rand(ses->ses_iv, sizeof(ses->ses_iv), 0);
  159         return (0);
  160 }
  161 
  162 /*
  163  * Function checks if the given buffer is already 16 bytes aligned.
  164  * If it is there is no need to allocate new buffer.
  165  * If it isn't, new buffer is allocated.
  166  */
  167 static u_char *
  168 padlock_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp,
  169     int *allocated)
  170 {
  171         u_char *addr;
  172 
  173         if (crp->crp_flags & CRYPTO_F_IMBUF)
  174                 goto alloc;
  175         else {
  176                 if (crp->crp_flags & CRYPTO_F_IOV) {
  177                         struct uio *uio;
  178                         struct iovec *iov;
  179 
  180                         uio = (struct uio *)crp->crp_buf;
  181                         if (uio->uio_iovcnt != 1)
  182                                 goto alloc;
  183                         iov = uio->uio_iov;
  184                         addr = (u_char *)iov->iov_base + enccrd->crd_skip;
  185                 } else {
  186                         addr = (u_char *)crp->crp_buf;
  187                 }
  188                 if (((uintptr_t)addr & 0xf) != 0) /* 16 bytes aligned? */
  189                         goto alloc;
  190                 *allocated = 0;
  191                 return (addr);
  192         }
  193 alloc:
  194         *allocated = 1;
  195         addr = malloc(enccrd->crd_len + 16, M_PADLOCK, M_NOWAIT);
  196         return (addr);
  197 }
  198 
  199 int
  200 padlock_cipher_process(struct padlock_session *ses, struct cryptodesc *enccrd,
  201     struct cryptop *crp)
  202 {
  203         union padlock_cw *cw;
  204         u_char *buf, *abuf;
  205         uint32_t *key;
  206         int allocated;
  207 
  208         buf = padlock_cipher_alloc(enccrd, crp, &allocated);
  209         if (buf == NULL)
  210                 return (ENOMEM);
  211         /* Buffer has to be 16 bytes aligned. */
  212         abuf = PADLOCK_ALIGN(buf);
  213 
  214         if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
  215                 padlock_cipher_key_setup(ses, enccrd->crd_key,
  216                     enccrd->crd_klen);
  217         }
  218 
  219         cw = &ses->ses_cw;
  220         cw->cw_filler0 = 0;
  221         cw->cw_filler1 = 0;
  222         cw->cw_filler2 = 0;
  223         cw->cw_filler3 = 0;
  224         if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
  225                 cw->cw_direction = PADLOCK_DIRECTION_ENCRYPT;
  226                 key = ses->ses_ekey;
  227                 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
  228                         bcopy(enccrd->crd_iv, ses->ses_iv, AES_BLOCK_LEN);
  229 
  230                 if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
  231                         crypto_copyback(crp->crp_flags, crp->crp_buf,
  232                             enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
  233                 }
  234         } else {
  235                 cw->cw_direction = PADLOCK_DIRECTION_DECRYPT;
  236                 key = ses->ses_dkey;
  237                 if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
  238                         bcopy(enccrd->crd_iv, ses->ses_iv, AES_BLOCK_LEN);
  239                 else {
  240                         crypto_copydata(crp->crp_flags, crp->crp_buf,
  241                             enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
  242                 }
  243         }
  244 
  245         if (allocated) {
  246                 crypto_copydata(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
  247                     enccrd->crd_len, abuf);
  248         }
  249 
  250         padlock_cbc(abuf, abuf, enccrd->crd_len / AES_BLOCK_LEN, key, cw,
  251             ses->ses_iv);
  252 
  253         if (allocated) {
  254                 crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
  255                     enccrd->crd_len, abuf);
  256         }
  257 
  258         /* copy out last block for use as next session IV */
  259         if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
  260                 crypto_copydata(crp->crp_flags, crp->crp_buf,
  261                     enccrd->crd_skip + enccrd->crd_len - AES_BLOCK_LEN,
  262                     AES_BLOCK_LEN, ses->ses_iv);
  263         }
  264 
  265         if (allocated) {
  266                 bzero(buf, enccrd->crd_len + 16);
  267                 free(buf, M_PADLOCK);
  268         }
  269         return (0);
  270 }

Cache object: 9f20b16d291633b1eae22dd4520ebdae


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