Fix WINC's FW update.

* Remove unused WINC code.
* Replace WINC fw update process with a single fw image.
This commit is contained in:
iabdalkader 2016-04-06 02:32:50 +02:00
parent f841828818
commit 37c8587333
12 changed files with 5 additions and 2418 deletions

View File

@ -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;
} }

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
}
}