Merge branch 'master' into iot-1785
authorKevin Kane <kkane@microsoft.com>
Fri, 3 Mar 2017 20:59:10 +0000 (12:59 -0800)
committerKevin Kane <kkane@microsoft.com>
Fri, 3 Mar 2017 21:27:34 +0000 (13:27 -0800)
Build breaks fixed.
occertutility.{c,h} moved back into security subtree.

Change-Id: I348dbe5d2133b57a49d4cdef05ce6e747af5eea0
Signed-off-by: Kevin Kane <kkane@microsoft.com>
19 files changed:
1  2 
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/src/adapter_util/ca_adapter_net_ssl.c
resource/csdk/security/SConscript
resource/csdk/security/include/occertutility.h
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
resource/csdk/security/provisioning/include/ocprovisioningmanager.h
resource/csdk/security/provisioning/include/pmtypes.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/certgenerator.cpp
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/csrresource.c
resource/csdk/security/src/occertutility.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/security/unittest/credentialresource.cpp
resource/csdk/stack/octbstack_product_secured.def

@@@ -123,7 -129,6 +129,7 @@@ if libocsrm_env.get('SECURED') == '1'
        libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmpincommon.c', OCSRM_SRC + 'pbkdf2.c']
        libocsrm_src = libocsrm_src + [OCSRM_SRC + 'crlresource.c', OCSRM_SRC + 'pkix_interface.c']
        libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmverifycommon.c']
-       libocsrm_src = libocsrm_src + [OCSRM_SRC + 'certhelpers.c', OCSRM_SRC + 'csrresource.c']
++      libocsrm_src = libocsrm_src + [OCSRM_SRC + 'certhelpers.c', OCSRM_SRC + 'csrresource.c', OCSRM_SRC + 'occertutility.c' ]
  
  if target_os in ['windows', 'msys_nt']:
        libocsrm_src  = libocsrm_src + [OCSRM_SRC + 'strptime.c']
index 7b3aa26,0000000..6db0b4f
mode 100644,000000..100644
--- /dev/null
@@@ -1,537 -1,0 +1,535 @@@
-     
-     return 0;
 +//******************************************************************
 +//
 +// Copyright 2017 Microsoft
 +//
 +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 +//
 +// 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
 +//
 +//      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 <stdio.h>
 +#include <string.h>
 +#include <errno.h>
 +#include <time.h>
 +#include <vector>
 +
 +#include "ocstack.h"
 +#include "oic_malloc.h"
 +#include "ocrandom.h"
 +#include "occertutility.h"
 +
 +#ifdef HAVE_WINDOWS_H
 +#include <windows.h>
 +/** @todo stop-gap for naming issue. Windows.h does not like us to use ERROR */
 +#ifdef ERROR
 +#undef ERROR
 +#endif //ERROR
 +#endif //HAVE_WINDOWS_H
 +
 +static long GetFileSize(FILE *f)
 +{
 +    long offset, size;
 +
 +    offset = ftell(f);
 +
 +    if (offset < 0)
 +    {
 +        return offset;
 +    }
 +
 +    if (fseek(f, 0, SEEK_END) < 0)
 +    {
 +        return -1;
 +    }
 +
 +    size = ftell(f);
 +
 +    if (fseek(f, 0, SEEK_SET) < 0)
 +    {
 +        return -1;
 +    }
 +
 +    return size;
 +}
 +
 +static char *ReadLine(char *buf, size_t len)
 +{
 +    char *p;
 +    int lenAsInt;
 +
 +    if (len > 0xFFFFFFFF)
 +    {
 +        return NULL;
 +    }
 +    else
 +    {
 +        lenAsInt = (int)len;
 +    }
 +
 +    if (NULL == fgets(buf, lenAsInt, stdin))
 +    {
 +        return NULL;
 +    }
 +
 +    /* Trim newline that fgets stores in the buffer. */
 +    for (p = buf; ((p - buf) < lenAsInt) && (*p != '\r') && (*p != '\n'); p++);
 +
 +    *p = '\0';
 +
 +    return buf;
 +}
 +
 +typedef enum {
 +    CA_CERT,
 +    IDENTITY_CERT,
 +    ROLE_CERT
 +} CertType;
 +
 +static void DoGenCertificate(CertType certType)
 +{
 +    OCStackResult res;
 +    char subjKeyPairName[50];
 +    char issKeyPairName[50];
 +    char filename[70];
 +    char subject[100];
 +    char authority[100];
 +    OicUuid_t subjectUuid;
 +    char notValidBefore[50];
 +    char notValidAfter[50];
 +    char *serial = NULL;
 +    size_t serialLen = 0;
 +    long fileLen = 0;
 +    size_t bytesProcessed = 0;
 +    std::vector<char> publicKey;
 +    std::vector<char> privateKey;
 +    std::vector<char> issuerCert;
 +    FILE *f = NULL;
 +    time_t nowTimeT;
 +    struct tm *now;
 +    char *certificate = NULL;
 +    size_t certificateLen = 0;
 +
 +    printf("Subject key pair name (do not include .pub or .prv): ");
 +    if (NULL == ReadLine(subjKeyPairName, sizeof(subjKeyPairName)))
 +    {
 +        printf("Failed to get key pair name!");
 +        goto exit;
 +    }
 +
 +    /* This sample only supports self-signed CAs. Intermediates can be created with
 +     * the helper functions, though, by providing a different issuer private key and
 +     * certificate.
 +     */
 +    if (CA_CERT != certType)
 +    {
 +        printf("Issuer cert/key pair name (do not include .crt, .pub, or .prv): ");
 +        if (NULL == ReadLine(issKeyPairName, sizeof(issKeyPairName)))
 +        {
 +            printf("Failed to get key pair name!");
 +            goto exit;
 +        }
 +    }
 +    else
 +    {
 +        strcpy(issKeyPairName, subjKeyPairName);
 +    }
 +
 +    // -- Load public key --
 +
 +    sprintf(filename, "%s.pub", subjKeyPairName);
 +    f = fopen(filename, "rb");
 +    if (NULL == f)
 +    {
 +        printf("Could not open public key!\n");
 +        goto exit;
 +    }
 +
 +    fileLen = GetFileSize(f);
 +    if (fileLen < 0)
 +    {
 +        printf("Could not get size of public key!\n");
 +        goto exit;
 +    }
 +
 +    publicKey.resize(fileLen);
 +    bytesProcessed = fread(publicKey.data(), 1, publicKey.size(), f);
 +    if (bytesProcessed < publicKey.size())
 +    {
 +        printf("Could not read public key! Got %zu, expected %zu\n", bytesProcessed, publicKey.size());
 +        goto exit;
 +    }
 +
 +    if (0 != fclose(f))
 +    {
 +        printf("Warning: could not fclose public key\n");
 +    }
 +
 +    // -- Load private key --
 +    sprintf(filename, "%s.prv", issKeyPairName);
 +    f = fopen(filename, "rb");
 +    if (NULL == f)
 +    {
 +        printf("Could not open private key!\n");
 +        goto exit;
 +    }
 +
 +    fileLen = GetFileSize(f);
 +    if (fileLen < 0)
 +    {
 +        printf("Could not get size of private key!\n");
 +        goto exit;
 +    }
 +
 +    privateKey.resize(fileLen);
 +    bytesProcessed = fread(privateKey.data(), 1, privateKey.size(), f);
 +    if (bytesProcessed < privateKey.size())
 +    {
 +        printf("Could not read private key! Got %zu, expected %zu\n", bytesProcessed, privateKey.size());
 +        goto exit;
 +    }
 +
 +    if (0 != fclose(f))
 +    {
 +        printf("Warning: could not fclose private key\n");
 +    }
 +
 +    f = NULL;
 +
 +    // -- Load issuer cert if applicable --
 +    if (CA_CERT != certType)
 +    {
 +        sprintf(filename, "%s.crt", issKeyPairName);
 +        f = fopen(filename, "rb");
 +        if (NULL == f)
 +        {
 +            printf("Could not open issuer certificate file!\n");
 +            goto exit;
 +        }
 +
 +        fileLen = GetFileSize(f);
 +        if (fileLen < 0)
 +        {
 +            printf("Could not get size of issuer certificate!\n");
 +            goto exit;
 +        }
 +
 +        issuerCert.resize(fileLen);
 +        bytesProcessed = fread(issuerCert.data(), 1, issuerCert.size(), f);
 +        if (bytesProcessed < issuerCert.size())
 +        {
 +            printf("Could not read issuer certificate! Got %zu, expected %zu\n", bytesProcessed, issuerCert.size());
 +            goto exit;
 +        }
 +
 +        if (0 != fclose(f))
 +        {
 +            printf("Warning: could not fclose issuer certificate\n");
 +        }
 +
 +        f = NULL;
 +    }
 +
 +    // -- Prompt user for subject name --
 +
 +    if (CA_CERT == certType)
 +    {
 +        printf("Subject name as comma-separated list of RDN types and values\n");
 +        printf("e.g.: C=US, O=Open Connectivity Foundation, CN=Main CA : ");
 +        if (NULL == ReadLine(subject, sizeof(subject)))
 +        {
 +            printf("Failed to get subject!\n");
 +            goto exit;
 +        }
 +    }
 +    else
 +    {
 +        printf("Subject UUID in the RFC 4122 form (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX): ");
 +        if (NULL == ReadLine(subject, sizeof(subject)))
 +        {
 +            printf("Failed to get subject UUID!");
 +            goto exit;
 +        }
 +
 +        if (!OCConvertStringToUuid(subject, subjectUuid.id))
 +        {
 +            printf("Failed to parse input UUID!\n");
 +            goto exit;
 +        }
 +    }
 +
 +    // -- Compute validity to be ten years from current time --
 +    nowTimeT = time(NULL);
 +    now = gmtime(&nowTimeT);
 +
 +    if (0 == strftime(notValidBefore, sizeof(notValidBefore), "%Y%m%d%H%M%S", now))
 +    {
 +        printf("Failed to format notValidBefore time!");
 +        goto exit;
 +    }
 +
 +    now->tm_year += 10;
 +
 +    if (0 == strftime(notValidAfter, sizeof(notValidAfter), "%Y%m%d%H%M%S", now))
 +    {
 +        printf("Failed to format notValidAfter time!");
 +        goto exit;
 +    }
 +
 +    // -- Generate random serial number. A real CA should record serial numbers as they are used, and --
 +    // -- make sure none are ever repeated!                                                           --
 +
 +    res = OCGenerateRandomSerialNumber(&serial, &serialLen);
 +    if (OC_STACK_OK != res)
 +    {
 +        printf("Failed to generate a serial number!\n");
 +        goto exit;
 +    }
 +
 +    switch (certType)
 +    {
 +    case CA_CERT:
 +        res = OCGenerateCACertificate(
 +            subject,
 +            publicKey.data(),
 +            NULL,
 +            privateKey.data(),
 +            serial,
 +            notValidBefore,
 +            notValidAfter,
 +            &certificate,
 +            &certificateLen);
 +        break;
 +
 +    case IDENTITY_CERT:
 +        res = OCGenerateIdentityCertificate(
 +            &subjectUuid,
 +            publicKey.data(),
 +            issuerCert.data(),
 +            privateKey.data(),
 +            serial,
 +            notValidBefore,
 +            notValidAfter,
 +            &certificate,
 +            &certificateLen);
 +        break;
 +
 +    case ROLE_CERT:
 +        printf("Role name: ");
 +        /* We don't need subject's contents now, so reuse the buffer.*/
 +        if (NULL == ReadLine(subject, sizeof(subject)))
 +        {
 +            printf("Failed to read role name!\n");
 +            goto exit;
 +        }
 +        printf("Authority name (press ENTER for none): ");
 +        if (NULL == ReadLine(authority, sizeof(authority)))
 +        {
 +            printf("Failed to read authority name!\n");
 +            goto exit;
 +        }
 +        res = OCGenerateRoleCertificate(
 +            &subjectUuid,
 +            publicKey.data(),
 +            issuerCert.data(),
 +            privateKey.data(),
 +            serial,
 +            notValidBefore,
 +            notValidAfter,
 +            subject,
 +            ('\0' != *authority)?authority:NULL,
 +            &certificate,
 +            &certificateLen);
 +        break;
 +    }
 +
 +    if (OC_STACK_OK != res)
 +    {
 +        printf("Failed to generate certificate!\n");
 +        goto exit;
 +    }
 +
 +    sprintf(filename, "%s.crt", subjKeyPairName);
 +    f = fopen(filename, "wb");
 +    if (NULL == f)
 +    {
 +        printf("Failed to open certificate file for writing!\n");
 +        goto exit;
 +    }
 +    
 +    bytesProcessed = fwrite(certificate, 1, certificateLen, f);
 +    if (bytesProcessed < certificateLen)
 +    {
 +        printf("Failed to write certificate! Had %zu bytes, wrote %zu\n", certificateLen, bytesProcessed);
 +        goto exit;
 +    }
 +
 +    if (0 != fclose(f))
 +    {
 +        printf("Warning: failed to close certificate file\n");
 +        goto exit;
 +    }
 +
 +    f = NULL;
 +
 +    printf("Wrote certificate file.\n");
 +
 +exit:
 +
 +    OICFree(serial);
 +    OICFree(certificate);
 +    if (NULL != f)
 +    {
 +        if (0 != fclose(f))
 +        {
 +            printf("Warning: failed to fclose\n");
 +        }
 +    }
 +}
 +
 +static void DoGenKeyPair()
 +{
 +    OCStackResult res = OC_STACK_OK;
 +    char nameBuf[100];
 +    char *publicKey = NULL;
 +    char *privateKey = NULL;
 +    size_t publicKeyLen = 0;
 +    size_t privateKeyLen = 0;
 +    FILE *f = NULL;
 +
 +    printf("Name the key pair: ");
 +    if (NULL == ReadLine(nameBuf, sizeof(nameBuf)))
 +    {
 +        printf("Failed to read name!");
 +        return;
 +    }
 +
 +    res = OCGenerateKeyPair(&publicKey, &publicKeyLen, &privateKey, &privateKeyLen);
 +    if (OC_STACK_OK == res)
 +    {
 +        char filename[120];
 +        size_t written;
 +
 +        sprintf(filename, "%s.pub", nameBuf);
 +        f = fopen(filename, "wb");
 +        if (NULL == f)
 +        {
 +            printf("Couldn't open %s to write public key!\n", filename);
 +            goto exit;
 +        }
 +
 +        written = fwrite(publicKey, 1, publicKeyLen, f);
 +        if (written < publicKeyLen)
 +        {
 +            printf("Failed to write public key! Had %zu, wrote %zu\n", publicKeyLen, written);
 +            goto exit;
 +        }
 +
 +        if (0 != fclose(f))
 +        {
 +            printf("Warning: failed to fclose. Errno: %d\n", errno);
 +        }
 +
 +        printf("Wrote public key.\n");
 +
 +        sprintf(filename, "%s.prv", nameBuf);
 +        f = fopen(filename, "wb");
 +        if (NULL == f)
 +        {
 +            printf("Couldn't open %s to write private key!\n", filename);
 +            goto exit;
 +        }
 +        written = fwrite(privateKey, 1, privateKeyLen, f);
 +        if (written < privateKeyLen)
 +        {
 +            printf("Failed to write private key! Had %zu, wrote %zu\n", privateKeyLen, written);
 +            goto exit;
 +        }
 +
 +        if (0 != fclose(f))
 +        {
 +            printf("Warning: failed to fclose. Errno: %d\n", errno);
 +        }
 +        f = NULL;
 +
 +        printf("Wrote private key.\n");
 +    }
 +    else
 +    {
 +        printf("Failed!\n");
 +    }
 +
 +exit:
 +
 +    OICFree(publicKey);
 +    OICClearMemory(privateKey, privateKeyLen);
 +    OICFree(privateKey);
 +    if (NULL != f)
 +    {
 +        if (0 != fclose(f))
 +        {
 +            printf("Warning: failed to fclose. errno: %d\n", errno);
 +        }
 +    }
 +}
 +
 +int main()
 +{
 +    for (;;)
 +    {
 +        int option;
 +
 +        printf("-- Certificate Generator Sample Utility --\n\n");
 +
 +        printf(" 1. Generate a new key pair\n");
 +        printf(" 2. Generate a self-signed CA certificate (requires a key pair for the CA)\n");
 +        printf(" 3. Generate an identity certificate for a particular device UUID\n");
 +        printf("       (requires the CA's private key and certificate, and the device's public key)\n");
 +        printf(" 4. Generate a role certificate for a particular device UUID and role\n");
 +        printf("       (requires the CA's private key and certificate, and the device's public key)\n");
 +
 +        printf("\n");
 +        printf(" 0. Exit\n");
 +        printf("\n");
 +        printf("Select: ");
 +
 +        if (scanf("%d", &option) < 1)
 +        {
 +            printf("Failed to read the option! Exiting.\n");
 +            return 0;
 +        }
 +
 +        while ('\n' != getchar()); /* Consume the rest of the line so it doesn't get fed to the next input. */
 +
 +        switch (option)
 +        {
 +        case 1:
 +            DoGenKeyPair();
 +            break;
 +        case 2:
 +            DoGenCertificate(CA_CERT);
 +            break;
 +        case 3:
 +            DoGenCertificate(IDENTITY_CERT);
 +            break;
 +        case 4:
 +            DoGenCertificate(ROLE_CERT);
 +            break;
 +        case 0:
 +            return 0;
 +        default:
 +            printf("Invalid option %d\n\n", option);
 +            break;
 +        }
 +    }
 +}
index 4ac1ea7,f6301c9..1578551
mode 100644,100755..100755
@@@ -945,8 -978,14 +981,6 @@@ OCStackResult CBORPayloadToCred(const u
                              {
                                  cborFindResult = DeserializeEncodingFromCbor(&credMap, &cred->privateData);
                                  VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to read privateData structure");
--
--                                OicEncodingType_t encoding = cred->privateData.encoding;
 -                                if (OIC_ENCODING_DER == encoding || OIC_ENCODING_PEM == encoding)
 -                                {
 -                                    //For unit test
 -                                    cred->privateData.encoding = OIC_ENCODING_RAW;
 -                                    OIC_LOG(WARNING, TAG, "Unknown encoding type detected for private data.");
 -                                }
                              }
  #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
                              //PublicData -- Not Mandatory
index 2a39e68,0000000..b1105b9
mode 100644,000000..100644
--- /dev/null
@@@ -1,528 -1,0 +1,528 @@@
-     VERIFY_NOT_NULL(TAG, outPayload, ERROR);
 +//******************************************************************
 +//
 +// Copyright 2017 Microsoft
 +//
 +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 +//
 +// 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
 +//
 +//      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 "iotivity_config.h"
 +#include <stdlib.h>
 +#ifdef HAVE_STRING_H
 +#include <string.h>
 +#endif
 +#ifdef HAVE_STRINGS_H
 +#include <strings.h>
 +#endif
 +#include <stdint.h>
 +#include <stdbool.h>
 +#include <inttypes.h>
 +#include "oic_string.h"
 +#include "cainterface.h"
 +#include "payload_logging.h"
 +#include "ocstack.h"
 +#include "ocrandom.h"
 +#include "cacommon.h"
 +#include "srmresourcestrings.h"
 +#include "ocpayload.h"
 +#include "ocpayloadcbor.h"
 +#include "credresource.h"
 +#include "doxmresource.h"
 +#include "srmutility.h"
 +#include "certhelpers.h"
 +#include "csrresource.h"
 +#include "resourcemanager.h"
 +
 +#define TAG  "OIC_SRM_CSR"
 +
 +static OCResourceHandle    gCsrHandle = NULL;
 +
 +/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
 + * The value of payload size is increased until reaching belox max cbor size.
 + */
 +static const uint16_t CBOR_SIZE = 2048;
 +
 +static const char* EncodingValueToString(OicEncodingType_t encoding)
 +{
 +    switch (encoding)
 +    {
 +    case OIC_ENCODING_RAW:    return OIC_SEC_ENCODING_RAW;
 +    case OIC_ENCODING_BASE64: return OIC_SEC_ENCODING_BASE64;
 +    case OIC_ENCODING_DER:    return OIC_SEC_ENCODING_DER;
 +    case OIC_ENCODING_PEM:    return OIC_SEC_ENCODING_PEM;
 +    default:                  return NULL;
 +    }
 +}
 +
 +
 +static OCStackResult StoreKeyPair(mbedtls_pk_context *keyPair, const OicUuid_t *myUuid)
 +{
 +    int ret = 0;
 +    OicSecCred_t *cred = NULL;
 +    OicSecKey_t publicData;
 +    OicSecKey_t privateData;
 +    uint8_t publicBuf[1024];
 +    uint8_t privateBuf[1024];
 +
 +    /* These DER writing APIs write at the END of the buffers, hence the pointer arithmetic. See the API
 +     * documentation for mbedTLS.
 +     */
 +
 +    ret = mbedtls_pk_write_pubkey_der(keyPair, publicBuf, sizeof(publicBuf));
 +    VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +    publicData.data = publicBuf + sizeof(publicBuf) - ret;
 +    publicData.len = ret;
 +    publicData.encoding = OIC_ENCODING_DER;
 +
 +    ret = mbedtls_pk_write_key_der(keyPair, privateBuf, sizeof(privateBuf));
 +    VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +    privateData.data = privateBuf + sizeof(privateBuf) - ret;
 +    privateData.len = ret;
 +    privateData.encoding = OIC_ENCODING_DER;
 +
 +    cred = GenerateCredential(myUuid, ASYMMETRIC_KEY, &publicData, &privateData, myUuid, NULL);
 +    VERIFY_NOT_NULL(TAG, cred, ERROR);
 +    cred->credUsage = OICStrdup(PRIMARY_KEY); // @todo: we may be able to use PRIMARY_CERT here too; need to investigate
 +    VERIFY_NOT_NULL(TAG, cred->credUsage, ERROR);
 +
 +    VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
 +
 +    return OC_STACK_OK;
 +
 +exit:
 +
 +    if (NULL != cred)
 +    {
 +        DeleteCredList(cred);
 +    }
 +
 +    OICClearMemory(privateBuf, sizeof(privateBuf));
 +
 +    return OC_STACK_ERROR;
 +}
 +
 +static OCStackResult CSRToCBORPayload(const uint8_t *csr, size_t csrLen, OicEncodingType_t encoding, uint8_t **cborPayload, size_t *cborSize)
 +{
 +    OCStackResult ret = OC_STACK_ERROR;
 +
 +    CborError cborEncoderResult = CborNoError;
 +    uint8_t *outPayload = NULL;
 +    size_t cborLen = *cborSize;
 +    CborEncoder encoder;
 +    CborEncoder csrRootMap;
 +    const char *strEncoding = NULL;
 +
 +    if ((NULL == csr) || (0 == csrLen) || (NULL == cborPayload) || (NULL == cborSize))
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    if ((OIC_ENCODING_DER != encoding) && (OIC_ENCODING_PEM != encoding))
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    *cborSize = 0;
 +    *cborPayload = NULL;
 +
 +    if (0 == cborLen)
 +    {
 +        cborLen = CBOR_SIZE;
 +    }
 +
 +    outPayload = (uint8_t *)OICCalloc(1, cborLen);
++    VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_NO_MEMORY);
 +    cbor_encoder_init(&encoder, outPayload, cborLen, 0);
 +
 +    // Create CSR Root Map (csr)
 +    cborEncoderResult = cbor_encoder_create_map(&encoder, &csrRootMap, 4);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CSR Root Map");
 +
 +    // Create CSR string entry
 +    cborEncoderResult = cbor_encode_text_string(&csrRootMap, OIC_JSON_CSR_NAME, strlen(OIC_JSON_CSR_NAME));
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding CSR name.");
 +    cborEncoderResult = cbor_encode_byte_string(&csrRootMap, csr, csrLen);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding CSR value.");
 +
 +    // Create encoding entry
 +    cborEncoderResult = cbor_encode_text_string(&csrRootMap, OIC_JSON_ENCODING_NAME, strlen(OIC_JSON_ENCODING_NAME));
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding encoding name.");
 +    strEncoding = EncodingValueToString(encoding);
 +    assert(strEncoding != NULL);
 +    cborEncoderResult = cbor_encode_text_string(&csrRootMap, strEncoding, strlen(strEncoding));
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding encoding value.");
 +
 +    // Rownerid
 +    {
 +        char *rowner = NULL;
 +        OicUuid_t myUuid;
 +        cborEncoderResult = cbor_encode_text_string(&csrRootMap, OIC_JSON_ROWNERID_NAME,
 +            strlen(OIC_JSON_ROWNERID_NAME));
 +        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
 +        ret = GetDoxmDeviceID(&myUuid);
 +        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
 +        ret = ConvertUuidToStr(&myUuid, &rowner);
 +        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
 +        cborEncoderResult = cbor_encode_text_string(&csrRootMap, rowner, strlen(rowner));
 +        OICFree(rowner);
 +        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
 +    }
 +
 +    //RT -- Mandatory
 +    CborEncoder rtArray;
 +    cborEncoderResult = cbor_encode_text_string(&csrRootMap, OIC_JSON_RT_NAME,
 +        strlen(OIC_JSON_RT_NAME));
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
 +    cborEncoderResult = cbor_encoder_create_array(&csrRootMap, &rtArray, 1);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding RT Value.");
 +    for (size_t i = 0; i < 1; i++)
 +    {
 +        cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_CSR,
 +            strlen(OIC_RSRC_TYPE_SEC_CSR));
 +        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding RT Value.");
 +    }
 +    cborEncoderResult = cbor_encoder_close_container(&csrRootMap, &rtArray);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing RT.");
 +
 +    //IF-- Mandatory
 +    CborEncoder ifArray;
 +    cborEncoderResult = cbor_encode_text_string(&csrRootMap, OIC_JSON_IF_NAME,
 +        strlen(OIC_JSON_IF_NAME));
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
 +    cborEncoderResult = cbor_encoder_create_array(&csrRootMap, &ifArray, 1);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding IF Value.");
 +    for (size_t i = 0; i < 1; i++)
 +    {
 +        cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
 +            strlen(OC_RSRVD_INTERFACE_DEFAULT));
 +        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding IF Value.");
 +    }
 +    cborEncoderResult = cbor_encoder_close_container(&csrRootMap, &ifArray);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing IF.");
 +
 +    // Close CSR Map
 +    cborEncoderResult = cbor_encoder_close_container(&encoder, &csrRootMap);
 +    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing CSR root Map.");
 +
 +    if (CborNoError == cborEncoderResult)
 +    {
 +        OIC_LOG(DEBUG, TAG, "CSRToCBORPayload Succeeded");
 +        *cborSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
 +        *cborPayload = outPayload;
 +        ret = OC_STACK_OK;
 +    }
 +exit:
 +    if (CborErrorOutOfMemory == cborEncoderResult)
 +    {
 +        OIC_LOG(DEBUG, TAG, "CSRToCBORPayload:CborErrorOutOfMemory : retry with more memory");
 +
 +        // reallocate and try again!
 +        OICFree(outPayload);
 +        // Since the allocated initial memory failed, double the memory.
 +        cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
 +        cborEncoderResult = CborNoError;
 +        ret = CSRToCBORPayload(csr, csrLen, encoding, cborPayload, &cborLen);
 +        *cborSize = cborLen;
 +    }
 +    else if (cborEncoderResult != CborNoError)
 +    {
 +        OIC_LOG(ERROR, TAG, "Failed to CSRToCBORPayload");
 +        OICFree(outPayload);
 +        outPayload = NULL;
 +        *cborSize = 0;
 +        *cborPayload = NULL;
 +        ret = OC_STACK_ERROR;
 +    }
 +
 +    return ret;
 +}
 +
 +OCStackResult CBORPayloadToCSR(const uint8_t *cborPayload, size_t size, uint8_t **csr, size_t *csrLen, OicEncodingType_t *encoding)
 +{
 +    if (NULL == cborPayload || 0 == size || NULL == csr || NULL == csrLen)
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    OCStackResult ret = OC_STACK_ERROR;
 +    CborValue csrCbor = { .parser = NULL };
 +    CborParser parser = { .end = NULL };
 +    CborError cborFindResult = CborNoError;
 +    uint8_t* cborCsr = NULL;
 +    size_t cborCsrLen = 0;
 +    char* tagName = NULL;
 +    size_t len = 0;
 +
 +    cborFindResult = cbor_parser_init(cborPayload, size, 0, &parser, &csrCbor);
 +    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to initialize parser.");
 +
 +    if (!cbor_value_is_container(&csrCbor))
 +    {
 +        return OC_STACK_ERROR;
 +    }
 +
 +    // Enter CSR Root Map
 +    CborValue csrRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
 +    cborFindResult = cbor_value_enter_container(&csrCbor, &csrRootMap);
 +    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering CSR Root Map.");
 +
 +    while (cbor_value_is_valid(&csrRootMap))
 +    {
 +        if (NULL != tagName)
 +        {
 +            free(tagName);
 +            tagName = NULL;
 +        }
 +        len = 0;
 +        CborType type = cbor_value_get_type(&csrRootMap);
 +        if (type == CborTextStringType && cbor_value_is_text_string(&csrRootMap))
 +        {
 +            cborFindResult = cbor_value_dup_text_string(&csrRootMap, &tagName, &len, NULL);
 +            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding name in CSR Root Map.");
 +            cborFindResult = cbor_value_advance(&csrRootMap);
 +            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing value in CSR Root Map.");
 +        }
 +        if (NULL != tagName)
 +        {
 +            if (strcmp(tagName, OIC_JSON_CSR_NAME) == 0 && cbor_value_is_byte_string(&csrRootMap))
 +            {
 +                cborFindResult = cbor_value_dup_byte_string(&csrRootMap, &cborCsr, &cborCsrLen, NULL);
 +                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding name in CSR Map");
 +                // Use our own heap allocator and copy the result in so callers can use OICFree.
 +                *csr = (uint8_t *)OICCalloc(1, cborCsrLen);
 +                VERIFY_NOT_NULL(TAG, *csr, ERROR);
 +                memcpy(*csr, cborCsr, cborCsrLen);
 +                free(cborCsr);
 +                cborCsr = NULL;
 +                *csrLen = cborCsrLen;
 +                cborCsrLen = 0;
 +            }
 +            else if (strcmp(tagName, OIC_JSON_ENCODING_NAME) == 0 && cbor_value_is_text_string(&csrRootMap))
 +            {
 +                char *strEncoding = NULL;
 +                cborFindResult = cbor_value_dup_text_string(&csrRootMap, &strEncoding, &len, NULL);
 +                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed finding encoding type");
 +
 +                if (strcmp(strEncoding, OIC_SEC_ENCODING_DER) == 0)
 +                {
 +                    *encoding = OIC_ENCODING_DER;
 +                }
 +                else if (strcmp(strEncoding, OIC_SEC_ENCODING_PEM) == 0)
 +                {
 +                    *encoding = OIC_ENCODING_PEM;
 +                }
 +                else
 +                {
 +                    OIC_LOG_V(ERROR, TAG, "Invalid encoding type %s", strEncoding);
 +                    ret = OC_STACK_ERROR;
 +                    free(strEncoding);
 +                    goto exit;
 +                }
 +
 +                free(strEncoding);
 +            }
 +            else
 +            {
 +                // Ignore any other tag type for now.
 +                OIC_LOG_V(WARNING, TAG, "Unknown tag %s", tagName);
 +            }
 +
 +        }
 +        if (cbor_value_is_valid(&csrRootMap))
 +        {
 +            cborFindResult = cbor_value_advance(&csrRootMap);
 +            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed advancing CSR Root Map");
 +        }
 +    }
 +
 +    ret = OC_STACK_OK;
 +
 +exit:
 +    if (CborNoError != cborFindResult)
 +    {
 +        if (NULL != *csr)
 +        {
 +            OICFreeAndSetToNull((void **)csr);
 +        }
 +
 +        *csrLen = 0;
 +
 +        ret = OC_STACK_ERROR;
 +    }
 +
 +    // tagName and cborCsr are both allocated internally by tinycbor, which uses malloc, not OICMalloc.
 +    // Therefore, they must be freed with free, not OICFree.
 +    if (NULL != tagName)
 +    {
 +        free(tagName);
 +    }
 +    if (NULL != cborCsr)
 +    {
 +        free(cborCsr);
 +    }
 +
 +    return ret;
 +
 +}
 +
 +static OCEntityHandlerResult HandleCsrGetRequest(OCEntityHandlerRequest * ehRequest)
 +{
 +    OCStackResult res = OC_STACK_OK;
 +    OCEntityHandlerResult ehRet = OC_EH_OK;
 +    int ret = 0;
 +    mbedtls_pk_context keyPair;
 +    OicUuid_t myUuid;
 +    char *myUuidStr = NULL;
 +    char *myDNStr = NULL;
 +    size_t myDNStrLen = 0;
 +    ByteArray_t keyData = { .data = NULL, .len = 0 };
 +    OCByteString csr = { .bytes = NULL, .len = 0 };
 +    size_t size = 0;
 +    uint8_t *payload = NULL;
 +
 +    OIC_LOG(INFO, TAG, "HandleCsrGetRequest  processing GET request");
 +
 +    mbedtls_pk_init(&keyPair);
 +
 +    // Retrieve our current certificate, if we have one, and use that key
 +    GetDerKey(&keyData, PRIMARY_CERT);
 +
 +    if (0 == keyData.len)
 +    {
 +        // No cert? Get our primary key pair, or generate it if absent.
 +        GetDerKey(&keyData, PRIMARY_KEY);
 +    }
 +
 +    res = GetDoxmDeviceID(&myUuid);
 +    VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
 +    res = ConvertUuidToStr(&myUuid, &myUuidStr);
 +    VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
 +
 +    if (0 < keyData.len)
 +    {
 +        ret = mbedtls_pk_parse_key(&keyPair, keyData.data, keyData.len, NULL, 0);
 +        if (0 > ret)
 +        {
 +            res = OC_STACK_ERROR;
 +            // Because we need to set res before failing out, this is a redundant check of ret, but gives better logging.
 +            VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +        }
 +    }
 +    else
 +    {
 +        ret = OCInternalGenerateKeyPair(&keyPair);
 +        if (0 > ret)
 +        {
 +            res = OC_STACK_ERROR;
 +            VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +        }
 +        VERIFY_SUCCESS(TAG, OC_STACK_OK == (res = StoreKeyPair(&keyPair, &myUuid)), ERROR);
 +    }
 +
 +    // Generate CSR
 +    myDNStrLen = strlen(myUuidStr) + sizeof(SUBJECT_PREFIX); // sizeof(SUBJECT_PREFIX) will also count the byte for terminating null.
 +    myDNStr = (char *)OICMalloc(myDNStrLen);
 +    VERIFY_NOT_NULL(TAG, myDNStr, ERROR);
 +    ret = snprintf(myDNStr, myDNStrLen, SUBJECT_PREFIX "%s", myUuidStr);
 +    VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +    /* ret >= myDNStrLen means there was truncation; assert because this means a code bug. */
 +    assert((size_t)ret < myDNStrLen);
 +    ret = OCInternalCSRRequest(myDNStr, &keyPair, OIC_ENCODING_DER, &csr);
 +    if (0 > ret)
 +    {
 +        res = OC_STACK_ERROR;
 +        VERIFY_SUCCESS(TAG, 0 <= ret, ERROR);
 +    }
 +
 +    // Convert CSR data into CBOR for transmission
 +    res = CSRToCBORPayload(csr.bytes, csr.len, OIC_ENCODING_DER, &payload, &size);
 +
 +exit:
 +
 +    ehRet = (OC_STACK_OK == res) ? OC_EH_OK : OC_EH_ERROR;
 +
 +    //Send payload to request originator
 +    ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
 +                       OC_EH_OK : OC_EH_ERROR;
 +
 +    mbedtls_pk_free(&keyPair);
 +    OICFree(myDNStr);
 +    OICFree(myUuidStr);
 +    OICFree(keyData.data);
 +    OICFree(csr.bytes);
 +    OICFree(payload);
 +    return ehRet;
 +}
 +
 +static OCEntityHandlerResult CredCsrEntityHandler(OCEntityHandlerFlag flag,
 +                                                  OCEntityHandlerRequest * ehRequest,
 +                                                  void* callbackParameter)
 +{
 +    OC_UNUSED(callbackParameter);
 +    OCEntityHandlerResult ret = OC_EH_ERROR;
 +
 +    if (!ehRequest)
 +    {
 +        return OC_EH_ERROR;
 +    }
 +
 +    if (flag & OC_REQUEST_FLAG)
 +    {
 +        OIC_LOG(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
 +        if (ehRequest->method == OC_REST_GET)
 +        {
 +            ret = HandleCsrGetRequest(ehRequest);
 +        }
 +        else
 +        {
 +            /* Only GET supported on CSR resource. */
 +            ret = OC_EH_ERROR;
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +OCStackResult InitCSRResource()
 +{
 +    OCStackResult ret = OCCreateResource(&gCsrHandle,
 +        OIC_RSRC_TYPE_SEC_CSR,
 +        OC_RSRVD_INTERFACE_DEFAULT,
 +        OIC_RSRC_CSR_URI,
 +        CredCsrEntityHandler,
 +        NULL,
 +        OC_SECURE);
 +
 +    if (OC_STACK_OK != ret)
 +    {
 +        OIC_LOG(FATAL, TAG, "Unable to instantiate CSR resource");
 +    }
 +
 +    return ret;
 +}
 +
 +OCStackResult DeInitCSRResource()
 +{
 +    OCStackResult res = OCDeleteResource(gCsrHandle);
 +
 +    if (OC_STACK_OK != res)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "Failed to delete CSR resource: %d", res);
 +    }
 +
 +    gCsrHandle = NULL;
 +
 +    return res;
 +}
index 2ee9de4,0000000..4ced39a
mode 100644,000000..100644
--- /dev/null
@@@ -1,612 -1,0 +1,613 @@@
-     *publicKeyLen = strlen(buf) + 1;
 +/* *****************************************************************
 + *
 + * Copyright 2017 Microsoft. 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
 + *
 + *     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.
 + *
 + * *****************************************************************/
 +
 +#if defined(__WITH_TLS__) || defined(__WITH_DTLS__)
 +
 +#include "iotivity_config.h"
 +
 +#include "logger.h"
 +#include <stddef.h>
 +#include <string.h>
 +#include <assert.h>
 +#include "oic_malloc.h"
 +#include "oic_string.h"
 +#include "cacommon.h"
 +#include "ocrandom.h"
 +#include "cacommonutil.h"
 +
 +#include "ocpayload.h"
 +#include "payload_logging.h"
 +#include "pmutility.h"
 +#include "srmutility.h"
 +
 +// headers required for mbed TLS
 +#include "mbedtls/config.h"
 +#include "mbedtls/platform.h"
 +#include "mbedtls/entropy.h"
 +#include "mbedtls/ctr_drbg.h"
 +#include "mbedtls/x509_csr.h"
 +#include "mbedtls/x509_crt.h"
 +#include "mbedtls/oid.h"
 +
 +#ifndef NDEBUG
 +#include "mbedtls/debug.h"
 +#include "mbedtls/version.h"
 +#endif
 +
 +#ifdef HAVE_UNISTD_H
 +#include <unistd.h>
 +#endif
 +#include <fcntl.h>
 +
++#include "certhelpers.h"
 +#include "occertutility.h"
 +
 +#define TAG "OIC_OCCERTUTILITY"
 +
 +/**
 + * @def PERSONALIZATION_STRING
 + * @brief Personalization string for the mbedtls RNG
 + */
 +#define PERSONALIZATION_STRING "IOTIVITY_RND"
 +
 +#define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
 +
 +#define MAX_STRING_LEN 254
 +
 +/* ASN.1 DER encoding of the EKU for identity certificates (1.3.6.1.4.1.44924.1.6) */
 +static const unsigned char s_ekuIdentity[] = { 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x06 };
 +
 +/* ASN.1 DER encoding of the EKU for role certificates (1.3.6.1.4.1.44924.1.7) */
 +static const unsigned char s_ekuRole[] = { 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x07 };
 +
 +/* ASN.1 DER encoding of the EKU for both identity and roles (for use by CAs) */
 +static const unsigned char s_ekuCA[] = { 0x30, 0x18, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x06, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDE, 0x7C, 0x01, 0x07 };
 +
 +/**
 + * Generates elliptic curve keypair.
 + *
 + * @param[out]  pk    mbedtls public key container
 + *
 + * @return  0 on success or <0 on error
 + */
 +static int GenerateEccKeyPair(mbedtls_pk_context *pk)
 +{
 +    int ret = 0;
 +    mbedtls_entropy_context entropy;
 +    mbedtls_ctr_drbg_context ctr_drbg;
 +
 +    OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
 +    VERIFY_NON_NULL_RET(pk, TAG, "Param pk is NULL", -1);
 +
 +    // Initialize the DRBG context
 +    mbedtls_ctr_drbg_init(&ctr_drbg);
 +    mbedtls_entropy_init(&entropy);
 +    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
 +                                &entropy, (const unsigned char *)PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING));
 +
 +    if (0 > ret)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "Seed initialization failed! %d", ret);
 +        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 +        goto exit;
 +    }
 +    mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
 +    ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
 +    if (0 > ret)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "mbedtls_pk_setup error %d", ret);
 +        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 +        goto exit;
 +    }
 +    ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*pk), mbedtls_ctr_drbg_random, &ctr_drbg);
 +    if (0 > ret)
 +    {
 +        OIC_LOG(ERROR, TAG, "mbedtls_ecp_gen_keypair error");
 +        OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 +        goto exit;
 +    }
 +
 +exit:
 +
 +    mbedtls_ctr_drbg_free(&ctr_drbg);
 +    mbedtls_entropy_free(&entropy);
 +
 +    OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
 +    return 0;
 +}
 +
 +OCStackResult OCGenerateRandomSerialNumber(char **serial, size_t *serialLen)
 +{
 +    int ret = 0;
 +    OCStackResult res = OC_STACK_ERROR;
 +    unsigned char random[20]; /* Per RFC 5280, 20 octets is the maximum length of a serial number. */
 +    mbedtls_mpi serialMpi;
 +
 +    VERIFY_NOT_NULL_RETURN(TAG, serial, ERROR, OC_STACK_INVALID_PARAM);
 +    VERIFY_NOT_NULL_RETURN(TAG, serialLen, ERROR, OC_STACK_INVALID_PARAM);
 +
 +    mbedtls_mpi_init(&serialMpi);
 +    memset(serial, 0, sizeof(*serial));
 +
 +    VERIFY_SUCCESS(TAG, OCGetRandomBytes(random, sizeof(random)), ERROR);
 +
 +    /* Per RFC 5280, 20 octets is the maximum length of a serial number. In ASN.1, if the highest-order
 +     * bit is set it causes a padding octet to be written, which would be 21 and non-compliant. 
 +     * Therefore, always clear the highest-order bit. Integers in ASN.1 are always big-Endian.
 +     */
 +    random[0] &= 0x7F;
 +
 +    /* Import into a large integer object and then output as a string. */
 +    ret = mbedtls_mpi_read_binary(&serialMpi, random, sizeof(random));
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    /* Get the needed string length and allocate. */
 +    ret = mbedtls_mpi_write_string(&serialMpi, 10, NULL, 0, serialLen);
 +    VERIFY_SUCCESS(TAG, ret == MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL, ERROR);
 +    *serial = OICCalloc(1, *serialLen);
 +    VERIFY_NOT_NULL(TAG, *serial, ERROR);
 +
 +    /* Do the write for real. */
 +    ret = mbedtls_mpi_write_string(&serialMpi, 10, *serial, *serialLen, serialLen);
 +    VERIFY_SUCCESS(TAG, ret == 0, ERROR);
 +
 +    res = OC_STACK_OK;
 +
 +exit:
 +
 +    if (OC_STACK_OK != res)
 +    {
 +        OICFree(*serial);
 +        *serial = NULL;
 +        *serialLen = 0;
 +    }
 +    mbedtls_mpi_free(&serialMpi);
 +
 +    return res;
 +}
 +
 +OCStackResult OCGenerateKeyPair(char **publicKey, size_t *publicKeyLen,
 +                                char **privateKey, size_t *privateKeyLen)
 +{
 +    int ret = 0;
 +    mbedtls_pk_context keyPair;
 +    unsigned char buf[2048];
 +
 +    mbedtls_pk_init(&keyPair);
 +
 +    VERIFY_NOT_NULL_RETURN(TAG, publicKey, ERROR, OC_STACK_INVALID_PARAM);
 +    VERIFY_NOT_NULL_RETURN(TAG, publicKeyLen, ERROR, OC_STACK_INVALID_PARAM);
 +    VERIFY_NOT_NULL_RETURN(TAG, privateKey, ERROR, OC_STACK_INVALID_PARAM);
 +    VERIFY_NOT_NULL_RETURN(TAG, privateKeyLen, ERROR, OC_STACK_INVALID_PARAM);
 +
 +    *publicKey = NULL;
 +    *publicKeyLen = 0;
 +    *privateKey = NULL;
 +    *privateKeyLen = 0;
 +
 +    ret = OCInternalGenerateKeyPair(&keyPair);
 +    if (ret != 0)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "Failed to generate key pair: %d", ret);
 +        goto exit;
 +    }
 +
 +    ret = mbedtls_pk_write_pubkey_pem(&keyPair, buf, sizeof(buf));
 +    if (ret != 0)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "Failed to export public key as PEM: %d", ret);
 +        goto exit;
 +    }
 +
-     *privateKeyLen = strlen(buf) + 1;
++    *publicKeyLen = strlen((char *)buf) + 1;
 +    *publicKey = OICCalloc(1, *publicKeyLen);
 +    if (NULL == *publicKey)
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not allocate memory for public key");
 +        ret = -1;
 +        goto exit;
 +    }
 +    memcpy(*publicKey, buf, *publicKeyLen);
 +
 +    ret = mbedtls_pk_write_key_pem(&keyPair, buf, sizeof(buf));
 +    if (ret != 0)
 +    {
 +        OIC_LOG_V(ERROR, TAG, "Failed to export private key as PEM: %d", ret);
 +        goto exit;
 +    }
 +
-     ret = mbedtls_pk_parse_public_key(&subjKeyCtx, subjectPublicKey, strlen(subjectPublicKey) + 1);
++    *privateKeyLen = strlen((char *)buf) + 1;
 +    *privateKey = OICCalloc(1, *privateKeyLen);
 +    if (NULL == *privateKey)
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not allocate memory for private key");
 +        ret = -1;
 +        goto exit;
 +    }
 +    memcpy(*privateKey, buf, *privateKeyLen);
 +
 +exit:
 +
 +    mbedtls_pk_free(&keyPair);
 +
 +    OICClearMemory(buf, sizeof(buf));
 +
 +    if (ret != 0)
 +    {
 +        OICFree(*publicKey);
 +        OICClearMemory(*privateKey, *privateKeyLen);
 +        OICFree(*privateKey);
 +
 +        *publicKey = NULL;
 +        *publicKeyLen = 0;
 +        *privateKey = NULL;
 +        *privateKeyLen = 0;
 +
 +        return OC_STACK_ERROR;
 +    }
 +    else
 +    {
 +        return OC_STACK_OK;
 +    }
 +}
 +
 +typedef enum {
 +    CERT_TYPE_CA,
 +    CERT_TYPE_IDENTITY,
 +    CERT_TYPE_ROLE
 +} CertificateType_t;
 +
 +static OCStackResult GenerateCertificate(
 +    CertificateType_t certType,
 +    const char *subject,
 +    const char *subjectPublicKey,
 +    const char *issuerCert,
 +    const char *issuerPrivateKey,
 +    const char *serial,
 +    const char *notValidBefore,
 +    const char *notValidAfter,
 +    const char *role,
 +    const char *authority,
 +    OCByteString *certificate)
 +{
 +    OCStackResult res = OC_STACK_INVALID_PARAM;
 +    int ret = 0;
 +    mbedtls_x509write_cert outCertCtx;
 +    mbedtls_pk_context subjKeyCtx;
 +    mbedtls_pk_context issKeyCtx;
 +    mbedtls_x509_crt issCertCtx;
 +    mbedtls_mpi serialMpi;
 +    mbedtls_x509_general_names names;
 +    mbedtls_entropy_context entropy;
 +    mbedtls_ctr_drbg_context ctr_drbg;
 +
 +    char buf[2048];
 +
 +    if (NULL == subjectPublicKey || NULL == issuerPrivateKey || NULL == subject || NULL == serial ||
 +        NULL == notValidBefore || NULL == notValidAfter)
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    mbedtls_x509write_crt_init(&outCertCtx);
 +    mbedtls_pk_init(&subjKeyCtx);
 +    mbedtls_pk_init(&issKeyCtx);
 +    mbedtls_x509_crt_init(&issCertCtx);
 +    mbedtls_mpi_init(&serialMpi);
 +    memset(&names, 0, sizeof(names));
 +    mbedtls_ctr_drbg_init(&ctr_drbg);
 +    mbedtls_entropy_init(&entropy);
 +    memset(certificate, 0, sizeof(*certificate));
 +
 +    ret = mbedtls_mpi_read_string(&serialMpi, 10, serial);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
-     ret = mbedtls_pk_parse_key(&issKeyCtx, issuerPrivateKey, strlen(issuerPrivateKey) + 1, NULL, 0);
++    ret = mbedtls_pk_parse_public_key(&subjKeyCtx, (const uint8_t *)subjectPublicKey, strlen(subjectPublicKey) + 1);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
-         ret = mbedtls_x509_crt_parse(&issCertCtx, issuerCert, strlen(issuerCert) + 1);
++    ret = mbedtls_pk_parse_key(&issKeyCtx, (const uint8_t *)issuerPrivateKey, strlen(issuerPrivateKey) + 1, NULL, 0);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    /* If issuerCert is NULL, then the cert will be self-signed. */
 +    if (NULL != issuerCert)
 +    {
-         &entropy, PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING));
++        ret = mbedtls_x509_crt_parse(&issCertCtx, (const uint8_t *)issuerCert, strlen(issuerCert) + 1);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +    }
 +
 +    ret = mbedtls_x509write_crt_set_validity(&outCertCtx, notValidBefore, notValidAfter);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    mbedtls_x509write_crt_set_version(&outCertCtx, MBEDTLS_X509_CRT_VERSION_3);
 +    mbedtls_x509write_crt_set_md_alg(&outCertCtx, MBEDTLS_MD_SHA256);
 +
 +    res = OC_STACK_ERROR;
 +
 +    ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
-     ret = mbedtls_x509write_crt_pem(&outCertCtx, buf, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg);
++        &entropy, (const uint8_t *)PERSONALIZATION_STRING, sizeof(PERSONALIZATION_STRING));
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +    mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON);
 +
 +    ret = mbedtls_x509write_crt_set_serial(&outCertCtx, &serialMpi);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    ret = mbedtls_x509write_crt_set_subject_name(&outCertCtx, subject);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    if (NULL != issuerCert)
 +    {
 +        // mbedtls_x509_dn_gets returns the number of bytes written to buf.
 +        ret = mbedtls_x509_dn_gets(buf, sizeof(buf), &issCertCtx.subject);
 +        VERIFY_SUCCESS(TAG, 0 < ret, ERROR);
 +        ret = mbedtls_x509write_crt_set_issuer_name(&outCertCtx, buf);
 +    }
 +    else
 +    {
 +        /* If self-signed, use the same contents of subject for the issuer name. */
 +        ret = mbedtls_x509write_crt_set_issuer_name(&outCertCtx, subject);
 +    }
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    mbedtls_x509write_crt_set_subject_key(&outCertCtx, &subjKeyCtx);
 +
 +    mbedtls_x509write_crt_set_issuer_key(&outCertCtx, &issKeyCtx);
 +
 +    if (certType == CERT_TYPE_CA)
 +    {
 +        ret = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, 1, -1);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        ret = mbedtls_x509write_crt_set_key_usage(&outCertCtx, 
 +            MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +    }
 +    else
 +    {
 +        ret = mbedtls_x509write_crt_set_basic_constraints(&outCertCtx, 0, 0);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        ret = mbedtls_x509write_crt_set_key_usage(&outCertCtx,
 +            MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
 +            MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
 +            MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
 +            MBEDTLS_X509_KU_KEY_AGREEMENT);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +    }
 +    
 +    switch (certType)
 +    {
 +    case CERT_TYPE_ROLE:
 +        ret = mbedtls_x509write_crt_set_extension(&outCertCtx,
 +            MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
 +            0,
 +            s_ekuRole, sizeof(s_ekuRole));
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        ret = snprintf(buf, sizeof(buf), "CN=%s%s%s", role, (NULL != authority) ? ",OU=" : "", (NULL != authority) ? authority : "");
 +        VERIFY_SUCCESS(TAG, ret < sizeof(buf), ERROR);
 +        names.next = NULL;
 +        names.general_name.name_type = MBEDTLS_X509_GENERALNAME_DIRECTORYNAME;
 +        ret = mbedtls_x509_string_to_names(&names.general_name.directory_name, buf);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +        ret = mbedtls_x509write_crt_set_subject_alt_names(&outCertCtx, &names);
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        break;
 +
 +    case CERT_TYPE_IDENTITY:
 +        ret = mbedtls_x509write_crt_set_extension(&outCertCtx,
 +            MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
 +            0,
 +            s_ekuIdentity, sizeof(s_ekuIdentity));
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        break;
 +
 +    case CERT_TYPE_CA:
 +        ret = mbedtls_x509write_crt_set_extension(&outCertCtx,
 +            MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
 +            0,
 +            s_ekuCA, sizeof(s_ekuCA));
 +        VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +        break;
 +
 +    default:
 +        assert(false);
 +        VERIFY_SUCCESS(TAG, false, ERROR);
 +    }
 +
-         *certificate = byteStr.bytes;
++    ret = mbedtls_x509write_crt_pem(&outCertCtx, (uint8_t *)buf, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg);
 +    VERIFY_SUCCESS(TAG, 0 == ret, ERROR);
 +
 +    certificate->len = strlen(buf) + 1;
 +    certificate->bytes = (uint8_t *)OICCalloc(1, certificate->len);
 +    VERIFY_NOT_NULL(TAG, certificate->bytes, ERROR);
 +    memcpy(certificate->bytes, buf, certificate->len);
 +
 +    res = OC_STACK_OK;
 +
 +exit:
 +
 +    if (OC_STACK_OK != res)
 +    {
 +        OICFree(certificate->bytes);
 +        certificate->bytes = NULL;
 +        certificate->len = 0;
 +    }
 +
 +    mbedtls_ctr_drbg_free(&ctr_drbg);
 +    mbedtls_entropy_free(&entropy);
 +    mbedtls_asn1_free_named_data_list(&names.general_name.directory_name);
 +    mbedtls_mpi_free(&serialMpi);
 +    mbedtls_x509_crt_free(&issCertCtx);
 +    mbedtls_pk_free(&issKeyCtx);
 +    mbedtls_pk_free(&subjKeyCtx);
 +    mbedtls_x509write_crt_free(&outCertCtx);
 +
 +    return res;
 +}
 +
 +OCStackResult OCGenerateCACertificate(
 +    const char *subject,
 +    const char *subjectPublicKey,
 +    const char *issuerCert,
 +    const char *issuerPrivateKey,
 +    const char *serial,
 +    const char *notValidBefore,
 +    const char *notValidAfter,
 +    char **certificate,
 +    size_t *certificateLen)
 +{
 +    OCStackResult res = OC_STACK_OK;
 +    OCByteString byteStr = { 0 };
 +    
 +    res = GenerateCertificate(
 +        CERT_TYPE_CA,
 +        subject,
 +        subjectPublicKey,
 +        issuerCert,
 +        issuerPrivateKey,
 +        serial,
 +        notValidBefore,
 +        notValidAfter,
 +        NULL,
 +        NULL,
 +        &byteStr);
 +
 +    if (OC_STACK_OK == res)
 +    {
-         *certificate = byteStr.bytes;
++        *certificate = (char *)byteStr.bytes;
 +        *certificateLen = byteStr.len;
 +    }
 +
 +    return res;
 +}
 +
 +OCStackResult OCGenerateIdentityCertificate(
 +    const OicUuid_t *subjectUuid,
 +    const char *subjectPublicKey,
 +    const char *issuerCert,
 +    const char *issuerPrivateKey,
 +    const char *serial,
 +    const char *notValidBefore,
 +    const char *notValidAfter,
 +    char **certificate,
 +    size_t *certificateLen)
 +{
 +    OCStackResult res = OC_STACK_OK;
 +    OCByteString byteStr = { 0 };
 +    char uuidStr[UUID_STRING_SIZE] = { 0 } ;
 +    char subject[sizeof(uuidStr) + sizeof(SUBJECT_PREFIX)] = { 0 } ;
 +
 +    if (NULL == issuerCert)
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    if (!OCConvertUuidToString(subjectUuid->id, uuidStr))
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not convert UUID");
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    if (snprintf(subject, sizeof(subject), "%s%s", SUBJECT_PREFIX, uuidStr) == sizeof(subject))
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not write subject string");
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    res = GenerateCertificate(
 +        CERT_TYPE_IDENTITY,
 +        subject,
 +        subjectPublicKey,
 +        issuerCert,
 +        issuerPrivateKey,
 +        serial,
 +        notValidBefore,
 +        notValidAfter,
 +        NULL,
 +        NULL,
 +        &byteStr);
 +
 +    if (OC_STACK_OK == res)
 +    {
-         *certificate = byteStr.bytes;
++        *certificate = (char *)byteStr.bytes;
 +        *certificateLen = byteStr.len;
 +    }
 +
 +    return res;
 +}
 +
 +OCStackResult OCGenerateRoleCertificate(
 +    const OicUuid_t *subjectUuid,
 +    const char *subjectPublicKey,
 +    const char *issuerCert,
 +    const char *issuerPrivateKey,
 +    const char *serial,
 +    const char *notValidBefore,
 +    const char *notValidAfter,
 +    const char *role,
 +    const char *authority,
 +    char **certificate,
 +    size_t *certificateLen)
 +{
 +    OCStackResult res = OC_STACK_ERROR;
 +    OCByteString byteStr;
 +    char uuidStr[UUID_STRING_SIZE] = { 0 };
 +    char subject[sizeof(uuidStr) + sizeof(SUBJECT_PREFIX)] = { 0 };
 +
 +    memset(&byteStr, 0, sizeof(byteStr));
 +
 +    if (NULL == role || NULL == issuerCert)
 +    {
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    if (!OCConvertUuidToString(subjectUuid->id, uuidStr))
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not convert UUID");
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    if (snprintf(subject, sizeof(subject), "%s%s", SUBJECT_PREFIX, uuidStr) == sizeof(subject))
 +    {
 +        OIC_LOG(ERROR, TAG, "Could not write subject string");
 +        return OC_STACK_INVALID_PARAM;
 +    }
 +
 +    res = GenerateCertificate(
 +        CERT_TYPE_ROLE,
 +        subject,
 +        subjectPublicKey,
 +        issuerCert,
 +        issuerPrivateKey,
 +        serial,
 +        notValidBefore,
 +        notValidAfter,
 +        role,
 +        authority,
 +        &byteStr);
 +
 +    if (OC_STACK_OK == res)
 +    {
++        *certificate = (char *)byteStr.bytes;
 +        *certificateLen = byteStr.len;
 +    }
 +
 +    return res;
 +}
 +
 +#endif /* defined(__WITH_TLS__) || defined(__WITH_DTLS__) */