| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 1 | /*************************************************************************** | 
 | 2 |  *                                  _   _ ____  _ | 
 | 3 |  *  Project                     ___| | | |  _ \| | | 
 | 4 |  *                             / __| | | | |_) | | | 
 | 5 |  *                            | (__| |_| |  _ <| |___ | 
 | 6 |  *                             \___|\___/|_| \_\_____| | 
 | 7 |  * | 
| Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 8 |  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 9 |  * | 
 | 10 |  * This software is licensed as described in the file COPYING, which | 
 | 11 |  * you should have received as part of this distribution. The terms | 
| Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 12 |  * are also available at https://curl.haxx.se/docs/copyright.html. | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 13 |  * | 
 | 14 |  * You may opt to use, copy, modify, merge, publish, distribute and/or sell | 
 | 15 |  * copies of the Software, and permit persons to whom the Software is | 
 | 16 |  * furnished to do so, under the terms of the COPYING file. | 
 | 17 |  * | 
 | 18 |  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | 
 | 19 |  * KIND, either express or implied. | 
 | 20 |  * | 
 | 21 |  * RFC2104 Keyed-Hashing for Message Authentication | 
 | 22 |  * | 
 | 23 |  ***************************************************************************/ | 
 | 24 |  | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 25 | #include "curl_setup.h" | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 26 |  | 
 | 27 | #ifndef CURL_DISABLE_CRYPTO_AUTH | 
 | 28 |  | 
| Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 29 | #include <curl/curl.h> | 
 | 30 |  | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 31 | #include "curl_hmac.h" | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 32 | #include "curl_memory.h" | 
| Alex Deymo | 8f1a214 | 2016-06-28 14:49:26 -0700 | [diff] [blame] | 33 |  | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 34 | /* The last #include file should be: */ | 
 | 35 | #include "memdebug.h" | 
 | 36 |  | 
 | 37 | /* | 
 | 38 |  * Generic HMAC algorithm. | 
 | 39 |  * | 
 | 40 |  *   This module computes HMAC digests based on any hash function. Parameters | 
 | 41 |  * and computing procedures are set-up dynamically at HMAC computation | 
 | 42 |  * context initialisation. | 
 | 43 |  */ | 
 | 44 |  | 
 | 45 | static const unsigned char hmac_ipad = 0x36; | 
 | 46 | static const unsigned char hmac_opad = 0x5C; | 
 | 47 |  | 
 | 48 |  | 
 | 49 |  | 
 | 50 | HMAC_context * | 
 | 51 | Curl_HMAC_init(const HMAC_params * hashparams, | 
| Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 52 |                const unsigned char *key, | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 53 |                unsigned int keylen) | 
 | 54 | { | 
 | 55 |   size_t i; | 
| Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 56 |   HMAC_context *ctxt; | 
 | 57 |   unsigned char *hkey; | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 58 |   unsigned char b; | 
 | 59 |  | 
 | 60 |   /* Create HMAC context. */ | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 61 |   i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize + | 
 | 62 |     hashparams->hmac_resultlen; | 
 | 63 |   ctxt = malloc(i); | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 64 |  | 
 | 65 |   if(!ctxt) | 
 | 66 |     return ctxt; | 
 | 67 |  | 
 | 68 |   ctxt->hmac_hash = hashparams; | 
 | 69 |   ctxt->hmac_hashctxt1 = (void *) (ctxt + 1); | 
 | 70 |   ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 + | 
 | 71 |       hashparams->hmac_ctxtsize); | 
 | 72 |  | 
 | 73 |   /* If the key is too long, replace it by its hash digest. */ | 
 | 74 |   if(keylen > hashparams->hmac_maxkeylen) { | 
 | 75 |     (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); | 
 | 76 |     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen); | 
 | 77 |     hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize; | 
 | 78 |     (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1); | 
 | 79 |     key = hkey; | 
 | 80 |     keylen = hashparams->hmac_resultlen; | 
 | 81 |   } | 
 | 82 |  | 
 | 83 |   /* Prime the two hash contexts with the modified key. */ | 
 | 84 |   (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1); | 
 | 85 |   (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2); | 
 | 86 |  | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 87 |   for(i = 0; i < keylen; i++) { | 
 | 88 |     b = (unsigned char)(*key ^ hmac_ipad); | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 89 |     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1); | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 90 |     b = (unsigned char)(*key++ ^ hmac_opad); | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 91 |     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1); | 
 | 92 |   } | 
 | 93 |  | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 94 |   for(; i < hashparams->hmac_maxkeylen; i++) { | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 95 |     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1); | 
 | 96 |     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1); | 
 | 97 |   } | 
 | 98 |  | 
 | 99 |   /* Done, return pointer to HMAC context. */ | 
 | 100 |   return ctxt; | 
 | 101 | } | 
 | 102 |  | 
 | 103 | int Curl_HMAC_update(HMAC_context * ctxt, | 
| Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 104 |                      const unsigned char *data, | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 105 |                      unsigned int len) | 
 | 106 | { | 
 | 107 |   /* Update first hash calculation. */ | 
 | 108 |   (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len); | 
 | 109 |   return 0; | 
 | 110 | } | 
 | 111 |  | 
 | 112 |  | 
| Elliott Hughes | cee0338 | 2017-06-23 12:17:18 -0700 | [diff] [blame] | 113 | int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 114 | { | 
 | 115 |   const HMAC_params * hashparams = ctxt->hmac_hash; | 
 | 116 |  | 
| Bertrand SIMONNET | e6cd738 | 2015-07-01 15:39:44 -0700 | [diff] [blame] | 117 |   /* Do not get result if called with a null parameter: only release | 
 | 118 |      storage. */ | 
| Lucas Eckels | 9bd90e6 | 2012-08-06 15:07:02 -0700 | [diff] [blame] | 119 |  | 
 | 120 |   if(!result) | 
 | 121 |     result = (unsigned char *) ctxt->hmac_hashctxt2 + | 
 | 122 |      ctxt->hmac_hash->hmac_ctxtsize; | 
 | 123 |  | 
 | 124 |   (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1); | 
 | 125 |   (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, | 
 | 126 |    result, hashparams->hmac_resultlen); | 
 | 127 |   (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2); | 
 | 128 |   free((char *) ctxt); | 
 | 129 |   return 0; | 
 | 130 | } | 
 | 131 |  | 
 | 132 | #endif /* CURL_DISABLE_CRYPTO_AUTH */ |