mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Fix WINC's FW update.
* Remove unused WINC code. * Replace WINC fw update process with a single fw image.
This commit is contained in:
parent
f841828818
commit
37c8587333
@ -799,7 +799,7 @@ static mp_obj_t winc_fw_dump(mp_obj_t self_in)
|
|||||||
static mp_obj_t winc_fw_update(mp_obj_t self_in)
|
static mp_obj_t winc_fw_update(mp_obj_t self_in)
|
||||||
{
|
{
|
||||||
// Erase the WINC1500 flash.
|
// Erase the WINC1500 flash.
|
||||||
printf("Erasing WINC's flash...\n");
|
printf("Erasing flash...\n");
|
||||||
if (programmer_erase_all() != M2M_SUCCESS) {
|
if (programmer_erase_all() != M2M_SUCCESS) {
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to erase entire flash!"));
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to erase entire flash!"));
|
||||||
}
|
}
|
||||||
@ -811,23 +811,11 @@ static mp_obj_t winc_fw_update(mp_obj_t self_in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the firmware on the WINC1500 flash.
|
// Verify the firmware on the WINC1500 flash.
|
||||||
printf("Verifying firmware image from flash...\n");
|
printf("Verifying firmware image...\n");
|
||||||
if (verify_firmware() != M2M_SUCCESS) {
|
if (verify_firmware() != M2M_SUCCESS) {
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to verify firmware section!"));
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to verify firmware section!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Program the certificates on the WINC1500 flash.
|
|
||||||
printf("Programming certificates...\n");
|
|
||||||
if (burn_certificates() != M2M_SUCCESS) {
|
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error while writing certificates!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the certificates on the WINC1500 flash.
|
|
||||||
printf("Reading certificates from flash...\n");
|
|
||||||
if (verify_certificates() != M2M_SUCCESS) {
|
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to dump certificate section!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("All task completed successfully.\n");
|
printf("All task completed successfully.\n");
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,4 @@
|
|||||||
int burn_firmware(void);
|
int burn_firmware(void);
|
||||||
int verify_firmware(void);
|
int verify_firmware(void);
|
||||||
int dump_firmware(void);
|
int dump_firmware(void);
|
||||||
int burn_certificates(void);
|
|
||||||
int verify_certificates(void);
|
|
||||||
#endif /* IMAGE_DOWNLOADER_H_INCLUDED */
|
#endif /* IMAGE_DOWNLOADER_H_INCLUDED */
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief Root Certificate Setup.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ROOT_CERT_SETUP_H_INCLUDED
|
|
||||||
#define ROOT_CERT_SETUP_H_INCLUDED
|
|
||||||
|
|
||||||
#include "programmer/programmer.h"
|
|
||||||
|
|
||||||
int WriteRootCertificate(const char *filename, char *pcRootCertFileData, uint32 u32FileSize);
|
|
||||||
|
|
||||||
#endif /* ROOT_CERT_SETUP_H_INCLUDED */
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief ASN1.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ASN1_H_INCLUDED
|
|
||||||
#define ASN1_H_INCLUDED
|
|
||||||
|
|
||||||
#include "common/include/nm_common.h"
|
|
||||||
|
|
||||||
/* ASN.1 TAG DEFINITIONS. */
|
|
||||||
#define ASN1_INVALID 0x00
|
|
||||||
#define ASN1_BOOLEAN 0x01
|
|
||||||
#define ASN1_INTEGER 0x02
|
|
||||||
#define ASN1_BIT_STRING 0x03
|
|
||||||
#define ASN1_OCTET_STRING 0x04
|
|
||||||
#define ASN1_NULL 0x05
|
|
||||||
#define ASN1_OBJECT_IDENTIFIER 0x06
|
|
||||||
#define ASN1_UTF8_DTRING 0x0C
|
|
||||||
#define ASN1_PRINTABLE_STRING 0x13
|
|
||||||
#define ASN1_TELETEX_STRING 0x14
|
|
||||||
#define ASN1_UTC_TIME 0x17
|
|
||||||
#define ASN1_GENERALIZED_TIME 0x18
|
|
||||||
#define ASN1_SEQUENCE 0x30
|
|
||||||
#define ASN1_SET 0x31
|
|
||||||
|
|
||||||
#define ASN1_SUCCESS 0
|
|
||||||
|
|
||||||
#define ASN1_FAIL -1
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 *pu8Buff;
|
|
||||||
uint8 *pu8Data;
|
|
||||||
uint16 u16BuffLen;
|
|
||||||
} tstrAsn1Context;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32 u32Length;
|
|
||||||
uint8 u8Tag;
|
|
||||||
} tstrAsn1Element;
|
|
||||||
|
|
||||||
uint16 ASN1_GetNextElement(tstrAsn1Context *pstrAsn1Ctxt, tstrAsn1Element *pstrElement);
|
|
||||||
|
|
||||||
uint16 ASN1_Read(tstrAsn1Context *pstrAsn1Cxt, uint32 u32ReadLength, uint8 *pu8ReadBuffer);
|
|
||||||
|
|
||||||
uint16 ASN1_ReadReference(tstrAsn1Context *pstrAsn1Cxt, uint32 u32ReadLength, uint8 **ppu8ReadBuffer);
|
|
||||||
|
|
||||||
#endif /* ASN1_H_INCLUDED */
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief Common Functions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef COMMON_H_INCLUDED
|
|
||||||
#define COMMON_H_INCLUDED
|
|
||||||
|
|
||||||
#include "common/include/nm_common.h"
|
|
||||||
#include <string.h>
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <Windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16 u16BufferSize;
|
|
||||||
uint8 *pu8Data;
|
|
||||||
} tstrBuffer;
|
|
||||||
|
|
||||||
/* Used for time storage. */
|
|
||||||
typedef struct {
|
|
||||||
uint16 u16Year;
|
|
||||||
uint8 u8Month;
|
|
||||||
uint8 u8Day;
|
|
||||||
uint8 u8Hour;
|
|
||||||
uint8 u8Minute;
|
|
||||||
uint8 u8Second;
|
|
||||||
} tstrSystemTime;
|
|
||||||
|
|
||||||
#define SIZE_128_BITS (16)
|
|
||||||
#define SIZE_256_BITS (32)
|
|
||||||
#define SIZE_512_BITS (64)
|
|
||||||
#define SIZE_1024_BITS (128)
|
|
||||||
#define SIZE_1536_BITS (192)
|
|
||||||
#define SIZE_2048_BITS (256)
|
|
||||||
|
|
||||||
#define GETU16(BUF, OFFSET) ((((uint16)((BUF)[OFFSET]) << 8)) | (((uint16)(BUF)[OFFSET + 1])))
|
|
||||||
|
|
||||||
/*!< Retrieve 2 bytes from the given buffer at the given
|
|
||||||
* offset as 16-bit unsigned integer in the Network byte order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GETU32(BUF,OFFSET) ((((uint32)((BUF)[OFFSET]) << 24)) | (((uint32)((BUF)[OFFSET + 1]) << 16)) | \
|
|
||||||
(((uint32)((BUF)[OFFSET + 2]) << 8)) | ((uint32)((BUF)[OFFSET + 3])))
|
|
||||||
/*!< Retrieve 4 bytes from the given buffer at the given
|
|
||||||
offset as 32-bit unsigned integer in the Network byte order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
#define PUTU16(VAL16, BUF, OFFSET) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
(BUF)[OFFSET ] = BYTE_1((VAL16)); \
|
|
||||||
(BUF)[OFFSET + 1 ] = BYTE_0((VAL16)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif /* COMMON_H_INCLUDED */
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief Hash Functions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HASH_H_INCLUDED
|
|
||||||
#define HASH_H_INCLUDED
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define SHA_BLOCK_SIZE 64
|
|
||||||
|
|
||||||
#define MD5_DIGEST_SIZE (16)
|
|
||||||
#define SHA1_DIGEST_SIZE (20)
|
|
||||||
#define SHA256_DIGEST_SIZE 32
|
|
||||||
|
|
||||||
#define SHA_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
|
|
||||||
|
|
||||||
#define SHA_FLAGS_INIT 0x01
|
|
||||||
|
|
||||||
/*!< A flag to tell the hash function to
|
|
||||||
* start hash from the initial state.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SHA_FLAGS_UPDATE 0x02
|
|
||||||
|
|
||||||
/*!< Update the current hash with the
|
|
||||||
* given data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SHA_FLAGS_FINISH 0x04
|
|
||||||
|
|
||||||
/*!< Finalize the hashing and calculate
|
|
||||||
* the final result.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SHA_FLAGS_FULL_HASH (SHA_FLAGS_INIT | SHA_FLAGS_UPDATE | SHA_FLAGS_FINISH)
|
|
||||||
|
|
||||||
#define SHA1_INIT(ctxt) SHA1_Hash((ctxt), SHA_FLAGS_INIT, NULL, 0, NULL)
|
|
||||||
#define SHA1_UPDATE(ctxt, data, dataLen) SHA1_Hash((ctxt), SHA_FLAGS_UPDATE, (data), (dataLen), NULL)
|
|
||||||
#define SHA1_FINISH(ctxt, digest) SHA1_Hash((ctxt), SHA_FLAGS_FINISH, NULL, 0, digest)
|
|
||||||
|
|
||||||
#define MD5_INIT(ctxt) MD5_Hash((ctxt), SHA_FLAGS_INIT, NULL, 0, NULL)
|
|
||||||
#define MD5_UPDATE(ctxt, data, dataLen) MD5_Hash((ctxt), SHA_FLAGS_UPDATE, (data), (dataLen), NULL)
|
|
||||||
#define MD5_FINISH(ctxt, digest) MD5_Hash((ctxt), SHA_FLAGS_FINISH, NULL, 0, digest)
|
|
||||||
|
|
||||||
typedef void (*tpfHashProcessBlock)(uint32 *pu32HashState, const uint8 *pu8MessageBlock);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32 au32HashState[SHA_MAX_DIGEST_SIZE / 4];
|
|
||||||
uint8 au8CurrentBlock[SHA_BLOCK_SIZE];
|
|
||||||
uint32 u32TotalLength;
|
|
||||||
tpfHashProcessBlock fpHash;
|
|
||||||
uint8 u8BlockSize;
|
|
||||||
uint8 u8DigestSize;
|
|
||||||
} tstrHashContext;
|
|
||||||
|
|
||||||
typedef tstrHashContext tstrMd5Context;
|
|
||||||
typedef tstrHashContext tstrSha1Context;
|
|
||||||
typedef tstrHashContext tstrSha256Context;
|
|
||||||
|
|
||||||
typedef void (*tpfHash)
|
|
||||||
(
|
|
||||||
tstrHashContext *pstrHashContext,
|
|
||||||
uint8 u8Flags,
|
|
||||||
uint8 *pu8Data,
|
|
||||||
uint32 u32DataLength,
|
|
||||||
uint8 *pu8Digest
|
|
||||||
);
|
|
||||||
|
|
||||||
void MD5_Hash(tstrHashContext *pstrMD5Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest);
|
|
||||||
void HMAC_Vector(tpfHash fpHash, uint8 *pu8Key, uint32 u32KeyLength, tstrBuffer *pstrInData, uint8 u8NumInputs, uint8 *pu8Out);
|
|
||||||
void SHA1_Hash(tstrHashContext *pstrSha1Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest);
|
|
||||||
void SHA256_Hash(tstrHashContext *pstrSha256Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest);
|
|
||||||
|
|
||||||
#endif /* HASH_H_INCLUDED */
|
|
||||||
@ -1,177 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief X509 Certificate Functions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef X509_CERT_H_INCLUDED
|
|
||||||
#define X509_CERT_H_INCLUDED
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
#define X509_SUCCESS 0
|
|
||||||
#define X509_FAIL -1
|
|
||||||
|
|
||||||
#define X509_SERIAL_NO_MAX_LENGTH 20
|
|
||||||
|
|
||||||
/* X509 ALGORITHMS. */
|
|
||||||
#define X509_ALG_NULL 0
|
|
||||||
#define X509_PUB_RSA 1
|
|
||||||
#define X509_SIGN_MD5RSA 2
|
|
||||||
#define X509_SIGN_SHA1RSA 3
|
|
||||||
#define X509_SIGN_SHA256RSA 4
|
|
||||||
#define X509_SIGN_SHA384RSA 5
|
|
||||||
#define X509_SIGN_SHA512RSA 6
|
|
||||||
|
|
||||||
#define X509_STATUS_VALID 0
|
|
||||||
/*!<
|
|
||||||
* The X.509 certificate is valid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_STATUS_EXPIRED 1
|
|
||||||
/*!<
|
|
||||||
* The X.509 certificate is expired.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_STATUS_REVOKED 2
|
|
||||||
/*!<
|
|
||||||
* The X.509 certificate is marked as revoked and should not
|
|
||||||
* be trusted.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_STATUS_DECODE_ERR 4
|
|
||||||
/*!<
|
|
||||||
* Error decoding the certificate time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_CERT_DUMP X509Cert_Dump
|
|
||||||
#define X509_CERT_IS_VALID X509Cert_IsValid
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PUBKEY_ALG_RSA,
|
|
||||||
PUBKEY_ALG_DH,
|
|
||||||
PUBKEY_ALG_ECDH
|
|
||||||
} tenuPubKeyAlg;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SIGN_VERIFY,
|
|
||||||
SIGN_GEN
|
|
||||||
} tenuSignMode;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* @struct tstrDHPublicKey
|
|
||||||
*
|
|
||||||
* @brief Diffie-Hellman Public Key Definition
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
uint8 *pu8P;
|
|
||||||
uint8 *pu8G;
|
|
||||||
uint8 *pu8Key;
|
|
||||||
uint16 u16PSize;
|
|
||||||
uint16 u16GSize;
|
|
||||||
uint16 u16KeySize;
|
|
||||||
} tstrDHPublicKey;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* @struct tstrRSAPublicKey
|
|
||||||
*
|
|
||||||
* @brief RSA Public Key Definition
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
uint16 u16NSize;
|
|
||||||
uint16 u16ESize;
|
|
||||||
uint8 *pu8N;
|
|
||||||
uint8 *pu8E;
|
|
||||||
} tstrRSAPublicKey;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
tenuPubKeyAlg enuType;
|
|
||||||
union {
|
|
||||||
tstrRSAPublicKey strRSAKey;
|
|
||||||
tstrDHPublicKey strDHKey;
|
|
||||||
};
|
|
||||||
} tstrPublicKey;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char acCmnName[65];
|
|
||||||
char acOrg[65];
|
|
||||||
char acOrgUnit[65];
|
|
||||||
uint8 au8NameSHA1[SHA1_DIGEST_SIZE];
|
|
||||||
} tstrX520Name;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 au8Time[20];
|
|
||||||
} tstrX509Time;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 u8Version;
|
|
||||||
/*!<
|
|
||||||
* X509 version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 u8SerialNumberLength;
|
|
||||||
/*!<
|
|
||||||
* X509 certificate serial number Length in bytes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 au8SerialNo[X509_SERIAL_NO_MAX_LENGTH];
|
|
||||||
/*!<
|
|
||||||
* X509 certificate serial number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 u8SignAlg;
|
|
||||||
/*!<
|
|
||||||
* X509 certificate serial number Length in bytes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8 u8ValidityStatus;
|
|
||||||
tstrX520Name strIssuer;
|
|
||||||
tstrX509Time strStartDate;
|
|
||||||
tstrX509Time strExpiryDate;
|
|
||||||
tstrX520Name strSubject;
|
|
||||||
tstrPublicKey strPubKey;
|
|
||||||
tstrBuffer strSignature;
|
|
||||||
uint8 *pu8TBSCert;
|
|
||||||
uint16 u16TBSCertSize;
|
|
||||||
} tstrX509Cert;
|
|
||||||
|
|
||||||
sint8 X509Cert_Decode(uint8 *pu8X509Buffer, uint32 u32CertSize, tstrX509Cert *pstrCert, uint8 bDumpX509);
|
|
||||||
void X509Cert_Dump(void *pvCert);
|
|
||||||
|
|
||||||
#endif /* X509_CERT_H_INCLUDED */
|
|
||||||
@ -1,120 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief ASN1.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "root_cert/x509/asn1.h"
|
|
||||||
|
|
||||||
uint16 ASN1_GetNextElement(tstrAsn1Context *pstrAsn1Ctxt, tstrAsn1Element *pstrElement)
|
|
||||||
{
|
|
||||||
uint16 u16ElemLength = 0;
|
|
||||||
|
|
||||||
if ((pstrElement != NULL) && (pstrAsn1Ctxt != NULL)) {
|
|
||||||
uint8 u8NLenBytes;
|
|
||||||
|
|
||||||
do {
|
|
||||||
u8NLenBytes = 0;
|
|
||||||
|
|
||||||
/* Get the ASN.1 Element Tag. */
|
|
||||||
pstrElement->u8Tag = *pstrAsn1Ctxt->pu8Data++;
|
|
||||||
|
|
||||||
/* Get the ASN.1 element length. */
|
|
||||||
pstrElement->u32Length = *pstrAsn1Ctxt->pu8Data++;
|
|
||||||
pstrElement->u32Length &= 0xFF;
|
|
||||||
if (pstrElement->u32Length & NBIT7) {
|
|
||||||
uint8 u8Idx;
|
|
||||||
uint8 au8Tmp[4];
|
|
||||||
|
|
||||||
/* Multiple Length octets. */
|
|
||||||
u8NLenBytes = (uint8)(pstrElement->u32Length & 0x03);
|
|
||||||
pstrElement->u32Length = 0;
|
|
||||||
|
|
||||||
m2m_memcpy(au8Tmp, pstrAsn1Ctxt->pu8Data, u8NLenBytes);
|
|
||||||
pstrAsn1Ctxt->pu8Data += u8NLenBytes;
|
|
||||||
|
|
||||||
for (u8Idx = 0; u8Idx < u8NLenBytes; u8Idx++) {
|
|
||||||
pstrElement->u32Length +=
|
|
||||||
(uint32)(au8Tmp[u8Idx] << ((u8NLenBytes - u8Idx - 1) * 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u16ElemLength += u8NLenBytes + 2 + (uint16)pstrElement->u32Length;
|
|
||||||
} while (pstrElement->u8Tag == ASN1_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return u16ElemLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 ASN1_Read(tstrAsn1Context *pstrAsn1Cxt, uint32 u32ReadLength, uint8 *pu8ReadBuffer)
|
|
||||||
{
|
|
||||||
uint16 u16Read = 0;
|
|
||||||
|
|
||||||
if (pstrAsn1Cxt != NULL) {
|
|
||||||
uint16 u16RemLen = pstrAsn1Cxt->u16BuffLen - (uint16)(pstrAsn1Cxt->pu8Data - pstrAsn1Cxt->pu8Buff);
|
|
||||||
|
|
||||||
u16Read = (uint16)((u32ReadLength <= u16RemLen) ? u32ReadLength : u16RemLen);
|
|
||||||
|
|
||||||
if (pu8ReadBuffer != NULL) {
|
|
||||||
m2m_memcpy(pu8ReadBuffer, pstrAsn1Cxt->pu8Data, u16Read);
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrAsn1Cxt->pu8Data += u16Read;
|
|
||||||
}
|
|
||||||
|
|
||||||
return u16Read;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 ASN1_ReadReference(tstrAsn1Context *pstrAsn1Cxt, uint32 u32ReadLength, uint8 **ppu8ReadBuffer)
|
|
||||||
{
|
|
||||||
uint16 u16Read = 0;
|
|
||||||
|
|
||||||
if (pstrAsn1Cxt != NULL) {
|
|
||||||
uint16 u16RemLen = pstrAsn1Cxt->u16BuffLen - (uint16)(pstrAsn1Cxt->pu8Data - pstrAsn1Cxt->pu8Buff);
|
|
||||||
|
|
||||||
u16Read = (uint16)((u32ReadLength <= u16RemLen) ? u32ReadLength : u16RemLen);
|
|
||||||
|
|
||||||
if (ppu8ReadBuffer != NULL) {
|
|
||||||
*ppu8ReadBuffer = pstrAsn1Cxt->pu8Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrAsn1Cxt->pu8Data += u16Read;
|
|
||||||
}
|
|
||||||
|
|
||||||
return u16Read;
|
|
||||||
}
|
|
||||||
@ -1,527 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief Hash Functions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "root_cert/x509/hash.h"
|
|
||||||
|
|
||||||
#define SHA_SHR(x, n) ((x & 0xFFFFFFFF) >> n)
|
|
||||||
#define SHA_SHL(x, n) ((x & 0xFFFFFFFF) << n)
|
|
||||||
#define SHA_ROTR(x, n) (SHA_SHR(x, n) | SHA_SHL(x, (32 - n)))
|
|
||||||
#define SHA_ROTL(x, n) (SHA_SHL(x, n) | SHA_SHR(x, (32 - n)))
|
|
||||||
|
|
||||||
/* MD5 specific defines. */
|
|
||||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
|
||||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
|
||||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
|
||||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
|
||||||
|
|
||||||
#define MD5_INERMEDIATE(A, B, C, D, W, K, S) \
|
|
||||||
{ \
|
|
||||||
W += A + K; \
|
|
||||||
W = B + SHA_ROTL(W, S); \
|
|
||||||
A = D; \
|
|
||||||
D = C; \
|
|
||||||
C = B; \
|
|
||||||
B = W; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA1 specific defines. */
|
|
||||||
#define SHA1_CH(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
|
|
||||||
#define SHA1_MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
|
|
||||||
#define SHA_PARITY(x, y, z) ((x) ^ (y) ^ (z))
|
|
||||||
#define SHA1_INERMEDIATE(A, B, C, D, E, W, K) \
|
|
||||||
{ \
|
|
||||||
W += SHA_ROTL(A, 5) + E + K; \
|
|
||||||
E = D; \
|
|
||||||
D = C; \
|
|
||||||
C = SHA_ROTL(B, 30); \
|
|
||||||
B = A; \
|
|
||||||
A = W; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SHA_PAD_BYTE 0x80
|
|
||||||
|
|
||||||
/* SHA256 specific defines. */
|
|
||||||
#define SHA256_SMALL_SIGMA0(x) (SHA_ROTR(x, 7) ^ SHA_ROTR(x, 18) ^ SHA_SHR(x, 3))
|
|
||||||
#define SHA256_SMALL_SIGMA1(x) (SHA_ROTR(x, 17) ^ SHA_ROTR(x, 19) ^ SHA_SHR(x, 10))
|
|
||||||
#define SHA256_CAP_SIGMA0(x) (SHA_ROTR(x, 2) ^ SHA_ROTR(x, 13) ^ SHA_ROTR(x, 22))
|
|
||||||
#define SHA256_CAP_SIGMA1(x) (SHA_ROTR(x, 6) ^ SHA_ROTR(x, 11) ^ SHA_ROTR(x, 25))
|
|
||||||
#define SHA256_MAJ(x, y, z) ((x & y) | (z & (x | y)))
|
|
||||||
#define SHA256_CH(x, y, z) (z ^ (x & (y ^ z)))
|
|
||||||
|
|
||||||
static void MD5ProcessBlock(uint32 *pu32Md5State, const uint8 *pu8MessageBlock)
|
|
||||||
{
|
|
||||||
const uint32 T[] = {
|
|
||||||
0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
|
|
||||||
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
|
|
||||||
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
|
|
||||||
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
|
|
||||||
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
|
|
||||||
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
|
|
||||||
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
|
|
||||||
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
|
|
||||||
};
|
|
||||||
uint8 S[] = {
|
|
||||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
|
||||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
|
||||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
|
||||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
|
|
||||||
};
|
|
||||||
uint32 A, B, C, D;
|
|
||||||
uint32 W = 0;
|
|
||||||
uint32 X[16];
|
|
||||||
uint8 u8Idx, u8Count;
|
|
||||||
|
|
||||||
A = pu32Md5State[0];
|
|
||||||
B = pu32Md5State[1];
|
|
||||||
C = pu32Md5State[2];
|
|
||||||
D = pu32Md5State[3];
|
|
||||||
|
|
||||||
memcpy(X, pu8MessageBlock, 64);
|
|
||||||
|
|
||||||
for (u8Idx = 0; u8Idx < 16; u8Idx++) {
|
|
||||||
W = F(B, C, D) + X[u8Idx];
|
|
||||||
MD5_INERMEDIATE(A, B, C, D, W, T[u8Idx], S[u8Idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u8Idx = 16, u8Count = 1; u8Idx < 32; u8Idx++, u8Count += 5) {
|
|
||||||
W = G(B, C, D) + X[u8Count & 0x0F];
|
|
||||||
MD5_INERMEDIATE(A, B, C, D, W, T[u8Idx], S[u8Idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u8Idx = 32, u8Count = 5; u8Idx < 48; u8Idx++, u8Count += 3) {
|
|
||||||
W = H(B, C, D) + X[u8Count & 0x0F];
|
|
||||||
MD5_INERMEDIATE(A, B, C, D, W, T[u8Idx], S[u8Idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u8Idx = 48, u8Count = 0; u8Idx < 64; u8Idx++, u8Count += 7) {
|
|
||||||
W = I(B, C, D) + X[u8Count & 0x0F];
|
|
||||||
MD5_INERMEDIATE(A, B, C, D, W, T[u8Idx], S[u8Idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pu32Md5State[0] += A;
|
|
||||||
pu32Md5State[1] += B;
|
|
||||||
pu32Md5State[2] += C;
|
|
||||||
pu32Md5State[3] += D;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SHA1ProcessBlock(uint32 *pu32Sha1State, const uint8 *pu8MessageBlock)
|
|
||||||
{
|
|
||||||
/* Constants defined in FIPS-180-2, section 4.2.1 */
|
|
||||||
const uint32 K[4] = {
|
|
||||||
0x5A827999,
|
|
||||||
0x6ED9EBA1,
|
|
||||||
0x8F1BBCDC,
|
|
||||||
0xCA62C1D6
|
|
||||||
};
|
|
||||||
int t; /* Loop counter */
|
|
||||||
uint32 W[80]; /* Word sequence */
|
|
||||||
uint32 A, B, C, D, E; /* Word buffers */
|
|
||||||
|
|
||||||
/* Initialize the first 16 words in the array W. */
|
|
||||||
for (t = 0; t < 16; t++) {
|
|
||||||
W[t] = GETU32(pu8MessageBlock, (t * 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 16; t < 80; t++) {
|
|
||||||
W[t] = SHA_ROTL((W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
A = pu32Sha1State[0];
|
|
||||||
B = pu32Sha1State[1];
|
|
||||||
C = pu32Sha1State[2];
|
|
||||||
D = pu32Sha1State[3];
|
|
||||||
E = pu32Sha1State[4];
|
|
||||||
|
|
||||||
for (t = 0; t < 20; t++) {
|
|
||||||
W[t] += SHA1_CH(B, C, D);
|
|
||||||
SHA1_INERMEDIATE(A, B, C, D, E, W[t], K[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 20; t < 40; t++) {
|
|
||||||
W[t] += SHA_PARITY(B, C, D);
|
|
||||||
SHA1_INERMEDIATE(A, B, C, D, E, W[t], K[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 40; t < 60; t++) {
|
|
||||||
W[t] += SHA1_MAJ(B, C, D);
|
|
||||||
SHA1_INERMEDIATE(A, B, C, D, E, W[t], K[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 60; t < 80; t++) {
|
|
||||||
W[t] += SHA_PARITY(B, C, D);
|
|
||||||
SHA1_INERMEDIATE(A, B, C, D, E, W[t], K[3])
|
|
||||||
}
|
|
||||||
|
|
||||||
pu32Sha1State[0] += A;
|
|
||||||
pu32Sha1State[1] += B;
|
|
||||||
pu32Sha1State[2] += C;
|
|
||||||
pu32Sha1State[3] += D;
|
|
||||||
pu32Sha1State[4] += E;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SHA256ProcessBlock(uint32 *pu32Sha256State, const uint8 *pu8Data)
|
|
||||||
{
|
|
||||||
/* Hardcoded when using for loop unrolling. */
|
|
||||||
/* Constants defined in SHA-256. */
|
|
||||||
const uint32 K[] = {
|
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
||||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
||||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
||||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32 t; /* Loop counter */
|
|
||||||
uint32 temp1, temp2; /* Temporary word value */
|
|
||||||
uint32 W[64]; /* Word sequence */
|
|
||||||
uint32 A, B, C, D, E, F, G, H; /* Word buffers */
|
|
||||||
|
|
||||||
A = pu32Sha256State[0];
|
|
||||||
B = pu32Sha256State[1];
|
|
||||||
C = pu32Sha256State[2];
|
|
||||||
D = pu32Sha256State[3];
|
|
||||||
E = pu32Sha256State[4];
|
|
||||||
F = pu32Sha256State[5];
|
|
||||||
G = pu32Sha256State[6];
|
|
||||||
H = pu32Sha256State[7];
|
|
||||||
|
|
||||||
/* Initialize the first 16 words in the array W */
|
|
||||||
for (t = 16; (t--) != 0;) {
|
|
||||||
W[t] = pu8Data[t * 4] << 24;
|
|
||||||
W[t] |= pu8Data[t * 4 + 1] << 16;
|
|
||||||
W[t] |= pu8Data[t * 4 + 2] << 8;
|
|
||||||
W[t] |= pu8Data[t * 4 + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 16; t < 64; t++) {
|
|
||||||
W[t] = SHA256_SMALL_SIGMA1(W[t - 2]) + W[t - 7] +
|
|
||||||
SHA256_SMALL_SIGMA0(W[t - 15]) + W[t - 16];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 0; t < 64; t++) {
|
|
||||||
temp1 = H + SHA256_CAP_SIGMA1(E) + SHA256_CH(E, F, G) + K[t] + W[t];
|
|
||||||
temp2 = SHA256_CAP_SIGMA0(A) + SHA256_MAJ(A, B, C);
|
|
||||||
|
|
||||||
H = G;
|
|
||||||
G = F;
|
|
||||||
F = E;
|
|
||||||
E = D + temp1;
|
|
||||||
D = C;
|
|
||||||
C = B;
|
|
||||||
B = A;
|
|
||||||
A = temp1 + temp2;
|
|
||||||
}
|
|
||||||
|
|
||||||
pu32Sha256State[0] += A;
|
|
||||||
pu32Sha256State[1] += B;
|
|
||||||
pu32Sha256State[2] += C;
|
|
||||||
pu32Sha256State[3] += D;
|
|
||||||
pu32Sha256State[4] += E;
|
|
||||||
pu32Sha256State[5] += F;
|
|
||||||
pu32Sha256State[6] += G;
|
|
||||||
pu32Sha256State[7] += H;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Sha_HashUpdate(tstrHashContext *pstrHashCxt, uint8 *pu8Data, uint32 u32DataLength)
|
|
||||||
{
|
|
||||||
if ((pstrHashCxt != NULL) && (pu8Data != NULL) && (u32DataLength != 0)) {
|
|
||||||
if (pstrHashCxt->fpHash != NULL) {
|
|
||||||
uint32 u32ResidualBytes;
|
|
||||||
uint32 u32NBlocks;
|
|
||||||
uint32 u32Offset;
|
|
||||||
uint32 u32BlockCount;
|
|
||||||
|
|
||||||
/* Get the remaining bytes from the previous update (if the length is not block alligned). */
|
|
||||||
u32ResidualBytes = pstrHashCxt->u32TotalLength % pstrHashCxt->u8BlockSize;
|
|
||||||
|
|
||||||
/* Update the total data length. */
|
|
||||||
pstrHashCxt->u32TotalLength += u32DataLength;
|
|
||||||
|
|
||||||
if (u32ResidualBytes != 0) {
|
|
||||||
if ((u32ResidualBytes + u32DataLength) >= pstrHashCxt->u8BlockSize) {
|
|
||||||
u32Offset = pstrHashCxt->u8BlockSize - u32ResidualBytes;
|
|
||||||
memcpy(&pstrHashCxt->au8CurrentBlock[u32ResidualBytes], pu8Data, u32Offset);
|
|
||||||
pu8Data += u32Offset;
|
|
||||||
u32DataLength -= u32Offset;
|
|
||||||
pstrHashCxt->fpHash(pstrHashCxt->au32HashState, pstrHashCxt->au8CurrentBlock);
|
|
||||||
} else {
|
|
||||||
memcpy(&pstrHashCxt->au8CurrentBlock[u32ResidualBytes], pu8Data, u32DataLength);
|
|
||||||
u32DataLength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the number of HASH BLOCKs and the residual bytes. */
|
|
||||||
u32NBlocks = u32DataLength / pstrHashCxt->u8BlockSize;
|
|
||||||
u32ResidualBytes = u32DataLength % pstrHashCxt->u8BlockSize;
|
|
||||||
for (u32BlockCount = 0; u32BlockCount < u32NBlocks; u32BlockCount++) {
|
|
||||||
pstrHashCxt->fpHash(pstrHashCxt->au32HashState, pu8Data);
|
|
||||||
pu8Data += pstrHashCxt->u8BlockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u32ResidualBytes != 0) {
|
|
||||||
memcpy(pstrHashCxt->au8CurrentBlock, pu8Data, u32ResidualBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Sha_HashFinish(tstrHashContext *pstrHashCxt, uint8 *pu8LengthPadding)
|
|
||||||
{
|
|
||||||
if (pstrHashCxt != NULL) {
|
|
||||||
if (pstrHashCxt->fpHash != NULL) {
|
|
||||||
uint32 u32Offset;
|
|
||||||
uint32 u32PaddingLength;
|
|
||||||
|
|
||||||
/* Calculate the offset of the last data byte in the current block. */
|
|
||||||
u32Offset = pstrHashCxt->u32TotalLength % pstrHashCxt->u8BlockSize;
|
|
||||||
|
|
||||||
/* Add the padding byte 0x80. */
|
|
||||||
pstrHashCxt->au8CurrentBlock[u32Offset++] = SHA_PAD_BYTE;
|
|
||||||
|
|
||||||
/* Calculate the required padding to complete one Hash Block Size. */
|
|
||||||
u32PaddingLength = pstrHashCxt->u8BlockSize - u32Offset;
|
|
||||||
memset(&pstrHashCxt->au8CurrentBlock[u32Offset], 0, u32PaddingLength);
|
|
||||||
|
|
||||||
/* If the padding count is not enough to hold 64-bit representation */
|
|
||||||
/* of the total input message length, one padding block is required. */
|
|
||||||
if (u32PaddingLength < 8) {
|
|
||||||
pstrHashCxt->fpHash(pstrHashCxt->au32HashState, pstrHashCxt->au8CurrentBlock);
|
|
||||||
memset(pstrHashCxt->au8CurrentBlock, 0, pstrHashCxt->u8BlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&pstrHashCxt->au8CurrentBlock[pstrHashCxt->u8BlockSize - 8], pu8LengthPadding, 8);
|
|
||||||
pstrHashCxt->fpHash(pstrHashCxt->au32HashState, pstrHashCxt->au8CurrentBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA1_Hash(tstrHashContext *pstrSha1Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest) {
|
|
||||||
if (pstrSha1Context != NULL) {
|
|
||||||
/* SHA1 HASH INITIALIZATION. */
|
|
||||||
if (u8Flags & SHA_FLAGS_INIT) {
|
|
||||||
/* Initialize the Hash Context. */
|
|
||||||
memset(pstrSha1Context, 0, sizeof(tstrHashContext));
|
|
||||||
|
|
||||||
/* Define SHA1 Specific parameters. */
|
|
||||||
pstrSha1Context->fpHash = SHA1ProcessBlock;
|
|
||||||
pstrSha1Context->u8BlockSize = SHA_BLOCK_SIZE;
|
|
||||||
pstrSha1Context->u8DigestSize = SHA1_DIGEST_SIZE;
|
|
||||||
|
|
||||||
/* Set the Hash state to the initial value (specified by the standard). */
|
|
||||||
pstrSha1Context->au32HashState[0] = 0x67452301;
|
|
||||||
pstrSha1Context->au32HashState[1] = 0xEFCDAB89;
|
|
||||||
pstrSha1Context->au32HashState[2] = 0x98BADCFE;
|
|
||||||
pstrSha1Context->au32HashState[3] = 0x10325476;
|
|
||||||
pstrSha1Context->au32HashState[4] = 0xC3D2E1F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA1 HASH UPDATE. */
|
|
||||||
if ((u8Flags & SHA_FLAGS_UPDATE) && (pu8Data != NULL)) {
|
|
||||||
Sha_HashUpdate(pstrSha1Context, pu8Data, u32DataLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA1 HASH FINISH. */
|
|
||||||
if (u8Flags & SHA_FLAGS_FINISH) {
|
|
||||||
uint8 au8Tmp[8];
|
|
||||||
|
|
||||||
/* Pack the length at the end of the padding block. */
|
|
||||||
PUTU32(pstrSha1Context->u32TotalLength >> 29, au8Tmp, 0);
|
|
||||||
PUTU32(pstrSha1Context->u32TotalLength << 3, au8Tmp, 4);
|
|
||||||
Sha_HashFinish(pstrSha1Context, au8Tmp);
|
|
||||||
|
|
||||||
/* Compute digest. */
|
|
||||||
PUTU32(pstrSha1Context->au32HashState[0], pu8Digest, 0);
|
|
||||||
PUTU32(pstrSha1Context->au32HashState[1], pu8Digest, 4);
|
|
||||||
PUTU32(pstrSha1Context->au32HashState[2], pu8Digest, 8);
|
|
||||||
PUTU32(pstrSha1Context->au32HashState[3], pu8Digest, 12);
|
|
||||||
PUTU32(pstrSha1Context->au32HashState[4], pu8Digest, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHA256_Hash(tstrHashContext *pstrSha256Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest)
|
|
||||||
{
|
|
||||||
if (pstrSha256Context != NULL) {
|
|
||||||
/* SHA256 HASH INITIALIZATION. */
|
|
||||||
if (u8Flags & SHA_FLAGS_INIT) {
|
|
||||||
/* Initialize the Hash Context. */
|
|
||||||
memset(pstrSha256Context, 0, sizeof(tstrHashContext));
|
|
||||||
|
|
||||||
/* Define SHA256 specific parameters. */
|
|
||||||
pstrSha256Context->fpHash = SHA256ProcessBlock;
|
|
||||||
pstrSha256Context->u8BlockSize = SHA_BLOCK_SIZE;
|
|
||||||
pstrSha256Context->u8DigestSize = SHA256_DIGEST_SIZE;
|
|
||||||
|
|
||||||
/* Set the Hash state to the initial value (specified by the standard). */
|
|
||||||
pstrSha256Context->au32HashState[0] = 0x6A09E667;
|
|
||||||
pstrSha256Context->au32HashState[1] = 0xBB67AE85;
|
|
||||||
pstrSha256Context->au32HashState[2] = 0x3C6EF372;
|
|
||||||
pstrSha256Context->au32HashState[3] = 0xA54FF53A;
|
|
||||||
pstrSha256Context->au32HashState[4] = 0x510E527F;
|
|
||||||
pstrSha256Context->au32HashState[5] = 0x9B05688C;
|
|
||||||
pstrSha256Context->au32HashState[6] = 0x1F83D9AB;
|
|
||||||
pstrSha256Context->au32HashState[7] = 0x5BE0CD19;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA256 HASH UPDATE. */
|
|
||||||
if ((u8Flags & SHA_FLAGS_UPDATE) && (pu8Data != NULL)) {
|
|
||||||
Sha_HashUpdate(pstrSha256Context, pu8Data, u32DataLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA256 HASH FINISH. */
|
|
||||||
if ((u8Flags & SHA_FLAGS_FINISH) && (pu8Digest != NULL)) {
|
|
||||||
uint8 au8Tmp[8];
|
|
||||||
|
|
||||||
/* Pack the length at the end of the padding block. */
|
|
||||||
PUTU32(pstrSha256Context->u32TotalLength >> 29, au8Tmp, 0);
|
|
||||||
PUTU32(pstrSha256Context->u32TotalLength << 3, au8Tmp, 4);
|
|
||||||
Sha_HashFinish(pstrSha256Context, au8Tmp);
|
|
||||||
|
|
||||||
/* Compute digest. */
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[0], pu8Digest, 0);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[1], pu8Digest, 4);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[2], pu8Digest, 8);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[3], pu8Digest, 12);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[4], pu8Digest, 16);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[5], pu8Digest, 20);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[6], pu8Digest, 24);
|
|
||||||
PUTU32(pstrSha256Context->au32HashState[7], pu8Digest, 28);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MD5_Hash( tstrHashContext *pstrMD5Context, uint8 u8Flags, uint8 *pu8Data, uint32 u32DataLength, uint8 *pu8Digest)
|
|
||||||
{
|
|
||||||
if (pstrMD5Context != NULL) {
|
|
||||||
/* SHA256 HASH INITIALIZATION. */
|
|
||||||
if (u8Flags & 1) {
|
|
||||||
/* Initialize the Hash Context. */
|
|
||||||
memset(pstrMD5Context, 0, sizeof(tstrHashContext));
|
|
||||||
|
|
||||||
/* Define SHA256 specific parameters. */
|
|
||||||
pstrMD5Context->fpHash = MD5ProcessBlock;
|
|
||||||
pstrMD5Context->u8BlockSize = 64;
|
|
||||||
pstrMD5Context->u8DigestSize = 16;
|
|
||||||
|
|
||||||
pstrMD5Context->au32HashState[0] = 0x67452301;
|
|
||||||
pstrMD5Context->au32HashState[1] = 0xEFCDAB89;
|
|
||||||
pstrMD5Context->au32HashState[2] = 0x98BADCFE;
|
|
||||||
pstrMD5Context->au32HashState[3] = 0x10325476;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA256 HASH UPDATE. */
|
|
||||||
if ((u8Flags & 2) && (pu8Data != NULL)) {
|
|
||||||
Sha_HashUpdate(pstrMD5Context, pu8Data, u32DataLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SHA256 HASH FINISH. */
|
|
||||||
if ((u8Flags & 4) && (pu8Digest != NULL)) {
|
|
||||||
uint8 au8Tmp[8] = {0};
|
|
||||||
uint8 u8Idx, u8ByteIdx = 0;
|
|
||||||
uint32 u32LengthBits = pstrMD5Context->u32TotalLength << 3;
|
|
||||||
|
|
||||||
/* Pack the length at the end of the padding block. */
|
|
||||||
au8Tmp[0] = BYTE_0(u32LengthBits);
|
|
||||||
au8Tmp[1] = BYTE_1(u32LengthBits);
|
|
||||||
au8Tmp[2] = BYTE_2(u32LengthBits);
|
|
||||||
au8Tmp[3] = BYTE_3(u32LengthBits);
|
|
||||||
|
|
||||||
Sha_HashFinish(pstrMD5Context, au8Tmp);
|
|
||||||
|
|
||||||
/* Compute digest. */
|
|
||||||
for (u8Idx = 0; u8Idx < (MD5_DIGEST_SIZE / 4); u8Idx++) {
|
|
||||||
pu8Digest[u8ByteIdx++] = BYTE_0(pstrMD5Context->au32HashState[u8Idx]);
|
|
||||||
pu8Digest[u8ByteIdx++] = BYTE_1(pstrMD5Context->au32HashState[u8Idx]);
|
|
||||||
pu8Digest[u8ByteIdx++] = BYTE_2(pstrMD5Context->au32HashState[u8Idx]);
|
|
||||||
pu8Digest[u8ByteIdx++] = BYTE_3(pstrMD5Context->au32HashState[u8Idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Perform the HMAC operation on a given vector of data streams.
|
|
||||||
*/
|
|
||||||
void HMAC_Vector(tpfHash fpHash, uint8 *pu8Key, uint32 u32KeyLength, tstrBuffer *pstrInData, uint8 u8NumInputs, uint8 *pu8Out)
|
|
||||||
{
|
|
||||||
if ((pu8Key != NULL) && (pstrInData != NULL) && (pu8Out != NULL) && (fpHash != NULL)) {
|
|
||||||
tstrHashContext strHashContext;
|
|
||||||
uint32 i;
|
|
||||||
uint8 au8TmpBuffer[SHA_BLOCK_SIZE];
|
|
||||||
uint8 au8TmpHash[SHA_MAX_DIGEST_SIZE];
|
|
||||||
uint8 au8TmpKey[SHA_MAX_DIGEST_SIZE];
|
|
||||||
|
|
||||||
/* HMAC INIT. */
|
|
||||||
/* Adjust the key size. */
|
|
||||||
if (u32KeyLength > SHA_BLOCK_SIZE) {
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_FULL_HASH, pu8Key, u32KeyLength, pu8Key);
|
|
||||||
u32KeyLength = strHashContext.u8DigestSize;
|
|
||||||
pu8Key = au8TmpKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(au8TmpBuffer, 0x36, SHA_BLOCK_SIZE);
|
|
||||||
for (i = 0; i < u32KeyLength; i++) {
|
|
||||||
au8TmpBuffer[i] ^= pu8Key[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start hashing. */
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_INIT | SHA_FLAGS_UPDATE, au8TmpBuffer, SHA_BLOCK_SIZE, NULL);
|
|
||||||
|
|
||||||
/* HMAC UPDATE. */
|
|
||||||
for (i = 0; i < u8NumInputs; i++) {
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_UPDATE, pstrInData[i].pu8Data, pstrInData[i].u16BufferSize, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_FINISH, NULL, 0, au8TmpHash);
|
|
||||||
|
|
||||||
/* HMAC Finalize. */
|
|
||||||
memset(au8TmpBuffer, 0x5C, SHA_BLOCK_SIZE);
|
|
||||||
for (i = 0; i < u32KeyLength; i++) {
|
|
||||||
au8TmpBuffer[i] ^= pu8Key[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_INIT | SHA_FLAGS_UPDATE, au8TmpBuffer, SHA_BLOCK_SIZE, NULL);
|
|
||||||
fpHash(&strHashContext, SHA_FLAGS_UPDATE | SHA_FLAGS_FINISH, au8TmpHash, strHashContext.u8DigestSize, pu8Out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,16 +3,11 @@
|
|||||||
#include "fb_alloc.h"
|
#include "fb_alloc.h"
|
||||||
|
|
||||||
#include "programmer/programmer.h"
|
#include "programmer/programmer.h"
|
||||||
#include "root_cert/root_setup.h"
|
|
||||||
#include "spi_flash/include/spi_flash_map.h"
|
#include "spi_flash/include/spi_flash_map.h"
|
||||||
|
|
||||||
#define FW_PATH "/firmware/bin/m2m_aio_3a0.bin"
|
// TODO pass file paths
|
||||||
#define FW_DUMP_PATH "/firmware/bin/fw_dump.bin"
|
#define FW_PATH "/firmware/m2m_aio_3a0.bin"
|
||||||
#define CERT_DIGI_PATH "/firmware/cert/DigiCert_Root.cer"
|
#define FW_DUMP_PATH "/firmware/fw_dump.bin"
|
||||||
#define CERT_DIGISHA2_PATH "/firmware/cert/DigiCertSHA2_Root.cer"
|
|
||||||
#define CERT_GEOTRUST_PATH "/firmware/cert/GeoTrustGlobalCA_Root.cer"
|
|
||||||
#define CERT_RADIUS_PATH "/firmware/cert/Radius_Root.cer"
|
|
||||||
#define CERT_VERISIGN_PATH "/firmware/cert/VeriSign_Root.cer"
|
|
||||||
|
|
||||||
#define MIN(a,b) \
|
#define MIN(a,b) \
|
||||||
({ __typeof__ (a) _a = (a); \
|
({ __typeof__ (a) _a = (a); \
|
||||||
@ -166,79 +161,3 @@ error:
|
|||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int burn_certificate(const char *cert, const char *path)
|
|
||||||
{
|
|
||||||
FIL fp;
|
|
||||||
int ret = M2M_ERR_FAIL;
|
|
||||||
// This is big enough for the max certificate
|
|
||||||
char *buf = fb_alloc(FLASH_SECTOR_SZ);
|
|
||||||
|
|
||||||
if (f_open(&fp, path, FA_READ|FA_OPEN_EXISTING) != FR_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT bytes_out=0;
|
|
||||||
UINT bytes = f_size(&fp);
|
|
||||||
|
|
||||||
// Read root certificate
|
|
||||||
if (f_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) {
|
|
||||||
printf("burn_certificate: file read error!\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write root certificate to the WINC1500 memory.
|
|
||||||
ret = WriteRootCertificate(cert, buf, bytes);
|
|
||||||
|
|
||||||
error:
|
|
||||||
fb_free();
|
|
||||||
f_close(&fp);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Program root certificates to WINC1500 memory.
|
|
||||||
*
|
|
||||||
* return: M2M_SUCCESS on success, error code otherwise.
|
|
||||||
*/
|
|
||||||
int burn_certificates()
|
|
||||||
{
|
|
||||||
const char *root_certs[][2] = {
|
|
||||||
{"DigiCert_Root", CERT_DIGI_PATH },
|
|
||||||
{"DigiCertSHA2_Root", CERT_DIGISHA2_PATH},
|
|
||||||
{"GeoTrustGlobalCA_Root", CERT_GEOTRUST_PATH},
|
|
||||||
{"Radius_Root", CERT_RADIUS_PATH },
|
|
||||||
{"VeriSign_Root", CERT_VERISIGN_PATH},
|
|
||||||
{0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int ret=M2M_SUCCESS;
|
|
||||||
for (int i=0; ret==M2M_SUCCESS && root_certs[i][0]; i++) {
|
|
||||||
ret = burn_certificate(root_certs[i][0], root_certs[i][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify WINC1500 certificates
|
|
||||||
* return M2M_SUCCESS on success, error code otherwise.
|
|
||||||
*/
|
|
||||||
int verify_certificates(void)
|
|
||||||
{
|
|
||||||
int ret = M2M_ERR_FAIL;
|
|
||||||
uint8_t *flash_buf = fb_alloc(FLASH_SECTOR_SZ);
|
|
||||||
|
|
||||||
/* Dump entire root certificate memory region. */
|
|
||||||
if (programmer_read_cert_image(flash_buf) != M2M_SUCCESS) {
|
|
||||||
printf("verify_certificate: read access failed on certificate section!\r\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = M2M_SUCCESS;
|
|
||||||
|
|
||||||
error:
|
|
||||||
fb_free();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,253 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief Root Certificate Setup.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "fb_alloc.h"
|
|
||||||
#include "root_cert/x509/x509_cert.h"
|
|
||||||
#include "root_cert/root_setup.h"
|
|
||||||
#include "programmer/programmer_apis.h"
|
|
||||||
|
|
||||||
//#define ENABLE_VERIFICATION
|
|
||||||
|
|
||||||
#define WORD_ALIGN(val) (((val) & 0x03) ? ((val) + 4 - ((val) & 0x03)) : (val))
|
|
||||||
|
|
||||||
#define ROOT_CERT_FLASH_START_PATTERN_LENGTH 16
|
|
||||||
|
|
||||||
#define ROOT_CERT_FLASH_START_PATTERN \
|
|
||||||
{ \
|
|
||||||
0x01, 0xF1, 0x02, 0xF2, 0x03, 0xF3, 0x04, 0xF4, \
|
|
||||||
0x05, 0xF5, 0x06, 0xF6, 0x07, 0xF7, 0x08, 0xF8 \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!< A Pattern is stored at the start of the root certificate flash area
|
|
||||||
* in order to identify if the flash is written before or not.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 au8StartPattern[ROOT_CERT_FLASH_START_PATTERN_LENGTH];
|
|
||||||
uint32 u32nCerts;
|
|
||||||
} tstrRootCertFlashHeader;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 au8SHA1NameHash[SHA1_DIGEST_SIZE];
|
|
||||||
uint16 u16NSize;
|
|
||||||
uint16 u16ESize;
|
|
||||||
uint8 au8ValidityStartDate[20];
|
|
||||||
uint8 au8ValidityExpDate[20];
|
|
||||||
} tstrRootCertEntryHeader;
|
|
||||||
|
|
||||||
#ifdef ENABLE_VERIFICATION
|
|
||||||
static uint8 gau8Verify[M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Parse and validate certificate.
|
|
||||||
*
|
|
||||||
* \return M2M_SUCCESS on success, error code otherwise.
|
|
||||||
*/
|
|
||||||
static int GetRootCertificate(uint8 *pcRootCertFileData, uint32 u32FileSize, tstrX509Cert *pstrX509, uint8 **ppu8CertificateBuffer)
|
|
||||||
{
|
|
||||||
sint8 ret = -1;
|
|
||||||
|
|
||||||
/* Decode the certificate. */
|
|
||||||
if (X509Cert_Decode(pcRootCertFileData, u32FileSize, pstrX509, 1) == X509_SUCCESS) {
|
|
||||||
printf(">Root certificate verified OK.\n");
|
|
||||||
*ppu8CertificateBuffer = pcRootCertFileData;
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Update the root certificate list.
|
|
||||||
*
|
|
||||||
* \return M2M_SUCCESS on success, error code otherwise.
|
|
||||||
*/
|
|
||||||
static sint8 UpdateRootList(tstrX509Cert *pstrRootCert, uint8 *gau8RootCertMem)
|
|
||||||
{
|
|
||||||
uint32 u32Idx;
|
|
||||||
uint8 bIncrement = 0;
|
|
||||||
uint32 u32nStoredCerts = 0;
|
|
||||||
uint8 au8StartPattern[] = ROOT_CERT_FLASH_START_PATTERN;
|
|
||||||
tstrRootCertFlashHeader *pstrRootFlashHdr;
|
|
||||||
tstrRootCertEntryHeader *pstrEntryHDR;
|
|
||||||
uint16 u16BufferOffset;
|
|
||||||
uint16 u16WriteSize;
|
|
||||||
tstrRSAPublicKey *pstrKey;
|
|
||||||
|
|
||||||
pstrKey = &pstrRootCert->strPubKey.strRSAKey;
|
|
||||||
pstrRootFlashHdr = (tstrRootCertFlashHeader *)((void *)gau8RootCertMem);
|
|
||||||
u16BufferOffset = sizeof(tstrRootCertFlashHeader);
|
|
||||||
u16WriteSize = pstrKey->u16ESize + pstrKey->u16NSize + sizeof(tstrRootCertEntryHeader);
|
|
||||||
|
|
||||||
/* Check if the flash has been written before. */
|
|
||||||
if (!memcmp(au8StartPattern, pstrRootFlashHdr->au8StartPattern, ROOT_CERT_FLASH_START_PATTERN_LENGTH)) {
|
|
||||||
u32nStoredCerts = pstrRootFlashHdr->u32nCerts;
|
|
||||||
bIncrement = 1;
|
|
||||||
|
|
||||||
for (u32Idx = 0; u32Idx < u32nStoredCerts; u32Idx++) {
|
|
||||||
pstrEntryHDR = (tstrRootCertEntryHeader *)((void *)&gau8RootCertMem[u16BufferOffset]);
|
|
||||||
|
|
||||||
/* Check for match (equivalent NameSHA1). */
|
|
||||||
if (!memcmp(pstrRootCert->strSubject.au8NameSHA1, pstrEntryHDR->au8SHA1NameHash, SHA1_DIGEST_SIZE)) {
|
|
||||||
/* The current entry will be overwritten. */
|
|
||||||
bIncrement = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
u16BufferOffset += sizeof(tstrRootCertEntryHeader) + WORD_ALIGN(pstrEntryHDR->u16NSize + pstrEntryHDR->u16ESize);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pstrRootFlashHdr->u32nCerts = 0;
|
|
||||||
memcpy(pstrRootFlashHdr->au8StartPattern, au8StartPattern, ROOT_CERT_FLASH_START_PATTERN_LENGTH);
|
|
||||||
bIncrement = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bIncrement) {
|
|
||||||
/* A new certificate is to be inserted into the flash. */
|
|
||||||
/* Increment the number of stored Certificates. */
|
|
||||||
if (u16BufferOffset + u16WriteSize > M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE) {
|
|
||||||
printf("(ERROR) Root Certificate Flash is Full\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrRootFlashHdr->u32nCerts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Root Certificate to flash. The entry is ordered as follows:
|
|
||||||
- SHA1_DIGEST_SIZE --> NameSHA1 of the Root certificate.
|
|
||||||
- uint16 --> N_SIZE (Byte count for the RSA modulus N).
|
|
||||||
- uint16 --> E_SIZE (Byte count for the RSA public exponent E).
|
|
||||||
- START_DATE --> Start date of the root certificate(20 bytes).
|
|
||||||
- EXPIRATION_DATE --> Expiration date of the root certificate(20 bytes).
|
|
||||||
- N_SIZE --> RSA Modulus N.
|
|
||||||
- E_SIZE --> RSA Public exponent.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pstrEntryHDR = (tstrRootCertEntryHeader *)((void *)&gau8RootCertMem[u16BufferOffset]);
|
|
||||||
|
|
||||||
/* NameSHA1 */
|
|
||||||
memcpy(pstrEntryHDR->au8SHA1NameHash, pstrRootCert->strSubject.au8NameSHA1, SHA1_DIGEST_SIZE);
|
|
||||||
|
|
||||||
/* N_SIZE */
|
|
||||||
pstrEntryHDR->u16NSize = pstrKey->u16NSize;
|
|
||||||
|
|
||||||
/* E_SIZE */
|
|
||||||
pstrEntryHDR->u16ESize = pstrKey->u16ESize;
|
|
||||||
|
|
||||||
/* Start Date */
|
|
||||||
memcpy(pstrEntryHDR->au8ValidityStartDate, pstrRootCert->strStartDate.au8Time, 20);
|
|
||||||
|
|
||||||
/* Expiration Date */
|
|
||||||
memcpy(pstrEntryHDR->au8ValidityExpDate, pstrRootCert->strExpiryDate.au8Time, 20);
|
|
||||||
u16BufferOffset += sizeof(tstrRootCertEntryHeader);
|
|
||||||
|
|
||||||
/* N */
|
|
||||||
memcpy(&gau8RootCertMem[u16BufferOffset], pstrKey->pu8N, pstrKey->u16NSize);
|
|
||||||
|
|
||||||
/* E */
|
|
||||||
memcpy(&gau8RootCertMem[u16BufferOffset + pstrKey->u16NSize], pstrKey->pu8E, pstrKey->u16ESize);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Write root certificate to flash.
|
|
||||||
*
|
|
||||||
* \return M2M_SUCCESS on success, error code otherwise.
|
|
||||||
*/
|
|
||||||
int WriteRootCertificate(const char *filename, char *pcRootCertFileData, uint32 u32FileSize)
|
|
||||||
{
|
|
||||||
uint8 *pu8CertBuffer;
|
|
||||||
tstrX509Cert strX509Root;
|
|
||||||
#ifdef ENABLE_VERIFICATION
|
|
||||||
uint32 u32Idx;
|
|
||||||
#endif
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
uint8 *gau8RootCertMem = fb_alloc(M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE);
|
|
||||||
|
|
||||||
/* Read Certificate File. */
|
|
||||||
if (GetRootCertificate((uint8 *)pcRootCertFileData, u32FileSize, &strX509Root, &pu8CertBuffer) == 0) {
|
|
||||||
programmer_read_cert_image(gau8RootCertMem);
|
|
||||||
|
|
||||||
if (UpdateRootList(&strX509Root, gau8RootCertMem) == 0) {
|
|
||||||
/* Erase memory. */
|
|
||||||
ret = programmer_erase_cert_image();
|
|
||||||
if (M2M_SUCCESS != ret) {
|
|
||||||
goto END;
|
|
||||||
}
|
|
||||||
|
|
||||||
nm_bsp_sleep(50);
|
|
||||||
|
|
||||||
/* Write. */
|
|
||||||
printf(">Writing the certificate to SPI flash...\r\n");
|
|
||||||
ret = programmer_write_cert_image(gau8RootCertMem);
|
|
||||||
if (M2M_SUCCESS != ret) {
|
|
||||||
goto END;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Done\r\n");
|
|
||||||
|
|
||||||
#ifdef ENABLE_VERIFICATION
|
|
||||||
/* Verification. */
|
|
||||||
memset(gau8Verify, 0, M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE);
|
|
||||||
programmer_read_cert_image(gau8Verify);
|
|
||||||
|
|
||||||
for (u32Idx = 0; u32Idx < M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE; u32Idx++) {
|
|
||||||
if (gau8RootCertMem[u32Idx] != gau8Verify[u32Idx]) {
|
|
||||||
printf("ERROR verification failed at %u\n", u32Idx);
|
|
||||||
ret = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("\r\n>>>Invalid root certificate %s\n", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
END:
|
|
||||||
fb_free();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@ -1,895 +0,0 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* \file
|
|
||||||
*
|
|
||||||
* \brief X509 Certificate Functions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2015 Atmel Corporation. All rights reserved.
|
|
||||||
*
|
|
||||||
* \asf_license_start
|
|
||||||
*
|
|
||||||
* \page License
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
||||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* \asf_license_stop
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "root_cert/x509/x509_cert.h"
|
|
||||||
#include "root_cert/x509/asn1.h"
|
|
||||||
|
|
||||||
/* X509 SUPPORTED VERSIONS. */
|
|
||||||
#define X509_VER_1 0
|
|
||||||
#define X509_VER_2 1
|
|
||||||
#define X509_VER_3 2
|
|
||||||
|
|
||||||
/* X509 CERTIFICATE PARSING STATES. */
|
|
||||||
|
|
||||||
#define CERT_VERSION_PENDING 0
|
|
||||||
#define CERT_SERIAL_PENDING 1
|
|
||||||
#define CERT_SIGNATURE_PENDING 2
|
|
||||||
#define CERT_ISSUER_PENDING 3
|
|
||||||
#define CERT_VALIDITY_PENDING 4
|
|
||||||
#define CERT_SUBJECT_PENDING 5
|
|
||||||
#define CERT_SUBECTKEYINFO_PENDING 6
|
|
||||||
#define CERT_EXTENSIONS_PENDING 7
|
|
||||||
#define CERT_PARSING_DONE 8
|
|
||||||
|
|
||||||
/* X509 ENCODED FIELD IDs. */
|
|
||||||
|
|
||||||
#define X509_VERSION 0xA0
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier of the version field in the X.509 certificate
|
|
||||||
* encoding. It is given in the ASN.1 syntax as
|
|
||||||
* [0] EXPLICIT
|
|
||||||
* Context-Specific class (10) | constructed (1) | 00000
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_SERIAL_NO ASN1_INTEGER
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the certificate serial num ber element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_SIGNATURE ASN1_SEQUENCE
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the Signature algorithm ID element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_ISSUER ASN1_SEQUENCE
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the certificate ISSUER element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_VALIDITY ASN1_SEQUENCE
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the certificate validity interval element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_SUBJECT ASN1_SEQUENCE
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the certificate SUBJECT information element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_SUBJECT_KEY_INFO ASN1_SEQUENCE
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Identifier for the publick key information element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_ISSUER_UNIQUE_ID 0x81
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Encoded value for the issuerUniqueID tag. It is defined as
|
|
||||||
* [1] IMPLICIT BIT STRING
|
|
||||||
* Context-Specific class (10) | primitive (0) | 00001
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_SUBJECT_UNIQUE_ID 0x82
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Encoded value for the subjectUniqueID tag. It is defined as
|
|
||||||
* [2] IMPLICIT BIT STRING
|
|
||||||
* Context-Specific class (10) | primitive (0) | 00010
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_EXTENSIONS_ID 0xA3
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* Encoded value for the issuerUniqueID tag. It is defined as
|
|
||||||
* [3] EXPLICIT
|
|
||||||
* Context-Specific class (10) | constructed (1) | 00011
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* NAME ATTRIBUTE IDs. */
|
|
||||||
|
|
||||||
#define ID_AT 85, 0x04,
|
|
||||||
#define ID_AT_COMMONNAME {ID_AT 3 }
|
|
||||||
#define ID_AT_SERIALNUMBER {ID_AT 5 }
|
|
||||||
#define ID_AT_COUNTRYNAME {ID_AT 6 }
|
|
||||||
#define ID_AT_ORGANIZATIONNAME {ID_AT 10}
|
|
||||||
#define ID_AT_ORGANIZATIONALUNITNAME {ID_AT 11}
|
|
||||||
|
|
||||||
#define X520_COMMON_NAME 1
|
|
||||||
#define X520_ORG_UNIT 2
|
|
||||||
#define X520_ORG 3
|
|
||||||
|
|
||||||
/* CERTIFICATE EXTENSION IDs. */
|
|
||||||
|
|
||||||
#define ID_CE 85, 29,
|
|
||||||
#define ID_CE_AUTHORITY_KEY_ID {ID_CE 35}
|
|
||||||
#define ID_CE_SUBJECT_KEY_ID {ID_CE 14}
|
|
||||||
|
|
||||||
/* SIGNATURE ALGORITHM IDs. */
|
|
||||||
|
|
||||||
#define PKCS_1 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, 0x01,
|
|
||||||
/* 1.2.840.113549.1.1 */
|
|
||||||
|
|
||||||
#define RSA_ENCRYPTION {PKCS_1 1} /* 1.2.840.113549.1.1 */
|
|
||||||
#define MD5_WITH_RSA_ENCRYPTION {PKCS_1 4} /* 1.2.840.113549.1.1.4 */
|
|
||||||
#define SHA1_WITH_RSA_ENCRYPTION {PKCS_1 5} /* 1.2.840.113549.1.1.5 */
|
|
||||||
#define SHA256_WITH_RSA_ENCRYPTION {PKCS_1 11} /* 1.2.840.113549.1.1.11 */
|
|
||||||
#define SHA384_WITH_RSA_ENCRYPTION {PKCS_1 12} /* 1.2.840.113549.1.1.12 */
|
|
||||||
#define SHA512_WITH_RSA_ENCRYPTION {PKCS_1 13} /* 1.2.840.113549.1.1.13 */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8 u8Type;
|
|
||||||
uint8 *pu8Name;
|
|
||||||
uint8 u8Length;
|
|
||||||
} tstrX520DistinguishedName;
|
|
||||||
|
|
||||||
sint8 M2M_GetTimeOfDay(tstrSystemTime *pstrSysTime);
|
|
||||||
uint8 Cert_DecodeAlgID(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size);
|
|
||||||
sint8 Cert_DecodeDistinguishedName(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX520DistinguishedName *pstrDN);
|
|
||||||
sint8 Cert_DecodeX520Name(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX520Name *pstrName);
|
|
||||||
sint8 Cert_DecodeRSAPubKey(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32KeySize, tstrRSAPublicKey *pstrRsaPublicKey);
|
|
||||||
sint8 Cert_DecodeSubjectPubKey(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrPublicKey *pstrPubKey);
|
|
||||||
sint8 Cert_DecodeValidity(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX509Time *pstrNotBefore, tstrX509Time *pstrNotAfter);
|
|
||||||
sint8 Cert_DecodeTBSCertificate(tstrAsn1Context *pstrX509Asn1Cxt, uint16 u16CertSize, tstrX509Cert *pstrCert);
|
|
||||||
sint8 Cert_DecodeTime(uint8 *pu8Time, tstrSystemTime *pstrTime);
|
|
||||||
sint8 Cert_CompareTime(tstrSystemTime *pstrT1, tstrSystemTime *pstrT2);
|
|
||||||
uint8 X509Cert_IsValid(void *pvX509);
|
|
||||||
|
|
||||||
sint8 M2M_GetTimeOfDay(tstrSystemTime *pstrSysTime)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
SYSTEMTIME winTime;
|
|
||||||
GetSystemTime(&winTime);
|
|
||||||
pstrSysTime->u16Year = (uint16)winTime.wYear;
|
|
||||||
pstrSysTime->u8Month = (uint8)winTime.wMonth;
|
|
||||||
pstrSysTime->u8Day = (uint8)winTime.wDay;
|
|
||||||
pstrSysTime->u8Hour = (uint8)winTime.wHour;
|
|
||||||
pstrSysTime->u8Minute = (uint8)winTime.wMinute;
|
|
||||||
pstrSysTime->u8Second = (uint8)winTime.wSecond;
|
|
||||||
#else
|
|
||||||
pstrSysTime->u16Year = (uint16)(2015);
|
|
||||||
pstrSysTime->u8Month = (uint8)8;
|
|
||||||
pstrSysTime->u8Day = (uint8)6;
|
|
||||||
pstrSysTime->u8Hour = (uint8)9;
|
|
||||||
pstrSysTime->u8Minute = (uint8)39;
|
|
||||||
pstrSysTime->u8Second = (uint8)10;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return M2M_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Perform decoding to the data type "AlgorithmIdentifier".
|
|
||||||
*/
|
|
||||||
uint8 Cert_DecodeAlgID(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* AlgorithmIdentifier ::= SEQUENCE {
|
|
||||||
* algorithm OBJECT IDENTIFIER,
|
|
||||||
* parameters NULL
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
const uint8 gau8SecAlgorithms[][16] = {
|
|
||||||
RSA_ENCRYPTION,
|
|
||||||
MD5_WITH_RSA_ENCRYPTION,
|
|
||||||
SHA1_WITH_RSA_ENCRYPTION,
|
|
||||||
SHA256_WITH_RSA_ENCRYPTION,
|
|
||||||
SHA384_WITH_RSA_ENCRYPTION,
|
|
||||||
SHA512_WITH_RSA_ENCRYPTION
|
|
||||||
};
|
|
||||||
#define X509_NUM_SUPPORTED_SEC_ALGORITHMS (sizeof(gau8SecAlgorithms) / sizeof(gau8SecAlgorithms[0]))
|
|
||||||
|
|
||||||
uint8 u8Alg = X509_ALG_NULL;
|
|
||||||
|
|
||||||
if (pstrX509Asn1Cxt != NULL) {
|
|
||||||
tstrAsn1Element strElem;
|
|
||||||
|
|
||||||
/* Initialize a decoding object for this SEQUENCE. */
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_OBJECT_IDENTIFIER) {
|
|
||||||
if (strElem.u32Length <= 16) {
|
|
||||||
uint8 u8Idx;
|
|
||||||
uint8 au8AlgID[16];
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElem.u32Length, au8AlgID);
|
|
||||||
for (u8Idx = 0; u8Idx < X509_NUM_SUPPORTED_SEC_ALGORITHMS; u8Idx++) {
|
|
||||||
if (!m2m_memcmp(au8AlgID, (uint8 *)gau8SecAlgorithms[u8Idx], strElem.u32Length)) {
|
|
||||||
u8Alg = u8Idx + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return u8Alg;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeDistinguishedName(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX520DistinguishedName *pstrDN)
|
|
||||||
{
|
|
||||||
sint8 s8Ret = X509_FAIL;
|
|
||||||
|
|
||||||
if ((pstrX509Asn1Cxt != NULL) && (pstrDN != NULL)) {
|
|
||||||
tstrAsn1Element strElem;
|
|
||||||
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_OBJECT_IDENTIFIER) {
|
|
||||||
uint8 au8CmnNameID[4] = ID_AT_COMMONNAME;
|
|
||||||
uint8 au8TempID[16];
|
|
||||||
|
|
||||||
pstrDN->u8Type = 0;
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElem.u32Length, au8TempID);
|
|
||||||
if (!m2m_memcmp(au8CmnNameID, au8TempID, strElem.u32Length)) {
|
|
||||||
pstrDN->u8Type = X520_COMMON_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem) != ASN1_FAIL) {
|
|
||||||
pstrDN->u8Length = (uint8)strElem.u32Length;
|
|
||||||
ASN1_ReadReference(pstrX509Asn1Cxt, strElem.u32Length, &pstrDN->pu8Name);
|
|
||||||
s8Ret = X509_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeX520Name(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX520Name *pstrName)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Name ::= CHOICE { -- only one possibility for now --
|
|
||||||
* rdnSequence RDNSequence
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
|
|
||||||
*
|
|
||||||
* RelativeDistinguishedName ::=
|
|
||||||
* SET SIZE (1..MAX) OF AttributeTypeAndValue
|
|
||||||
*
|
|
||||||
* AttributeTypeAndValue ::= SEQUENCE {
|
|
||||||
* type AttributeType,
|
|
||||||
* value AttributeValue
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* AttributeType ::= OBJECT IDENTIFIER
|
|
||||||
* AttributeValue ::= ANY -- DEFINED BY AttributeType
|
|
||||||
*
|
|
||||||
* DirectoryString ::= CHOICE {
|
|
||||||
* teletexString TeletexString (SIZE (1..MAX)),
|
|
||||||
* printableString PrintableString (SIZE (1..MAX)),
|
|
||||||
* universalString UniversalString (SIZE (1..MAX)),
|
|
||||||
* utf8String UTF8String (SIZE (1..MAX)),
|
|
||||||
* bmpString BMPString (SIZE (1..MAX))
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_SUCCESS;
|
|
||||||
|
|
||||||
if ((pstrX509Asn1Cxt != NULL) && (pstrName != NULL)) {
|
|
||||||
tstrAsn1Element strSetElem, strSeqElem;
|
|
||||||
tstrX520DistinguishedName strDN;
|
|
||||||
tstrSha1Context strSha1Cxt;
|
|
||||||
uint16 u16Offset = 0;
|
|
||||||
|
|
||||||
SHA1_INIT(&strSha1Cxt);
|
|
||||||
|
|
||||||
/* RelativeDistinguishedName. */
|
|
||||||
while (u16Offset < u32Size) {
|
|
||||||
u16Offset += ASN1_GetNextElement(pstrX509Asn1Cxt, &strSetElem);
|
|
||||||
if (strSetElem.u8Tag == ASN1_SET) {
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strSeqElem);
|
|
||||||
if (strSeqElem.u8Tag != ASN1_SEQUENCE) {
|
|
||||||
s8Ret = X509_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Cert_DecodeDistinguishedName(pstrX509Asn1Cxt, strSeqElem.u32Length, &strDN) != X509_SUCCESS) {
|
|
||||||
s8Ret = X509_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strDN.u8Type == X520_COMMON_NAME) {
|
|
||||||
m2m_memcpy((uint8 *)pstrName->acCmnName, strDN.pu8Name, strDN.u8Length);
|
|
||||||
pstrName->acCmnName[strDN.u8Length] = '\0';
|
|
||||||
} else if (strDN.u8Type == X520_ORG_UNIT) {
|
|
||||||
if (pstrName->acOrgUnit[0] == 0) {
|
|
||||||
m2m_memcpy((uint8 *)pstrName->acOrgUnit, strDN.pu8Name, strDN.u8Length);
|
|
||||||
pstrName->acOrgUnit[strDN.u8Length] = '\0';
|
|
||||||
}
|
|
||||||
} else if (strDN.u8Type == X520_ORG) {
|
|
||||||
m2m_memcpy((uint8 *)pstrName->acOrg, strDN.pu8Name, strDN.u8Length);
|
|
||||||
pstrName->acOrg[strDN.u8Length] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
SHA1_UPDATE(&strSha1Cxt, strDN.pu8Name, strDN.u8Length);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SHA1_FINISH(&strSha1Cxt, pstrName->au8NameSHA1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeRSAPubKey(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32KeySize, tstrRSAPublicKey *pstrRsaPublicKey)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* RSAPublicKey ::= SEQUENCE {
|
|
||||||
* modulus INTEGER, -- n
|
|
||||||
* publicExponent INTEGER -- e
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_FAIL;
|
|
||||||
if ((pstrX509Asn1Cxt != NULL) && (pstrRsaPublicKey != NULL)) {
|
|
||||||
tstrAsn1Element strElem;
|
|
||||||
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_SEQUENCE) {
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_INTEGER) {
|
|
||||||
ASN1_ReadReference(pstrX509Asn1Cxt, strElem.u32Length, &pstrRsaPublicKey->pu8N);
|
|
||||||
while (*pstrRsaPublicKey->pu8N == 0) {
|
|
||||||
pstrRsaPublicKey->pu8N++;
|
|
||||||
strElem.u32Length--;
|
|
||||||
}
|
|
||||||
pstrRsaPublicKey->u16NSize = (uint16)strElem.u32Length;
|
|
||||||
|
|
||||||
ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_INTEGER) {
|
|
||||||
ASN1_ReadReference(pstrX509Asn1Cxt, strElem.u32Length, &pstrRsaPublicKey->pu8E);
|
|
||||||
while (*pstrRsaPublicKey->pu8E == 0) {
|
|
||||||
pstrRsaPublicKey->pu8E++;
|
|
||||||
strElem.u32Length--;
|
|
||||||
}
|
|
||||||
pstrRsaPublicKey->u16ESize = (uint16)strElem.u32Length;
|
|
||||||
s8Ret = X509_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeSubjectPubKey(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrPublicKey *pstrPubKey)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
|
||||||
* algorithm AlgorithmIdentifier,
|
|
||||||
* subjectPublicKey BIT STRING
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_SUCCESS;
|
|
||||||
|
|
||||||
if ((pstrX509Asn1Cxt != NULL) && (pstrPubKey != NULL)) {
|
|
||||||
tstrAsn1Element strElem;
|
|
||||||
uint8 u8PubKeyAlg = 0;
|
|
||||||
uint16 u16Offset = 0;
|
|
||||||
|
|
||||||
while (u16Offset < u32Size) {
|
|
||||||
u16Offset += ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem);
|
|
||||||
if (strElem.u8Tag == ASN1_SEQUENCE) {
|
|
||||||
u8PubKeyAlg = Cert_DecodeAlgID(pstrX509Asn1Cxt, strElem.u32Length);
|
|
||||||
} else if (strElem.u8Tag == ASN1_BIT_STRING) {
|
|
||||||
if (u8PubKeyAlg != X509_PUB_RSA) {
|
|
||||||
s8Ret = X509_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrPubKey->enuType = PUBKEY_ALG_RSA;
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, 1, NULL);
|
|
||||||
s8Ret = Cert_DecodeRSAPubKey(pstrX509Asn1Cxt, strElem.u32Length - 1, &pstrPubKey->strRSAKey);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeValidity(tstrAsn1Context *pstrX509Asn1Cxt, uint32 u32Size, tstrX509Time *pstrNotBefore, tstrX509Time *pstrNotAfter)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Validity ::= SEQUENCE {
|
|
||||||
* notBefore Time,
|
|
||||||
* notAfter Time
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_FAIL;
|
|
||||||
|
|
||||||
if ((pstrX509Asn1Cxt != 0) && (pstrNotAfter != NULL) && (pstrNotBefore != NULL)) {
|
|
||||||
tstrAsn1Element strElem;
|
|
||||||
|
|
||||||
if (ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem) != ASN1_INVALID) {
|
|
||||||
/* Start time. */
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElem.u32Length, pstrNotBefore->au8Time);
|
|
||||||
pstrNotBefore->au8Time[strElem.u32Length] = '\0';
|
|
||||||
|
|
||||||
if (ASN1_GetNextElement(pstrX509Asn1Cxt, &strElem) != ASN1_INVALID) {
|
|
||||||
/* End time. */
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElem.u32Length, pstrNotAfter->au8Time);
|
|
||||||
pstrNotAfter->au8Time[strElem.u32Length] = '\0';
|
|
||||||
s8Ret = X509_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_DecodeTBSCertificate(tstrAsn1Context *pstrX509Asn1Cxt, uint16 u16CertSize, tstrX509Cert *pstrCert)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* TBSCertificate ::= SEQUENCE {
|
|
||||||
* version [0]
|
|
||||||
* Version DEFAULT v1,
|
|
||||||
* serialNumber CertificateSerialNumber,
|
|
||||||
* signature AlgorithmIdentifier,
|
|
||||||
* issuer Name,
|
|
||||||
* validity Validity,
|
|
||||||
* subject Name,
|
|
||||||
* subjectPublicKeyInfo SubjectPublicKeyInfo,
|
|
||||||
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, If present, version MUST be v2 or v3
|
|
||||||
* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, If present, version MUST be v2 or v3
|
|
||||||
* extensions [3] Extensions OPTIONAL If present, version MUST be v3
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_SUCCESS;
|
|
||||||
|
|
||||||
if ((pstrX509Asn1Cxt != NULL) && (pstrCert != NULL)) {
|
|
||||||
uint16 u16ReadOffset = 0;
|
|
||||||
tstrAsn1Element strElement;
|
|
||||||
uint8 u8CertState = CERT_VERSION_PENDING;
|
|
||||||
|
|
||||||
/* Loop on the elements of the certificate until finishing. */
|
|
||||||
while (u16ReadOffset < u16CertSize) {
|
|
||||||
u16ReadOffset += ASN1_GetNextElement(pstrX509Asn1Cxt, &strElement);
|
|
||||||
switch (u8CertState) {
|
|
||||||
case CERT_VERSION_PENDING:
|
|
||||||
|
|
||||||
/* Version. */
|
|
||||||
if (strElement.u8Tag == X509_VERSION) {
|
|
||||||
/* The encoding of version is on the form A0 03 02 01 ver. */
|
|
||||||
if (strElement.u32Length < 3) {
|
|
||||||
s8Ret = X509_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, 2, NULL);
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, 1, &pstrCert->u8Version);
|
|
||||||
u8CertState = CERT_SERIAL_PENDING;
|
|
||||||
} else if (strElement.u8Tag == X509_SERIAL_NO) {
|
|
||||||
/* The certificate version number is absent from the certificate. */
|
|
||||||
/* It will be set to the default value Version 1.0. */
|
|
||||||
pstrCert->u8Version = X509_VER_1;
|
|
||||||
|
|
||||||
/* The first field is the serial number. */
|
|
||||||
if (strElement.u32Length > X509_SERIAL_NO_MAX_LENGTH) {
|
|
||||||
strElement.u32Length = X509_SERIAL_NO_MAX_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrCert->u8SerialNumberLength = (uint8)strElement.u32Length;
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElement.u32Length, pstrCert->au8SerialNo);
|
|
||||||
u8CertState = CERT_SIGNATURE_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_SERIAL_PENDING:
|
|
||||||
|
|
||||||
/* SerialNumber. */
|
|
||||||
if (strElement.u8Tag == X509_SERIAL_NO) {
|
|
||||||
/* The first field is the serial number. */
|
|
||||||
if (strElement.u32Length > X509_SERIAL_NO_MAX_LENGTH) {
|
|
||||||
strElement.u32Length = X509_SERIAL_NO_MAX_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrCert->u8SerialNumberLength = (uint8)strElement.u32Length;
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElement.u32Length, pstrCert->au8SerialNo);
|
|
||||||
u8CertState = CERT_SIGNATURE_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_SIGNATURE_PENDING:
|
|
||||||
|
|
||||||
/* Signature. */
|
|
||||||
if (strElement.u8Tag == X509_SIGNATURE) {
|
|
||||||
pstrCert->u8SignAlg = Cert_DecodeAlgID(pstrX509Asn1Cxt, strElement.u32Length);
|
|
||||||
u8CertState = CERT_ISSUER_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_ISSUER_PENDING:
|
|
||||||
|
|
||||||
/* Issuer. */
|
|
||||||
if (strElement.u8Tag == X509_ISSUER) {
|
|
||||||
Cert_DecodeX520Name(pstrX509Asn1Cxt, strElement.u32Length, &pstrCert->strIssuer);
|
|
||||||
u8CertState = CERT_VALIDITY_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_VALIDITY_PENDING:
|
|
||||||
|
|
||||||
/* Validity. */
|
|
||||||
if (strElement.u8Tag == X509_VALIDITY) {
|
|
||||||
Cert_DecodeValidity(pstrX509Asn1Cxt, strElement.u32Length,
|
|
||||||
&pstrCert->strStartDate, &pstrCert->strExpiryDate);
|
|
||||||
u8CertState = CERT_SUBJECT_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_SUBJECT_PENDING:
|
|
||||||
|
|
||||||
/* Subject. */
|
|
||||||
if (strElement.u8Tag == X509_SUBJECT) {
|
|
||||||
Cert_DecodeX520Name(pstrX509Asn1Cxt, strElement.u32Length, &pstrCert->strSubject);
|
|
||||||
u8CertState = CERT_SUBECTKEYINFO_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_SUBECTKEYINFO_PENDING:
|
|
||||||
|
|
||||||
/* SubjectPublicKeyInfo. */
|
|
||||||
if (strElement.u8Tag == X509_SUBJECT_KEY_INFO) {
|
|
||||||
Cert_DecodeSubjectPubKey(pstrX509Asn1Cxt, strElement.u32Length, &pstrCert->strPubKey);
|
|
||||||
u8CertState = CERT_EXTENSIONS_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CERT_EXTENSIONS_PENDING:
|
|
||||||
ASN1_Read(pstrX509Asn1Cxt, strElement.u32Length, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 X509Cert_Decode(uint8 *pu8X509Buffer, uint32 u32CertSize, tstrX509Cert *pstrCert, uint8 bDumpX509)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Certificate ::= SEQUENCE {
|
|
||||||
* tbsCertificate TBSCertificate,
|
|
||||||
* signatureAlgorithm AlgorithmIdentifier,
|
|
||||||
* signature BIT STRING }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
sint8 s8Ret = X509_FAIL;
|
|
||||||
|
|
||||||
if ((pu8X509Buffer != NULL) && (pstrCert != NULL)) {
|
|
||||||
tstrAsn1Context strX509ASN1Cxt;
|
|
||||||
tstrAsn1Element strElement;
|
|
||||||
uint8 u8SignAlgorithm = X509_ALG_NULL;
|
|
||||||
|
|
||||||
/* Initialize the certificate structure. */
|
|
||||||
m2m_memset((uint8 *)pstrCert, 0, sizeof(tstrX509Cert));
|
|
||||||
|
|
||||||
/* Initialize the ASN1 Decoding operation. */
|
|
||||||
strX509ASN1Cxt.pu8Buff = pu8X509Buffer;
|
|
||||||
strX509ASN1Cxt.pu8Data = pu8X509Buffer;
|
|
||||||
|
|
||||||
ASN1_GetNextElement(&strX509ASN1Cxt, &strElement);
|
|
||||||
if ((strElement.u8Tag == ASN1_SEQUENCE) && (strElement.u32Length < u32CertSize)) {
|
|
||||||
/* Copy the TBS certificate. It shall be used later to calculate the certificate HASH. */
|
|
||||||
pstrCert->pu8TBSCert = strX509ASN1Cxt.pu8Data;
|
|
||||||
|
|
||||||
/* tbsCertificate. */
|
|
||||||
pstrCert->u16TBSCertSize = ASN1_GetNextElement(&strX509ASN1Cxt, &strElement);
|
|
||||||
if (strElement.u8Tag == ASN1_SEQUENCE) {
|
|
||||||
if (Cert_DecodeTBSCertificate(&strX509ASN1Cxt, (uint16)strElement.u32Length, pstrCert) == 0) {
|
|
||||||
/* signatureAlgorithm. */
|
|
||||||
ASN1_GetNextElement(&strX509ASN1Cxt, &strElement);
|
|
||||||
if (strElement.u8Tag == ASN1_SEQUENCE) {
|
|
||||||
/* Check if the signatureAlgorithm ID obtained in this element matches */
|
|
||||||
/* the signature field of the TBS Certificate. */
|
|
||||||
u8SignAlgorithm = Cert_DecodeAlgID(&strX509ASN1Cxt, strElement.u32Length);
|
|
||||||
if (u8SignAlgorithm == pstrCert->u8SignAlg) {
|
|
||||||
/* signature. */
|
|
||||||
ASN1_GetNextElement(&strX509ASN1Cxt, &strElement);
|
|
||||||
if (strElement.u8Tag == ASN1_BIT_STRING) {
|
|
||||||
/* Store the obtained signature. */
|
|
||||||
pstrCert->strSignature.u16BufferSize = (uint16)strElement.u32Length - 1;
|
|
||||||
|
|
||||||
/* Jump one byte. */
|
|
||||||
ASN1_Read(&strX509ASN1Cxt, 1, NULL);
|
|
||||||
|
|
||||||
/* Get the signature value. */
|
|
||||||
ASN1_ReadReference(&strX509ASN1Cxt, pstrCert->strSignature.u16BufferSize,
|
|
||||||
&pstrCert->strSignature.pu8Data);
|
|
||||||
|
|
||||||
/* Dump the certificate contents. */
|
|
||||||
if (bDumpX509) {
|
|
||||||
X509_CERT_DUMP(pstrCert);
|
|
||||||
}
|
|
||||||
|
|
||||||
s8Ret = X509_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define X509_UTC_TIME_LENGTH 0x0D
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* The UTC time for the X.509 encoding takes the format
|
|
||||||
* YYMMDDHHMMSSZ. Each digit is BCD encoded as ASCII digit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define X509_GENERALIZED_TIME_LENGTH 0x0F
|
|
||||||
|
|
||||||
/*!<
|
|
||||||
* The UTC time for the X.509 encoding takes the format
|
|
||||||
* YYYYMMDDHHMMSSZ. Each digit is BCD encoded as ASCII digit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define GET_VAL(BUF, OFFSET) (((BUF)[OFFSET] * 10) + ((BUF)[OFFSET + 1]))
|
|
||||||
|
|
||||||
sint8 Cert_DecodeTime(uint8 *pu8Time, tstrSystemTime *pstrTime)
|
|
||||||
{
|
|
||||||
sint8 s8Ret = X509_FAIL;
|
|
||||||
|
|
||||||
if (pu8Time != NULL) {
|
|
||||||
uint8 u8TimeLength = (uint8)strlen((char *)pu8Time);
|
|
||||||
uint8 au8Time[20];
|
|
||||||
uint8 u8Idx;
|
|
||||||
|
|
||||||
memcpy(au8Time, pu8Time, 20);
|
|
||||||
|
|
||||||
if ((u8TimeLength >= X509_UTC_TIME_LENGTH) && (u8TimeLength <= X509_GENERALIZED_TIME_LENGTH)) {
|
|
||||||
if (au8Time[u8TimeLength - 1] == 'Z') {
|
|
||||||
for (u8Idx = 0; u8Idx < (u8TimeLength - 1); u8Idx++) {
|
|
||||||
au8Time[u8Idx] -= '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u8TimeLength == X509_UTC_TIME_LENGTH) {
|
|
||||||
pstrTime->u16Year = (au8Time[0] * 10) + au8Time[1];
|
|
||||||
pstrTime->u16Year += (pstrTime->u16Year < 50 ? 2000 : 1900);
|
|
||||||
u8Idx = 2;
|
|
||||||
} else {
|
|
||||||
pstrTime->u16Year = (au8Time[0] * 1000) + (au8Time[1] * 100) + (au8Time[2] * 10) + au8Time[3];
|
|
||||||
u8Idx = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrTime->u8Month = GET_VAL(au8Time, u8Idx);
|
|
||||||
u8Idx += 2;
|
|
||||||
|
|
||||||
pstrTime->u8Day = GET_VAL(au8Time, u8Idx);
|
|
||||||
u8Idx += 2;
|
|
||||||
|
|
||||||
pstrTime->u8Hour = GET_VAL(au8Time, u8Idx);
|
|
||||||
u8Idx += 2;
|
|
||||||
|
|
||||||
pstrTime->u8Minute = GET_VAL(au8Time, u8Idx);
|
|
||||||
u8Idx += 2;
|
|
||||||
|
|
||||||
pstrTime->u8Second = GET_VAL(au8Time, u8Idx);
|
|
||||||
|
|
||||||
s8Ret = X509_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
sint8 Cert_CompareTime(tstrSystemTime *pstrT1, tstrSystemTime *pstrT2)
|
|
||||||
{
|
|
||||||
sint8 s8Cmp = 1;
|
|
||||||
|
|
||||||
if ((pstrT1 != NULL) && (pstrT2 != NULL)) {
|
|
||||||
/* YEAR. */
|
|
||||||
if (pstrT1->u16Year == pstrT2->u16Year) {
|
|
||||||
/* MONTH. */
|
|
||||||
if (pstrT1->u8Month == pstrT2->u8Month) {
|
|
||||||
/* DAY */
|
|
||||||
if (pstrT1->u8Day == pstrT2->u8Day) {
|
|
||||||
s8Cmp = pstrT1->u8Hour - pstrT2->u8Hour;
|
|
||||||
} else {
|
|
||||||
s8Cmp = pstrT1->u8Day - pstrT2->u8Day;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s8Cmp = pstrT1->u8Month - pstrT2->u8Month;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s8Cmp = pstrT1->u16Year - pstrT2->u16Year;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s8Cmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 X509Cert_IsValid(void *pvX509)
|
|
||||||
{
|
|
||||||
tstrX509Cert *pstrX509 = (tstrX509Cert *)pvX509;
|
|
||||||
uint8 u8Status = X509_STATUS_VALID;
|
|
||||||
|
|
||||||
if (pstrX509 != NULL) {
|
|
||||||
tstrSystemTime strExpirationDate = {0};
|
|
||||||
|
|
||||||
if (Cert_DecodeTime(pstrX509->strExpiryDate.au8Time, &strExpirationDate) == X509_SUCCESS) {
|
|
||||||
M2M_DBG("Expiration Date\n\t%d-%02d-%02d %02d:%02d:%02d\n",
|
|
||||||
strExpirationDate.u16Year, strExpirationDate.u8Month, strExpirationDate.u8Day,
|
|
||||||
strExpirationDate.u8Hour, strExpirationDate.u8Minute, strExpirationDate.u8Second);
|
|
||||||
|
|
||||||
if (strExpirationDate.u16Year != 9999) {
|
|
||||||
#ifdef WIN32
|
|
||||||
if (M2M_GetTimeOfDay(&strSystemTime) == M2M_SUCCESS) {
|
|
||||||
if (Cert_CompareTime(&strExpirationDate, &strSystemTime) <= 0) {
|
|
||||||
u8Status = X509_STATUS_EXPIRED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
u8Status = X509_STATUS_DECODE_ERR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
u8Status = X509_STATUS_DECODE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return u8Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X509Cert_Dump(void *pvCert)
|
|
||||||
{
|
|
||||||
tstrX509Cert *pstrCert = (tstrX509Cert *)pvCert;
|
|
||||||
if (pstrCert != NULL) {
|
|
||||||
#define X509_DUMP_ENABLE
|
|
||||||
#ifdef X509_DUMP_ENABLE
|
|
||||||
uint32 i;
|
|
||||||
tstrSystemTime strTime = {0};
|
|
||||||
|
|
||||||
printf("\r\n");
|
|
||||||
printf("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\r\n");
|
|
||||||
printf(" ROOT CERTIFICATE \r\n");
|
|
||||||
printf("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\r\n");
|
|
||||||
|
|
||||||
printf("VERSION %u\r\n", pstrCert->u8Version + 1);
|
|
||||||
printf("SERIAL NO ");
|
|
||||||
for (i = 0; i < pstrCert->u8SerialNumberLength; i++) {
|
|
||||||
printf("%02X ", pstrCert->au8SerialNo[i]);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("SIGNATURE ALGORITHM ");
|
|
||||||
if (pstrCert->u8SignAlg == X509_SIGN_MD5RSA) {
|
|
||||||
printf("md5WithRsaEncryption");
|
|
||||||
} else if (pstrCert->u8SignAlg == X509_SIGN_SHA1RSA) {
|
|
||||||
printf("shaWithRsaEncryption");
|
|
||||||
} else if (pstrCert->u8SignAlg == X509_SIGN_SHA256RSA) {
|
|
||||||
printf("sha256WithRsaEncryption");
|
|
||||||
} else if (pstrCert->u8SignAlg == X509_SIGN_SHA384RSA) {
|
|
||||||
printf("sha384WithRsaEncryption");
|
|
||||||
} else if (pstrCert->u8SignAlg == X509_SIGN_SHA512RSA) {
|
|
||||||
printf("sha512WithRsaEncryption");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("ISSUER ");
|
|
||||||
if (strlen(pstrCert->strIssuer.acCmnName) != 0) {
|
|
||||||
printf("%s", pstrCert->strIssuer.acCmnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("SUBJECT ");
|
|
||||||
if (strlen(pstrCert->strSubject.acCmnName) != 0) {
|
|
||||||
printf("%s", pstrCert->strSubject.acCmnName);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("VALIDITY\n");
|
|
||||||
printf(" Not Before : ");
|
|
||||||
Cert_DecodeTime(pstrCert->strStartDate.au8Time, &strTime);
|
|
||||||
printf("%d-%02d-%02d %02d:%02d:%02d\r\n",
|
|
||||||
strTime.u16Year, strTime.u8Month, strTime.u8Day,
|
|
||||||
strTime.u8Hour, strTime.u8Minute, strTime.u8Second);
|
|
||||||
|
|
||||||
printf(" Not After : ");
|
|
||||||
Cert_DecodeTime(pstrCert->strExpiryDate.au8Time, &strTime);
|
|
||||||
printf("%d-%02d-%02d %02d:%02d:%02d\r\n",
|
|
||||||
strTime.u16Year, strTime.u8Month, strTime.u8Day,
|
|
||||||
strTime.u8Hour, strTime.u8Minute, strTime.u8Second);
|
|
||||||
|
|
||||||
if (pstrCert->strPubKey.enuType == PUBKEY_ALG_RSA) {
|
|
||||||
printf("PUBLIC KEY ");
|
|
||||||
printf("RSA\n\n");
|
|
||||||
printf("\tModulus");
|
|
||||||
for (i = 0; i < pstrCert->strPubKey.strRSAKey.u16NSize; i++) {
|
|
||||||
if (!(i % 16)) {
|
|
||||||
printf("\r\n\t\t");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%02X ", pstrCert->strPubKey.strRSAKey.pu8N[i]);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("\tExponent");
|
|
||||||
for (i = 0; i < pstrCert->strPubKey.strRSAKey.u16ESize; i++) {
|
|
||||||
if (!(i % 16)) {
|
|
||||||
printf("\r\n\t\t");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%02X ", pstrCert->strPubKey.strRSAKey.pu8E[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\r\n");
|
|
||||||
|
|
||||||
printf("SIGNATURE");
|
|
||||||
for (i = 0; i < pstrCert->strSignature.u16BufferSize; i++) {
|
|
||||||
if (!(i % 16)) {
|
|
||||||
printf("\r\n\t");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%02X ", pstrCert->strSignature.pu8Data[i]);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
printf("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=\n");
|
|
||||||
#else
|
|
||||||
M2M_INFO("*=*=* X509 *=*=*\n");
|
|
||||||
M2M_INFO("\tSubject <%s>\n", ((strlen(pstrCert->strSubject.acCmnName) != 0) ? pstrCert->strSubject.acCmnName : " "));
|
|
||||||
M2M_INFO("\tIssuer <%s>\n", ((strlen(pstrCert->strIssuer.acCmnName) != 0) ? pstrCert->strIssuer.acCmnName : " "));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user