1*7821a847Stb /* $OpenBSD: cmac.c,v 1.24 2024/05/20 14:53:37 tb Exp $ */
2ec07fdf1Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3ec07fdf1Sdjm * project.
4ec07fdf1Sdjm */
5ec07fdf1Sdjm /* ====================================================================
6ec07fdf1Sdjm * Copyright (c) 2010 The OpenSSL Project. All rights reserved.
7ec07fdf1Sdjm *
8ec07fdf1Sdjm * Redistribution and use in source and binary forms, with or without
9ec07fdf1Sdjm * modification, are permitted provided that the following conditions
10ec07fdf1Sdjm * are met:
11ec07fdf1Sdjm *
12ec07fdf1Sdjm * 1. Redistributions of source code must retain the above copyright
13ec07fdf1Sdjm * notice, this list of conditions and the following disclaimer.
14ec07fdf1Sdjm *
15ec07fdf1Sdjm * 2. Redistributions in binary form must reproduce the above copyright
16ec07fdf1Sdjm * notice, this list of conditions and the following disclaimer in
17ec07fdf1Sdjm * the documentation and/or other materials provided with the
18ec07fdf1Sdjm * distribution.
19ec07fdf1Sdjm *
20ec07fdf1Sdjm * 3. All advertising materials mentioning features or use of this
21ec07fdf1Sdjm * software must display the following acknowledgment:
22ec07fdf1Sdjm * "This product includes software developed by the OpenSSL Project
23ec07fdf1Sdjm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24ec07fdf1Sdjm *
25ec07fdf1Sdjm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26ec07fdf1Sdjm * endorse or promote products derived from this software without
27ec07fdf1Sdjm * prior written permission. For written permission, please contact
28ec07fdf1Sdjm * licensing@OpenSSL.org.
29ec07fdf1Sdjm *
30ec07fdf1Sdjm * 5. Products derived from this software may not be called "OpenSSL"
31ec07fdf1Sdjm * nor may "OpenSSL" appear in their names without prior written
32ec07fdf1Sdjm * permission of the OpenSSL Project.
33ec07fdf1Sdjm *
34ec07fdf1Sdjm * 6. Redistributions of any form whatsoever must retain the following
35ec07fdf1Sdjm * acknowledgment:
36ec07fdf1Sdjm * "This product includes software developed by the OpenSSL Project
37ec07fdf1Sdjm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38ec07fdf1Sdjm *
39ec07fdf1Sdjm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40ec07fdf1Sdjm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41ec07fdf1Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42ec07fdf1Sdjm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43ec07fdf1Sdjm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44ec07fdf1Sdjm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45ec07fdf1Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46ec07fdf1Sdjm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47ec07fdf1Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48ec07fdf1Sdjm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49ec07fdf1Sdjm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50ec07fdf1Sdjm * OF THE POSSIBILITY OF SUCH DAMAGE.
51ec07fdf1Sdjm * ====================================================================
52ec07fdf1Sdjm */
53ec07fdf1Sdjm
54ec07fdf1Sdjm #include <stdio.h>
55ec07fdf1Sdjm #include <stdlib.h>
56ec07fdf1Sdjm #include <string.h>
57b6ab114eSjsing
58ec07fdf1Sdjm #include <openssl/cmac.h>
59ec07fdf1Sdjm
60c9675a23Stb #include "evp_local.h"
61bc366ef8Stb
628865b67aStb /*
638865b67aStb * This implementation follows https://doi.org/10.6028/NIST.SP.800-38B
648865b67aStb */
658865b67aStb
668865b67aStb /*
678865b67aStb * CMAC context. k1 and k2 are the secret subkeys, computed as in section 6.1.
688865b67aStb * The temporary block tbl is a scratch buffer that holds intermediate secrets.
698865b67aStb */
7045c944e0Smiod struct CMAC_CTX_st {
712fe3a397Sjoshua EVP_CIPHER_CTX *cipher_ctx;
72ec07fdf1Sdjm unsigned char k1[EVP_MAX_BLOCK_LENGTH];
73ec07fdf1Sdjm unsigned char k2[EVP_MAX_BLOCK_LENGTH];
74ec07fdf1Sdjm unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
75ec07fdf1Sdjm unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
768865b67aStb /* Bytes in last block. -1 means not initialized. */
77ec07fdf1Sdjm int nlast_block;
78ec07fdf1Sdjm };
79ec07fdf1Sdjm
808865b67aStb /*
818865b67aStb * SP 800-38B, section 6.1, steps 2 and 3: given the input key l, calculate
828865b67aStb * the subkeys k1 and k2: shift l one bit to the left. If the most significant
838865b67aStb * bit of l was 1, additionally xor the result with Rb to get kn.
848865b67aStb *
858865b67aStb * Step 2: calculate k1 with l being the intermediate block CIPH_K(0),
868865b67aStb * Step 3: calculate k2 from l == k1.
878865b67aStb *
888865b67aStb * Per 5.3, Rb is the lexically first irreducible polynomial of degree b with
898865b67aStb * the minimum number of non-zero terms. This gives R128 = (1 << 128) | 0x87
908865b67aStb * and R64 = (1 << 64) | 0x1b for the only supported block sizes 128 and 64.
918865b67aStb */
9245c944e0Smiod static void
make_kn(unsigned char * kn,const unsigned char * l,int block_size)93eb570f66Stb make_kn(unsigned char *kn, const unsigned char *l, int block_size)
94ec07fdf1Sdjm {
958865b67aStb unsigned char mask, Rb;
96ec07fdf1Sdjm int i;
9745c944e0Smiod
988865b67aStb /* Choose Rb according to the block size in bytes. */
99eb570f66Stb Rb = block_size == 16 ? 0x87 : 0x1b;
1008865b67aStb
1018865b67aStb /* Compute l << 1 up to last byte. */
102eb570f66Stb for (i = 0; i < block_size - 1; i++)
1038865b67aStb kn[i] = (l[i] << 1) | (l[i + 1] >> 7);
1048865b67aStb
1058865b67aStb /* Only xor with Rb if the MSB is one. */
1068865b67aStb mask = 0 - (l[0] >> 7);
107eb570f66Stb kn[block_size - 1] = (l[block_size - 1] << 1) ^ (Rb & mask);
108ec07fdf1Sdjm }
109ec07fdf1Sdjm
11045c944e0Smiod CMAC_CTX *
CMAC_CTX_new(void)11145c944e0Smiod CMAC_CTX_new(void)
112ec07fdf1Sdjm {
113ec07fdf1Sdjm CMAC_CTX *ctx;
11445c944e0Smiod
1152fe3a397Sjoshua if ((ctx = calloc(1, sizeof(CMAC_CTX))) == NULL)
1162fe3a397Sjoshua goto err;
1172fe3a397Sjoshua if ((ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL)
1182fe3a397Sjoshua goto err;
1192fe3a397Sjoshua
120ec07fdf1Sdjm ctx->nlast_block = -1;
1212fe3a397Sjoshua
122ec07fdf1Sdjm return ctx;
1232fe3a397Sjoshua
1242fe3a397Sjoshua err:
1252fe3a397Sjoshua CMAC_CTX_free(ctx);
1262fe3a397Sjoshua
1272fe3a397Sjoshua return NULL;
128ec07fdf1Sdjm }
129df60ae0eSbeck LCRYPTO_ALIAS(CMAC_CTX_new);
130ec07fdf1Sdjm
13145c944e0Smiod void
CMAC_CTX_cleanup(CMAC_CTX * ctx)13245c944e0Smiod CMAC_CTX_cleanup(CMAC_CTX *ctx)
133ec07fdf1Sdjm {
1344ee61787Stb (void)EVP_CIPHER_CTX_reset(ctx->cipher_ctx);
1350f777b12Sjsing explicit_bzero(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
1360f777b12Sjsing explicit_bzero(ctx->k1, EVP_MAX_BLOCK_LENGTH);
1370f777b12Sjsing explicit_bzero(ctx->k2, EVP_MAX_BLOCK_LENGTH);
1380f777b12Sjsing explicit_bzero(ctx->last_block, EVP_MAX_BLOCK_LENGTH);
139ec07fdf1Sdjm ctx->nlast_block = -1;
140ec07fdf1Sdjm }
141df60ae0eSbeck LCRYPTO_ALIAS(CMAC_CTX_cleanup);
142ec07fdf1Sdjm
14345c944e0Smiod EVP_CIPHER_CTX *
CMAC_CTX_get0_cipher_ctx(CMAC_CTX * ctx)14445c944e0Smiod CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
145ec07fdf1Sdjm {
1462fe3a397Sjoshua return ctx->cipher_ctx;
147ec07fdf1Sdjm }
148df60ae0eSbeck LCRYPTO_ALIAS(CMAC_CTX_get0_cipher_ctx);
149ec07fdf1Sdjm
15045c944e0Smiod void
CMAC_CTX_free(CMAC_CTX * ctx)15145c944e0Smiod CMAC_CTX_free(CMAC_CTX *ctx)
152ec07fdf1Sdjm {
15368a272ffSmiod if (ctx == NULL)
15468a272ffSmiod return;
15568a272ffSmiod
156ec07fdf1Sdjm CMAC_CTX_cleanup(ctx);
1572fe3a397Sjoshua EVP_CIPHER_CTX_free(ctx->cipher_ctx);
1582fe3a397Sjoshua freezero(ctx, sizeof(CMAC_CTX));
159ec07fdf1Sdjm }
160df60ae0eSbeck LCRYPTO_ALIAS(CMAC_CTX_free);
161ec07fdf1Sdjm
16245c944e0Smiod int
CMAC_CTX_copy(CMAC_CTX * out,const CMAC_CTX * in)16345c944e0Smiod CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
164ec07fdf1Sdjm {
165eb570f66Stb int block_size;
16645c944e0Smiod
167ec07fdf1Sdjm if (in->nlast_block == -1)
168ec07fdf1Sdjm return 0;
1692fe3a397Sjoshua if (!EVP_CIPHER_CTX_copy(out->cipher_ctx, in->cipher_ctx))
170ec07fdf1Sdjm return 0;
1712fe3a397Sjoshua block_size = EVP_CIPHER_CTX_block_size(in->cipher_ctx);
172eb570f66Stb memcpy(out->k1, in->k1, block_size);
173eb570f66Stb memcpy(out->k2, in->k2, block_size);
174eb570f66Stb memcpy(out->tbl, in->tbl, block_size);
175eb570f66Stb memcpy(out->last_block, in->last_block, block_size);
176ec07fdf1Sdjm out->nlast_block = in->nlast_block;
177ec07fdf1Sdjm return 1;
178ec07fdf1Sdjm }
179df60ae0eSbeck LCRYPTO_ALIAS(CMAC_CTX_copy);
180ec07fdf1Sdjm
18145c944e0Smiod int
CMAC_Init(CMAC_CTX * ctx,const void * key,size_t keylen,const EVP_CIPHER * cipher,ENGINE * impl)18245c944e0Smiod CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
183ec07fdf1Sdjm const EVP_CIPHER *cipher, ENGINE *impl)
184ec07fdf1Sdjm {
185*7821a847Stb static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
186eb570f66Stb int block_size;
18745c944e0Smiod
188ec07fdf1Sdjm /* All zeros means restart */
189592331b2Stb if (key == NULL && cipher == NULL && keylen == 0) {
190ec07fdf1Sdjm /* Not initialised */
191ec07fdf1Sdjm if (ctx->nlast_block == -1)
192ec07fdf1Sdjm return 0;
1932fe3a397Sjoshua if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, NULL, zero_iv))
194ec07fdf1Sdjm return 0;
1958865b67aStb explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
196ec07fdf1Sdjm ctx->nlast_block = 0;
197ec07fdf1Sdjm return 1;
198ec07fdf1Sdjm }
19945c944e0Smiod
2008865b67aStb /* Initialise context. */
2018865b67aStb if (cipher != NULL) {
2020fbfcfcfStb /*
2030fbfcfcfStb * Disallow ciphers for which EVP_Cipher() behaves differently.
2040fbfcfcfStb * These are AEAD ciphers (or AES keywrap) for which the CMAC
2050fbfcfcfStb * construction makes little sense.
2060fbfcfcfStb */
2070fbfcfcfStb if ((cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
2080fbfcfcfStb return 0;
2092fe3a397Sjoshua if (!EVP_EncryptInit_ex(ctx->cipher_ctx, cipher, NULL, NULL, NULL))
210ec07fdf1Sdjm return 0;
2118865b67aStb }
2128865b67aStb
2138865b67aStb /* Non-NULL key means initialisation is complete. */
2148865b67aStb if (key != NULL) {
2152fe3a397Sjoshua if (EVP_CIPHER_CTX_cipher(ctx->cipher_ctx) == NULL)
2168865b67aStb return 0;
2178865b67aStb
2188865b67aStb /* make_kn() only supports block sizes of 8 and 16 bytes. */
2192fe3a397Sjoshua block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
220eb570f66Stb if (block_size != 8 && block_size != 16)
2218865b67aStb return 0;
2228865b67aStb
2238865b67aStb /*
2248865b67aStb * Section 6.1, step 1: store the intermediate secret CIPH_K(0)
2258865b67aStb * in ctx->tbl.
2268865b67aStb */
2272fe3a397Sjoshua if (!EVP_CIPHER_CTX_set_key_length(ctx->cipher_ctx, keylen))
228ec07fdf1Sdjm return 0;
2292fe3a397Sjoshua if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, key, zero_iv))
230ec07fdf1Sdjm return 0;
2312fe3a397Sjoshua if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, zero_iv, block_size))
232ec07fdf1Sdjm return 0;
2338865b67aStb
2348865b67aStb /* Section 6.1, step 2: compute k1 from intermediate secret. */
235eb570f66Stb make_kn(ctx->k1, ctx->tbl, block_size);
2368865b67aStb /* Section 6.1, step 3: compute k2 from k1. */
237eb570f66Stb make_kn(ctx->k2, ctx->k1, block_size);
2388865b67aStb
2398865b67aStb /* Destroy intermediate secret and reset last block count. */
2408865b67aStb explicit_bzero(ctx->tbl, sizeof(ctx->tbl));
2418865b67aStb ctx->nlast_block = 0;
2428865b67aStb
2438865b67aStb /* Reset context again to get ready for the first data block. */
2442fe3a397Sjoshua if (!EVP_EncryptInit_ex(ctx->cipher_ctx, NULL, NULL, NULL, zero_iv))
245ec07fdf1Sdjm return 0;
246ec07fdf1Sdjm }
2478865b67aStb
248ec07fdf1Sdjm return 1;
249ec07fdf1Sdjm }
250df60ae0eSbeck LCRYPTO_ALIAS(CMAC_Init);
251ec07fdf1Sdjm
25245c944e0Smiod int
CMAC_Update(CMAC_CTX * ctx,const void * in,size_t dlen)25345c944e0Smiod CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
254ec07fdf1Sdjm {
255ec07fdf1Sdjm const unsigned char *data = in;
256eb570f66Stb size_t block_size;
25768c01845Stedu
258ec07fdf1Sdjm if (ctx->nlast_block == -1)
259ec07fdf1Sdjm return 0;
260ec07fdf1Sdjm if (dlen == 0)
261ec07fdf1Sdjm return 1;
2622fe3a397Sjoshua block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
263ec07fdf1Sdjm /* Copy into partial block if we need to */
26445c944e0Smiod if (ctx->nlast_block > 0) {
265ec07fdf1Sdjm size_t nleft;
26645c944e0Smiod
267eb570f66Stb nleft = block_size - ctx->nlast_block;
268ec07fdf1Sdjm if (dlen < nleft)
269ec07fdf1Sdjm nleft = dlen;
270ec07fdf1Sdjm memcpy(ctx->last_block + ctx->nlast_block, data, nleft);
271ec07fdf1Sdjm dlen -= nleft;
272ec07fdf1Sdjm ctx->nlast_block += nleft;
273ec07fdf1Sdjm /* If no more to process return */
274ec07fdf1Sdjm if (dlen == 0)
275ec07fdf1Sdjm return 1;
276ec07fdf1Sdjm data += nleft;
277ec07fdf1Sdjm /* Else not final block so encrypt it */
2782fe3a397Sjoshua if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, ctx->last_block,
279eb570f66Stb block_size))
280ec07fdf1Sdjm return 0;
281ec07fdf1Sdjm }
282ec07fdf1Sdjm /* Encrypt all but one of the complete blocks left */
283eb570f66Stb while (dlen > block_size) {
2842fe3a397Sjoshua if (!EVP_Cipher(ctx->cipher_ctx, ctx->tbl, data, block_size))
285ec07fdf1Sdjm return 0;
286eb570f66Stb dlen -= block_size;
287eb570f66Stb data += block_size;
288ec07fdf1Sdjm }
289ec07fdf1Sdjm /* Copy any data left to last block buffer */
290ec07fdf1Sdjm memcpy(ctx->last_block, data, dlen);
291ec07fdf1Sdjm ctx->nlast_block = dlen;
292ec07fdf1Sdjm return 1;
293ec07fdf1Sdjm }
294df60ae0eSbeck LCRYPTO_ALIAS(CMAC_Update);
295ec07fdf1Sdjm
29645c944e0Smiod int
CMAC_Final(CMAC_CTX * ctx,unsigned char * out,size_t * poutlen)29745c944e0Smiod CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
298ec07fdf1Sdjm {
299eb570f66Stb int i, block_size, lb;
30068c01845Stedu
301ec07fdf1Sdjm if (ctx->nlast_block == -1)
302ec07fdf1Sdjm return 0;
3032fe3a397Sjoshua block_size = EVP_CIPHER_CTX_block_size(ctx->cipher_ctx);
304eb570f66Stb *poutlen = (size_t)block_size;
305ec07fdf1Sdjm if (!out)
306ec07fdf1Sdjm return 1;
307ec07fdf1Sdjm lb = ctx->nlast_block;
308ec07fdf1Sdjm /* Is last block complete? */
309eb570f66Stb if (lb == block_size) {
310eb570f66Stb for (i = 0; i < block_size; i++)
311ec07fdf1Sdjm out[i] = ctx->last_block[i] ^ ctx->k1[i];
31245c944e0Smiod } else {
313ec07fdf1Sdjm ctx->last_block[lb] = 0x80;
314eb570f66Stb if (block_size - lb > 1)
315eb570f66Stb memset(ctx->last_block + lb + 1, 0, block_size - lb - 1);
316eb570f66Stb for (i = 0; i < block_size; i++)
317ec07fdf1Sdjm out[i] = ctx->last_block[i] ^ ctx->k2[i];
318ec07fdf1Sdjm }
3192fe3a397Sjoshua if (!EVP_Cipher(ctx->cipher_ctx, out, out, block_size)) {
320eb570f66Stb explicit_bzero(out, block_size);
321ec07fdf1Sdjm return 0;
322ec07fdf1Sdjm }
323ec07fdf1Sdjm return 1;
324ec07fdf1Sdjm }
325df60ae0eSbeck LCRYPTO_ALIAS(CMAC_Final);
326