summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/cmac/cmac.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
committercvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
commiteb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch)
treeedb6da6af7e865d488dc1a29309f1e1ec226e603 /src/lib/libcrypto/cmac/cmac.c
parent247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff)
downloadopenbsd-tb_20250414.tar.gz
openbsd-tb_20250414.tar.bz2
openbsd-tb_20250414.zip
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/lib/libcrypto/cmac/cmac.c')
-rw-r--r--src/lib/libcrypto/cmac/cmac.c325
1 files changed, 0 insertions, 325 deletions
diff --git a/src/lib/libcrypto/cmac/cmac.c b/src/lib/libcrypto/cmac/cmac.c
deleted file mode 100644
index 5c917439a1..0000000000
--- a/src/lib/libcrypto/cmac/cmac.c
+++ /dev/null
@@ -1,325 +0,0 @@
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 */
70struct 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 */
92static void
93make_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
110CMAC_CTX *
111CMAC_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}
129LCRYPTO_ALIAS(CMAC_CTX_new);
130
131void
132CMAC_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}
141LCRYPTO_ALIAS(CMAC_CTX_cleanup);
142
143EVP_CIPHER_CTX *
144CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
145{
146 return ctx->cipher_ctx;
147}
148LCRYPTO_ALIAS(CMAC_CTX_get0_cipher_ctx);
149
150void
151CMAC_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}
160LCRYPTO_ALIAS(CMAC_CTX_free);
161
162int
163CMAC_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}
179LCRYPTO_ALIAS(CMAC_CTX_copy);
180
181int
182CMAC_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}
250LCRYPTO_ALIAS(CMAC_Init);
251
252int
253CMAC_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}
294LCRYPTO_ALIAS(CMAC_Update);
295
296int
297CMAC_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}
325LCRYPTO_ALIAS(CMAC_Final);