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 31 void ghash_gfmul(uint32_t *, uint32_t *, uint32_t *); 32 void ghash_update_mi(GHASH_CTX *, uint8_t *, size_t); 33 34 /* Allow overriding with optimized MD function */ 35 void (*ghash_update)(GHASH_CTX *, uint8_t *, size_t) = ghash_update_mi; 36 37 /* Computes a block multiplication in the GF(2^128) */ 38 void 39 ghash_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 75 void 76 ghash_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 101 void 102 AES_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 112 void 113 AES_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 124 void 125 AES_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 133 int 134 AES_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 155 void 156 AES_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 } 169