155714Skris/* crypto/hmac/hmac.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris#include <stdio.h> 5955714Skris#include <stdlib.h> 6055714Skris#include <string.h> 61160814Ssimon#include "cryptlib.h" 6255714Skris#include <openssl/hmac.h> 6355714Skris 64238405Sjkim#ifdef OPENSSL_FIPS 65238405Sjkim#include <openssl/fips.h> 66238405Sjkim#endif 67194206Ssimon 68238405Sjkimint HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, 69109998Smarkm const EVP_MD *md, ENGINE *impl) 7055714Skris { 7155714Skris int i,j,reset=0; 7255714Skris unsigned char pad[HMAC_MAX_MD_CBLOCK]; 7355714Skris 74238405Sjkim#ifdef OPENSSL_FIPS 75238405Sjkim if (FIPS_mode()) 76238405Sjkim { 77238405Sjkim /* If we have an ENGINE need to allow non FIPS */ 78238405Sjkim if ((impl || ctx->i_ctx.engine) 79238405Sjkim && !(ctx->i_ctx.flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) 80238405Sjkim { 81238405Sjkim EVPerr(EVP_F_HMAC_INIT_EX, EVP_R_DISABLED_FOR_FIPS); 82238405Sjkim return 0; 83238405Sjkim } 84238405Sjkim /* Other algorithm blocking will be done in FIPS_cmac_init, 85238405Sjkim * via FIPS_hmac_init_ex(). 86238405Sjkim */ 87238405Sjkim if (!impl && !ctx->i_ctx.engine) 88238405Sjkim return FIPS_hmac_init_ex(ctx, key, len, md, NULL); 89238405Sjkim } 90238405Sjkim#endif 91238405Sjkim 9255714Skris if (md != NULL) 9355714Skris { 9455714Skris reset=1; 9555714Skris ctx->md=md; 9655714Skris } 9755714Skris else 9855714Skris md=ctx->md; 9955714Skris 10055714Skris if (key != NULL) 10155714Skris { 10255714Skris reset=1; 10355714Skris j=EVP_MD_block_size(md); 104160814Ssimon OPENSSL_assert(j <= (int)sizeof(ctx->key)); 10555714Skris if (j < len) 10655714Skris { 107238405Sjkim if (!EVP_DigestInit_ex(&ctx->md_ctx,md, impl)) 108238405Sjkim goto err; 109238405Sjkim if (!EVP_DigestUpdate(&ctx->md_ctx,key,len)) 110238405Sjkim goto err; 111238405Sjkim if (!EVP_DigestFinal_ex(&(ctx->md_ctx),ctx->key, 112238405Sjkim &ctx->key_length)) 113238405Sjkim goto err; 11455714Skris } 11555714Skris else 11655714Skris { 117160814Ssimon OPENSSL_assert(len>=0 && len<=(int)sizeof(ctx->key)); 11855714Skris memcpy(ctx->key,key,len); 11955714Skris ctx->key_length=len; 12055714Skris } 12159191Skris if(ctx->key_length != HMAC_MAX_MD_CBLOCK) 12259191Skris memset(&ctx->key[ctx->key_length], 0, 12359191Skris HMAC_MAX_MD_CBLOCK - ctx->key_length); 12455714Skris } 12555714Skris 12655714Skris if (reset) 12755714Skris { 12855714Skris for (i=0; i<HMAC_MAX_MD_CBLOCK; i++) 12955714Skris pad[i]=0x36^ctx->key[i]; 130238405Sjkim if (!EVP_DigestInit_ex(&ctx->i_ctx,md, impl)) 131238405Sjkim goto err; 132238405Sjkim if (!EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md))) 133238405Sjkim goto err; 13455714Skris 13555714Skris for (i=0; i<HMAC_MAX_MD_CBLOCK; i++) 13655714Skris pad[i]=0x5c^ctx->key[i]; 137238405Sjkim if (!EVP_DigestInit_ex(&ctx->o_ctx,md, impl)) 138238405Sjkim goto err; 139238405Sjkim if (!EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md))) 140238405Sjkim goto err; 14155714Skris } 142238405Sjkim if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx)) 143238405Sjkim goto err; 144238405Sjkim return 1; 145238405Sjkim err: 146238405Sjkim return 0; 147109998Smarkm } 14855714Skris 149238405Sjkimint HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md) 150109998Smarkm { 151109998Smarkm if(key && md) 152109998Smarkm HMAC_CTX_init(ctx); 153238405Sjkim return HMAC_Init_ex(ctx,key,len,md, NULL); 15455714Skris } 15555714Skris 156238405Sjkimint HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) 15755714Skris { 158238405Sjkim#ifdef OPENSSL_FIPS 159238405Sjkim if (FIPS_mode() && !ctx->i_ctx.engine) 160238405Sjkim return FIPS_hmac_update(ctx, data, len); 161238405Sjkim#endif 162238405Sjkim return EVP_DigestUpdate(&ctx->md_ctx,data,len); 16355714Skris } 16455714Skris 165238405Sjkimint HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) 16655714Skris { 16755714Skris unsigned int i; 16855714Skris unsigned char buf[EVP_MAX_MD_SIZE]; 169238405Sjkim#ifdef OPENSSL_FIPS 170238405Sjkim if (FIPS_mode() && !ctx->i_ctx.engine) 171238405Sjkim return FIPS_hmac_final(ctx, md, len); 172238405Sjkim#endif 17355714Skris 174238405Sjkim if (!EVP_DigestFinal_ex(&ctx->md_ctx,buf,&i)) 175238405Sjkim goto err; 176238405Sjkim if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->o_ctx)) 177238405Sjkim goto err; 178238405Sjkim if (!EVP_DigestUpdate(&ctx->md_ctx,buf,i)) 179238405Sjkim goto err; 180238405Sjkim if (!EVP_DigestFinal_ex(&ctx->md_ctx,md,len)) 181238405Sjkim goto err; 182238405Sjkim return 1; 183238405Sjkim err: 184238405Sjkim return 0; 18555714Skris } 18655714Skris 187109998Smarkmvoid HMAC_CTX_init(HMAC_CTX *ctx) 18855714Skris { 189109998Smarkm EVP_MD_CTX_init(&ctx->i_ctx); 190109998Smarkm EVP_MD_CTX_init(&ctx->o_ctx); 191109998Smarkm EVP_MD_CTX_init(&ctx->md_ctx); 19255714Skris } 19355714Skris 194238405Sjkimint HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) 195238405Sjkim { 196238405Sjkim if (!EVP_MD_CTX_copy(&dctx->i_ctx, &sctx->i_ctx)) 197238405Sjkim goto err; 198238405Sjkim if (!EVP_MD_CTX_copy(&dctx->o_ctx, &sctx->o_ctx)) 199238405Sjkim goto err; 200238405Sjkim if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx)) 201238405Sjkim goto err; 202238405Sjkim memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); 203238405Sjkim dctx->key_length = sctx->key_length; 204238405Sjkim dctx->md = sctx->md; 205238405Sjkim return 1; 206238405Sjkim err: 207238405Sjkim return 0; 208238405Sjkim } 209238405Sjkim 210109998Smarkmvoid HMAC_CTX_cleanup(HMAC_CTX *ctx) 211109998Smarkm { 212238405Sjkim#ifdef OPENSSL_FIPS 213238405Sjkim if (FIPS_mode() && !ctx->i_ctx.engine) 214238405Sjkim { 215238405Sjkim FIPS_hmac_ctx_cleanup(ctx); 216238405Sjkim return; 217238405Sjkim } 218238405Sjkim#endif 219109998Smarkm EVP_MD_CTX_cleanup(&ctx->i_ctx); 220109998Smarkm EVP_MD_CTX_cleanup(&ctx->o_ctx); 221109998Smarkm EVP_MD_CTX_cleanup(&ctx->md_ctx); 222109998Smarkm memset(ctx,0,sizeof *ctx); 223109998Smarkm } 224109998Smarkm 22555714Skrisunsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, 226160814Ssimon const unsigned char *d, size_t n, unsigned char *md, 22755714Skris unsigned int *md_len) 22855714Skris { 22955714Skris HMAC_CTX c; 23055714Skris static unsigned char m[EVP_MAX_MD_SIZE]; 23155714Skris 23255714Skris if (md == NULL) md=m; 233109998Smarkm HMAC_CTX_init(&c); 234238405Sjkim if (!HMAC_Init(&c,key,key_len,evp_md)) 235238405Sjkim goto err; 236238405Sjkim if (!HMAC_Update(&c,d,n)) 237238405Sjkim goto err; 238238405Sjkim if (!HMAC_Final(&c,md,md_len)) 239238405Sjkim goto err; 240109998Smarkm HMAC_CTX_cleanup(&c); 241238405Sjkim return md; 242238405Sjkim err: 243238405Sjkim return NULL; 24455714Skris } 24555714Skris 246194206Ssimonvoid HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags) 247194206Ssimon { 248194206Ssimon EVP_MD_CTX_set_flags(&ctx->i_ctx, flags); 249194206Ssimon EVP_MD_CTX_set_flags(&ctx->o_ctx, flags); 250194206Ssimon EVP_MD_CTX_set_flags(&ctx->md_ctx, flags); 251194206Ssimon } 252