[IOT-2359][IOT-2360][IOT-2364] Separate provisioning with DOS
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / secureresourceprovider.c
index 625d4cf..f191914 100644 (file)
@@ -202,8 +202,11 @@ struct RemoveData {
 /**
  * Function prototypes
  */
-static OCStackResult provisionCredentials(void *ctx, OicSecCred_t *cred,
+static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler);
+static OCStackResult provisionCredentials(OicSecCred_t *cred,
+        const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+        OCClientResponseHandler responseHandler);
 static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse);
 static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
@@ -302,6 +305,128 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
                                                        OCClientResponse *clientResponse)
 {
     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    CredentialData_t *credData = (CredentialData_t *) ctx;
+    (void)UNUSED;
+
+    OCProvisionResultCB resultCallback = credData->resultCallback;
+    OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
+    if (clientResponse)
+    {
+        if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+        {
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
+            OCStackResult res =  PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
+                    &credData->deviceInfo[1]->doxm->deviceID);
+            if (OC_STACK_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+            OIC_LOG(INFO, TAG, "Link created successfully");
+
+            ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                    credData->resArr,
+                                                    false);
+             OICFree(credData->resArr);
+             OICFree(credData);
+             return OC_STACK_DELETE_TRANSACTION;
+        }
+
+    }
+    OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
+    registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
+    ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                            credData->resArr,
+                                            true);
+    OICFree(credData->resArr);
+    OICFree(credData);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 1.
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] UNUSED          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    (void)UNUSED;
+    CredentialData_t* credData = (CredentialData_t*) ctx;
+    OICFree(credData->credInfo[0]);
+    const OCProvisionDev_t *deviceInfo = credData->deviceInfo[1];
+    OicSecCred_t *credInfo = credData->credInfo[1];
+    const OCProvisionResultCB resultCallback = credData->resultCallback;
+    if (clientResponse)
+    {
+        if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+        {
+            // send credentials to second device
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
+            OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
+                    provisionCredentialCB2);
+            // If deviceInfo is NULL, this device is the second device. Don't delete the cred
+            // because provisionCredentials added it to the local cred store and it now owns
+            // the memory.
+            if ((NULL != deviceInfo) || (OC_STACK_OK != res))
+            {
+                DeleteCredList(credInfo);
+            }
+            if (OC_STACK_OK != res)
+            {
+                registerResultForCredProvisioning(credData, res,2);
+                ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                        credData->resArr,
+                                                        true);
+                OICFree(credData->resArr);
+                OICFree(credData);
+                credData = NULL;
+            }
+        }
+        else
+        {
+            registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
+            ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                    credData->resArr,
+                                                    true);
+            OICFree(credData->resArr);
+            OICFree(credData);
+            credData = NULL;
+        }
+    }
+    else
+    {
+        OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
+        registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
+       ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                     credData->resArr,
+                                                     true);
+        DeleteCredList(credInfo);
+        OICFree(credData->resArr);
+        OICFree(credData);
+        credData = NULL;
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 2.
+ *
+ * @param[in] ctx             ctx value passed to callback from calling function.
+ * @param[in] UNUSED          handle to an invocation
+ * @param[in] clientResponse  Response from queries to remote servers.
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult ProvisionCredentialDosCB2(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
     CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
     (void)UNUSED;
 
@@ -329,7 +454,7 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
         }
 
     }
-    OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
+    OIC_LOG(INFO, TAG, "ProvisionCredentialDosCB2 received Null clientResponse");
     registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
     ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
                                             credData->resArr,
@@ -348,7 +473,7 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNU
  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
  */
-static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
+static OCStackApplicationResult ProvisionCredentialDosCB1(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
@@ -396,7 +521,83 @@ static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNU
     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
     return OC_STACK_DELETE_TRANSACTION;
 }
+/**
+ * Internal function for handling credential generation and sending credential to resource server.
+ *
+ * @param[in] cred Instance of cred resource.
+ * @param[in] deviceInfo information about device to which credential is to be provisioned.
+ * @param[in] responseHandler callbak called by OC stack when request API receives response.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+static OCStackResult provisionCredentials(OicSecCred_t *cred,
+        const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+        OCClientResponseHandler responseHandler)
+{
+    OCStackResult res = OC_STACK_OK;
+
+    if (NULL != deviceInfo)
+    {
+        OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+        if (!secPayload)
+        {
+            OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+            return OC_STACK_NO_MEMORY;
+        }
+        secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+        int secureFlag = 0;
+        res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
+        if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
+        {
+            OCPayloadDestroy((OCPayload *)secPayload);
+            OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
+            return OC_STACK_NO_MEMORY;
+        }
 
+        OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
+        OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+        char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
+        if (!PMGenerateQuery(true,
+            deviceInfo->endpoint.addr,
+            deviceInfo->securePort,
+            deviceInfo->connType,
+            query, sizeof(query), OIC_RSRC_CRED_URI))
+        {
+            OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+            OCPayloadDestroy((OCPayload *)secPayload);
+            return OC_STACK_ERROR;
+        }
+        OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+        OCCallbackData cbData;
+        memset(&cbData, 0, sizeof(cbData));
+        cbData.cb = responseHandler;
+        cbData.context = (void *)credData;
+        cbData.cd = NULL;
+
+        OCDoHandle handle = NULL;
+        OCMethod method = OC_REST_POST;
+        res = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
+            deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+        OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
+        if (res != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "OCStack resource error");
+            return res;
+        }
+        return OC_STACK_OK;
+    }
+    else
+    {
+        /* Provision this credential to the local cred store. On success, the cred resource takes
+         * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
+         */
+        res = AddCredential(cred);
+        /* Call the result callback directly. */
+        registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
+        (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
+        return res;
+    }
+}
 /**
  * Internal function for handling credential generation and sending credential to resource server.
  *
@@ -405,7 +606,7 @@ static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNU
  * @param[in] responseHandler callbak called by OC stack when request API receives response.
  * @return  OC_STACK_OK in case of success and other value otherwise.
  */
-static OCStackResult provisionCredentials(void *ctx, OicSecCred_t *cred,
+static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
         const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler)
 {
     OCStackResult res = OC_STACK_OK;
@@ -464,7 +665,7 @@ static OCStackResult provisionCredentials(void *ctx, OicSecCred_t *cred,
     else
     {
         /* Provision this credential to the local cred store. On success, the cred resource takes
-         * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
+         * ownership of the memory. On failure, ProvisionCredentialDosCB1 will delete the cred object.
          */
         res = AddCredential(cred);
         /* Call the result callback directly. */
@@ -560,11 +761,11 @@ static OCStackApplicationResult SetReadyForNormalOperationCB(void *ctx, OCDoHand
         if (pskData->currIndex == 0)
         {
             pskData->currIndex = 1;
-            provisionCredentialCB1(ctx, handler, clientResponse);
+            ProvisionCredentialDosCB1(ctx, handler, clientResponse);
         }
         else
         {
-            provisionCredentialCB2(ctx, handler, clientResponse);
+            ProvisionCredentialDosCB2(ctx, handler, clientResponse);
         }
     }
 
@@ -741,7 +942,7 @@ static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
     {
         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
         {
-            OCStackResult res = provisionCredentials(ctx, cred, device, ProvisionCB);
+            OCStackResult res = ProvisionCredentialsDos(ctx, cred, device, ProvisionCB);
             if (OC_STACK_OK != res)
             {
                 registerResultForCredProvisioning(credData, res, 2);
@@ -1186,48 +1387,42 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
         return OC_STACK_ERROR;
     }
     OIC_LOG(INFO, TAG, "retrieved deviceid");
-
-    CredentialData_t *credData = (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
-    Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
-    if (NULL == credData || NULL == data)
-    {
-
-        OICFree(credData);
-        OICFree(data);
-        OIC_LOG(ERROR, TAG, "Memory allocation problem");
-        return OC_STACK_NO_MEMORY;
-    }
-
-    data->ctx = credData;
-
     switch (type)
     {
         case SYMMETRIC_PAIR_WISE_KEY:
         {
-            data->type = PSK_TYPE;
+            const OCProvisionDev_t *firstDevice = pDev1;
+            const OCProvisionDev_t *secondDevice = pDev2;
+
             OicSecCred_t *firstCred = NULL;
             OicSecCred_t *secondCred = NULL;
             OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
-                                &pDev1->doxm->deviceID, (NULL != pDev2) ? &pDev2->doxm->deviceID :
-                                &provTooldeviceID,
-                                role1, role2,
-                                &firstCred, &secondCred);
-            VERIFY_SUCCESS_RETURN(TAG, (res == OC_STACK_OK), ERROR, OC_STACK_ERROR);
+                    &firstDevice->doxm->deviceID, (NULL != secondDevice) ? &secondDevice->doxm->deviceID : &provTooldeviceID,
+                    role1, role2,
+                    &firstCred, &secondCred);
+            VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
             OIC_LOG(INFO, TAG, "Credentials generated successfully");
-
-            credData->deviceInfo[0] = pDev1;
-            credData->deviceInfo[1] = pDev2;
-            credData->credInfo[0] = firstCred;
+            CredentialData_t *credData =
+                (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
+            if (NULL == credData)
+            {
+                OICFree(firstCred);
+                OICFree(secondCred);
+                OIC_LOG(ERROR, TAG, "Memory allocation problem");
+                return OC_STACK_NO_MEMORY;
+            }
+            credData->deviceInfo[0] = firstDevice;
+            credData->deviceInfo[1] = secondDevice;
             credData->credInfo[1] = secondCred;
             credData->ctx = ctx;
-            credData->currIndex = 0;
+            credData->credInfo[0] = firstCred;
             credData->numOfResults = 0;
             credData->resultCallback = resultCallback;
             // first call to provision creds to device1.
             // second call to provision creds to device2.
             int noOfRiCalls = 2;
             credData->resArr =
-                (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+                (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
             if (NULL == credData->resArr)
             {
                 OICFree(firstCred);
@@ -1236,18 +1431,16 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
                 return OC_STACK_NO_MEMORY;
             }
-
-            res = SetDOS(data, DOS_RFPRO, ProvisionPskCB);
-
+            res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
             if (OC_STACK_OK != res)
             {
                 DeleteCredList(firstCred);
                 DeleteCredList(secondCred);
-                FreeData(data);
-                OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
-                return res;
+                OICFree(credData->resArr);
+                OICFree(credData);
             }
-            OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d", res);
+            OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
+            VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
             return res;
         }
         case SIGNED_ASYMMETRIC_KEY:
@@ -1258,7 +1451,6 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
             /* pemCert is the cerficiate to be provisioned */
             VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR, OC_STACK_INVALID_PARAM);
 
-            data->type = CERT_TYPE;
             OicSecKey_t deviceCert = { 0 };
             deviceCert.data = (uint8_t*) pemCert; /* Casting away const is OK here */
             deviceCert.len = strlen(pemCert) + 1;
@@ -1281,10 +1473,10 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
                 cred->credUsage = OICStrdup(PRIMARY_CERT);
             }
 
-            if (NULL == cred->credUsage)
+            /* Create credential data (used by the response handler provisionCertificateCB and freed there) */
+            CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t));
+            if ((NULL == credData) || (NULL == cred->credUsage))
             {
-                OICFree(credData);
-                OICFree(data);
                 DeleteCredList(cred);
                 OIC_LOG(ERROR, TAG, "Memory allocation problem");
                 return OC_STACK_NO_MEMORY;
@@ -1298,13 +1490,11 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
             credData->resultCallback = resultCallback;
             credData->resArr = NULL;
 
-            /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls ResultCallback */
-            // TODO update flow with DOS
-            OCStackResult res = provisionCredentials(ctx, cred, pDev1, &provisionCertificateCB);
-            if (OC_STACK_OK != res)
+            /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls resultCallback */
+            OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionCertificateCB);
+            if (res != OC_STACK_OK)
             {
                 OICFree(credData);
-                OICFree(data);
             }
 
             DeleteCredList(cred);
@@ -1317,6 +1507,135 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k
         }
     }
 }
+
+OCStackResult SRPProvisionCredentialsDos(void *ctx, OicSecCredType_t type, size_t keySize,
+                                      const OCProvisionDev_t *pDev1,
+                                      const OCProvisionDev_t *pDev2,
+                                      OCProvisionResultCB resultCallback)
+{
+    VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
+    if (!resultCallback)
+    {
+        OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos: NULL Callback");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+    if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
+        (NULL != pDev2) &&
+        (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
+    {
+        OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : Same device ID");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (SYMMETRIC_PAIR_WISE_KEY == type && NULL == pDev2)
+    {
+        OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : NULL device");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (SYMMETRIC_PAIR_WISE_KEY == type &&
+       !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
+    {
+        OIC_LOG(INFO, TAG, "Invalid key size");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OIC_LOG(INFO, TAG, "In SRPProvisionCredentialsDos");
+
+    if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
+    {
+        bool linkExisits = true;
+        OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
+
+        if (res != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "Internal error occured");
+            return res;
+        }
+        if (linkExisits)
+        {
+            OIC_LOG(ERROR, TAG, "Link already exists");
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+
+    OicUuid_t provTooldeviceID =   {{0,}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+    {
+        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG(INFO, TAG, "retrieved deviceid");
+
+    CredentialData_t *credData = (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
+    Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
+    if (NULL == credData || NULL == data)
+    {
+
+        OICFree(credData);
+        OICFree(data);
+        OIC_LOG(ERROR, TAG, "Memory allocation problem");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    data->ctx = credData;
+
+    switch (type)
+    {
+        case SYMMETRIC_PAIR_WISE_KEY:
+        {
+            data->type = PSK_TYPE;
+            OicSecCred_t *firstCred = NULL;
+            OicSecCred_t *secondCred = NULL;
+            OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
+                                &pDev1->doxm->deviceID, (NULL != pDev2) ? &pDev2->doxm->deviceID :
+                                &provTooldeviceID,
+                                NULL, NULL,
+                                &firstCred, &secondCred);
+            VERIFY_SUCCESS_RETURN(TAG, (res == OC_STACK_OK), ERROR, OC_STACK_ERROR);
+            OIC_LOG(INFO, TAG, "Credentials generated successfully");
+
+            credData->deviceInfo[0] = pDev1;
+            credData->deviceInfo[1] = pDev2;
+            credData->credInfo[0] = firstCred;
+            credData->credInfo[1] = secondCred;
+            credData->ctx = ctx;
+            credData->currIndex = 0;
+            credData->numOfResults = 0;
+            credData->resultCallback = resultCallback;
+            // first call to provision creds to device1.
+            // second call to provision creds to device2.
+            int noOfRiCalls = 2;
+            credData->resArr =
+                (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+            if (NULL == credData->resArr)
+            {
+                OICFree(firstCred);
+                OICFree(secondCred);
+                OICFree(credData);
+                OIC_LOG(ERROR, TAG, "Memory allocation problem");
+                return OC_STACK_NO_MEMORY;
+            }
+
+            res = SetDOS(data, DOS_RFPRO, ProvisionPskCB);
+
+            if (OC_STACK_OK != res)
+            {
+                DeleteCredList(firstCred);
+                DeleteCredList(secondCred);
+                FreeData(data);
+                OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
+                return res;
+            }
+            OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d", res);
+            return res;
+        }
+        default:
+        {
+            OIC_LOG(ERROR, TAG, "Invalid option.");
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+}
 /**
  * Callback for ACL provisioning.
  */