Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
hmac.c
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
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2