19bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*************************************************************************** 29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * _ _ ____ _ 39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Project ___| | | | _ \| | 49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * / __| | | | |_) | | 59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * | (__| |_| | _ <| |___ 69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * \___|\___/|_| \_\_____| 79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 88f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. 99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is licensed as described in the file COPYING, which 119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * you should have received as part of this distribution. The terms 128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html. 139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * You may opt to use, copy, modify, merge, publish, distribute and/or sell 159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * copies of the Software, and permit persons to whom the Software is 169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * furnished to do so, under the terms of the COPYING file. 179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * KIND, either express or implied. 209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * RFC2104 Keyed-Hashing for Message Authentication 229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ***************************************************************************/ 249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 25e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h" 269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifndef CURL_DISABLE_CRYPTO_AUTH 289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 298f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo#include <curl/curl.h> 308f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curl_hmac.h" 329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curl_memory.h" 338f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* The last #include file should be: */ 359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "memdebug.h" 369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* 389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Generic HMAC algorithm. 399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * 409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This module computes HMAC digests based on any hash function. Parameters 419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * and computing procedures are set-up dynamically at HMAC computation 429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * context initialisation. 439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */ 449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic const unsigned char hmac_ipad = 0x36; 469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic const unsigned char hmac_opad = 0x5C; 479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsHMAC_context * 519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas EckelsCurl_HMAC_init(const HMAC_params * hashparams, 52cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes const unsigned char *key, 539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned int keylen) 549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels size_t i; 56cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes HMAC_context *ctxt; 57cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes unsigned char *hkey; 589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned char b; 599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Create HMAC context. */ 61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize + 62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET hashparams->hmac_resultlen; 63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ctxt = malloc(i); 649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!ctxt) 669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return ctxt; 679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ctxt->hmac_hash = hashparams; 699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); 709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + 719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels hashparams->hmac_ctxtsize); 729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* If the key is too long, replace it by its hash digest. */ 749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(keylen > hashparams->hmac_maxkeylen) { 759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); 769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); 779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; 789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); 799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels key = hkey; 809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels keylen = hashparams->hmac_resultlen; 819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Prime the two hash contexts with the modified key. */ 849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); 859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); 869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i = 0; i < keylen; i++) { 88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET b = (unsigned char)(*key ^ hmac_ipad); 899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); 90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET b = (unsigned char)(*key++ ^ hmac_opad); 919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); 929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(; i < hashparams->hmac_maxkeylen; i++) { 959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); 969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); 979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels } 989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Done, return pointer to HMAC context. */ 1009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return ctxt; 1019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsint Curl_HMAC_update(HMAC_context * ctxt, 104cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes const unsigned char *data, 1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels unsigned int len) 1069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels /* Update first hash calculation. */ 1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); 1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 1109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 113cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughesint Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) 1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{ 1159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels const HMAC_params * hashparams = ctxt->hmac_hash; 1169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Do not get result if called with a null parameter: only release 118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET storage. */ 1199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels if(!result) 1219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result = (unsigned char *) ctxt->hmac_hashctxt2 + 1229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ctxt->hmac_hash->hmac_ctxtsize; 1239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); 1259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, 1269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels result, hashparams->hmac_resultlen); 1279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); 1289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels free((char *) ctxt); 1299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels return 0; 1309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels} 1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels 1329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif /* CURL_DISABLE_CRYPTO_AUTH */ 133