1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 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 * HMAC 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/opensslconf.h> 21e1051a39Sopenharmony_ci#include <openssl/hmac.h> 22e1051a39Sopenharmony_ci#include <openssl/core_names.h> 23e1051a39Sopenharmony_ci#include "hmac_local.h" 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ciint HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, 26e1051a39Sopenharmony_ci const EVP_MD *md, ENGINE *impl) 27e1051a39Sopenharmony_ci{ 28e1051a39Sopenharmony_ci int rv = 0, reset = 0; 29e1051a39Sopenharmony_ci int i, j; 30e1051a39Sopenharmony_ci unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE]; 31e1051a39Sopenharmony_ci unsigned int keytmp_length; 32e1051a39Sopenharmony_ci unsigned char keytmp[HMAC_MAX_MD_CBLOCK_SIZE]; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci /* If we are changing MD then we must have a key */ 35e1051a39Sopenharmony_ci if (md != NULL && md != ctx->md && (key == NULL || len < 0)) 36e1051a39Sopenharmony_ci return 0; 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_ci if (md != NULL) 39e1051a39Sopenharmony_ci ctx->md = md; 40e1051a39Sopenharmony_ci else if (ctx->md != NULL) 41e1051a39Sopenharmony_ci md = ctx->md; 42e1051a39Sopenharmony_ci else 43e1051a39Sopenharmony_ci return 0; 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci /* 46e1051a39Sopenharmony_ci * The HMAC construction is not allowed to be used with the 47e1051a39Sopenharmony_ci * extendable-output functions (XOF) shake128 and shake256. 48e1051a39Sopenharmony_ci */ 49e1051a39Sopenharmony_ci if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) 50e1051a39Sopenharmony_ci return 0; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci if (key != NULL) { 53e1051a39Sopenharmony_ci reset = 1; 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci j = EVP_MD_get_block_size(md); 56e1051a39Sopenharmony_ci if (!ossl_assert(j <= (int)sizeof(keytmp))) 57e1051a39Sopenharmony_ci return 0; 58e1051a39Sopenharmony_ci if (j < 0) 59e1051a39Sopenharmony_ci return 0; 60e1051a39Sopenharmony_ci if (j < len) { 61e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl) 62e1051a39Sopenharmony_ci || !EVP_DigestUpdate(ctx->md_ctx, key, len) 63e1051a39Sopenharmony_ci || !EVP_DigestFinal_ex(ctx->md_ctx, keytmp, 64e1051a39Sopenharmony_ci &keytmp_length)) 65e1051a39Sopenharmony_ci return 0; 66e1051a39Sopenharmony_ci } else { 67e1051a39Sopenharmony_ci if (len < 0 || len > (int)sizeof(keytmp)) 68e1051a39Sopenharmony_ci return 0; 69e1051a39Sopenharmony_ci memcpy(keytmp, key, len); 70e1051a39Sopenharmony_ci keytmp_length = len; 71e1051a39Sopenharmony_ci } 72e1051a39Sopenharmony_ci if (keytmp_length != HMAC_MAX_MD_CBLOCK_SIZE) 73e1051a39Sopenharmony_ci memset(&keytmp[keytmp_length], 0, 74e1051a39Sopenharmony_ci HMAC_MAX_MD_CBLOCK_SIZE - keytmp_length); 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) 77e1051a39Sopenharmony_ci pad[i] = 0x36 ^ keytmp[i]; 78e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl) 79e1051a39Sopenharmony_ci || !EVP_DigestUpdate(ctx->i_ctx, pad, 80e1051a39Sopenharmony_ci EVP_MD_get_block_size(md))) 81e1051a39Sopenharmony_ci goto err; 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++) 84e1051a39Sopenharmony_ci pad[i] = 0x5c ^ keytmp[i]; 85e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl) 86e1051a39Sopenharmony_ci || !EVP_DigestUpdate(ctx->o_ctx, pad, 87e1051a39Sopenharmony_ci EVP_MD_get_block_size(md))) 88e1051a39Sopenharmony_ci goto err; 89e1051a39Sopenharmony_ci } 90e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx)) 91e1051a39Sopenharmony_ci goto err; 92e1051a39Sopenharmony_ci rv = 1; 93e1051a39Sopenharmony_ci err: 94e1051a39Sopenharmony_ci if (reset) { 95e1051a39Sopenharmony_ci OPENSSL_cleanse(keytmp, sizeof(keytmp)); 96e1051a39Sopenharmony_ci OPENSSL_cleanse(pad, sizeof(pad)); 97e1051a39Sopenharmony_ci } 98e1051a39Sopenharmony_ci return rv; 99e1051a39Sopenharmony_ci} 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_1_1_0 102e1051a39Sopenharmony_ciint HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) 103e1051a39Sopenharmony_ci{ 104e1051a39Sopenharmony_ci if (key && md) 105e1051a39Sopenharmony_ci HMAC_CTX_reset(ctx); 106e1051a39Sopenharmony_ci return HMAC_Init_ex(ctx, key, len, md, NULL); 107e1051a39Sopenharmony_ci} 108e1051a39Sopenharmony_ci#endif 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ciint HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) 111e1051a39Sopenharmony_ci{ 112e1051a39Sopenharmony_ci if (!ctx->md) 113e1051a39Sopenharmony_ci return 0; 114e1051a39Sopenharmony_ci return EVP_DigestUpdate(ctx->md_ctx, data, len); 115e1051a39Sopenharmony_ci} 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ciint HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) 118e1051a39Sopenharmony_ci{ 119e1051a39Sopenharmony_ci unsigned int i; 120e1051a39Sopenharmony_ci unsigned char buf[EVP_MAX_MD_SIZE]; 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci if (!ctx->md) 123e1051a39Sopenharmony_ci goto err; 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i)) 126e1051a39Sopenharmony_ci goto err; 127e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx)) 128e1051a39Sopenharmony_ci goto err; 129e1051a39Sopenharmony_ci if (!EVP_DigestUpdate(ctx->md_ctx, buf, i)) 130e1051a39Sopenharmony_ci goto err; 131e1051a39Sopenharmony_ci if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len)) 132e1051a39Sopenharmony_ci goto err; 133e1051a39Sopenharmony_ci return 1; 134e1051a39Sopenharmony_ci err: 135e1051a39Sopenharmony_ci return 0; 136e1051a39Sopenharmony_ci} 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_cisize_t HMAC_size(const HMAC_CTX *ctx) 139e1051a39Sopenharmony_ci{ 140e1051a39Sopenharmony_ci int size = EVP_MD_get_size((ctx)->md); 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ci return (size < 0) ? 0 : size; 143e1051a39Sopenharmony_ci} 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ciHMAC_CTX *HMAC_CTX_new(void) 146e1051a39Sopenharmony_ci{ 147e1051a39Sopenharmony_ci HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci if (ctx != NULL) { 150e1051a39Sopenharmony_ci if (!HMAC_CTX_reset(ctx)) { 151e1051a39Sopenharmony_ci HMAC_CTX_free(ctx); 152e1051a39Sopenharmony_ci return NULL; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci } 155e1051a39Sopenharmony_ci return ctx; 156e1051a39Sopenharmony_ci} 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_cistatic void hmac_ctx_cleanup(HMAC_CTX *ctx) 159e1051a39Sopenharmony_ci{ 160e1051a39Sopenharmony_ci EVP_MD_CTX_reset(ctx->i_ctx); 161e1051a39Sopenharmony_ci EVP_MD_CTX_reset(ctx->o_ctx); 162e1051a39Sopenharmony_ci EVP_MD_CTX_reset(ctx->md_ctx); 163e1051a39Sopenharmony_ci ctx->md = NULL; 164e1051a39Sopenharmony_ci} 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_civoid HMAC_CTX_free(HMAC_CTX *ctx) 167e1051a39Sopenharmony_ci{ 168e1051a39Sopenharmony_ci if (ctx != NULL) { 169e1051a39Sopenharmony_ci hmac_ctx_cleanup(ctx); 170e1051a39Sopenharmony_ci EVP_MD_CTX_free(ctx->i_ctx); 171e1051a39Sopenharmony_ci EVP_MD_CTX_free(ctx->o_ctx); 172e1051a39Sopenharmony_ci EVP_MD_CTX_free(ctx->md_ctx); 173e1051a39Sopenharmony_ci OPENSSL_free(ctx); 174e1051a39Sopenharmony_ci } 175e1051a39Sopenharmony_ci} 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_cistatic int hmac_ctx_alloc_mds(HMAC_CTX *ctx) 178e1051a39Sopenharmony_ci{ 179e1051a39Sopenharmony_ci if (ctx->i_ctx == NULL) 180e1051a39Sopenharmony_ci ctx->i_ctx = EVP_MD_CTX_new(); 181e1051a39Sopenharmony_ci if (ctx->i_ctx == NULL) 182e1051a39Sopenharmony_ci return 0; 183e1051a39Sopenharmony_ci if (ctx->o_ctx == NULL) 184e1051a39Sopenharmony_ci ctx->o_ctx = EVP_MD_CTX_new(); 185e1051a39Sopenharmony_ci if (ctx->o_ctx == NULL) 186e1051a39Sopenharmony_ci return 0; 187e1051a39Sopenharmony_ci if (ctx->md_ctx == NULL) 188e1051a39Sopenharmony_ci ctx->md_ctx = EVP_MD_CTX_new(); 189e1051a39Sopenharmony_ci if (ctx->md_ctx == NULL) 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci return 1; 192e1051a39Sopenharmony_ci} 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ciint HMAC_CTX_reset(HMAC_CTX *ctx) 195e1051a39Sopenharmony_ci{ 196e1051a39Sopenharmony_ci hmac_ctx_cleanup(ctx); 197e1051a39Sopenharmony_ci if (!hmac_ctx_alloc_mds(ctx)) { 198e1051a39Sopenharmony_ci hmac_ctx_cleanup(ctx); 199e1051a39Sopenharmony_ci return 0; 200e1051a39Sopenharmony_ci } 201e1051a39Sopenharmony_ci return 1; 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ciint HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) 205e1051a39Sopenharmony_ci{ 206e1051a39Sopenharmony_ci if (!hmac_ctx_alloc_mds(dctx)) 207e1051a39Sopenharmony_ci goto err; 208e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx)) 209e1051a39Sopenharmony_ci goto err; 210e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx)) 211e1051a39Sopenharmony_ci goto err; 212e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx)) 213e1051a39Sopenharmony_ci goto err; 214e1051a39Sopenharmony_ci dctx->md = sctx->md; 215e1051a39Sopenharmony_ci return 1; 216e1051a39Sopenharmony_ci err: 217e1051a39Sopenharmony_ci hmac_ctx_cleanup(dctx); 218e1051a39Sopenharmony_ci return 0; 219e1051a39Sopenharmony_ci} 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ciunsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, 222e1051a39Sopenharmony_ci const unsigned char *data, size_t data_len, 223e1051a39Sopenharmony_ci unsigned char *md, unsigned int *md_len) 224e1051a39Sopenharmony_ci{ 225e1051a39Sopenharmony_ci static unsigned char static_md[EVP_MAX_MD_SIZE]; 226e1051a39Sopenharmony_ci int size = EVP_MD_get_size(evp_md); 227e1051a39Sopenharmony_ci size_t temp_md_len = 0; 228e1051a39Sopenharmony_ci unsigned char *ret = NULL; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if (size >= 0) { 231e1051a39Sopenharmony_ci ret = EVP_Q_mac(NULL, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, 232e1051a39Sopenharmony_ci key, key_len, data, data_len, 233e1051a39Sopenharmony_ci md == NULL ? static_md : md, size, &temp_md_len); 234e1051a39Sopenharmony_ci if (md_len != NULL) 235e1051a39Sopenharmony_ci *md_len = (unsigned int)temp_md_len; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci return ret; 238e1051a39Sopenharmony_ci} 239e1051a39Sopenharmony_ci 240e1051a39Sopenharmony_civoid HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) 241e1051a39Sopenharmony_ci{ 242e1051a39Sopenharmony_ci EVP_MD_CTX_set_flags(ctx->i_ctx, flags); 243e1051a39Sopenharmony_ci EVP_MD_CTX_set_flags(ctx->o_ctx, flags); 244e1051a39Sopenharmony_ci EVP_MD_CTX_set_flags(ctx->md_ctx, flags); 245e1051a39Sopenharmony_ci} 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ciconst EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) 248e1051a39Sopenharmony_ci{ 249e1051a39Sopenharmony_ci return ctx->md; 250e1051a39Sopenharmony_ci} 251