Add WINC1500 FW upload code.

This commit is contained in:
iabdalkader 2016-04-05 22:31:39 +02:00
parent dae73f6250
commit 330b41aab6
15 changed files with 3772 additions and 0 deletions

View File

@ -0,0 +1,61 @@
/**
*
* \file
*
* \brief Programmer APIs.
*
* 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 IMAGE_DOWNLOADER_H_INCLUDED
#define IMAGE_DOWNLOADER_H_INCLUDED
#include "spi_flash/include/spi_flash_map.h"
#include "spi_flash/include/spi_flash.h"
#include "programmer/programmer_apis.h"
#define ROOT_CERT_SIZE M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE
#define programmer_get_flash_size() (((spi_flash_get_size() * 1024) / 8) * 1024)
#define programmer_write(pu8Buf, u32Offset, u32Sz) spi_flash_write(pu8Buf, u32Offset, u32Sz)
#define programmer_erase(u32Offset, u32Sz) spi_flash_erase(u32Offset, u32Sz)
#define programmer_eraseall() programmer_erase(0, programmer_get_flash_size())
#define programmer_read(pu8Buf, u32Offset, u32Sz) spi_flash_read(pu8Buf, u32Offset, u32Sz)
int burn_firmware(void);
int verify_firmware(void);
int burn_certificates(void);
int verify_certificates(void);
#endif /* IMAGE_DOWNLOADER_H_INCLUDED */

View File

@ -0,0 +1,56 @@
/**
*
* \file
*
* \brief Programmer APIs.
*
* 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 FIRMWARE_PROGRAMMER_APIS_H_INCLUDED
#define FIRMWARE_PROGRAMMER_APIS_H_INCLUDED
#include "common/include/nm_common.h"
#include "spi_flash/include/spi_flash_map.h"
#define programmer_write_cert_image(buff) programmer_write((uint8*)buff, M2M_TLS_FLASH_ROOTCERT_CACHE_OFFSET, M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE)
#define programmer_read_cert_image(buff) programmer_read((uint8*)buff, M2M_TLS_FLASH_ROOTCERT_CACHE_OFFSET, M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE)
#define programmer_erase_cert_image() programmer_erase(M2M_TLS_FLASH_ROOTCERT_CACHE_OFFSET, M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE)
#define programmer_write_firmware_image(buff,offSet,sz) programmer_write((uint8*)buff, offSet, sz)
#define programmer_read_firmware_image(buff,offSet,sz) programmer_read((uint8*)buff, offSet, sz)
#define programmer_erase_all() programmer_erase(0, programmer_get_flash_size())
#endif /* FIRMWARE_PROGRAMMER_APIS_H_INCLUDED */

View File

@ -0,0 +1,49 @@
/**
*
* \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

@ -0,0 +1,84 @@
/**
*
* \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

@ -0,0 +1,101 @@
/**
*
* \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

@ -0,0 +1,112 @@
/**
*
* \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

@ -0,0 +1,177 @@
/**
*
* \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

@ -0,0 +1,223 @@
/**
*
* \file
*
* \brief WINC1500 SPI Flash.
*
* 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
*
*/
/** \defgroup SPIFLASH Spi Flash
* @file spi_flash.h
* @brief This file describe SPI flash APIs, how to use it and limitations with each one.
* @section Example
* This example illustrates a complete guide of how to use these APIs.
* @code{.c}
#include "spi_flash.h"
#define DATA_TO_REPLACE "THIS IS A NEW SECTOR IN FLASH"
int main()
{
uint8 au8FlashContent[FLASH_SECTOR_SZ] = {0};
uint32 u32FlashTotalSize = 0;
uint32 u32FlashOffset = 0;
ret = m2m_wifi_download_mode();
if(M2M_SUCCESS != ret)
{
printf("Unable to enter download mode\r\n");
}
else
{
u32FlashTotalSize = spi_flash_get_size();
}
while((u32FlashTotalSize > u32FlashOffset) && (M2M_SUCCESS == ret))
{
ret = spi_flash_read(au8FlashContent, u32FlashOffset, FLASH_SECTOR_SZ);
if(M2M_SUCCESS != ret)
{
printf("Unable to read SPI sector\r\n");
break;
}
memcpy(au8FlashContent, DATA_TO_REPLACE, strlen(DATA_TO_REPLACE));
ret = spi_flash_erase(u32FlashOffset, FLASH_SECTOR_SZ);
if(M2M_SUCCESS != ret)
{
printf("Unable to erase SPI sector\r\n");
break;
}
ret = spi_flash_write(au8FlashContent, u32FlashOffset, FLASH_SECTOR_SZ);
if(M2M_SUCCESS != ret)
{
printf("Unable to write SPI sector\r\n");
break;
}
u32FlashOffset += FLASH_SECTOR_SZ;
}
if(M2M_SUCCESS == ret)
{
printf("Successful operations\r\n");
}
else
{
printf("Failed operations\r\n");
}
while(1);
return M2M_SUCCESS;
}
* @endcode
*/
#ifndef __SPI_FLASH_H__
#define __SPI_FLASH_H__
#include "common/include/nm_common.h"
#include "bus_wrapper/include/nm_bus_wrapper.h"
#include "driver/include/nmbus.h"
#include "driver/include/nmasic.h"
#include "spi_flash/include/spi_flash_map.h"
/**
* @fn spi_flash_enable
* @brief Enable spi flash operations
* @version 1.0
*/
sint8 spi_flash_enable(uint8 enable);
/** \defgroup SPIFLASHAPI Function
* @ingroup SPIFLASH
*/
/** @defgroup SPiFlashGetFn spi_flash_get_size
* @ingroup SPIFLASHAPI
*/
/**@{*/
/*!
* @fn uint32 spi_flash_get_size(void);
* @brief Returns with \ref uint32 value which is total flash size\n
* @note Returned value in Mb (Mega Bit).
* @return SPI flash size in case of success and a ZERO value in case of failure.
*/
uint32 spi_flash_get_size(void);
/**@}*/
/** @defgroup SPiFlashRead spi_flash_read
* @ingroup SPIFLASHAPI
*/
/**@{*/
/*!
* @fn sint8 spi_flash_read(uint8 *, uint32, uint32);
* @brief Read a specified portion of data from SPI Flash.\n
* @param [out] pu8Buf
* Pointer to data buffer which will fill in with data in case of successful operation.
* @param [in] u32Addr
* Address (Offset) to read from at the SPI flash.
* @param [in] u32Sz
* Total size of data to be read in bytes
* @warning
* - Address (offset) plus size of data must not exceed flash size.\n
* - No firmware is required for reading from SPI flash.\n
* - In case of there is a running firmware, it is required to pause your firmware first
* before any trial to access SPI flash to avoid any racing between host and running firmware on bus using
* @ref m2m_wifi_download_mode
* @note
* - It is blocking function\n
* @sa m2m_wifi_download_mode, spi_flash_get_size
* @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise.
*/
sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz);
/**@}*/
/** @defgroup SPiFlashWrite spi_flash_write
* @ingroup SPIFLASHAPI
*/
/**@{*/
/*!
* @fn sint8 spi_flash_write(uint8 *, uint32, uint32);
* @brief Write a specified portion of data to SPI Flash.\n
* @param [in] pu8Buf
* Pointer to data buffer which contains the required to be written.
* @param [in] u32Offset
* Address (Offset) to write at the SPI flash.
* @param [in] u32Sz
* Total number of size of data bytes
* @note
* - It is blocking function\n
* - It is user's responsibility to verify that data has been written successfully
* by reading data again and compare it with the original.
* @warning
* - Address (offset) plus size of data must not exceed flash size.\n
* - No firmware is required for writing to SPI flash.\n
* - In case of there is a running firmware, it is required to pause your firmware first
* before any trial to access SPI flash to avoid any racing between host and running firmware on bus using
* @ref m2m_wifi_download_mode.
* - Before writing to any section, it is required to erase it first.
* @sa m2m_wifi_download_mode, spi_flash_get_size, spi_flash_erase
* @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise.
*/
sint8 spi_flash_write(uint8* pu8Buf, uint32 u32Offset, uint32 u32Sz);
/**@}*/
/** @defgroup SPiFlashErase spi_flash_erase
* @ingroup SPIFLASHAPI
*/
/**@{*/
/*!
* @fn sint8 spi_flash_erase(uint32, uint32);
* @brief Erase a specified portion of SPI Flash.\n
* @param [in] u32Offset
* Address (Offset) to erase from the SPI flash.
* @param [in] u32Sz
* Size of SPI flash required to be erased.
* @note It is blocking function \n
* @warning
* - Address (offset) plus size of data must not exceed flash size.\n
* - No firmware is required for writing to SPI flash.\n
* - In case of there is a running firmware, it is required to pause your firmware first
* before any trial to access SPI flash to avoid any racing between host and running firmware on bus using
* @ref m2m_wifi_download_mode
* - It is blocking function\n
* @sa m2m_wifi_download_mode, spi_flash_get_size
* @return The function returns @ref M2M_SUCCESS for successful operations and a negative value otherwise.
*/
sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz);
/**@}*/
#endif //__SPI_FLASH_H__

View File

@ -0,0 +1,230 @@
/**
*
* \file
*
* \brief SPI Flash Memory Mapping.
*
* 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 SPI_FLASH_MAP_H_INCLUDED
#define SPI_FLASH_MAP_H_INCLUDED
#define FLASH_MAP_VER_0 (0)
#define FLAAH_MAP_VER_1 (1)
#define FLASH_MAP_VERSION FLAAH_MAP_VER_1
//#define DOWNLOAD_ROLLBACK
//#define OTA_GEN
#define _PROGRAM_POWER_SAVE_
/* =======*=======*=======*=======*=======
* General Sizes for Flash Memory
* =======*=======*=======*=======*=======
*/
#define FLASH_START_ADDR (0UL)
/*!<Starting Address of Flash Memory
*
*/
#define FLASH_BLOCK_SIZE (32 * 1024UL)
/*!<Block Size in Flash Memory
*/
#define FLASH_SECTOR_SZ (4 * 1024UL)
/*!<Sector Size in Flash Memory
*/
#define FLASH_PAGE_SZ (256)
/*!<Page Size in Flash Memory
*/
#define FLASH_2M_TOTAL_SZ (256 * 1024UL)
/*!<Total Size of 2M Flash Memory
*/
#define FLASH_4M_TOTAL_SZ (512 * 1024UL)
/*!<Total Size of 4M Flash Memory
*/
#define FLASH_8M_TOTAL_SZ (1024 * 1024UL)
/*!<Total Size of 8M Flash Memory
*/
/*
* Detailed Sizes and locations for Flash Memory:
* ____________________ ___________ ___________________________ _______________________________________________
* | Starting Address | Size | Location's Name | Description |
* |____________________|___________|___________________________|_______________________________________________|
* | 0 K | 4 K | Boot Firmware | Firmware to select which version to run |
* | 4 K | 8 K | Control Section | Structured data used by Boot firmware |
* | 12 K | 4 K | PLL+GAIN : | LookUp Table for PLL and Gain calculations |
* | | | PLL Size = 1K | PLL |
* | | | GAIN Size = 3K | Gain configuration |
* | 16 K | 4 K | CERTIFICATE | X.509 Certificate storage |
* | 20 K | 4 K | Scratch Section | Empty Section |
* | 24 K | 4 K | Reserved TLS Server | Reserved |
* | 28 K | 8 K | HTTP Files | Files used with Provisioning Mode |
* | 36 K | 4 K | Connection Parameters | Parameters for success connection to AP |
* | 40 K | 236 K | Main Firmware/program | Main Firmware to run WiFi Chip |
* | 276 K | 236 K | OTA Firmware | OTA firmware |
* | 512 K Total flash size |
* |____________________|___________|___________________________|_______________________________________________|
*
*
* *Keys for Comments with each MACRO:
* "L:xxxK" -means-> location :xxxK
* "S:xxxK" -means-> Size is :xxxK
*/
/*
* Boot Firmware: which used to select which firmware to run
*
*/
#define M2M_BOOT_FIRMWARE_STARTING_ADDR (FLASH_START_ADDR)
#define M2M_BOOT_FIRMWARE_FLASH_SZ (FLASH_SECTOR_SZ)
/*
* Control Section: which used by Boot firmware
*
*/
#define M2M_CONTROL_FLASH_OFFSET (M2M_BOOT_FIRMWARE_STARTING_ADDR + M2M_BOOT_FIRMWARE_FLASH_SZ)
#define M2M_CONTROL_FLASH_BKP_OFFSET (M2M_CONTROL_FLASH_OFFSET + FLASH_SECTOR_SZ)
#define M2M_CONTROL_FLASH_SEC_SZ (FLASH_SECTOR_SZ)
#define M2M_CONTROL_FLASH_TOTAL_SZ (FLASH_SECTOR_SZ * 2)
/*
* LUT for PLL and TX Gain settings:
*
*/
#define M2M_PLL_FLASH_OFFSET (M2M_CONTROL_FLASH_OFFSET + M2M_CONTROL_FLASH_TOTAL_SZ)
#define M2M_PLL_FLASH_SZ (1024 * 1)
#define M2M_GAIN_FLASH_OFFSET (M2M_PLL_FLASH_OFFSET + M2M_PLL_FLASH_SZ)
#define M2M_GAIN_FLASH_SZ (M2M_CONFIG_SECT_TOTAL_SZ - M2M_PLL_FLASH_SZ)
#define M2M_CONFIG_SECT_TOTAL_SZ (FLASH_SECTOR_SZ)
/*
* Certificate:
*
*/
#define M2M_TLS_FLASH_ROOTCERT_CACHE_OFFSET (M2M_PLL_FLASH_OFFSET + M2M_CONFIG_SECT_TOTAL_SZ)
#define M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE (FLASH_SECTOR_SZ * 1)
/*
* Scratch:
*
*/
#define M2M_TLS_FLASH_SESSION_CACHE_OFFSET (M2M_TLS_FLASH_ROOTCERT_CACHE_OFFSET + M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE)
#define M2M_TLS_FLASH_SESSION_CACHE_SIZE (FLASH_SECTOR_SZ * 1)
/*
* reserved section
*
*/
#define M2M_RESERVED_FLASH_OFFSET (M2M_TLS_FLASH_SESSION_CACHE_OFFSET + M2M_TLS_FLASH_SESSION_CACHE_SIZE)
#define M2M_RESERVED_FLASH_SZ (FLASH_SECTOR_SZ * 1)
/*
* HTTP Files
*
*/
#define M2M_HTTP_MEM_FLASH_OFFSET (M2M_RESERVED_FLASH_OFFSET + M2M_RESERVED_FLASH_SZ)
#define M2M_HTTP_MEM_FLASH_SZ (FLASH_SECTOR_SZ * 2)
/*
* Saved Connection Parameters:
*
*/
#define M2M_CACHED_CONNS_FLASH_OFFSET (M2M_HTTP_MEM_FLASH_OFFSET + M2M_HTTP_MEM_FLASH_SZ)
#define M2M_CACHED_CONNS_FLASH_SZ (FLASH_SECTOR_SZ * 1)
/*
*
* Common section size
*/
#define M2M_COMMON_DATA_SEC (M2M_BOOT_FIRMWARE_FLASH_SZ + M2M_CONTROL_FLASH_TOTAL_SZ + M2M_CONFIG_SECT_TOTAL_SZ + \
M2M_TLS_FLASH_ROOTCERT_CACHE_SIZE + M2M_TLS_FLASH_SESSION_CACHE_SIZE + \
M2M_HTTP_MEM_FLASH_SZ + M2M_CACHED_CONNS_FLASH_SZ + M2M_RESERVED_FLASH_SZ)
/*
*
* OTA image1 Offset
*/
#define M2M_OTA_IMAGE1_OFFSET (M2M_CACHED_CONNS_FLASH_OFFSET + M2M_CACHED_CONNS_FLASH_SZ)
/*
* Firmware Offset
*
*/
#if (defined _FIRMWARE_)||(defined OTA_GEN)
#define M2M_FIRMWARE_FLASH_OFFSET (0UL)
#else
#if (defined DOWNLOAD_ROLLBACK)
#define M2M_FIRMWARE_FLASH_OFFSET (M2M_OTA_IMAGE2_OFFSET)
#else
#define M2M_FIRMWARE_FLASH_OFFSET (M2M_OTA_IMAGE1_OFFSET)
#endif
#endif
/*
*
* Firmware
*/
#define M2M_FIRMWARE_FLASH_SZ (236*1024UL)
/**
*
* OTA image Size
*/
#define OTA_IMAGE_SIZE (M2M_FIRMWARE_FLASH_SZ)
/**
*
* Flash Total size
*/
#define FLASH_IMAGE1_CONTENT_SZ (M2M_COMMON_DATA_SEC + OTA_IMAGE_SIZE)
/**
*
* OTA image 2 offset
*/
#define M2M_OTA_IMAGE2_OFFSET (FLASH_IMAGE1_CONTENT_SZ)
/*
* App(Cortus App 4M): App. which runs over firmware
*
*/
#define M2M_APP_4M_MEM_FLASH_SZ (FLASH_SECTOR_SZ * 10)
#define M2M_APP_4M_MEM_FLASH_OFFSET (FLASH_4M_TOTAL_SZ - M2M_APP_4M_MEM_FLASH_SZ)
/* Check if total size of content
* don't exceed total size of memory allowed
**/
#if (M2M_COMMON_DATA_SEC + (OTA_IMAGE_SIZE *2)> FLASH_4M_TOTAL_SZ)
#error "Excced 4M Flash Size"
#endif /* (FLASH_CONTENT_SZ > FLASH_TOTAL_SZ) */
#endif /* SPI_FLASH_MAP_H_INCLUDED */

120
src/winc1500/src/asn1.c Normal file
View File

@ -0,0 +1,120 @@
/**
*
* \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;
}

527
src/winc1500/src/hash.c Normal file
View File

@ -0,0 +1,527 @@
/**
*
* \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

@ -0,0 +1,194 @@
#include <ff.h>
#include <stdio.h>
#include "fb_alloc.h"
#include "programmer/programmer.h"
#include "root_cert/root_setup.h"
#include "spi_flash/include/spi_flash_map.h"
#define FW_PATH "/firmware/bin/m2m_aio_3a0.bin"
#define CERT_DIGI_PATH "/firmware/cert/DigiCert_Root.cer"
#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) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
/**
* Program firmware to WINC1500 memory.
*
* return M2M_SUCCESS on success, error code otherwise.
*/
int burn_firmware()
{
FIL fp;
uint32_t offset = 0;
UINT bytes = 0, bytes_out=0;
int ret = M2M_ERR_FAIL;
uint8_t *buf = fb_alloc(FLASH_SECTOR_SZ);
if (f_open(&fp, FW_PATH, FA_READ|FA_OPEN_EXISTING) != FR_OK) {
goto error;
}
// Firmware image size
uint32_t size = f_size(&fp);
while (size) {
// Read a chuck (max FLASH_SECTOR_SZ bytes).
bytes = MIN(size, FLASH_SECTOR_SZ);
if (f_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes != bytes_out) {
printf("burn_firmware: file read error!\n");
goto error;
}
// Write firmware sector to the WINC1500 memory.
if (programmer_write_firmware_image(buf, offset, bytes) != M2M_SUCCESS) {
printf("burn_firmware: write error!\n");
goto error;
}
size -= bytes;
offset += bytes;
}
ret = M2M_SUCCESS;
error:
fb_free();
f_close(&fp);
return ret;
}
/**
* Verify WINC1500 firmware
* return M2M_SUCCESS on success, error code otherwise.
*/
int verify_firmware()
{
FIL fp;
uint32_t offset = 0;
UINT bytes = 0, bytes_out=0;
int ret = M2M_ERR_FAIL;
uint8_t *file_buf = fb_alloc(FLASH_SECTOR_SZ);
uint8_t *flash_buf = fb_alloc(FLASH_SECTOR_SZ);
if (f_open(&fp, FW_PATH, FA_READ|FA_OPEN_EXISTING) != FR_OK) {
goto error;
}
// Firmware image size
uint32_t size = f_size(&fp);
while (size) {
// Firmware chuck size (max FLASH_SECTOR_SZ bytes).
bytes = MIN(size, FLASH_SECTOR_SZ);
if (f_read(&fp, file_buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) {
printf("burn_firmware: file read error!\n");
goto error;
}
if (programmer_read_firmware_image(flash_buf, offset, bytes) != M2M_SUCCESS) {
printf("verify_firmware: read access failed on firmware section!\r\n");
return M2M_ERR_FAIL;
}
for (int i=0; i<bytes; i++) {
if (flash_buf[i] != file_buf[i]) {
printf("verify_firmware: verification failed! offset:%d flash:%x file:%x\n", i, flash_buf[i], file_buf[i]);
return M2M_ERR_FAIL;
}
}
size -= bytes;
offset += bytes;
}
ret = M2M_SUCCESS;
error:
fb_free();
fb_free();
f_close(&fp);
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(2048);
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;
}
#if 0
/**
* Verify WINC1500 certificates
* return M2M_SUCCESS on success, error code otherwise.
*/
int verify_certificate(void)
{
uint8_t flash_content[FLASH_SECTOR_SZ] = {0};
/* Dump entire root certificate memory region. */
if (programmer_read_cert_image(flash_content) != M2M_SUCCESS) {
printf("verify_certificate: read access failed on certificate section!\r\n");
return M2M_ERR_FAIL;
}
return M2M_SUCCESS;
}
#endif

View File

@ -0,0 +1,253 @@
/**
*
* \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

@ -0,0 +1,690 @@
/**
*
* \file
*
* \brief WINC1500 SPI Flash.
*
* 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 "spi_flash/include/spi_flash.h"
#define DUMMY_REGISTER (0x1084)
#define HOST_SHARE_MEM_BASE (0xd0000UL)
#define CORTUS_SHARE_MEM_BASE (0x60000000UL)
#define NMI_SPI_FLASH_ADDR (0x111c)
/***********************************************************
SPI Flash DMA
***********************************************************/
#define GET_UINT32(X,Y) (X[0+Y] + ((uint32)X[1+Y]<<8) + ((uint32)X[2+Y]<<16) +((uint32)X[3+Y]<<24))
#define SPI_FLASH_BASE (0x10200)
#define SPI_FLASH_MODE (SPI_FLASH_BASE + 0x00)
#define SPI_FLASH_CMD_CNT (SPI_FLASH_BASE + 0x04)
#define SPI_FLASH_DATA_CNT (SPI_FLASH_BASE + 0x08)
#define SPI_FLASH_BUF1 (SPI_FLASH_BASE + 0x0c)
#define SPI_FLASH_BUF2 (SPI_FLASH_BASE + 0x10)
#define SPI_FLASH_BUF_DIR (SPI_FLASH_BASE + 0x14)
#define SPI_FLASH_TR_DONE (SPI_FLASH_BASE + 0x18)
#define SPI_FLASH_DMA_ADDR (SPI_FLASH_BASE + 0x1c)
#define SPI_FLASH_MSB_CTL (SPI_FLASH_BASE + 0x20)
#define SPI_FLASH_TX_CTL (SPI_FLASH_BASE + 0x24)
/*********************************************/
/* STATIC FUNCTIONS */
/*********************************************/
/**
* @fn spi_flash_read_status_reg
* @brief Read status register
* @param[OUT] val
value of status reg
* @return Status of execution
*/
static sint8 spi_flash_read_status_reg(uint8 * val)
{
sint8 ret = M2M_SUCCESS;
uint8 cmd[1];
uint32 reg;
cmd[0] = 0x05;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
if(M2M_SUCCESS != ret) break;
}
while(reg != 1);
reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
*val = (uint8)(reg & 0xff);
return ret;
}
#ifdef DISABLE_UNSED_FLASH_FUNCTIONS
/**
* @fn spi_flash_read_security_reg
* @brief Read security register
* @return Security register value
*/
static uint8 spi_flash_read_security_reg(void)
{
uint8 cmd[1];
uint32 reg;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x2b;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 1);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
if(M2M_SUCCESS != ret) break;
}
while(reg != 1);
reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
return (sint8)reg & 0xff;
}
/**
* @fn spi_flash_gang_unblock
* @brief Unblock all flash area
*/
static sint8 spi_flash_gang_unblock(void)
{
uint8 cmd[1];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x98;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_clear_security_flags
* @brief Clear all security flags
*/
static sint8 spi_flash_clear_security_flags(void)
{
uint8 cmd[1];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x30;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
#endif
/**
* @fn spi_flash_load_to_cortus_mem
* @brief Load data from SPI flash into cortus memory
* @param[IN] u32MemAdr
* Cortus load address. It must be set to its AHB access address
* @param[IN] u32FlashAdr
* Address to read from at the SPI flash
* @param[IN] u32Sz
* Data size
* @return Status of execution
*/
static sint8 spi_flash_load_to_cortus_mem(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
{
uint8 cmd[5];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x0b;
cmd[1] = (uint8)(u32FlashAdr >> 16);
cmd[2] = (uint8)(u32FlashAdr >> 8);
cmd[3] = (uint8)(u32FlashAdr);
cmd[4] = 0xA5;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, u32Sz);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
ret += nm_write_reg(SPI_FLASH_BUF2, cmd[4]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1f);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 5 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_sector_erase
* @brief Erase sector (4KB)
* @param[IN] u32FlashAdr
* Any memory address within the sector
* @return Status of execution
*/
static sint8 spi_flash_sector_erase(uint32 u32FlashAdr)
{
uint8 cmd[4];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x20;
cmd[1] = (uint8)(u32FlashAdr >> 16);
cmd[2] = (uint8)(u32FlashAdr >> 8);
cmd[3] = (uint8)(u32FlashAdr);
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_write_enable
* @brief Send write enable command to SPI flash
* @return Status of execution
*/
static sint8 spi_flash_write_enable(void)
{
uint8 cmd[1];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x06;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_write_disable
* @brief Send write disable command to SPI flash
*/
static sint8 spi_flash_write_disable(void)
{
uint8 cmd[1];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x04;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x01);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_page_program
* @brief Write data (less than page size) from cortus memory to SPI flash
* @param[IN] u32MemAdr
* Cortus data address. It must be set to its AHB access address
* @param[IN] u32FlashAdr
* Address to write to at the SPI flash
* @param[IN] u32Sz
* Data size
*/
static sint8 spi_flash_page_program(uint32 u32MemAdr, uint32 u32FlashAdr, uint32 u32Sz)
{
uint8 cmd[4];
uint32 val = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x02;
cmd[1] = (uint8)(u32FlashAdr >> 16);
cmd[2] = (uint8)(u32FlashAdr >> 8);
cmd[3] = (uint8)(u32FlashAdr);
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 0);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]|(cmd[1]<<8)|(cmd[2]<<16)|(cmd[3]<<24));
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x0f);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, u32MemAdr);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 4 | (1<<7) | ((u32Sz & 0xfffff) << 8));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&val);
if(M2M_SUCCESS != ret) break;
}
while(val != 1);
return ret;
}
/**
* @fn spi_flash_read_internal
* @brief Read from data from SPI flash
* @param[OUT] pu8Buf
* Pointer to data buffer
* @param[IN] u32Addr
* Address to read from at the SPI flash
* @param[IN] u32Sz
* Data size
*/
static sint8 spi_flash_read_internal(uint8 *pu8Buf, uint32 u32Addr, uint32 u32Sz)
{
sint8 ret = M2M_SUCCESS;
/* read size must be < 64KB */
ret = spi_flash_load_to_cortus_mem(HOST_SHARE_MEM_BASE, u32Addr, u32Sz);
if(M2M_SUCCESS != ret) goto ERR;
ret = nm_read_block(HOST_SHARE_MEM_BASE, pu8Buf, u32Sz);
ERR:
return ret;
}
/**
* @fn spi_flash_pp
* @brief Program data of size less than a page (256 bytes) at the SPI flash
* @param[IN] u32Offset
* Address to write to at the SPI flash
* @param[IN] pu8Buf
* Pointer to data buffer
* @param[IN] u32Sz
* Data size
* @return Status of execution
*/
static sint8 spi_flash_pp(uint32 u32Offset, uint8 *pu8Buf, uint16 u16Sz)
{
sint8 ret = M2M_SUCCESS;
uint8 tmp;
spi_flash_write_enable();
/* use shared packet memory as temp mem */
ret += nm_write_block(HOST_SHARE_MEM_BASE, pu8Buf, u16Sz);
ret += spi_flash_page_program(HOST_SHARE_MEM_BASE, u32Offset, u16Sz);
ret += spi_flash_read_status_reg(&tmp);
do
{
if(ret != M2M_SUCCESS) goto ERR;
ret += spi_flash_read_status_reg(&tmp);
}while(tmp & 0x01);
ret += spi_flash_write_disable();
ERR:
return ret;
}
/**
* @fn spi_flash_rdid
* @brief Read SPI Flash ID
* @return SPI FLash ID
*/
static uint32 spi_flash_rdid(void)
{
unsigned char cmd[1];
uint32 reg = 0;
uint32 cnt = 0;
sint8 ret = M2M_SUCCESS;
cmd[0] = 0x9f;
ret += nm_write_reg(SPI_FLASH_DATA_CNT, 4);
ret += nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
ret += nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
ret += nm_write_reg(SPI_FLASH_DMA_ADDR, DUMMY_REGISTER);
ret += nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1<<7));
do
{
ret += nm_read_reg_with_ret(SPI_FLASH_TR_DONE, (uint32 *)&reg);
if(M2M_SUCCESS != ret) break;
if(++cnt > 500)
{
ret = M2M_ERR_INIT;
break;
}
}
while(reg != 1);
reg = (M2M_SUCCESS == ret)?(nm_read_reg(DUMMY_REGISTER)):(0);
M2M_PRINT("Flash ID %x \n",(unsigned int)reg);
return reg;
}
/**
* @fn spi_flash_unlock
* @brief Unlock SPI Flash
*/
#if 0
static void spi_flash_unlock(void)
{
uint8 tmp;
tmp = spi_flash_read_security_reg();
spi_flash_clear_security_flags();
if(tmp & 0x80)
{
spi_flash_write_enable();
spi_flash_gang_unblock();
}
}
#endif
static void spi_flash_enter_low_power_mode(void) {
volatile unsigned long tmp;
unsigned char* cmd = (unsigned char*) &tmp;
cmd[0] = 0xb9;
nm_write_reg(SPI_FLASH_DATA_CNT, 0);
nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
while(nm_read_reg(SPI_FLASH_TR_DONE) != 1);
}
static void spi_flash_leave_low_power_mode(void) {
volatile unsigned long tmp;
unsigned char* cmd = (unsigned char*) &tmp;
cmd[0] = 0xab;
nm_write_reg(SPI_FLASH_DATA_CNT, 0);
nm_write_reg(SPI_FLASH_BUF1, cmd[0]);
nm_write_reg(SPI_FLASH_BUF_DIR, 0x1);
nm_write_reg(SPI_FLASH_DMA_ADDR, 0);
nm_write_reg(SPI_FLASH_CMD_CNT, 1 | (1 << 7));
while(nm_read_reg(SPI_FLASH_TR_DONE) != 1);
}
/*********************************************/
/* GLOBAL FUNCTIONS */
/*********************************************/
/**
* @fn spi_flash_enable
* @brief Enable spi flash operations
*/
sint8 spi_flash_enable(uint8 enable)
{
sint8 s8Ret = M2M_SUCCESS;
if(REV(nmi_get_chipid()) >= REV_3A0) {
uint32 u32Val;
/* Enable pinmux to SPI flash. */
s8Ret = nm_read_reg_with_ret(0x1410, &u32Val);
if(s8Ret != M2M_SUCCESS) {
goto ERR1;
}
/* GPIO15/16/17/18 */
u32Val &= ~((0x7777ul) << 12);
u32Val |= ((0x1111ul) << 12);
nm_write_reg(0x1410, u32Val);
if(enable) {
spi_flash_leave_low_power_mode();
} else {
spi_flash_enter_low_power_mode();
}
/* Disable pinmux to SPI flash to minimize leakage. */
u32Val &= ~((0x7777ul) << 12);
u32Val |= ((0x0010ul) << 12);
nm_write_reg(0x1410, u32Val);
}
ERR1:
return s8Ret;
}
/**
* @fn spi_flash_read
* @brief Read from data from SPI flash
* @param[OUT] pu8Buf
* Pointer to data buffer
* @param[IN] u32offset
* Address to read from at the SPI flash
* @param[IN] u32Sz
* Data size
* @return Status of execution
* @note Data size is limited by the SPI flash size only
*/
sint8 spi_flash_read(uint8 *pu8Buf, uint32 u32offset, uint32 u32Sz)
{
sint8 ret = M2M_SUCCESS;
if(u32Sz > FLASH_BLOCK_SIZE)
{
do
{
ret = spi_flash_read_internal(pu8Buf, u32offset, FLASH_BLOCK_SIZE);
if(M2M_SUCCESS != ret) goto ERR;
u32Sz -= FLASH_BLOCK_SIZE;
u32offset += FLASH_BLOCK_SIZE;
pu8Buf += FLASH_BLOCK_SIZE;
} while(u32Sz > FLASH_BLOCK_SIZE);
}
ret = spi_flash_read_internal(pu8Buf, u32offset, u32Sz);
ERR:
return ret;
}
/**
* @fn spi_flash_write
* @brief Proram SPI flash
* @param[IN] pu8Buf
* Pointer to data buffer
* @param[IN] u32Offset
* Address to write to at the SPI flash
* @param[IN] u32Sz
* Data size
* @return Status of execution
*/
sint8 spi_flash_write(uint8* pu8Buf, uint32 u32Offset, uint32 u32Sz)
{
#ifdef PROFILING
uint32 t1 = 0;
uint32 percent =0;
uint32 tpercent =0;
#endif
sint8 ret = M2M_SUCCESS;
uint32 u32wsz;
uint32 u32off;
uint32 u32Blksz;
u32Blksz = FLASH_PAGE_SZ;
u32off = u32Offset % u32Blksz;
#ifdef PROFILING
tpercent = (u32Sz/u32Blksz)+((u32Sz%u32Blksz)>0);
t1 = GetTickCount();
M2M_PRINT(">Start programming...\r\n");
#endif
if(u32Sz<=0)
{
M2M_ERR("Data size = %d",(int)u32Sz);
ret = M2M_ERR_FAIL;
goto ERR;
}
if (u32off)/*first part of data in the address page*/
{
u32wsz = u32Blksz - u32off;
if(spi_flash_pp(u32Offset, pu8Buf, (uint16)BSP_MIN(u32Sz, u32wsz))!=M2M_SUCCESS)
{
ret = M2M_ERR_FAIL;
goto ERR;
}
if (u32Sz < u32wsz) goto EXIT;
pu8Buf += u32wsz;
u32Offset += u32wsz;
u32Sz -= u32wsz;
}
while (u32Sz > 0)
{
u32wsz = BSP_MIN(u32Sz, u32Blksz);
/*write complete page or the remaining data*/
if(spi_flash_pp(u32Offset, pu8Buf, (uint16)u32wsz)!=M2M_SUCCESS)
{
ret = M2M_ERR_FAIL;
goto ERR;
}
pu8Buf += u32wsz;
u32Offset += u32wsz;
u32Sz -= u32wsz;
#ifdef PROFILING
percent++;
printf("\r>Complete Percentage = %d%%.\r",((percent*100)/tpercent));
#endif
}
EXIT:
#ifdef PROFILING
M2M_PRINT("\rDone\t\t\t\t\t\t");
M2M_PRINT("\n#Programming time = %f sec\n\r",(GetTickCount() - t1)/1000.0);
#endif
ERR:
return ret;
}
/**
* @fn spi_flash_erase
* @brief Erase from data from SPI flash
* @param[IN] u32Offset
* Address to write to at the SPI flash
* @param[IN] u32Sz
* Data size
* @return Status of execution
* @note Data size is limited by the SPI flash size only
*/
sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz)
{
uint32 i = 0;
sint8 ret = M2M_SUCCESS;
uint8 tmp = 0;
#ifdef PROFILING
uint32 t;
t = GetTickCount();
#endif
M2M_PRINT("\r\n>Start erasing...\r\n");
for(i = u32Offset; i < (u32Sz +u32Offset); i += (16*FLASH_PAGE_SZ))
{
ret += spi_flash_write_enable();
ret += spi_flash_read_status_reg(&tmp);
ret += spi_flash_sector_erase(i + 10);
ret += spi_flash_read_status_reg(&tmp);
do
{
if(ret != M2M_SUCCESS) goto ERR;
ret += spi_flash_read_status_reg(&tmp);
}while(tmp & 0x01);
}
M2M_PRINT("Done\r\n");
#ifdef PROFILING
M2M_PRINT("#Erase time = %f sec\n", (GetTickCount()-t)/1000.0);
#endif
ERR:
return ret;
}
/**
* @fn spi_flash_get_size
* @brief Get size of SPI Flash
* @return Size of Flash
*/
uint32 spi_flash_get_size(void)
{
uint32 u32FlashId = 0, u32FlashPwr = 0;
static uint32 gu32InernalFlashSize= 0;
if(!gu32InernalFlashSize)
{
u32FlashId = spi_flash_rdid();//spi_flash_probe();
if(u32FlashId != 0xffffffff)
{
/*flash size is the third byte from the FLASH RDID*/
u32FlashPwr = ((u32FlashId>>16)&0xff) - 0x11; /*2MBIT is the min*/
/*That number power 2 to get the flash size*/
gu32InernalFlashSize = 1<<u32FlashPwr;
M2M_INFO("Flash Size %lu Mb\n",gu32InernalFlashSize);
}
else
{
M2M_ERR("Cann't Detect Flash size\n");
}
}
return gu32InernalFlashSize;
}

View File

@ -0,0 +1,895 @@
/**
*
* \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
}
}