Merge branch 'security-CKM' into 'master'
authorSachin Agrawal <sachin.agrawal@intel.com>
Mon, 28 Sep 2015 16:38:19 +0000 (09:38 -0700)
committerSachin Agrawal <sachin.agrawal@intel.com>
Mon, 28 Sep 2015 20:23:29 +0000 (20:23 +0000)
* security-CKM:
  Removed automatic switching to X.509 in CA
  implement unit tests for CK manager
  Add sample of PKIX provisioning

Conflicts:
resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c

Change-Id: If1e8367e3729b152602d1585bc433f083354c5e1
Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/3233
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
14 files changed:
resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp [new file with mode: 0755]
resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp [new file with mode: 0755]
resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json [new file with mode: 0755]
resource/csdk/security/provisioning/ck_manager/sample/README.txt [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/pki_test.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/01.der [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/CKMInfo.json [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/cacert.der [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/capub.der [new file with mode: 0644]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/cert_chain.dat [new file with mode: 0755]
resource/csdk/security/provisioning/ck_manager/unittest/test_data/chain.der [new file with mode: 0644]

diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp
new file mode 100755 (executable)
index 0000000..c4db6bc
--- /dev/null
@@ -0,0 +1,574 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "global.h"
+#include "cainterface.h"
+#include "cacommon.h"
+#include "ocstackinternal.h"
+#include "payload_logging.h"
+#include "ocpayload.h"
+
+
+#define TAG "DEMO"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define STATE "state"
+#define OPEN_DURATION "openDuration"
+#define OPEN_ALARM "openAlarm"
+
+static const char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
+
+volatile sig_atomic_t gQuitFlag = 0;
+OCPersistentStorage ps = {0, 0, 0, 0, 0};
+static const char *gResourceUri = "/a/door";
+uint8_t lightIpAddr[4] = {};
+uint16_t lightPortNu;
+static bool isUpdated = false;
+static std::string coapServerIP;
+static std::string coapServerPort;
+static std::string coapServerResource;
+static OCConnectivityType ocConnType;
+
+static std::string address;
+
+static int coapSecureResource;
+
+static const char CRED_FILE[] = "oic_svr_db_door.json";
+
+CAEndpoint_t endpoint = {CA_DEFAULT_ADAPTER, CA_DEFAULT_FLAGS, 0, {0}, 0};
+
+// myDoorState_t variable to store resource's state .
+typedef enum
+{
+    STATE_OPEN,    /**< State is opened */
+    STATE_CLOSED        /**< State is closed*/
+} myDoorState_t;
+
+//Structure to represent a door resource  and its attributes
+typedef struct DOORRESOURCE
+{
+    OCResourceHandle handle;
+    myDoorState_t state; //ReadOnly, The state of the door (open or closed)"
+    char *openDuration;  //ReadOnly, The time duration the door has been open
+    bool openAlarm ; //The state of the door open alarm
+
+} DoorResource;
+
+static DoorResource Door;
+
+int parseClientResponse(OCClientResponse * clientResponse)
+{
+    if(!clientResponse)
+    {
+        return 0;
+    }
+
+    OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+    // Initialize all global variables
+    coapServerResource.clear();
+    coapSecureResource = 0;
+
+    while (res)
+    {
+        coapServerResource.assign(res->uri);
+        OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
+
+        if (res->secure)
+        {
+            endpoint.port = res->port;
+            coapSecureResource = 1;
+        }
+
+        OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
+
+        // If we discovered a secure resource, exit from here
+        if (coapSecureResource)
+        {
+            break;
+        }
+
+        res = res->next;
+    }
+
+    return 0;
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t state, char* openDuration, bool openAlarm)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropInt(payload, STATE, state);
+    OCRepPayloadSetPropString(payload, OPEN_DURATION, openDuration);
+    OCRepPayloadSetPropBool(payload, OPEN_ALARM, openAlarm);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return nullptr;
+    }
+
+    DoorResource *currdoorResource = &Door;
+
+    return getPayload(gResourceUri, currdoorResource->state, currdoorResource->openDuration, currdoorResource->openAlarm);
+}
+
+OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest *entityHandlerRequest,
+                                        void* /*callbackParam*/)
+{
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = nullptr;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+
+        if (entityHandlerRequest)
+        {
+            switch(entityHandlerRequest->method)
+            {
+            case OC_REST_GET:
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            break;
+            default:
+            {
+                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+            break;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = reinterpret_cast<OCPayload*>(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE *server_fopen(const char * /*path*/, const char *mode)
+{
+    return fopen(CRED_FILE, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+{
+    if (ps)
+    {
+        ps->open =  server_fopen;
+        ps->read = fread;
+        ps->write = fwrite;
+        ps->close = fclose;
+        ps->unlink = unlink;
+
+        OCRegisterPersistentStorageHandler(ps);
+    }
+}
+
+/**
+ * GetResult is returned result to string.
+ * @param   result             [IN] stack result
+ * @return  converted OCStackResult as string for debugging
+ */
+static const char *getResult(OCStackResult result)
+{
+    switch (result)
+    {
+        case OC_STACK_OK:
+            return "OC_STACK_OK";
+        case OC_STACK_RESOURCE_CREATED:
+            return "OC_STACK_RESOURCE_CREATED";
+        case OC_STACK_RESOURCE_DELETED:
+            return "OC_STACK_RESOURCE_DELETED";
+        case OC_STACK_INVALID_URI:
+            return "OC_STACK_INVALID_URI";
+        case OC_STACK_INVALID_QUERY:
+            return "OC_STACK_INVALID_QUERY";
+        case OC_STACK_INVALID_IP:
+            return "OC_STACK_INVALID_IP";
+        case OC_STACK_INVALID_PORT:
+            return "OC_STACK_INVALID_PORT";
+        case OC_STACK_INVALID_CALLBACK:
+            return "OC_STACK_INVALID_CALLBACK";
+        case OC_STACK_INVALID_METHOD:
+            return "OC_STACK_INVALID_METHOD";
+        case OC_STACK_NO_MEMORY:
+            return "OC_STACK_NO_MEMORY";
+        case OC_STACK_COMM_ERROR:
+            return "OC_STACK_COMM_ERROR";
+        case OC_STACK_INVALID_PARAM:
+            return "OC_STACK_INVALID_PARAM";
+        case OC_STACK_NOTIMPL:
+            return "OC_STACK_NOTIMPL";
+        case OC_STACK_NO_RESOURCE:
+            return "OC_STACK_NO_RESOURCE";
+        case OC_STACK_RESOURCE_ERROR:
+            return "OC_STACK_RESOURCE_ERROR";
+        case OC_STACK_SLOW_RESOURCE:
+            return "OC_STACK_SLOW_RESOURCE";
+        case OC_STACK_NO_OBSERVERS:
+            return "OC_STACK_NO_OBSERVERS";
+    case OC_STACK_UNAUTHORIZED_REQ:
+        return "OC_STACK_UNAUTHORIZED_REQ";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    #endif
+        case OC_STACK_ERROR:
+            return "OC_STACK_ERROR";
+        default:
+            return "UNKNOWN";
+    }
+}
+
+
+/**
+ * CreateDoorResource creates a new door resource by calling the OCCreateResource() method.
+ * @param   uri                   [IN] uri
+ * @param   doorResource          [IN] info of resource
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+int  createDoorResource (const char *uri, DoorResource *doorResource)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+
+    }
+
+    doorResource->state = STATE_CLOSED; //1:closed , 0: open
+    char str[] = "10min";
+    doorResource->openDuration = str;
+    doorResource->openAlarm = false;
+    OCStackResult res = OCCreateResource(&(doorResource->handle),
+                                         "core.door",
+                                         OC_RSRVD_INTERFACE_DEFAULT,
+                                         uri,
+                                         OCEntityHandlerCb,
+                                         NULL,
+                                         OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+
+    OC_LOG_V(INFO, TAG, "Created Door resource with result: %s", getResult(res));
+    return 0;
+}
+
+OCStackApplicationResult putReqCB(void * ctx, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+    if (ctx == (void *)DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
+    }
+
+    if (clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        if ((OCSecurityPayload*)clientResponse->payload)
+        {
+            OC_LOG_V(INFO, TAG, "=============> Put Response",
+                    ((OCSecurityPayload*)clientResponse->payload)->securityData);
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult getReqCB(void * /*ctx*/, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+    OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+
+    if (clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+        if ((OCSecurityPayload*)clientResponse->payload)
+        {
+            OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* /*ctx*/, OCDoHandle /*handle*/,
+        OCClientResponse * clientResponse)
+{
+    OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+
+    if (clientResponse)
+    {
+        OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+        OC_LOG_V(INFO, TAG,
+                "Device =============> Discovered @ %s:%d",
+                clientResponse->devAddr.addr,
+                clientResponse->devAddr.port);
+
+        if (clientResponse->result == OC_STACK_OK)
+        {
+            OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+            ocConnType = clientResponse->connType;
+            parseClientResponse(clientResponse);
+        }
+    }
+
+    return OC_STACK_KEEP_TRANSACTION;
+
+}
+
+
+
+void initAddress()
+{
+    static bool initFlag = false;
+    if (!initFlag)
+    {
+        OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+        OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+        OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+        std::cin >> address;
+    }
+    initFlag = true;
+}
+
+// Local function to send get request of light resource
+void SendGetRequest()
+{
+    OCStackResult ret;
+    OC_LOG(INFO, TAG, "Send Get REQ to Light server");
+
+    initAddress();
+
+    char szQueryUri[64] = { '\0'};
+    OCDoHandle handle;
+    OCCallbackData cbData;
+    cbData.cb = getReqCB;
+    cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+    OC_LOG_V(INFO, TAG, "Get payload from Door sample = /a/light ");
+    snprintf(szQueryUri,  sizeof(szQueryUri), "coaps://%s/a/light", const_cast<char*> (address.c_str())); // lightPortNu);
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, NULL, ocConnType, OC_LOW_QOS,
+                 &cbData, NULL, 0);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+}
+
+
+void *input_function(void * /*data*/)
+{
+    char input;
+    char szQueryUri[64] = { 0 };
+    OCDoHandle handle;
+    OCCallbackData cbData;
+    cbData.cb = discoveryReqCB;
+    cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+
+    strcpy(szQueryUri, MULTICAST_DISCOVERY_QUERY);
+
+    while (1)
+    {
+        std::cin >> input;
+        switch (input)
+        {
+            case 'D':
+            case 'd':
+                if (isUpdated == false)
+                {
+                    OC_LOG(INFO, TAG, "isUpdated is false...");
+                    OCDoResource(&handle, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+
+                }
+                break;
+            case 'G':
+            case 'g':
+                isUpdated = true;
+                if (isUpdated == true)
+                {
+                    OC_LOG(INFO, TAG, "isUpdated is true...");
+                    SendGetRequest();
+                }
+                break;
+            case 'Q':
+            case 'q':
+                gQuitFlag = 1;
+                   return 0;
+            default: break;
+        }
+    }
+    return 0;
+}
+
+static void PrintUsage()
+{
+    OC_LOG(INFO, TAG, "*******************************************");
+    OC_LOG(INFO, TAG, "Input D or d to discover Resources");
+    OC_LOG(INFO, TAG, "Input G or g to initiate Get Request");
+    OC_LOG(INFO, TAG, "Input Q or q to exit");
+    OC_LOG(INFO, TAG, "*******************************************");
+}
+
+int main()
+{
+
+    OC_LOG(INFO, TAG, "OCServer is starting...");
+    SetPersistentHandler(&ps);
+    //PrintUsage();
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: Door
+     */
+    createDoorResource(gResourceUri, &Door);
+    PrintUsage();
+
+    //select ciphersuite for certificates
+    CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+
+    struct timespec timeout;
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    int thr_id;
+    pthread_t p_thread;
+    thr_id = pthread_create(&p_thread, NULL, input_function, (void *)NULL);
+    if (thr_id < 0)
+    {
+        OC_LOG(ERROR, TAG, "create thread error");
+        return 0;
+    }
+
+    while (!gQuitFlag)
+    {
+
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+
+
+        nanosleep(&timeout, NULL);
+    }
+
+    pthread_join(p_thread, NULL);
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json
new file mode 100644 (file)
index 0000000..21aa0e7
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "ZG9vckRldmljZVVVSUQwMA=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/crl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "ZG9vckRldmljZVVVSUQwMA=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "ZG9vckRldmljZVVVSUQwMA==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "ZG9vckRldmljZVVVSUQwMA=="
+       }
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp
new file mode 100755 (executable)
index 0000000..9a3f82e
--- /dev/null
@@ -0,0 +1,334 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <iostream>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "global.h"
+#include "cainterface.h"
+#include "cacommon.h"
+#include "ocpayload.h"
+
+#define TAG "DEMO"
+
+volatile sig_atomic_t gQuitFlag = 0;
+OCPersistentStorage ps = {0, 0, 0, 0, 0};
+const char *gResourceUri = (char *)"/a/light";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_light.json";
+
+
+//Structure to represent a light resource  and its attributes
+typedef struct LIGHTRESOURCE
+{
+    OCResourceHandle handle;
+    //Attributes
+    int brightness;   // 0-100
+} LightResource;
+
+// Structure to represent a light resource  and its attributes
+static LightResource Light;
+
+OCRepPayload* getPayload(const char* uri, int64_t brightness)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropInt(payload, "brightness", brightness);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
+{
+    if(!ehRequest)
+    {
+        return nullptr;
+    }
+
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return nullptr;
+    }
+
+    return getPayload(gResourceUri, Light.brightness);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp && payload)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+
+    return ehResult;
+}
+
+
+OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
+                                         OCEntityHandlerRequest *entityHandlerRequest,
+                                         void* /*callbackParam*/)
+{
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response;
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = nullptr;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            switch(entityHandlerRequest->method)
+            {
+            case OC_REST_GET:
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            break;
+            default:
+            {
+                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+            break;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = reinterpret_cast<OCPayload*>(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* server_fopen(const char * /*path*/, const char *mode)
+{
+    return fopen(CRED_FILE, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+
+{
+
+    if (ps)
+
+    {
+
+        ps->open =  server_fopen;
+
+        ps->read = fread;
+
+        ps->write = fwrite;
+
+        ps->close = fclose;
+
+        ps->unlink = unlink;
+
+
+        OCRegisterPersistentStorageHandler(ps);
+
+    }
+
+}
+/**
+ * GetResult is returned result to string.
+ * @param   result             [IN] stack result
+ * @return  converted OCStackResult as string for debugging
+ */
+static const char *getResult(OCStackResult result)
+{
+    switch (result)
+    {
+        case OC_STACK_OK:
+            return "OC_STACK_OK";
+        case OC_STACK_RESOURCE_CREATED:
+            return "OC_STACK_RESOURCE_CREATED";
+        case OC_STACK_RESOURCE_DELETED:
+            return "OC_STACK_RESOURCE_DELETED";
+        case OC_STACK_INVALID_URI:
+            return "OC_STACK_INVALID_URI";
+        case OC_STACK_INVALID_QUERY:
+            return "OC_STACK_INVALID_QUERY";
+        case OC_STACK_INVALID_IP:
+            return "OC_STACK_INVALID_IP";
+        case OC_STACK_INVALID_PORT:
+            return "OC_STACK_INVALID_PORT";
+        case OC_STACK_INVALID_CALLBACK:
+            return "OC_STACK_INVALID_CALLBACK";
+        case OC_STACK_INVALID_METHOD:
+            return "OC_STACK_INVALID_METHOD";
+        case OC_STACK_NO_MEMORY:
+            return "OC_STACK_NO_MEMORY";
+        case OC_STACK_COMM_ERROR:
+            return "OC_STACK_COMM_ERROR";
+        case OC_STACK_INVALID_PARAM:
+            return "OC_STACK_INVALID_PARAM";
+        case OC_STACK_NOTIMPL:
+            return "OC_STACK_NOTIMPL";
+        case OC_STACK_NO_RESOURCE:
+            return "OC_STACK_NO_RESOURCE";
+        case OC_STACK_RESOURCE_ERROR:
+            return "OC_STACK_RESOURCE_ERROR";
+        case OC_STACK_SLOW_RESOURCE:
+            return "OC_STACK_SLOW_RESOURCE";
+        case OC_STACK_NO_OBSERVERS:
+            return "OC_STACK_NO_OBSERVERS";
+        case OC_STACK_ERROR:
+            return "OC_STACK_ERROR";
+        default:
+            return "UNKNOWN";
+    }
+}
+
+/**
+ * CreateLightResource creates a new light resource by calling the OCCreateResource() method.
+ * @param   uri                    [IN] uri
+ * @param   lightResource          [IN] info of resource
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+int createLightResource (const char *uri, LightResource *lightResource)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+
+    }
+
+    lightResource->brightness = 0;
+    OCStackResult res = OCCreateResource(&(lightResource->handle),
+                                         "core.light",
+                                         OC_RSRVD_INTERFACE_DEFAULT,
+                                         uri,
+                                         OCEntityHandlerCb,
+                                         NULL,
+                                         OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+
+    OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
+    return 0;
+}
+
+
+int main()
+{
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+    SetPersistentHandler(&ps);
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: Light
+     */
+    createLightResource(gResourceUri, &Light);
+
+    CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+
+    struct timespec timeout;
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+
+        nanosleep(&timeout, NULL);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json
new file mode 100755 (executable)
index 0000000..d10b71e
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "bGlnaHREZXZpY2VVVUlEMA=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/crl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "bGlnaHREZXZpY2VVVUlEMA=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "bGlnaHREZXZpY2VVVUlEMA==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "bGlnaHREZXZpY2VVVUlEMA=="
+       }
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/README.txt b/resource/csdk/security/provisioning/ck_manager/sample/README.txt
new file mode 100644 (file)
index 0000000..5338d76
--- /dev/null
@@ -0,0 +1,132 @@
+# Open three terminal windows in linux
+# The first one use for start Light server
+# Note: Here and below $PROJ_DIR is root directory of iotivity project (e.g /path/to/iotivity)
+$ cd $PROJ_DIR/out/linux/x86_64/release/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/*.json ./
+$ ./Light_server
+
+# Second terminal window use for start Door server
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/*.json ./
+$ ./Door_server
+
+# And third terminal window use for start provisioning_client
+# provisioning_client ask for input ACL data:
+# 1. Controller device. Enter ID of the doorDeviceUUID00
+# 2. Controlee device. Enter ID of the lightDeviceUUID0
+# 3. Subject : doorDeviceUUID00
+# 4. Num. of Resource : 1
+# 5. [1]Resource : /a/light
+# 6. permissions: CRUDN
+# 7. Num. of Rowner : 1
+# 8. [1]Rowner : lightDeviceUUID0
+#
+# After successfull sending acl provisioning_client will ask you for CRL data:
+# 1. Enter number of revoced certificates(1..9): 1
+# 2. Revoced certificate 0: Serial number (E. g.: 100): 3
+# And then you should see message about successfull sending CRL
+#
+# Note: provisioning_client send ACL and CRL only to Light sever
+
+$ cd $PROJ_DIR/out/linux/x86_64/release/resource/csdk/security/provisioning/ck_manager/sample
+$ rm ckminfo.dat
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json ./
+$ ./provisioningclient
+Provisioning device ID : doorDeviceUUID00
+Provisioning Success~!!
+Provisioning device ID : lightDeviceUUID0
+Provisioning Success~!!
+Sending credential is succeed~!!
+******************************************************************************
+-Set ACL policy for target device
+******************************************************************************
+-URN identifying the subject
+ex) doorDeviceUUID00 (16 Numbers except to '-')
+Subject : doorDeviceUUID00
+Num. of Resource : 1
+-URI of resource
+ex) /a/light (Max_URI_Length: 64 Byte )
+[1]Resource : /a/light
+-Set the permission(C,R,U,D,N)
+ex) CRUDN, CRU_N,..(5 Charaters)
+Permission : CRUDN
+Num. of Rowner : 1
+-URN identifying the rowner
+ex) lightDeviceUUID0 (16 Numbers except to '-')
+[1]Rowner : lightDeviceUUID0
+Sending ACL is succeed~!!
+Enter number of revoced certificates (1..9)
+1
+Revoked certificate 0:
+Serial number (E. g.: 100):
+2
+Sending CRL is succeed~!!
+
+# Change window to terminal where Door server is running
+# Enter 'd' for  discovery. You should see output like this:
+21:56.283 INFO: DEMO: isUpdated is false...
+21:56.495 INFO: DEMO: Callback Context for DISCOVER query recvd successfully
+21:56.495 INFO: DEMO: StackResult: OC_STACK_OK
+21:56.495 INFO: DEMO: Device =============> Discovered @ 10.0.2.15:37942
+21:56.495 INFO: DEMO: Payload Type: Discovery
+21:56.495 INFO: DEMO:  Resource #1
+21:56.495 INFO: DEMO:  URI:/a/light
+21:56.495 INFO: DEMO:  SID:
+21:56.495 INFO: DEMO: F0 5A 6C 8B 59 66 48 89 BE 1E 4E EF FA 23 4E FD
+21:56.495 INFO: DEMO:  Resource Types:
+21:56.495 INFO: DEMO:          core.light
+21:56.495 INFO: DEMO:  Interfaces:
+21:56.495 INFO: DEMO:          oic.if.baseline
+21:56.495 INFO: DEMO:  Bitmap: 3
+21:56.495 INFO: DEMO:  Secure?: true
+21:56.495 INFO: DEMO:  Port: 43910
+21:56.495 INFO: DEMO:
+21:56.495 INFO: DEMO: Uri -- /a/light
+21:56.495 INFO: DEMO: Secure -- YES
+21:56.591 INFO: DEMO: Callback Context for DISCOVER query recvd successfully
+21:56.591 INFO: DEMO: StackResult: OC_STACK_OK
+21:56.591 INFO: DEMO: Device =============> Discovered @ 10.0.2.15:55808
+21:56.591 INFO: DEMO: Payload Type: Discovery
+21:56.591 INFO: DEMO:  Resource #1
+21:56.591 INFO: DEMO:  URI:/a/door
+21:56.591 INFO: DEMO:  SID:
+21:56.591 INFO: DEMO: E9 68 45 ED 5D E1 4A F3 86 31 FD 0E 5E 25 EB B3
+21:56.591 INFO: DEMO:  Resource Types:
+21:56.591 INFO: DEMO:          core.door
+21:56.591 INFO: DEMO:  Interfaces:
+21:56.591 INFO: DEMO:          oic.if.baseline
+21:56.591 INFO: DEMO:  Bitmap: 3
+21:56.591 INFO: DEMO:  Secure?: true
+21:56.591 INFO: DEMO:  Port: 41403
+21:56.591 INFO: DEMO:
+21:56.591 INFO: DEMO: Uri -- /a/door
+21:56.591 INFO: DEMO: Secure -- YES
+
+# If you can see /a/light discowered then this is success.
+# Next you should enter g to start get request
+# Enter address : 10.0.2.15:43910
+# Port you can find here
+21:56.495 INFO: DEMO:  URI:/a/light
+21:56.495 INFO: DEMO:  SID:
+21:56.495 INFO: DEMO: F0 5A 6C 8B 59 66 48 89 BE 1E 4E EF FA 23 4E FD
+21:56.495 INFO: DEMO:  Resource Types:
+21:56.495 INFO: DEMO:          core.light
+21:56.495 INFO: DEMO:  Interfaces:
+21:56.495 INFO: DEMO:          oic.if.baseline
+21:56.495 INFO: DEMO:  Bitmap: 3
+21:56.495 INFO: DEMO:  Secure?: true
+21:56.495 INFO: DEMO:  Port: 43910
+
+# If you see this lines in output:
+22:31.647 INFO: DEMO: Callback Context for GET query recvd successfully
+22:31.647 INFO: DEMO: StackResult: OC_STACK_OK
+22:31.647 INFO: DEMO: SEQUENCE NUMBER: 2
+22:31.647 INFO: DEMO: Payload Type: Representation
+22:31.647 INFO: DEMO:  Resource #1
+22:31.647 INFO: DEMO:  URI:/a/light
+22:31.647 INFO: DEMO:  Resource Types:
+22:31.647 INFO: DEMO:  Interfaces:
+22:31.647 INFO: DEMO:  Values:
+22:31.647 INFO: DEMO:          brightness(int):0
+22:31.647 INFO: DEMO: =============> Get Response
+# then certificate did not rejected with CRL
+# if not then it did.
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json b/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json
new file mode 100644 (file)
index 0000000..49fb2a8
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 7,
+             "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+       }
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c b/resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c
new file mode 100644 (file)
index 0000000..466cfe9
--- /dev/null
@@ -0,0 +1,701 @@
+/******************************************************************
+*
+* 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
+*
+*      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 <unistd.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "utlist.h"
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "oxmjustworks.h"
+#include "oic_string.h"
+#include "securevirtualresourcetypes.h"
+#include "cacommon.h"
+#include "ck_manager.h"
+#include "ckm_info.h"
+#include "crlresource.h"
+
+#define MAX_URI_LENGTH (64)
+#define MAX_PERMISSION_LENGTH (5)
+#define CREATE (1)
+#define READ (2)
+#define UPDATE (4)
+#define DELETE (8)
+#define NOTIFY (16)
+#define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
+#define DATE_LENGTH      (14)
+#define TAG  "provisioningclient"
+
+static OicSecAcl_t        *gAcl = NULL;
+static OicSecCrl_t        *gCrl = NULL;
+static char PROV_TOOL_DB_FILE[] = "oic_svr_db_pt.json";
+static int gOwnershipState = 0;
+
+typedef enum
+{
+    ownershipDone = 1 << 1,
+    finalizeDone = 1 << 2,
+    provisionAclDone = 1 << 3,
+    provisionCert1Done = 1 << 4,
+    provisionCert2Done = 1 << 5,
+    provisionCrlDone = 1 << 6
+} StateManager;
+
+
+/**
+ * Perform cleanup for ACL
+ * @param[in]    ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+    if (acl)
+    {
+        /* Clean Resources */
+        for (size_t i = 0; i < (acl)->resourcesLen; i++)
+        {
+            OICFree((acl)->resources[i]);
+        }
+        OICFree((acl)->resources);
+
+        /* Clean Owners */
+        OICFree((acl)->owners);
+
+        /* Clean ACL node itself */
+        OICFree((acl));
+
+        acl = NULL;
+    }
+}
+
+void deleteCrl(OicSecCrl_t *crl)
+{
+    if (crl)
+    {
+        //Clean ThisUpdate
+        OICFree(crl->ThisUpdate.data);
+
+        //clean CrlData
+        OICFree(crl->CrlData.data);
+
+        //Clean crl itself
+        OICFree(crl);
+    }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm    Input data of ACL permission string
+ * @param[in,out] pms    The pointer of ACL permission value
+ * @return  0 on success otherwise -1.
+ */
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+    int i = 0;
+
+    if (NULL == temp_pms || NULL == pms)
+    {
+        return -1;
+    }
+    *pms = 0;
+    while (temp_pms[i] != '\0')
+    {
+        switch (temp_pms[i])
+        {
+            case 'C':
+                {
+                    *pms += CREATE;
+                    i++;
+                    break;
+                }
+            case 'R':
+                {
+                    *pms += READ;
+                    i++;
+                    break;
+                }
+            case 'U':
+                {
+                    *pms += UPDATE;
+                    i++;
+                    break;
+                }
+            case 'D':
+                {
+                    *pms += DELETE;
+                    i++;
+                    break;
+                }
+            case 'N':
+                {
+                    *pms += NOTIFY;
+                    i++;
+                    break;
+                }
+            case '_':
+                {
+                    i++;
+                    break;
+                }
+            default:
+                {
+                    return -1;
+                }
+        }
+    }
+    return 0;
+}
+
+/**
+ * Get the ACL property from user
+ *
+ * @param[in]    ACL Datastructure to save user inputs
+ * @return  0 on success otherwise -1.
+ */
+static int InputACL(OicSecAcl_t *acl)
+{
+    int ret;
+    char temp_id [UUID_LENGTH + 4] = {0,};
+    char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
+    char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
+    printf("******************************************************************************\n");
+    printf("-Set ACL policy for target device\n");
+    printf("******************************************************************************\n");
+    //Set Subject.
+    printf("-URN identifying the subject\n");
+    printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
+    printf("Subject : ");
+    char *ptr = NULL;
+    ret = scanf("%19ms", &ptr);
+    if(1==ret)
+    {
+        OICStrcpy(temp_id, sizeof(temp_id), ptr);
+        OICFree(ptr);
+    }
+    else
+    {
+         printf("Error while input\n");
+         return -1;
+    }
+    int j = 0;
+    for (int i = 0; temp_id[i] != '\0'; i++)
+    {
+        if (DASH != temp_id[i])
+        {
+            if(j>UUID_LENGTH)
+            {
+                printf("Invalid input\n");
+                return -1;
+            }
+            acl->subject.id[j++] = temp_id[i];
+        }
+    }
+
+    //Set Resource.
+    printf("Num. of Resource : \n");
+    ret = scanf("%zu", &acl->resourcesLen);
+    printf("-URI of resource\n");
+    printf("ex) /a/light (Max_URI_Length: 64 Byte )\n");
+    acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
+    if (NULL == acl->resources)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return -1;
+    }
+    for (size_t i = 0; i < acl->resourcesLen; i++)
+    {
+        printf("[%zu]Resource : ", i + 1);
+        char *ptr_tempRsc = NULL;
+        ret = scanf("%64ms", &ptr_tempRsc);
+        if (1==ret)
+        {
+            OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
+            OICFree(ptr_tempRsc);
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+        acl->resources[i] = OICStrdup(temp_rsc);
+
+        if (NULL == acl->resources[i])
+        {
+            OC_LOG(ERROR, TAG, "Error while memory allocation");
+            return -1;
+        }
+    }
+    // Set Permission
+    do
+    {
+        printf("-Set the permission(C,R,U,D,N)\n");
+        printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
+        printf("Permission : ");
+        char *ptr_temp_pms = NULL;
+        ret = scanf("%5ms", &ptr_temp_pms);
+        if(1 == ret)
+        {
+            OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
+            OICFree(ptr_temp_pms);
+
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+    }
+    while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
+    // Set Rowner
+    printf("Num. of Rowner : ");
+    ret = scanf("%zu", &acl->ownersLen);
+    printf("-URN identifying the rowner\n");
+    printf("ex) lightDeviceUUID0 (16 Numbers except to '-')\n");
+    acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+    if (NULL == acl->owners)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return -1;
+    }
+    for (size_t i = 0; i < acl->ownersLen; i++)
+    {
+        printf("[%zu]Rowner : ", i + 1);
+        char *ptr_temp_id = NULL;
+        ret = scanf("%19ms", &ptr_temp_id);
+        if (1 == ret)
+        {
+            OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
+            OICFree(ptr_temp_id);
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+        j = 0;
+        for (int k = 0; temp_id[k] != '\0'; k++)
+        {
+            if (DASH != temp_id[k])
+            {
+                acl->owners[i].id[j++] = temp_id[k];
+            }
+        }
+    }
+    return 0;
+}
+
+
+//FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
+{
+    (void)UNUSED_PARAM;
+    return fopen(PROV_TOOL_DB_FILE, mode);
+}
+
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    printf("-----------------------------------------------------------\n");
+    if(!hasError)
+    {
+        printf("%s was successfully done.\n", procName);
+    }
+    else
+    {
+        for(int i = 0; i < nOfRes; i++)
+        {
+            printf("UUID : ");
+            for(int j = 0; j < UUID_LENGTH; j++)
+            {
+                printf("%c", arr[i].deviceId.id[j]);
+            }
+            printf("\t");
+            printf("Result=%d\n", arr[i].res);
+        }
+    }
+
+    if(ctx)
+    {
+        printf("Context is %s\n", (char*)ctx);
+    }
+    printf("-----------------------------------------------------------\n");
+}
+
+void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
+    }
+    else printf("Cert provisioning error\n-----------------------------------------");
+}
+
+void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
+    }
+}
+
+void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
+    }
+}
+
+
+
+void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
+    }
+}
+
+static short IsCKMInfoFileExists()
+{
+    FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
+    if (NULL != ckmInf)
+    {
+        fclose(ckmInf);
+        return 1;
+    }
+    return 0;
+}
+
+static PKIError InitCA()
+{
+    FUNCTION_INIT();
+
+    if (IsCKMInfoFileExists())
+    {
+        CHECK_CALL(InitCKMInfo);
+    }
+    else
+    {
+        ByteArray rootName  = BYTE_ARRAY_INITIALIZER;
+        ByteArray CAPubKey  = BYTE_ARRAY_INITIALIZER;
+        ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
+        ByteArray rootCert  = BYTE_ARRAY_INITIALIZER;
+
+
+        uint8_t rootCertData[ISSUER_MAX_CERT_SIZE];
+        uint8_t CAPubKeyData[PUBLIC_KEY_SIZE];
+        uint8_t CAPrivKeyData[PRIVATE_KEY_SIZE];
+        const char rootNameStr[] = "Sample_Root";
+
+        CAPubKey.data  = CAPubKeyData;
+        CAPubKey.len   = PUBLIC_KEY_SIZE;
+        CAPrivKey.data = CAPrivKeyData;
+        CAPrivKey.len  = PRIVATE_KEY_SIZE;
+        rootCert.data  = rootCertData;
+        rootCert.len   = ISSUER_MAX_CERT_SIZE;
+        rootName.data  = (uint8_t *)rootNameStr;
+        rootName.len   = strlen(rootNameStr);
+
+        CHECK_CALL(SetRootName, rootName);
+        CHECK_CALL(GenerateCAKeyPair, &CAPrivKey, &CAPubKey);
+        CHECK_CALL(SetSerialNumber, 1);
+        CHECK_CALL(CKMIssueRootCertificate, NULL, NULL, &rootCert);
+        CHECK_CALL(SetCACertificate, &rootCert);
+    }
+
+    FUNCTION_CLEAR();
+}
+
+static int InputCRL(OicSecCrl_t *crlRes)
+{
+    FUNCTION_INIT(
+            ByteArray crl = BYTE_ARRAY_INITIALIZER;
+            );
+
+    const int MAX_Revoked_NUMBER = 9;
+    uint8_t uint8ThisUpdateTime[DATE_LENGTH] = "130101000005Z";
+    uint32_t revokedNumbers[MAX_Revoked_NUMBER];
+    const uint8_t* revocationDates[MAX_Revoked_NUMBER];
+   // const uint8_t revocationDatesContent[MAX_Revoked_NUMBER][DATE_LENGTH];
+    uint32_t nuberOfRevoked = 0;
+    printf("Enter number of Revoked certificates(1..%d)\n", MAX_Revoked_NUMBER);
+    scanf("%u", &nuberOfRevoked);
+
+    for (size_t i = 0; i < nuberOfRevoked; ++i)
+    {
+        printf("Revoked certificate %d:", i);
+        printf("Serial number (E. g.: 100):");
+        scanf("%u", &revokedNumbers[i]);
+        revocationDates[i] = (const uint8_t*)"130101000005Z";
+    }
+
+    crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
+    crl.data = (uint8_t *)OICCalloc(1, crl.len);
+
+    CHECK_CALL(CKMIssueCRL, uint8ThisUpdateTime, nuberOfRevoked, revokedNumbers,
+            revocationDates, &crl);
+    PRINT_BYTE_ARRAY("CRL:\n",crl);
+    CHECK_CALL(SetCertificateRevocationList, &crl);
+    crlRes->CrlData = crl;
+    crlRes->ThisUpdate.data = uint8ThisUpdateTime;
+    crlRes->ThisUpdate.len = DATE_LENGTH;
+    crlRes->CrlId = 1;
+
+
+    FUNCTION_CLEAR(
+    //OICFree(crl.data);
+            );
+}
+
+
+/**
+ * Provisioning client sample using ProvisioningAPI
+ */
+int main()
+{
+    OCStackResult res = OC_STACK_OK;
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = { .open = client_fopen,
+                               .read = fread,
+                               .write = fwrite,
+                               .close = fclose,
+                               .unlink = unlink};
+
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        goto error;
+    }
+
+    OCProvisionDev_t* pDeviceList = NULL;
+    res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
+        goto error;
+    }
+
+    OCProvisionDev_t* pCurDev = pDeviceList;
+    int i;
+    while(pCurDev !=NULL)
+    {
+        for(i = 0; i < UUID_LENGTH; i++)
+        {
+            printf("%c", pCurDev->doxm->deviceID.id[i]);
+        }
+        printf("\n");
+        pCurDev = pCurDev->next;
+    }
+
+    //Register callback function to each OxM
+    OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+                                         .createSecureSessionCB=NULL,
+                                         .createSelectOxmPayloadCB=NULL,
+                                         .createOwnerTransferPayloadCB=NULL};
+    justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+    justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+    justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+    justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+    OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+    char* myContext = "OTM Context";
+    //Perform ownership transfer
+    res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
+    if(OC_STACK_OK == res)
+    {
+        OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
+    }
+
+    gOwnershipState = 0;
+    while (gOwnershipState == 0)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+
+// Credential & ACL provisioning between two devices.
+
+    OCProvisionDev_t *pOwnedList = NULL;
+    OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
+    int nOwnedDevice = 0;
+
+    res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
+    if (OC_STACK_OK == res)
+    {
+        printf("################## Owned Device List #######################\n");
+        while (pOwnedList != NULL)
+        {
+            nOwnedDevice ++;
+            printf(" %d : ", nOwnedDevice);
+            for (int i = 0; i < UUID_LENGTH; i++)
+            {
+                printf("%c", pOwnedList->doxm->deviceID.id[i]);
+            }
+            printf("\n");
+            pOwnedDevices[nOwnedDevice] = pOwnedList;
+            pOwnedList = pOwnedList->next;
+        }
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
+    }
+
+    int Device1 = 0;
+    int Device2 = 0;
+
+    printf("Select 2 devices for Credential & ACL provisioning\n");
+    printf("Device 1: ");
+    scanf("%d", &Device1);
+    printf("Device 2: ");
+    scanf("%d", &Device2);
+
+
+    gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+    if (NULL == gAcl)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        goto error;
+    }
+
+    if (PKI_SUCCESS != InitCA())
+    {
+        OC_LOG(ERROR, TAG, "CA init error");
+        goto error;
+    }
+
+
+    char *ctx = "DUMMY";
+
+    res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device1],
+                                                                NULL, ProvisionCertCB);
+    if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to provision Device 1 : %d", res);
+    gOwnershipState = 0;
+    while ( gOwnershipState == 0 )
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+
+    res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
+                                                                NULL, ProvisionCertCB);
+    if (OC_STACK_OK != res)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
+    }
+
+    gOwnershipState = 0;
+    while (gOwnershipState == 0)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+
+    printf("Input ACL for Device2\n");
+    if (0 == InputACL(gAcl))
+    {
+        printf("Success Input ACL\n");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "InputACL error");
+        goto error;
+    }
+    res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
+    if (OC_STACK_OK != res)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
+    }
+
+    gOwnershipState = 0;
+    while (gOwnershipState == 0)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+    gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
+    if (PKI_SUCCESS != InputCRL(gCrl))
+    {
+        OC_LOG(ERROR, TAG, "CA init error");
+        goto error;
+    }
+
+    PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
+
+
+    res = OCProvisionCRL(ctx, pOwnedDevices[Device2], gCrl, &ProvisionCrlCB);
+    if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to CRL provision Device 2 : %d", res);
+
+    gOwnershipState = 0;
+    while (gOwnershipState == 0)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+        goto error;
+    }
+
+error:
+    deleteACL(gAcl);
+    OCDeleteDiscoveredDevices(&pDeviceList);
+    OCDeleteDiscoveredDevices(&pOwnedList);
+
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/pki_test.cpp b/resource/csdk/security/provisioning/ck_manager/unittest/pki_test.cpp
new file mode 100644 (file)
index 0000000..e2dc42d
--- /dev/null
@@ -0,0 +1,968 @@
+/******************************************************************
+ *
+ * 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 <iostream>
+#include <string.h>
+#include <oic_malloc.h>
+#include <gtest/gtest.h>
+#include "ocstack.h"
+
+#include "cert_generator.h"
+#include "ck_manager.h"
+#include "pki.h"
+#include "sn_store.h"
+#include "der_dec.h"
+#include "crl.h"
+#include "crl_generator.h"
+#include "crlresource.h"
+#include "ckm_info.h"
+
+
+#define RUNS          1
+#define MAX_LEN     1000
+#define TEST_SN       50
+#define READ_WRITE_BLOCK_N 1ul
+#define N_LENGTH_BYTES 3
+
+const char *CKMI_JSON_FILE_NAME = "CKMInfo.json";
+
+#define CRL_DEFAULT_CRL_ID           1
+#define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
+#define CRL_DEFAULT_CRL_DATA        "-"
+
+#define NUMBER_OF_REVOKED 2
+
+OCPersistentStorage ps = { NULL, NULL, NULL, NULL, NULL};
+
+//#define NUM_ACE_FOR_WILDCARD_IN_CKM1_JSON (2)
+
+FILE* ckm_fopen(const char * /*path*/, const char *mode)
+{
+    return fopen(CKMI_JSON_FILE_NAME, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+{
+    if(ps)
+    {
+        ps->open = ckm_fopen;
+        ps->read = fread;
+        ps->write = fwrite;
+        ps->close = fclose;
+        ps->unlink = unlink;
+    }
+}
+
+// Length of test certificate
+#define SIMPLE_CRT_LEN 469
+
+class PKITest : public ::testing::Test
+{
+public:
+    static void SetUpTestCase()
+    {
+        SetPersistentHandler(&ps);
+        OCStackResult res = OCRegisterPersistentStorageHandler(&ps);
+        ASSERT_TRUE(res == OC_STACK_OK);
+    }
+
+    static void TearDownTestCase()
+    {
+    }
+
+    static CertificateX509  g_certificate;
+
+    static const ByteArray g_caPublicKey;
+
+    static const ByteArray g_derCode ;
+
+    static ByteArray g_serNum;
+};
+
+CertificateX509  PKITest::g_certificate;
+
+const ByteArray PKITest::g_derCode = {(uint8_t[])
+    {
+        0x30, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+        0xd7, 0x56, 0x8c, 0xfc, 0x53, 0x18, 0xb0, 0xab, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
+        0x3d, 0x04, 0x03, 0x02, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+        0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
+        0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+        0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+        0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+        0x35, 0x30, 0x33, 0x31, 0x32, 0x31, 0x32, 0x32, 0x35, 0x31, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x37,
+        0x30, 0x33, 0x31, 0x31, 0x31, 0x32, 0x32, 0x35, 0x31, 0x31, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30,
+        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+        0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+        0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+        0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+        0x74, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
+        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xc8, 0x92,
+        0x1d, 0xaa, 0x7f, 0xf0, 0xe4, 0xb2, 0x75, 0xd6, 0x4a, 0xf1, 0xd5, 0x14, 0x3f, 0x1a, 0x09, 0xc5,
+        0x3e, 0x52, 0xd6, 0xda, 0xa0, 0xbf, 0x90, 0x43, 0xd1, 0x6b, 0xfe, 0xd1, 0xb3, 0x75, 0x5c, 0xdd,
+        0x69, 0xac, 0x42, 0xa1, 0xcb, 0x03, 0x16, 0xee, 0xa4, 0x30, 0xa5, 0x8d, 0x36, 0x8f, 0xc5, 0x7b,
+        0xb4, 0xb5, 0x6a, 0x7d, 0x9b, 0x16, 0x04, 0x46, 0xab, 0xae, 0xbb, 0x56, 0xa1, 0xa3, 0x50, 0x30,
+        0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x5c, 0x0e, 0x30, 0xa8,
+        0x8e, 0x7f, 0xc9, 0x02, 0xcd, 0xa8, 0xed, 0x0d, 0x1a, 0x1b, 0xd9, 0x7d, 0xe6, 0xce, 0x2a, 0x59,
+        0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x5c, 0x0e, 0x30,
+        0xa8, 0x8e, 0x7f, 0xc9, 0x02, 0xcd, 0xa8, 0xed, 0x0d, 0x1a, 0x1b, 0xd9, 0x7d, 0xe6, 0xce, 0x2a,
+        0x59, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+        0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
+        0x02, 0x21, 0x00, 0xf6, 0x79, 0xed, 0x69, 0xd5, 0xe5, 0xba, 0x42, 0x14, 0xfc, 0xce, 0x47, 0xf1,
+        0x61, 0x1c, 0x51, 0x11, 0x2b, 0xba, 0x04, 0x70, 0x56, 0x78, 0xaf, 0xa9, 0xa6, 0x98, 0x8f, 0x4b,
+        0xa8, 0x11, 0x67, 0x02, 0x20, 0x3a, 0xdf, 0xf1, 0x74, 0xc9, 0x2f, 0xfb, 0x84, 0x46, 0xde, 0xbc,
+        0x2d, 0xda, 0xe3, 0x05, 0xb4, 0x81, 0x31, 0x45, 0xf7, 0x3d, 0x71, 0x46, 0x07, 0xa7, 0xd8, 0xcb,
+        0xae, 0x1e, 0x1b, 0x1c, 0x5a
+    }, SIMPLE_CRT_LEN };
+
+
+const ByteArray PKITest::g_caPublicKey = {(uint8_t[])
+{
+    0x8c, 0xc8, 0x92, 0x1d, 0xaa, 0x7f, 0xf0, 0xe4, 0xb2, 0x75, 0xd6, 0x4a, 0xf1, 0xd5, 0x14, 0x3f,
+    0x1a, 0x09, 0xc5, 0x3e, 0x52, 0xd6, 0xda, 0xa0, 0xbf, 0x90, 0x43, 0xd1, 0x6b, 0xfe, 0xd1, 0xb3,
+    0x75, 0x5c, 0xdd, 0x69, 0xac, 0x42, 0xa1, 0xcb, 0x03, 0x16, 0xee, 0xa4, 0x30, 0xa5, 0x8d, 0x36,
+    0x8f, 0xc5, 0x7b, 0xb4, 0xb5, 0x6a, 0x7d, 0x9b, 0x16, 0x04, 0x46, 0xab, 0xae, 0xbb, 0x56, 0xa1
+}, PUBLIC_KEY_SIZE };
+
+
+ByteArray PKITest::g_serNum = {(uint8_t[SERIAL_NUMBER_MAX_LEN]) {0}, SERIAL_NUMBER_MAX_LEN};
+
+//registering persistent storage test
+TEST(CKManager, RegisterPersistentStorage)
+{
+    SetPersistentHandler(&ps);
+    ASSERT_EQ(OC_STACK_OK, OCRegisterPersistentStorageHandler(&ps));
+}
+
+//check decoding predefined certificate
+TEST(X509Certificate, DecodeTest)
+{
+    ByteArray code = PKITest::g_derCode;
+
+    ASSERT_EQ(DecodeCertificate(code, &PKITest::g_certificate), PKI_SUCCESS);
+    code.data = NULL;
+    ASSERT_NE(DecodeCertificate(code, &PKITest::g_certificate), PKI_SUCCESS);
+}
+
+//check decoding of random symbols sequence
+TEST(X509Certificate, RandomDecode)
+{
+    srand((unsigned int)time(NULL));
+
+    ByteArray code;
+    INIT_BYTE_ARRAY(code);
+
+    for (unsigned int i = 0; i < RUNS; i++)
+    {
+        code.len = rand() % MAX_LEN;
+        code.data = (uint8_t *)malloc(code.len * sizeof(uint8_t));
+
+        EXPECT_NE(code.data, (uint8_t *)NULL);
+
+        for (unsigned int j = 0; j < code.len; j++)
+        {
+            code.data[j] = (uint8_t)(rand() % 128 + 1);
+        }
+
+        EXPECT_NE(PKI_SUCCESS, DecodeCertificate(code, &PKITest::g_certificate));
+
+        free(code.data);
+    }
+}
+//testing validity check of predefined certificate
+TEST(X509Certificate, testCheckValidity)
+{
+    CertificateX509 tempCrt;
+    ASSERT_EQ(PKI_SUCCESS, DecodeCertificate(PKITest::g_derCode, &tempCrt));
+    ASSERT_EQ(PKI_SUCCESS, CheckValidity(tempCrt.validFrom, tempCrt.validTo));
+    ByteArray temp = tempCrt.validTo;
+
+    tempCrt.validTo = tempCrt.validFrom;
+    tempCrt.validFrom = temp;
+    ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckValidity(tempCrt.validFrom, tempCrt.validTo));
+}
+
+//testing signature check of predefined certificate
+TEST(X509Certificate, CheckSignature)
+{
+    ByteArray code = PKITest::g_derCode;
+
+    ASSERT_EQ(PKI_SUCCESS, CheckCertificate(code, PKITest::g_caPublicKey));
+    code.data = NULL;
+    ASSERT_NE(PKI_SUCCESS, CheckCertificate(code, PKITest::g_caPublicKey));
+}
+
+//test saving certificate into file
+TEST_F(PKITest, DERCertificateFile)
+{
+    uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    certDer.data = derData;
+    certDer.len = ISSUER_MAX_CERT_SIZE;
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = sizeof(caPubKey);
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = sizeof(caPrivKey);
+    rootName.data = (uint8_t *)"ROOT1";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+    for (int i = 1; i <= RUNS; i++)
+    {
+        ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+        ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+        ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        ASSERT_EQ(PKI_SUCCESS, GenerateDERCertificateFile (&certDer, "der_cert"));
+    }
+    ASSERT_EQ(CloseCKMInfo(), PKI_SUCCESS);
+}
+
+//test checking time validity of generated certificate
+TEST_F(PKITest, TimeValidity)
+{
+    uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKey = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKey = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    privKey.data = caPrivKey;
+    privKey.len = sizeof(caPrivKey);
+
+    certDer.data = derData;
+    certDer.len = sizeof(derData);
+
+    pubKey.data = caPubKey;
+    pubKey.len = sizeof(caPubKey);
+
+    rootName.data = (uint8_t *)"ROOT3";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+    for (int i = 1; i <= RUNS; i++)
+    {
+        ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKey, &pubKey));
+        ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+        ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKey));
+
+        certDer.len = sizeof(derData);
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, (uint8_t *)"130101000000Z", &certDer));
+        ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckCertificate(certDer, pubKey));
+
+        certDer.len = sizeof(derData);
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate((uint8_t *)"160101000000Z", 0, &certDer));
+        ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckCertificate(certDer, pubKey));
+    }
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing certificate generation by certificate signing request
+TEST_F(PKITest, CertificateSigningRequest)
+{
+    uint8_t certData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t csrData[CSR_MAX_SIZE] = {0};
+    uint8_t subjPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t subjPrivKey[PRIVATE_KEY_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+    uint8_t *subjName = (uint8_t *)"Subject05";
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray csrDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeySubj = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeySubj = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    certDer.data = certData;
+    certDer.len = sizeof(certData);
+    csrDer.data = csrData;
+    csrDer.len = CSR_MAX_SIZE;
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = sizeof(caPubKey);
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = sizeof(caPrivKey);
+    pubKeySubj.data = subjPubKey;
+    pubKeySubj.len = sizeof(subjPubKey);
+    privKeySubj.data = subjPrivKey;
+    privKeySubj.len = sizeof(subjPrivKey);
+    rootName.data = (uint8_t *)"ROOT2";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+    ASSERT_EQ(GenerateCAKeyPair(&privKeyIss, &pubKeyIss), PKI_SUCCESS);
+    ASSERT_EQ(SetSerialNumber(1), PKI_SUCCESS);
+    ASSERT_EQ(SetRootName(rootName), PKI_SUCCESS);
+
+    for (int i = 1; i <= RUNS; i++)
+    {
+        ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeySubj, &pubKeySubj));
+        ASSERT_EQ(PKI_SUCCESS, GenerateCSR(subjName, subjPubKey, subjPrivKey, &csrDer));
+        ASSERT_EQ(PKI_SUCCESS, GenerateCertificateByCSR(&csrDer, &certDer));
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]++;
+        ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]--;
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+    }
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//test public key structure parsing
+TEST(X509Certificate, testParsePublicKey)
+{
+    ASSERT_EQ(PKI_SUCCESS, ParsePublicKey((ByteArray*)&PKITest::g_caPublicKey));
+
+    size_t length = 3;
+    uint8_t shortAr[length];
+    ByteArray shortArray = {shortAr, length};
+    ASSERT_EQ(PKI_WRONG_ARRAY_LEN, ParsePublicKey(&shortArray));
+
+    uint8_t uncompressed[PUBLIC_KEY_SIZE + 2];
+    uncompressed[0] = 0;
+    uncompressed[1] = ASN1_UNCOMPRESSED_KEY;
+    memcpy(&uncompressed[2], PKITest::g_caPublicKey.data, PUBLIC_KEY_SIZE);
+    ByteArray uncomprArr = {uncompressed, PUBLIC_KEY_SIZE+2};
+    ParsePublicKey(&uncomprArr);
+    ASSERT_EQ((size_t)PUBLIC_KEY_SIZE, uncomprArr.len);
+    ASSERT_EQ(0, memcmp(uncomprArr.data, PKITest::g_caPublicKey.data, PUBLIC_KEY_SIZE));
+}
+
+//test checking of certificate generated by OpenSSL
+TEST(OpenSSLCompatibility, verifyOpenSslCertSign)
+{
+    ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+    CertificateX509 certificate;
+
+    FILE *fileCert = fopen("01.der", "rb");
+    ASSERT_TRUE(fileCert != NULL);
+
+    //get the length
+    fseek(fileCert, 0, SEEK_END);
+    crtDer.len = ftell(fileCert);
+    fseek(fileCert, 0, SEEK_SET);
+    //allocate memory
+    crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, fileCert));
+    fclose(fileCert);
+
+    ByteArray pubKey = BYTE_ARRAY_INITIALIZER;
+    FILE * fileKey = fopen("capub.der", "rb");
+    ASSERT_TRUE(fileKey != NULL);
+    fseek(fileKey, 0, SEEK_END);
+    pubKey.len = ftell(fileKey);
+    fseek(fileKey, 0, SEEK_SET);
+    //openssl generates a public key that is longer than 64 bytes
+    //with additional 27 bytes prepending the actual key
+    if(pubKey.len > PUBLIC_KEY_SIZE){
+        fseek(fileKey, (pubKey.len - PUBLIC_KEY_SIZE), SEEK_SET);
+        pubKey.len = PUBLIC_KEY_SIZE;
+    }
+    pubKey.data = (uint8_t*)malloc(pubKey.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(pubKey.data, pubKey.len, READ_WRITE_BLOCK_N, fileKey));
+    fclose(fileKey);
+
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtDer, &certificate));
+    EXPECT_EQ(PKI_SUCCESS, CheckCertificate(crtDer, pubKey));
+
+    free(crtDer.data);
+    free(pubKey.data);
+}
+
+//test parsing of certificate chain generated by OpenSSL
+TEST(CertificateChain, LoadCertificateChain)
+{
+    ByteArray crtChainDer[MAX_CHAIN_LEN] = {{0,0},};
+    CertificateX509 crtChain[MAX_CHAIN_LEN] = {{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}},};
+    ByteArray msg = BYTE_ARRAY_INITIALIZER;
+    uint8_t chainLength;
+
+    FILE *file = fopen("cert_chain.dat", "rb");
+
+    ASSERT_TRUE(file  != NULL);
+
+    while (!feof (file))
+    {
+        msg.data = (uint8_t *) realloc (msg.data, msg.len + 1);
+        msg.data[msg.len] = fgetc (file);
+        msg.len++;
+    }
+    msg.len--;
+    fclose (file);
+    INC_BYTE_ARRAY(msg, 3);
+    EXPECT_EQ(PKI_SUCCESS, LoadCertificateChain (msg, crtChainDer, &chainLength));
+#ifdef X509_DEBUG
+    printf("chain len: %d\n", chainLength);
+#endif
+    EXPECT_EQ(PKI_UNKNOWN_OID, ParseCertificateChain (crtChainDer, crtChain, chainLength));
+
+    free(msg.data - 3);
+}
+
+//test checking CA certificate generated by OpenSSL
+TEST(OpenSSLCompatibility, testOpenSSLCertificate)
+{
+    ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+    FILE *fileCert = fopen("cacert.der", "rb");
+    ASSERT_TRUE(fileCert != NULL);
+
+    //get the length
+    fseek(fileCert, 0, SEEK_END);
+    crtDer.len = ftell(fileCert);
+    fseek(fileCert, 0, SEEK_SET);
+    //allocate memory
+    crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, fileCert));
+
+    fclose(fileCert);
+    #ifdef X509_DEBUG
+    printf("Length of cert: %lu\n", crtDer.len);
+    #endif
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtDer, &PKITest::g_certificate));
+    free(crtDer.data);
+}
+
+//test signatures checking of certificate chain generated by OpenSSL
+TEST(OpenSSLCompatibility, ParseAndCheckCertificateChain)
+{
+    ByteArray crtChainDer[MAX_CHAIN_LEN] = {{0,0},};
+    CertificateX509 crtChain[MAX_CHAIN_LEN] = {{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}},};
+    ByteArray msg = BYTE_ARRAY_INITIALIZER;
+    uint8_t chainLength;
+
+    const char* chainPath = {"chain.der"};
+    FILE *fileChain = fopen(chainPath, "rb");
+    ASSERT_TRUE(fileChain != NULL);
+
+    //get the length
+    fseek(fileChain, 0, SEEK_END);
+    msg.len = ftell(fileChain);
+    fseek(fileChain, 0, SEEK_SET);
+    //allocate memory
+    msg.data = (uint8_t*)malloc(msg.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(msg.data, msg.len, READ_WRITE_BLOCK_N, fileChain));
+
+    fclose (fileChain);
+
+    INC_BYTE_ARRAY(msg, 3);
+    EXPECT_EQ(PKI_SUCCESS, LoadCertificateChain(msg, crtChainDer, &chainLength));
+    EXPECT_EQ(3, chainLength);
+    #ifdef X509_DEBUG
+    printf("Length of the chain: %d\n", chainLength);
+    #endif
+
+    EXPECT_EQ(PKI_SUCCESS, ParseCertificateChain(crtChainDer, crtChain, chainLength));
+
+    ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
+
+    const char* caPubKeyPath = {"capub.der"};
+    FILE *fileCaPubKey = fopen(caPubKeyPath, "rb");
+    ASSERT_TRUE(fileCaPubKey != NULL);
+
+    fseek(fileCaPubKey, 0, SEEK_END);
+    caPubKey.len = ftell(fileCaPubKey);
+    fseek(fileCaPubKey, 0, SEEK_SET);
+    if(caPubKey.len > PUBLIC_KEY_SIZE){
+        fseek(fileCaPubKey, (caPubKey.len - PUBLIC_KEY_SIZE), SEEK_SET);
+        caPubKey.len = PUBLIC_KEY_SIZE;
+    }
+    caPubKey.data = (uint8_t*)malloc(caPubKey.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(caPubKey.data, caPubKey.len, READ_WRITE_BLOCK_N, fileCaPubKey));
+    fclose(fileCaPubKey);
+
+    EXPECT_EQ(PKI_SUCCESS, CheckCertificateChain(crtChain, chainLength, caPubKey));
+
+    free(msg.data - 3);
+    free(caPubKey.data);
+}
+
+//testing correctness of decoding certificate length from ASN.1 structure
+TEST(CRL, testDecodeLength)
+{
+    ByteArray cert = BYTE_ARRAY_INITIALIZER;
+    size_t length(0);
+    EXPECT_EQ(PKI_NULL_PASSED, DecodeLength(&cert, &length));
+
+    //a simple DER
+    size_t derLength = (size_t)rand() % LEN_LONG;
+    cert.len = derLength + 2;
+    uint8_t *certData = (uint8_t*)malloc(cert.len);
+    cert.data = certData;
+    cert.data[0] = (uint8_t)0x30; //mixed types
+    cert.data[1] = (uint8_t)(derLength & 0xff);
+    EXPECT_EQ(PKI_SUCCESS, DecodeLength(&cert, &length));
+    EXPECT_EQ(derLength, length);
+    free(certData);
+}
+
+//testing serial number storage
+TEST(CRL, StoreSerialNumber)
+{
+    uint8_t data[10] = {0x01, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03};
+    const ByteArray sn = { data, sizeof(data) / sizeof(uint8_t)};
+    int i;
+    for (i = 0; i < 400; i++)
+    {
+        sn.data[0] = i % 20;
+        ASSERT_EQ(PKI_SUCCESS, StoreSerialNumber(sn));
+    }
+    ASSERT_EQ(PKI_CERT_REVOKED, CheckSerialNumber(sn));
+
+    sn.data[1] = 0x01;
+    ASSERT_EQ(PKI_SUCCESS, CheckSerialNumber(sn));
+
+    FreeSNStore();
+}
+#ifdef ARDUINO_MEMORY_DEBUG
+//testing memory allocation fault handling at Arduino
+TEST(SNStore, MemoryOverflow)
+{
+    uint8_t data[10] = {0x01, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03};
+    const ByteArray sn = { data, sizeof(data) / sizeof(uint8_t)};
+    int i;
+    PKIError res;
+    do
+    {
+        res  = StoreSerialNumber(sn);
+    }
+    while (res == PKI_SUCCESS);
+    ASSERT_EQ(PKI_MEMORY_ALLOC_FAILED, res);
+
+    FreeSNStore();
+}
+#endif /* ARDUINO_MEMORY_DEBUG */
+
+//testing next certificate serial number handling by "CKM info" unit
+TEST_F(PKITest, CAInitAndSerialNum)
+{
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    long serialNum = rand() % (MAX_LEN - 1) + 1;
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    //all the serials should start from
+    ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(serialNum));
+    long nextSerial;
+    ASSERT_EQ(PKI_SUCCESS, GetNextSerialNumber(&nextSerial));
+    ASSERT_EQ(nextSerial, serialNum);
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing CA name handling by "CKM info" unit
+TEST_F(PKITest, testCAName)
+{
+    ByteArray caName = BYTE_ARRAY_INITIALIZER;
+    caName.len = ((size_t)rand() % (ISSUER_MAX_NAME_SIZE - 1) + 1);
+    caName.data = (uint8_t*)malloc(caName.len);
+    size_t i;
+    for(i = 0; i < caName.len; i++){
+            caName.data[i] = (uint8_t)(rand() % 128);
+    }
+    EXPECT_EQ(PKI_SUCCESS, InitCKMInfo());
+    EXPECT_EQ(PKI_SUCCESS, SetRootName(caName));
+    ByteArray getName = BYTE_ARRAY_INITIALIZER;
+    uint8_t uint8CAName[ISSUER_MAX_NAME_SIZE] = {0};
+    getName.data     = uint8CAName;
+    getName.len      = ISSUER_MAX_NAME_SIZE;
+    EXPECT_EQ(PKI_SUCCESS, GetCAName(&getName));
+    EXPECT_EQ(0, memcmp(caName.data, getName.data, caName.len));
+    free(caName.data);
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing key pair generation and storing by "CKM info" unit
+TEST_F(PKITest, testKeyPair)
+{
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+    rootName.data = (uint8_t *)"ROOT";
+    rootName.len = strlen((char *)rootName.data);
+    SetRootName(rootName);
+
+    //first test the GenerateCAKeyPair - this writes to the CA storage
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    privKeyIss.len = PRIVATE_KEY_SIZE;
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+    privKeyIss.data = caPrivKey;
+
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    pubKeyIss.len = PUBLIC_KEY_SIZE;
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    pubKeyIss.data = caPubKey;
+
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+    ByteArray keyCheck = BYTE_ARRAY_INITIALIZER;
+    keyCheck.len = PUBLIC_KEY_SIZE;
+    uint8_t keyCheckData[PUBLIC_KEY_SIZE] = {0};
+    keyCheck.data = keyCheckData;
+    ASSERT_EQ(PKI_SUCCESS, GetCAPrivateKey(&keyCheck));
+    ASSERT_EQ(0, memcmp(keyCheck.data, privKeyIss.data, PRIVATE_KEY_SIZE));
+
+    ASSERT_EQ(PKI_SUCCESS, GetCAPublicKey(&keyCheck));
+    ASSERT_EQ(0, memcmp(keyCheck.data, pubKeyIss.data, PUBLIC_KEY_SIZE));
+
+    //now test the GenerateKeyPair - does not write to the CA storage
+    ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeyIss, &pubKeyIss));
+
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    ASSERT_EQ(PKI_SUCCESS, GetCAPrivateKey(&keyCheck));
+    ASSERT_NE(0, memcmp(keyCheck.data, privKeyIss.data, PRIVATE_KEY_SIZE));
+
+    ASSERT_EQ(PKI_SUCCESS, GetCAPublicKey(&keyCheck));
+    ASSERT_NE(0, memcmp(keyCheck.data, pubKeyIss.data, PUBLIC_KEY_SIZE));
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing CRL encoding
+TEST_F(PKITest, testEncodeCRL)
+{
+    CertificateList crl;
+
+    uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+    uint32_t numberOfRevoked = 0;
+    uint32_t revokedNumbers[2];
+    const uint8_t *revocationDates[2];
+
+    ByteArray code = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss =  BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = PUBLIC_KEY_SIZE;
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = PRIVATE_KEY_SIZE;
+
+    numberOfRevoked = 2;
+
+    revokedNumbers[0] = 100; // serial number of first revoked certificate
+    revokedNumbers[1] = 200; // serial number of second revoked certificate
+    revocationDates[0] = (const uint8_t *)"130101000001Z";
+    revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+    rootName.data = (uint8_t *)"ROOT2";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+    ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+    code.data = (uint8_t *)calloc(1,
+                (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)));
+    code.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+
+    EXPECT_EQ(PKI_SUCCESS,CKMIssueCRL(uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+                                      revocationDates,&code));
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+    PrintSNStore();
+    PrintCRL(&crl);
+#endif
+
+    FreeSNStore();
+    free(code.data);
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//check correctness of certificate revocation by CKMIssueCRL() and CKMRevocateCertificate()
+TEST_F(PKITest, testRevocateCertificate)
+{
+    CertificateList crl;
+
+    uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+    uint32_t numberOfRevoked = 0;
+    uint32_t revokedNumbers[2];
+    const uint8_t *revocationDates[2];
+
+    ByteArray code = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss =  BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = sizeof(caPubKey);
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = sizeof(caPrivKey);
+
+    numberOfRevoked = 2;
+
+    revokedNumbers[0] = 100; // serial number of first revoked certificate
+    revokedNumbers[1] = 200; // serial number of second revoked certificate
+    revocationDates[0] = (const uint8_t *)"130101000001Z";
+    revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+    rootName.data = (uint8_t *)"ROOT2";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+    ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+    code.len = CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4);
+    code.data = (uint8_t *)calloc(1, code.len);
+
+    EXPECT_EQ(PKI_SUCCESS, CKMIssueCRL (uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+                                        revocationDates, &code));
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+    free(code.data);
+    numberOfRevoked++;
+    code.len = CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4);
+    code.data = (uint8_t *)calloc(1, code.len);
+    EXPECT_EQ(PKI_SUCCESS, CKMRevocateCertificate (uint8ThisUpdateTime, 50, &code));
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+    PrintSNStore();
+    PrintCRL(&crl);
+#endif
+
+    FreeSNStore();
+    free(code.data);
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//checck correctness of saving root certificate to binary file
+TEST_F(PKITest, StoreCKMInfo)
+{
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+    uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+    const long serNum  = 48598490;
+    CertificateList crl;
+    uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+    uint32_t numberOfRevoked = 0;
+    uint32_t revokedNumbers[2];
+    const uint8_t *revocationDates[2];
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+    ByteArray code = BYTE_ARRAY_INITIALIZER;
+
+    certDer.data = derData;
+    certDer.len = ISSUER_MAX_CERT_SIZE;
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = PUBLIC_KEY_SIZE;
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = PRIVATE_KEY_SIZE;
+    rootName.data = (uint8_t *)"ROOT";
+    rootName.len = strlen((char *)rootName.data);
+
+    //generate CA Certificate
+    ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+    ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(serNum));
+    ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+    ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+
+    //generate CRL
+    numberOfRevoked = NUMBER_OF_REVOKED;
+
+    revokedNumbers[0] = 100; // serial number of first revoked certificate
+    revokedNumbers[1] = 200; // serial number of second revoked certificate
+    revocationDates[0] = (const uint8_t *)"130101000001Z";
+    revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+    code.data = (uint8_t *)calloc(1,
+                (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)));
+    code.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+
+    ASSERT_EQ(PKI_SUCCESS, CKMIssueCRL (uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+                                        revocationDates, &code));
+
+    // Check Certificate file
+    CertificateX509 certificate;
+    ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+    FILE *filePtr = fopen(CA_STORAGE_CRT_FILE , "rb");
+    ASSERT_TRUE(filePtr != NULL);
+
+    //get the length
+    fseek(filePtr, 0, SEEK_END);
+    crtDer.len = ftell(filePtr);
+    fseek(filePtr, 0, SEEK_SET);
+    //allocate memory
+    crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+    //read the content
+    EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, filePtr));
+    fclose(filePtr);
+    ByteArray crtCheck;
+    crtCheck.data = crtDer.data + 3;    //now file contains length of certificate
+    crtCheck.len = crtDer.len - 3;
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtCheck, &certificate));
+#ifdef X509_DEBUG
+    PrintCertificate(&certificate);
+#endif
+
+    //check CRL
+    ByteArray crlDer = BYTE_ARRAY_INITIALIZER;
+    crlDer.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+    crlDer.data = (uint8_t *)malloc(crlDer.len);
+
+    EXPECT_EQ(PKI_SUCCESS, GetCertificateRevocationList(&crlDer));
+
+    EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (crlDer, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+       PrintCRL(&crl);
+#endif
+    EXPECT_EQ(PKI_SUCCESS, CloseCKMInfo());
+    free(crlDer.data);
+    free(code.data);
+    free(crtDer.data);
+}
+
+//check correctness of root certificate generation
+TEST_F(PKITest, GenerateRootCertificate)
+{
+    uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    certDer.data = derData;
+    certDer.len = sizeof(derData);
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = sizeof(caPubKey);
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = sizeof(caPrivKey);
+    rootName.data = (uint8_t *)"ROOT";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+    for (int i = 1; i <= RUNS; i++)
+    {
+        ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+        ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+        ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]++;
+        ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]--;
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+    }
+    ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//check correctness of ordinal device certificate generation
+TEST_F(PKITest, GenerateDeviceCertificate)
+{
+    uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+    uint8_t subjPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t subjPrivKey[PRIVATE_KEY_SIZE] = {0};
+    uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+    uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+    uint8_t *subjName = (uint8_t *)"Subject Name";
+
+    ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+    ByteArray pubKeySubj = BYTE_ARRAY_INITIALIZER;
+    ByteArray privKeySubj = BYTE_ARRAY_INITIALIZER;
+    ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+    certDer.data = derData;
+    certDer.len = ISSUER_MAX_CERT_SIZE;
+
+    pubKeyIss.data = caPubKey;
+    pubKeyIss.len = sizeof(caPubKey);
+    privKeyIss.data = caPrivKey;
+    privKeyIss.len = sizeof(caPrivKey);
+    pubKeySubj.data = subjPubKey;
+    pubKeySubj.len = sizeof(subjPubKey);
+    privKeySubj.data = subjPrivKey;
+    privKeySubj.len = sizeof(subjPrivKey);
+    rootName.data = (uint8_t *)"ROOT2";
+    rootName.len = strlen((char *)rootName.data);
+    ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+    ASSERT_EQ(GenerateCAKeyPair(&privKeyIss, &pubKeyIss), PKI_SUCCESS);
+    for (int i = 1; i <= RUNS; i++)
+    {
+        ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeySubj, &pubKeySubj));
+        ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+        ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+        ASSERT_EQ(PKI_SUCCESS, CKMIssueDeviceCertificate(subjName, 0, 0, subjPubKey, &certDer));
+
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]++;
+        ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+        certDer.data[0]--;
+        ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+    }
+    ASSERT_EQ(CloseCKMInfo(), PKI_SUCCESS);
+}
+
+//check correctness of saving CRL to storage and loading CRL from storage
+TEST_F(PKITest, CRLSetGet)
+{
+    OicSecCrl_t *defaultCrl = NULL;
+    defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
+    defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
+    defaultCrl->CrlData.data = (uint8_t *)CRL_DEFAULT_CRL_DATA;
+    defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
+    defaultCrl->ThisUpdate.data = (uint8_t *)CRL_DEFAULT_THIS_UPDATE;
+    defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
+    EXPECT_EQ(OC_STACK_OK, UpdateCRLResource(defaultCrl));
+
+    EXPECT_NE((void *)NULL, GetBase64CRL());
+    OICFree(defaultCrl);
+
+
+}
+
+int main(int argc, char **argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/01.der b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/01.der
new file mode 100644 (file)
index 0000000..9f4e0d9
Binary files /dev/null and b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/01.der differ
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/CKMInfo.json b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/CKMInfo.json
new file mode 100644 (file)
index 0000000..d036473
--- /dev/null
@@ -0,0 +1,48 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+            ],
+            "perms": 2,
+            "ownrs" : ["YWRtaW5EZXZpY2VVVUlE"]
+        },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 7,
+             "ownrs" : ["YWRtaW5EZXZpY2VVVUlE"]
+        }
+    ],
+    "crl": {
+        "CRLId": 1,
+        "ThisUpdate": "MTUwMTAxMDAwMDAwWg==",
+        "CRLData": "LQ=="
+    },
+    "pstat": {
+        "isop": true,
+        "deviceid": "YWRtaW5EZXZpY2VVVUlE",
+        "ch": 0,
+        "cm":   0,
+        "tm":   0,
+        "om":   3,
+        "sm":   [3]
+    },
+    "doxm": {
+        "oxm":  [0],
+        "oxmsel": 0,
+        "owned": true,
+        "deviceid": "YWRtaW5EZXZpY2VVVUlE",
+        "ownr": "YWRtaW5EZXZpY2VVVUlE"
+    }
+}
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cacert.der b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cacert.der
new file mode 100644 (file)
index 0000000..e8d0a67
Binary files /dev/null and b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cacert.der differ
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/capub.der b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/capub.der
new file mode 100644 (file)
index 0000000..55252f0
Binary files /dev/null and b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/capub.der differ
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cert_chain.dat b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cert_chain.dat
new file mode 100755 (executable)
index 0000000..e400aa8
Binary files /dev/null and b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/cert_chain.dat differ
diff --git a/resource/csdk/security/provisioning/ck_manager/unittest/test_data/chain.der b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/chain.der
new file mode 100644 (file)
index 0000000..37f3dd8
Binary files /dev/null and b/resource/csdk/security/provisioning/ck_manager/unittest/test_data/chain.der differ