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