/*! * @file apm32f4xx_hash_md5.c * * @brief This file provides high level functions to compute the HASH MD5 and * HMAC MD5 Digest of an input message. * * @version V1.0.2 * * @date 2022-06-23 * * @attention * * Copyright (C) 2021-2022 Geehy Semiconductor * * You may not use this file except in compliance with the * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope * that it will be usefull and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ #include "apm32f4xx_hash.h" /** @addtogroup APM32F4xx_StdPeriphDriver @{ */ /** @defgroup HASH_MD5_Driver * @brief HASH MD5 driver modules @{ */ /** @defgroup HASH_MD5_Functions @{ */ /** @defgroup HASH_MD5_Macros Macros @{ */ /* HASH MD5 timeout definition */ #define MD5_BUSY_TIMEOUT ((uint32_t) 0x00010000) /**@} end of group HASH_MD5_Macros*/ /*! * @brief Compute the HASH MD5 digest * * @param inBuffer: pointer to the input buffer to be treated * * @param lenBuffer: length of the input buffer. * * @param outBuffer: the returned digest. * * @retval An ErrorStatus enumeration value: * SUCCESS: digest computation done * ERROR: digest computation failed * */ uint8_t HASH_ComputeMD5(uint8_t *inBuffer, uint32_t lenBuffer, uint8_t outBuffer[16]) { HASH_Config_T hashMD5Config; HASH_MessageDigest_T hashMD5MessageDigest; uint16_t nuValidBits = 0; uint32_t m = 0; uint32_t inBufferaddr = (uint32_t)inBuffer; uint32_t outBufferaddr = (uint32_t)outBuffer; nuValidBits = 8 * (lenBuffer % 4); HASH_Reset(); /* HASH Configuration */ hashMD5Config.algoSelect = HASH_ALGO_SELECTION_MD5; hashMD5Config.algoMode = HASH_ALGO_MODE_HASH; hashMD5Config.dataType = HASH_DATA_TYPE_8B; HASH_Config(&hashMD5Config); /* Configure the number of valid bits in last word of the data */ HASH_ConfigLastWordValidBitsNbr(nuValidBits); /* Write the input block in the IN FIFO */ for (m = 0; m < lenBuffer; m += 4) { HASH_WritesInputData(*(uint32_t *)inBufferaddr); inBufferaddr += 4; } /* Start the HASH processor */ HASH_StartDigest(); /* wait until the Busy flag is RESET */ if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0) { return ERROR; } else { /* Read the message digest */ HASH_ReadDigest(&hashMD5MessageDigest); *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[0]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[1]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[2]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hashMD5MessageDigest.Data[3]); } return SUCCESS; } /*! * @brief Compute the HMAC MD5 digest * * @param key: pointer to the Key used for HMAC * * @param lenkey: length of the Key used for HMAC * * @param inBuffer: pointer to the Input buffer to be treated * * @param lenBuffer: length of the Input buffer * * @param outBuffer: the returned digest * * @retval An ErrorStatus enumeration value: * SUCCESS: digest computation done * ERROR: digest computation failed * */ uint8_t HMAC_ComputeMD5(uint8_t *key, uint32_t keylen, uint8_t *inBuffer, uint32_t lenBuffer, uint8_t outBuffer[16]) { HASH_Config_T hmacMD5Config; HASH_MessageDigest_T hmacMD5MessageDigest; uint16_t nuValidBits = 0; uint16_t nuValidKey = 0; uint32_t m = 0; uint32_t keyaddr = (uint32_t)key; uint32_t inBufferaddr = (uint32_t)inBuffer; uint32_t outBufferaddr = (uint32_t)outBuffer; nuValidBits = 8 * (lenBuffer % 4); nuValidKey = 8 * (keylen % 4); HASH_Reset(); /* HASH Configuration */ hmacMD5Config.algoSelect = HASH_ALGO_SELECTION_MD5; hmacMD5Config.algoMode = HASH_ALGO_MODE_HMAC; hmacMD5Config.dataType = HASH_DATA_TYPE_8B; if (keylen > 64) { hmacMD5Config.hmacKeyType = HASH_HMAC_KEY_TYPE_LONGKEY; } else { hmacMD5Config.hmacKeyType = HASH_HMAC_KEY_TYPE_SHORTKEY; } HASH_Config(&hmacMD5Config); HASH_ConfigLastWordValidBitsNbr(nuValidKey); for (m = 0; m < keylen; m += 4) { HASH_WritesInputData(*(uint32_t *)keyaddr); keyaddr += 4; } /* Start the HASH processor */ HASH_StartDigest(); /* wait until the Busy flag is RESET */ if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0) { return ERROR; } else { /* Configure the number of valid bits in last word of the input data */ HASH_ConfigLastWordValidBitsNbr(nuValidBits); /* Write the input block in the IN FIFO */ for (m = 0; m < lenBuffer; m += 4) { HASH_WritesInputData(*(uint32_t *)inBufferaddr); inBufferaddr += 4; } /* Start the HASH processor */ HASH_StartDigest(); /* wait until the Busy flag is RESET */ if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0) { return ERROR; } else { HASH_ConfigLastWordValidBitsNbr(nuValidKey); keyaddr = (uint32_t)key; for (m = 0; m < keylen; m += 4) { HASH_WritesInputData(*(uint32_t *)keyaddr); keyaddr += 4; } /* Start the HASH processor */ HASH_StartDigest(); /* wait until the Busy flag is RESET */ if (HASH_WaitForCompute(MD5_BUSY_TIMEOUT) != 0) { return ERROR; } else { /* Read the message digest */ HASH_ReadDigest(&hmacMD5MessageDigest); *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[0]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[1]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[2]); outBufferaddr += 4; *(uint32_t *)(outBufferaddr) = __REV(hmacMD5MessageDigest.Data[3]); } } } return SUCCESS; } /**@} end of group HASH_MD5_Functions */ /**@} end of group HASH_MD5_Driver */ /**@} end of group APM32F4xx_StdPeriphDriver */