From: Oleksii Udod Date: Mon, 14 Sep 2015 14:11:13 +0000 (+0300) Subject: implement certificate key manager X-Git-Tag: 1.2.0+RC1~999^2^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56bf1899473a5908d82d22944d097d8fa7e0cbb7;p=platform%2Fupstream%2Fiotivity.git implement certificate key manager Change-Id: Ie77bc7f7cffe9536a0ca7a24625af17d01bf63ed Signed-off-by: Oleksii Udod Reviewed-on: https://gerrit.iotivity.org/gerrit/2447 Reviewed-by: dongik Lee Tested-by: jenkins-iotivity Reviewed-by: Sachin Agrawal --- diff --git a/resource/csdk/security/provisioning/ck_manager/include/cert_generator.h b/resource/csdk/security/provisioning/ck_manager/include/cert_generator.h new file mode 100644 index 0000000..a21980f --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/include/cert_generator.h @@ -0,0 +1,60 @@ +/****************************************************************** + * + * 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 INCLUDE_ISSUER_ISSUER_H_ +#define INCLUDE_ISSUER_ISSUER_H_ + +#include "Certificate.h" // Certificate ASN.1 type +#include "pki.h" +#include "pki_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define X509_V1 0 +#define X509_V2 1 +#define X509_V3 2 + +/** + * Encodes X.509 certificate with specified parameters. + * + * @param[in] subjectName pointer to serial subject's common name + * @param[in] issuerName pointer to issuer's common name + * @param[in] notBefore pointer to certificate validity limit + * @param[in] notAfter pointer to certificate validity limit + * @param[in] subjectPublicKey pointer to subject's public key to be signed + * @param[in] issuerPrivateKey pointer to issuer's private key to sign certificate + * @param[out] encodedCertificate pointer to allocated memory for DER encoded certificate + * (ISSUER_MAX_CERT_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateCertificate (const UTF8String_t *subjectName, const UTF8String_t *issuerName, + const UTCTime_t *notBefore, const UTCTime_t *notAfter, + const BIT_STRING_t *subjectPublicKey, const BIT_STRING_t *issuerPrivateKey, + ByteArray *encodedCertificate); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_ISSUER_ISSUER_H_ */ diff --git a/resource/csdk/security/provisioning/ck_manager/include/ck_manager.h b/resource/csdk/security/provisioning/ck_manager/include/ck_manager.h new file mode 100644 index 0000000..02ac6a3 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/include/ck_manager.h @@ -0,0 +1,208 @@ +/****************************************************************** + * + * 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 INCLUDE_MASTER_ISSUER_H_ +#define INCLUDE_MASTER_ISSUER_H_ + +#include "byte_array.h" +#include "cert_generator.h" +#include "ckm_info.h" +#include "csr_generator.h" +#include "ecc.h" +#include "crl_generator.h" +#include "pki_errors.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISSUER_DEFAULT_CA_NAME "CA_name" +#define ISSUER_DEFAULT_SUBJECT_NAME "Subj_name" +#define ISSUER_DEFAULT_NOT_BEFORE "130101000000Z" +#define ISSUER_DEFAULT_NOT_AFTER "490101000000Z" +#define ISSUER_DEFAULT_THIS_UPDATE "150601000000Z" + +/** + * Set serial number for next certificate and save it in the CA storage. + * + * Used by CKMSetCAInfo() + * + * @param[in] serNum certificate serial number to be set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetSerialNumber (const long serNum); + +/** + * Set CA common name and save it in the CA storage. + * + * Used by CKMSetCAInfo() + * + * @param[in] rootName CA common name to be set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetRootName (const ByteArray rootName); + +/** + * Set CA info and save it in the CA storage. + * + * Should be called before certificate generation + * + * @param[in] serNum certificate serial number to be set + * @param[in] rootName CA common name to be set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMSetCAInfo (const long serNum, const ByteArray rootName); + +/** + * Generate key pair for CA. + * + * Should be called before certificate generation + * + * @param[out] caPrivateKey pointer to allocated ByteArray for CA private key + * @param[out] caPublicKey pointer to allocated ByteArray for CA public key + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateCAKeyPair (ByteArray *caPrivateKey, ByteArray *caPublicKey); + +/** + * Issues X.509 certificate with specified parameters. + * + * SetSerialNumber, SetRootName and GenerateCAKeyPair should be called before. + * + * @param[in] uint8NotBefore pointer to string with certificate validity limit + * or 0 to use default value + * @param[in] uint8NotAfter pointer to string with certificate validity limit + * or 0 to use default value + * @param[out] issuedCertificate pointer to allocated memory for DER encoded certificate + * (ISSUER_MAX_CERT_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMIssueRootCertificate (const uint8_t *uint8NotBefore, const uint8_t *uint8NotAfter, + ByteArray *issuedRootCertificate); + +/** + * Generate key pair for ordinary device. + * + * @param[out] privateKey pointer to allocated ByteArray for private key + * @param[out] publicKey pointer to allocated ByteArray for public key + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateKeyPair (ByteArray *privateKey, ByteArray *publicKey); + +/** + * Issues X.509 certificate with specified parameters. + * + * SetSerialNumber, SetRootName and GenerateCAKeyPair should be called before. + * + * @param[in] uint8SubjectName pointer to string with serial subject's common name + * or 0 to use default value + * @param[in] uint8NotBefore pointer to string with certificate validity limit + * or 0 to use default value + * @param[in] uint8NotAfter pointer to string with certificate validity limit + * or 0 to use default value + * @param[in] uint8SubjectPublicKey pointer to array with subject's public key to be signed + * @param[out] issuedCertificate pointer to allocated memory for DER encoded certificate + * (ISSUER_MAX_CERT_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMIssueDeviceCertificate (const uint8_t *uint8SubjectName, + const uint8_t *uint8NotBefore, const uint8_t *uint8NotAfter, + const uint8_t *uint8SubjectPublicKey, + ByteArray *issuedCertificate); + +/** + * Write certificate into specified file. + * + * @param[in] certificate pointer to DER-encoded certificate that should be written into the file + * @param[in] certFileName pointer to null-terminated string with file name + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateDERCertificateFile (const ByteArray *certificate, const char *certFileName); + +/** + * Issues certificate signing request with specified parameters. + * + * @param[in] uint8SubjectName pointer to string with serial subject's common name + * or 0 to use default value + * @param[in] uint8SubjectPublicKey pointer to array with subject's public key to be signed + * @param[in] uint8SubjectPrivateKey pointer to array with subject's private key to be signed + * @param[out] encodedCSR pointer to allocated memory for DER encoded certificate signing request + * (CSR_MAX_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateCSR (const uint8_t *uint8SubjectName, + const uint8_t *uint8SubjectPublicKey, + const uint8_t *uint8SubjectPrivateKey, + ByteArray *encodedCSR); + +/** + * Issues X.509 certificate based on certificate signing request. + * + * @param[in] encodedCSR pointer to array with DER encoded certificate signing request + * @param[out] issuedCertificate pointer to allocated memory for DER encoded certificate + * (MAX_CERT_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateCertificateByCSR (const ByteArray *encodedCSR, ByteArray *issuedCertificate); + +/** + * Generate certificate revocation list with specified parameters. + * + * @param[in] thisUpdateTime pointer to time of issuing CRL or 0 to use default + * @param[in] nuberOfRevoked number of revoked certificates + * @param[in] revokedNumbers array with numbers of revoked certificates + * @param[in] revocationDates + * @param[out] encodedCRL pointer to allocated memory for DER encoded certificate revocation list + * ( (CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)) bytes + * should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMIssueCRL (const uint8_t *uint8ThisUpdateTime, const uint32_t nuberOfRevoked, + const uint32_t *revokedNumbers, const uint8_t **revocationDates, + ByteArray *encodedCRL); + +/** + * Gets current certificate revocation list. + * + * @param[out] certificateRevocationList pointer to the certificate revocation list to get + * (Memory should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMGetCRL (ByteArray *certificateRevocationList); + +/** + * Add specified certificate into certificate revocation list. + * + * @param[in] thisUpdateTime pointer to time of issuing CRL or 0 to use default + * @param[in] revokedNumber number of certificate to revoke + * @param[out] encodedCRL pointer to allocated memory for DER encoded certificate revocation list + * ( (CRL_MIN_SIZE + number of ALL revoked certificates * + * (sizeof(CertificateRevocationInfo_t) + 4)) bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CKMRevocateCertificate (const uint8_t *uint8ThisUpdateTime, const long revokedNumber, + ByteArray *encodedCRL); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_MASTER_ISSUER_H_ */ diff --git a/resource/csdk/security/provisioning/ck_manager/include/ckm_info.h b/resource/csdk/security/provisioning/ck_manager/include/ckm_info.h new file mode 100644 index 0000000..c3ce9d3 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/include/ckm_info.h @@ -0,0 +1,328 @@ +/****************************************************************** + * + * 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 INCLUDE_CA_STORAGE_H_ +#define INCLUDE_CA_STORAGE_H_ + +#include "byte_array.h" +#include +#include "pki_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CA_STORAGE_FILE "ckminfo.dat" +#define CA_STORAGE_CRT_FILE "crt.der" +#define ISSUER_MAX_NAME_SIZE (100) +#define PRIVATE_KEY_SIZE (32) +#define PUBLIC_KEY_SIZE (64) +#define ISSUER_MAX_CERT_SIZE (1000) +/** + * Certificate Authority storage + */ +typedef struct /*CA private key, CA certificate, other CA-related info*/ +{ + uint8_t CKMInfoIsLoaded; + + uint8_t CAPrivateKeyIsSet; + uint8_t CAPrivateKey[PRIVATE_KEY_SIZE]; + + uint8_t CAPublicKeyIsSet; + uint8_t CAPublicKey[PUBLIC_KEY_SIZE]; + + uint8_t CAChainLength; + + ByteArray *CACertificateChain; + + uint32_t CANameSize; + uint8_t CAName[ISSUER_MAX_NAME_SIZE]; + + long nextSerialNumber; + + long CRLSerialNumber; + + long numberOfRevoked; +} CKMInfo_t; + +typedef struct /*CA private key, CA certificate, certificate revocation/white list*/ +{ + uint32_t CRLsize; + uint8_t *certificateRevocationList;//should be allocated dynamically +} CRLInfo_t; + +//General functions + +/** + * Initializes CA storage from CA_STORAGE_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError InitCKMInfo(void); + +/** + * Saves CA storage into CA_STORAGE_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SaveCKMInfo(void); + +/** + * Frees CA storage memory. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError CloseCKMInfo(void); + +/** + * Sets CKM Info. + * + * @param[in] nextSN pointer to the next serial number to set + * or 0 to skip this parameter + * @param[in] CRLSerialNumber pointer to the next CRL serial number to set + * or 0 to skip this parameter + * @param[in] CAPrivateKey pointer to the CA's private key to set + * or 0 to skip this parameter + * @param[in] CAPublicKey pointer to the CA's public key to set + * or 0 to skip this parameter + * @param[in] CAName pointer to the CA's common name to set + * or 0 to skip this parameter + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCKMInfo (const long *nextSN, const long *CRLSerialNumber, + const ByteArray *CAPrivateKey, const ByteArray *CAPublicKey, + const ByteArray *CAName); + +/** + * Gets CKM Info. + * + * @param[out] nextSN pointer to the next serial number to get + * (Memory should be allocated before call) + * or 0 to skip this parameter + * @param[out] CRLSerialNumber pointer to the next CRL serial number to get + * (Memory should be allocated before call) + * or 0 to skip this parameter + * @param[out] CAPrivateKey pointer to the CA's private key to get + * (PRIVATE_KEY_SIZE bytes should be allocated before call) + * or 0 to skip this parameter + * @param[out] CAPublicKey pointer to the CA's public key to get + * (PUBLIC_KEY_SIZE bytes should be allocated before call) + * or 0 to skip this parameter + * @param[out] CAName pointer to the CA's common name to get + * (ISSUER_MAX_NAME_SIZE bytes should be allocated before call) + * or 0 to skip this parameter + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCKMInfo (long *nextSN, long *CRLSerialNumber, + ByteArray *CAPrivateKey, ByteArray *CAPublicKey, + ByteArray *CAName); + +/** + * Sets CA's private key. + * + * @param[in] CAPrivateKey pointer to the CA's private key to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCAPrivateKey (const ByteArray *CAPrivateKey); + +/** + * Gets CA's private key. + * + * @param[out] CAPrivateKey pointer to the CA's private key to get + * (PRIVATE_KEY_SIZE bytes should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCAPrivateKey (ByteArray *CAPrivateKey); + +/** + * Sets CA's public key. + * + * @param[in] CAPublicKey pointer to the CA's public key to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCAPublicKey (const ByteArray *CAPublicKey); + +/** + * Gets CA's public key. + * + * @param[out] CAPublicKey pointer to the CA's public key to get + * (PUBLIC_KEY_SIZE bytes should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCAPublicKey (ByteArray *CAPublicKey); + +/** + * Sets CA's common name. + * + * @param[in] CAName pointer to the CA's common name to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCAName (const ByteArray *CAName); + +/** + * Gets CA's common name. + * + * @param[out] CAName pointer to the CA's common name to get + * (ISSUER_MAX_NAME_SIZE bytes should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCAName (ByteArray *CAName); + +//Certificate-related functions + +/** + * Initializes CA Certificate from CA_STORAGE_CRT_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError InitCRT(void); + +/** + * Saves CA Certificate into CA_STORAGE_CRT_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SaveCRT(void); + +/** + * Sets next serial number for certificate issuer. + * + * @param[in] nextSN pointer to the next serial number to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetNextSerialNumber (const long *nextSN); + +/** + * Gets next serial number for certificate issuer. + * + * @param[out] nextSN pointer to the next serial number to get + * (Memory should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetNextSerialNumber (long *nextSN); + +/** + * Sets DER encoded CA's certificate chain. + * + * @param[in] CAChain pointer to the CA's certificate to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCAChain (const uint8_t CAChainLength, const ByteArray *CAChain); + +/** + * Gets DER encoded CA's certificate chain. + * + * @param[out] CAChain pointer to allocated memory to get the CA's certificate chain + * (ISSUER_MAX_CHAIN_SIZE bytes should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCAChain (uint8_t* CAChainLength, ByteArray *CAChain); + +/** + * Sets DER encoded CA's certificate. + * + * @param[in] CACertificate pointer to the CA's certificate to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCACertificate (const ByteArray *CACertificate); + +/** + * Gets DER encoded CA's certificate. + * + * @param[out] CACertificate pointer to the CA's certificate to get + * (ISSUER_MAX_CERT_SIZE bytes should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCACertificate (ByteArray *CACertificate); + +//CRL-related functions + +/** + * Initializes CRL from CA_STORAGE_CRL_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError InitCRL(void); + +/** + * Saves CRL into CA_STORAGE_CRL_FILE. + * + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SaveCRL(void); + +/** + * Sets next CRL serial number for certificate issuer. + * + * @param[in] CRLSerialNumber pointer to the next CRL serial number to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCRLSerialNumber (const long *CRLSerialNumber); + +/** + * Gets next CRL serial number for certificate issuer. + * + * @param[out] CRLSerialNumber pointer to the next CRL serial number to get + * (Memory should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCRLSerialNumber (long *CRLSerialNumber); + +/** + * Sets current certificate revocation list. + * + * @param[in] certificateRevocationList pointer to the certificate revocation list to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetCertificateRevocationList (const ByteArray *certificateRevocationList); + +/** + * Gets current certificate revocation list. + * + * @param[out] certificateRevocationList pointer to the certificate revocation list to get + * (Memory should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetCertificateRevocationList (ByteArray *certificateRevocationList); + +/** + * Sets number of revoked certificates. + * + * @param[in] numberOfRevoked pointer to number of revoked certificates to set + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SetNumberOfRevoked (const long *numberOfRevoked); + +/** + * Gets number of revoked certificates. + * + * @param[out] numberOfRevoked pointer to number of revoked certificates to get + * (Memory should be allocated before call) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GetNumberOfRevoked (long *numberOfRevoked); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_CA_STORAGE_H_ */ diff --git a/resource/csdk/security/provisioning/ck_manager/include/crl_generator.h b/resource/csdk/security/provisioning/ck_manager/include/crl_generator.h new file mode 100644 index 0000000..dfdec1c --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/include/crl_generator.h @@ -0,0 +1,75 @@ +/****************************************************************** + * + * 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 INCLUDE_MASTER_CRL_ENCODER_H_ +#define INCLUDE_MASTER_CRL_ENCODER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "CertificateRevocationList.h" /* CertificateList ASN.1 type */ +#include "pki.h" +#include "pki_errors.h" + +// Minimal memory allocated for DER encoded CRL +#define CRL_MIN_SIZE 250 //minimal size of CRL (issuer info + signature) + +#define CRL_MAX_NAME_SIZE 100 //maximal length of CRL issuer field + +/** + * Encode certificate revocation list with specified parameters. + * + * @param[in] issuerName pointer to issuer's common name + * @param[in] thisUpdateTime pointer to time of issuing CRL + * @param[in] nuberOfRevoked number of revoked certificates + * @param[in] certificateRevocationInfo array with certificate revocation info + * @param[in] issuerPrivateKey pointer to issuer's private key to sign CRL + * @param[out] encodedCRL pointer to allocated memory for DER encoded certificate revocation list + * ( (CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)) bytes + * should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError GenerateCRL (const UTF8String_t *issuerName, + const UTCTime_t *thisUpdateTime, const uint32_t nuberOfRevoked, + const CertificateRevocationInfo_t *certificateRevocationInfo, + const BIT_STRING_t *issuerPrivateKey, ByteArray *encodedCRL); + +/** + * Sign certificate revocation list. + * + * @param[in] certificateRevocationList pointer to CRL for signing + * @param[in] crlMaxSize max size of DER encoded CRL + * @param[in] issuerPrivateKey pointer to issuer private key + * @param[out] encodedCRL pointer to allocated memory for DER encoded certificate revocation list + * crlMaxSize bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError SignCRL(CertificateRevocationList_t *certificateRevocationList, + const uint32_t crlMaxSize, const BIT_STRING_t *issuerPrivateKey, + ByteArray *encodedCRL); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_MASTER_CRL_ENCODER_H_ */ diff --git a/resource/csdk/security/provisioning/ck_manager/include/csr_generator.h b/resource/csdk/security/provisioning/ck_manager/include/csr_generator.h new file mode 100644 index 0000000..e1f0870 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/include/csr_generator.h @@ -0,0 +1,74 @@ +/****************************************************************** + * + * 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 INCLUDE_MASTER_CSR_H_ +#define INCLUDE_MASTER_CSR_H_ + +#include "CertificationRequest.h" /* CertificationRequest ASN.1 type */ +#include "pki.h" +#include "pki_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Memory allocated for DER encoded CSR +#define CSR_MAX_SIZE 1000 + +#define CSR_DEFAULT_VERSION 0 +#define CSR_MAX_NAME_SIZE 100 + +/** + * Encode certificate signing request with specified parameters. + * + * @param[in] subjectName pointer to subject's common name + * @param[in] subjectPublicKey pointer to subject's public key to be signed + * @param[in] subjectPrivateKey pointer to subject's private key to be signed + * @param[out] encodedCSR pointer to allocated memory for DER encoded certificate signing request + * (CSR_MAX_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError EncodeCSR (const UTF8String_t *subjectName, + const BIT_STRING_t *subjectPublicKey, + const BIT_STRING_t *subjectPrivateKey, + ByteArray *encodedCSR); + +/** + * Decode certificate signing request, extracts its common name and public key. + * + * Return error if signature is not valid. + * + * @param[in] encodedCSR pointer to array with DER encoded certificate signing request + * @param[out] subjectName pointer to allocated memory for subject's common name extraction + * (CSR_MAX_NAME_SIZE bytes should be allocated) + * @param[out] subjectPublicKey pointer to allocated memory for subject's public key extraction + * (PUBLIC_KEY_SIZE bytes should be allocated) + * @return PKI_SUCCESS if success, error code otherwise + */ +PKIError DecodeCSR (const ByteArray *encodedCSR, + UTF8String_t *subjectName, BIT_STRING_t *subjectPublicKey); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_MASTER_CSR_H_ */ diff --git a/resource/csdk/security/provisioning/ck_manager/src/cert_generator.c b/resource/csdk/security/provisioning/ck_manager/src/cert_generator.c new file mode 100644 index 0000000..ec9bf74 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/src/cert_generator.c @@ -0,0 +1,243 @@ +/****************************************************************** + * + * 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 "cert_generator.h" +#include "ckm_info.h" +#include "pki.h" +#include "oic_malloc.h" + +//ecdsa-with-SHA256 1.2.840.10045.4.3.2 [RFC5759] +static const uint8_t g_ECDSA_WITH_SHA256_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; + +//Elliptic Curve Digital Signature Algorithm (ECDSA) 1.2.840.10045.2.1 [RFC7250] +static const uint8_t g_EC_PUBLIC_KEY_OID[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}; + +//secp256r1 1.2.840.10045.3.1.7 [RFC5656] +static const uint8_t g_PRIME_256_V1_OID[] = {0x2A, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; + +//commonName 2.5.4.3 [RFC2256] +static const uint8_t g_COMMON_NAME_OID[] = {0x55, 0x04, 0x03}; + + +PKIError GenerateCertificate (const UTF8String_t *subjectName, const UTF8String_t *issuerName, + const UTCTime_t *notBefore, const UTCTime_t *notAfter, + const BIT_STRING_t *subjectPublicKey, const BIT_STRING_t *issuerPrivateKey, + ByteArray *encodedCertificate) +{ + FUNCTION_INIT(); + asn_enc_rval_t ec; /* Encoder return value */ + Certificate_t *certificate = NULL; /* Type to encode */ + AttributeTypeAndValue_t *issuerTypeAndValue = NULL; + AttributeTypeAndValue_t *subjectTypeAndValue = NULL; + RelativeDistinguishedName_t *issuerRDN = NULL; + RelativeDistinguishedName_t *subjectRDN = NULL; + uint8_t *uint8Pointer = NULL; + ByteArray tbs = BYTE_ARRAY_INITIALIZER; + uint8_t signature[SIGN_FULL_SIZE]; + uint8_t sha256[SHA_256_HASH_LEN]; + uint8_t tbsDer[ISSUER_MAX_CERT_SIZE]; + long serialNumber = 0; + + CHECK_NULL(subjectName, ISSUER_X509_NULL_PASSED); + CHECK_NULL(issuerName, ISSUER_X509_NULL_PASSED); + CHECK_NULL(notBefore, ISSUER_X509_NULL_PASSED); + CHECK_NULL(notAfter, ISSUER_X509_NULL_PASSED); + CHECK_NULL(subjectPublicKey, ISSUER_X509_NULL_PASSED); + CHECK_NULL(issuerPrivateKey, ISSUER_X509_NULL_PASSED); + CHECK_NULL_BYTE_ARRAY_PTR(encodedCertificate, ISSUER_X509_NULL_PASSED); + CHECK_LESS_EQUAL(ISSUER_MAX_CERT_SIZE, encodedCertificate->len, + ISSUER_X509_WRONG_BYTE_ARRAY_LEN); + + /* Allocate the memory */ + certificate = OICCalloc(1, sizeof(Certificate_t)); // not malloc! + CHECK_NULL(certificate, ISSUER_X509_MEMORY_ALLOC_FAILED); + + issuerTypeAndValue = OICCalloc(1, sizeof(AttributeTypeAndValue_t)); + CHECK_NULL(issuerTypeAndValue, ISSUER_X509_MEMORY_ALLOC_FAILED); + + issuerRDN = OICCalloc(1, sizeof(RelativeDistinguishedName_t)); + CHECK_NULL(issuerRDN, ISSUER_X509_MEMORY_ALLOC_FAILED); + + subjectTypeAndValue = OICCalloc(1, sizeof(AttributeTypeAndValue_t)); + CHECK_NULL(subjectTypeAndValue, ISSUER_X509_MEMORY_ALLOC_FAILED); + + subjectRDN = OICCalloc(1, sizeof(RelativeDistinguishedName_t)); + CHECK_NULL(subjectRDN, ISSUER_X509_MEMORY_ALLOC_FAILED); + + //set issuer name + issuerTypeAndValue->value = *issuerName; + issuerTypeAndValue->type.buf = (uint8_t *)g_COMMON_NAME_OID; //2.5.4.3 + issuerTypeAndValue->type.size = sizeof(g_COMMON_NAME_OID) / sizeof(g_COMMON_NAME_OID[0]); + ASN_SET_ADD(issuerRDN, issuerTypeAndValue); + ASN_SEQUENCE_ADD(&(certificate->tbsCertificate.issuer), issuerRDN); + + //set subject name + subjectTypeAndValue->value = *subjectName; + subjectTypeAndValue->type.buf = (uint8_t *)g_COMMON_NAME_OID; //2.5.4.3 + subjectTypeAndValue->type.size = sizeof(g_COMMON_NAME_OID) / sizeof(g_COMMON_NAME_OID[0]); + ASN_SET_ADD(subjectRDN, subjectTypeAndValue); + ASN_SEQUENCE_ADD(&(certificate->tbsCertificate.subject), subjectRDN); + + //set validity + certificate->tbsCertificate.validity.notBefore = *notBefore; + certificate->tbsCertificate.validity.notAfter = *notAfter; + + //set X.509 certificate version + certificate->tbsCertificate.version = X509_V2; + + //set serial number + certificate->tbsCertificate.serialNumber = 0; + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetNextSerialNumber, &serialNumber); + certificate->tbsCertificate.serialNumber = serialNumber; + serialNumber++; + CHECK_CALL(SetNextSerialNumber, &serialNumber); + CHECK_CALL(SaveCKMInfo); + + //set signature algorithm in TBS + certificate->tbsCertificate.signature.algorithm.buf = + (uint8_t *)g_ECDSA_WITH_SHA256_OID; //1.2.840.10045.4.3.2 + certificate->tbsCertificate.signature.algorithm.size = + sizeof(g_ECDSA_WITH_SHA256_OID) / sizeof(g_ECDSA_WITH_SHA256_OID[0]); + certificate->tbsCertificate.signature.nul = OICCalloc(1, sizeof(NULL_t)); + CHECK_NULL(certificate->tbsCertificate.signature.nul, ISSUER_X509_MEMORY_ALLOC_FAILED); + + //set subject Public Key algorithm + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.buf = + (uint8_t *)g_EC_PUBLIC_KEY_OID; //1.2.840.10045.2.1 + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.size = + sizeof(g_EC_PUBLIC_KEY_OID) / sizeof(g_EC_PUBLIC_KEY_OID[0]); + + //set subject Public Key curve + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.id_ecPublicKey = + OICCalloc(1, sizeof(OBJECT_IDENTIFIER_t)); + CHECK_NULL(certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.id_ecPublicKey, + ISSUER_X509_MEMORY_ALLOC_FAILED); + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.id_ecPublicKey->buf = + (uint8_t *)g_PRIME_256_V1_OID; //1.2.840.10045.3.1.7 + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.id_ecPublicKey->size = + sizeof(g_PRIME_256_V1_OID) / sizeof(g_PRIME_256_V1_OID[0]); + + //set subject Public Key + certificate->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey = *subjectPublicKey; + + //set signature algorithm + certificate->signatureAlgorithm.algorithm.buf = (uint8_t *)g_ECDSA_WITH_SHA256_OID; + certificate->signatureAlgorithm.algorithm.size = + sizeof(g_ECDSA_WITH_SHA256_OID) / sizeof(g_ECDSA_WITH_SHA256_OID[0]); + certificate->signatureAlgorithm.nul = OICCalloc(1, sizeof(NULL_t)); + CHECK_NULL(certificate->signatureAlgorithm.nul, ISSUER_X509_MEMORY_ALLOC_FAILED); + + //encode TBS to DER + ec = der_encode_to_buffer(&asn_DEF_TBSCertificate, &(certificate->tbsCertificate), + tbsDer, ISSUER_MAX_CERT_SIZE); + CHECK_COND(ec.encoded > 0, ISSUER_X509_DER_ENCODE_FAIL); + tbs.len = ec.encoded; + tbs.data = tbsDer; + GET_SHA_256(tbs, sha256); + CHECK_COND(uECC_sign((issuerPrivateKey->buf) + 1, sha256, signature), + ISSUER_X509_SIGNATURE_FAIL); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + + // ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER } (RFC 5480) + certificate->signatureValue.size = SIGN_FULL_SIZE + 6;// size for SEQUENCE ID + 2 * INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + certificate->signatureValue.size ++; + } + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[SIGN_R_LEN] > 127) + { + certificate->signatureValue.size ++; + } + certificate->signatureValue.buf = OICCalloc(certificate->signatureValue.size, sizeof(uint8_t)); + CHECK_NULL(certificate->signatureValue.buf, ISSUER_X509_MEMORY_ALLOC_FAILED); + *(certificate->signatureValue.buf) = (12 << 2); //ASN.1 SEQUENCE ID + *(certificate->signatureValue.buf + 1) = certificate->signatureValue.size - 2; + //ASN.1 SEQUENCE size + + uint8Pointer = certificate->signatureValue.buf + 2; //skip SEQUENCE ID and size + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + *(uint8Pointer + 1) = SIGN_R_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_R_LEN; //ASN.1 INTEGER SIZE + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature, SIGN_R_LEN); + + uint8Pointer += SIGN_R_LEN; //skip first part of signature + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature [SIGN_R_LEN] > 127) + { + *(uint8Pointer + 1) = SIGN_S_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_S_LEN; //ASN.1 INTEGER size + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature + SIGN_R_LEN, SIGN_S_LEN); + + ec = der_encode_to_buffer(&asn_DEF_Certificate, certificate, + encodedCertificate->data, ISSUER_MAX_CERT_SIZE); + CHECK_COND(ec.encoded > 0, ISSUER_X509_DER_ENCODE_FAIL); + encodedCertificate->len = ec.encoded; + + FUNCTION_CLEAR( + if (issuerTypeAndValue) + { + issuerTypeAndValue->value.buf = NULL; + issuerTypeAndValue->type.buf = NULL; + } + if (subjectTypeAndValue) + { + subjectTypeAndValue->value.buf = NULL; + subjectTypeAndValue->type.buf = NULL; + } + if (certificate) + { + certificate->tbsCertificate.validity.notBefore.buf = NULL; + certificate->tbsCertificate.validity.notAfter.buf = NULL; + certificate->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.buf = NULL; + certificate->tbsCertificate.signature.algorithm.buf = NULL; + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm.buf = NULL; + certificate->tbsCertificate.subjectPublicKeyInfo.algorithm.id_ecPublicKey->buf = NULL; + certificate->signatureAlgorithm.algorithm.buf = NULL; + } + ASN_STRUCT_FREE(asn_DEF_Certificate, certificate); + certificate = NULL; + ); +} diff --git a/resource/csdk/security/provisioning/ck_manager/src/ck_manager.c b/resource/csdk/security/provisioning/ck_manager/src/ck_manager.c new file mode 100644 index 0000000..df79fd5 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/src/ck_manager.c @@ -0,0 +1,669 @@ +/****************************************************************** + * + * 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 "ck_manager.h" +#include "crlresource.h" +#include "oic_malloc.h" + +/* 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_ID (0x04) + +PKIError GenerateCAKeyPair (ByteArray *caPrivateKey, ByteArray *caPublicKey) +{ + FUNCTION_INIT(); + + CHECK_NULL(caPrivateKey, ISSUER_NULL_PASSED); + CHECK_NULL(caPrivateKey->data, ISSUER_NULL_PASSED); + CHECK_NULL(caPublicKey, ISSUER_NULL_PASSED); + CHECK_NULL(caPublicKey->data, ISSUER_NULL_PASSED); + + CHECK_COND(uECC_make_key(caPublicKey->data, caPrivateKey->data), ISSUER_MAKE_KEY_ERROR); + caPublicKey->len = PUBLIC_KEY_SIZE; + caPrivateKey->len = PRIVATE_KEY_SIZE; + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(SetCAPrivateKey, caPrivateKey); + CHECK_CALL(SetCAPublicKey, caPublicKey); + CHECK_CALL(SaveCKMInfo); + FUNCTION_CLEAR(); +} + +PKIError CKMIssueRootCertificate (const uint8_t *uint8NotBefore, const uint8_t *uint8NotAfter, + ByteArray *issuedRootCertificate) +{ + FUNCTION_INIT(); + + UTF8String_t *rootName = NULL; + UTCTime_t *notBefore = NULL; + UTCTime_t *notAfter = NULL; + BIT_STRING_t *subjectPublicKey = NULL; + BIT_STRING_t *issuerPrivateKey = NULL; + + ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER; + ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER; + ByteArray caName = BYTE_ARRAY_INITIALIZER; + + uint8_t caPublicKey[PUBLIC_KEY_SIZE]; + uint8_t caPrivateKey[PRIVATE_KEY_SIZE]; + uint8_t uint8caName[ISSUER_MAX_NAME_SIZE]; + + CHECK_NULL(issuedRootCertificate, ISSUER_NULL_PASSED); + CHECK_NULL(issuedRootCertificate->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL(ISSUER_MAX_CERT_SIZE, issuedRootCertificate->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + pubKeyIss.data = caPublicKey; + pubKeyIss.len = PUBLIC_KEY_SIZE; + privKeyIss.data = caPrivateKey; + privKeyIss.len = PRIVATE_KEY_SIZE; + caName.data = uint8caName; + caName.len = ISSUER_MAX_NAME_SIZE; + + rootName = (UTF8String_t *)OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(rootName, ISSUER_MEMORY_ALLOC_FAILED); + + notBefore = (UTCTime_t *)OICCalloc(1, sizeof(UTCTime_t)); + CHECK_NULL(notBefore, ISSUER_MEMORY_ALLOC_FAILED); + + notAfter = (UTCTime_t *)OICCalloc(1, sizeof(UTCTime_t)); + CHECK_NULL(notAfter, ISSUER_MEMORY_ALLOC_FAILED); + + subjectPublicKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(subjectPublicKey, ISSUER_MEMORY_ALLOC_FAILED); + + issuerPrivateKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(issuerPrivateKey, ISSUER_MEMORY_ALLOC_FAILED); + + //RootName + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAName, &caName); + rootName->buf = caName.data; + rootName->size = caName.len; + + //notBefore + if (uint8NotBefore) + { + notBefore->buf = (uint8_t *)uint8NotBefore; + } + else + { + notBefore->buf = (uint8_t *)ISSUER_DEFAULT_NOT_BEFORE; + } + notBefore->size = strlen((const char *)notBefore->buf); + + //notAfter + if (uint8NotAfter) + { + notAfter->buf = (uint8_t *)uint8NotAfter; + } + else + { + notAfter->buf = (uint8_t *)ISSUER_DEFAULT_NOT_AFTER; + } + notAfter->size = strlen((const char *)notAfter->buf); + + //common keys + issuerPrivateKey->size = PRIVATE_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + issuerPrivateKey->buf = (uint8_t *)OICCalloc((issuerPrivateKey->size), sizeof(uint8_t)); + CHECK_NULL(issuerPrivateKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(issuerPrivateKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + + subjectPublicKey->size = PUBLIC_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + subjectPublicKey->buf = (uint8_t *)OICCalloc(subjectPublicKey->size, sizeof(uint8_t)); + CHECK_NULL(subjectPublicKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(subjectPublicKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + //common keys + + //read CA key pair from the CA storage + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAPrivateKey, &privKeyIss); + + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((issuerPrivateKey->buf) + 1, privKeyIss.data, PRIVATE_KEY_SIZE); + CHECK_CALL(GetCAPublicKey, &pubKeyIss); + + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((subjectPublicKey->buf) + 1, pubKeyIss.data, PUBLIC_KEY_SIZE); + + CHECK_CALL(GenerateCertificate, rootName, rootName, notBefore, notAfter, + subjectPublicKey, issuerPrivateKey, issuedRootCertificate); + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(SetCACertificate, issuedRootCertificate); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR( + OICFree(rootName); + OICFree(notBefore); + OICFree(notAfter); + ASN_STRUCT_FREE(asn_DEF_BIT_STRING, subjectPublicKey); + ASN_STRUCT_FREE(asn_DEF_BIT_STRING, issuerPrivateKey); + ); +} + +PKIError GenerateKeyPair (ByteArray *privateKey, ByteArray *publicKey) +{ + FUNCTION_INIT(); + CHECK_NULL(privateKey, ISSUER_NULL_PASSED); + CHECK_NULL(privateKey->data, ISSUER_NULL_PASSED); + CHECK_NULL(publicKey, ISSUER_NULL_PASSED); + CHECK_NULL(publicKey->data, ISSUER_NULL_PASSED); + CHECK_COND(uECC_make_key(publicKey->data, privateKey->data), ISSUER_MAKE_KEY_ERROR); + publicKey->len = PUBLIC_KEY_SIZE; + privateKey->len = PRIVATE_KEY_SIZE; + FUNCTION_CLEAR(); +} + +PKIError CKMIssueDeviceCertificate (const uint8_t *uint8SubjectName, + const uint8_t *uint8NotBefore, const uint8_t *uint8NotAfter, + const uint8_t *uint8SubjectPublicKey, + ByteArray *issuedCertificate) +{ + FUNCTION_INIT(); + + UTF8String_t *subjectName = NULL; + UTF8String_t *issuerName = NULL; + UTCTime_t *notBefore = NULL; + UTCTime_t *notAfter = NULL; + BIT_STRING_t *subjectPublicKey = NULL; + BIT_STRING_t *issuerPrivateKey = NULL; + + ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER; + ByteArray pubKeySubj = BYTE_ARRAY_INITIALIZER; + ByteArray privKeySubj = BYTE_ARRAY_INITIALIZER; + ByteArray caName = BYTE_ARRAY_INITIALIZER; + + uint8_t subjPubKey[PUBLIC_KEY_SIZE]; + uint8_t subjPrivKey[PRIVATE_KEY_SIZE]; + uint8_t caPrivateKey[PRIVATE_KEY_SIZE]; + uint8_t uint8caName[ISSUER_MAX_NAME_SIZE]; + + CHECK_NULL(uint8SubjectPublicKey, ISSUER_NULL_PASSED); + CHECK_NULL(issuedCertificate, ISSUER_NULL_PASSED); + CHECK_NULL(issuedCertificate->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL(ISSUER_MAX_CERT_SIZE, issuedCertificate->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + privKeyIss.data = caPrivateKey; + privKeyIss.len = PRIVATE_KEY_SIZE; + pubKeySubj.data = subjPubKey; + pubKeySubj.len = PUBLIC_KEY_SIZE; + privKeySubj.data = subjPrivKey; + privKeySubj.len = PRIVATE_KEY_SIZE; + caName.data = uint8caName; + caName.len = ISSUER_MAX_NAME_SIZE; + + subjectName = (UTF8String_t *)OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(subjectName, ISSUER_MEMORY_ALLOC_FAILED); + + issuerName = (UTF8String_t *)OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(issuerName, ISSUER_MEMORY_ALLOC_FAILED); + + notBefore = (UTCTime_t *)OICCalloc(1, sizeof(UTCTime_t)); + CHECK_NULL(notBefore, ISSUER_MEMORY_ALLOC_FAILED); + + notAfter = (UTCTime_t *)OICCalloc(1, sizeof(UTCTime_t)); + CHECK_NULL(notAfter, ISSUER_MEMORY_ALLOC_FAILED); + + subjectPublicKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(subjectPublicKey, ISSUER_MEMORY_ALLOC_FAILED); + + issuerPrivateKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(issuerPrivateKey, ISSUER_MEMORY_ALLOC_FAILED); + + //SubjectName + if (uint8SubjectName) + { + subjectName->buf = (uint8_t *)uint8SubjectName; + } + else + { + subjectName->buf = (uint8_t *)ISSUER_DEFAULT_SUBJECT_NAME; + } + subjectName->size = strlen((const char *)subjectName->buf); + + //IssuerName + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAName, &caName); + issuerName->buf = caName.data; + issuerName->size = caName.len; + + //notBefore + if (uint8NotBefore) + { + notBefore->buf = (uint8_t *)uint8NotBefore; + } + else + { + notBefore->buf = (uint8_t *)ISSUER_DEFAULT_NOT_BEFORE; + } + notBefore->size = strlen((const char *)notBefore->buf); + + //notAfter + if (uint8NotAfter) + { + notAfter->buf = (uint8_t *)uint8NotAfter; + } + else + { + notAfter->buf = (uint8_t *)ISSUER_DEFAULT_NOT_AFTER; + } + notAfter->size = strlen((const char *)notAfter->buf); + + //common keys + issuerPrivateKey->size = PRIVATE_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + issuerPrivateKey->buf = (uint8_t *)OICCalloc((issuerPrivateKey->size), sizeof(uint8_t)); + CHECK_NULL(issuerPrivateKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(issuerPrivateKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + + subjectPublicKey->size = PUBLIC_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + subjectPublicKey->buf = (uint8_t *)OICCalloc(subjectPublicKey->size, sizeof(uint8_t)); + CHECK_NULL(subjectPublicKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(subjectPublicKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + //common keys + + //read CA private key from the CA storage + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAPrivateKey, &privKeyIss); + + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((issuerPrivateKey->buf) + 1, privKeyIss.data, PRIVATE_KEY_SIZE); + + if (!uint8SubjectPublicKey) + { + //GenerateKeyPair + GenerateKeyPair(&privKeySubj, &pubKeySubj); + } + else + { + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((subjectPublicKey->buf) + 1, uint8SubjectPublicKey, PUBLIC_KEY_SIZE); + } + + CHECK_CALL(GenerateCertificate, subjectName, issuerName, notBefore, notAfter, + subjectPublicKey, issuerPrivateKey, issuedCertificate); + + FUNCTION_CLEAR( + OICFree(subjectName); + OICFree(issuerName); + OICFree(notBefore); + OICFree(notAfter); + ASN_STRUCT_FREE(asn_DEF_BIT_STRING, subjectPublicKey); + ASN_STRUCT_FREE(asn_DEF_BIT_STRING, issuerPrivateKey); + ); +} + +PKIError GenerateDERCertificateFile (const ByteArray *certificate, const char *certFileName) +{ + FUNCTION_INIT(); + FILE *filePointer = NULL; + + CHECK_NULL(certFileName, ISSUER_NULL_PASSED); + CHECK_NULL(certificate, ISSUER_NULL_PASSED); + CHECK_NULL(certificate->data, ISSUER_NULL_PASSED); + filePointer = fopen(certFileName, "wb"); + CHECK_NULL(filePointer, ISSUER_FILE_WRITE_ERROR); + CHECK_EQUAL(fwrite(certificate->data, 1, certificate->len, filePointer), certificate->len, + ISSUER_FILE_WRITE_ERROR); + + FUNCTION_CLEAR( + if(filePointer) + { + fclose(filePointer); + } + filePointer = NULL; + ); +} + +PKIError SetSerialNumber (const long serNum) +{ + FUNCTION_INIT(); + + CHECK_LESS_EQUAL(0, serNum, ISSUER_WRONG_SERIAL_NUMBER); + CHECK_CALL(InitCKMInfo); + CHECK_CALL(SetNextSerialNumber, &serNum); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR(); +} + +PKIError SetRootName (const ByteArray rootName) +{ + FUNCTION_INIT(); + + CHECK_NULL(rootName.data, ISSUER_NULL_PASSED); + CHECK_LESS(0, rootName.len, ISSUER_WRONG_ROOT_NAME_LEN); + CHECK_LESS(rootName.len, ISSUER_MAX_NAME_SIZE, ISSUER_WRONG_ROOT_NAME_LEN); + CHECK_CALL(InitCKMInfo); + CHECK_CALL(SetCAName, &rootName); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR(); +} + +PKIError CKMSetCAInfo (const long serNum, const ByteArray rootName) +{ + FUNCTION_INIT(); + CHECK_CALL(SetSerialNumber, serNum); + CHECK_CALL(SetRootName, rootName); + + FUNCTION_CLEAR(); +} + +PKIError GenerateCSR (const uint8_t *uint8SubjectName, + const uint8_t *uint8SubjectPublicKey, + const uint8_t *uint8SubjectPrivateKey, + ByteArray *encodedCSR) +{ + FUNCTION_INIT(); + UTF8String_t *subjectName = NULL; + BIT_STRING_t *subjectPublicKey = NULL; + BIT_STRING_t *subjectPrivateKey = NULL; + + CHECK_NULL(uint8SubjectPublicKey, ISSUER_NULL_PASSED); + CHECK_NULL(uint8SubjectPrivateKey, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCSR, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCSR->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL(CSR_MAX_SIZE, encodedCSR->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + subjectName = OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(subjectName, ISSUER_MEMORY_ALLOC_FAILED); + + subjectPublicKey = OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(subjectPublicKey, ISSUER_MEMORY_ALLOC_FAILED); + + subjectPrivateKey = OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(subjectPrivateKey, ISSUER_MEMORY_ALLOC_FAILED); + + //SubjectName + if (uint8SubjectName) + { + subjectName->buf = (uint8_t *)uint8SubjectName; + } + else + { + subjectName->buf = (uint8_t *)ISSUER_DEFAULT_SUBJECT_NAME; + } + subjectName->size = strlen((const char *)subjectName->buf); + + //common keys + subjectPrivateKey->size = PRIVATE_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + subjectPrivateKey->buf = (uint8_t *)OICCalloc((subjectPrivateKey->size), sizeof(uint8_t)); + CHECK_NULL(subjectPrivateKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(subjectPrivateKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + + subjectPublicKey->size = PUBLIC_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + subjectPublicKey->buf = (uint8_t *)OICCalloc(subjectPublicKey->size, sizeof(uint8_t)); + CHECK_NULL(subjectPublicKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(subjectPublicKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + //common keys + + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((subjectPrivateKey->buf) + 1, uint8SubjectPrivateKey, PRIVATE_KEY_SIZE); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((subjectPublicKey->buf) + 1, uint8SubjectPublicKey, PUBLIC_KEY_SIZE); + + CHECK_CALL(EncodeCSR, subjectName, subjectPublicKey, subjectPrivateKey, encodedCSR); + + FUNCTION_CLEAR( + OICFree(subjectName); + OICFree(subjectPublicKey); + OICFree(subjectPrivateKey->buf); + OICFree(subjectPrivateKey); + ); +} + +PKIError GenerateCertificateByCSR (const ByteArray *encodedCSR, ByteArray *issuedCertificate) +{ + FUNCTION_INIT(); + UTF8String_t *subjectName = NULL; + BIT_STRING_t *subjectPublicKey = NULL; + uint8_t uint8SubjectName[ISSUER_MAX_NAME_SIZE]; + uint8_t uint8SubjectPublicKey[PUBLIC_KEY_SIZE + 1]; + + CHECK_NULL(encodedCSR, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCSR->data, ISSUER_NULL_PASSED); + CHECK_NULL(issuedCertificate, ISSUER_NULL_PASSED); + CHECK_NULL(issuedCertificate->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL(ISSUER_MAX_CERT_SIZE, issuedCertificate->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + subjectName = OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(subjectName, ISSUER_MEMORY_ALLOC_FAILED); + + subjectPublicKey = OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(subjectPublicKey, ISSUER_MEMORY_ALLOC_FAILED); + + subjectName->buf = uint8SubjectName; + subjectPublicKey->buf = uint8SubjectPublicKey; + + CHECK_CALL(DecodeCSR, encodedCSR, subjectName, subjectPublicKey); + + uint8SubjectName[subjectName->size] = '\0'; + CHECK_CALL(CKMIssueDeviceCertificate, uint8SubjectName, 0, 0, uint8SubjectPublicKey + 1, + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + issuedCertificate); + + FUNCTION_CLEAR( + OICFree(subjectPublicKey); + OICFree(subjectName); + ); +} + +PKIError CKMIssueCRL (const uint8_t *uint8ThisUpdateTime, const uint32_t numberOfRevoked, + const uint32_t *revokedNumbers, const uint8_t **revocationDates, + ByteArray *encodedCRL) +{ + FUNCTION_INIT(); + BIT_STRING_t *issuerPrivateKey = NULL; + UTCTime_t *thisUpdateTime = NULL; + CertificateRevocationInfo_t *certificateRevocationInfo = NULL; + UTF8String_t *issuerName = NULL; + uint32_t i; + + uint8_t caPrivateKey[PRIVATE_KEY_SIZE]; + uint8_t uint8caName[ISSUER_MAX_NAME_SIZE]; + + ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER; + ByteArray caName = BYTE_ARRAY_INITIALIZER; + + CHECK_NULL(numberOfRevoked, ISSUER_NULL_PASSED); + CHECK_NULL(revokedNumbers, ISSUER_NULL_PASSED); + CHECK_NULL(revocationDates, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCRL, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCRL->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL((CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)), + encodedCRL->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + issuerPrivateKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(issuerPrivateKey, ISSUER_MEMORY_ALLOC_FAILED); + + thisUpdateTime = (UTCTime_t *)OICCalloc(1, sizeof(UTCTime_t)); + CHECK_NULL(thisUpdateTime, ISSUER_MEMORY_ALLOC_FAILED); + + issuerName = (UTF8String_t *)OICCalloc(1, sizeof(UTF8String_t)); + CHECK_NULL(issuerName, ISSUER_MEMORY_ALLOC_FAILED); + + certificateRevocationInfo = (CertificateRevocationInfo_t *)OICCalloc(numberOfRevoked, + sizeof(CertificateRevocationInfo_t)); + CHECK_NULL(certificateRevocationInfo, ISSUER_MEMORY_ALLOC_FAILED); + + privKeyIss.data = caPrivateKey; + privKeyIss.len = PRIVATE_KEY_SIZE; + caName.data = uint8caName; + caName.len = ISSUER_MAX_NAME_SIZE; + + //allocate issuerPrivateKey + issuerPrivateKey->size = PRIVATE_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + issuerPrivateKey->buf = (uint8_t *)OICCalloc((issuerPrivateKey->size), sizeof(uint8_t)); + CHECK_NULL(issuerPrivateKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(issuerPrivateKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + + //read CA private key from the CA storage + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAPrivateKey, &privKeyIss); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((issuerPrivateKey->buf) + 1, privKeyIss.data, PRIVATE_KEY_SIZE); + + //thisUpdateTime + if (uint8ThisUpdateTime) + { + thisUpdateTime->buf = (uint8_t *)uint8ThisUpdateTime; + } + else + { + thisUpdateTime->buf = (uint8_t *)ISSUER_DEFAULT_THIS_UPDATE; + } + thisUpdateTime->size = strlen((const char *)thisUpdateTime->buf); + + //RootName + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAName, &caName); + issuerName->buf = caName.data; + issuerName->size = caName.len; + + // CRI + for ( i = 0; i < numberOfRevoked; i++ ) + { + certificateRevocationInfo[i].userCertificate = revokedNumbers[i]; + certificateRevocationInfo[i].revocationDate.buf = (uint8_t *)revocationDates[i]; + certificateRevocationInfo[i].revocationDate.size = + strlen((const char *)revocationDates[i]); + } + + CHECK_CALL(GenerateCRL, issuerName, thisUpdateTime, numberOfRevoked, certificateRevocationInfo, + issuerPrivateKey, encodedCRL); + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(SetCertificateRevocationList, encodedCRL); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR( + OICFree(issuerName); + OICFree(thisUpdateTime); + OICFree(certificateRevocationInfo); + ASN_STRUCT_FREE(asn_DEF_BIT_STRING, issuerPrivateKey); + ); +} + +PKIError CKMRevocateCertificate (const uint8_t *uint8ThisUpdateTime, const long revokedNumber, + ByteArray *encodedCRL) +{ + FUNCTION_INIT(); + ByteArray oldCRL = BYTE_ARRAY_INITIALIZER; + asn_dec_rval_t rval; /* Decoder return value */ + CertificateRevocationList_t *certificateRevocationList = NULL; // Type to decode + CertificateRevocationInfo_t *CRI = NULL; + long serialNumber = 0; + long numberOfRevoked = 0; + uint32_t crlMaxSize = 0; + + BIT_STRING_t *issuerPrivateKey = NULL; + uint8_t caPrivateKey[PRIVATE_KEY_SIZE]; + ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER; + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetNumberOfRevoked, &numberOfRevoked); + + crlMaxSize = (CRL_MIN_SIZE + + (numberOfRevoked + 1) * (sizeof(CertificateRevocationInfo_t) + 4)); + + CHECK_NULL(encodedCRL, ISSUER_NULL_PASSED); + CHECK_NULL(encodedCRL->data, ISSUER_NULL_PASSED); + CHECK_LESS_EQUAL(crlMaxSize, encodedCRL->len, ISSUER_WRONG_BYTE_ARRAY_LEN); + + //obtain CRL + oldCRL.data = (uint8_t *)OICMalloc(crlMaxSize); + CHECK_NULL(oldCRL.data, ISSUER_MEMORY_ALLOC_FAILED); + oldCRL.len = crlMaxSize; + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCertificateRevocationList, &oldCRL); + CHECK_CALL(CloseCKMInfo); + + //decode CRL + rval = ber_decode(0, &asn_DEF_CertificateRevocationList, (void **)&certificateRevocationList, + oldCRL.data, oldCRL.len); + CHECK_EQUAL(rval.code, RC_OK, ISSUER_CSR_DER_DECODE_FAIL); + + //add one certificate into CRL + CRI = (CertificateRevocationInfo_t *)OICCalloc(1, sizeof(CertificateRevocationInfo_t)); + CHECK_NULL(CRI, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + CRI->revocationDate.size = (int)strlen((const char *)uint8ThisUpdateTime); + CRI->revocationDate.buf = OICCalloc((CRI->revocationDate.size) + 1, sizeof(char)); + //additional byte for \0 at the end + CHECK_NULL(CRI->revocationDate.buf, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + memcpy(CRI->revocationDate.buf, uint8ThisUpdateTime, CRI->revocationDate.size + 1); + //additional byte for \0 at the end + + CRI->userCertificate = revokedNumber; + ASN_SEQUENCE_ADD((void *)(&(certificateRevocationList-> + tbsCertList.revokedCertificates.list)), (void *)(CRI)); + + //prepare memory for issuerPrivateKey + issuerPrivateKey = (BIT_STRING_t *)OICCalloc(1, sizeof(BIT_STRING_t)); + CHECK_NULL(issuerPrivateKey, ISSUER_MEMORY_ALLOC_FAILED); + privKeyIss.data = caPrivateKey; + privKeyIss.len = PRIVATE_KEY_SIZE; + //allocate issuerPrivateKey + issuerPrivateKey->size = PRIVATE_KEY_SIZE + 1; //additional byte for ASN1_UNCOMPRESSED_KEY_ID + issuerPrivateKey->buf = (uint8_t *)OICCalloc((issuerPrivateKey->size), sizeof(uint8_t)); + CHECK_NULL(issuerPrivateKey->buf, ISSUER_MEMORY_ALLOC_FAILED); + *(issuerPrivateKey->buf) = (uint8_t)ASN1_UNCOMPRESSED_KEY_ID; + + //read CA private key from the CA storage + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCAPrivateKey, &privKeyIss); + + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + memcpy((issuerPrivateKey->buf) + 1, privKeyIss.data, PRIVATE_KEY_SIZE); + + //SignCRL + CHECK_CALL(SignCRL, certificateRevocationList, crlMaxSize, issuerPrivateKey, encodedCRL); + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCRLSerialNumber, &serialNumber); + serialNumber++; + CHECK_CALL(SetCRLSerialNumber, &serialNumber); + numberOfRevoked++; + CHECK_CALL(SetNumberOfRevoked, &numberOfRevoked); + CHECK_CALL(SetCertificateRevocationList, encodedCRL); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR( + ASN_STRUCT_FREE(asn_DEF_CertificateRevocationList, certificateRevocationList); + certificateRevocationList = NULL; + + ); +} + +PKIError CKMGetCRL (ByteArray *certificateRevocationList) +{ + FUNCTION_INIT(); + CHECK_NULL(certificateRevocationList, ISSUER_NULL_PASSED); + CHECK_NULL(certificateRevocationList->data, ISSUER_NULL_PASSED); + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCertificateRevocationList, certificateRevocationList); + CHECK_CALL(CloseCKMInfo); + + FUNCTION_CLEAR(); +} diff --git a/resource/csdk/security/provisioning/ck_manager/src/ckm_info.c b/resource/csdk/security/provisioning/ck_manager/src/ckm_info.c new file mode 100644 index 0000000..cd4bf15 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/src/ckm_info.c @@ -0,0 +1,537 @@ +/****************************************************************** + * + * 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 "ckm_info.h" +#include "ocstack.h" +#include "oic_malloc.h" +#include "cJSON.h" +#include "base64.h" +#include "psinterface.h" +#include "srmresourcestrings.h" +#include "crlresource.h" +#include "crl_generator.h" + +//constants used in ckmInfo +#define CKM_INFO_IS_NOT_LOADED (0) +#define CKM_INFO_IS_LOADED (1) +#define CA_PRIVATE_KEY_IS_NOT_SET (0) +#define CA_PRIVATE_KEY_IS_SET (1) +#define CA_PRIVATE_KEY_DEFAULT_VALUE (0) +#define CA_PUBLIC_KEY_IS_NOT_SET (0) +#define CA_PUBLIC_KEY_IS_SET (1) +#define CA_PUBLIC_KEY_DEFAULT_VALUE (0) +#define CA_CERTIFICATE_CHAIN_IS_NOT_SET (0) +#define CA_CERTIFICATE_CHAIN_MEMORY_IS_NOT_ALLOCATED (0) +#define CA_NAME_IS_NOT_SET (0) +#define CA_NAME_DEFAULT_VALUE (0) +#define CERTIFICATE_SN_INITIAL_VALUE (1) +#define CRL_SN_INITIAL_VALUE (1) +#define NUMBER_OF_REVOKED_CERTIFICATES_INITIAL_VALUE (0) + +//constants used in crlInfo +#define CRL_IS_NOT_SET (0) +#define CRL_MEMORY_IS_NOT_ALLOCATED (0) + +static CKMInfo_t g_ckmInfo = {CKM_INFO_IS_NOT_LOADED, + CA_PRIVATE_KEY_IS_NOT_SET, {CA_PRIVATE_KEY_DEFAULT_VALUE}, + CA_PUBLIC_KEY_IS_NOT_SET, {CA_PUBLIC_KEY_DEFAULT_VALUE}, + CA_CERTIFICATE_CHAIN_IS_NOT_SET, + CA_CERTIFICATE_CHAIN_MEMORY_IS_NOT_ALLOCATED, + CA_NAME_IS_NOT_SET, {CA_NAME_DEFAULT_VALUE}, + CERTIFICATE_SN_INITIAL_VALUE, CRL_SN_INITIAL_VALUE, + NUMBER_OF_REVOKED_CERTIFICATES_INITIAL_VALUE}; + +static OicSecCrl_t g_crlInfo = {CRL_IS_NOT_SET, + BYTE_ARRAY_INITIALIZER, BYTE_ARRAY_INITIALIZER}; + +//General functions + +PKIError InitCKMInfo(void) +{ + FUNCTION_INIT(); + FILE *filePointer = NULL; + int count = 1; + int objectsRead = 0; + int objectsWrote = 0; + + if (!g_ckmInfo.CKMInfoIsLoaded) + { + filePointer = fopen(CA_STORAGE_FILE, "rb"); + if (filePointer) //read existing storage + { + objectsRead = fread(&g_ckmInfo, sizeof(CKMInfo_t), count, filePointer); + g_ckmInfo.CACertificateChain = CA_CERTIFICATE_CHAIN_MEMORY_IS_NOT_ALLOCATED; + CHECK_EQUAL(objectsRead, count, ISSUER_CA_STORAGE_FILE_READ_ERROR); + } + else ////create new storage + { + filePointer = fopen(CA_STORAGE_FILE, "wb"); + CHECK_NULL(filePointer, ISSUER_CA_STORAGE_FILE_WRITE_ERROR); + objectsWrote = fwrite(&g_ckmInfo, sizeof(CKMInfo_t), count, filePointer); + CHECK_EQUAL(objectsWrote, count, ISSUER_CA_STORAGE_FILE_WRITE_ERROR); + } + CHECK_CALL(InitCRL); + CHECK_CALL(InitCRT); + g_ckmInfo.CKMInfoIsLoaded = CKM_INFO_IS_LOADED; + } + FUNCTION_CLEAR( + if (filePointer) + { + fclose(filePointer); + filePointer = NULL; + } + ); +} + +PKIError SaveCKMInfo(void) +{ + FUNCTION_INIT(); + FILE *filePointer = NULL; + int count = 1; + int objectsWrote = 0; + + CHECK_COND(g_ckmInfo.CKMInfoIsLoaded, CKM_INFO_IS_NOT_INIT); + filePointer = fopen(CA_STORAGE_FILE, "wb"); + CHECK_NULL(filePointer, ISSUER_CA_STORAGE_FILE_WRITE_ERROR); + objectsWrote = fwrite(&g_ckmInfo, sizeof(CKMInfo_t), count, filePointer); + CHECK_EQUAL(objectsWrote, count, ISSUER_CA_STORAGE_FILE_WRITE_ERROR); + if ((g_crlInfo.CrlData.data)&&(g_crlInfo.CrlData.len)) + { + CHECK_CALL(SaveCRL); + } + if (g_ckmInfo.CAChainLength) + { + CHECK_CALL(SaveCRT); + } + FUNCTION_CLEAR( + if (filePointer) + { + fclose(filePointer); + filePointer = NULL; + } + ); +} + +PKIError CloseCKMInfo(void) +{ + FUNCTION_INIT(); + CHECK_CALL(SaveCKMInfo); + OICFree(g_crlInfo.CrlData.data); + g_crlInfo.CrlData.data = CRL_MEMORY_IS_NOT_ALLOCATED; + OICFree(g_crlInfo.ThisUpdate.data); + g_crlInfo.ThisUpdate.data = CRL_MEMORY_IS_NOT_ALLOCATED; + OICFree(g_ckmInfo.CACertificateChain); + g_ckmInfo.CACertificateChain = CA_CERTIFICATE_CHAIN_MEMORY_IS_NOT_ALLOCATED; + g_ckmInfo.CKMInfoIsLoaded = CKM_INFO_IS_NOT_LOADED; + g_crlInfo.CrlId = CRL_IS_NOT_SET; + FUNCTION_CLEAR(); +} + +PKIError SetCKMInfo (const long *nextSN, const long *CRLSerialNumber, + const ByteArray *CAPrivateKey, const ByteArray *CAPublicKey, + const ByteArray *CAName) +{ + FUNCTION_INIT(); + if (nextSN) + CHECK_CALL(SetNextSerialNumber, nextSN); + if (CRLSerialNumber) + CHECK_CALL(SetCRLSerialNumber, CRLSerialNumber); + if (CAPrivateKey) + CHECK_CALL(SetCAPrivateKey, CAPrivateKey); + if (CAPublicKey) + CHECK_CALL(SetCAPublicKey, CAPublicKey); + if (CAName) + CHECK_CALL(SetCAName, CAName); + + FUNCTION_CLEAR(); +} + +PKIError GetCKMInfo (long *nextSN, long *CRLSerialNumber, + ByteArray *CAPrivateKey, ByteArray *CAPublicKey, + ByteArray *CAName) +{ + FUNCTION_INIT(); + if (nextSN) + CHECK_CALL(GetNextSerialNumber, nextSN); + if (CRLSerialNumber) + CHECK_CALL(GetCRLSerialNumber, CRLSerialNumber); + if (CAPrivateKey) + CHECK_CALL(GetCAPrivateKey, CAPrivateKey); + if (CAPublicKey) + CHECK_CALL(GetCAPublicKey, CAPublicKey); + if (CAName) + CHECK_CALL(GetCAName, CAName); + + FUNCTION_CLEAR(); +} + +/*Private Key*/ +PKIError SetCAPrivateKey (const ByteArray *CAPrivateKey) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(CAPrivateKey, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_EQUAL(CAPrivateKey->len, PRIVATE_KEY_SIZE, ISSUER_CA_STORAGE_WRONG_PRIVATE_KEY_LEN); + memcpy(g_ckmInfo.CAPrivateKey, CAPrivateKey->data, PRIVATE_KEY_SIZE); + g_ckmInfo.CAPrivateKeyIsSet = CA_PRIVATE_KEY_IS_SET; + + FUNCTION_CLEAR(); +} + +PKIError GetCAPrivateKey (ByteArray *CAPrivateKey) +{ + FUNCTION_INIT(); + CHECK_COND(g_ckmInfo.CAPrivateKeyIsSet, ISSUER_CA_STORAGE_PRIVATE_KEY_UNDEFINED); + CHECK_NULL_BYTE_ARRAY_PTR(CAPrivateKey, ISSUER_CA_STORAGE_NULL_PASSED); + memcpy(CAPrivateKey->data, g_ckmInfo.CAPrivateKey, PRIVATE_KEY_SIZE); + CAPrivateKey->len = PRIVATE_KEY_SIZE; + + FUNCTION_CLEAR(); +} + +/*Public Key*/ +PKIError SetCAPublicKey (const ByteArray *CAPublicKey) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(CAPublicKey, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_EQUAL(CAPublicKey->len, PUBLIC_KEY_SIZE, ISSUER_CA_STORAGE_WRONG_PUBLIC_KEY_LEN); + memcpy(g_ckmInfo.CAPublicKey, CAPublicKey->data, PUBLIC_KEY_SIZE); + g_ckmInfo.CAPublicKeyIsSet = CA_PUBLIC_KEY_IS_SET; + + FUNCTION_CLEAR(); +} + +PKIError GetCAPublicKey (ByteArray *CAPublicKey) +{ + FUNCTION_INIT(); + CHECK_COND(g_ckmInfo.CAPublicKeyIsSet, ISSUER_CA_STORAGE_PUBLIC_KEY_UNDEFINED); + CHECK_NULL_BYTE_ARRAY_PTR(CAPublicKey, ISSUER_CA_STORAGE_NULL_PASSED); + memcpy(CAPublicKey->data, g_ckmInfo.CAPublicKey, PUBLIC_KEY_SIZE); + CAPublicKey->len = PUBLIC_KEY_SIZE; + + FUNCTION_CLEAR(); +} + +/*CAName*/ +PKIError SetCAName (const ByteArray *CAName) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(CAName, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_LESS_EQUAL(CAName->len, ISSUER_MAX_NAME_SIZE, ISSUER_CA_STORAGE_WRONG_CA_NAME_LEN); + memcpy(g_ckmInfo.CAName, CAName->data, CAName->len); + g_ckmInfo.CANameSize = CAName->len; + + FUNCTION_CLEAR(); +} + +PKIError GetCAName (ByteArray *CAName) +{ + FUNCTION_INIT(); + CHECK_COND(g_ckmInfo.CANameSize, ISSUER_CA_STORAGE_CA_NAME_UNDEFINED); + CHECK_NULL_BYTE_ARRAY_PTR(CAName, ISSUER_CA_STORAGE_NULL_PASSED); + memcpy(CAName->data, g_ckmInfo.CAName, g_ckmInfo.CANameSize); + CAName->len = g_ckmInfo.CANameSize; + + FUNCTION_CLEAR(); +} + +//Certificate-related functions + +#define CERT_LEN_PREFIX (3) +#define BYTE_SIZE (8) //bits + +static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen) +{ + for (size_t i = 0; i < CERT_LEN_PREFIX; ++i) + { + prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF; + } +} + +static uint32_t ParseCertPrefix(uint8_t *prefix) +{ + uint32_t res = 0; + if(NULL != prefix) + { + for(int i=0; i < CERT_LEN_PREFIX; ++i) + { + res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE)); + } + } + return res; +} + +PKIError InitCRT(void) +{ + FUNCTION_INIT(); + FILE *filePointer = NULL; + uint32_t objectsRead = 0; + uint8_t prefix[CERT_LEN_PREFIX] = {0}; + + if (g_ckmInfo.CAChainLength) + { + filePointer = fopen(CA_STORAGE_CRT_FILE, "rb"); + CHECK_NULL(filePointer, ISSUER_CA_STORAGE_CRT_READ_ERROR); + + g_ckmInfo.CACertificateChain = + (ByteArray *)OICMalloc(sizeof(ByteArray) * g_ckmInfo.CAChainLength); + CHECK_NULL(g_ckmInfo.CACertificateChain, ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED); + + for (int i = 0; i < g_ckmInfo.CAChainLength; i++) + { + objectsRead = fread(prefix, sizeof(uint8_t), CERT_LEN_PREFIX, filePointer); + CHECK_EQUAL(objectsRead, CERT_LEN_PREFIX, ISSUER_CA_STORAGE_CRT_READ_ERROR); + g_ckmInfo.CACertificateChain[i].len = ParseCertPrefix(prefix); + + g_ckmInfo.CACertificateChain[i].data = + (uint8_t *)OICMalloc(g_ckmInfo.CACertificateChain[i].len); + CHECK_NULL(g_ckmInfo.CACertificateChain[i].data, + ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED); + objectsRead = fread(g_ckmInfo.CACertificateChain[i].data, sizeof(uint8_t), + g_ckmInfo.CACertificateChain[i].len, filePointer); + CHECK_EQUAL(objectsRead, g_ckmInfo.CACertificateChain[i].len, + ISSUER_CA_STORAGE_CRT_READ_ERROR); + } + } + FUNCTION_CLEAR( + if (filePointer) + { + fclose(filePointer); + filePointer = NULL; + } + ); +} + +PKIError SaveCRT(void) +{ + FUNCTION_INIT(); + FILE *filePointer = NULL; + uint32_t objectsWrote = 0; + uint8_t prefix[CERT_LEN_PREFIX] = {0}; + + filePointer = fopen(CA_STORAGE_CRT_FILE, "wb"); + CHECK_NULL(filePointer, ISSUER_CA_STORAGE_CRT_WRITE_ERROR); + + for (int i = 0; i < g_ckmInfo.CAChainLength; i++) + { + WriteCertPrefix(prefix, g_ckmInfo.CACertificateChain[i].len); + objectsWrote = fwrite(prefix, sizeof(uint8_t), CERT_LEN_PREFIX, filePointer); + CHECK_EQUAL(objectsWrote, CERT_LEN_PREFIX, ISSUER_CA_STORAGE_CRT_WRITE_ERROR); + objectsWrote = fwrite(g_ckmInfo.CACertificateChain[i].data, sizeof(uint8_t), + g_ckmInfo.CACertificateChain[i].len, filePointer); + CHECK_EQUAL(objectsWrote, g_ckmInfo.CACertificateChain[i].len, + ISSUER_CA_STORAGE_CRT_WRITE_ERROR); + } + + FUNCTION_CLEAR( + if (filePointer) + { + fclose(filePointer); + filePointer = NULL; + } + ); +} + +/*Serial Number*/ +PKIError SetNextSerialNumber (const long *nextSN) +{ + FUNCTION_INIT(); + CHECK_NULL(nextSN, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_LESS_EQUAL(0, *nextSN, ISSUER_CA_STORAGE_WRONG_SERIAL_NUMBER); + g_ckmInfo.nextSerialNumber = *nextSN; + + FUNCTION_CLEAR(); +} + +PKIError GetNextSerialNumber (long *nextSN) +{ + FUNCTION_INIT(); + CHECK_NULL(nextSN, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(g_ckmInfo.nextSerialNumber, ISSUER_CA_STORAGE_SN_UNDEFINED); + *nextSN = g_ckmInfo.nextSerialNumber; + + FUNCTION_CLEAR(); +} + +/*CA Certificate Chain*/ +PKIError SetCAChain (const uint8_t CAChainLength, const ByteArray *CAChain) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(CAChain, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(CAChainLength, ISSUER_CA_STORAGE_NULL_PASSED); + + OICFree(g_ckmInfo.CACertificateChain); + g_ckmInfo.CACertificateChain = NULL; + g_ckmInfo.CACertificateChain = (ByteArray *)OICMalloc(sizeof(ByteArray) * CAChainLength); + CHECK_NULL(g_ckmInfo.CACertificateChain, ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED); + + for (int i = 0; i < CAChainLength; i++) + { + g_ckmInfo.CACertificateChain[i].data = (uint8_t *)OICMalloc(CAChain[i].len); + CHECK_NULL(g_ckmInfo.CACertificateChain[i].data, ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED); + memcpy(g_ckmInfo.CACertificateChain[i].data, CAChain[i].data, CAChain[i].len); + g_ckmInfo.CACertificateChain[i].len = CAChain[i].len; + } + g_ckmInfo.CAChainLength = CAChainLength; + + FUNCTION_CLEAR(); +} + +PKIError GetCAChain (uint8_t* CAChainLength, ByteArray *CAChain) +{ + FUNCTION_INIT(); + CHECK_COND(g_ckmInfo.CAChainLength, ISSUER_CA_STORAGE_CA_CHAIN_LENGTH_UNDEFINED); + CHECK_NULL_BYTE_ARRAY_PTR(CAChain, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(CAChainLength, PKI_NULL_PASSED); + + for (int i = 0; i < g_ckmInfo.CAChainLength; i++) + { + CHECK_LESS_EQUAL(g_ckmInfo.CACertificateChain[i].len, CAChain[i].len, + ISSUER_CA_STORAGE_WRONG_BYTE_ARRAY_LEN); + memcpy(CAChain[i].data, g_ckmInfo.CACertificateChain[i].data, + g_ckmInfo.CACertificateChain[i].len); + CAChain[i].len = g_ckmInfo.CACertificateChain[i].len; + } + + *CAChainLength = g_ckmInfo.CAChainLength; + + FUNCTION_CLEAR(); +} + +/*Certificate*/ +PKIError SetCACertificate (const ByteArray *CACertificate) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(CACertificate, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_CALL(SetCAChain, 1, CACertificate); + + FUNCTION_CLEAR(); +} + +PKIError GetCACertificate (ByteArray *CACertificate) +{ + FUNCTION_INIT(); + uint8_t i; + CHECK_NULL_BYTE_ARRAY_PTR(CACertificate, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_CALL(GetCAChain, &i, CACertificate); + + FUNCTION_CLEAR(); +} +//CRL-related functions + +PKIError InitCRL(void) +{ + FUNCTION_INIT(); + g_crlInfo = *(OicSecCrl_t *)GetCRLResource(); + CHECK_NULL(g_crlInfo.CrlData.data, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(g_crlInfo.ThisUpdate.data, ISSUER_CA_STORAGE_NULL_PASSED); + + FUNCTION_CLEAR(); +} + +PKIError SaveCRL(void) +{ + FUNCTION_INIT(); + + CHECK_EQUAL(UpdateCRLResource(&g_crlInfo), + OC_STACK_OK, ISSUER_CA_STORAGE_CRL_WRITE_ERROR); + FUNCTION_CLEAR(); +} + +/*CRL Serial Number*/ +PKIError SetCRLSerialNumber (const long *CRLSerialNumber) +{ + FUNCTION_INIT(); + CHECK_NULL(CRLSerialNumber, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_LESS_EQUAL(0, *CRLSerialNumber, ISSUER_CA_STORAGE_WRONG_CRL_SERIAL_NUMBER); + g_ckmInfo.CRLSerialNumber = *CRLSerialNumber; + + FUNCTION_CLEAR(); +} + +PKIError GetCRLSerialNumber (long *CRLSerialNumber) +{ + FUNCTION_INIT(); + CHECK_NULL(CRLSerialNumber, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(g_ckmInfo.CRLSerialNumber, ISSUER_CA_STORAGE_CRL_SN_UNDEFINED); + *CRLSerialNumber = g_ckmInfo.CRLSerialNumber; + + FUNCTION_CLEAR(); +} + +/*Revocation List*/ +PKIError SetCertificateRevocationList (const ByteArray *certificateRevocationList) +{ + FUNCTION_INIT(); + CHECK_NULL_BYTE_ARRAY_PTR(certificateRevocationList, ISSUER_CA_STORAGE_NULL_PASSED); + + OICFree(g_crlInfo.CrlData.data); + g_crlInfo.CrlData.data = CRL_MEMORY_IS_NOT_ALLOCATED; + g_crlInfo.CrlData.data = (uint8_t *)OICMalloc(certificateRevocationList->len + 1); + CHECK_NULL(g_crlInfo.CrlData.data, ISSUER_CA_STORAGE_MEMORY_ALLOC_FAILED); + memcpy(g_crlInfo.CrlData.data, certificateRevocationList->data, certificateRevocationList->len); + g_crlInfo.CrlData.len = certificateRevocationList->len; + + g_crlInfo.CrlId ++; + CHECK_CALL(SaveCRL); + + FUNCTION_CLEAR(); +} + +PKIError GetCertificateRevocationList (ByteArray *certificateRevocationList) +{ + FUNCTION_INIT(); + CHECK_COND(g_crlInfo.CrlData.data, ISSUER_CA_STORAGE_CRL_UNDEFINED); + CHECK_NULL_BYTE_ARRAY_PTR(certificateRevocationList, ISSUER_CA_STORAGE_NULL_PASSED); + OicSecCrl_t *tmpCRL; + tmpCRL = (OicSecCrl_t *)GetCRLResource(); + g_crlInfo.CrlId = tmpCRL->CrlId; + g_crlInfo.CrlData = tmpCRL->CrlData; + g_crlInfo.ThisUpdate = tmpCRL->ThisUpdate; + + CHECK_LESS_EQUAL(g_crlInfo.CrlData.len, certificateRevocationList->len, + ISSUER_WRONG_BYTE_ARRAY_LEN); + memcpy(certificateRevocationList->data, g_crlInfo.CrlData.data, g_crlInfo.CrlData.len); + certificateRevocationList->len = g_crlInfo.CrlData.len; + + FUNCTION_CLEAR( + OICFree(tmpCRL); + ); +} + +PKIError SetNumberOfRevoked (const long *numberOfRevoked) +{ + FUNCTION_INIT(); + CHECK_NULL(numberOfRevoked, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_LESS_EQUAL(0, *numberOfRevoked, ISSUER_CA_STORAGE_WRONG_CRL_SERIAL_NUMBER); + g_ckmInfo.numberOfRevoked = *numberOfRevoked; + + FUNCTION_CLEAR(); +} +PKIError GetNumberOfRevoked (long *numberOfRevoked) +{ + FUNCTION_INIT(); + CHECK_NULL(numberOfRevoked, ISSUER_CA_STORAGE_NULL_PASSED); + CHECK_NULL(g_ckmInfo.numberOfRevoked, ISSUER_CA_STORAGE_CRL_SN_UNDEFINED); + *numberOfRevoked = g_ckmInfo.numberOfRevoked; + + FUNCTION_CLEAR(); +} diff --git a/resource/csdk/security/provisioning/ck_manager/src/crl_generator.c b/resource/csdk/security/provisioning/ck_manager/src/crl_generator.c new file mode 100644 index 0000000..1c48dea --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/src/crl_generator.c @@ -0,0 +1,241 @@ +/****************************************************************** + * + * 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_generator.h" +#include "pki.h" +#include "oic_malloc.h" +#include "ckm_info.h" + +//ecdsa-with-SHA256 1.2.840.10045.4.3.2 [RFC5759] +static const uint8_t g_ECDSA_WITH_SHA256_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; + +//commonName 2.5.4.3 [RFC2256] +static const uint8_t g_COMMON_NAME_OID[] = {0x55, 0x04, 0x03}; + +PKIError GenerateCRL (const UTF8String_t *issuerName, + const UTCTime_t *thisUpdateTime, const uint32_t nuberOfRevoked, + const CertificateRevocationInfo_t *certificateRevocationInfo, + const BIT_STRING_t *issuerPrivateKey, ByteArray *encodedCRL) +{ + FUNCTION_INIT(); + + CertificateRevocationList_t *certificateRevocationList = NULL; /* Type to encode */ + AttributeTypeAndValue_t *issuerTypeAndValue = NULL; + RelativeDistinguishedName_t *issuerRDN = NULL; + CertificateRevocationInfo_t *cri = NULL; + + uint32_t crlMaxSize = (CRL_MIN_SIZE + + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)); + + uint32_t i; + long serialNumber = 0; + + CHECK_NULL(issuerName, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(thisUpdateTime, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(certificateRevocationInfo, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(issuerPrivateKey, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(encodedCRL, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(encodedCRL->data, ISSUER_CRL_NULL_PASSED); + CHECK_LESS_EQUAL(crlMaxSize, encodedCRL->len, ISSUER_CRL_WRONG_BYTE_ARRAY_LEN); + + /* Allocate the memory */ + certificateRevocationList = OICCalloc(1, sizeof(CertificateRevocationList_t));//not malloc! + CHECK_NULL(certificateRevocationList, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + issuerTypeAndValue = OICCalloc(1, sizeof(AttributeTypeAndValue_t)); + CHECK_NULL(issuerTypeAndValue, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + issuerRDN = OICCalloc(1, sizeof(RelativeDistinguishedName_t)); + CHECK_NULL(issuerRDN, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + //set subject name + issuerTypeAndValue->value = *issuerName; + issuerTypeAndValue->type.buf = (uint8_t *)g_COMMON_NAME_OID; //2.5.4.3 + issuerTypeAndValue->type.size = sizeof(g_COMMON_NAME_OID) / sizeof(g_COMMON_NAME_OID[0]); + ASN_SET_ADD(issuerRDN, issuerTypeAndValue); + ASN_SEQUENCE_ADD(&(certificateRevocationList->tbsCertList.issuer), issuerRDN); + + //set signature algorithm + certificateRevocationList->signatureAlgorithm.algorithm.buf = + (uint8_t *)g_ECDSA_WITH_SHA256_OID; //1.2.840.10045.4.3.2 + certificateRevocationList->signatureAlgorithm.algorithm.size = + sizeof(g_ECDSA_WITH_SHA256_OID) / sizeof(g_ECDSA_WITH_SHA256_OID[0]); + certificateRevocationList->signatureAlgorithm.nul = OICCalloc(1, sizeof(NULL_t)); + CHECK_NULL(certificateRevocationList->signatureAlgorithm.nul, + ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + //set signature algorithm in TBS part + certificateRevocationList->tbsCertList.signature.algorithm.buf = + (uint8_t *)g_ECDSA_WITH_SHA256_OID; //1.2.840.10045.4.3.2 + certificateRevocationList->tbsCertList.signature.algorithm.size = + sizeof(g_ECDSA_WITH_SHA256_OID) / sizeof(g_ECDSA_WITH_SHA256_OID[0]); + certificateRevocationList->tbsCertList.signature.nul = OICCalloc(1, sizeof(NULL_t)); + CHECK_NULL(certificateRevocationList->tbsCertList.signature.nul, + ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + //set thisUpdateTime + certificateRevocationList->tbsCertList.thisUpdate = *thisUpdateTime; + + //add revoked info + for ( i = 0; i < nuberOfRevoked; i++) + { + cri = OICCalloc(1, sizeof(CertificateRevocationInfo_t)); + CHECK_NULL(cri, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + cri->revocationDate.size = (certificateRevocationInfo + i)->revocationDate.size; + cri->revocationDate.buf = OICCalloc((cri->revocationDate.size) + 1, sizeof(char)); + CHECK_NULL(cri->revocationDate.buf, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + memcpy(cri->revocationDate.buf, (certificateRevocationInfo + i)->revocationDate.buf, + cri->revocationDate.size + 1); + cri->userCertificate = (certificateRevocationInfo + i)->userCertificate; + ASN_SEQUENCE_ADD((void *)(&(certificateRevocationList-> + tbsCertList.revokedCertificates.list)), (void *)(cri)); + } + + CHECK_CALL(SignCRL, certificateRevocationList, crlMaxSize, issuerPrivateKey, encodedCRL); + + CHECK_CALL(InitCKMInfo); + CHECK_CALL(GetCRLSerialNumber, &serialNumber); + serialNumber++; + CHECK_CALL(SetCRLSerialNumber, &serialNumber); + CHECK_CALL(SetNumberOfRevoked, (const long *)&nuberOfRevoked); + CHECK_CALL(SaveCKMInfo); + + FUNCTION_CLEAR( + if (issuerTypeAndValue) + { + issuerTypeAndValue->value.buf = NULL; + issuerTypeAndValue->type.buf = NULL; + } + if (certificateRevocationList) + { + certificateRevocationList->tbsCertList.signature.algorithm.buf = NULL; + certificateRevocationList->signatureAlgorithm.algorithm.buf = NULL; + certificateRevocationList->tbsCertList.thisUpdate.buf = NULL; + } + + ASN_STRUCT_FREE(asn_DEF_CertificateRevocationList, certificateRevocationList); + certificateRevocationList = NULL; + ); +} + +PKIError SignCRL(CertificateRevocationList_t *certificateRevocationList, + const uint32_t crlMaxSize, const BIT_STRING_t *issuerPrivateKey, + ByteArray *encodedCRL) +{ + FUNCTION_INIT(); + uint8_t *crlInfoInDER = NULL; + asn_enc_rval_t ec; /* Encoder return value */ + uint8_t *uint8Pointer = NULL; + ByteArray tbs = BYTE_ARRAY_INITIALIZER; + uint8_t signature[SIGN_FULL_SIZE]; + uint8_t sha256[SHA_256_HASH_LEN]; + + CHECK_NULL(certificateRevocationList, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(crlMaxSize, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(issuerPrivateKey, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(encodedCRL, ISSUER_CRL_NULL_PASSED); + CHECK_NULL(encodedCRL->data, ISSUER_CRL_NULL_PASSED); + CHECK_LESS_EQUAL(crlMaxSize, encodedCRL->len, ISSUER_CRL_WRONG_BYTE_ARRAY_LEN); + + //encode TBS to DER + crlInfoInDER = OICCalloc(1, crlMaxSize); + CHECK_NULL(crlInfoInDER, ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + + ec = der_encode_to_buffer(&asn_DEF_TBSCertList, &(certificateRevocationList->tbsCertList), + crlInfoInDER, crlMaxSize); + + //sign CRL + CHECK_COND(ec.encoded > 0, ISSUER_CRL_ENCODER_DER_ENCODE_FAIL); + tbs.len = ec.encoded; + tbs.data = crlInfoInDER; + GET_SHA_256(tbs, sha256); + CHECK_COND(uECC_sign((issuerPrivateKey->buf) + 1, sha256, signature), + ISSUER_CRL_ENCODER_SIGNATURE_FAIL); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + + // ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER } (RFC 5480) + certificateRevocationList->signatureValue.size = SIGN_FULL_SIZE + 6; + // size for SEQUENCE ID + 2 * INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + certificateRevocationList->signatureValue.size ++; + } + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[SIGN_R_LEN] > 127) + { + certificateRevocationList->signatureValue.size ++; + } + OICFree(certificateRevocationList->signatureValue.buf); + certificateRevocationList->signatureValue.buf = (uint8_t *)OICCalloc( + certificateRevocationList->signatureValue.size, sizeof(uint8_t)); + CHECK_NULL(certificateRevocationList->signatureValue.buf, + ISSUER_CRL_ENCODER_MEMORY_ALLOC_FAILED); + *(certificateRevocationList->signatureValue.buf) = (12 << 2); //ASN.1 SEQUENCE ID + *(certificateRevocationList->signatureValue.buf + 1) = + certificateRevocationList->signatureValue.size - 2; //ASN.1 SEQUENCE size + + uint8Pointer = certificateRevocationList->signatureValue.buf + 2; //skip SEQUENCE ID and size + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + *(uint8Pointer + 1) = SIGN_R_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_R_LEN; //ASN.1 INTEGER size + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature, SIGN_R_LEN); + + uint8Pointer += SIGN_R_LEN; + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature [SIGN_R_LEN] > 127) + { + *(uint8Pointer + 1) = SIGN_S_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_S_LEN; //ASN.1 INTEGER size + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature + SIGN_R_LEN, SIGN_S_LEN); + + ec = der_encode_to_buffer(&asn_DEF_CertificateRevocationList, certificateRevocationList, + encodedCRL->data, crlMaxSize); + CHECK_COND(ec.encoded > 0, ISSUER_CRL_ENCODER_DER_ENCODE_FAIL); + encodedCRL->len = ec.encoded; + + FUNCTION_CLEAR( + OICFree(crlInfoInDER); + crlInfoInDER = NULL; + ); +} diff --git a/resource/csdk/security/provisioning/ck_manager/src/csr_generator.c b/resource/csdk/security/provisioning/ck_manager/src/csr_generator.c new file mode 100644 index 0000000..95662e7 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/src/csr_generator.c @@ -0,0 +1,278 @@ +/****************************************************************** + * + * 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 "csr_generator.h" +#include "pki.h" +#include "oic_malloc.h" + +//ecdsa-with-SHA256 1.2.840.10045.4.3.2 [RFC5759] +static const uint8_t g_ECDSA_WITH_SHA256_OID[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; + +//Elliptic Curve Digital Signature Algorithm (ECDSA) 1.2.840.10045.2.1 [RFC7250] +static const uint8_t g_EC_PUBLIC_KEY_OID[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}; + +//secp256r1 1.2.840.10045.3.1.7 [RFC5656] +static const uint8_t g_PRIME_256_V1_OID[] = {0x2A, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; + +//commonName 2.5.4.3 [RFC2256] +static const uint8_t g_COMMON_NAME_OID[] = {0x55, 0x04, 0x03}; + +PKIError EncodeCSR (const UTF8String_t *subjectName, + const BIT_STRING_t *subjectPublicKey, + const BIT_STRING_t *subjectPrivateKey, + ByteArray *encodedCSR) +{ + FUNCTION_INIT(); + asn_enc_rval_t ec; /* Encoder return value */ + CertificationRequest_t *certificationRequest = NULL; /* Type to encode */ + AttributeTypeAndValue_t *subjTypeAndValue = NULL; + RelativeDistinguishedName_t *subjRDN = NULL; + uint8_t *uint8Pointer = NULL; + ByteArray tbs = BYTE_ARRAY_INITIALIZER; + uint8_t signature[SIGN_FULL_SIZE]; + uint8_t sha256[SHA_256_HASH_LEN]; + uint8_t ReqInfoInDER[CSR_MAX_SIZE]; + + CHECK_NULL(subjectName, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(subjectPublicKey, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(subjectPrivateKey, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(encodedCSR, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(encodedCSR->data, ISSUER_CSR_NULL_PASSED); + CHECK_LESS_EQUAL(CSR_MAX_SIZE, encodedCSR->len, ISSUER_CSR_WRONG_BYTE_ARRAY_LEN); + + /* Allocate the memory */ + certificationRequest = OICCalloc(1, sizeof(CertificationRequest_t)); // not malloc! + CHECK_NULL(certificationRequest, ISSUER_CSR_MEMORY_ALLOC_FAILED); + + subjTypeAndValue = OICCalloc(1, sizeof(AttributeTypeAndValue_t)); + CHECK_NULL(subjTypeAndValue, ISSUER_CSR_MEMORY_ALLOC_FAILED); + + subjRDN = OICCalloc(1, sizeof(RelativeDistinguishedName_t)); + CHECK_NULL(subjRDN, ISSUER_CSR_MEMORY_ALLOC_FAILED); + + //set subject name + subjTypeAndValue->value = *subjectName; + subjTypeAndValue->type.buf = (uint8_t *)g_COMMON_NAME_OID; //2.5.4.3 + subjTypeAndValue->type.size = sizeof(g_COMMON_NAME_OID) / sizeof(g_COMMON_NAME_OID[0]); + ASN_SET_ADD(subjRDN, subjTypeAndValue); + ASN_SEQUENCE_ADD(&(certificationRequest->certificationRequestInfo.subject), subjRDN); + + //set version 0 + certificationRequest->certificationRequestInfo.version = CSR_DEFAULT_VERSION; + + //set signature algorithm + certificationRequest->signatureAlgorithm.algorithm.buf = + (uint8_t *)g_ECDSA_WITH_SHA256_OID; //1.2.840.10045.4.3.2 + certificationRequest->signatureAlgorithm.algorithm.size = + sizeof(g_ECDSA_WITH_SHA256_OID) / sizeof(g_ECDSA_WITH_SHA256_OID[0]); + certificationRequest->signatureAlgorithm.nul = OICCalloc(1, sizeof(NULL_t)); + CHECK_NULL(certificationRequest->signatureAlgorithm.nul, ISSUER_CSR_MEMORY_ALLOC_FAILED); + + //set subject Public Key algorithm + certificationRequest->certificationRequestInfo.subjectPKInfo.algorithm.algorithm.buf = + (uint8_t *)g_EC_PUBLIC_KEY_OID; //1.2.840.10045.2.1 + certificationRequest->certificationRequestInfo.subjectPKInfo.algorithm.algorithm.size = + sizeof(g_EC_PUBLIC_KEY_OID) / sizeof(g_EC_PUBLIC_KEY_OID[0]); + + //set subject Public Key curve + certificationRequest->certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey = + OICCalloc(1, sizeof(OBJECT_IDENTIFIER_t)); + CHECK_NULL(certificationRequest-> + certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey, + ISSUER_CSR_MEMORY_ALLOC_FAILED); + + certificationRequest->certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey->buf = + (uint8_t *)g_PRIME_256_V1_OID; //1.2.840.10045.3.1.7 + certificationRequest->certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey->size = + sizeof(g_PRIME_256_V1_OID) / sizeof(g_PRIME_256_V1_OID[0]); + + //set subject Public Key + certificationRequest->certificationRequestInfo.subjectPKInfo.subjectPublicKey = + *subjectPublicKey; + + //encode TBS to DER + ec = der_encode_to_buffer(&asn_DEF_CertificationRequestInfo, + &(certificationRequest->certificationRequestInfo), + ReqInfoInDER, CSR_MAX_SIZE); + CHECK_COND(ec.encoded > 0, ISSUER_CSR_DER_ENCODE_FAIL); + tbs.len = ec.encoded; + tbs.data = ReqInfoInDER; + GET_SHA_256(tbs, sha256); + CHECK_COND(uECC_sign((subjectPrivateKey->buf) + 1, sha256, signature), + ISSUER_CSR_SIGNATURE_FAIL); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + + // ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER } (RFC 5480) + certificationRequest->signature.size = SIGN_FULL_SIZE + 6; + // size for SEQUENCE ID + 2 * INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + certificationRequest->signature.size ++; + } + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[SIGN_R_LEN] > 127) + { + certificationRequest->signature.size ++; + } + certificationRequest->signature.buf = OICCalloc(certificationRequest->signature.size, + sizeof(uint8_t)); + CHECK_NULL(certificationRequest->signature.buf, ISSUER_CSR_MEMORY_ALLOC_FAILED); + *(certificationRequest->signature.buf) = (12 << 2); //ASN.1 SEQUENCE ID + *(certificationRequest->signature.buf + 1) = certificationRequest->signature.size - 2; + //ASN.1 SEQUENCE size + + uint8Pointer = certificationRequest->signature.buf + 2; //skip SEQUENCE ID and size + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature[0] > 127) + { + *(uint8Pointer + 1) = SIGN_R_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_R_LEN; //ASN.1 INTEGER size + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature, SIGN_R_LEN); + + uint8Pointer += SIGN_R_LEN; + *uint8Pointer = (2 << 0); //ASN.1 INTEGER ID + + // if first byte of positive INTEGER exceed 127 add 0 byte before + if (signature [SIGN_R_LEN] > 127) + { + *(uint8Pointer + 1) = SIGN_R_LEN + 1; //ASN.1 INTEGER size + uint8Pointer += 3; //skip INTEGER ID and size + } + else + { + *(uint8Pointer + 1) = SIGN_S_LEN; //ASN.1 INTEGER size + uint8Pointer += 2; //skip INTEGER ID and size + } + memcpy(uint8Pointer, signature + SIGN_R_LEN, SIGN_S_LEN); + + ec = der_encode_to_buffer(&asn_DEF_CertificationRequest, certificationRequest, + encodedCSR->data, CSR_MAX_SIZE); + CHECK_COND(ec.encoded > 0, ISSUER_CSR_DER_ENCODE_FAIL); + encodedCSR->len = ec.encoded; + + FUNCTION_CLEAR( + if (subjTypeAndValue) + { + subjTypeAndValue->value.buf = NULL; + subjTypeAndValue->type.buf = NULL; + } + if (certificationRequest) + { + certificationRequest-> + certificationRequestInfo.subjectPKInfo.algorithm.algorithm.buf = NULL; + + certificationRequest->signatureAlgorithm.algorithm.buf = NULL; + + if (certificationRequest-> + certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey) + { + certificationRequest-> + certificationRequestInfo.subjectPKInfo.algorithm.id_ecPublicKey->buf = NULL; + } + } + ASN_STRUCT_FREE(asn_DEF_CertificationRequest, certificationRequest); + certificationRequest = NULL; + ); +} + +PKIError DecodeCSR (const ByteArray *encodedCSR, + UTF8String_t *subjectName, BIT_STRING_t *subjectPublicKey) +{ + FUNCTION_INIT(); + asn_dec_rval_t rval; /* Decoder return value */ + asn_enc_rval_t ec; /* Encoder return value */ + CertificationRequest_t *certificationRequest = NULL; // Type to decode + ByteArray tbs = BYTE_ARRAY_INITIALIZER; + uint8_t sha256[SHA_256_HASH_LEN]; + uint8_t ReqInfoInDER[CSR_MAX_SIZE]; + uint8_t signature[SIGN_FULL_SIZE]; + + CHECK_NULL(encodedCSR, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(encodedCSR->data, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(subjectName, ISSUER_CSR_NULL_PASSED); + CHECK_NULL(subjectPublicKey, ISSUER_CSR_NULL_PASSED); + + rval = ber_decode(0, &asn_DEF_CertificationRequest, (void **)&certificationRequest, + encodedCSR->data, encodedCSR->len); + CHECK_EQUAL(rval.code, RC_OK, ISSUER_CSR_DER_DECODE_FAIL); + + //encode TBS to DER + ec = der_encode_to_buffer(&asn_DEF_CertificationRequestInfo, + &(certificationRequest->certificationRequestInfo), + ReqInfoInDER, CSR_MAX_SIZE); + CHECK_COND(ec.encoded > 0, ISSUER_CSR_DER_ENCODE_FAIL); + tbs.len = ec.encoded; + tbs.data = ReqInfoInDER; + GET_SHA_256(tbs, sha256); + + // ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER } (RFC 5480) + if (*(certificationRequest->signature.buf + 3) > SIGN_R_LEN) //check length of first INTEGER (r) + { + //move to start of second INTEGER (s) + memcpy(signature, certificationRequest->signature.buf + 5, SIGN_R_LEN); + } + else + { + //move to start of second INTEGER (s) + memcpy(signature, certificationRequest->signature.buf + 4, SIGN_R_LEN); + } + memcpy((signature + SIGN_R_LEN), + (certificationRequest->signature.buf + + certificationRequest->signature.size - SIGN_S_LEN), SIGN_S_LEN); + //verify signature + CHECK_COND(uECC_verify(certificationRequest-> + certificationRequestInfo.subjectPKInfo.subjectPublicKey.buf + 1, + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + sha256, signature), ISSUER_CSR_INVALID_SIGNATURE); + + subjectName->size = + certificationRequest->certificationRequestInfo.subject.list.array[0]-> + list.array[0]->value.size; + CHECK_LESS_EQUAL(subjectName->size, CSR_MAX_NAME_SIZE, ISSUER_CSR_TOO_LONG_NAME); + memcpy(subjectName->buf, + certificationRequest->certificationRequestInfo.subject.list.array[0]-> + list.array[0]->value.buf, subjectName->size); + + subjectPublicKey->size = + certificationRequest->certificationRequestInfo.subjectPKInfo.subjectPublicKey.size; + CHECK_EQUAL(subjectPublicKey->size, PUBLIC_KEY_SIZE + 1, ISSUER_CSR_INVALID_KEY_FORMAT); + //additional byte for ASN1_UNCOMPRESSED_KEY_ID + + memcpy(subjectPublicKey->buf, + certificationRequest->certificationRequestInfo.subjectPKInfo.subjectPublicKey.buf, + subjectPublicKey->size); + + FUNCTION_CLEAR( + ASN_STRUCT_FREE(asn_DEF_CertificationRequest, certificationRequest); + ); +}