Modify OTM & SRM to resolve gap in ownership transfer sequence.
authorleechul <chuls.lee@samsung.com>
Wed, 24 Feb 2016 00:29:35 +0000 (09:29 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Wed, 2 Mar 2016 08:16:37 +0000 (08:16 +0000)
According to OIC security spec B,
Current IoTivity security module(OTM/SRM) has gap in ownership transfer sequence.

This patch includes the following modifications to remove the gap :
  1. Modify to update the 'Owned' as TRUE after owner credential is determined.
  2. In case of PIN based OxM, We should not create a temporal credential.
     It will be handled directly in dtls layer.
     It means we should use another get_psk_info callback
     instead of GetDtlsPskCredentials during PIN based OxM.
  3. The PT(OBT) transmits the owner credential(OwnerPSK) directly to the client.
     The client will only need to verify recevied OwnerPSK.
  4. Modify to include the 'cm' when update pstat in end of security provisioning.

NOTE1 : Please refer to the Figure 9, Table 3 and Figure 10, Table 4 in Spec B.
NOTE2 : IMHO, The current spec B document is not perfect in implementation perspective.
So we've proposed a updated ownership transfer sequence in details through CR document.
And it is expected to be accepted.
We should be update again when spec document is released or CR codument is accepted.
Please keep this in mind.

[Patch #1] : Initial upload.
[Patch #2~#4] : Remove the compile errors and warnings.
[Patch #5] : Retrigger
[Patch #6] : Remove the compile error in doxmresource for arduino
[Patch #7] : Modify according to review comments.
[Patch #8~#9] : Retrigger

Change-Id: If88e7028b55d830d21643a915444a81dc912a948
Signed-off-by: leechul <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5149
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
Tested-by: Randeep Singh <randeep.s@samsung.com>
12 files changed:
resource/csdk/security/include/pinoxmcommon.h
resource/csdk/security/include/srmutility.h
resource/csdk/security/provisioning/include/oxm/oxmrandompin.h
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmjustworks.c
resource/csdk/security/provisioning/src/oxmrandompin.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/oxmpincommon.c
resource/csdk/security/src/srmutility.c
resource/provisioning/SConscript
resource/provisioning/examples/SConscript

index b4658ad..de15015 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef PIN_CALLBACK_DEF_H_
 #define PIN_CALLBACK_DEF_H_
 
+#include "securevirtualresourcetypes.h"
+#include "casecurityinterface.h"
+
 #ifdef __cplusplus
  extern "C" {
 #endif // __cplusplus
@@ -70,6 +73,32 @@ OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize);
  */
 OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
 
+#ifdef __WITH_DTLS__
+
+/**
+ * This function is used by OTM and SRM to
+ * register device UUID is required to derive the temporal PSK.
+ */
+void SetUuidForRandomPinOxm(const OicUuid_t* uuid);
+
+/**
+ * This internal callback is used while PIN based ownership transfer.
+ * This callback will be used to establish a temporary secure session according to
+ * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256.
+ *
+ * @param[in]  type type of PSK data required by tinyDTLS layer during DTLS handshake.
+ * @param[in]  desc UNUSED.
+ * @param[in]  desc_len UNUSED.
+ * @param[out] result  Must be filled with the requested information.
+ * @param[in]  result_length  Maximum size of @p result.
+ *
+ * @return The number of bytes written to @p result or a value
+ *         less than zero on error.
+ */
+int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
+              const unsigned char *UNUSED1, size_t UNUSED2,
+              unsigned char *result, size_t result_length);
+#endif //__WITH_DTLS__
 
 #ifdef __cplusplus
 }
index d6861e3..80548f0 100644 (file)
@@ -114,6 +114,15 @@ OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter);
 OCStackResult AddUuidArray(cJSON* jsonRoot, const char* arrayItem,
                            size_t *numUuids, OicUuid_t** uuids );
 
+/**
+ * Function to getting string of ownership transfer method
+ *
+ * @prarm oxmType ownership transfer method
+ *
+ * @return string value of ownership transfer method
+ */
+const char* GetOxmString(OicSecOxm_t oxmType);
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index db5556f..5fa0a36 100644 (file)
@@ -31,8 +31,6 @@
 extern "C" {
 #endif // __cplusplus
 
-#define OXM_PBKDF2_ITERATIONS 1000
-
 /**
  * Callback implementation to input the PIN code from user.
  *
@@ -70,4 +68,4 @@ char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx);
 #ifdef __cplusplus
 }
 #endif
-#endif //OXM_RANDOM_PIN_H_
\ No newline at end of file
+#endif //OXM_RANDOM_PIN_H_
index 66c9179..210030c 100644 (file)
@@ -85,24 +85,6 @@ static size_t gNumOfProvisioningMethodsPT = 1;
 static OTMContext_t* g_otmCtx = NULL;
 
 /**
- * Function to getting string of ownership transfer method
- */
-static const char* GetOxmString(OicSecOxm_t oxmType)
-{
-    switch(oxmType)
-    {
-        case OIC_JUST_WORKS:
-            return OXM_JUST_WORKS;
-        case OIC_RANDOM_DEVICE_PIN:
-            return OXM_RANDOM_DEVICE_PIN;
-        case OIC_MANUFACTURER_CERTIFICATE:
-            return OXM_MANUFACTURER_CERTIFICATE;
-        default:
-            return NULL;
-    }
-}
-
-/**
  * Function to select appropriate  provisioning method.
  *
  * @param[in] supportedMethods   Array of supported methods
@@ -165,10 +147,23 @@ static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
             break;
         }
     }
+    OIC_LOG_V(DEBUG, TAG, "Selected Operation Mode = %d", *selectedMode);
+
     OIC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
 }
 
 /**
+ * Function to start ownership transfer.
+ * This function will send the first request for provisioning,
+ * The next request message is sent from the response handler for this request.
+ *
+ * @param[in] ctx   context value passed to callback from calling function.
+ * @param[in] selectedDevice   selected device information to performing provisioning.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
+
+/**
  * Function to update owner transfer mode
  *
  * @param[in]  otmCtx  Context value of ownership transfer.
@@ -186,35 +181,50 @@ static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
 
 
 /**
- * Function to send ownerShip info. This function would update Owned as true and
- * owner as UUID for provisioning tool
+ * Function to send  uuid of owner device to new device.
+ * This function would update 'owner of doxm' as UUID for provisioning tool.
  *
  * @param[in]  otmCtx  Context value of ownership transfer.
  * @return  OC_STACK_OK on success
  */
-static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
+static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx);
 
 /**
  * Function to update the operation mode. As per the spec. Operation mode in client driven
  * single service provisioning it will be updated to 0x3
  *
  * @param[in]  otmCtx  Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx);
+
+/**
+ * Function to update the owner credential to new device
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
  * @param[in] selectedOperationMode selected operation mode
  * @return  OC_STACK_OK on success
  */
-static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
-                                    OicSecDpom_t selectedOperationMode);
+static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx);
 
 /**
- * Function to start ownership transfer.
- * This function will send the first request for provisioning,
- * The next request message is sent from the response handler for this request.
+ * Function to send ownerShip info.
+ * This function would update 'owned of doxm' as true.
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
+
+/**
+ * Function to update pstat when finalize provisioning.
+ * This function would update 'cm' as bx0011,1100 and 'tm' as bx0000,0000.
  *
  * @param[in] ctx   context value passed to callback from calling function.
  * @param[in] selectedDevice   selected device information to performing provisioning.
  * @return  OC_STACK_OK on success
  */
-static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
+static OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx);
 
 /*
  * Function to finalize provisioning.
@@ -225,6 +235,7 @@ static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selecte
  */
 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
 
+
 static bool IsComplete(OTMContext_t* otmCtx)
 {
     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
@@ -256,6 +267,17 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
 
     if(otmCtx->selectedDeviceInfo)
     {
+        //Revert psk_info callback and new deivce uuid in case of random PIN OxM
+        if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+        {
+            if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
+            {
+                OIC_LOG(WARNING, TAG, "Failed to revert  is DTLS credential handler.");
+            }
+            OicUuid_t emptyUuid = { .id={0}};
+            SetUuidForRandomPinOxm(&emptyUuid);
+        }
+
         for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
         {
             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
@@ -312,15 +334,13 @@ void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
            sizeof(endpoint->addr)) == 0 &&
            g_otmCtx->selectedDeviceInfo->securePort == endpoint->port)
         {
-            OCStackResult res;
-
-            CARegisterDTLSHandshakeCallback(NULL);
+            OCStackResult res = OC_STACK_ERROR;
 
             //In case of success, send next coaps request.
             if(CA_STATUS_OK == info->result)
             {
-                //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
-                res = PutOwnershipInformation(g_otmCtx);
+                //Send request : PUT /oic/sec/doxm [{... , "devowner":"PT's UUID"}]
+                res = PutOwnerUuid(g_otmCtx);
                 if(OC_STACK_OK != res)
                 {
                     OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
@@ -335,13 +355,14 @@ void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
 
                 if(g_otmCtx->selectedDeviceInfo->doxm->oxmSel == OIC_RANDOM_DEVICE_PIN)
                 {
+                    /*
                     res = RemoveCredential(&g_otmCtx->subIdForPinOxm);
                     if(OC_STACK_RESOURCE_DELETED != res)
                     {
                         OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
                         SetResult(g_otmCtx, res);
                         return;
-                    }
+                    }*/
 
                     if(WRONG_PIN_MAX_ATTEMP > g_otmCtx->attemptCnt)
                     {
@@ -396,10 +417,10 @@ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
     //Generating OwnerPSK
     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
-            strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
-            sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
-            sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
-            OWNER_PSK_LENGTH_128);
+            strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
+            ptDeviceID.id, sizeof(ptDeviceID.id),
+            selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
+            ownerPSK, OWNER_PSK_LENGTH_128);
 
     if (CA_STATUS_OK == pskRet)
     {
@@ -525,11 +546,10 @@ static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
         otmCtx->selectedDeviceInfo->pstat = pstat;
 
         //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
-        OicSecDpom_t selectedOperationMode;
-        SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
+        SelectOperationMode(otmCtx->selectedDeviceInfo, &(otmCtx->selectedDeviceInfo->pstat->om));
 
-        //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
-        OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
+        //Send request : PUT /oic/sec/pstat [{"om":"bx11", .. }]
+        OCStackResult res = PutUpdateOperationMode(otmCtx);
         if (OC_STACK_OK != res)
         {
             OIC_LOG(ERROR, TAG, "Error while updating operation mode.");
@@ -549,7 +569,7 @@ exit:
 }
 
 /**
- * Callback handler for OwnershipInformationHandler API.
+ * Response handler for update owner uuid request.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
  * @param[in] UNUSED          handle to an invocation
@@ -557,13 +577,13 @@ exit:
  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
  */
-static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
+static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNUSED,
                                 OCClientResponse *clientResponse)
 {
     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
     VERIFY_NON_NULL(TAG, ctx, WARNING);
 
-    OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+    OIC_LOG(DEBUG, TAG, "IN OwnerUuidUpdateHandler");
     (void)UNUSED;
     OCStackResult res = OC_STACK_OK;
     OTMContext_t* otmCtx = (OTMContext_t*)ctx;
@@ -572,64 +592,33 @@ static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandl
     {
         if(otmCtx && otmCtx->selectedDeviceInfo)
         {
-            if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
-            {
-                res = RemoveCredential(&otmCtx->subIdForPinOxm);
-                if(OC_STACK_RESOURCE_DELETED != res)
-                {
-                    OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
-                    return OC_STACK_DELETE_TRANSACTION;
-                }
-            }
-
             res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
             if(OC_STACK_OK != res)
             {
-                OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
+                OIC_LOG(ERROR, TAG, "OwnerUuidUpdateHandler:Failed to owner PSK generation");
                 SetResult(otmCtx, res);
                 return OC_STACK_DELETE_TRANSACTION;
             }
 
-            CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
-            endpoint->port = otmCtx->selectedDeviceInfo->securePort;
-            CAResult_t caResult = CACloseDtlsSession(endpoint);
-            if(CA_STATUS_OK != caResult)
-            {
-                OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
-                SetResult(otmCtx, caResult);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-
-            /**
-             * If we select NULL cipher,
-             * client will select appropriate cipher suite according to server's cipher-suite list.
-             */
-            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);
-            if(CA_STATUS_OK != caResult)
-            {
-                OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
-                SetResult(otmCtx, caResult);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-
-            OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
-            OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
-
-            res = FinalizeProvisioning(otmCtx);
+            //PUT owner credential to new device according to security spec B.
+            res = PutOwnerCredential(otmCtx);
             if(OC_STACK_OK != res)
             {
+                OIC_LOG(ERROR, TAG,
+                        "OwnerUuidUpdateHandler:Failed to send PUT request for onwer credential");
                 SetResult(otmCtx, res);
+                return OC_STACK_DELETE_TRANSACTION;
             }
         }
     }
     else
     {
         res = clientResponse->result;
-        OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
+        OIC_LOG_V(ERROR, TAG, "OwnerUuidHandler : Unexpected result %d", res);
         SetResult(otmCtx, res);
     }
 
-    OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+    OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
 
 exit:
     return  OC_STACK_DELETE_TRANSACTION;
@@ -698,6 +687,260 @@ exit:
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
+/**
+ * Response handler for update owner crendetial request.
+ *
+ * @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 OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
+    (void)UNUSED;
+    OCStackResult res = OC_STACK_OK;
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+
+    if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+    {
+        if(otmCtx && otmCtx->selectedDeviceInfo)
+        {
+            //PUT /oic/sec/doxm [{ ..., "owned":"TRUE" }]
+            res = PutOwnershipInformation(otmCtx);
+            if(OC_STACK_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "Failed to put ownership information to new device");
+                SetResult(otmCtx, res);
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+        }
+    }
+    else
+    {
+        res = clientResponse->result;
+        OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
+        SetResult(otmCtx, res);
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
+
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+
+/**
+ * Response handler for update owner information request.
+ *
+ * @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 OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+    (void)UNUSED;
+    OCStackResult res = OC_STACK_OK;
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+
+    if(OC_STACK_OK == clientResponse->result)
+    {
+        if(otmCtx && otmCtx->selectedDeviceInfo)
+        {
+            OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
+            OIC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
+
+            res = PutProvisioningStatus(otmCtx);
+            if(OC_STACK_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "Failed to update pstat");
+                SetResult(otmCtx, res);
+            }
+        }
+    }
+    else
+    {
+        res = clientResponse->result;
+        OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
+        SetResult(otmCtx, res);
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Response handler of update provisioning status.
+ *
+ * @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 ProvisioningStatusHandler(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "IN ProvisioningStatusHandler.");
+
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    (void)UNUSED;
+    if(OC_STACK_OK == clientResponse->result)
+    {
+        OCStackResult res = FinalizeProvisioning(otmCtx);
+         if (OC_STACK_OK != res)
+         {
+                OIC_LOG_V(INFO, TAG, "Failed to finalize provisioning.");
+                SetResult(otmCtx, res);
+                return OC_STACK_DELETE_TRANSACTION;
+         }
+    }
+
+exit:
+    OIC_LOG_V(INFO, TAG, "OUT ProvisioningStatusHandler.");
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of finalize provisioning.
+ *
+ * @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 FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
+
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+    OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+    (void)UNUSED;
+
+    if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+    {
+        OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
+         if (OC_STACK_OK == res)
+         {
+                OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
+                SetResult(otmCtx, OC_STACK_OK);
+                return OC_STACK_DELETE_TRANSACTION;
+         }
+          else
+         {
+              OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
+         }
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
+                            clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackResult PutOwnerCredential(OTMContext_t* otmCtx)
+{
+    OIC_LOG(DEBUG, TAG, "IN PutOwnerCredential");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        OIC_LOG(ERROR, TAG, "Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    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, "PutOwnerCredential : Failed to generate query");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    //Generate owner credential for new device
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    OicSecCred_t* ownerCredential =
+        GetCredResourceData(&(deviceInfo->doxm->deviceID));
+    if(!ownerCredential)
+    {
+        OIC_LOG(ERROR, TAG, "Can not find OwnerPSK.");
+        return OC_STACK_NO_RESOURCE;
+    }
+
+    OicUuid_t credSubjectId = {.id={0}};
+    if(OC_STACK_OK == GetDoxmDeviceID(&credSubjectId))
+    {
+        OicSecCred_t newCredential;
+        memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
+        newCredential.next = NULL;
+        memcpy(&(newCredential.subject), &credSubjectId, sizeof(OicUuid_t));
+
+        //Send owner credential to new device : PUT /oic/sec/cred [ owner credential ]
+        secPayload->securityData = BinToCredJSON(&newCredential);
+        if (NULL == secPayload->securityData)
+        {
+            OICFree(secPayload);
+            OIC_LOG(ERROR, TAG, "Error while converting bin to json");
+            return OC_STACK_ERROR;
+        }
+        OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
+
+        OCCallbackData cbData;
+        cbData.cb = &OwnerCredentialHandler;
+        cbData.context = (void *)otmCtx;
+        cbData.cd = NULL;
+        OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
+                                         &deviceInfo->endpoint, (OCPayload*)secPayload,
+                                         deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+        if (res != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "OCStack resource error");
+        }
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
+        return OC_STACK_NO_RESOURCE;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT PutOwnerCredential");
+
+    return OC_STACK_OK;
+}
 
 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
 {
@@ -736,7 +979,6 @@ static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
         OIC_LOG(ERROR, TAG, "Error while converting bin to json");
         return OC_STACK_ERROR;
     }
-    OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
 
     OCCallbackData cbData;
     cbData.cb = &OwnerTransferModeHandler;
@@ -793,6 +1035,62 @@ static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
     return res;
 }
 
+static OCStackResult PutOwnerUuid(OTMContext_t* otmCtx)
+{
+    OIC_LOG(DEBUG, TAG, "IN PutOwnerUuid");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        OIC_LOG(ERROR, TAG, "Invailed parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if(!PMGenerateQuery(true,
+                        deviceInfo->endpoint.addr, deviceInfo->securePort,
+                        deviceInfo->connType,
+                        query, sizeof(query), OIC_RSRC_DOXM_URI))
+    {
+        OIC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+    //PUT PT's uuid to new device
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData =
+        g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(otmCtx);
+    if (NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
+        return OC_STACK_INVALID_PARAM;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
+
+    OCCallbackData cbData;
+    cbData.cb = &OwnerUuidUpdateHandler;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+
+    OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+                                     deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT PutOwnerUuid");
+
+    return res;
+}
 
 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
 {
@@ -817,21 +1115,22 @@ static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
 
     //OwnershipInformationHandler
-    OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
     if(!secPayload)
     {
         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
         return OC_STACK_NO_MEMORY;
     }
-    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-    secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
+
+    otmCtx->selectedDeviceInfo->doxm->owned = true;
+    secPayload->securityData = BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
     if (NULL == secPayload->securityData)
     {
         OICFree(secPayload);
         OIC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
         return OC_STACK_INVALID_PARAM;
     }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
 
     OCCallbackData cbData;
     cbData.cb = &OwnershipInformationHandler;
@@ -850,8 +1149,7 @@ static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
     return res;
 }
 
-static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
-                                    OicSecDpom_t selectedOperationMode)
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx)
 {
     OIC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
 
@@ -872,8 +1170,6 @@ static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
     }
     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
 
-    deviceInfo->pstat->om = selectedOperationMode;
-
     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
     if(!secPayload)
     {
@@ -1048,122 +1344,70 @@ error:
 
 }
 
-/**
- * Callback handler of SRPFinalizeProvisioning.
- *
- * @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 FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
-                                                       OCClientResponse *clientResponse)
+OCStackResult PutProvisioningStatus(OTMContext_t* otmCtx)
 {
-    OIC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
-
-    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
-    VERIFY_NON_NULL(TAG, ctx, ERROR);
+    OIC_LOG(INFO, TAG, "IN PutProvisioningStatus");
 
-    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-    (void)UNUSED;
-    if(OC_STACK_OK == clientResponse->result)
+    if(!otmCtx)
     {
-        OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
-
-         if (OC_STACK_OK == res)
-         {
-                OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
-                SetResult(otmCtx, OC_STACK_OK);
-                return OC_STACK_DELETE_TRANSACTION;
-         }
-         else
-         {
-              OIC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
-         }
+        OIC_LOG(ERROR, TAG, "OTMContext is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(!otmCtx->selectedDeviceInfo)
+    {
+        OIC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
+        OICFree(otmCtx);
+        return OC_STACK_INVALID_PARAM;
     }
-exit:
-    return OC_STACK_DELETE_TRANSACTION;
-}
-
-/**
- * Callback handler of default ACL provisioning.
- *
- * @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 ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
-                                                       OCClientResponse *clientResponse)
-{
-    OIC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
-
-    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
-    VERIFY_NON_NULL(TAG, ctx, ERROR);
-
-    OTMContext_t* otmCtx = (OTMContext_t*) ctx;
-    (void)UNUSED;
 
-    if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+    otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
+    otmCtx->selectedDeviceInfo->pstat->cm = PROVISION_ACLS | PROVISION_CREDENTIALS |
+                                            SECURITY_MANAGEMENT_SERVICES | BOOTSTRAP_SERVICE;
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
     {
-        OIC_LOG_V(INFO, TAG, "Staring commit hash task.");
-        // TODO hash currently have fixed value 0.
-        uint16_t aclHash = 0;
-        otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
-        otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
-        OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
-        if(!secPayload)
-        {
-            OIC_LOG(ERROR, TAG, "Failed to memory allocation");
-            return OC_STACK_NO_MEMORY;
-        }
-        secPayload->base.type = PAYLOAD_TYPE_SECURITY;
-        secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
-        if (NULL == secPayload->securityData)
-        {
-            OICFree(secPayload);
-            SetResult(otmCtx, OC_STACK_INVALID_JSON);
-            return OC_STACK_DELETE_TRANSACTION;
-        }
-        OIC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
-
-        char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
-        if(!PMGenerateQuery(true,
-                            otmCtx->selectedDeviceInfo->endpoint.addr,
-                            otmCtx->selectedDeviceInfo->securePort,
-                            otmCtx->selectedDeviceInfo->connType,
-                            query, sizeof(query), OIC_RSRC_PSTAT_URI))
-        {
-            OIC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
-            return OC_STACK_ERROR;
-        }
-        OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
+    if (NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        SetResult(otmCtx, OC_STACK_INVALID_JSON);
+        return OC_STACK_INVALID_JSON;
+    }
+    OIC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
 
-        OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
-        cbData.cb = &FinalizeProvisioningCB;
-        cbData.context = (void*)otmCtx;
-        cbData.cd = NULL;
-        OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
-                otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
-        OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
-        if (ret != OC_STACK_OK)
-        {
-            OIC_LOG(ERROR, TAG, "OCStack resource error");
-            SetResult(otmCtx, ret);
-        }
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if(!PMGenerateQuery(true,
+                        otmCtx->selectedDeviceInfo->endpoint.addr,
+                        otmCtx->selectedDeviceInfo->securePort,
+                        otmCtx->selectedDeviceInfo->connType,
+                        query, sizeof(query), OIC_RSRC_PSTAT_URI))
+    {
+        OIC_LOG(ERROR, TAG, "PutProvisioningStatus : Failed to generate query");
+        return OC_STACK_ERROR;
     }
-    else
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+    OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = &ProvisioningStatusHandler;
+    cbData.context = (void*)otmCtx;
+    cbData.cd = NULL;
+    OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+            otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    OIC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
+    if (ret != OC_STACK_OK)
     {
-        OIC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
-                            clientResponse->result);
-        SetResult(otmCtx, clientResponse->result);
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        SetResult(otmCtx, ret);
     }
-exit:
-    return OC_STACK_DELETE_TRANSACTION;
-}
 
+    OIC_LOG(INFO, TAG, "OUT PutProvisioningStatus");
+
+    return ret;
+}
 
 OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
 {
@@ -1249,7 +1493,7 @@ OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
     OIC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
 
     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
-    cbData.cb = &ProvisionDefaultACLCB;
+    cbData.cb = &FinalizeProvisioningCB;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
     OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
index 07d0244..ca65bdd 100644 (file)
@@ -58,7 +58,6 @@ char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx)
         return NULL;
     }
     memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
-    otmCtx->selectedDeviceInfo->doxm->owned = true;
 
     return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
 }
index 8af7ce7..e10f343 100644 (file)
@@ -47,14 +47,6 @@ char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx)
 
     otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RANDOM_DEVICE_PIN;
 
-    OicUuid_t uuidPT = {.id={0}};
-    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
-    {
-        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
-        return NULL;
-    }
-    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id, UUID_LENGTH);
-
     return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
 }
 
@@ -73,7 +65,6 @@ char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx)
         return NULL;
     }
     memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
-    otmCtx->selectedDeviceInfo->doxm->owned = true;
 
     return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
 }
@@ -94,21 +85,19 @@ OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx)
         return res;
     }
 
-    OicUuid_t deviceUUID = {.id={0}};
-    if (OC_STACK_OK != GetDoxmDeviceID(&deviceUUID))
+    /**
+     * Since PSK will be used directly while PIN based ownership transfer,
+     * Credential should not be saved into SVR.
+     * For this reason, We will use a temporary get_psk_info callback to random PIN OxM.
+     */
+    if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm))
     {
-        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
-        return OC_STACK_ERROR;
+        OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
+        res = OC_STACK_ERROR;
     }
 
-    res = AddTmpPskWithPIN(&otmCtx->selectedDeviceInfo->doxm->deviceID,
-                           SYMMETRIC_PAIR_WISE_KEY,
-                           (char*)pinData, OXM_RANDOM_PIN_SIZE,
-                           1, &deviceUUID, &otmCtx->subIdForPinOxm);
-    if(res != OC_STACK_OK)
-    {
-        OIC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
-    }
+    //Set the device id to derive temporal PSK
+    SetUuidForRandomPinOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
 
     return res;
 }
@@ -159,3 +148,4 @@ OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx)
 
     return OC_STACK_OK;
 }
+
index 68f0eb0..35663d1 100644 (file)
@@ -36,6 +36,8 @@
 #include "pbkdf2.h"
 #include <stdlib.h>
 #include "iotvticalendar.h"
+#include "ocserverrequest.h"
+
 #ifdef WITH_ARDUINO
 #include <string.h>
 #else
@@ -658,6 +660,145 @@ OCStackResult RemoveAllCredentials(void)
     return OC_STACK_OK;
 }
 
+#ifdef __WITH_DTLS__
+/**
+ * Internal function to verify recevied owner PSK.
+ *
+ * @param receviedCred recevied Owner Credential from OBT(PT)
+ * @param ownerAdd address of OBT(PT)
+ * @param doxm current device's doxm resource
+ *
+ * @retval
+ *     true valid ower psk
+ *     false Invalid owner psk or failed to owner psk verification
+ */
+static bool isValidOwnerPSK(const OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
+                           const OicSecDoxm_t* doxm)
+{
+    //Decode received PSK to verify OwnerPSKs match
+    uint32_t privLen = strlen(receviedCred->privateData.data);
+    size_t b64BufSize = B64DECODE_OUT_SAFESIZE((privLen + 1) * sizeof(char));
+    uint8_t* decodeBuff = OICMalloc(b64BufSize);
+    VERIFY_NON_NULL(TAG, decodeBuff, ERROR);
+    uint32_t decodedSize = 0;
+    B64Result b64Ret = b64Decode(receviedCred->privateData.data, privLen,
+                                 decodeBuff, b64BufSize, &decodedSize);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+    //Derive OwnerPSK locally
+    const char* oxmLabel = GetOxmString(doxm->oxmSel);
+    VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
+
+    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
+    CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
+        (uint8_t*)oxmLabel, strlen(oxmLabel),
+        doxm->owner.id, sizeof(doxm->owner.id),
+        doxm->deviceID.id, sizeof(doxm->deviceID.id),
+        ownerPSK, OWNER_PSK_LENGTH_128);
+    VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+
+    OIC_LOG_V(DEBUG, TAG, "Oxm Label = %s", oxmLabel);
+    OIC_LOG_V(DEBUG, TAG, "PSK size compare : %s",
+              OWNER_PSK_LENGTH_128 == decodedSize ? "TRUE" : "FALSE");
+    OIC_LOG_V(DEBUG, TAG, "SubjectID compare = %s",
+              memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 ?
+              "TRUE" : "FALSE");
+    OIC_LOG_V(DEBUG, TAG, "Owner PSK compare = %s",
+              memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 ? "TRUE" : "FALSE");
+
+    //Verify OwnerPSKs match
+    return (OWNER_PSK_LENGTH_128 == decodedSize &&
+            memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 &&
+            memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0);
+exit:
+    return false;
+}
+
+#endif //__WITH_DTLS__
+
+static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+
+    //Get binary representation of json
+    OicSecCred_t * cred  = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
+
+    if(cred)
+    {
+#ifdef __WITH_DTLS__
+        OicUuid_t emptyUuid = {.id={0}};
+        const OicSecDoxm_t* doxm = GetDoxmResourceData();
+        if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
+        {
+            //in case of owner PSK
+            switch(cred->credType)
+            {
+                case SYMMETRIC_PAIR_WISE_KEY:
+                {
+                    OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
+                    if(isValidOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
+                    {
+                        OIC_LOG(ERROR, TAG, "OwnerPKS is matched");
+                        if(OC_STACK_OK == AddCredential(cred))
+                        {
+                            ret = OC_EH_RESOURCE_CREATED;
+                        }
+                        else
+                        {
+                            OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
+                            ret = OC_EH_ERROR;
+                        }
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
+                        ret = OC_EH_ERROR;
+                    }
+
+                    break;
+                }
+                case SYMMETRIC_GROUP_KEY:
+                case ASYMMETRIC_KEY:
+                case SIGNED_ASYMMETRIC_KEY:
+                case PIN_PASSWORD:
+                case ASYMMETRIC_ENCRYPTION_KEY:
+                {
+                    OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
+                    ret = OC_EH_ERROR;
+                    break;
+                }
+                default:
+                {
+                    OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
+                    ret = OC_EH_ERROR;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            /*
+             * If the post request credential has credId, it will be
+             * discarded and the next available credId will be assigned
+             * to it before getting appended to the existing credential
+             * list and updating svr database.
+             */
+            ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
+        }
+#else //not __WITH_DTLS__
+        /*
+         * If the post request credential has credId, it will be
+         * discarded and the next available credId will be assigned
+         * to it before getting appended to the existing credential
+         * list and updating svr database.
+         */
+        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
+#endif//__WITH_DTLS__
+    }
+
+    return ret;
+}
+
 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
 {
     OCEntityHandlerResult ret = OC_EH_ERROR;
@@ -671,8 +812,9 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
         //discarded and the next available credId will be assigned
         //to it before getting appended to the existing credential
         //list and updating svr database.
-        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
+        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;\r
     }
+
     return ret;
 }
 
@@ -742,6 +884,9 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
             case OC_REST_GET:
                 ret = OC_EH_FORBIDDEN;
                 break;
+            case OC_REST_PUT:
+                ret = HandlePutRequest(ehRequest);
+                break;
             case OC_REST_POST:
                 ret = HandlePostRequest(ehRequest);
                 break;
@@ -967,62 +1112,6 @@ int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
     return ret;
 }
 
-/**
- * Add temporal PSK to PIN based OxM
- *
- * @param[in] tmpSubject UUID of target device
- * @param[in] credType Type of credential to be added
- * @param[in] pin numeric characters
- * @param[in] pinSize length of 'pin'
- * @param[in] ownersLen Number of owners
- * @param[in] owners Array of owners
- * @param[out] tmpCredSubject Generated credential's subject.
- *
- * @return OC_STACK_OK for success and errorcode otherwise.
- */
-OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
-                            const char * pin, size_t pinSize,
-                            size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
-{
-    OCStackResult ret = OC_STACK_ERROR;
-
-    if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
-    int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
-                                              UUID_LENGTH, PBKDF_ITERATIONS,
-                                              OWNER_PSK_LENGTH_128, privData);
-    VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
-
-    uint32_t outLen = 0;
-    char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
-    B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
-                                sizeof(base64Buff), &outLen);
-    VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
-
-    OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
-                                            base64Buff, ownersLen, owners);
-    if(NULL == cred)
-    {
-        OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
-        return OC_STACK_ERROR;
-    }
-
-    memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
-
-    ret = AddCredential(cred);
-    if( OC_STACK_OK != ret)
-    {
-        OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
-    }
-
-exit:
-    return ret;
-}
-
 #endif /* __WITH_DTLS__ */
 #ifdef __WITH_X509__
 #define CERT_LEN_PREFIX (3)
index cd2cae0..22688d6 100644 (file)
@@ -460,53 +460,6 @@ static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest
     return ehRet;
 }
 
-#ifdef __WITH_DTLS__
-/*
- * Generating new credential for provisioning tool
- *
- * PSK generated by
- */
-static OCEntityHandlerResult AddOwnerPSK(const CAEndpoint_t* endpoint,
-                    OicSecDoxm_t* ptDoxm,
-                    const uint8_t* label, const size_t labelLen)
-{
-    size_t ownLen = 1;
-    uint32_t outLen = 0;
-    OicSecCred_t *cred = NULL;
-    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
-
-    CAResult_t pskRet = CAGenerateOwnerPSK(endpoint,
-        label, labelLen,
-        ptDoxm->owner.id, sizeof(ptDoxm->owner.id),
-        gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
-        ownerPSK, OWNER_PSK_LENGTH_128);
-
-    VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
-
-    char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
-    B64Result b64Ret = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, base64Buff,
-                    sizeof(base64Buff), &outLen);
-    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
-
-    OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  generating Credential");
-    cred = GenerateCredential(&ptDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
-                              NULL, base64Buff, ownLen, &ptDoxm->owner);
-    VERIFY_NON_NULL(TAG, cred, ERROR);
-
-    //Adding provisioning tool credential to cred Resource.
-    VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
-
-    gDoxm->owned = true;
-    gDoxm->oxmSel = ptDoxm->oxmSel;
-    memcpy(&(gDoxm->owner), &(ptDoxm->owner), sizeof(OicUuid_t));
-
-    return OC_EH_OK;
-
-exit:
-    return OC_EH_ERROR;
-}
-#endif //__WITH_DTLS__
-
 static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
 {
     OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing PUT request");
@@ -524,165 +477,183 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
         // Iotivity SRM ONLY supports OIC_JUST_WORKS now
         if (OIC_JUST_WORKS == newDoxm->oxmSel)
         {
-            /*
-             * If current state of the device is un-owned, enable
-             * anonymous ECDH cipher in tinyDTLS so that Provisioning
-             * tool can initiate JUST_WORKS ownership transfer process.
-             */
             if ((false == gDoxm->owned) && (false == newDoxm->owned))
             {
-                OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
-#ifdef __WITH_DTLS__
-                ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
-#endif //__WITH_DTLS__
-                goto exit;
-            }
-
-            /*
-             * When current state of the device is un-owned and Provisioning
-             * Tool is attempting to change the state to 'Owned' with a
-             * qualified value for the field 'Owner'
-             */
-            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
-                (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
-            {
                 /*
-                 * Generate OwnerPSK and create credential for Provisioning
-                 * tool with the generated OwnerPSK.
-                 * Update persistent storage and disable anonymous ECDH cipher
-                 *
+                 * If current state of the device is un-owned, enable
+                 * anonymous ECDH cipher in tinyDTLS so that Provisioning
+                 * tool can initiate JUST_WORKS ownership transfer process.
                  */
-#ifdef __WITH_DTLS__
-                OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
-
-                //Generating OwnerPSK
-                OIC_LOG (INFO, TAG, "Doxm EntityHandle  generating OwnerPSK");
-
-                //Generate new credential for provisioning tool
-                ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
-                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
-
-                VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
-
-                // Update new state in persistent storage
-                if (true == UpdatePersistentStorage(gDoxm))
+                if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                 {
-                    ehRet = OC_EH_OK;
+                    OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
+#ifdef __WITH_DTLS__
+                    ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
+#endif //__WITH_DTLS__
+                    goto exit;
                 }
                 else
                 {
-                    ehRet = OC_EH_ERROR;
+#ifdef __WITH_DTLS__
+                    //Save the owner's UUID to derive owner credential
+                    memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+
+//                    OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
+//                    //Generating OwnerPSK
+//                    OIC_LOG (INFO, TAG, "Doxm EntityHandle  generating OwnerPSK");
+//                    //Generate new credential for provisioning tool
+//                    ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+//                            (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
+//                    VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+
+                    // Update new state in persistent storage
+                    if (true == UpdatePersistentStorage(gDoxm))
+                    {
+                        ehRet = OC_EH_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
+                        ehRet = OC_EH_ERROR;
+                    }
 
                     /*
-                     * If persistent storage update failed, revert back the state
-                     * for global variable.
+                     * Disable anonymous ECDH cipher in tinyDTLS since device is now
+                     * in owned state.
                      */
-                    gDoxm->owned = false;
-                    gDoxm->oxmSel = 0;
-                    memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
-                }
-
-                /*
-                 * Disable anonymous ECDH cipher in tinyDTLS since device is now
-                 * in owned state.
-                 */
-                CAEnableAnonECDHCipherSuite(false);
+                    CAEnableAnonECDHCipherSuite(false);
 #ifdef __WITH_X509__
 #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
-                CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+                    CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
 #endif //__WITH_X509__
 #endif //__WITH_DTLS__
+                }
             }
         }
         else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
         {
-#ifdef __WITH_DTLS__
-            //this temp Credential ID is used to track temporal Cred Id
-            static OicUuid_t tmpCredId = {.id={0}};
-            static bool tmpCredGenFlag = false;
-#endif //__WITH_DTLS__
-
             if ((false == gDoxm->owned) && (false == newDoxm->owned))
             {
-#ifdef __WITH_DTLS__
-                CAEnableAnonECDHCipherSuite(false);
-                OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
-                CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
-
-                char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
-                if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+                /*
+                 * If current state of the device is un-owned, enable
+                 * anonymous ECDH cipher in tinyDTLS so that Provisioning
+                 * tool can initiate JUST_WORKS ownership transfer process.
+                 */
+                if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                 {
-                    if(tmpCredGenFlag)
+                    gDoxm->oxmSel = newDoxm->oxmSel;
+                    //Update new state in persistent storage
+                    if((UpdatePersistentStorage(gDoxm) == true))
                     {
-                       OIC_LOG(INFO, TAG, "Corrupted PSK is detected!!!");
-                       VERIFY_SUCCESS(TAG,
-                                      OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
-                                      ERROR);
+                        ehRet = OC_EH_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
+                        ehRet = OC_EH_ERROR;
                     }
 
-                    OCStackResult res = AddTmpPskWithPIN( &(newDoxm->owner), SYMMETRIC_PAIR_WISE_KEY,
-                                     ranPin, OXM_RANDOM_PIN_SIZE, 1, &(newDoxm->owner), &tmpCredId);
-                    VERIFY_SUCCESS(TAG, res == OC_STACK_OK, ERROR);
-                    tmpCredGenFlag = true;
-                    ehRet = OC_EH_OK;
-                }
-                else
-                {
-                    OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
-                    ehRet = OC_EH_ERROR;
-                }
-
-#endif //__WITH_DTLS__
-            }
-
-            /*
-             * When current state of the device is un-owned and Provisioning
-             * Tool is attempting to change the state to 'Owned' with a
-             * qualified value for the field 'Owner'
-             */
-            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
-                (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
-            {
 #ifdef __WITH_DTLS__
-                OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+                    CAResult_t caRes = CA_STATUS_OK;
 
-                //Remove Temporal Credential resource
-                if(tmpCredGenFlag)
-                {
-                    VERIFY_SUCCESS(TAG,
-                                   OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
-                                   ERROR);
-                    tmpCredGenFlag = false;
-                }
+                    caRes = CAEnableAnonECDHCipherSuite(false);
+                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+                    OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
 
-                //Generate new credential for provisioning tool
-                ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
-                                    (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
-                VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+                    caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
 
-                //Update new state in persistent storage
-                if((UpdatePersistentStorage(gDoxm) == true))
-                {
-                    ehRet = OC_EH_OK;
+                    char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
+                    if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+                    {
+                        //Set the device id to derive temporal PSK
+                        SetUuidForRandomPinOxm(&gDoxm->deviceID);
+
+                        /**
+                         * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
+                         * Credential should not be saved into SVR.
+                         * For this reason, use a temporary get_psk_info callback to random PIN OxM.
+                         */
+                        caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
+                        VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+
+                        ehRet = OC_EH_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
+                        ehRet = OC_EH_ERROR;
+                    }
+#endif //__WITH_DTLS__
                 }
                 else
                 {
-                    /*
-                     * If persistent storage update failed, revert back the state
-                     * for global variable.
-                     */
-                    gDoxm->owned = false;
-                    gDoxm->oxmSel = 0;
-                    memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
-                    ehRet = OC_EH_ERROR;
+#ifdef __WITH_DTLS__
+                    //Save the owner's UUID to derive owner credential
+                    memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
 
-                }
+//                    OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+//                    //Generate new credential for provisioning tool
+//                    ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
+//                                        (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
+//                    VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+
+                    //Update new state in persistent storage
+                    if((UpdatePersistentStorage(gDoxm) == true))
+                    {
+                        ehRet = OC_EH_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
+                        ehRet = OC_EH_ERROR;
+                    }
 #endif
-             }
+                }
+            }
+        }
+
+        /*
+         * When current state of the device is un-owned and Provisioning
+         * Tool is attempting to change the state to 'Owned' with a
+         * qualified value for the field 'Owner'
+         */
+        if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
+            (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
+        {
+            gDoxm->owned = true;
+            // Update new state in persistent storage
+            if (true == UpdatePersistentStorage(gDoxm))
+            {
+                ehRet = OC_EH_OK;
+            }
+            else
+            {
+                OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
+                ehRet = OC_EH_ERROR;
+            }
         }
     }
 
 exit:
+    if(OC_EH_OK != ehRet)
+    {
+        OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
+                            "DOXM will be reverted.");
+
+        /*
+         * If persistent storage update failed, revert back the state
+         * for global variable.
+         */
+        gDoxm->owned = false;
+        gDoxm->oxmSel = OIC_JUST_WORKS;
+        memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
+
+        if(!UpdatePersistentStorage(gDoxm))
+        {
+            OIC_LOG(ERROR, TAG, "Failed to revert DOXM in persistent storage");
+        }
+    }
 
     //Send payload to request originator
     if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
index 1aa0ac0..5652236 100644 (file)
  * limitations under the License.
  *
  * *****************************************************************/
+
+ #include <memory.h>
+
 #include "ocstack.h"
 #include "ocrandom.h"
 #include "logger.h"
 #include "pinoxmcommon.h"
+#include "pbkdf2.h"
+#include "securevirtualresourcetypes.h"
 
 #define TAG "PIN_OXM_COMMON"
 
 static GeneratePinCallback gGenPinCallback = NULL;
 static InputPinCallback gInputPinCallback = NULL;
 
+typedef struct PinOxmData {
+    uint8_t pinData[OXM_RANDOM_PIN_SIZE + 1];
+    OicUuid_t newDevice;
+}PinOxmData_t;
+
+static PinOxmData_t g_PinOxmData;
+
+
 void SetInputPinCB(InputPinCallback pinCB)
 {
     if(NULL == pinCB)
@@ -64,8 +77,10 @@ OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
     for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
     {
         pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
+        g_PinOxmData.pinData[i] = pinBuffer[i];
     }
     pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
+    g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
 
     if(gGenPinCallback)
     {
@@ -98,6 +113,8 @@ OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
     if(gInputPinCallback)
     {
         gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
+        memcpy(g_PinOxmData.pinData, pinBuffer, OXM_RANDOM_PIN_SIZE);
+        g_PinOxmData.pinData[OXM_RANDOM_PIN_SIZE] = '\0';
     }
     else
     {
@@ -108,3 +125,83 @@ OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
 
     return OC_STACK_OK;
 }
+
+#ifdef __WITH_DTLS__
+
+void SetUuidForRandomPinOxm(const OicUuid_t* uuid)
+{
+    if(NULL != uuid)
+    {
+        memcpy(g_PinOxmData.newDevice.id, uuid->id, UUID_LENGTH);
+    }
+}
+
+int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
+              const unsigned char *UNUSED1, size_t UNUSED2,
+              unsigned char *result, size_t result_length)
+{
+    int32_t ret = -1;
+
+    (void)UNUSED1;
+    (void)UNUSED2;
+
+    if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
+    {
+        return ret;
+    }
+
+    switch (type)
+    {
+        case CA_DTLS_PSK_HINT:
+        case CA_DTLS_PSK_IDENTITY:
+            /**
+             * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
+             *
+             * At this point, The server generate random hint and
+             * provide it to client through server key exchange message.
+             */
+            OCFillRandomMem(result, result_length);
+            ret = result_length;
+
+            OIC_LOG(DEBUG, TAG, "PSK HINT : ");
+            OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
+            break;
+
+        case CA_DTLS_PSK_KEY:
+            {
+                int dtlsRes = DeriveCryptoKeyFromPassword(
+                                                          (const unsigned char *)g_PinOxmData.pinData,
+                                                          OXM_RANDOM_PIN_SIZE,
+                                                          g_PinOxmData.newDevice.id,
+                                                          UUID_LENGTH, PBKDF_ITERATIONS,
+                                                          OWNER_PSK_LENGTH_128, (uint8_t*)result);
+
+                OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
+                OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
+                OIC_LOG(DEBUG, TAG, "UUID : ");
+                OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
+
+                if(0 == dtlsRes)
+                {
+                    ret = OWNER_PSK_LENGTH_128;
+                }
+                else
+                {
+                    OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result=%d", dtlsRes);
+                    ret = -1;
+                }
+            }
+            break;
+
+        default:
+            {
+                OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
+                ret = -1;
+            }
+            break;
+    }
+
+    return ret;
+}
+#endif //__WITH_DTLS__
+
index 1a745b8..9562664 100644 (file)
@@ -128,3 +128,26 @@ exit:
     return OC_STACK_ERROR;
 
 }
+
+/**
+ * Function to getting string of ownership transfer method
+ *
+ * @prarm oxmType ownership transfer method
+ *
+ * @return string value of ownership transfer method
+ */
+const char* GetOxmString(OicSecOxm_t oxmType)
+{
+    switch(oxmType)
+    {
+        case OIC_JUST_WORKS:
+            return OXM_JUST_WORKS;
+        case OIC_RANDOM_DEVICE_PIN:
+            return OXM_RANDOM_DEVICE_PIN;
+        case OIC_MANUFACTURER_CERTIFICATE:
+            return OXM_MANUFACTURER_CERTIFICATE;
+        default:
+            return NULL;
+    }
+}
+
index a7c035d..5908775 100644 (file)
@@ -27,9 +27,10 @@ ocprovision_env = env.Clone()
 ######################################################################
 ocprovision_env.AppendUnique(CPPPATH = [
                '../include/',
-        '../csdk/stack/include',
-        '../csdk/logger/include',
-        '../oc_logger/include',
+               '../csdk/stack/include',
+               '../csdk/logger/include',
+               '../oc_logger/include',
+               '../csdk/connectivity/api',
                '../csdk/security/include',
                '../csdk/security/provisioning/include',
                '../csdk/security/provisioning/include/oxm',
index 184a73a..3f182b5 100644 (file)
@@ -36,6 +36,7 @@ examples_env.AppendUnique(CPPPATH = [
         '../../csdk/stack/include',
         '../../csdk/logger/include',
         '../../oc_logger/include',
+        '../../csdk/connectivity/api',
         '../../csdk/security/include',
         '../../csdk/security/provisioning/include',
         '../../csdk/security/provisioning/include/oxm',