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$");
   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/pcpu.h>
   57 #include <sys/uio.h>
   58 
   59 #include <opencrypto/cryptodev.h>
   60 #include <crypto/rijndael/rijndael.h>
   61 
   62 #include <crypto/via/padlock.h>
   63 
   64 #define PADLOCK_ROUND_COUNT_AES128      10
   65 #define PADLOCK_ROUND_COUNT_AES192      12
   66 #define PADLOCK_ROUND_COUNT_AES256      14
   67 
   68 #define PADLOCK_ALGORITHM_TYPE_AES      0
   69 
   70 #define PADLOCK_KEY_GENERATION_HW       0
   71 #define PADLOCK_KEY_GENERATION_SW       1
   72 
   73 #define PADLOCK_DIRECTION_ENCRYPT       0
   74 #define PADLOCK_DIRECTION_DECRYPT       1
   75 
   76 #define PADLOCK_KEY_SIZE_128    0
   77 #define PADLOCK_KEY_SIZE_192    1
   78 #define PADLOCK_KEY_SIZE_256    2
   79 
   80 MALLOC_DECLARE(M_PADLOCK);
   81 
   82 static __inline void
   83 padlock_cbc(void *in, void *out, size_t count, void *key, union padlock_cw *cw,
   84     void *iv)
   85 {
   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 }
   97 
   98 static void
   99 padlock_cipher_key_setup(struct padlock_session *ses, const void *key, int klen)
  100 {
  101         union padlock_cw *cw;
  102         int i;
  103 
  104         cw = &ses->ses_cw;
  105         if (cw->cw_key_generation == PADLOCK_KEY_GENERATION_SW) {
  106                 /* Build expanded keys for both directions */
  107                 rijndaelKeySetupEnc(ses->ses_ekey, key, klen * 8);
  108                 rijndaelKeySetupDec(ses->ses_dkey, key, klen * 8);
  109                 for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
  110                         ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
  111                         ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
  112                 }
  113         } else {
  114                 bcopy(key, ses->ses_ekey, klen);
  115                 bcopy(key, ses->ses_dkey, klen);
  116         }
  117 }
  118 
  119 int
  120 padlock_cipher_setup(struct padlock_session *ses,
  121     const struct crypto_session_params *csp)
  122 {
  123         union padlock_cw *cw;
  124 
  125         if (csp->csp_cipher_klen != 16 && csp->csp_cipher_klen != 24 &&
  126             csp->csp_cipher_klen != 32) {
  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 (csp->csp_cipher_klen * 8) {
  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 (csp->csp_cipher_key != NULL) {
  154                 padlock_cipher_key_setup(ses, csp->csp_cipher_key,
  155                     csp->csp_cipher_klen);
  156         }
  157         return (0);
  158 }
  159 
  160 /*
  161  * Function checks if the given buffer is already 16 bytes aligned.
  162  * If it is there is no need to allocate new buffer.
  163  * If it isn't, new buffer is allocated.
  164  */
  165 static u_char *
  166 padlock_cipher_alloc(struct cryptop *crp, int *allocated)
  167 {
  168         u_char *addr;
  169 
  170         addr = crypto_contiguous_subsegment(crp, crp->crp_payload_start,
  171             crp->crp_payload_length);
  172         if (((uintptr_t)addr & 0xf) == 0) { /* 16 bytes aligned? */
  173                 *allocated = 0;
  174                 return (addr);
  175         }
  176 
  177         *allocated = 1;
  178         addr = malloc(crp->crp_payload_length + 16, M_PADLOCK, M_NOWAIT);
  179         return (addr);
  180 }
  181 
  182 int
  183 padlock_cipher_process(struct padlock_session *ses, struct cryptop *crp,
  184     const struct crypto_session_params *csp)
  185 {
  186         union padlock_cw *cw;
  187         struct thread *td;
  188         u_char *buf, *abuf;
  189         uint32_t *key;
  190         uint8_t iv[AES_BLOCK_LEN] __aligned(16);
  191         int allocated;
  192 
  193         buf = padlock_cipher_alloc(crp, &allocated);
  194         if (buf == NULL)
  195                 return (ENOMEM);
  196         /* Buffer has to be 16 bytes aligned. */
  197         abuf = PADLOCK_ALIGN(buf);
  198 
  199         if (crp->crp_cipher_key != NULL) {
  200                 padlock_cipher_key_setup(ses, crp->crp_cipher_key,
  201                     csp->csp_cipher_klen);
  202         }
  203 
  204         cw = &ses->ses_cw;
  205         cw->cw_filler0 = 0;
  206         cw->cw_filler1 = 0;
  207         cw->cw_filler2 = 0;
  208         cw->cw_filler3 = 0;
  209 
  210         crypto_read_iv(crp, iv);
  211 
  212         if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
  213                 cw->cw_direction = PADLOCK_DIRECTION_ENCRYPT;
  214                 key = ses->ses_ekey;
  215         } else {
  216                 cw->cw_direction = PADLOCK_DIRECTION_DECRYPT;
  217                 key = ses->ses_dkey;
  218         }
  219 
  220         if (allocated) {
  221                 crypto_copydata(crp, crp->crp_payload_start,
  222                     crp->crp_payload_length, abuf);
  223         }
  224 
  225         td = curthread;
  226         fpu_kern_enter(td, ses->ses_fpu_ctx, FPU_KERN_NORMAL | FPU_KERN_KTHR);
  227         padlock_cbc(abuf, abuf, crp->crp_payload_length / AES_BLOCK_LEN, key,
  228             cw, iv);
  229         fpu_kern_leave(td, ses->ses_fpu_ctx);
  230 
  231         if (allocated) {
  232                 crypto_copyback(crp, crp->crp_payload_start,
  233                     crp->crp_payload_length, abuf);
  234 
  235                 zfree(buf, M_PADLOCK);
  236         }
  237         return (0);
  238 }

Cache object: 0fb686e3cf9b488066f886001ccc1949


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