1/* 2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <openssl/hmac.h> 11 12#include <assert.h> 13#include <string.h> 14 15#include <openssl/digest.h> 16#include <openssl/mem.h> 17 18#include "../../internal.h" 19#include "../service_indicator/internal.h" 20 21 22uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len, 23 const uint8_t *data, size_t data_len, uint8_t *out, 24 unsigned int *out_len) { 25 HMAC_CTX ctx; 26 HMAC_CTX_init(&ctx); 27 28 // The underlying hash functions should not set the FIPS service indicator 29 // until all operations have completed. 30 FIPS_service_indicator_lock_state(); 31 const int ok = HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) && 32 HMAC_Update(&ctx, data, data_len) && 33 HMAC_Final(&ctx, out, out_len); 34 FIPS_service_indicator_unlock_state(); 35 36 HMAC_CTX_cleanup(&ctx); 37 38 if (!ok) { 39 return NULL; 40 } 41 42 HMAC_verify_service_indicator(evp_md); 43 return out; 44} 45 46void HMAC_CTX_init(HMAC_CTX *ctx) { 47 ctx->md = NULL; 48 EVP_MD_CTX_init(&ctx->i_ctx); 49 EVP_MD_CTX_init(&ctx->o_ctx); 50 EVP_MD_CTX_init(&ctx->md_ctx); 51} 52 53HMAC_CTX *HMAC_CTX_new(void) { 54 HMAC_CTX *ctx = 55 reinterpret_cast<HMAC_CTX *>(OPENSSL_malloc(sizeof(HMAC_CTX))); 56 if (ctx != NULL) { 57 HMAC_CTX_init(ctx); 58 } 59 return ctx; 60} 61 62void HMAC_CTX_cleanup(HMAC_CTX *ctx) { 63 EVP_MD_CTX_cleanup(&ctx->i_ctx); 64 EVP_MD_CTX_cleanup(&ctx->o_ctx); 65 EVP_MD_CTX_cleanup(&ctx->md_ctx); 66 OPENSSL_cleanse(ctx, sizeof(HMAC_CTX)); 67} 68 69void HMAC_CTX_cleanse(HMAC_CTX *ctx) { 70 EVP_MD_CTX_cleanse(&ctx->i_ctx); 71 EVP_MD_CTX_cleanse(&ctx->o_ctx); 72 EVP_MD_CTX_cleanse(&ctx->md_ctx); 73 OPENSSL_cleanse(ctx, sizeof(HMAC_CTX)); 74} 75 76void HMAC_CTX_free(HMAC_CTX *ctx) { 77 if (ctx == NULL) { 78 return; 79 } 80 81 HMAC_CTX_cleanup(ctx); 82 OPENSSL_free(ctx); 83} 84 85int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, 86 const EVP_MD *md, ENGINE *impl) { 87 int ret = 0; 88 FIPS_service_indicator_lock_state(); 89 90 if (md == NULL) { 91 md = ctx->md; 92 } 93 94 // If either |key| is non-NULL or |md| has changed, initialize with a new key 95 // rather than rewinding the previous one. 96 // 97 // TODO(davidben,eroman): Passing the previous |md| with a NULL |key| is 98 // ambiguous between using the empty key and reusing the previous key. There 99 // exist callers which intend the latter, but the former is an awkward edge 100 // case. Fix to API to avoid this. 101 if (md != ctx->md || key != NULL) { 102 uint8_t pad[EVP_MAX_MD_BLOCK_SIZE]; 103 uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE]; 104 unsigned key_block_len; 105 106 size_t block_size = EVP_MD_block_size(md); 107 assert(block_size <= sizeof(key_block)); 108 assert(EVP_MD_size(md) <= block_size); 109 if (block_size < key_len) { 110 // Long keys are hashed. 111 if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl) || 112 !EVP_DigestUpdate(&ctx->md_ctx, key, key_len) || 113 !EVP_DigestFinal_ex(&ctx->md_ctx, key_block, &key_block_len)) { 114 goto out; 115 } 116 } else { 117 assert(key_len <= sizeof(key_block)); 118 OPENSSL_memcpy(key_block, key, key_len); 119 key_block_len = (unsigned)key_len; 120 } 121 // Keys are then padded with zeros. 122 OPENSSL_memset(key_block + key_block_len, 0, block_size - key_block_len); 123 124 for (size_t i = 0; i < block_size; i++) { 125 pad[i] = 0x36 ^ key_block[i]; 126 } 127 if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) || 128 !EVP_DigestUpdate(&ctx->i_ctx, pad, block_size)) { 129 goto out; 130 } 131 132 for (size_t i = 0; i < block_size; i++) { 133 pad[i] = 0x5c ^ key_block[i]; 134 } 135 if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) || 136 !EVP_DigestUpdate(&ctx->o_ctx, pad, block_size)) { 137 goto out; 138 } 139 140 ctx->md = md; 141 } 142 143 ret = EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx); 144 145out: 146 FIPS_service_indicator_unlock_state(); 147 return ret; 148} 149 150int HMAC_Update(HMAC_CTX *ctx, const uint8_t *data, size_t data_len) { 151 return EVP_DigestUpdate(&ctx->md_ctx, data, data_len); 152} 153 154int HMAC_Final(HMAC_CTX *ctx, uint8_t *out, unsigned int *out_len) { 155 int ret = 0; 156 unsigned int i; 157 uint8_t buf[EVP_MAX_MD_SIZE]; 158 159 FIPS_service_indicator_lock_state(); 160 // TODO(davidben): The only thing that can officially fail here is 161 // |EVP_MD_CTX_copy_ex|, but even that should be impossible in this case. 162 if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i) || 163 !EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx) || 164 !EVP_DigestUpdate(&ctx->md_ctx, buf, i) || 165 !EVP_DigestFinal_ex(&ctx->md_ctx, out, out_len)) { 166 *out_len = 0; 167 goto out; 168 } 169 170 ret = 1; 171 172out: 173 FIPS_service_indicator_unlock_state(); 174 if (ret) { 175 HMAC_verify_service_indicator(ctx->md); 176 } 177 return ret; 178} 179 180size_t HMAC_size(const HMAC_CTX *ctx) { return EVP_MD_size(ctx->md); } 181 182const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx) { return ctx->md; } 183 184int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src) { 185 if (!EVP_MD_CTX_copy_ex(&dest->i_ctx, &src->i_ctx) || 186 !EVP_MD_CTX_copy_ex(&dest->o_ctx, &src->o_ctx) || 187 !EVP_MD_CTX_copy_ex(&dest->md_ctx, &src->md_ctx)) { 188 return 0; 189 } 190 191 dest->md = src->md; 192 return 1; 193} 194 195void HMAC_CTX_reset(HMAC_CTX *ctx) { 196 HMAC_CTX_cleanup(ctx); 197 HMAC_CTX_init(ctx); 198} 199 200int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) { 201 if (key && md) { 202 HMAC_CTX_init(ctx); 203 } 204 return HMAC_Init_ex(ctx, key, key_len, md, NULL); 205} 206 207int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src) { 208 HMAC_CTX_init(dest); 209 return HMAC_CTX_copy_ex(dest, src); 210} 211