implement certificate key manager
authorOleksii Udod <o.udod@samsung.com>
Mon, 14 Sep 2015 14:11:13 +0000 (17:11 +0300)
committerSachin Agrawal <sachin.agrawal@intel.com>
Fri, 18 Sep 2015 23:19:54 +0000 (23:19 +0000)
Change-Id: Ie77bc7f7cffe9536a0ca7a24625af17d01bf63ed
Signed-off-by: Oleksii Udod <o.udod@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2447
Reviewed-by: dongik Lee <dongik.lee@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sachin Agrawal <sachin.agrawal@intel.com>
resource/csdk/security/provisioning/ck_manager/include/cert_generator.h [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/include/ck_manager.h [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/include/ckm_info.h [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/include/crl_generator.h [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/include/csr_generator.h [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/src/cert_generator.c [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/src/ck_manager.c [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/src/ckm_info.c [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/src/crl_generator.c [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/src/csr_generator.c [new file with mode: 0644]

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 (file)
index 0000000..a21980f
--- /dev/null
@@ -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 (file)
index 0000000..02ac6a3
--- /dev/null
@@ -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 <stdio.h>
+
+#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 (file)
index 0000000..c3ce9d3
--- /dev/null
@@ -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 <stdio.h>
+#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 (file)
index 0000000..dfdec1c
--- /dev/null
@@ -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 (file)
index 0000000..e1f0870
--- /dev/null
@@ -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 (file)
index 0000000..ec9bf74
--- /dev/null
@@ -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 (file)
index 0000000..df79fd5
--- /dev/null
@@ -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 (file)
index 0000000..cd4bf15
--- /dev/null
@@ -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 (file)
index 0000000..1c48dea
--- /dev/null
@@ -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 (file)
index 0000000..95662e7
--- /dev/null
@@ -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);
+    );
+}