1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * CMAC low level APIs are deprecated for public use, but still ok for internal 12e1051a39Sopenharmony_ci * use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <stdio.h> 17e1051a39Sopenharmony_ci#include <stdlib.h> 18e1051a39Sopenharmony_ci#include <string.h> 19e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 20e1051a39Sopenharmony_ci#include <openssl/cmac.h> 21e1051a39Sopenharmony_ci#include <openssl/err.h> 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_cistruct CMAC_CTX_st { 24e1051a39Sopenharmony_ci /* Cipher context to use */ 25e1051a39Sopenharmony_ci EVP_CIPHER_CTX *cctx; 26e1051a39Sopenharmony_ci /* Keys k1 and k2 */ 27e1051a39Sopenharmony_ci unsigned char k1[EVP_MAX_BLOCK_LENGTH]; 28e1051a39Sopenharmony_ci unsigned char k2[EVP_MAX_BLOCK_LENGTH]; 29e1051a39Sopenharmony_ci /* Temporary block */ 30e1051a39Sopenharmony_ci unsigned char tbl[EVP_MAX_BLOCK_LENGTH]; 31e1051a39Sopenharmony_ci /* Last (possibly partial) block */ 32e1051a39Sopenharmony_ci unsigned char last_block[EVP_MAX_BLOCK_LENGTH]; 33e1051a39Sopenharmony_ci /* Number of bytes in last block: -1 means context not initialised */ 34e1051a39Sopenharmony_ci int nlast_block; 35e1051a39Sopenharmony_ci}; 36e1051a39Sopenharmony_ci 37e1051a39Sopenharmony_ci/* Make temporary keys K1 and K2 */ 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_cistatic void make_kn(unsigned char *k1, const unsigned char *l, int bl) 40e1051a39Sopenharmony_ci{ 41e1051a39Sopenharmony_ci int i; 42e1051a39Sopenharmony_ci unsigned char c = l[0], carry = c >> 7, cnext; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci /* Shift block to left, including carry */ 45e1051a39Sopenharmony_ci for (i = 0; i < bl - 1; i++, c = cnext) 46e1051a39Sopenharmony_ci k1[i] = (c << 1) | ((cnext = l[i + 1]) >> 7); 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci /* If MSB set fixup with R */ 49e1051a39Sopenharmony_ci k1[i] = (c << 1) ^ ((0 - carry) & (bl == 16 ? 0x87 : 0x1b)); 50e1051a39Sopenharmony_ci} 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ciCMAC_CTX *CMAC_CTX_new(void) 53e1051a39Sopenharmony_ci{ 54e1051a39Sopenharmony_ci CMAC_CTX *ctx; 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { 57e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); 58e1051a39Sopenharmony_ci return NULL; 59e1051a39Sopenharmony_ci } 60e1051a39Sopenharmony_ci ctx->cctx = EVP_CIPHER_CTX_new(); 61e1051a39Sopenharmony_ci if (ctx->cctx == NULL) { 62e1051a39Sopenharmony_ci OPENSSL_free(ctx); 63e1051a39Sopenharmony_ci return NULL; 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci ctx->nlast_block = -1; 66e1051a39Sopenharmony_ci return ctx; 67e1051a39Sopenharmony_ci} 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_civoid CMAC_CTX_cleanup(CMAC_CTX *ctx) 70e1051a39Sopenharmony_ci{ 71e1051a39Sopenharmony_ci EVP_CIPHER_CTX_reset(ctx->cctx); 72e1051a39Sopenharmony_ci OPENSSL_cleanse(ctx->tbl, EVP_MAX_BLOCK_LENGTH); 73e1051a39Sopenharmony_ci OPENSSL_cleanse(ctx->k1, EVP_MAX_BLOCK_LENGTH); 74e1051a39Sopenharmony_ci OPENSSL_cleanse(ctx->k2, EVP_MAX_BLOCK_LENGTH); 75e1051a39Sopenharmony_ci OPENSSL_cleanse(ctx->last_block, EVP_MAX_BLOCK_LENGTH); 76e1051a39Sopenharmony_ci ctx->nlast_block = -1; 77e1051a39Sopenharmony_ci} 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ciEVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx) 80e1051a39Sopenharmony_ci{ 81e1051a39Sopenharmony_ci return ctx->cctx; 82e1051a39Sopenharmony_ci} 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_civoid CMAC_CTX_free(CMAC_CTX *ctx) 85e1051a39Sopenharmony_ci{ 86e1051a39Sopenharmony_ci if (!ctx) 87e1051a39Sopenharmony_ci return; 88e1051a39Sopenharmony_ci CMAC_CTX_cleanup(ctx); 89e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(ctx->cctx); 90e1051a39Sopenharmony_ci OPENSSL_free(ctx); 91e1051a39Sopenharmony_ci} 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ciint CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) 94e1051a39Sopenharmony_ci{ 95e1051a39Sopenharmony_ci int bl; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci if (in->nlast_block == -1) 98e1051a39Sopenharmony_ci return 0; 99e1051a39Sopenharmony_ci if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) < 0) 100e1051a39Sopenharmony_ci return 0; 101e1051a39Sopenharmony_ci if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx)) 102e1051a39Sopenharmony_ci return 0; 103e1051a39Sopenharmony_ci memcpy(out->k1, in->k1, bl); 104e1051a39Sopenharmony_ci memcpy(out->k2, in->k2, bl); 105e1051a39Sopenharmony_ci memcpy(out->tbl, in->tbl, bl); 106e1051a39Sopenharmony_ci memcpy(out->last_block, in->last_block, bl); 107e1051a39Sopenharmony_ci out->nlast_block = in->nlast_block; 108e1051a39Sopenharmony_ci return 1; 109e1051a39Sopenharmony_ci} 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ciint CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, 112e1051a39Sopenharmony_ci const EVP_CIPHER *cipher, ENGINE *impl) 113e1051a39Sopenharmony_ci{ 114e1051a39Sopenharmony_ci static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 }; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci /* All zeros means restart */ 117e1051a39Sopenharmony_ci if (!key && !cipher && !impl && keylen == 0) { 118e1051a39Sopenharmony_ci /* Not initialised */ 119e1051a39Sopenharmony_ci if (ctx->nlast_block == -1) 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) 122e1051a39Sopenharmony_ci return 0; 123e1051a39Sopenharmony_ci memset(ctx->tbl, 0, EVP_CIPHER_CTX_get_block_size(ctx->cctx)); 124e1051a39Sopenharmony_ci ctx->nlast_block = 0; 125e1051a39Sopenharmony_ci return 1; 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci /* Initialise context */ 128e1051a39Sopenharmony_ci if (cipher != NULL) { 129e1051a39Sopenharmony_ci /* Ensure we can't use this ctx until we also have a key */ 130e1051a39Sopenharmony_ci ctx->nlast_block = -1; 131e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL)) 132e1051a39Sopenharmony_ci return 0; 133e1051a39Sopenharmony_ci } 134e1051a39Sopenharmony_ci /* Non-NULL key means initialisation complete */ 135e1051a39Sopenharmony_ci if (key != NULL) { 136e1051a39Sopenharmony_ci int bl; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci /* If anything fails then ensure we can't use this ctx */ 139e1051a39Sopenharmony_ci ctx->nlast_block = -1; 140e1051a39Sopenharmony_ci if (EVP_CIPHER_CTX_get0_cipher(ctx->cctx) == NULL) 141e1051a39Sopenharmony_ci return 0; 142e1051a39Sopenharmony_ci if (EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen) <= 0) 143e1051a39Sopenharmony_ci return 0; 144e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, key, zero_iv)) 145e1051a39Sopenharmony_ci return 0; 146e1051a39Sopenharmony_ci if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) 147e1051a39Sopenharmony_ci return 0; 148e1051a39Sopenharmony_ci if (EVP_Cipher(ctx->cctx, ctx->tbl, zero_iv, bl) <= 0) 149e1051a39Sopenharmony_ci return 0; 150e1051a39Sopenharmony_ci make_kn(ctx->k1, ctx->tbl, bl); 151e1051a39Sopenharmony_ci make_kn(ctx->k2, ctx->k1, bl); 152e1051a39Sopenharmony_ci OPENSSL_cleanse(ctx->tbl, bl); 153e1051a39Sopenharmony_ci /* Reset context again ready for first data block */ 154e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) 155e1051a39Sopenharmony_ci return 0; 156e1051a39Sopenharmony_ci /* Zero tbl so resume works */ 157e1051a39Sopenharmony_ci memset(ctx->tbl, 0, bl); 158e1051a39Sopenharmony_ci ctx->nlast_block = 0; 159e1051a39Sopenharmony_ci } 160e1051a39Sopenharmony_ci return 1; 161e1051a39Sopenharmony_ci} 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ciint CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) 164e1051a39Sopenharmony_ci{ 165e1051a39Sopenharmony_ci const unsigned char *data = in; 166e1051a39Sopenharmony_ci int bl; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci if (ctx->nlast_block == -1) 169e1051a39Sopenharmony_ci return 0; 170e1051a39Sopenharmony_ci if (dlen == 0) 171e1051a39Sopenharmony_ci return 1; 172e1051a39Sopenharmony_ci if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) 173e1051a39Sopenharmony_ci return 0; 174e1051a39Sopenharmony_ci /* Copy into partial block if we need to */ 175e1051a39Sopenharmony_ci if (ctx->nlast_block > 0) { 176e1051a39Sopenharmony_ci size_t nleft; 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci nleft = bl - ctx->nlast_block; 179e1051a39Sopenharmony_ci if (dlen < nleft) 180e1051a39Sopenharmony_ci nleft = dlen; 181e1051a39Sopenharmony_ci memcpy(ctx->last_block + ctx->nlast_block, data, nleft); 182e1051a39Sopenharmony_ci dlen -= nleft; 183e1051a39Sopenharmony_ci ctx->nlast_block += nleft; 184e1051a39Sopenharmony_ci /* If no more to process return */ 185e1051a39Sopenharmony_ci if (dlen == 0) 186e1051a39Sopenharmony_ci return 1; 187e1051a39Sopenharmony_ci data += nleft; 188e1051a39Sopenharmony_ci /* Else not final block so encrypt it */ 189e1051a39Sopenharmony_ci if (EVP_Cipher(ctx->cctx, ctx->tbl, ctx->last_block, bl) <= 0) 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci } 192e1051a39Sopenharmony_ci /* Encrypt all but one of the complete blocks left */ 193e1051a39Sopenharmony_ci while (dlen > (size_t)bl) { 194e1051a39Sopenharmony_ci if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0) 195e1051a39Sopenharmony_ci return 0; 196e1051a39Sopenharmony_ci dlen -= bl; 197e1051a39Sopenharmony_ci data += bl; 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci /* Copy any data left to last block buffer */ 200e1051a39Sopenharmony_ci memcpy(ctx->last_block, data, dlen); 201e1051a39Sopenharmony_ci ctx->nlast_block = dlen; 202e1051a39Sopenharmony_ci return 1; 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci} 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ciint CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen) 207e1051a39Sopenharmony_ci{ 208e1051a39Sopenharmony_ci int i, bl, lb; 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci if (ctx->nlast_block == -1) 211e1051a39Sopenharmony_ci return 0; 212e1051a39Sopenharmony_ci if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) 213e1051a39Sopenharmony_ci return 0; 214e1051a39Sopenharmony_ci if (poutlen != NULL) 215e1051a39Sopenharmony_ci *poutlen = (size_t)bl; 216e1051a39Sopenharmony_ci if (!out) 217e1051a39Sopenharmony_ci return 1; 218e1051a39Sopenharmony_ci lb = ctx->nlast_block; 219e1051a39Sopenharmony_ci /* Is last block complete? */ 220e1051a39Sopenharmony_ci if (lb == bl) { 221e1051a39Sopenharmony_ci for (i = 0; i < bl; i++) 222e1051a39Sopenharmony_ci out[i] = ctx->last_block[i] ^ ctx->k1[i]; 223e1051a39Sopenharmony_ci } else { 224e1051a39Sopenharmony_ci ctx->last_block[lb] = 0x80; 225e1051a39Sopenharmony_ci if (bl - lb > 1) 226e1051a39Sopenharmony_ci memset(ctx->last_block + lb + 1, 0, bl - lb - 1); 227e1051a39Sopenharmony_ci for (i = 0; i < bl; i++) 228e1051a39Sopenharmony_ci out[i] = ctx->last_block[i] ^ ctx->k2[i]; 229e1051a39Sopenharmony_ci } 230e1051a39Sopenharmony_ci if (EVP_Cipher(ctx->cctx, out, out, bl) <= 0) { 231e1051a39Sopenharmony_ci OPENSSL_cleanse(out, bl); 232e1051a39Sopenharmony_ci return 0; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci return 1; 235e1051a39Sopenharmony_ci} 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ciint CMAC_resume(CMAC_CTX *ctx) 238e1051a39Sopenharmony_ci{ 239e1051a39Sopenharmony_ci if (ctx->nlast_block == -1) 240e1051a39Sopenharmony_ci return 0; 241e1051a39Sopenharmony_ci /* 242e1051a39Sopenharmony_ci * The buffer "tbl" contains the last fully encrypted block which is the 243e1051a39Sopenharmony_ci * last IV (or all zeroes if no last encrypted block). The last block has 244e1051a39Sopenharmony_ci * not been modified since CMAC_final(). So reinitialising using the last 245e1051a39Sopenharmony_ci * decrypted block will allow CMAC to continue after calling 246e1051a39Sopenharmony_ci * CMAC_Final(). 247e1051a39Sopenharmony_ci */ 248e1051a39Sopenharmony_ci return EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, ctx->tbl); 249e1051a39Sopenharmony_ci} 250