1275732Sjmg/*- 2275732Sjmg * Copyright (c) 2014 The FreeBSD Foundation 3275732Sjmg * All rights reserved. 4275732Sjmg * 5275732Sjmg * This software was developed by John-Mark Gurney under 6275732Sjmg * the sponsorship of the FreeBSD Foundation and 7275732Sjmg * Rubicon Communications, LLC (Netgate). 8275732Sjmg * Redistribution and use in source and binary forms, with or without 9275732Sjmg * modification, are permitted provided that the following conditions 10275732Sjmg * are met: 11275732Sjmg * 1. Redistributions of source code must retain the above copyright 12275732Sjmg * notice, this list of conditions and the following disclaimer. 13275732Sjmg * 2. Redistributions in binary form must reproduce the above copyright 14275732Sjmg * notice, this list of conditions and the following disclaimer in the 15275732Sjmg * documentation and/or other materials provided with the distribution. 16275732Sjmg * 17275732Sjmg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18275732Sjmg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19275732Sjmg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20275732Sjmg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21275732Sjmg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22275732Sjmg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23275732Sjmg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24275732Sjmg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25275732Sjmg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26275732Sjmg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27275732Sjmg * SUCH DAMAGE. 28275732Sjmg * 29275732Sjmg * $FreeBSD$ 30275732Sjmg * 31275732Sjmg */ 32275732Sjmg 33275732Sjmg#include <sys/types.h> 34275732Sjmg#include <sys/systm.h> 35275732Sjmg#include <opencrypto/gfmult.h> 36275732Sjmg#include <opencrypto/gmac.h> 37275732Sjmg 38275732Sjmgvoid 39275732SjmgAES_GMAC_Init(struct aes_gmac_ctx *agc) 40275732Sjmg{ 41275732Sjmg 42275732Sjmg bzero(agc, sizeof *agc); 43275732Sjmg} 44275732Sjmg 45275732Sjmgvoid 46275732SjmgAES_GMAC_Setkey(struct aes_gmac_ctx *agc, const uint8_t *key, uint16_t klen) 47275732Sjmg{ 48275732Sjmg const uint8_t zeros[GMAC_BLOCK_LEN] = {}; 49275732Sjmg struct gf128 h; 50275732Sjmg uint8_t hbuf[GMAC_BLOCK_LEN]; 51275732Sjmg 52275732Sjmg agc->rounds = rijndaelKeySetupEnc(agc->keysched, key, klen * 8); 53275732Sjmg 54275732Sjmg rijndaelEncrypt(agc->keysched, agc->rounds, zeros, hbuf); 55275732Sjmg 56275732Sjmg h = gf128_read(hbuf); 57275732Sjmg gf128_genmultable4(h, &agc->ghashtbl); 58275732Sjmg 59275732Sjmg explicit_bzero(&h, sizeof h); 60275732Sjmg explicit_bzero(hbuf, sizeof hbuf); 61275732Sjmg} 62275732Sjmg 63275732Sjmgvoid 64275732SjmgAES_GMAC_Reinit(struct aes_gmac_ctx *agc, const uint8_t *iv, uint16_t ivlen) 65275732Sjmg{ 66275732Sjmg 67275732Sjmg KASSERT(ivlen <= sizeof agc->counter, ("passed ivlen too large!")); 68275732Sjmg bcopy(iv, agc->counter, ivlen); 69275732Sjmg} 70275732Sjmg 71275732Sjmgint 72275732SjmgAES_GMAC_Update(struct aes_gmac_ctx *agc, const uint8_t *data, uint16_t len) 73275732Sjmg{ 74275732Sjmg struct gf128 v; 75275732Sjmg uint8_t buf[GMAC_BLOCK_LEN] = {}; 76275732Sjmg int i; 77275732Sjmg 78275732Sjmg v = agc->hash; 79275732Sjmg 80275732Sjmg while (len > 0) { 81275732Sjmg if (len >= 4*GMAC_BLOCK_LEN) { 82275732Sjmg i = 4*GMAC_BLOCK_LEN; 83275732Sjmg v = gf128_mul4b(v, data, &agc->ghashtbl); 84275732Sjmg } else if (len >= GMAC_BLOCK_LEN) { 85275732Sjmg i = GMAC_BLOCK_LEN; 86275732Sjmg v = gf128_add(v, gf128_read(data)); 87275732Sjmg v = gf128_mul(v, &agc->ghashtbl.tbls[0]); 88275732Sjmg } else { 89275732Sjmg i = len; 90275732Sjmg bcopy(data, buf, i); 91275732Sjmg v = gf128_add(v, gf128_read(&buf[0])); 92275732Sjmg v = gf128_mul(v, &agc->ghashtbl.tbls[0]); 93275732Sjmg explicit_bzero(buf, sizeof buf); 94275732Sjmg } 95275732Sjmg len -= i; 96275732Sjmg data += i; 97275732Sjmg } 98275732Sjmg 99275732Sjmg agc->hash = v; 100275732Sjmg explicit_bzero(&v, sizeof v); 101275732Sjmg 102275732Sjmg return (0); 103275732Sjmg} 104275732Sjmg 105275732Sjmgvoid 106275732SjmgAES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], struct aes_gmac_ctx *agc) 107275732Sjmg{ 108275732Sjmg uint8_t enccntr[GMAC_BLOCK_LEN]; 109275732Sjmg struct gf128 a; 110275732Sjmg 111275732Sjmg /* XXX - zero additional bytes? */ 112275732Sjmg agc->counter[GMAC_BLOCK_LEN - 1] = 1; 113275732Sjmg 114275732Sjmg rijndaelEncrypt(agc->keysched, agc->rounds, agc->counter, enccntr); 115275732Sjmg a = gf128_add(agc->hash, gf128_read(enccntr)); 116275732Sjmg gf128_write(a, digest); 117275732Sjmg 118275732Sjmg explicit_bzero(enccntr, sizeof enccntr); 119275732Sjmg} 120