Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      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
     12  * are also available at http://curl.haxx.se/docs/copyright.html.
     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 
     25 #include "curl_setup.h"
     26 
     27 #ifndef CURL_DISABLE_CRYPTO_AUTH
     28 
     29 #include "curl_hmac.h"
     30 #include "curl_memory.h"
     31 /* The last #include file should be: */
     32 #include "memdebug.h"
     33 
     34 /*
     35  * Generic HMAC algorithm.
     36  *
     37  *   This module computes HMAC digests based on any hash function. Parameters
     38  * and computing procedures are set-up dynamically at HMAC computation
     39  * context initialisation.
     40  */
     41 
     42 static const unsigned char hmac_ipad = 0x36;
     43 static const unsigned char hmac_opad = 0x5C;
     44 
     45 
     46 
     47 HMAC_context *
     48 Curl_HMAC_init(const HMAC_params * hashparams,
     49                const unsigned char * key,
     50                unsigned int keylen)
     51 {
     52   size_t i;
     53   HMAC_context * ctxt;
     54   unsigned char * hkey;
     55   unsigned char b;
     56 
     57   /* Create HMAC context. */
     58   i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
     59     hashparams->hmac_resultlen;
     60   ctxt = malloc(i);
     61 
     62   if(!ctxt)
     63     return ctxt;
     64 
     65   ctxt->hmac_hash = hashparams;
     66   ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
     67   ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
     68       hashparams->hmac_ctxtsize);
     69 
     70   /* If the key is too long, replace it by its hash digest. */
     71   if(keylen > hashparams->hmac_maxkeylen) {
     72     (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
     73     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
     74     hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
     75     (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
     76     key = hkey;
     77     keylen = hashparams->hmac_resultlen;
     78   }
     79 
     80   /* Prime the two hash contexts with the modified key. */
     81   (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
     82   (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
     83 
     84   for(i = 0; i < keylen; i++) {
     85     b = (unsigned char)(*key ^ hmac_ipad);
     86     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
     87     b = (unsigned char)(*key++ ^ hmac_opad);
     88     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
     89   }
     90 
     91   for(; i < hashparams->hmac_maxkeylen; i++) {
     92     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
     93     (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
     94   }
     95 
     96   /* Done, return pointer to HMAC context. */
     97   return ctxt;
     98 }
     99 
    100 int Curl_HMAC_update(HMAC_context * ctxt,
    101                      const unsigned char * data,
    102                      unsigned int len)
    103 {
    104   /* Update first hash calculation. */
    105   (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
    106   return 0;
    107 }
    108 
    109 
    110 int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
    111 {
    112   const HMAC_params * hashparams = ctxt->hmac_hash;
    113 
    114   /* Do not get result if called with a null parameter: only release
    115      storage. */
    116 
    117   if(!result)
    118     result = (unsigned char *) ctxt->hmac_hashctxt2 +
    119      ctxt->hmac_hash->hmac_ctxtsize;
    120 
    121   (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
    122   (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
    123    result, hashparams->hmac_resultlen);
    124   (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
    125   free((char *) ctxt);
    126   return 0;
    127 }
    128 
    129 #endif /* CURL_DISABLE_CRYPTO_AUTH */
    130