summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/cmac/cmac.c100
1 files changed, 66 insertions, 34 deletions
diff --git a/src/lib/libcrypto/cmac/cmac.c b/src/lib/libcrypto/cmac/cmac.c
index 9c05a98e15..f5b5f5e320 100644
--- a/src/lib/libcrypto/cmac/cmac.c
+++ b/src/lib/libcrypto/cmac/cmac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cmac.c,v 1.14 2023/07/08 14:27:14 beck Exp $ */ 1/* $OpenBSD: cmac.c,v 1.15 2023/11/29 18:11:10 tb Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project. 3 * project.
4 */ 4 */
@@ -59,37 +59,52 @@
59 59
60#include "evp_local.h" 60#include "evp_local.h"
61 61
62/*
63 * This implementation follows https://doi.org/10.6028/NIST.SP.800-38B
64 */
65
66/*
67 * CMAC context. k1 and k2 are the secret subkeys, computed as in section 6.1.
68 * The temporary block tbl is a scratch buffer that holds intermediate secrets.
69 */
62struct CMAC_CTX_st { 70struct CMAC_CTX_st {
63 /* Cipher context to use */
64 EVP_CIPHER_CTX cctx; 71 EVP_CIPHER_CTX cctx;
65 /* Keys k1 and k2 */
66 unsigned char k1[EVP_MAX_BLOCK_LENGTH]; 72 unsigned char k1[EVP_MAX_BLOCK_LENGTH];
67 unsigned char k2[EVP_MAX_BLOCK_LENGTH]; 73 unsigned char k2[EVP_MAX_BLOCK_LENGTH];
68 /* Temporary block */
69 unsigned char tbl[EVP_MAX_BLOCK_LENGTH]; 74 unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
70 /* Last (possibly partial) block */
71 unsigned char last_block[EVP_MAX_BLOCK_LENGTH]; 75 unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
72 /* Number of bytes in last block: -1 means context not initialised */ 76 /* Bytes in last block. -1 means not initialized. */
73 int nlast_block; 77 int nlast_block;
74}; 78};
75 79
76 80/*
77/* Make temporary keys K1 and K2 */ 81 * SP 800-38B, section 6.1, steps 2 and 3: given the input key l, calculate
78 82 * the subkeys k1 and k2: shift l one bit to the left. If the most significant
83 * bit of l was 1, additionally xor the result with Rb to get kn.
84 *
85 * Step 2: calculate k1 with l being the intermediate block CIPH_K(0),
86 * Step 3: calculate k2 from l == k1.
87 *
88 * Per 5.3, Rb is the lexically first irreducible polynomial of degree b with
89 * the minimum number of non-zero terms. This gives R128 = (1 << 128) | 0x87
90 * and R64 = (1 << 64) | 0x1b for the only supported block sizes 128 and 64.
91 */
79static void 92static void
80make_kn(unsigned char *k1, unsigned char *l, int bl) 93make_kn(unsigned char *kn, const unsigned char *l, int bl)
81{ 94{
95 unsigned char mask, Rb;
82 int i; 96 int i;
83 97
84 /* Shift block to left, including carry */ 98 /* Choose Rb according to the block size in bytes. */
85 for (i = 0; i < bl; i++) { 99 Rb = bl == 16 ? 0x87 : 0x1b;
86 k1[i] = l[i] << 1; 100
87 if (i < bl - 1 && l[i + 1] & 0x80) 101 /* Compute l << 1 up to last byte. */
88 k1[i] |= 1; 102 for (i = 0; i < bl - 1; i++)
89 } 103 kn[i] = (l[i] << 1) | (l[i + 1] >> 7);
90 /* If MSB set fixup with R */ 104
91 if (l[0] & 0x80) 105 /* Only xor with Rb if the MSB is one. */
92 k1[bl - 1] ^= bl == 16 ? 0x87 : 0x1b; 106 mask = 0 - (l[0] >> 7);
107 kn[bl - 1] = (l[bl - 1] << 1) ^ (Rb & mask);
93} 108}
94 109
95CMAC_CTX * 110CMAC_CTX *
@@ -160,44 +175,61 @@ CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
160 const EVP_CIPHER *cipher, ENGINE *impl) 175 const EVP_CIPHER *cipher, ENGINE *impl)
161{ 176{
162 static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH]; 177 static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
178 int bl;
163 179
164 /* All zeros means restart */ 180 /* All zeros means restart */
165 if (!key && !cipher && !impl && keylen == 0) { 181 if (key == NULL && cipher == NULL && impl == NULL && keylen == 0) {
166 /* Not initialised */ 182 /* Not initialised */
167 if (ctx->nlast_block == -1) 183 if (ctx->nlast_block == -1)
168 return 0; 184 return 0;
169 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) 185 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
170 return 0; 186 return 0;
171 memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(&ctx->cctx)); 187 explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
172 ctx->nlast_block = 0; 188 ctx->nlast_block = 0;
173 return 1; 189 return 1;
174 } 190 }
175 /* Initialise context */
176 if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
177 return 0;
178 /* Non-NULL key means initialisation complete */
179 if (key) {
180 int bl;
181 191
182 if (!EVP_CIPHER_CTX_cipher(&ctx->cctx)) 192 /* Initialise context. */
193 if (cipher != NULL) {
194 if (!EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
183 return 0; 195 return 0;
196 }
197
198 /* Non-NULL key means initialisation is complete. */
199 if (key != NULL) {
200 if (EVP_CIPHER_CTX_cipher(&ctx->cctx) == NULL)
201 return 0;
202
203 /* make_kn() only supports block sizes of 8 and 16 bytes. */
204 bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
205 if (bl != 8 && bl != 16)
206 return 0;
207
208 /*
209 * Section 6.1, step 1: store the intermediate secret CIPH_K(0)
210 * in ctx->tbl.
211 */
184 if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen)) 212 if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen))
185 return 0; 213 return 0;
186 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv)) 214 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv))
187 return 0; 215 return 0;
188 bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
189 if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl)) 216 if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl))
190 return 0; 217 return 0;
218
219 /* Section 6.1, step 2: compute k1 from intermediate secret. */
191 make_kn(ctx->k1, ctx->tbl, bl); 220 make_kn(ctx->k1, ctx->tbl, bl);
221 /* Section 6.1, step 3: compute k2 from k1. */
192 make_kn(ctx->k2, ctx->k1, bl); 222 make_kn(ctx->k2, ctx->k1, bl);
193 explicit_bzero(ctx->tbl, bl); 223
194 /* Reset context again ready for first data block */ 224 /* Destroy intermediate secret and reset last block count. */
225 explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
226 ctx->nlast_block = 0;
227
228 /* Reset context again to get ready for the first data block. */
195 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) 229 if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
196 return 0; 230 return 0;
197 /* Zero tbl so resume works */
198 memset(ctx->tbl, 0, bl);
199 ctx->nlast_block = 0;
200 } 231 }
232
201 return 1; 233 return 1;
202} 234}
203LCRYPTO_ALIAS(CMAC_Init); 235LCRYPTO_ALIAS(CMAC_Init);