--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#ifndef _BYTE_ARRAY_H_
+#define _BYTE_ARRAY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+/**
+ * @struct ByteArray
+ *
+ * General purpose byte array structure.
+ *
+ * Contains pointer to array of bytes and it's length.
+ */
+
+typedef struct
+{
+ uint8_t *data; /**< Pointer to the byte array */
+ size_t len; /**< Data size */
+} ByteArray;
+
+
+/**@def BYTE_ARRAY_INITIALIZER
+ *
+ * Initializes of existing byte array pointer to \a NULL.
+ */
+#undef BYTE_ARRAY_INITIALIZER
+#define BYTE_ARRAY_INITIALIZER {NULL, 0}
+
+/**@def INIT_BYTE_ARRAY(array)
+ *
+ * Initializes of existing byte array \a array.
+ *
+ * @param array ByteArray
+ */
+#undef INIT_BYTE_ARRAY
+#define INIT_BYTE_ARRAY(array) do{ \
+ (array).data = NULL; \
+ (array).len = 0; \
+ }while(0)
+
+/**@def PRINT_BYTE_ARRAY(msg, array)
+ *
+ * Prints out byte array \a array in hex representation with message \a msg.
+ *
+ * @param msg string of characters
+ * @param array byte array
+ */
+#undef PRINT_BYTE_ARRAY
+#define PRINT_BYTE_ARRAY(msg, array) do{ \
+ size_t i; \
+ printf("%10s", msg); \
+ for( i=0; i< (array).len; i++) { \
+ if( (i!=0) && ((i%16)==0) ) putchar('\n'); \
+ printf("%02X ", (array).data[i]); \
+ } \
+ putchar('\n'); \
+ }while(0)
+
+/**@def INC_BYTE_ARRAY_PTR(array, size)
+ *
+ * Increments byte array pointer \a array by \a size.
+ *
+ * @param array byte array pointer
+ * @param size number of positions
+ */
+#undef INC_BYTE_ARRAY_PTR
+#define INC_BYTE_ARRAY_PTR(array, size) do{ \
+ (array)->data += size; \
+ (array)->len -= size; \
+ }while(0)
+
+/**@def INC_BYTE_ARRAY(array, size)
+ *
+ * Increments byte array \a array by \a size.
+ *
+ * @param array byte array
+ * @param size number of positions
+ */
+#undef INC_BYTE_ARRAY
+#define INC_BYTE_ARRAY(array, size) do{ \
+ (array).data += size; \
+ (array).len -= size; \
+ }while(0)
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif // _BYTE_ARRAY_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+#ifndef _CERT_H_
+#define _CERT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include "byte_array.h"
+#include "pki_errors.h"
+
+/**
+ * @struct CertificateX509
+ *
+ * Certificate structure.
+ *
+ * Structure fields contain byte arrays pointed to relative DER certificate positions.
+ */
+typedef struct
+{
+ ByteArray tbs; /**< TBS certificate.*/
+ ByteArray serNum; /**< Serial number.*/
+ ByteArray pubKey; /**< Public key.*/
+
+ ByteArray signR; /**< Signature r value.*/
+ ByteArray signS; /**< Signature s value.*/
+
+ ByteArray issuer; /**< Issuer name.*/
+ ByteArray subject; /**< Subject name.*/
+
+ ByteArray validFrom; /**< Start time of certificate validity. */
+ ByteArray validTo; /**< End time of certificate validity. */
+
+} CertificateX509;
+
+/**
+ * Reads certificate from byte array and write it into certificate structure.
+ *
+ * @param[in] code Byte array with DER encoded certificate
+ * @param[out] crt Pointer to certificate structure
+ * @return PKI_SUCCESS if successful
+ */
+PKIError DecodeCertificate(ByteArray code, CertificateX509 *crt);
+
+/**
+ * Parse ECDSA public key, remove ASN.1 extra bytes.
+ *
+ * @param ByteArray structure which contains public key
+ * @return PKI_SUCCESS if public key is correct, error code in case of invalid key
+ */
+PKIError ParsePublicKey(ByteArray *caPublicKey);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+
+#endif //_CERT_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#ifndef _CRL_H_
+#define _CRL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include "byte_array.h"
+#include "pki_errors.h"
+
+/// Maximal number of revoked certificates in list
+#ifdef WITH_ARDUINO
+#define CRL_MAX_LEN (256)
+#else
+#define CRL_MAX_LEN (1024)
+#endif // WITH_ARDUINO
+/**
+ * @struct CertificateList
+ *
+ * CRL structure.
+ *
+ * Structure fields contain byte arrays pointed to relative DER certificate positions.
+ */
+typedef struct
+{
+ ByteArray tbs; /**< TBS sequence of CRL.*/
+ ByteArray issuer; /**< Issuer name.*/
+ ByteArray date; /**< The issue-date for CRL.*/
+ ByteArray signR; /**< Signature r value.*/
+ ByteArray signS; /**< Signature s value.*/
+} CertificateList;
+
+#ifdef X509_DEBUG
+/**
+ * Prints Certificate List to console.
+ *
+ * @param crl - pointer to certificate list structure
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError PrintCRL(const CertificateList *const crl);
+#endif
+
+/**
+ * Decodes and checks Certificate List.
+ *
+ * @param code - certificate list structure in DER format
+ * @param crl - pointer to certificate list structure
+ * @param caPubKey - ByteArray structure contains CA public key
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError DecodeCertificateList(ByteArray code, CertificateList *crl, ByteArray caPubKey);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+#endif //_CRL_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#ifndef _CRYPTO_ADAPTER_H_
+#define _CRYPTO_ADAPTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include "ecc.h"
+#include "sha2.h"
+
+/// Sizes for ECDSA prime256v1 elliptic curve
+#define PUBLIC_KEY_SIZE (64)
+#define SIGN_R_LEN (32)
+#define SIGN_S_LEN (32)
+#define SIGN_FULL_SIZE (64)
+#define PRIVATE_KEY_SIZE (32)
+
+/// Length of SHA 256 hash
+#define SHA_256_HASH_LEN (32)
+
+#define uECC_SIGN_VERIFICATION_SUCCESS (1)
+
+/**
+ * @def GET_SHA_256(tbs, sha256)
+ *
+ * A macro that compute sha-256 hash of tbs part.
+ *
+ * @param[in] tbs "to be signed" part
+ * @param[out] sha256 hash of tbs
+ */
+#undef GET_SHA_256
+#define GET_SHA_256(tbs, sha256) do{ \
+ SHA256_CTX ctx256; \
+ SHA256_Init(&ctx256); \
+ SHA256_Update(&ctx256, tbs.data, tbs.len); \
+ SHA256_Final(sha256, &ctx256); \
+ }while(0)
+
+/**@def CHECK_SIGN(structure, caPubKey)
+ * Checks the sign of ASN.1 structure.
+ *
+ * @param structure ASN.1 stucture
+ * @param caPubKey public key of CA
+ */
+#undef CHECK_SIGN
+#define CHECK_SIGN(structure, caPubKey) do{ \
+ int err; \
+ uint8_t sha256[SHA_256_HASH_LEN]; \
+ uint8_t fullSignature[SIGN_FULL_SIZE]; \
+ GET_SHA_256((structure).tbs, sha256); \
+ memcpy(fullSignature, (structure).signR.data, SIGN_R_LEN); \
+ memcpy((fullSignature + SIGN_R_LEN), (structure).signS.data, SIGN_S_LEN);\
+ err = uECC_verify(caPubKey.data, sha256, fullSignature); \
+ CHECK_EQUAL(err, uECC_SIGN_VERIFICATION_SUCCESS, PKI_SIG_MISMATCH); \
+ }while(0)
+
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+#endif //_CRYPTO_ADAPTER_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+#ifndef _DER_DEC_H_
+#define _DER_DEC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include "byte_array.h"
+#include "pki_errors.h"
+#include "crypto_adapter.h"
+
+/// Maximal octet number in certificate's serial number
+#define SERIAL_NUMBER_MAX_LEN (20)
+/**
+ * @name DER constants
+ * These constants comply with DER encoded the ANS.1 type tags.
+ * DER encoding uses hexadecimal representation.
+ */
+#define DER_UNIVERSAL (0x00)
+#define DER_SEQUENCE (0x30)
+#define DER_OBJECT_IDENTIFIER (0x06)
+#define DER_BIT_STRING (0x03)
+#define DER_INTEGER (0x02)
+#define DER_UTC_TIME (0x17)
+#define DER_VERSION (0xa0)
+
+/* The first octet of the OCTET STRING indicates whether the key is
+compressed or uncompressed. The uncompressed form is indicated by 0x04
+and the compressed form is indicated by either 0x02 or 0x03 (RFC 5480)*/
+#define ASN1_UNCOMPRESSED_KEY (0x04)
+/// ASN.1 UTC time length
+#define UTC_TIME_LEN (13)
+/// Length Octet ASN.1
+#define LEN_LONG (128)
+/// Size of byte
+#define SIZE_OF_BYTE (8)
+
+#define ECDSA_WITH_SHA256_OID_LEN (8)
+#define EC_PUBLIC_KEY_OID_LEN (7)
+#define PRIME_256_V1_OID_LEN (8)
+
+/**@def SKIP_DER_FIELD(array, type, length)
+ * Skips the field in the ASN.1 structure.
+ *
+ * @param array pointer to ASN.1 stucture
+ * @param type type of ASN.1 field
+ * @param length length of ASN.1 field
+ */
+#undef SKIP_DER_FIELD
+#define SKIP_DER_FIELD(array, type, length) do{ \
+ CHECK_EQUAL(*((array).data), type, PKI_INVALID_FORMAT); \
+ CHECK_CALL(DecodeLength , &(array), &(length)); \
+ INC_BYTE_ARRAY(array, length); \
+ }while(0)
+
+/**@def COPY_DER_FIELD(array, str, field, type, length)
+ * Copies the field from the ASN.1 structure.
+ *
+ * @param array pointer to ASN.1 stucture
+ * @param str structure in which the array is copied
+ * @param field field of the structure in which the array is copied
+ * @param type type of ASN.1 field
+ * @param length length of ASN.1 field
+ */
+#undef COPY_DER_FIELD
+#define COPY_DER_FIELD(array, crt, field, type, length) do{ \
+ CHECK_EQUAL(*((array).data), type, PKI_INVALID_FORMAT); \
+ CHECK_CALL(DecodeLength , &(array), &(length)); \
+ ((crt)->field).data = (array).data; \
+ ((crt)->field).len = length; \
+ INC_BYTE_ARRAY(array, length); \
+ }while(0)
+
+
+/**@def CHECK_DER_OID(array, oid, length)
+ * Checks the field from the ASN.1 structure.
+ *
+ * @param array pointer to ASN.1 stucture
+ * @param oid type of DER object
+ * @param oidLen length of DER array
+ * @param length length of ASN.1 field
+ */
+#undef CHECK_DER_OID
+#undef CHECK_DER_OID
+#define CHECK_DER_OID(array, oid, oidLen, length) do{ \
+ int ret = 0; \
+ CHECK_EQUAL(*((array).data), DER_OBJECT_IDENTIFIER, PKI_INVALID_FORMAT); \
+ CHECK_CALL(DecodeLength , &(array), &(length)); \
+ CHECK_EQUAL(length, oidLen, PKI_UNKNOWN_OID); \
+ ret = memcmp ((array).data, oid, oidLen); \
+ CHECK_EQUAL(ret, 0, PKI_UNKNOWN_OID); \
+ }while(0)
+
+/**@def PARSE_SIGNATURE(structure)
+ * Parse signature of ASN.1 structure , remove ASN.1 extra bytes.
+ *
+ * @param structure Certificate or CertificateList structure
+ */
+#undef PARSE_SIGNATURE
+#define PARSE_SIGNATURE(structure) do{ \
+ if (((structure)->signR.len == SIGN_R_LEN + 1) && ((structure)->signR.data[0] == 0)) \
+ INC_BYTE_ARRAY((structure)->signR, 1); \
+ else if ((structure)->signR.len != SIGN_R_LEN) \
+ CHECK_NULL(NULL, PKI_WRONG_ARRAY_LEN); \
+ if (((structure)->signS.len == SIGN_S_LEN + 1) && ((structure)->signS.data[0] == 0)) \
+ INC_BYTE_ARRAY((structure)->signS, 1); \
+ else if ((structure)->signS.len != SIGN_S_LEN) \
+ CHECK_NULL(NULL, PKI_WRONG_ARRAY_LEN); \
+ }while(0)
+
+/**
+ * Computes length of ASN.1 object in DER format.
+ *
+ * @param[in] code array with DER encoded ASN.1 structure
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError DecodeLength(ByteArray *code, size_t *length);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+
+#endif //_X509_PARSE_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#ifndef _PKI_H_
+#define _PKI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "byte_array.h"
+#include "pki_errors.h"
+#include "crypto_adapter.h"
+#include "cert.h"
+
+/**
+ * Maximal lengths of certificate chain.
+ */
+#define MAX_CHAIN_LEN (3)
+
+#ifdef X509_DEBUG
+/**
+ * Prints Certificate to console.
+ *
+ * @param crt - pointer to Certificate structure
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError PrintCertificate(const CertificateX509 *const crt);
+#endif
+
+/**
+ * Checks certificate validity period.
+ *
+ * @param dateFrom - array with not before field
+ * @param dateTo - array with not after field
+ * @return PKI_SUCCESS if valid, error code otherwise
+ */
+PKIError CheckValidity(ByteArray dateFrom, ByteArray dateTo);
+
+/**
+ * Checks certificate date and sign.
+ *
+ * @param[in] certDerCode - Byte array with DER encoded certificate
+ * @param[in] caPublicKey - CA public key
+ * @return 0 if successful
+ */
+PKIError CheckCertificate(ByteArray certDerCode, ByteArray caPublicKey);
+
+/**
+ * Parses each certificates from list.
+ *
+ * @param[in] chainDerCode Array of DER encoded certificates
+ * @param[out] chainCrt Array of parsed certificates
+ * @param[in] chainLen Lengths of array
+ * @returns PKI_SUCCESS if no error is occurred
+ */
+PKIError ParseCertificateChain (ByteArray *chainDerCode, CertificateX509 *chainCrt,
+ uint8_t chainLen);
+
+/**
+ * Loads certificates in DER format from TLS message to array.
+ *
+ * @param[in] msg TLS message with certificate's chain
+ * @param[out] chain Array of DER encoded certificates
+ * @param[out] chainLen Lengths of array
+ * @returns PKI_SUCCESS if no error is occurred
+ */
+PKIError LoadCertificateChain (ByteArray msg, ByteArray *chain, uint8_t *chainLength);
+
+/**
+ * Checks the signature of each certificate in chain.
+ *
+ * @param[in] chainCrt Chain of certificates structures
+ * @param[in] chainLen Number of certificates in the chain
+ * @param[in] caPubKey Public key which sign the last certificate from chain
+ * @returns PKI_SUCCESS if no error is occurred
+ */
+PKIError CheckCertificateChain (CertificateX509 *chainCrt, uint8_t chainLen, ByteArray caPubKey);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+#endif // _PKI_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#ifndef _PKI_ERRORS_H_
+#define _PKI_ERRORS_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#ifdef X509_DEBUG
+#warning "DEBUG is enabled"
+#include <stdio.h> // <printf>
+#endif
+
+/**
+ * @enum PKIError
+ *
+ * The enumeration of error codes.
+ */
+
+typedef enum
+{
+ PKI_SUCCESS = 0, /**< No error occurred. */
+ PKI_UNKNOWN_ERROR, /**< Unknown error occurred. */
+ PKI_NULL_PASSED, /**< NULL passed to function. */
+ PKI_CERT_DATE_INVALID, /**< Certificate date expired. */
+ PKI_BUFFER_OVERFLOW, /**< Array out of range. */
+ PKI_WRONG_OCTET_LEN, /**< Wrong length of octet. */
+ PKI_UNKNOWN_OID, /**< Requested OID is unknown. */
+ PKI_INVALID_FORMAT, /**< The CRT/CRL/CSR format is invalid. */
+ PKI_INVALID_DATE_FORMAT, /**< The date tag or value is invalid. */
+ PKI_INVALID_SIGNATURE, /**< The signature tag or value invalid. */
+ PKI_SIG_MISMATCH, /**< Signature algorithms do not match. */
+ PKI_CERT_VERIFY_FAILED, /**< Certificate verification failed*/
+ PKI_CERT_REVOKED, /**< Certificate is revoked. */
+ PKI_WRONG_ARRAY_LEN, /**< Wrong length of input array*/
+ PKI_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory */
+ PKI_BASE64_ERROR, /**< Base64 convertion error occurred. */
+ PKI_JSON_ERROR, /**< JSON convertion error occurred. */
+ PKI_JSON_NOT_FOUND, /**< JSON object not found. */
+
+ ISSUER_CA_STORAGE_FILE_READ_ERROR, /**< File read error in CA storage */
+ ISSUER_CA_STORAGE_FILE_WRITE_ERROR, /**< File write error in CA storage */
+ ISSUER_CA_STORAGE_CRL_READ_ERROR, /**< CRL file read error in CA storage */
+ ISSUER_CA_STORAGE_CRL_WRITE_ERROR, /**< CRL file write error in CA storage */
+ ISSUER_CA_STORAGE_CRT_READ_ERROR, /**< Certificate file read error in CA storage */
+ ISSUER_CA_STORAGE_CRT_WRITE_ERROR, /**< Certificate file write error in CA storage */
+ ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory in CA storage */
+ ISSUER_CA_STORAGE_WRONG_SERIAL_NUMBER, /**< Wrong serial number passed to CA storage */
+ ISSUER_CA_STORAGE_SN_UNDEFINED, /**< Serial number is not defined in CA storage */
+ ISSUER_CA_STORAGE_WRONG_CRL_SERIAL_NUMBER, /**< Wrong CRL serial number passed to CA
+ storage */
+ ISSUER_CA_STORAGE_CRL_SN_UNDEFINED, /**< CRL serial number is not defined in CA
+ storage */
+ ISSUER_CA_STORAGE_WRONG_PRIVATE_KEY_LEN, /**< Passed private key length not equal to
+ PRIVATE_KEY_SIZE*/
+ ISSUER_CA_STORAGE_PRIVATE_KEY_UNDEFINED, /**< CA private key is not defined in CA storage */
+ ISSUER_CA_STORAGE_WRONG_PUBLIC_KEY_LEN, /**< Passed public key length not equal to
+ PUBLIC_KEY_SIZE*/
+ ISSUER_CA_STORAGE_PUBLIC_KEY_UNDEFINED, /**< CA public key is not defined in CA storage */
+ ISSUER_CA_STORAGE_CA_CHAIN_LENGTH_UNDEFINED,/**< CA certificate chain length is not defined in
+ CA storage */
+ ISSUER_CA_STORAGE_WRONG_CA_NAME_LEN, /**< CA name length is bigger than
+ ISSUER_MAX_NAME_SIZE */
+ ISSUER_CA_STORAGE_CA_NAME_UNDEFINED, /**< CA name is not defined in CA storage */
+ ISSUER_CA_STORAGE_CRL_UNDEFINED, /**< CRL is not defined in CA storage */
+ ISSUER_CA_STORAGE_NULL_PASSED, /**< NULL passed to function in CA storage */
+ CKM_INFO_IS_NOT_INIT, /**< CKM info storage was not init */
+ ISSUER_CA_STORAGE_WRONG_BYTE_ARRAY_LEN, /**< ByteArray with wrong lenth passed into
+ CA storage */
+
+ ISSUER_MAKE_KEY_ERROR, /**< Error during uECC_make_key() */
+ ISSUER_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory in issuer */
+ ISSUER_FILE_WRITE_ERROR, /**< File write error in issuer */
+ ISSUER_WRONG_SERIAL_NUMBER, /**< Wrong serial number passed to issuer */
+ ISSUER_WRONG_ROOT_NAME_LEN, /**< CA name length is bigger than ISSUER_MAX_NAME_SIZE */
+ ISSUER_NULL_PASSED, /**< NULL passed to function in issuer */
+ ISSUER_WRONG_BYTE_ARRAY_LEN,/**< ByteArray with wrong length passed into issuer */
+
+ ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory in CRL encoder */
+ ISSUER_CRL_ENCODER_DER_ENCODE_FAIL, /**< Failed to encode structure into DER
+ in CRL encoder */
+ ISSUER_CRL_ENCODER_SIGNATURE_FAIL, /**< Failed to sign TBS in CRL encoder */
+ ISSUER_CRL_NULL_PASSED, /**< NULL passed to function in CRL encoder */
+ ISSUER_CRL_WRONG_BYTE_ARRAY_LEN, /**< ByteArray with wrong length passed into
+ CRL encoder */
+
+ ISSUER_CSR_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory in CSR unit */
+ ISSUER_CSR_DER_ENCODE_FAIL, /**< Failed to encode structure into DER in CSR unit */
+ ISSUER_CSR_SIGNATURE_FAIL, /**< Failed to sign TBS in CSR unit */
+ ISSUER_CSR_DER_DECODE_FAIL, /**< Failed to decode structure from DER in CSR unit */
+ ISSUER_CSR_INVALID_SIGNATURE, /**< Signature check fail in CSR unit. */
+ ISSUER_CSR_TOO_LONG_NAME, /**< CSR subject name length is bigger than CSR_MAX_NAME_SIZE */
+ ISSUER_CSR_INVALID_KEY_FORMAT, /**< Public key format is invalid in CSR unit. */
+ ISSUER_CSR_NULL_PASSED, /**< NULL passed to function in CSR unit */
+ ISSUER_CSR_WRONG_BYTE_ARRAY_LEN,/**< ByteArray with wrong length passed into CSR unit */
+
+ ISSUER_X509_MEMORY_ALLOC_FAILED, /**< Failed to allocate memory in X.509 encoder */
+ ISSUER_X509_DER_ENCODE_FAIL, /**< Failed to encode structure into DER in X.509 encoder */
+ ISSUER_X509_SIGNATURE_FAIL, /**< Failed to sign TBS in X.509 encoder */
+ ISSUER_X509_NULL_PASSED, /**< NULL passed to function in X.509 encoder */
+ ISSUER_X509_WRONG_BYTE_ARRAY_LEN /**< ByteArray with wrong length passed into X.509 encoder */
+} PKIError;
+
+
+/** @def CHECK_PRINT(err_code, ...)
+ *
+ * Prints debug information \a err_code and __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__ values.
+ *
+ * @param[in] err_code Error code
+*/
+#ifdef X509_DEBUG
+#define CHECK_PRINT(err_code) \
+fprintf(stderr, "%s() in %s, line %i: %d\n",__func__, __FILE__, __LINE__, err_code);
+#else
+# define CHECK_PRINT(...)
+#endif
+
+/**
+ * @def CHECK_NULL(param, error)
+ * A macro that checks whether \a param is not NULL.
+ *
+ * If \a (param = NULL) it goes to error processing with \a error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] error Error code
+ */
+#define CHECK_NULL(param, error) do { \
+ if (!(param)) { \
+ error_value = error; \
+ CHECK_PRINT(error); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_EQUAL(param, checker, err_code)
+ *
+ * A macro that checks whether \a param equal to \a checker.
+ *
+ * If \a (param != checker) it goes to error processing with \a err_code error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] error Error code
+ */
+#define CHECK_EQUAL(param, checker, err_code) do { \
+ if ((param) != (checker)) { \
+ error_value = err_code; \
+ CHECK_PRINT(err_code); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_NOT_EQUAL(param, checker, err_code)
+ * A macro that checks whether \a param not equal to \a checker.
+ *
+ * If \a (param == checker) it goes to error processing with \a err_code error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] error Error code
+ */
+#define CHECK_NOT_EQUAL(param, checker, err_code) do { \
+ if ((param) == (checker)) { \
+ error_value = err_code; \
+ CHECK_PRINT(err_code); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_LESS(param, checker, err_code)
+ * A macro that checks whether \a param less then \a checker.
+ *
+ * If \a (param > checker) it goes to error processing with \a err_code error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] error error code
+ */
+#define CHECK_LESS(param, checker, err_code) do { \
+ if ((param) >= (checker)) { \
+ error_value = err_code; \
+ CHECK_PRINT(err_code); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_COND(param, err_code)
+ *
+ * A macro that checks whether condition \a param is true.
+ *
+ * If \a (param != true) it goes to error processing with \a err_code error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] error error code
+ */
+#define CHECK_COND(param, err_code) do { \
+ if (!(param)) { \
+ error_value = err_code; \
+ CHECK_PRINT(err_code); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_LESS_EQUAL(param, checker, err_code)
+*
+* A macro that checks whether \a param <= \a checker.
+*
+* If \a (param < checker) it goes to error processing with \a err_code error code.
+*
+* @param[in] param Parameter to check
+* @param[in] error error code
+*/
+#define CHECK_LESS_EQUAL(param, checker, err_code) do { \
+ if ((param) > (checker)) { \
+ error_value = err_code; \
+ CHECK_PRINT(err_code); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_NULL_BYTE_ARRAY_PTR(param, err_code)
+ *
+ * A macro that checks whether pointer to ByteArray \a param is not NULL and contains a valid pointer.
+ *
+ * If \a (param != checker) it goes to error processing with \a err_code error code.
+ *
+ * @param[in] param Parameter to check
+ * @param[in] err_code Error code
+ */
+#define CHECK_NULL_BYTE_ARRAY_PTR(param, err_code) do { \
+ CHECK_NULL(param, err_code); \
+ CHECK_NULL((param)->data, err_code); \
+ CHECK_NULL((param)->len, err_code); \
+ } while(0)
+
+/** @def FUNCTION_INIT(...)
+ * A macro for initializations function variables.
+ *
+ * If error occurs it goes to error processing.
+ */
+#define FUNCTION_INIT(...) \
+ PKIError error_value = PKI_UNKNOWN_ERROR; \
+ __VA_ARGS__;
+
+/** @def FUNCTION_CLEAR(...)
+ *
+ * A macro for freeing function variables.
+ *
+ * @return 0 if successful
+ */
+#define FUNCTION_CLEAR(...) \
+ error_value = PKI_SUCCESS; \
+ ERROR_PROC: \
+ __VA_ARGS__ \
+ return error_value;
+
+/** @def CHECK_CALL(fn, ...)
+ * A macro that checks \a fn function return code
+ *
+ * If function return error code it goes to error processing.
+ *
+ * @param[in] fn Function to call
+ */
+#define CHECK_CALL(fn, ...) do { \
+ error_value = fn(__VA_ARGS__); \
+ if ((int)error_value != (int)PKI_SUCCESS) { \
+ CHECK_PRINT(error_value); \
+ goto ERROR_PROC; \
+ } } while(0)
+
+/** @def CHECK_INC_BYTE_ARRAY_PTR(array, size)
+ *
+ * Increments byte array pointer \a array by \a size with bound checking.
+ *
+ * @param array byte array pointer
+ * @param size number of positions
+ */
+#undef CHECK_INC_BYTE_ARRAY_PTR
+#define CHECK_INC_BYTE_ARRAY_PTR(array, size) do{ \
+ if (size > ((array)->len)){ \
+ error_value = PKI_BUFFER_OVERFLOW; \
+ CHECK_PRINT(error_value); \
+ goto ERROR_PROC; } \
+ INC_BYTE_ARRAY_PTR(array, size); \
+ }while(0)
+
+/** @def CHECK_INC_BYTE_ARRAY(array, size)
+ *
+ * Increments byte array \a array by \a size with bound checking.
+ *
+ * @param array byte array pointer
+ * @param size number of positions
+ */
+#undef CHECK_INC_BYTE_ARRAY
+#define CHECK_INC_BYTE_ARRAY(array, size) do{ \
+ if (size > ((array).len)) { \
+ error_value = PKI_BUFFER_OVERFLOW; \
+ CHECK_PRINT(error_value); \
+ goto ERROR_PROC; } \
+ INC_BYTE_ARRAY(array, size); \
+ }while(0)
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif // _PKI_ERRORS_H_
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+#ifndef _SN_STORE_H_
+#define _SN_STORE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include "pki_errors.h"
+#include "byte_array.h"
+
+
+/**
+ * Stores serial number to SN storage.
+ *
+ * @param[in] serNum certificate serial number to be stored
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError StoreSerialNumber(const ByteArray serNum);
+
+/**
+ * Check whether there is \a serNum in SN storage.
+ *
+ * @param[in] serNum certificate serial number to be stored
+ * @return PKI_SUCCESS if \a not belongs SN storage, error code otherwise
+ */
+PKIError CheckSerialNumber(const ByteArray serNum);
+
+
+#ifdef X509_DEBUG
+/**
+ * Prints all serial numbers from SN storage.
+ */
+void PrintSNStore(void);
+#endif
+
+
+/**
+ * Frees memory occupied by SN storage.
+ */
+void FreeSNStore(void);
+
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+#endif //_SN_STORE_H_
+
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#include "byte_array.h"
+#include "cert.h"
+#include "der_dec.h"
+
+
+extern const uint8_t g_ECDSA_WITH_SHA256_OID[];
+extern const uint8_t g_EC_PUBLIC_KEY_OID[];
+extern const uint8_t g_PRIME_256_V1_OID[];
+
+/**
+ * Decodes TBSCertificate.
+ */
+static PKIError DecodeTbs(CertificateX509 *const crt)
+{
+ FUNCTION_INIT(
+ size_t length, temp_len;
+ ByteArray tbs = crt->tbs, temp;
+ CHECK_NULL(crt, PKI_NULL_PASSED);
+ );
+ //skip version
+ SKIP_DER_FIELD(tbs, DER_VERSION, length);
+ //serial number
+ COPY_DER_FIELD(tbs, crt, serNum, DER_INTEGER, length);
+
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ //copy to temp
+ temp = tbs; // OPTIONAL
+ INC_BYTE_ARRAY(tbs, length); // skip algorithm identifier
+ //check_signature_algorithm
+ //1.2.840.10045.4.3.2
+ CHECK_DER_OID(temp, g_ECDSA_WITH_SHA256_OID, ECDSA_WITH_SHA256_OID_LEN, temp_len);
+ //copy issuer X.500 name
+ COPY_DER_FIELD(tbs, crt, issuer, DER_SEQUENCE, length);
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+
+ //copy valid period
+ COPY_DER_FIELD(tbs, crt, validFrom, DER_UTC_TIME, length);
+ COPY_DER_FIELD(tbs, crt, validTo, DER_UTC_TIME, length);
+
+ //copy subject X.500 name
+ COPY_DER_FIELD(tbs, crt, subject, DER_SEQUENCE, length);
+ //public key
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ //check public key type
+ //1.2.840.10045.2.1
+ CHECK_DER_OID(tbs, g_EC_PUBLIC_KEY_OID, EC_PUBLIC_KEY_OID_LEN, length);
+ INC_BYTE_ARRAY(tbs, length);
+ //check curve
+ //1.2.840.10045.3.1.7
+ CHECK_DER_OID(tbs, g_PRIME_256_V1_OID, PRIME_256_V1_OID_LEN, length);
+ INC_BYTE_ARRAY(tbs, length);
+ //copy public key
+ COPY_DER_FIELD(tbs, crt, pubKey, DER_BIT_STRING, length);
+ FUNCTION_CLEAR();
+}
+
+
+/**
+ * Decodes certificate in DER format.
+ */
+PKIError DecodeCertificate(ByteArray code, CertificateX509 *crt)
+{
+ FUNCTION_INIT(
+ size_t length, tempLen;
+ ByteArray temp;
+ CHECK_NULL(crt, PKI_NULL_PASSED);
+ CHECK_NULL(code.data, PKI_NULL_PASSED);
+ );
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //store sequence position
+ temp = code;
+ //TODO check length of TBS
+ //copy tbs
+ COPY_DER_FIELD(code, crt, tbs, DER_SEQUENCE, length);
+ //decode tbs
+ CHECK_CALL(DecodeTbs, crt);
+ //include sequense and len to tbs
+ crt->tbs.len += crt->tbs.data - temp.data;
+ crt->tbs.data = temp.data;
+ //printf("DATA %02X\n", *(code.data));
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //copy to temp
+ temp = code;
+ INC_BYTE_ARRAY(code, length); // skip algorithm identifier
+ //check_signature_algorithm
+ //1.2.840.10045.4.3.2
+ CHECK_DER_OID(temp, g_ECDSA_WITH_SHA256_OID, ECDSA_WITH_SHA256_OID_LEN, tempLen);
+ //decode_signature_value
+ CHECK_EQUAL(*(code.data), DER_BIT_STRING, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //skip DER_UNIVERSAL
+ CHECK_EQUAL(*(code.data), DER_UNIVERSAL, PKI_INVALID_FORMAT);
+ CHECK_INC_BYTE_ARRAY(code, 1);
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //copy sign r value
+ COPY_DER_FIELD(code, crt, signR, DER_INTEGER, length);
+ //copy sign s value
+ COPY_DER_FIELD(code, crt, signS, DER_INTEGER, length);
+
+ PARSE_SIGNATURE(crt);
+
+ FUNCTION_CLEAR();
+}
+
+#ifdef X509_DEBUG
+/**
+ * Prints certificate to console.
+ */
+PKIError PrintCertificate(const CertificateX509 *const crt)
+{
+ FUNCTION_INIT(
+ CHECK_NULL(crt, PKI_NULL_PASSED);
+ );
+ printf("\n-----BEGIN CERTIFICATE-----\n");
+ PRINT_BYTE_ARRAY("SER NUM:\n", crt->serNum);
+ PRINT_BYTE_ARRAY("ISSUER:\n", crt->issuer);
+ PRINT_BYTE_ARRAY("SUBJECT:\n", crt->subject);
+ PRINT_BYTE_ARRAY("PUB KEY:\n", crt->pubKey);
+ PRINT_BYTE_ARRAY("SIGN R VALUE:\n", crt->signR);
+ PRINT_BYTE_ARRAY("SIGN S VALUE:\n", crt->signS);
+ PRINT_BYTE_ARRAY("TBS:\n", crt->tbs);
+ printf("-----END CERTIFICATE-----\n");
+ FUNCTION_CLEAR(
+ );
+}
+#endif
+
+PKIError ParsePublicKey(ByteArray *caPublicKey)
+{
+ FUNCTION_INIT(
+ CHECK_NULL(caPublicKey, PKI_NULL_PASSED);
+ );
+
+ if ((caPublicKey->len == PUBLIC_KEY_SIZE + 2) && (caPublicKey->data[0] == 0)
+ && (caPublicKey->data[1] == ASN1_UNCOMPRESSED_KEY))
+ INC_BYTE_ARRAY(*caPublicKey, 2);
+ else if (caPublicKey->len != PUBLIC_KEY_SIZE)
+ CHECK_NULL(NULL, PKI_WRONG_ARRAY_LEN);
+
+ FUNCTION_CLEAR();
+}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#include "crl.h"
+#include "byte_array.h"
+#include "der_dec.h"
+#include "sn_store.h"
+#include "der_dec.h"
+#include "crypto_adapter.h"
+
+
+extern const uint8_t g_ECDSA_WITH_SHA256_OID[ECDSA_WITH_SHA256_OID_LEN];
+extern const uint8_t g_EC_PUBLIC_KEY_OID[EC_PUBLIC_KEY_OID_LEN];
+extern const uint8_t g_PRIME_256_V1_OID[PRIME_256_V1_OID_LEN];
+
+/*
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, MUST be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time
+ * } OPTIONAL,
+ * }
+*/
+
+
+/**
+ * Decodes TBS of CRL.
+ */
+static PKIError DecodeTbs(CertificateList *const crl)
+{
+ FUNCTION_INIT(
+ size_t length;
+ ByteArray tbs = crl->tbs, temp;
+ CHECK_NULL(crl, PKI_NULL_PASSED);
+ ByteArray sn = BYTE_ARRAY_INITIALIZER;
+ FreeSNStore();
+ );
+
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+
+ INC_BYTE_ARRAY(tbs, length); // skip algorithm identifier
+ //1.2.840.10045.4.3.2
+ //copy issuer X.500 name
+ COPY_DER_FIELD(tbs, crl, issuer, DER_SEQUENCE, length);
+ //copy date
+ COPY_DER_FIELD(tbs, crl, date, DER_UTC_TIME, length);
+ //COPY_DER_FIELD(tbs, crl, date, DER_UTC_TIME, length); // optional
+ // copy serial numbers
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ temp.data = tbs.data;
+ temp.len = length;
+ while (tbs.data < temp.data + temp.len)
+ {
+ CHECK_EQUAL(*(tbs.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ //serial number
+ CHECK_EQUAL(*(tbs.data), DER_INTEGER, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &tbs, &length);
+ sn.data = tbs.data;
+ sn.len = length;
+ CHECK_CALL(StoreSerialNumber, sn);
+ INC_BYTE_ARRAY(tbs, length);
+ SKIP_DER_FIELD(tbs, DER_UTC_TIME, length);
+ }
+ FUNCTION_CLEAR();
+}
+
+/*
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+*/
+
+/**
+ * Decodes certificate in DER format.
+ */
+PKIError DecodeCertificateList(ByteArray code, CertificateList *crl, ByteArray caPubKey)
+{
+ FUNCTION_INIT(
+ size_t length, tempLen;
+ ByteArray temp;
+ CHECK_NULL(crl, PKI_NULL_PASSED);
+ CHECK_NULL(code.data, PKI_NULL_PASSED);
+ );
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //store sequence position
+ temp = code;
+ //TODO check length of TBS
+ //copy tbs
+ COPY_DER_FIELD(code, crl, tbs, DER_SEQUENCE, length);
+ //decode tbs
+ CHECK_CALL(DecodeTbs, crl); //TODO
+ //include sequense and len to tbs
+ crl->tbs.len += crl->tbs.data - temp.data;
+ crl->tbs.data = temp.data;
+
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //copy to temp
+ temp = code;
+ INC_BYTE_ARRAY(code, length); // skip algorithm identifier
+ //check_signature_algorithm
+ //1.2.840.10045.4.3.2
+ CHECK_DER_OID(temp, g_ECDSA_WITH_SHA256_OID, ECDSA_WITH_SHA256_OID_LEN, tempLen);
+ //decode_signature_value
+ CHECK_EQUAL(*(code.data), DER_BIT_STRING, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //skip DER_UNIVERSAL
+ CHECK_EQUAL(*(code.data), DER_UNIVERSAL, PKI_INVALID_FORMAT);
+ CHECK_INC_BYTE_ARRAY(code, 1);
+ CHECK_EQUAL(*(code.data), DER_SEQUENCE, PKI_INVALID_FORMAT);
+ CHECK_CALL(DecodeLength , &code, &length);
+ //copy sign r value
+ COPY_DER_FIELD(code, crl, signR, DER_INTEGER, length);
+ //copy sign s value
+ COPY_DER_FIELD(code, crl, signS, DER_INTEGER, length);
+ if (caPubKey.data != NULL)
+ {
+ PARSE_SIGNATURE(crl);
+ CHECK_SIGN(*crl, caPubKey);
+ }
+ FUNCTION_CLEAR();
+}
+
+#ifdef X509_DEBUG
+/**
+ * Prints CRL to console.
+ */
+PKIError PrintCRL(const CertificateList *const crl)
+{
+ FUNCTION_INIT(
+ CHECK_NULL(crl, PKI_NULL_PASSED);
+ );
+ printf("\n-----BEGIN CRL-----\n");
+ PRINT_BYTE_ARRAY("ISSUER:\n", crl->issuer);
+ PRINT_BYTE_ARRAY("DATE:\n", crl->date);
+ PRINT_BYTE_ARRAY("TBS:\n", crl->tbs);
+ printf("-----END CRL-----\n");
+ FUNCTION_CLEAR(
+ );
+}
+#endif
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+#include "stdint.h"
+
+const uint8_t g_ECDSA_WITH_SHA256_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02};
+const uint8_t g_EC_PUBLIC_KEY_OID[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01};
+const uint8_t g_PRIME_256_V1_OID[] = {0x2A, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
+
+
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+#include "der_dec.h"
+
+/**
+ * Computes length.
+ */
+PKIError DecodeLength(ByteArray *code, size_t *length)
+{
+ FUNCTION_INIT(
+ CHECK_NULL_BYTE_ARRAY_PTR(code, PKI_NULL_PASSED);
+ );
+ CHECK_INC_BYTE_ARRAY_PTR(code, 1);
+
+ if ((*(code->data)) < LEN_LONG)
+ {
+ *length = *(code->data);
+ CHECK_INC_BYTE_ARRAY_PTR(code, 1);
+ }
+ else
+ {
+ uint8_t i = 0;
+ uint8_t blocksNum = *(code->data) - LEN_LONG;
+ CHECK_INC_BYTE_ARRAY_PTR(code, 1);
+ CHECK_LESS(blocksNum, 5, PKI_WRONG_OCTET_LEN);
+ *length = 0;
+
+ for (i = 0; i < blocksNum; ++i)
+ {
+ *length |= *(code->data) << ((blocksNum - i - 1) * SIZE_OF_BYTE);
+ CHECK_INC_BYTE_ARRAY_PTR(code, 1);
+ }
+ }
+
+ //should be: length <= array size
+ CHECK_LESS_EQUAL(*length, code->len, PKI_WRONG_OCTET_LEN);
+ FUNCTION_CLEAR();
+}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+#include "pki.h"
+#include "cert.h"
+#include "sn_store.h"
+#include "der_dec.h"
+#include "crypto_adapter.h"
+
+#ifndef WITH_ARDUINO
+#include <time.h>
+#endif
+
+
+/**
+ * Check: notBefore <= now <= notAfter.
+ */
+PKIError CheckValidity(ByteArray dateFrom, ByteArray dateTo)
+{
+ FUNCTION_INIT(
+ struct tm t = {0};
+ struct tm lnow = {0};
+ time_t now;
+ int i;
+ ByteArray date;
+ CHECK_EQUAL(dateFrom.len, UTC_TIME_LEN, PKI_INVALID_DATE_FORMAT);
+ CHECK_EQUAL(dateTo.len, UTC_TIME_LEN, PKI_INVALID_DATE_FORMAT);
+ );
+ /* Get the current time */
+ now = time(NULL);
+ gmtime_r( &now, &lnow);
+ for (i = 0; i < 2; i ++)
+ {
+ date = (i == 0 ? dateFrom : dateTo);
+ t.tm_year = (date.data[0] - '0') * 10 + date.data[1] - '0';
+ /* It is considered date from 1950 to 2050 */
+ if (t.tm_year < 50)
+ {
+ t.tm_year += 100;
+ }
+ t.tm_mon = (date.data[2] - '0') * 10 + date.data[3] - '0' - 1;
+ t.tm_mday = (date.data[4] - '0') * 10 + date.data[5] - '0';
+ t.tm_hour = (date.data[6] - '0') * 10 + date.data[7] - '0';
+ t.tm_min = (date.data[8] - '0') * 10 + date.data[9] - '0';
+ t.tm_sec = (date.data[10] - '0') * 10 + date.data[11] - '0';
+ if (i == 0)
+ {
+ CHECK_LESS_EQUAL(t.tm_year, lnow.tm_year, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year)
+ CHECK_LESS_EQUAL(t.tm_mon, lnow.tm_mon, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon)
+ CHECK_LESS_EQUAL(t.tm_mday, lnow.tm_mday, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday)
+ CHECK_LESS_EQUAL(t.tm_hour, lnow.tm_hour, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday
+ && t.tm_hour == lnow.tm_hour)
+ CHECK_LESS_EQUAL(t.tm_min, lnow.tm_min, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday
+ && t.tm_hour == lnow.tm_hour && t.tm_min == lnow.tm_min)
+ CHECK_LESS_EQUAL(t.tm_sec, lnow.tm_sec, PKI_CERT_DATE_INVALID);
+ }
+ else
+ {
+ CHECK_LESS_EQUAL(lnow.tm_year, t.tm_year, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year)
+ CHECK_LESS_EQUAL(lnow.tm_mon, t.tm_mon, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon)
+ CHECK_LESS_EQUAL(lnow.tm_mday, t.tm_mday, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday)
+ CHECK_LESS_EQUAL(lnow.tm_hour, t.tm_hour, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday
+ && t.tm_hour == lnow.tm_hour)
+ CHECK_LESS_EQUAL(lnow.tm_min, t.tm_min, PKI_CERT_DATE_INVALID);
+ if (t.tm_year == lnow.tm_year && t.tm_mon == lnow.tm_mon && t.tm_mday == lnow.tm_mday
+ && t.tm_hour == lnow.tm_hour && t.tm_min == lnow.tm_min)
+ CHECK_LESS_EQUAL(lnow.tm_sec, t.tm_sec, PKI_CERT_DATE_INVALID);
+ }
+ }
+ FUNCTION_CLEAR();
+}
+
+/**
+ * Decode certDerCode certificate and performs verification.
+ *
+ * @param[in] certDerCode Byte array with DER encoded certificate
+ * @param[in] caPublicKey Byte array with CA public key
+ * @return PKI_SUCCESS if success, error code otherwise
+ */
+PKIError CheckCertificate(ByteArray certDerCode, ByteArray caPublicKey)
+{
+ FUNCTION_INIT(
+ CertificateX509 crt;
+ INIT_BYTE_ARRAY(crt.tbs);
+ INIT_BYTE_ARRAY(crt.signR);
+ INIT_BYTE_ARRAY(crt.signS);
+ INIT_BYTE_ARRAY(crt.pubKey);
+ INIT_BYTE_ARRAY(crt.issuer);
+ INIT_BYTE_ARRAY(crt.subject);
+ );
+
+ CHECK_CALL(DecodeCertificate, certDerCode, &crt);
+ CHECK_CALL(CheckValidity, crt.validFrom, crt.validTo);
+ CHECK_CALL(ParsePublicKey, &caPublicKey);
+ CHECK_SIGN(crt, caPublicKey);
+ CHECK_CALL(CheckSerialNumber, crt.serNum);
+
+ FUNCTION_CLEAR();
+}
+
+/*
+ * https://tools.ietf.org/html/rfc5246
+ * This is a sequence (chain) of certificates. The sender's certificate MUST come first
+ * in the list. Each following certificate MUST directly certify the one preceding it.
+ */
+
+
+/*
+ * Handshake Message: certificate consist of the list of certificates.
+ * Certificate length (3 bytes)
+ * DER encoded certificate
+ * The first is server’s certificate
+ * Other certificates are optional
+ * Usually intermediate CA certificates
+ */
+
+// Parses each certificate from list.
+PKIError ParseCertificateChain (ByteArray *chainDerCode, CertificateX509 *chainCrt,
+ uint8_t chainLen)
+{
+ FUNCTION_INIT(
+ int i;
+ CHECK_NULL(chainDerCode, PKI_NULL_PASSED);
+ CHECK_NULL(chainCrt, PKI_NULL_PASSED);
+ CHECK_LESS_EQUAL(chainLen, MAX_CHAIN_LEN, PKI_WRONG_ARRAY_LEN);
+ );
+ for (i = 0; i < chainLen; i++)
+ {
+ CHECK_CALL(DecodeCertificate, (*chainDerCode), chainCrt);
+#ifdef X509_DEBUG
+ PrintCertificate(chainCrt);
+#endif
+ chainDerCode++;
+ chainCrt++;
+ }
+ FUNCTION_CLEAR();
+}
+
+// Loads certificates from TLS message
+PKIError LoadCertificateChain (ByteArray msg, ByteArray *chain, uint8_t *chainLength)
+{
+ FUNCTION_INIT(
+ CHECK_NULL(msg.data, PKI_NULL_PASSED);
+ CHECK_LESS_EQUAL(3, msg.len, PKI_WRONG_ARRAY_LEN);
+ CHECK_NULL(chain, PKI_NULL_PASSED);
+ CHECK_NULL(chainLength, PKI_NULL_PASSED);
+ uint32_t tmpLengthChain = 0;
+ *chainLength = 0;
+ );
+
+ CHECK_COND(msg.data[0] != 0 || msg.data[1] != 0 || msg.data[2] != 3, PKI_SUCCESS);
+#ifdef X509_DEBUG
+ printf("start chain parsing\n");
+#endif
+ while (msg.len > 0)
+ {
+#ifdef X509_DEBUG
+ printf("chain parsing: %d\n", msg.len);
+#endif
+ CHECK_LESS_EQUAL(3, msg.len, PKI_WRONG_ARRAY_LEN);
+ tmpLengthChain = (((uint32_t) msg.data[0]) << 16) | (((uint32_t) msg.data[1]) << 8) | msg.data[2];
+ CHECK_INC_BYTE_ARRAY(msg, 3);
+ (*chain).data = msg.data;
+ (*chain).len = tmpLengthChain;
+ chain ++;
+ (*chainLength) ++;
+ CHECK_LESS_EQUAL((*chainLength), MAX_CHAIN_LEN, PKI_WRONG_ARRAY_LEN);
+ CHECK_INC_BYTE_ARRAY(msg, tmpLengthChain); // Check this
+ }
+ FUNCTION_CLEAR();
+}
+
+/*
+ * Certificate validation requires that root keys be distributed independently,
+ * the self-signed certificate that specifies the root certificate authority MAY be omitted
+ * from the chain, under the assumption that the remote end must already possess it in order to
+ * validate it in any case.
+ */
+
+// Verifies each certificate from list using next public key from list
+PKIError CheckCertificateChain (CertificateX509 *chainCrt, uint8_t chainLen, ByteArray caPubKey)
+{
+ FUNCTION_INIT(
+ int i;
+ CHECK_NULL(chainCrt, PKI_NULL_PASSED);
+ CHECK_LESS_EQUAL(chainLen, MAX_CHAIN_LEN, PKI_WRONG_ARRAY_LEN);
+ );
+ for (i = 0; i < chainLen - 1; i++)
+ {
+ ParsePublicKey(&(chainCrt + 1)->pubKey);
+ CHECK_SIGN(*chainCrt, (chainCrt + 1)->pubKey);
+ CHECK_CALL(CheckSerialNumber, chainCrt->serNum);
+ chainCrt++;
+ }
+ CHECK_SIGN(*chainCrt, caPubKey);
+ CHECK_CALL(CheckSerialNumber, chainCrt->serNum);
+ FUNCTION_CLEAR();
+}
+
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+#include "sn_store.h"
+#include <string.h>
+#include <stdlib.h>
+
+//Size of initial memory
+#define CRL_BLOCK_LEN 20
+
+
+/**
+ * @struct SNStore
+ *
+ * General structure for storing serial numbers.
+ *
+ * Contains pointer to array of bytes and it's length.
+ */
+typedef struct
+{
+ ByteArray array; /**< Byte array with data*/
+ size_t blockNumber; /**< Number of used memory blocks */
+} SNStore;
+
+
+/**
+ * Internal storage for serial numbers.
+ */
+static SNStore Store = {{NULL, 0}, 1};
+
+// Frees memory occupied by SN storage.
+void FreeSNStore(void)
+{
+ free(Store.array.data);
+ INIT_BYTE_ARRAY(Store.array);
+ Store.blockNumber = 1;
+}
+
+// Stores serial number to SN storage.
+PKIError StoreSerialNumber(const ByteArray sn)
+{
+ FUNCTION_INIT(
+ CHECK_NULL(sn.data, PKI_NULL_PASSED);
+ uint8_t *temp = NULL;
+ );
+ if (Store.array.len == 0 || Store.array.len + sn.len + 1 > CRL_BLOCK_LEN * Store.blockNumber)
+ {
+ temp = (uint8_t *) realloc(Store.array.data,
+ sizeof(uint8_t) * CRL_BLOCK_LEN * Store.blockNumber * 2);
+ CHECK_NULL(temp, PKI_MEMORY_ALLOC_FAILED);
+ Store.array.data = temp;
+ Store.blockNumber *= 2;
+ }
+ Store.array.data[Store.array.len] = sn.len;
+ memcpy(&Store.array.data[Store.array.len + 1], sn.data, sn.len);
+ Store.array.len += sn.len + 1;
+ FUNCTION_CLEAR(
+ if (error_value != PKI_SUCCESS) free(temp);
+ );
+}
+
+
+// Checks whether there is serial number in SN storage
+PKIError CheckSerialNumber(const ByteArray sn)
+{
+ FUNCTION_INIT(
+ int i, res;
+ CHECK_NULL(sn.data, PKI_NULL_PASSED);
+ );
+ CHECK_NULL(Store.array.data, PKI_SUCCESS);
+ for ( i = 0; i < Store.array.len; i += Store.array.data[i] + 1)
+ {
+ if (sn.len == Store.array.data[i])
+ {
+ res = memcmp(&Store.array.data[i + 1], sn.data, sn.len);
+ CHECK_NOT_EQUAL(res, 0, PKI_CERT_REVOKED);
+ }
+ }
+ FUNCTION_CLEAR();
+}
+
+#ifdef X509_DEBUG
+//Prints store content
+void PrintSNStore(void)
+{
+ ByteArray curr;
+ int i, count = 0;
+ if (Store.array.data != NULL)
+ {
+ for ( i = 0; i < Store.array.len; i += Store.array.data[i] + 1)
+ {
+ curr.len = Store.array.data[i];
+ curr.data = &Store.array.data[i + 1];
+ PRINT_BYTE_ARRAY("", curr);
+ count++;
+ }
+ }
+ printf("\nSN STORE CONTAINS %d ELEMENTS\n", count);
+}
+#endif //DEBUG