Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hmac.c Source File

hmac.c

Go to the documentation of this file.
00001 /**
00002  * @file hmac.c
00003  * @brief HMAC (Keyed-Hashing for Message Authentication)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @section Description
00026  *
00027  * HMAC is a mechanism for message authentication using cryptographic hash
00028  * functions. HMAC can be used with any iterative cryptographic hash
00029  * function (MD5, SHA-1 or SHA-256) in combination with a secret shared
00030  * key. Refer to RFC 2104 for more details
00031  *
00032  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00033  * @version 1.7.6
00034  **/
00035 
00036 //Switch to the appropriate trace level
00037 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00038 
00039 //Dependencies
00040 #include <string.h>
00041 #include "crypto.h"
00042 #include "hmac.h"
00043 
00044 //Check crypto library configuration
00045 #if (HMAC_SUPPORT == ENABLED)
00046 
00047 //HMAC with MD5 OID (1.3.6.1.5.5.8.1.1)
00048 const uint8_t HMAC_WITH_MD5_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x01};
00049 //HMAC with Tiger OID (1.3.6.1.5.5.8.1.3)
00050 const uint8_t HMAC_WITH_TIGER_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x03};
00051 //HMAC with RIPEMD-160 OID (1.3.6.1.5.5.8.1.4)
00052 const uint8_t HMAC_WITH_RIPEMD160_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x04};
00053 //HMAC with SHA-1 OID (1.2.840.113549.2.7)
00054 const uint8_t HMAC_WITH_SHA1_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07};
00055 //HMAC with SHA-224 OID (1.2.840.113549.2.8)
00056 const uint8_t HMAC_WITH_SHA224_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x08};
00057 //HMAC with SHA-256 OID (1.2.840.113549.2.9)
00058 const uint8_t HMAC_WITH_SHA256_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09};
00059 //HMAC with SHA-384 OID (1.2.840.113549.2.10)
00060 const uint8_t HMAC_WITH_SHA384_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0A};
00061 //HMAC with SHA-512 OID (1.2.840.113549.2.11)
00062 const uint8_t HMAC_WITH_SHA512_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0B};
00063 //HMAC with SHA-3-224 object identifier (2.16.840.1.101.3.4.2.13)
00064 const uint8_t HMAC_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0D};
00065 //HMAC with SHA-3-256 object identifier (2.16.840.1.101.3.4.2.14)
00066 const uint8_t HMAC_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0E};
00067 //HMAC with SHA-3-384 object identifier (2.16.840.1.101.3.4.2.15)
00068 const uint8_t HMAC_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0F};
00069 //HMAC with SHA-3-512 object identifier (2.16.840.1.101.3.4.2.16)
00070 const uint8_t HMAC_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x10};
00071 
00072 
00073 /**
00074  * @brief Compute HMAC using the specified hash function
00075  * @param[in] hash Hash algorithm used to compute HMAC
00076  * @param[in] key Key to use in the hash algorithm
00077  * @param[in] keyLength Length of the key
00078  * @param[in] data The input data for which to compute the hash code
00079  * @param[in] dataLength Length of the input data
00080  * @param[out] digest The computed HMAC value
00081  * @return Error code
00082  **/
00083 
00084 error_t hmacCompute(const HashAlgo *hash, const void *key, size_t keyLength,
00085    const void *data, size_t dataLength, uint8_t *digest)
00086 {
00087    //Allocate a memory buffer to hold the HMAC context
00088    HmacContext *context = cryptoAllocMem(sizeof(HmacContext));
00089    //Failed to allocate memory?
00090    if(context == NULL)
00091       return ERROR_OUT_OF_MEMORY;
00092 
00093    //Initialize the HMAC context
00094    hmacInit(context, hash, key, keyLength);
00095    //Digest the message
00096    hmacUpdate(context, data, dataLength);
00097    //Finalize the HMAC computation
00098    hmacFinal(context, digest);
00099 
00100    //Free previously allocated memory
00101    cryptoFreeMem(context);
00102    //Successful processing
00103    return NO_ERROR;
00104 }
00105 
00106 
00107 /**
00108  * @brief Initialize HMAC calculation
00109  * @param[in] context Pointer to the HMAC context to initialize
00110  * @param[in] hash Hash algorithm used to compute HMAC
00111  * @param[in] key Key to use in the hash algorithm
00112  * @param[in] keyLength Length of the key
00113  **/
00114 
00115 void hmacInit(HmacContext *context, const HashAlgo *hash,
00116    const void *key, size_t keyLength)
00117 {
00118    uint_t i;
00119 
00120    //Hash algorithm used to compute HMAC
00121    context->hash = hash;
00122 
00123    //The key is longer than the block size?
00124    if(keyLength > hash->blockSize)
00125    {
00126       //Initialize the hash function context
00127       hash->init(context->hashContext);
00128       //Digest the original key
00129       hash->update(context->hashContext, key, keyLength);
00130       //Finalize the message digest computation
00131       hash->final(context->hashContext, context->key);
00132       //Key is padded to the right with extra zeros
00133       memset(context->key + hash->digestSize, 0, hash->blockSize - hash->digestSize);
00134    }
00135    else
00136    {
00137       //Copy the key
00138       memcpy(context->key, key, keyLength);
00139       //Key is padded to the right with extra zeros
00140       memset(context->key + keyLength, 0, hash->blockSize - keyLength);
00141    }
00142 
00143    //XOR the resulting key with ipad
00144    for(i = 0; i < hash->blockSize; i++)
00145       context->key[i] ^= HMAC_IPAD;
00146 
00147    //Initialize context for the first pass
00148    hash->init(context->hashContext);
00149    //Start with the inner pad
00150    hash->update(context->hashContext, context->key, hash->blockSize);
00151 }
00152 
00153 
00154 /**
00155  * @brief Update the HMAC context with a portion of the message being hashed
00156  * @param[in] context Pointer to the HMAC context
00157  * @param[in] data Pointer to the buffer being hashed
00158  * @param[in] length Length of the buffer
00159  **/
00160 
00161 void hmacUpdate(HmacContext *context, const void *data, size_t length)
00162 {
00163    //Hash algorithm used to compute HMAC
00164    const HashAlgo *hash = context->hash;
00165    //Digest the message (first pass)
00166    hash->update(context->hashContext, data, length);
00167 }
00168 
00169 
00170 /**
00171  * @brief Finish the HMAC calculation
00172  * @param[in] context Pointer to the HMAC context
00173  * @param[out] digest Calculated HMAC value (optional parameter)
00174  **/
00175 
00176 void hmacFinal(HmacContext *context, uint8_t *digest)
00177 {
00178    uint_t i;
00179 
00180    //Hash algorithm used to compute HMAC
00181    const HashAlgo *hash = context->hash;
00182    //Finish the first pass
00183    hash->final(context->hashContext, context->digest);
00184 
00185    //XOR the original key with opad
00186    for(i = 0; i < hash->blockSize; i++)
00187       context->key[i] ^= HMAC_IPAD ^ HMAC_OPAD;
00188 
00189    //Initialize context for the second pass
00190    hash->init(context->hashContext);
00191    //Start with outer pad
00192    hash->update(context->hashContext, context->key, hash->blockSize);
00193    //Then digest the result of the first hash
00194    hash->update(context->hashContext, context->digest, hash->digestSize);
00195    //Finish the second pass
00196    hash->final(context->hashContext, context->digest);
00197 
00198    //Copy the resulting HMAC value
00199    if(digest != NULL)
00200       memcpy(digest, context->digest, hash->digestSize);
00201 }
00202 
00203 #endif
00204