jcs's openbsd hax
openbsd
at jcs 168 lines 4.3 kB view raw
1/* $OpenBSD: gmac.c,v 1.10 2017/05/02 11:44:32 mikeb Exp $ */ 2 3/* 4 * Copyright (c) 2010 Mike Belopuhov 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 28#include <crypto/aes.h> 29#include <crypto/gmac.h> 30 31void ghash_gfmul(uint32_t *, uint32_t *, uint32_t *); 32void ghash_update_mi(GHASH_CTX *, uint8_t *, size_t); 33 34/* Allow overriding with optimized MD function */ 35void (*ghash_update)(GHASH_CTX *, uint8_t *, size_t) = ghash_update_mi; 36 37/* Computes a block multiplication in the GF(2^128) */ 38void 39ghash_gfmul(uint32_t *X, uint32_t *Y, uint32_t *product) 40{ 41 uint32_t v[4]; 42 uint32_t z[4] = { 0, 0, 0, 0}; 43 uint8_t *x = (uint8_t *)X; 44 uint32_t mask; 45 int i; 46 47 v[0] = betoh32(Y[0]); 48 v[1] = betoh32(Y[1]); 49 v[2] = betoh32(Y[2]); 50 v[3] = betoh32(Y[3]); 51 52 for (i = 0; i < GMAC_BLOCK_LEN * 8; i++) { 53 /* update Z */ 54 mask = !!(x[i >> 3] & (1 << (~i & 7))); 55 mask = ~(mask - 1); 56 z[0] ^= v[0] & mask; 57 z[1] ^= v[1] & mask; 58 z[2] ^= v[2] & mask; 59 z[3] ^= v[3] & mask; 60 61 /* update V */ 62 mask = ~((v[3] & 1) - 1); 63 v[3] = (v[2] << 31) | (v[3] >> 1); 64 v[2] = (v[1] << 31) | (v[2] >> 1); 65 v[1] = (v[0] << 31) | (v[1] >> 1); 66 v[0] = (v[0] >> 1) ^ (0xe1000000 & mask); 67 } 68 69 product[0] = htobe32(z[0]); 70 product[1] = htobe32(z[1]); 71 product[2] = htobe32(z[2]); 72 product[3] = htobe32(z[3]); 73} 74 75void 76ghash_update_mi(GHASH_CTX *ctx, uint8_t *X, size_t len) 77{ 78 uint32_t *x = (uint32_t *)X; 79 uint32_t *s = (uint32_t *)ctx->S; 80 uint32_t *y = (uint32_t *)ctx->Z; 81 int i; 82 83 for (i = 0; i < len / GMAC_BLOCK_LEN; i++) { 84 s[0] = y[0] ^ x[0]; 85 s[1] = y[1] ^ x[1]; 86 s[2] = y[2] ^ x[2]; 87 s[3] = y[3] ^ x[3]; 88 89 ghash_gfmul((uint32_t *)ctx->S, (uint32_t *)ctx->H, 90 (uint32_t *)ctx->S); 91 92 y = s; 93 x += 4; 94 } 95 96 bcopy(ctx->S, ctx->Z, GMAC_BLOCK_LEN); 97} 98 99#define AESCTR_NONCESIZE 4 100 101void 102AES_GMAC_Init(void *xctx) 103{ 104 AES_GMAC_CTX *ctx = xctx; 105 106 bzero(ctx->ghash.H, GMAC_BLOCK_LEN); 107 bzero(ctx->ghash.S, GMAC_BLOCK_LEN); 108 bzero(ctx->ghash.Z, GMAC_BLOCK_LEN); 109 bzero(ctx->J, GMAC_BLOCK_LEN); 110} 111 112void 113AES_GMAC_Setkey(void *xctx, const uint8_t *key, uint16_t klen) 114{ 115 AES_GMAC_CTX *ctx = xctx; 116 117 AES_Setkey(&ctx->K, key, klen - AESCTR_NONCESIZE); 118 /* copy out salt to the counter block */ 119 bcopy(key + klen - AESCTR_NONCESIZE, ctx->J, AESCTR_NONCESIZE); 120 /* prepare a hash subkey */ 121 AES_Encrypt(&ctx->K, ctx->ghash.H, ctx->ghash.H); 122} 123 124void 125AES_GMAC_Reinit(void *xctx, const uint8_t *iv, uint16_t ivlen) 126{ 127 AES_GMAC_CTX *ctx = xctx; 128 129 /* copy out IV to the counter block */ 130 bcopy(iv, ctx->J + AESCTR_NONCESIZE, ivlen); 131} 132 133int 134AES_GMAC_Update(void *xctx, const uint8_t *data, uint16_t len) 135{ 136 AES_GMAC_CTX *ctx = xctx; 137 uint32_t blk[4] = { 0, 0, 0, 0 }; 138 int plen; 139 140 if (len > 0) { 141 plen = len % GMAC_BLOCK_LEN; 142 if (len >= GMAC_BLOCK_LEN) 143 (*ghash_update)(&ctx->ghash, (uint8_t *)data, 144 len - plen); 145 if (plen) { 146 memcpy((uint8_t *)blk, (uint8_t *)data + (len - plen), 147 plen); 148 (*ghash_update)(&ctx->ghash, (uint8_t *)blk, 149 GMAC_BLOCK_LEN); 150 } 151 } 152 return (0); 153} 154 155void 156AES_GMAC_Final(uint8_t digest[GMAC_DIGEST_LEN], void *xctx) 157{ 158 AES_GMAC_CTX *ctx = xctx; 159 uint8_t keystream[GMAC_BLOCK_LEN]; 160 int i; 161 162 /* do one round of GCTR */ 163 ctx->J[GMAC_BLOCK_LEN - 1] = 1; 164 AES_Encrypt(&ctx->K, ctx->J, keystream); 165 for (i = 0; i < GMAC_DIGEST_LEN; i++) 166 digest[i] = ctx->ghash.S[i] ^ keystream[i]; 167 explicit_bzero(keystream, sizeof(keystream)); 168}