1 /*- 2 * Copyright (c) 2014 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by John-Mark Gurney under 6 * the sponsorship of the FreeBSD Foundation and 7 * Rubicon Communications, LLC (Netgate). 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 * 31 */ 32 33 #include <sys/types.h> 34 #include <sys/systm.h> 35 #include <opencrypto/gfmult.h> 36 #include <opencrypto/gmac.h> 37 38 void 39 AES_GMAC_Init(void *ctx) 40 { 41 struct aes_gmac_ctx *agc; 42 43 agc = ctx; 44 bzero(agc, sizeof *agc); 45 } 46 47 void 48 AES_GMAC_Setkey(void *ctx, const uint8_t *key, u_int klen) 49 { 50 struct aes_gmac_ctx *agc; 51 const uint8_t zeros[GMAC_BLOCK_LEN] = {}; 52 struct gf128 h; 53 uint8_t hbuf[GMAC_BLOCK_LEN]; 54 55 agc = ctx; 56 agc->rounds = rijndaelKeySetupEnc(agc->keysched, key, klen * 8); 57 58 rijndaelEncrypt(agc->keysched, agc->rounds, zeros, hbuf); 59 60 h = gf128_read(hbuf); 61 gf128_genmultable4(h, &agc->ghashtbl); 62 63 explicit_bzero(&h, sizeof h); 64 explicit_bzero(hbuf, sizeof hbuf); 65 } 66 67 void 68 AES_GMAC_Reinit(void *ctx, const uint8_t *iv, u_int ivlen) 69 { 70 struct aes_gmac_ctx *agc; 71 72 agc = ctx; 73 KASSERT(ivlen <= sizeof agc->counter, ("passed ivlen too large!")); 74 bcopy(iv, agc->counter, ivlen); 75 } 76 77 int 78 AES_GMAC_Update(void *ctx, const void *vdata, u_int len) 79 { 80 struct aes_gmac_ctx *agc; 81 const uint8_t *data; 82 struct gf128 v; 83 uint8_t buf[GMAC_BLOCK_LEN] = {}; 84 int i; 85 86 agc = ctx; 87 data = vdata; 88 v = agc->hash; 89 90 while (len > 0) { 91 if (len >= 4*GMAC_BLOCK_LEN) { 92 i = 4*GMAC_BLOCK_LEN; 93 v = gf128_mul4b(v, data, &agc->ghashtbl); 94 } else if (len >= GMAC_BLOCK_LEN) { 95 i = GMAC_BLOCK_LEN; 96 v = gf128_add(v, gf128_read(data)); 97 v = gf128_mul(v, &agc->ghashtbl.tbls[0]); 98 } else { 99 i = len; 100 bcopy(data, buf, i); 101 v = gf128_add(v, gf128_read(&buf[0])); 102 v = gf128_mul(v, &agc->ghashtbl.tbls[0]); 103 explicit_bzero(buf, sizeof buf); 104 } 105 len -= i; 106 data += i; 107 } 108 109 agc->hash = v; 110 explicit_bzero(&v, sizeof v); 111 112 return (0); 113 } 114 115 void 116 AES_GMAC_Final(uint8_t *digest, void *ctx) 117 { 118 struct aes_gmac_ctx *agc; 119 uint8_t enccntr[GMAC_BLOCK_LEN]; 120 struct gf128 a; 121 122 /* XXX - zero additional bytes? */ 123 agc = ctx; 124 agc->counter[GMAC_BLOCK_LEN - 1] = 1; 125 126 rijndaelEncrypt(agc->keysched, agc->rounds, agc->counter, enccntr); 127 a = gf128_add(agc->hash, gf128_read(enccntr)); 128 gf128_write(a, digest); 129 130 explicit_bzero(enccntr, sizeof enccntr); 131 } 132