/** * * \file m2m_crypto.c * * \brief WINC Crypto module. * * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * * Subject to your compliance with these terms, you may use Microchip * software and any derivatives exclusively with Microchip products. * It is your responsibility to comply with third party license terms applicable * to your use of third party software (including open source software) that * may accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* INCLUDES *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ #include "driver/include/m2m_crypto.h" #include "driver/source/nmbus.h" #include "driver/source/nmasic.h" #ifdef CONF_CRYPTO /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* MACROS *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ /*======*======*======*======*======*=======* * WINC SHA256 HW Engine Register Definition * *======*======*======*======*======*========*/ #define SHA_BLOCK_SIZE (64) #define SHARED_MEM_BASE (0xd0000) #define SHA256_MEM_BASE (0x180000UL) #define SHA256_ENGINE_ADDR (0x180000ul) /* SHA256 Registers */ #define SHA256_CTRL (SHA256_MEM_BASE+0x00) #define SHA256_CTRL_START_CALC_MASK (NBIT0) #define SHA256_CTRL_START_CALC_SHIFT (0) #define SHA256_CTRL_PREPROCESS_MASK (NBIT1) #define SHA256_CTRL_PREPROCESS_SHIFT (1) #define SHA256_CTRL_HASH_HASH_MASK (NBIT2) #define SHA256_CTRL_HASH_HASH_SHIFT (2) #define SHA256_CTRL_INIT_SHA256_STATE_MASK (NBIT3) #define SHA256_CTRL_INIT_SHA256_STATE_SHIFT (3) #define SHA256_CTRL_WR_BACK_HASH_VALUE_MASK (NBIT4) #define SHA256_CTRL_WR_BACK_HASH_VALUE_SHIFT (4) #define SHA256_CTRL_FORCE_SHA256_QUIT_MASK (NBIT5) #define SHA256_CTRL_FORCE_SHA256_QUIT_SHIFT (5) #define SHA256_REGS_SHA256_CTRL_AHB_BYTE_REV_EN (NBIT6) #define SHA256_REGS_SHA256_CTRL_RESERVED (NBIT7) #define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO (NBIT8+ NBIT9+ NBIT10) #define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO_MASK (NBIT2+ NBIT1+ NBIT0) #define SHA256_REGS_SHA256_CTRL_CORE_TO_AHB_CLK_RATIO_SHIFT (8) #define SHA256_REGS_SHA256_CTRL_RESERVED_11 (NBIT11) #define SHA256_REGS_SHA256_CTRL_SHA1_CALC (NBIT12) #define SHA256_REGS_SHA256_CTRL_PBKDF2_SHA1_CALC (NBIT13) #define SHA256_START_RD_ADDR (SHA256_MEM_BASE+0x04UL) #define SHA256_DATA_LENGTH (SHA256_MEM_BASE+0x08UL) #define SHA256_START_WR_ADDR (SHA256_MEM_BASE+0x0cUL) #define SHA256_COND_CHK_CTRL (SHA256_MEM_BASE+0x10) #define SHA256_COND_CHK_CTRL_HASH_VAL_COND_CHK_MASK (NBIT1 | NBIT0) #define SHA256_COND_CHK_CTRL_HASH_VAL_COND_CHK_SHIFT (0) #define SHA256_COND_CHK_CTRL_STEP_VAL_MASK (NBIT6 | NBIT5 | NBIT4 | NBIT3 | NBIT2) #define SHA256_COND_CHK_CTRL_STEP_VAL_SHIFT (2) #define SHA256_COND_CHK_CTRL_COND_CHK_RESULT_MASK (NBIT7) #define SHA256_COND_CHK_CTRL_COND_CHK_RESULT_SHIFT (7) #define SHA256_MOD_DATA_RANGE (SHA256_MEM_BASE+0x14) #define SHA256_MOD_DATA_RANGE_ST_BYTE_2_ADD_STP_MASK (NBIT24-1) #define SHA256_MOD_DATA_RANGE_ST_BYTE_2_ADD_STP_SHIFT (0) #define SHA256_MOD_DATA_RANGE_MOD_DATA_LEN_MASK (NBIT24 | NBIT25| NBIT26) #define SHA256_MOD_DATA_RANGE_MOD_DATA_LEN_SHIFT (24) #define SHA256_COND_CHK_STS_1 (SHA256_MEM_BASE+0x18) #define SHA256_COND_CHK_STS_2 (SHA256_MEM_BASE+0x1c) #define SHA256_DONE_INTR_ENABLE (SHA256_MEM_BASE+0x20) #define SHA256_DONE_INTR_STS (SHA256_MEM_BASE+0x24) #define SHA256_TARGET_HASH_H1 (SHA256_MEM_BASE+0x28) #define SHA256_TARGET_HASH_H2 (SHA256_MEM_BASE+0x2c) #define SHA256_TARGET_HASH_H3 (SHA256_MEM_BASE+0x30) #define SHA256_TARGET_HASH_H4 (SHA256_MEM_BASE+0x34) #define SHA256_TARGET_HASH_H5 (SHA256_MEM_BASE+0x38) #define SHA256_TARGET_HASH_H6 (SHA256_MEM_BASE+0x3c) #define SHA256_TARGET_HASH_H7 (SHA256_MEM_BASE+0x40) #define SHA256_TARGET_HASH_H8 (SHA256_MEM_BASE+0x44) /*======*======*======*======*======*=======* * WINC BIGINT HW Engine Register Definition * *======*======*======*======*======*========*/ #define BIGINT_ENGINE_ADDR (0x180080ul) #define BIGINT_VERSION (BIGINT_ENGINE_ADDR + 0x00) #define BIGINT_MISC_CTRL (BIGINT_ENGINE_ADDR + 0x04) #define BIGINT_MISC_CTRL_CTL_START (NBIT0) #define BIGINT_MISC_CTRL_CTL_RESET (NBIT1) #define BIGINT_MISC_CTRL_CTL_MSW_FIRST (NBIT2) #define BIGINT_MISC_CTRL_CTL_SWAP_BYTE_ORDER (NBIT3) #define BIGINT_MISC_CTRL_CTL_FORCE_BARRETT (NBIT4) #define BIGINT_MISC_CTRL_CTL_M_PRIME_VALID (NBIT5) #define BIGINT_M_PRIME (BIGINT_ENGINE_ADDR + 0x08) #define BIGINT_STATUS (BIGINT_ENGINE_ADDR + 0x0C) #define BIGINT_STATUS_STS_DONE (NBIT0) #define BIGINT_CLK_COUNT (BIGINT_ENGINE_ADDR + 0x10) #define BIGINT_ADDR_X (BIGINT_ENGINE_ADDR + 0x14) #define BIGINT_ADDR_E (BIGINT_ENGINE_ADDR + 0x18) #define BIGINT_ADDR_M (BIGINT_ENGINE_ADDR + 0x1C) #define BIGINT_ADDR_R (BIGINT_ENGINE_ADDR + 0x20) #define BIGINT_LENGTH (BIGINT_ENGINE_ADDR + 0x24) #define BIGINT_IRQ_STS (BIGINT_ENGINE_ADDR + 0x28) #define BIGINT_IRQ_STS_DONE (NBIT0) #define BIGINT_IRQ_STS_CHOOSE_MONT (NBIT1) #define BIGINT_IRQ_STS_M_READ (NBIT2) #define BIGINT_IRQ_STS_X_READ (NBIT3) #define BIGINT_IRQ_STS_START (NBIT4) #define BIGINT_IRQ_STS_PRECOMP_FINISH (NBIT5) #define BIGINT_IRQ_MASK (BIGINT_ENGINE_ADDR + 0x2C) #define BIGINT_IRQ_MASK_CTL_IRQ_MASK_START (NBIT4) #define ENABLE_FLIPPING 1 #define GET_UINT32(BUF,OFFSET) (((uint32)((BUF)[OFFSET])) | ((uint32)(((BUF)[OFFSET + 1]) << 8)) | \ ((uint32)(((BUF)[OFFSET + 2]) << 16)) | ((uint32)(((BUF)[OFFSET + 3]) << 24))) #define PUTU32(VAL32,BUF,OFFSET) \ do \ { \ (BUF)[OFFSET ] = BYTE_3((VAL32)); \ (BUF)[OFFSET +1 ] = BYTE_2((VAL32)); \ (BUF)[OFFSET +2 ] = BYTE_1((VAL32)); \ (BUF)[OFFSET +3 ] = BYTE_0((VAL32)); \ }while(0) /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* DATA TYPES *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ /*! @struct \ tstrHashContext @brief */ typedef struct{ uint32 au32HashState[M2M_SHA256_DIGEST_LEN/4]; uint8 au8CurrentBlock[64]; uint32 u32TotalLength; uint8 u8InitHashFlag; }tstrSHA256HashCtxt; /*======*======*======*======*======*=======* * SHA256 IMPLEMENTATION * *======*======*======*======*======*========*/ sint8 m2m_sha256_hash_init(tstrM2mSha256Ctxt *pstrSha256Ctxt) { tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; if(pstrSHA256 != NULL) { m2m_memset((uint8*)pstrSha256Ctxt, 0, sizeof(tstrM2mSha256Ctxt)); pstrSHA256->u8InitHashFlag = 1; } return 0; } sint8 m2m_sha256_hash_update(tstrM2mSha256Ctxt *pstrSha256Ctxt, uint8 *pu8Data, uint16 u16DataLength) { sint8 s8Ret = M2M_ERR_FAIL; tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; if(pstrSHA256 != NULL) { uint32 u32ReadAddr; uint32 u32WriteAddr = SHARED_MEM_BASE; uint32 u32Addr = u32WriteAddr; uint32 u32ResidualBytes; uint32 u32NBlocks; uint32 u32Offset; uint32 u32CurrentBlock = 0; uint8 u8IsDone = 0; /* Get the remaining bytes from the previous update (if the length is not block aligned). */ u32ResidualBytes = pstrSHA256->u32TotalLength % SHA_BLOCK_SIZE; /* Update the total data length. */ pstrSHA256->u32TotalLength += u16DataLength; if(u32ResidualBytes != 0) { if((u32ResidualBytes + u16DataLength) >= SHA_BLOCK_SIZE) { u32Offset = SHA_BLOCK_SIZE - u32ResidualBytes; m2m_memcpy(&pstrSHA256->au8CurrentBlock[u32ResidualBytes], pu8Data, u32Offset); pu8Data += u32Offset; u16DataLength -= u32Offset; nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); u32Addr += SHA_BLOCK_SIZE; u32CurrentBlock = 1; } else { m2m_memcpy(&pstrSHA256->au8CurrentBlock[u32ResidualBytes], pu8Data, u16DataLength); u16DataLength = 0; } } /* Get the number of HASH BLOCKs and the residual bytes. */ u32NBlocks = u16DataLength / SHA_BLOCK_SIZE; u32ResidualBytes = u16DataLength % SHA_BLOCK_SIZE; if(u32NBlocks != 0) { nm_write_block(u32Addr, pu8Data, (uint16)(u32NBlocks * SHA_BLOCK_SIZE)); pu8Data += (u32NBlocks * SHA_BLOCK_SIZE); } u32NBlocks += u32CurrentBlock; if(u32NBlocks != 0) { uint32 u32RegVal = 0; nm_write_reg(SHA256_CTRL, u32RegVal); u32RegVal |= SHA256_CTRL_FORCE_SHA256_QUIT_MASK; nm_write_reg(SHA256_CTRL, u32RegVal); if(pstrSHA256->u8InitHashFlag) { pstrSHA256->u8InitHashFlag = 0; u32RegVal |= SHA256_CTRL_INIT_SHA256_STATE_MASK; } u32ReadAddr = u32WriteAddr + (u32NBlocks * SHA_BLOCK_SIZE); nm_write_reg(SHA256_DATA_LENGTH, (u32NBlocks * SHA_BLOCK_SIZE)); nm_write_reg(SHA256_START_RD_ADDR, u32WriteAddr); nm_write_reg(SHA256_START_WR_ADDR, u32ReadAddr); u32RegVal |= SHA256_CTRL_START_CALC_MASK; u32RegVal &= ~(0x7 << 8); u32RegVal |= (2 << 8); nm_write_reg(SHA256_CTRL, u32RegVal); /* 5. Wait for done_intr */ while(!u8IsDone) { u32RegVal = nm_read_reg(SHA256_DONE_INTR_STS); u8IsDone = u32RegVal & NBIT0; } } if(u32ResidualBytes != 0) { m2m_memcpy(pstrSHA256->au8CurrentBlock, pu8Data, u32ResidualBytes); } s8Ret = M2M_SUCCESS; } return s8Ret; } sint8 m2m_sha256_hash_finish(tstrM2mSha256Ctxt *pstrSha256Ctxt, uint8 *pu8Sha256Digest) { sint8 s8Ret = M2M_ERR_FAIL; tstrSHA256HashCtxt *pstrSHA256 = (tstrSHA256HashCtxt*)pstrSha256Ctxt; if(pstrSHA256 != NULL) { uint32 u32ReadAddr; uint32 u32WriteAddr = SHARED_MEM_BASE; uint32 u32Addr = u32WriteAddr; uint16 u16Offset; uint16 u16PaddingLength; uint16 u16NBlocks = 1; uint32 u32RegVal = 0; uint32 u32Idx,u32ByteIdx; uint32 au32Digest[M2M_SHA256_DIGEST_LEN / 4]; uint8 u8IsDone = 0; nm_write_reg(SHA256_CTRL,u32RegVal); u32RegVal |= SHA256_CTRL_FORCE_SHA256_QUIT_MASK; nm_write_reg(SHA256_CTRL,u32RegVal); if(pstrSHA256->u8InitHashFlag) { pstrSHA256->u8InitHashFlag = 0; u32RegVal |= SHA256_CTRL_INIT_SHA256_STATE_MASK; } /* Calculate the offset of the last data byte in the current block. */ u16Offset = (uint16)(pstrSHA256->u32TotalLength % SHA_BLOCK_SIZE); /* Add the padding byte 0x80. */ pstrSHA256->au8CurrentBlock[u16Offset ++] = 0x80; /* Calculate the required padding to complete one Hash Block Size. */ u16PaddingLength = SHA_BLOCK_SIZE - u16Offset; m2m_memset(&pstrSHA256->au8CurrentBlock[u16Offset], 0, u16PaddingLength); /* If the padding count is not enough to hold 64-bit representation of the total input message length, one padding block is required. */ if(u16PaddingLength < 8) { nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); u32Addr += SHA_BLOCK_SIZE; m2m_memset(pstrSHA256->au8CurrentBlock, 0, SHA_BLOCK_SIZE); u16NBlocks ++; } /* pack the length at the end of the padding block */ PUTU32(pstrSHA256->u32TotalLength << 3, pstrSHA256->au8CurrentBlock, (SHA_BLOCK_SIZE - 4)); u32ReadAddr = u32WriteAddr + (u16NBlocks * SHA_BLOCK_SIZE); nm_write_block(u32Addr, pstrSHA256->au8CurrentBlock, SHA_BLOCK_SIZE); nm_write_reg(SHA256_DATA_LENGTH, (u16NBlocks * SHA_BLOCK_SIZE)); nm_write_reg(SHA256_START_RD_ADDR, u32WriteAddr); nm_write_reg(SHA256_START_WR_ADDR, u32ReadAddr); u32RegVal |= SHA256_CTRL_START_CALC_MASK; u32RegVal |= SHA256_CTRL_WR_BACK_HASH_VALUE_MASK; u32RegVal &= ~(0x7UL << 8); u32RegVal |= (0x2UL << 8); nm_write_reg(SHA256_CTRL,u32RegVal); /* 5. Wait for done_intr */ while(!u8IsDone) { u32RegVal = nm_read_reg(SHA256_DONE_INTR_STS); u8IsDone = u32RegVal & NBIT0; } nm_read_block(u32ReadAddr, (uint8*)au32Digest, 32); /* Convert the output words to an array of bytes. */ u32ByteIdx = 0; for(u32Idx = 0; u32Idx < (M2M_SHA256_DIGEST_LEN / 4); u32Idx ++) { pu8Sha256Digest[u32ByteIdx ++] = BYTE_3(au32Digest[u32Idx]); pu8Sha256Digest[u32ByteIdx ++] = BYTE_2(au32Digest[u32Idx]); pu8Sha256Digest[u32ByteIdx ++] = BYTE_1(au32Digest[u32Idx]); pu8Sha256Digest[u32ByteIdx ++] = BYTE_0(au32Digest[u32Idx]); } s8Ret = M2M_SUCCESS; } return s8Ret; } /*======*======*======*======*======*=======* * RSA IMPLEMENTATION * *======*======*======*======*======*========*/ static void FlipBuffer(uint8 *pu8InBuffer, uint8 *pu8OutBuffer, uint16 u16BufferSize) { uint16 u16Idx; for(u16Idx = 0; u16Idx < u16BufferSize; u16Idx ++) { #if ENABLE_FLIPPING == 1 pu8OutBuffer[u16Idx] = pu8InBuffer[u16BufferSize - u16Idx - 1]; #else pu8OutBuffer[u16Idx] = pu8InBuffer[u16Idx]; #endif } } void BigInt_ModExp ( uint8 *pu8X, uint16 u16XSize, uint8 *pu8E, uint16 u16ESize, uint8 *pu8M, uint16 u16MSize, uint8 *pu8R, uint16 u16RSize ) { uint32 u32Reg; uint8 au8Tmp[780] = {0}; uint32 u32XAddr = SHARED_MEM_BASE; uint32 u32MAddr; uint32 u32EAddr; uint32 u32RAddr; uint8 u8EMswBits = 32; uint32 u32Mprime = 0x7F; uint16 u16XSizeWords,u16ESizeWords; uint32 u32Exponent; u16XSizeWords = (u16XSize + 3) / 4; u16ESizeWords = (u16ESize + 3) / 4; u32MAddr = u32XAddr + (u16XSizeWords * 4); u32EAddr = u32MAddr + (u16XSizeWords * 4); u32RAddr = u32EAddr + (u16ESizeWords * 4); /* Reset the core. */ u32Reg = 0; u32Reg |= BIGINT_MISC_CTRL_CTL_RESET; u32Reg = nm_read_reg(BIGINT_MISC_CTRL); u32Reg &= ~BIGINT_MISC_CTRL_CTL_RESET; u32Reg = nm_read_reg(BIGINT_MISC_CTRL); nm_write_block(u32RAddr,au8Tmp, u16RSize); /* Write Input Operands to Chip Memory. */ /*------- X -------*/ FlipBuffer(pu8X,au8Tmp,u16XSize); nm_write_block(u32XAddr,au8Tmp,u16XSizeWords * 4); /*------- E -------*/ m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); FlipBuffer(pu8E, au8Tmp, u16ESize); nm_write_block(u32EAddr, au8Tmp, u16ESizeWords * 4); u32Exponent = GET_UINT32(au8Tmp, (u16ESizeWords * 4) - 4); while((u32Exponent & NBIT31)== 0) { u32Exponent <<= 1; u8EMswBits --; } /*------- M -------*/ m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); FlipBuffer(pu8M, au8Tmp, u16XSize); nm_write_block(u32MAddr, au8Tmp, u16XSizeWords * 4); /* Program the addresses of the input operands. */ nm_write_reg(BIGINT_ADDR_X, u32XAddr); nm_write_reg(BIGINT_ADDR_E, u32EAddr); nm_write_reg(BIGINT_ADDR_M, u32MAddr); nm_write_reg(BIGINT_ADDR_R, u32RAddr); /* Mprime. */ nm_write_reg(BIGINT_M_PRIME,u32Mprime); /* Length. */ u32Reg = (u16XSizeWords & 0xFF); u32Reg += ((u16ESizeWords & 0xFF) << 8); u32Reg += (u8EMswBits << 16); nm_write_reg(BIGINT_LENGTH,u32Reg); /* CTRL Register. */ u32Reg = nm_read_reg(BIGINT_MISC_CTRL); u32Reg ^= BIGINT_MISC_CTRL_CTL_START; u32Reg |= BIGINT_MISC_CTRL_CTL_FORCE_BARRETT; //u32Reg |= BIGINT_MISC_CTRL_CTL_M_PRIME_VALID; #if ENABLE_FLIPPING == 0 u32Reg |= BIGINT_MISC_CTRL_CTL_MSW_FIRST; #endif nm_write_reg(BIGINT_MISC_CTRL,u32Reg); /* Wait for computation to complete. */ while(1) { u32Reg = nm_read_reg(BIGINT_IRQ_STS); if(u32Reg & BIGINT_IRQ_STS_DONE) { break; } } nm_write_reg(BIGINT_IRQ_STS,0); m2m_memset(au8Tmp, 0, sizeof(au8Tmp)); nm_read_block(u32RAddr, au8Tmp, u16RSize); FlipBuffer(au8Tmp, pu8R, u16RSize); } #define MD5_DIGEST_SIZE (16) #define SHA1_DIGEST_SIZE (20) static const uint8 au8TEncodingMD5[] = { 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04 }; /*!< Fixed part of the Encoding T for the MD5 hash algorithm. */ static const uint8 au8TEncodingSHA1[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04 }; /*!< Fixed part of the Encoding T for the SHA-1 hash algorithm. */ static const uint8 au8TEncodingSHA2[] = { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04 }; /*!< Fixed part of the Encoding T for the SHA-2 hash algorithm. */ sint8 m2m_rsa_sign_verify(uint8 *pu8N, uint16 u16NSize, uint8 *pu8E, uint16 u16ESize, uint8 *pu8SignedMsgHash, uint16 u16HashLength, uint8 *pu8RsaSignature) { sint8 s8Ret = M2M_RSA_SIGN_FAIL; if((pu8N != NULL) && (pu8E != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL)) { uint16 u16TLength, u16TEncodingLength; uint8 *pu8T; uint8 au8EM[512]; /* Selection of correct T Encoding based on the hash size. */ if(u16HashLength == MD5_DIGEST_SIZE) { pu8T = (uint8*)au8TEncodingMD5; u16TEncodingLength = sizeof(au8TEncodingMD5); } else if(u16HashLength == SHA1_DIGEST_SIZE) { pu8T = (uint8*)au8TEncodingSHA1; u16TEncodingLength = sizeof(au8TEncodingSHA1); } else { pu8T = (uint8*)au8TEncodingSHA2; u16TEncodingLength = sizeof(au8TEncodingSHA2); } u16TLength = u16TEncodingLength + 1 + u16HashLength; /* If emLen < tLen + 11. */ if(u16NSize >= (u16TLength + 11)) { uint32 u32PSLength,u32Idx = 0; /* RSA verification */ BigInt_ModExp(pu8RsaSignature, u16NSize, pu8E, u16ESize, pu8N, u16NSize, au8EM, u16NSize); u32PSLength = u16NSize - u16TLength - 3; /* The calculated EM must match the following pattern. *======*======*======*======*======* * 0x00 || 0x01 || PS || 0x00 || T * *======*======*======*======*======* Where PS is all 0xFF T is defined based on the hash algorithm. */ if((au8EM[0] == 0x00) && (au8EM[1] == 0x01)) { for(u32Idx = 2; au8EM[u32Idx] == 0xFF; u32Idx ++); if(u32Idx == (u32PSLength + 2)) { if(au8EM[u32Idx ++] == 0x00) { if(!m2m_memcmp(&au8EM[u32Idx], pu8T, u16TEncodingLength)) { u32Idx += u16TEncodingLength; if(au8EM[u32Idx ++] == u16HashLength) s8Ret = m2m_memcmp(&au8EM[u32Idx], pu8SignedMsgHash, u16HashLength); } } } } } } return s8Ret; } sint8 m2m_rsa_sign_gen(uint8 *pu8N, uint16 u16NSize, uint8 *pu8d, uint16 u16dSize, uint8 *pu8SignedMsgHash, uint16 u16HashLength, uint8 *pu8RsaSignature) { sint8 s8Ret = M2M_RSA_SIGN_FAIL; if((pu8N != NULL) && (pu8d != NULL) && (pu8RsaSignature != NULL) && (pu8SignedMsgHash != NULL)) { uint16 u16TLength, u16TEncodingLength; uint8 *pu8T; uint8 au8EM[512]; /* Selection of correct T Encoding based on the hash size. */ if(u16HashLength == MD5_DIGEST_SIZE) { pu8T = (uint8*)au8TEncodingMD5; u16TEncodingLength = sizeof(au8TEncodingMD5); } else if(u16HashLength == SHA1_DIGEST_SIZE) { pu8T = (uint8*)au8TEncodingSHA1; u16TEncodingLength = sizeof(au8TEncodingSHA1); } else { pu8T = (uint8*)au8TEncodingSHA2; u16TEncodingLength = sizeof(au8TEncodingSHA2); } u16TLength = u16TEncodingLength + 1 + u16HashLength; /* If emLen < tLen + 11. */ if(u16NSize >= (u16TLength + 11)) { uint16 u16PSLength = 0; uint16 u16Offset = 0; /* The calculated EM must match the following pattern. *======*======*======*======*======* * 0x00 || 0x01 || PS || 0x00 || T * *======*======*======*======*======* Where PS is all 0xFF T is defined based on the hash algorithm. */ au8EM[u16Offset ++] = 0; au8EM[u16Offset ++] = 1; u16PSLength = u16NSize - u16TLength - 3; m2m_memset(&au8EM[u16Offset], 0xFF, u16PSLength); u16Offset += u16PSLength; au8EM[u16Offset ++] = 0; m2m_memcpy(&au8EM[u16Offset], pu8T, u16TEncodingLength); u16Offset += u16TEncodingLength; au8EM[u16Offset ++] = u16HashLength; m2m_memcpy(&au8EM[u16Offset], pu8SignedMsgHash, u16HashLength); /* RSA Signature Generation */ BigInt_ModExp(au8EM, u16NSize, pu8d, u16dSize, pu8N, u16NSize, pu8RsaSignature, u16NSize); s8Ret = M2M_RSA_SIGN_OK; } } return s8Ret; } #endif /* CONF_CRYPTO */