xref: /openbsd/lib/libcrypto/cmac/cmac.c (revision 7821a847)
1 /* $OpenBSD: cmac.c,v 1.24 2024/05/20 14:53:37 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53 
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #include <openssl/cmac.h>
59 
60 #include "evp_local.h"
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  */
70 struct CMAC_CTX_st {
71 	EVP_CIPHER_CTX *cipher_ctx;
72 	unsigned char k1[EVP_MAX_BLOCK_LENGTH];
73 	unsigned char k2[EVP_MAX_BLOCK_LENGTH];
74 	unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
75 	unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
76 	/* Bytes in last block. -1 means not initialized. */
77 	int nlast_block;
78 };
79 
80 /*
81  * SP 800-38B, section 6.1, steps 2 and 3: given the input key l, calculate
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  */
92 static void
make_kn(unsigned char * kn,const unsigned char * l,int block_size)93 make_kn(unsigned char *kn, const unsigned char *l, int block_size)
94 {
95 	unsigned char mask, Rb;
96 	int i;
97 
98 	/* Choose Rb according to the block size in bytes. */
99 	Rb = block_size == 16 ? 0x87 : 0x1b;
100 
101 	/* Compute l << 1 up to last byte. */
102 	for (i = 0; i < block_size - 1; i++)
103 		kn[i] = (l[i] << 1) | (l[i + 1] >> 7);
104 
105 	/* Only xor with Rb if the MSB is one. */
106 	mask = 0 - (l[0] >> 7);
107 	kn[block_size - 1] = (l[block_size - 1] << 1) ^ (Rb & mask);
108 }
109 
110 CMAC_CTX *
CMAC_CTX_new(void)111 CMAC_CTX_new(void)
112 {
113 	CMAC_CTX *ctx;
114 
115 	if ((ctx = calloc(1, sizeof(CMAC_CTX))) == NULL)
116 		goto err;
117 	if ((ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL)
118 		goto err;
119 
120 	ctx->nlast_block = -1;
121 
122 	return ctx;
123 
124  err:
125 	CMAC_CTX_free(ctx);
126 
127 	return NULL;
128 }
129 LCRYPTO_ALIAS(CMAC_CTX_new);
130 
131 void
CMAC_CTX_cleanup(CMAC_CTX * ctx)132 CMAC_CTX_cleanup(CMAC_CTX *ctx)
133 {
134 	(void)EVP_CIPHER_CTX_reset(ctx->cipher_ctx);
135 	explicit_bzero(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
136 	explicit_bzero(ctx->k1, EVP_MAX_BLOCK_LENGTH);
137 	explicit_bzero(ctx->k2, EVP_MAX_BLOCK_LENGTH);
138 	explicit_bzero(ctx->last_block, EVP_MAX_BLOCK_LENGTH);
139 	ctx->nlast_block = -1;
140 }
141 LCRYPTO_ALIAS(CMAC_CTX_cleanup);
142 
143 EVP_CIPHER_CTX *
CMAC_CTX_get0_cipher_ctx(CMAC_CTX * ctx)144 CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
145 {
146 	return ctx->cipher_ctx;
147 }
148 LCRYPTO_ALIAS(CMAC_CTX_get0_cipher_ctx);
149 
150 void
CMAC_CTX_free(CMAC_CTX * ctx)151 CMAC_CTX_free(CMAC_CTX *ctx)
152 {
153 	if (ctx == NULL)
154 		return;
155 
156 	CMAC_CTX_cleanup(ctx);
157 	EVP_CIPHER_CTX_free(ctx->cipher_ctx);
158 	freezero(ctx, sizeof(CMAC_CTX));
159 }
160 LCRYPTO_ALIAS(CMAC_CTX_free);
161 
162 int
CMAC_CTX_copy(CMAC_CTX * out,const CMAC_CTX * in)163 CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
164 {
165 	int block_size;
166 
167 	if (in->nlast_block == -1)
168 		return 0;
169 	if (!EVP_CIPHER_CTX_copy(out->cipher_ctx, in->cipher_ctx))
170 		return 0;
171 	block_size = EVP_CIPHER_CTX_block_size(in->cipher_ctx);
172 	memcpy(out->k1, in->k1, block_size);
173 	memcpy(out->k2, in->k2, block_size);
174 	memcpy(out->tbl, in->tbl, block_size);
175 	memcpy(out->last_block, in->last_block, block_size);
176 	out->nlast_block = in->nlast_block;
177 	return 1;
178 }
179 LCRYPTO_ALIAS(CMAC_CTX_copy);
180 
181 int
CMAC_Init(CMAC_CTX * ctx,const void * key,size_t keylen,const EVP_CIPHER * cipher,ENGINE * impl)182 CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
183     const EVP_CIPHER *cipher, ENGINE *impl)
184 {
185 	static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
186 	int block_size;
187 
188 	/* All zeros means restart */
189 	if (key == NULL && cipher == NULL && keylen == 0) {
190 		/* Not initialised */
191 		if (ctx->nlast_block == -1)
192 			return 0;
193 		if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, NULL, zero_iv))
194 			return 0;
195 		explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
196 		ctx->nlast_block = 0;
197 		return 1;
198 	}
199 
200 	/* Initialise context. */
201 	if (cipher != NULL) {
202 		/*
203 		 * Disallow ciphers for which EVP_Cipher() behaves differently.
204 		 * These are AEAD ciphers (or AES keywrap) for which the CMAC
205 		 * construction makes little sense.
206 		 */
207 		if ((cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
208 			return 0;
209 		if (!EVP_EncryptInit_ex(ctx->cipher_ctx, cipher, NULL, NULL, NULL))
210 			return 0;
211 	}
212 
213 	/* Non-NULL key means initialisation is complete. */
214 	if (key != NULL) {
215 		if (EVP_CIPHER_CTX_cipher(ctx->cipher_ctx) == NULL)
216 			return 0;
217 
218 		/* make_kn() only supports block sizes of 8 and 16 bytes. */
219 		block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
220 		if (block_size != 8 && block_size != 16)
221 			return 0;
222 
223 		/*
224 		 * Section 6.1, step 1: store the intermediate secret CIPH_K(0)
225 		 * in ctx->tbl.
226 		 */
227 		if (!EVP_CIPHER_CTX_set_key_length(ctx->cipher_ctx, keylen))
228 			return 0;
229 		if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, key, zero_iv))
230 			return 0;
231 		if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, zero_iv, block_size))
232 			return 0;
233 
234 		/* Section 6.1, step 2: compute k1 from intermediate secret. */
235 		make_kn(ctx->k1, ctx->tbl, block_size);
236 		/* Section 6.1, step 3: compute k2 from k1. */
237 		make_kn(ctx->k2, ctx->k1, block_size);
238 
239 		/* Destroy intermediate secret and reset last block count. */
240 		explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
241 		ctx->nlast_block = 0;
242 
243 		/* Reset context again to get ready for the first data block. */
244 		if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, NULL, zero_iv))
245 			return 0;
246 	}
247 
248 	return 1;
249 }
250 LCRYPTO_ALIAS(CMAC_Init);
251 
252 int
CMAC_Update(CMAC_CTX * ctx,const void * in,size_t dlen)253 CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
254 {
255 	const unsigned char *data = in;
256 	size_t block_size;
257 
258 	if (ctx->nlast_block == -1)
259 		return 0;
260 	if (dlen == 0)
261 		return 1;
262 	block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
263 	/* Copy into partial block if we need to */
264 	if (ctx->nlast_block > 0) {
265 		size_t nleft;
266 
267 		nleft = block_size - ctx->nlast_block;
268 		if (dlen < nleft)
269 			nleft = dlen;
270 		memcpy(ctx->last_block + ctx->nlast_block, data, nleft);
271 		dlen -= nleft;
272 		ctx->nlast_block += nleft;
273 		/* If no more to process return */
274 		if (dlen == 0)
275 			return 1;
276 		data += nleft;
277 		/* Else not final block so encrypt it */
278 		if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, ctx->last_block,
279 		    block_size))
280 			return 0;
281 	}
282 	/* Encrypt all but one of the complete blocks left */
283 	while (dlen > block_size) {
284 		if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, data, block_size))
285 			return 0;
286 		dlen -= block_size;
287 		data += block_size;
288 	}
289 	/* Copy any data left to last block buffer */
290 	memcpy(ctx->last_block, data, dlen);
291 	ctx->nlast_block = dlen;
292 	return 1;
293 }
294 LCRYPTO_ALIAS(CMAC_Update);
295 
296 int
CMAC_Final(CMAC_CTX * ctx,unsigned char * out,size_t * poutlen)297 CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
298 {
299 	int i, block_size, lb;
300 
301 	if (ctx->nlast_block == -1)
302 		return 0;
303 	block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
304 	*poutlen = (size_t)block_size;
305 	if (!out)
306 		return 1;
307 	lb = ctx->nlast_block;
308 	/* Is last block complete? */
309 	if (lb == block_size) {
310 		for (i = 0; i < block_size; i++)
311 			out[i] = ctx->last_block[i] ^ ctx->k1[i];
312 	} else {
313 		ctx->last_block[lb] = 0x80;
314 		if (block_size - lb > 1)
315 			memset(ctx->last_block + lb + 1, 0, block_size - lb - 1);
316 		for (i = 0; i < block_size; i++)
317 			out[i] = ctx->last_block[i] ^ ctx->k2[i];
318 	}
319 	if (!EVP_Cipher(ctx->cipher_ctx, out, out, block_size)) {
320 		explicit_bzero(out, block_size);
321 		return 0;
322 	}
323 	return 1;
324 }
325 LCRYPTO_ALIAS(CMAC_Final);
326