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