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/opencrypto/gmac.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 /*      $OpenBSD: gmac.c,v 1.3 2011/01/11 15:44:23 deraadt Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2010 Mike Belopuhov <mike@vantronix.net>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * This code implements the Message Authentication part of the
   21  * Galois/Counter Mode (as being described in the RFC 4543) using
   22  * the AES cipher.  FIPS SP 800-38D describes the algorithm details.
   23  */
   24 
   25 #include <sys/param.h>
   26 #include <sys/systm.h>
   27 #include <sys/endian.h>
   28 
   29 #include <crypto/rijndael/rijndael.h>
   30 #include <opencrypto/gmac.h>
   31 
   32 void    ghash_gfmul(uint32_t *, uint32_t *, uint32_t *);
   33 void    ghash_update(GHASH_CTX *, uint8_t *, size_t);
   34 
   35 /* Computes a block multiplication in the GF(2^128) */
   36 void
   37 ghash_gfmul(uint32_t *X, uint32_t *Y, uint32_t *product)
   38 {
   39         uint32_t        v[4];
   40         uint32_t        z[4] = { 0, 0, 0, 0};
   41         uint8_t         *x = (uint8_t *)X;
   42         uint32_t        mul;
   43         int             i;
   44 
   45         v[0] = be32toh(Y[0]);
   46         v[1] = be32toh(Y[1]);
   47         v[2] = be32toh(Y[2]);
   48         v[3] = be32toh(Y[3]);
   49 
   50         for (i = 0; i < GMAC_BLOCK_LEN * 8; i++) {
   51                 /* update Z */
   52                 if (x[i >> 3] & (1 << (~i & 7))) {
   53                         z[0] ^= v[0];
   54                         z[1] ^= v[1];
   55                         z[2] ^= v[2];
   56                         z[3] ^= v[3];
   57                 } /* else: we preserve old values */
   58 
   59                 /* update V */
   60                 mul = v[3] & 1;
   61                 v[3] = (v[2] << 31) | (v[3] >> 1);
   62                 v[2] = (v[1] << 31) | (v[2] >> 1);
   63                 v[1] = (v[0] << 31) | (v[1] >> 1);
   64                 v[0] = (v[0] >> 1) ^ (0xe1000000 * mul);
   65         }
   66 
   67         product[0] = htobe32(z[0]);
   68         product[1] = htobe32(z[1]);
   69         product[2] = htobe32(z[2]);
   70         product[3] = htobe32(z[3]);
   71 }
   72 
   73 void
   74 ghash_update(GHASH_CTX *ctx, uint8_t *X, size_t len)
   75 {
   76         uint32_t        *x = (uint32_t *)X;
   77         uint32_t        *s = (uint32_t *)ctx->S;
   78         uint32_t        *y = (uint32_t *)ctx->Z;
   79         int             i;
   80 
   81         for (i = 0; i < len / GMAC_BLOCK_LEN; i++) {
   82                 s[0] = y[0] ^ x[0];
   83                 s[1] = y[1] ^ x[1];
   84                 s[2] = y[2] ^ x[2];
   85                 s[3] = y[3] ^ x[3];
   86 
   87                 ghash_gfmul((uint32_t *)ctx->S, (uint32_t *)ctx->H,
   88                     (uint32_t *)ctx->S);
   89 
   90                 y = s;
   91                 x += 4;
   92         }
   93 
   94         bcopy(ctx->S, ctx->Z, GMAC_BLOCK_LEN);
   95 }
   96 
   97 #define AESCTR_NONCESIZE        4
   98 
   99 void
  100 AES_GMAC_Init(AES_GMAC_CTX *ctx)
  101 {
  102         bzero(ctx->ghash.H, GMAC_BLOCK_LEN);
  103         bzero(ctx->ghash.S, GMAC_BLOCK_LEN);
  104         bzero(ctx->ghash.Z, GMAC_BLOCK_LEN);
  105         bzero(ctx->J, GMAC_BLOCK_LEN);
  106 }
  107 
  108 void
  109 AES_GMAC_Setkey(AES_GMAC_CTX *ctx, const uint8_t *key, uint16_t klen)
  110 {
  111         ctx->rounds = rijndaelKeySetupEnc(ctx->K, __DECONST(u_char *, key),
  112             (klen - AESCTR_NONCESIZE) * 8);
  113         /* copy out salt to the counter block */
  114         bcopy(key + klen - AESCTR_NONCESIZE, ctx->J, AESCTR_NONCESIZE);
  115         /* prepare a hash subkey */
  116         rijndaelEncrypt(ctx->K, ctx->rounds, ctx->ghash.H, ctx->ghash.H);
  117 }
  118 
  119 void
  120 AES_GMAC_Reinit(AES_GMAC_CTX *ctx, const uint8_t *iv, uint16_t ivlen)
  121 {
  122         /* copy out IV to the counter block */
  123         bcopy(iv, ctx->J + AESCTR_NONCESIZE, ivlen);
  124 }
  125 
  126 int
  127 AES_GMAC_Update(AES_GMAC_CTX *ctx, uint8_t *data, uint16_t len)
  128 {
  129         uint32_t        blk[4] = { 0, 0, 0, 0 };
  130         int             plen;
  131 
  132         if (len > 0) {
  133                 plen = len % GMAC_BLOCK_LEN;
  134                 if (len >= GMAC_BLOCK_LEN)
  135                         ghash_update(&ctx->ghash, data, len - plen);
  136                 if (plen) {
  137                         bcopy(data + (len - plen), (uint8_t *)blk, plen);
  138                         ghash_update(&ctx->ghash, (uint8_t *)blk,
  139                             GMAC_BLOCK_LEN);
  140                 }
  141         }
  142         return (0);
  143 }
  144 
  145 void
  146 AES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], AES_GMAC_CTX *ctx)
  147 {
  148         uint8_t         keystream[GMAC_BLOCK_LEN];
  149         int             i;
  150 
  151         /* do one round of GCTR */
  152         ctx->J[GMAC_BLOCK_LEN - 1] = 1;
  153         rijndaelEncrypt(ctx->K, ctx->rounds, ctx->J, keystream);
  154         for (i = 0; i < GMAC_DIGEST_LEN; i++)
  155                 digest[i] = ctx->ghash.S[i] ^ keystream[i];
  156         bzero(keystream, sizeof(keystream));
  157 }
  158 

Cache object: afdfc1386aa1fdc6e961c3e86d8ab8bb


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