Add sample of PKIX provisioning
authori.pazderskyy <i.pazderskyy@samsung.com>
Thu, 24 Sep 2015 14:36:25 +0000 (17:36 +0300)
committerJon A. Cruz <jonc@osg.samsung.com>
Fri, 25 Sep 2015 01:06:43 +0000 (01:06 +0000)
Includes provisioning client, door and light samples

Change-Id: I1457076f665ff8226a779bfe683e5a7536cabe83
Signed-off-by: Dmytro Zhuravlev <d.zhuravlev@samsung.com>
Signed-off-by: i.pazderskyy <i.pazderskyy@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2480
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
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]

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;
+}