"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.2/libcanlock/src/hmac.c" (12 Mar 2017, 7031 Bytes) of package /linux/misc/tin-2.4.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hmac.c" see the Fossies "Dox" file reference documentation.

    1 /**************************** hmac.c ***************************/
    2 /***************** See RFC 6234 for details. *******************/
    3 /* Copyright (c) 2011 IETF Trust and the persons identified as */
    4 /* authors of the code.  All rights reserved.                  */
    5 /* See sha.h for terms of use and redistribution.              */
    6 
    7 /*
    8  *  Description:
    9  *      This file implements the HMAC algorithm (Keyed-Hashing for
   10  *      Message Authentication, [RFC 2104]), expressed in terms of
   11  *      the various SHA algorithms.
   12  */
   13 
   14 #include "sha.h"
   15 
   16 /*
   17  *  hmac
   18  *
   19  *  Description:
   20  *      This function will compute an HMAC message digest.
   21  *
   22  *  Parameters:
   23  *      whichSha: [in]
   24  *          One of SHA1, SHA224, SHA256, SHA384, SHA512
   25  *      message_array[ ]: [in]
   26  *          An array of octets representing the message.
   27  *          Note: in RFC 2104, this parameter is known
   28  *          as 'text'.
   29  *      length: [in]
   30  *          The length of the message in message_array.
   31  *      key[ ]: [in]
   32  *          The secret shared key.
   33  *      key_len: [in]
   34  *          The length of the secret shared key.
   35  *      digest[ ]: [out]
   36  *          Where the digest is to be returned.
   37  *          NOTE: The length of the digest is determined by
   38  *              the value of whichSha.
   39  *
   40  *  Returns:
   41  *      sha Error Code.
   42  *
   43  */
   44 int hmac(SHAversion whichSha,
   45     const unsigned char *message_array, int length,
   46     const unsigned char *key, int key_len,
   47     uint8_t digest[USHAMaxHashSize])
   48 {
   49   HMACContext context;
   50   return hmacReset(&context, whichSha, key, key_len) ||
   51          hmacInput(&context, message_array, length) ||
   52          hmacResult(&context, digest);
   53 }
   54 
   55 /*
   56  *  hmacReset
   57  *
   58  *  Description:
   59  *      This function will initialize the hmacContext in preparation
   60  *      for computing a new HMAC message digest.
   61  *
   62  *  Parameters:
   63  *      context: [in/out]
   64  *          The context to reset.
   65  *      whichSha: [in]
   66  *          One of SHA1, SHA224, SHA256, SHA384, SHA512
   67  *      key[ ]: [in]
   68  *          The secret shared key.
   69  *      key_len: [in]
   70  *          The length of the secret shared key.
   71  *
   72  *  Returns:
   73  *      sha Error Code.
   74  *
   75  */
   76 int hmacReset(HMACContext *context, enum SHAversion whichSha,
   77     const unsigned char *key, int key_len)
   78 {
   79   int i, blocksize, hashsize, ret;
   80 
   81   /* inner padding - key XORd with ipad */
   82   unsigned char k_ipad[USHA_Max_Message_Block_Size];
   83 
   84   /* temporary buffer when keylen > blocksize */
   85   unsigned char tempkey[USHAMaxHashSize];
   86 
   87   if (!context) return shaNull;
   88   context->Computed = 0;
   89   context->Corrupted = shaSuccess;
   90 
   91   blocksize = context->blockSize = USHABlockSize(whichSha);
   92   hashsize = context->hashSize = USHAHashSize(whichSha);
   93   context->whichSha = whichSha;
   94 
   95   /*
   96    * If key is longer than the hash blocksize,
   97    * reset it to key = HASH(key).
   98    */
   99   if (key_len > blocksize) {
  100     USHAContext tcontext;
  101     int err = USHAReset(&tcontext, whichSha) ||
  102               USHAInput(&tcontext, key, key_len) ||
  103               USHAResult(&tcontext, tempkey);
  104     if (err != shaSuccess) return err;
  105 
  106     key = tempkey;
  107     key_len = hashsize;
  108   }
  109 
  110   /*
  111    * The HMAC transform looks like:
  112    *
  113    * SHA(K XOR opad, SHA(K XOR ipad, text))
  114    *
  115    * where K is an n byte key, 0-padded to a total of blocksize bytes,
  116    * ipad is the byte 0x36 repeated blocksize times,
  117    * opad is the byte 0x5c repeated blocksize times,
  118    * and text is the data being protected.
  119    */
  120 
  121   /* store key into the pads, XOR'd with ipad and opad values */
  122   for (i = 0; i < key_len; i++) {
  123     k_ipad[i] = key[i] ^ 0x36;
  124     context->k_opad[i] = key[i] ^ 0x5c;
  125   }
  126   /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
  127   for ( ; i < blocksize; i++) {
  128     k_ipad[i] = 0x36;
  129     context->k_opad[i] = 0x5c;
  130   }
  131 
  132   /* perform inner hash */
  133   /* init context for 1st pass */
  134   ret = USHAReset(&context->shaContext, whichSha) ||
  135         /* and start with inner pad */
  136         USHAInput(&context->shaContext, k_ipad, blocksize);
  137   return context->Corrupted = ret;
  138 }
  139 
  140 /*
  141  *  hmacInput
  142  *
  143  *  Description:
  144  *      This function accepts an array of octets as the next portion
  145  *      of the message.  It may be called multiple times.
  146  *
  147  *  Parameters:
  148  *      context: [in/out]
  149  *          The HMAC context to update.
  150  *      text[ ]: [in]
  151  *          An array of octets representing the next portion of
  152  *          the message.
  153  *      text_len: [in]
  154  *          The length of the message in text.
  155  *
  156  *  Returns:
  157  *      sha Error Code.
  158  *
  159  */
  160 int hmacInput(HMACContext *context, const unsigned char *text,
  161     int text_len)
  162 {
  163   if (!context) return shaNull;
  164   if (context->Corrupted) return context->Corrupted;
  165   if (context->Computed) return context->Corrupted = shaStateError;
  166   /* then text of datagram */
  167   return context->Corrupted =
  168     USHAInput(&context->shaContext, text, text_len);
  169 }
  170 
  171 /*
  172  * hmacFinalBits
  173  *
  174  * Description:
  175  *   This function will add in any final bits of the message.
  176  *
  177  * Parameters:
  178  *   context: [in/out]
  179  *     The HMAC context to update.
  180  *   message_bits: [in]
  181  *     The final bits of the message, in the upper portion of the
  182  *     byte.  (Use 0b###00000 instead of 0b00000### to input the
  183  *     three bits ###.)
  184  *   length: [in]
  185  *     The number of bits in message_bits, between 1 and 7.
  186  *
  187  * Returns:
  188  *   sha Error Code.
  189  */
  190 int hmacFinalBits(HMACContext *context,
  191     uint8_t bits, unsigned int bit_count)
  192 {
  193   if (!context) return shaNull;
  194   if (context->Corrupted) return context->Corrupted;
  195   if (context->Computed) return context->Corrupted = shaStateError;
  196   /* then final bits of datagram */
  197   return context->Corrupted =
  198     USHAFinalBits(&context->shaContext, bits, bit_count);
  199 }
  200 
  201 /*
  202  * hmacResult
  203  *
  204  * Description:
  205  *   This function will return the N-byte message digest into the
  206  *   Message_Digest array provided by the caller.
  207  *
  208  * Parameters:
  209  *   context: [in/out]
  210  *     The context to use to calculate the HMAC hash.
  211  *   digest[ ]: [out]
  212  *     Where the digest is returned.
  213  *     NOTE 2: The length of the hash is determined by the value of
  214  *      whichSha that was passed to hmacReset().
  215  *
  216  * Returns:
  217  *   sha Error Code.
  218  *
  219  */
  220 int hmacResult(HMACContext *context, uint8_t *digest)
  221 {
  222   int ret;
  223   if (!context) return shaNull;
  224   if (context->Corrupted) return context->Corrupted;
  225   if (context->Computed) return context->Corrupted = shaStateError;
  226 
  227   /* finish up 1st pass */
  228   /* (Use digest here as a temporary buffer.) */
  229   ret =
  230     USHAResult(&context->shaContext, digest) ||
  231          /* perform outer SHA */
  232          /* init context for 2nd pass */
  233          USHAReset(&context->shaContext, context->whichSha) ||
  234 
  235          /* start with outer pad */
  236          USHAInput(&context->shaContext, context->k_opad,
  237                    context->blockSize) ||
  238 
  239          /* then results of 1st hash */
  240          USHAInput(&context->shaContext, digest, context->hashSize) ||
  241          /* finish up 2nd pass */
  242          USHAResult(&context->shaContext, digest);
  243 
  244   context->Computed = 1;
  245   return context->Corrupted = ret;
  246 }