Add PIN based OxM for security provisioning
authorleechul <chuls.lee@samsung.com>
Mon, 10 Aug 2015 02:21:34 +0000 (11:21 +0900)
committerSachin Agrawal <sachin.agrawal@intel.com>
Mon, 17 Aug 2015 16:08:55 +0000 (16:08 +0000)
  1. Implement PIN based OxM according to OTM(Ownership Transfer Manager) callbacks.
  2. Add pbkdf2 implementation
  3. Modify doxmresource.c and credresource.c to support PIN based OxM.

NOTE1:This patch will include several compile warning and work around codes.
        It can be removed after the refactored PM and ECDHE_PSK cipher suite of tinydtls is merged
        into security-basecamp branch.
NOTE2:This patch will not working. Please code review only.

[Patch #1] Initial upload.
[Patch #2] Update codes according to comments.
[Patch #3] Update codes according to Mr.Shim's comments.
[Patch #4] Update codes according to Sakthivel's comment.
[Patch #5] Updated to remove arduino build failure
[Patch #6~8] Update code and scons script according to review comments.
[Patch #9] Delete unnecessary codes.
[Patch #10] Rebase
[Patch #11] Rebase
[Patch #12] Merge with refactored PM.
[Patch #13] Remove build error.
[Patch #14] Delete unnecessary files.
[Patch #15] Update according to comments.
            Remove the removable warnings.
[Patch #16] Update according to Shilpa's comments.
[Patch #18] Update according to Shilpa's comments.
[Patch #19] Refresh for rebuild.
[Patch #20] Refresh for rebuild since Jenkins Server issue is Fixed.

Change-Id: I1328db852a4a7e8225737719061b6c61c37a2f9c
Signed-off-by: leechul <chuls.lee@samsung.com>
Signed-off-by: Randeep Singh <randeep.s@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1989
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Sachin Agrawal <sachin.agrawal@intel.com>
26 files changed:
resource/csdk/security/SConscript
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/include/pbkdf2.h [new file with mode: 0644]
resource/csdk/security/include/pinoxmcommon.h [new file with mode: 0644]
resource/csdk/security/include/srmutility.h
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h
resource/csdk/security/provisioning/include/oxm/oxmrandompin.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/pmutility.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/sample/sampleserver_justworks.cpp
resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmjustworks.c
resource/csdk/security/provisioning/src/oxmrandompin.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/pmutility.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/provisioning/unittest/otmunittest.cpp
resource/csdk/security/provisioning/unittest/secureresourceprovider.cpp
resource/csdk/security/src/credresource.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/oxmpincommon.c [new file with mode: 0644]
resource/csdk/security/src/pbkdf2.c [new file with mode: 0644]

index f1adb9c..033a4d7 100644 (file)
@@ -40,7 +40,7 @@ if target_os == 'arduino':
 ######################################################################
 libocsrm_env.PrependUnique(CPPPATH = [
                '../../../extlibs/cjson/',
-#              '../../../extlibs/tinydtls/',
+               '../../../extlibs/tinydtls/',
                '../logger/include',
                '../ocrandom/include',
                '../stack/include',
@@ -82,22 +82,44 @@ if not env.get('RELEASE'):
 # Source files and Targets
 ######################################################################
 OCSRM_SRC = 'src/'
-libocsrm_src = [
-       OCSRM_SRC + 'secureresourcemanager.c',
-       OCSRM_SRC + 'resourcemanager.c',
-    OCSRM_SRC + 'aclresource.c',
-    OCSRM_SRC + 'amaclresource.c',
-       OCSRM_SRC + 'pstatresource.c',
-       OCSRM_SRC + 'doxmresource.c',
-       OCSRM_SRC + 'credresource.c',
-       OCSRM_SRC + 'svcresource.c',
-       OCSRM_SRC + 'policyengine.c',
-       OCSRM_SRC + 'psinterface.c',
-       OCSRM_SRC + 'srmresourcestrings.c',
-       OCSRM_SRC + 'srmutility.c',
-       OCSRM_SRC + 'iotvticalendar.c',
-       OCSRM_SRC + 'base64.c'
-       ]
+if env.get('SECURED') == '1':
+       libocsrm_src = [
+               OCSRM_SRC + 'secureresourcemanager.c',
+               OCSRM_SRC + 'resourcemanager.c',
+               OCSRM_SRC + 'aclresource.c',
+               OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'pstatresource.c',
+               OCSRM_SRC + 'doxmresource.c',
+               OCSRM_SRC + 'credresource.c',
+               OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'policyengine.c',
+               OCSRM_SRC + 'psinterface.c',
+               OCSRM_SRC + 'srmresourcestrings.c',
+               OCSRM_SRC + 'srmutility.c',
+               OCSRM_SRC + 'iotvticalendar.c',
+               OCSRM_SRC + 'oxmpincommon.c',
+               OCSRM_SRC + 'base64.c',
+               #pbkdf2.c is required to PIN based OxM only.
+               #But we did not use a separate build options to prevent the build command becomes complicated.
+               OCSRM_SRC + 'pbkdf2.c'
+               ]
+else:
+       libocsrm_src = [
+               OCSRM_SRC + 'secureresourcemanager.c',
+               OCSRM_SRC + 'resourcemanager.c',
+               OCSRM_SRC + 'aclresource.c',
+               OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'pstatresource.c',
+               OCSRM_SRC + 'doxmresource.c',
+               OCSRM_SRC + 'credresource.c',
+               OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'policyengine.c',
+               OCSRM_SRC + 'psinterface.c',
+               OCSRM_SRC + 'srmresourcestrings.c',
+               OCSRM_SRC + 'srmutility.c',
+               OCSRM_SRC + 'iotvticalendar.c',
+               OCSRM_SRC + 'base64.c'
+               ]
 
 libocsrm = libocsrm_env.StaticLibrary('libocsrm', libocsrm_src)
 
index 9ae31bd..2170521 100644 (file)
@@ -100,6 +100,15 @@ OicSecCred_t * GenerateCredential(const OicUuid_t* subject, OicSecCredType_t cre
  */
 OCStackResult AddCredential(OicSecCred_t * cred);
 
+/**
+ * Function to remove the credential from SVR DB.
+ *
+ * @param credId Credential ID to be deleted.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult RemoveCredential(const OicUuid_t* credId);
+
 #if defined(__WITH_DTLS__)
 /**
  * This internal callback is used by lower stack (i.e. CA layer) to
@@ -114,6 +123,24 @@ OCStackResult AddCredential(OicSecCred_t * cred);
  * @retval none
  */
 void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
+
+/**
+ * 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);
+
 #endif /* __WITH_DTLS__ */
 
 /**
diff --git a/resource/csdk/security/include/pbkdf2.h b/resource/csdk/security/include/pbkdf2.h
new file mode 100644 (file)
index 0000000..ff2e3e5
--- /dev/null
@@ -0,0 +1,62 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef _PBKDF2_H
+#define _PBKDF2_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * The number of iterations desired to derived key.
+ * (Recommened by RFC 2898)
+ */
+#define PBKDF_ITERATIONS 1000
+
+/**
+ * Function to derive cryptographic key from the password. (RFC 2898)
+ * In this implementation, HMAC with SHA2 is considered as a pseudorandom function
+ *
+ * @param[in] passwd is the master password from which a derived key is generated.
+ * @param[in] pLen is the byte size of the passwd.
+ * @param[in] salt is a cryptographic salt.
+ * @param[in] saltlen is the byte size of the salt.
+ * @param[in] iteration is the number of iterations desired.
+ * @param[in] keyLen is the desired byte size of the derived key. (should be the same as
+ *       derivedKey size)
+ * @param[out] derivedKey is the generated derived key
+ *
+ * @return  0 on success
+ */
+int DeriveCryptoKeyFromPassword(const unsigned char* passwd, size_t pLen,
+                                const uint8_t* salt, const size_t saltLen,
+                                const size_t iterations,
+                                const size_t keyLen, uint8_t* derivedKey);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _PBKDF2_H
+
diff --git a/resource/csdk/security/include/pinoxmcommon.h b/resource/csdk/security/include/pinoxmcommon.h
new file mode 100644 (file)
index 0000000..b4658ad
--- /dev/null
@@ -0,0 +1,78 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef PIN_CALLBACK_DEF_H_
+#define PIN_CALLBACK_DEF_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif // __cplusplus
+
+#define OXM_RANDOM_PIN_SIZE 8
+
+/**
+ * Function pointer to print pin code
+ */
+typedef void (*GeneratePinCallback)(char* pinData, size_t pinSize);
+
+/**
+ * Function pointer to input pin code
+ */
+typedef void (*InputPinCallback)(char* pinBuf, size_t bufSize);
+
+/**
+ * Function to setting generate PIN callback from user
+ *
+ * @param[in] pinCB implementation of generate PIN callback
+ */
+void SetGeneratePinCB(GeneratePinCallback pinCB);
+
+/**
+ * Function to setting input PIN callback from user
+ *
+ * @param[in] pinCB implementation of input PIN callback
+ */
+void SetInputPinCB(InputPinCallback pinCB);
+
+/**
+ * Function to generate random PIN.
+ * This function will send generated PIN to user via callback.
+ *
+ * @param[in,out] pinBuffer   Buffer to store the generated PIN data.
+ * @param[in] bufferSize   Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize);
+
+/**
+ * Function to input PIN callback via input callback
+ *
+ * @param[in,out] pinBuffer Buffer to store the inputed PIN data.
+ * @param[in] bufferSize Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PIN_CALLBACK_DEF_H_
index ded297d..9230ef6 100644 (file)
@@ -64,8 +64,8 @@ struct OicParseQueryIter
  * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
  */
-#define VERIFY_SUCCESS(tag, op, logLevel) { if (!(op)) \
-            {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit;} }
+#define VERIFY_SUCCESS(tag, op, logLevel) do{ if (!(op)) \
+            {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit; } }while(0)
 
 /**
  * @def VERIFY_NON_NULL
@@ -74,8 +74,8 @@ struct OicParseQueryIter
  * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
  */
-#define VERIFY_NON_NULL(tag, arg, logLevel) { if (NULL == (arg)) \
-            { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }
+#define VERIFY_NON_NULL(tag, arg, logLevel) do{ if (NULL == (arg)) \
+            { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }while(0)
 
 /**
  * This method initializes the OicParseQueryIter_t struct
index cea9b32..86317a1 100644 (file)
@@ -42,6 +42,7 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../connectivity/inc',
                '../../connectivity/external/inc',
                '../../connectivity/common/inc',
+               '../../connectivity/lib/libcoap-4.1.1',
                '../../connectivity/api',
                '../include',
                '../include/internal'
@@ -80,11 +81,12 @@ if target_os in ['darwin', 'ios']:
 ######################################################################
 provisioning_src = [
        'src/pmutility.c',
-    'src/credentialgenerator.c',
-    'src/ownershiptransfermanager.c',
-    'src/secureresourceprovider.c',
-    'src/ocprovisioningmanager.c',
-    'src/oxmjustworks.c' ]
+       'src/credentialgenerator.c',
+       'src/ownershiptransfermanager.c',
+       'src/secureresourceprovider.c',
+       'src/ocprovisioningmanager.c',
+       'src/oxmjustworks.c',
+       'src/oxmrandompin.c' ]
 provisioningserver = provisioning_env.StaticLibrary('ocpmapi', provisioning_src)
 
 provisioning_env.InstallTarget(provisioningserver, 'libocpmapi')
index 6208a39..64f7368 100644 (file)
@@ -39,7 +39,7 @@ extern "C" {
 typedef struct OTMContext{\r
     void* userCtx; /**< Context for user**/\r
     OCProvisionDev_t* selectedDeviceInfo; /**< Selected device info for OT */\r
-    uint16_t tempCredId;\r
+    OicUuid_t tempCredId;\r
 }OTMContext_t;\r
 \r
 /**\r
diff --git a/resource/csdk/security/provisioning/include/oxm/oxmrandompin.h b/resource/csdk/security/provisioning/include/oxm/oxmrandompin.h
new file mode 100644 (file)
index 0000000..db5556f
--- /dev/null
@@ -0,0 +1,73 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef OXM_RANDOM_PIN_H_
+#define OXM_RANDOM_PIN_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+#include "pmtypes.h"
+#include "pinoxmcommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define OXM_PBKDF2_ITERATIONS 1000
+
+/**
+ * Callback implementation to input the PIN code from user.
+ *
+ * @otmCtx  Context of OTM, It includes current device infomation.
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx);
+
+/**
+ * Callback implemenration to establish a secure channel with PSK cipher suite
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the selected OxM.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the owner information.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_RANDOM_PIN_H_
\ No newline at end of file
index 877ce3d..79f98b5 100644 (file)
@@ -38,21 +38,6 @@ extern "C"
 #define COAP_QUERY "coap://%s:%d%s"
 
 /**
- * Macro to verify argument is not equal to NULL.
- * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
- */
-#define VERIFY_NON_NULL(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
-            { OC_LOG((logLevel), tag, (#arg " is NULL")); return retValue; } }
-
-/**
- * Macro to verify success of operation.
- * eg: VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
- */
-#define VERIFY_SUCCESS(tag, op, logLevel, retValue) { if (!(op)) \
-            {OC_LOG((logLevel), tag, (#op " failed!!")); return retValue;} }
-
-
-/**
  * Discover owned/unowned devices in the same IP subnet. .
  *
  * @param[in] waittime      Timeout in seconds.
index 489b927..46e270e 100644 (file)
@@ -65,8 +65,9 @@ provisioning_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
 provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
 sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp')
+sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
 
-Alias("samples", [provisioningclient, sampleserver_justworks])
+Alias("samples", [provisioningclient, sampleserver_justworks, sampleserver_randompin])
 
 provisioning_env.AppendTarget('samples')
 
@@ -78,4 +79,5 @@ provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_bui
     sec_provisioning_src_dir + 'oic_svr_db_client.json'))
 provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
     sec_provisioning_src_dir + 'oic_svr_db_server_justworks.json'))
-
+provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
+    sec_provisioning_src_dir + 'oic_svr_db_server_randompin.json'))
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json
new file mode 100644 (file)
index 0000000..a3a4b6f
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "cmFuZG9tUGluRGV2VVVJRA=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "cmFuZG9tUGluRGV2VVVJRA=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0,2],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA=="
+       }
+}
index fab89e0..9607e1b 100644 (file)
@@ -28,8 +28,8 @@
 #include "ocprovisioningmanager.h"
 #include "secureresourceprovider.h"
 #include "oxmjustworks.h"
-// TODO: PIN based OxM implementation is required.
-//#include "oxmrandompin.h"
+#include "oxmrandompin.h"
+#include "pinoxmcommon.h"
 #include "oic_string.h"
 
 #define MAX_URI_LENGTH (64)
@@ -67,7 +67,7 @@ static void deleteACL(OicSecAcl_t *acl)
     if (acl)
     {
         /* Clean Resources */
-        for (int i = 0; i < (acl)->resourcesLen; i++)
+        for (size_t i = 0; i < (acl)->resourcesLen; i++)
         {
             OICFree((acl)->resources[i]);
         }
@@ -185,9 +185,9 @@ static int InputACL(OicSecAcl_t *acl)
         OC_LOG(ERROR, TAG, "Error while memory allocation");
         return -1;
     }
-    for (int i = 0; i < acl->resourcesLen; i++)
+    for (size_t i = 0; i < acl->resourcesLen; i++)
     {
-        printf("[%d]Resource : ", i + 1);
+        printf("[%zu]Resource : ", i + 1);
         unused = scanf("%64s", temp_rsc);
         acl->resources[i] = OICStrdup(temp_rsc);
 
@@ -219,9 +219,9 @@ static int InputACL(OicSecAcl_t *acl)
         OC_LOG(ERROR, TAG, "Error while memory allocation");
         return -1;
     }
-    for (int i = 0; i < acl->ownersLen; i++)
+    for (size_t i = 0; i < acl->ownersLen; i++)
     {
-        printf("[%d]Rowner : ", i + 1);
+        printf("[%zu]Rowner : ", i + 1);
         unused = scanf("%19s", temp_id);
         j = 0;
         for (int k = 0; temp_id[k] != '\0'; k++)
@@ -237,17 +237,45 @@ static int InputACL(OicSecAcl_t *acl)
 
 
 //FILE *client_fopen(const char *path, const char *mode)
-FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char *UNUSED_PARAM, const char *mode)
 {
     return fopen(CRED_FILE, mode);
 }
 
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    printf("-----------------------------------------------------------\n");
+    if(!hasError)
+    {
+        printf("%s was successfully done.\n", procName);
+    }
+    else
+    {
+        for(int i = 0; i < nOfRes; i++)
+        {
+            printf("UUID : ");
+            for(int j = 0; j < UUID_LENGTH; i++)
+            {
+                printf("%c", arr[i].deviceId.id[j]);
+            }
+            printf("\t");
+            printf("Result=%d\n", arr[i].res);
+        }
+    }
+
+    if(ctx)
+    {
+        printf("Context is %s\n", (char*)ctx);
+    }
+    printf("-----------------------------------------------------------\n");
+}
+
 void ProvisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
 {
     if(!hasError)
     {
-        OC_LOG(INFO, TAG, "Provision Credential IS DONE~~!!");
         gOwnershipState = 1;
+        PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
     }
 }
 
@@ -255,8 +283,8 @@ void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasErr
 {
     if(!hasError)
     {
-        OC_LOG(INFO, TAG, "Provision Acl IS DONE~~!!");
         gOwnershipState = 1;
+        PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
     }
 }
 
@@ -264,9 +292,8 @@ void ProvisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool h
 {
     if(!hasError)
     {
-        OC_LOG_V(INFO, TAG, "Context is %s", (char*)ctx);
-        OC_LOG(INFO, TAG, "Provision Pairwise IS DONE~~!!");
         gOwnershipState = 1;
+        PrintfResult("Provision Pairwise Credential", ctx, nOfRes, arr, hasError);
     }
 }
 
@@ -274,9 +301,8 @@ void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool h
 {
     if(!hasError)
     {
-        OC_LOG_V(INFO, TAG, "Context is %s", (char*)ctx);
-        OC_LOG(INFO, TAG, "OWNERSHIP TRANSFER IS DONE~~!!");
         gOwnershipState = 1;
+        PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
     }
 }
 
@@ -284,7 +310,8 @@ void InputPinCB(char* pinBuf, size_t bufSize)
 {
     if(pinBuf)
     {
-        scanf("%s", pinBuf);
+        printf("INPUT PIN : ");
+        int unused = scanf("%s", pinBuf);
         pinBuf[bufSize - 1] = '\0';
     }
 }
@@ -305,7 +332,11 @@ int main(int argc, char **argv)
     }
 
     // Initialize Persistent Storage for SVR database
-    OCPersistentStorage ps = {};
+    OCPersistentStorage ps = { .open = NULL,
+                               .read = NULL,
+                               .write = NULL,
+                               .close = NULL,
+                               .unlink = NULL };
     ps.open = client_fopen;
     ps.read = fread;
     ps.write = fwrite;
@@ -338,20 +369,27 @@ int main(int argc, char **argv)
     }
 
     //Register callback function to each OxM
-    OTMCallbackData_t justWorksCBData = {};
+    OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+                                         .createSecureSessionCB=NULL,
+                                         .createSelectOxmPayloadCB=NULL,
+                                         .createOwnerTransferPayloadCB=NULL};
     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
     justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
     justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
     justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
     OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
 
-    // TODO: PIN based OxM implementation is required.
-    //OTMCallbackData_t pinBasedCBData = {};
-    //pinBasedCBData.loadSecretCB = InputPinCodeCallback;
-    //pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
-    //pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
-    //pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
-    //OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+    OTMCallbackData_t pinBasedCBData = {.loadSecretCB=NULL,
+                                         .createSecureSessionCB=NULL,
+                                         .createSelectOxmPayloadCB=NULL,
+                                         .createOwnerTransferPayloadCB=NULL};
+    pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+    pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+    pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+    pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+    OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+    SetInputPinCB(&InputPinCB);
 
     char* myContext = "OTM Context";
     //Perform ownership transfer
index 0569eea..35db3e5 100644 (file)
@@ -358,7 +358,8 @@ OCEntityHandlerCb (OCEntityHandlerFlag flag,
                 response.ehResult = ehResult;
                 response.payload = (OCPayload*)(payload);
                 response.numSendVendorSpecificHeaderOptions = 0;
-                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(response.sendVendorSpecificHeaderOptions));
                 memset(response.resourceUri, 0, sizeof(response.resourceUri));
                 // Indicate that response is NOT in a persistent buffer
                 response.persistentBufferFlag = 0;
diff --git a/resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp b/resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp
new file mode 100644 (file)
index 0000000..25e84f8
--- /dev/null
@@ -0,0 +1,488 @@
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE :  This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+#include "pinoxmcommon.h"
+
+#define TAG "SAMPLE_RANDOMPIN"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE  2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server_randompin.json";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+    switch (result) {
+    case OC_STACK_OK:
+        return "OC_STACK_OK";
+    case OC_STACK_RESOURCE_CREATED:
+        return "OC_STACK_RESOURCE_CREATED";
+    case OC_STACK_RESOURCE_DELETED:
+        return "OC_STACK_RESOURCE_DELETED";
+    case OC_STACK_INVALID_URI:
+        return "OC_STACK_INVALID_URI";
+    case OC_STACK_INVALID_QUERY:
+        return "OC_STACK_INVALID_QUERY";
+    case OC_STACK_INVALID_IP:
+        return "OC_STACK_INVALID_IP";
+    case OC_STACK_INVALID_PORT:
+        return "OC_STACK_INVALID_PORT";
+    case OC_STACK_INVALID_CALLBACK:
+        return "OC_STACK_INVALID_CALLBACK";
+    case OC_STACK_INVALID_METHOD:
+        return "OC_STACK_INVALID_METHOD";
+    case OC_STACK_NO_MEMORY:
+        return "OC_STACK_NO_MEMORY";
+    case OC_STACK_COMM_ERROR:
+        return "OC_STACK_COMM_ERROR";
+    case OC_STACK_INVALID_PARAM:
+        return "OC_STACK_INVALID_PARAM";
+    case OC_STACK_NOTIMPL:
+        return "OC_STACK_NOTIMPL";
+    case OC_STACK_NO_RESOURCE:
+        return "OC_STACK_NO_RESOURCE";
+    case OC_STACK_RESOURCE_ERROR:
+        return "OC_STACK_RESOURCE_ERROR";
+    case OC_STACK_SLOW_RESOURCE:
+        return "OC_STACK_SLOW_RESOURCE";
+    case OC_STACK_NO_OBSERVERS:
+        return "OC_STACK_NO_OBSERVERS";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    #endif
+    case OC_STACK_ERROR:
+        return "OC_STACK_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return NULL;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return NULL;
+    }
+
+    OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+    LEDResource *currLEDResource = &LED;
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = (char *) "/a/led/0";
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = (char *) "/a/led/1";
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
+        {
+            currLEDResource->power =pow;
+        }
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+    }
+
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *putResp = constructResponse(ehRequest);
+
+    if(putResp)
+    {
+        *payload = putResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+    OCRepPayload *respPLPost_led = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    /*
+     * The entity handler determines how to process a POST request.
+     * Per the REST paradigm, POST can also be used to update representation of existing
+     * resource or create a new resource.
+     * In the sample below, if the POST is for /a/led then a new instance of the LED
+     * resource is created with default representation (if representation is included in
+     * POST payload it can be used as initial values) as long as the instance is
+     * lesser than max new instance count. Once max instance count is reached, POST on
+     * /a/led updated the representation of /a/led (just like PUT)
+     */
+
+    if (ehRequest->resource == LED.handle)
+    {
+        if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+        {
+            // Create new LED instance
+            char newLedUri[15] = "/a/led/";
+            int newLedUriLength = strlen(newLedUri);
+            snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+            if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+            {
+                OC_LOG (INFO, TAG, "Created new LED instance");
+                gLedInstance[gCurrLedInstance].state = 0;
+                gLedInstance[gCurrLedInstance].power = 0;
+                gCurrLedInstance++;
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
+            }
+        }
+        else
+        {
+            respPLPost_led = constructResponse(ehRequest);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+        {
+            if (ehRequest->resource == gLedInstance[i].handle)
+            {
+                if (i == 0)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                    break;
+                }
+                else if (i == 1)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                }
+            }
+        }
+    }
+
+    if (respPLPost_led != NULL)
+    {
+        *payload = respPLPost_led;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        OC_LOG_V (INFO, TAG, "Payload was NULL");
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam)
+{
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response = {};
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = NULL;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            if (OC_REST_GET == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_PUT == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_POST == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+            }
+            else
+            {
+                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (OCPayload*)(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(response.sendVendorSpecificHeaderOptions));
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
+void GeneratePinCB(char* pin, size_t pinSize)
+{
+    if(NULL == pin || pinSize <= 0)
+    {
+        OC_LOG(INFO, TAG, "Invalid PIN");
+        return;
+    }
+
+    OC_LOG(INFO, TAG, "============================");
+    OC_LOG_V(INFO, TAG, "    PIN CODE : %s", pin);
+    OC_LOG(INFO, TAG, "============================");
+}
+
+int main(int argc, char* argv[])
+{
+    struct timespec timeout;
+
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {};
+    ps.open = server_fopen;
+    ps.read = fread;
+    ps.write = fwrite;
+    ps.close = fclose;
+    ps.unlink = unlink;
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+   /**
+     * If server supported random pin based ownership transfer,
+     * callback of print PIN should be registered before runing server.
+     */
+    SetGeneratePinCB(&GeneratePinCB);
+
+    /*
+     * Declare and create the example resource: LED
+     */
+    createLEDResource(gResourceUri, &LED, false, 0);
+
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            OC_RSRVD_INTERFACE_DEFAULT,
+            uri,
+            OCEntityHandlerCb,
+            NULL,
+            OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
index 1e6aef9..fa26f36 100644 (file)
@@ -350,13 +350,14 @@ OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_
                                          OCProvisionResultCB resultCallback)
 {
 
-    VERIFY_NON_NULL(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
-
+    if(!pDev1 || !pDev2 || !resultCallback)
+    {
+        OC_LOG(ERROR, TAG, "OCProvisionPairwiseDevices : Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
     if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
     {
-        OC_LOG(INFO, TAG, "Invalid key size");
+        OC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Invalid key size");
         return OC_STACK_INVALID_PARAM;
     }
     int noOfResults = 2; // Initial Value
index ab922df..2510a9d 100644 (file)
@@ -54,6 +54,7 @@
 #include "oxmjustworks.h"
 #include "pmtypes.h"
 #include "pmutility.h"
+#include "srmutility.h"
 
 // TODO: Not yet supported.
 //#include "oxmrandompin.h"
@@ -65,8 +66,8 @@
 
 OCProvisionResultCB g_resultCallback;
 OCProvisionResult_t* g_resultArray = NULL;
-uint32_t g_resultArraySize = 0;
-bool hasError = false;
+size_t g_resultArraySize = 0;
+bool g_hasError = false;
 
 /**
  * Possible states of ownership transfer manager module.
@@ -109,7 +110,7 @@ static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIV
  * Number of supported provisioning methods
  * current version supports only one.
  */
-static int gNumOfProvisioningMethodsPT = 1;
+static size_t gNumOfProvisioningMethodsPT = 1;
 
 /**
  * Function to getting string of ownership transfer method
@@ -136,14 +137,15 @@ static const char* GetOxmString(OicSecOxm_t oxmType)
 /**
  * Function to select appropriate  provisioning method.
  *
- * @param[in]   supportedMethodsList   List of supported methods
+ * @param[in] supportedMethods   Array of supported methods
+ * @param[in] numberOfMethods   number of supported methods
  * @param[out]  selectedMethod         Selected methods
  * @return  SP_SUCCESS on success
  */
-static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods, size_t numberOfMethods,
+static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
+                                                            size_t numberOfMethods,
                                                             OicSecOxm_t *selectedMethod)
 {
-    int i;
     OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
 
     if(numberOfMethods == 0 || !supportedMethods)
@@ -153,7 +155,7 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod
     }
 
     *selectedMethod  = supportedMethods[0];
-    for(i = 0; i < numberOfMethods; i++)
+    for(size_t i = 0; i < numberOfMethods; i++)
     {
         if(*selectedMethod < supportedMethods[i])
         {
@@ -167,6 +169,7 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod
 /**
  * Function to select operation mode.This function will return most secure common operation mode.
  *
+ * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
  * @param[out]   selectedMode   selected operation mode
  * @return  SP_SUCCESS on success
  */
@@ -175,8 +178,8 @@ static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
 {
     OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
 
-    int i = 0;
-    int j = 0;
+    size_t i = 0;
+    size_t j = 0;
 
     while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
     {
@@ -200,7 +203,7 @@ static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
 /**
  * Function to update owner transfer mode
  *
- * @param[in]  deviceInfo  Device Info.
+ * @param[in]  otmCtx  Context value of ownership transfer.
  * @return  OC_STACK_OK on success
  */
 static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
@@ -208,8 +211,7 @@ static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
 /**
  * Function to send request to resource to get its pstat resource information.
  *
- * @param[in] deviceInfo  Selected device Info.
- * @param[in] otmCtx address of pointer variable for OTMContext_t
+ * @param[in]  otmCtx  Context value of ownership transfer.
  * @return  OC_STACK_OK on success
  */
 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
@@ -219,8 +221,7 @@ 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
  *
- * @param[in] deviceInfo  Selected device info
- * @param[in] otmCtx address of pointer variable for OTMContext_t
+ * @param[in]  otmCtx  Context value of ownership transfer.
  * @return  OC_STACK_OK on success
  */
 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
@@ -229,23 +230,37 @@ static OCStackResult PutOwnershipInformation(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] deviceInfo  Selected device Info.
+ * @param[in]  otmCtx  Context value of ownership transfer.
  * @param[in] selectedOperationMode selected operation mode
- * @param[in] otmCtx address of pointer variable for OTMContext_t
  * @return  OC_STACK_OK on success
  */
 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
                                     OicSecDpom_t selectedOperationMode);
 
+/**
+ * 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 finalize provisioning.
+ * This function will send default ACL and commit hash.
+ *
+ * @param[in] otmCtx   Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
 static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
 
 
 static bool IsComplete()
 {
-    int i;
-    for(i = 0; i < g_resultArraySize; i++)
+    for(size_t i = 0; i < g_resultArraySize; i++)
     {
         if(OC_STACK_CONTINUE == g_resultArray[i].res)
         {
@@ -256,20 +271,25 @@ static bool IsComplete()
     return true;
 }
 
-static void SetResult(OTMContext_t* otmCtx, OCStackResult res)
+/**
+ * Function to save the result of provisioning.
+ *
+ * @param[in,out] otmCtx   Context value of ownership transfer.
+ * @param[in] res   result of provisioning
+ */
+static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
 {
-    int i;
-
     OC_LOG(DEBUG, TAG, "IN SetResult");
 
     if(!otmCtx)
     {
         OC_LOG(WARNING, TAG, "OTMContext is NULL");
+        return;
     }
 
     if(otmCtx->selectedDeviceInfo)
     {
-        for(i = 0; i < g_resultArraySize; i++)
+        for(size_t i = 0; i < g_resultArraySize; i++)
         {
             if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
                       g_resultArray[i].deviceId.id, UUID_LENGTH) == 0)
@@ -277,7 +297,7 @@ static void SetResult(OTMContext_t* otmCtx, OCStackResult res)
                 g_resultArray[i].res = res;
                 if(OC_STACK_OK != res)
                 {
-                    hasError = true;
+                    g_hasError = true;
                 }
             }
         }
@@ -285,7 +305,7 @@ static void SetResult(OTMContext_t* otmCtx, OCStackResult res)
         //If all request is completed, invoke the user callback.
         if(IsComplete())
         {
-            g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, hasError);
+            g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, g_hasError);
         }
         else
         {
@@ -306,6 +326,7 @@ static void SetResult(OTMContext_t* otmCtx, OCStackResult res)
 /**
  * Function to save ownerPSK at provisioning tool end.
  *
+ * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
  * @return  OC_STACK_OK on success
  */
 static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
@@ -314,19 +335,20 @@ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
 
     OCStackResult res = OC_STACK_ERROR;
 
-    CAEndpoint_t endpoint = {0};
+    CAEndpoint_t endpoint;
+    memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
     endpoint.port = selectedDeviceInfo->securePort;
 
-    OicUuid_t ptDeviceID = {};
+    OicUuid_t ptDeviceID = {.id={0}};
     if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
     {
         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
         return res;
     }
 
-    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
+    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
 
     //Generating OwnerPSK
     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
@@ -347,31 +369,18 @@ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
         B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
                 &outLen);
-        if (B64_OK == b64Ret)
-        {
-            OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
-                    SYMMETRIC_PAIR_WISE_KEY, NULL,
-                    base64Buff, ownLen, &ptDeviceID);
-            if (cred)
-            {
-                //Update the SVR database.
-                if (OC_STACK_OK == AddCredential(cred))
-                {
-                    res = OC_STACK_OK;
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, "AddCredential failed");
-                }
-            }
-            else
-            {
-                OC_LOG(ERROR, TAG, "GenerateCredential failed");
-            }
-        }
-        else
+        VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
+
+        OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
+                SYMMETRIC_PAIR_WISE_KEY, NULL,
+                base64Buff, ownLen, &ptDeviceID);
+        VERIFY_NON_NULL(TAG, cred, ERROR);
+
+        res = AddCredential(cred);
+        if(res != OC_STACK_OK)
         {
-            OC_LOG(ERROR, TAG, "b64Encode failed");
+            DeleteCredList(cred);
+            return res;
         }
     }
     else
@@ -380,271 +389,255 @@ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
     }
 
     OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
-
+exit:
     return res;
 }
 
 /**
  * Callback handler for OwnerShipTransferModeHandler API.
  *
- * @param[in] ctx             IP of target device.
- * @param[in] handle          port of remote server.
- * @param[in] clientResponse  adapter type of endpoint.
- * @param[in] doxm            pointer to doxm instance.
- * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
- *         OC_STACK_DELETE_TRANSACTION to delete it.
+ * @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 OwnerTransferModeHandler(void *ctx, OCDoHandle handle,
+static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
-    if (clientResponse)
-    {
-        OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
+    OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
 
-        OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-        if(!otmCtx)
-        {
-            OC_LOG(ERROR, TAG, "Can't find OTMContext");
-            return OC_STACK_DELETE_TRANSACTION;
-        }
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
 
-        if(clientResponse->result == OC_STACK_OK)
-        {
-            OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
-            //Send request : GET /oic/sec/pstat
-            OCStackResult res = GetProvisioningStatusResource(otmCtx);
-            if(OC_STACK_OK != res)
-            {
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
 
-                OC_LOG(WARNING, TAG, "Failed to getting pstat information");
-                SetResult(otmCtx, res);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-        }
-        else
+    if(clientResponse->result == OC_STACK_OK)
+    {
+        OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
+        //Send request : GET /oic/sec/pstat
+        OCStackResult res = GetProvisioningStatusResource(otmCtx);
+        if(OC_STACK_OK != res)
         {
-
-            OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
-                clientResponse->result);
-            SetResult(otmCtx, clientResponse->result);
-            return OC_STACK_DELETE_TRANSACTION;
+            OC_LOG(WARNING, TAG, "Failed to get pstat information");
+            SetResult(otmCtx, res);
         }
-        OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
     }
+    else
+    {
+        OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
+        clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
 
+exit:
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
 /**
  * Callback handler for ProvisioningStatusResouceHandler API.
  *
- * @param[in] ctx             IP of target device.
- * @param[in] handle          port of remote server.
- * @param[in] clientResponse  adapter type of endpoint.
- * @param[in] doxm            pointer to doxm instance.
- * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
- *         OC_STACK_DELETE_TRANSACTION to delete it.
+ * @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 ListMethodsHandler(void *ctx, OCDoHandle handle,
+static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
-    if (clientResponse)
-    {
-        OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
+    OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
+
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
 
-        OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-        if(!otmCtx)
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        if  (NULL == clientResponse->payload)
         {
-            OC_LOG(ERROR, TAG, "Can't find OTMContext");
+            OC_LOG(INFO, TAG, "Skiping Null payload");
+            SetResult(otmCtx, OC_STACK_ERROR);
             return OC_STACK_DELETE_TRANSACTION;
         }
 
-        if  (OC_STACK_OK == clientResponse->result)
+        if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
         {
-            if  (NULL == clientResponse->payload)
-            {
-                OC_LOG(INFO, TAG, "Skiping Null payload");
-                SetResult(otmCtx, OC_STACK_ERROR);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-
-            if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
-            {
-                OC_LOG(INFO, TAG, "Unknown payload type");
-                SetResult(otmCtx, OC_STACK_ERROR);
-                return OC_STACK_KEEP_TRANSACTION;
-            }
-
-            OicSecPstat_t* pstat = JSONToPstatBin(
-                    ((OCSecurityPayload*)clientResponse->payload)->securityData);
-            if(NULL == pstat)
-            {
-                OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
-                SetResult(otmCtx, OC_STACK_ERROR);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-            otmCtx->selectedDeviceInfo->pstat = pstat;
+            OC_LOG(INFO, TAG, "Unknown payload type");
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
 
-            //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
-            OicSecDpom_t selectedOperationMode;
-            SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
+        OicSecPstat_t* pstat = JSONToPstatBin(
+                ((OCSecurityPayload*)clientResponse->payload)->securityData);
+        if(NULL == pstat)
+        {
+            OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+        otmCtx->selectedDeviceInfo->pstat = pstat;
 
-            //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
-            OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
-            if (OC_STACK_OK != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while updating operation mode.");
-                SetResult(otmCtx, res);
+        //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
+        OicSecDpom_t selectedOperationMode;
+        SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
 
-            }
-        }
-        else
+        //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
+        OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
+        if (OC_STACK_OK != res)
         {
-            OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
-                clientResponse->result);
-            SetResult(otmCtx, clientResponse->result);
+            OC_LOG(ERROR, TAG, "Error while updating operation mode.");
+            SetResult(otmCtx, res);
         }
-
-        OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
+    }
+    else
+    {
+        OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
+            clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
     }
 
+    OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
+exit:
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
 /**
  * Callback handler for OwnershipInformationHandler API.
  *
- * @param[in] ctx             IP of target device.
- * @param[in] handle          port of remote server.
- * @param[in] clientResponse  adapter type of endpoint.
- * @param[in] doxm            pointer to doxm instance.
- * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
- *         OC_STACK_DELETE_TRANSACTION to delete it.
+ * @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 handle, OCClientResponse *clientResponse)
+                                OCDoHandle UNUSED, OCClientResponse *clientResponse)
 {
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
 
-    if (clientResponse)
-    {
-        OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+    OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
 
-        OCStackResult res = OC_STACK_OK;
-        OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-        if  (OC_STACK_OK == clientResponse->result)
+    OCStackResult res = OC_STACK_OK;
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
         {
-            res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
-            if(OC_STACK_OK != res)
-            {
-                OC_LOG(ERROR, TAG, "OperationModeUpdate : 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 closeRes = CACloseDtlsSession(endpoint);
-            if(CA_STATUS_OK != closeRes)
+            res = RemoveCredential(&otmCtx->tempCredId);
+            if(OC_STACK_RESOURCE_DELETED != res)
             {
-                OC_LOG(ERROR, TAG, "Failed to close DTLS session");
-                SetResult(otmCtx, closeRes);
+                OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
                 return OC_STACK_DELETE_TRANSACTION;
             }
+        }
 
-            // TODO: PIN based OxM is required.
-            /*
-                       if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
-            {
-                res = RemoveCredential(otmCtx->tempCredId);
-                if(OC_STACK_OK != res)
-                {
-                    OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
-                    return OC_STACK_DELETE_TRANSACTION;
-                }
-            }
-            */
-            OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
-            OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
-
-            res = FinalizeProvisioning(otmCtx);
-            if(OC_STACK_OK != res)
-            {
-                SetResult(otmCtx, res);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
+        res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
+        if(OC_STACK_OK != res)
+        {
+            OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
+            SetResult(otmCtx, res);
+            return OC_STACK_DELETE_TRANSACTION;
         }
-        else
+
+        CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
+        endpoint->port = otmCtx->selectedDeviceInfo->securePort;
+        CAResult_t closeRes = CACloseDtlsSession(endpoint);
+        if(CA_STATUS_OK != closeRes)
         {
-            res = clientResponse->result;
+            OC_LOG(ERROR, TAG, "Failed to close DTLS session");
+            SetResult(otmCtx, closeRes);
+            return OC_STACK_DELETE_TRANSACTION;
         }
 
-        OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+        OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
+        OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
+
+        res = FinalizeProvisioning(otmCtx);
+        if(OC_STACK_OK != res)
+        {
+            SetResult(otmCtx, res);
+        }
+    }
+    else
+    {
+        res = clientResponse->result;
     }
 
+    OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+
+exit:
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
 /**
  * Response handler for update operation mode.
  *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
+ * @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 OperationModeUpdateHandler(void *ctx,
-                                OCDoHandle handle, OCClientResponse *clientResponse)
+                                OCDoHandle UNUSED, OCClientResponse *clientResponse)
 {
-    if (clientResponse)
-    {
-        OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
+    OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
 
-        OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-        if  (OC_STACK_OK == clientResponse->result)
-        {
-            OCStackResult res = OC_STACK_ERROR;
-            OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
-            //DTLS Handshake
-            //Load secret for temporal secure session.
-            if(g_OTMDatas[selOxm].loadSecretCB)
-            {
-                res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
-                if(OC_STACK_OK != res)
-                {
-                    OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
-                    SetResult(otmCtx, res);
-                    return  OC_STACK_DELETE_TRANSACTION;
-                }
-            }
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
 
-            //Try DTLS handshake to generate secure session
-            if(g_OTMDatas[selOxm].createSecureSessionCB)
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        OCStackResult res = OC_STACK_ERROR;
+        OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
+        //DTLS Handshake
+        //Load secret for temporal secure session.
+        if(g_OTMDatas[selOxm].loadSecretCB)
+        {
+            res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
+            if(OC_STACK_OK != res)
             {
-                res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
-                if(OC_STACK_OK != res)
-                {
-                    OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
-                    SetResult(otmCtx, res);
-                    return OC_STACK_DELETE_TRANSACTION;
-                }
+                OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
+                SetResult(otmCtx, res);
+                return  OC_STACK_DELETE_TRANSACTION;
             }
+        }
 
-            //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
-            res = PutOwnershipInformation(otmCtx);
+        //Try DTLS handshake to generate secure session
+        if(g_OTMDatas[selOxm].createSecureSessionCB)
+        {
+            res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
             if(OC_STACK_OK != res)
             {
-                OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
+                OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
                 SetResult(otmCtx, res);
-                return  OC_STACK_DELETE_TRANSACTION;
+                return OC_STACK_DELETE_TRANSACTION;
             }
         }
-        else
+
+        //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
+        res = PutOwnershipInformation(otmCtx);
+        if(OC_STACK_OK != res)
         {
-            OC_LOG(ERROR, TAG, "Error while update operation mode");
-            SetResult(otmCtx, clientResponse->result);
-            return  OC_STACK_DELETE_TRANSACTION;
+            OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
+            SetResult(otmCtx, res);
         }
-        OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
     }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error while update operation mode");
+        SetResult(otmCtx, clientResponse->result);
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
 
+exit:
     return  OC_STACK_DELETE_TRANSACTION;
 }
 
@@ -675,6 +668,7 @@ static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
     secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
     if (NULL == secPayload->securityData)
     {
+        OICFree(secPayload);
         OC_LOG(ERROR, TAG, "Error while converting bin to json");
         return OC_STACK_ERROR;
     }
@@ -699,13 +693,6 @@ static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
     return res;
 }
 
-/**
- * Function to send request to resource to get its pstat resource information.
- *
- * @param[in]  timeout     timeout for operation.
- * @param[in]  deviceInfo  Device Info.
- * @return  OC_STACK_OK on success
- */
 static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
 {
     OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
@@ -740,14 +727,6 @@ 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
- *
- * @param[in]  timeout     timeout value for the operation.
- * @param[in]  deviceInfo  provisioning context.
- * @return  OC_STACK_OK on success
- */
 static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
 {
     OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
@@ -775,6 +754,7 @@ static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
     secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
     if (NULL == secPayload->securityData)
     {
+        OICFree(secPayload);
         OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
         return OC_STACK_INVALID_PARAM;
     }
@@ -783,7 +763,6 @@ static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
     cbData.cb = &OwnershipInformationHandler;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
-
     // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
     OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
                                      CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
@@ -797,14 +776,6 @@ static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
     return res;
 }
 
-/**
- * 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]  timeout     timeout for operation.
- * @param[in]  deviceInfo  Device Info.
- * @return  OC_STACK_OK on success
- */
 static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
                                     OicSecDpom_t selectedOperationMode)
 {
@@ -832,6 +803,7 @@ static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
     secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
     if (NULL == secPayload->securityData)
     {
+        OICFree(secPayload);
         OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
         return OC_STACK_INVALID_PARAM;
     }
@@ -932,7 +904,7 @@ OCStackResult OTMDoOwnershipTransfer(void* ctx,
     }
 
     g_resultCallback = resultCallback;
-    hasError = false;
+    g_hasError = false;
 
     OCProvisionDev_t* pCurDev = selectedDevicelist;
 
@@ -956,10 +928,9 @@ OCStackResult OTMDoOwnershipTransfer(void* ctx,
         return OC_STACK_NO_MEMORY;
     }
 
-    int devIdx = 0;
     pCurDev = selectedDevicelist;
     //Fill the device UUID for result array.
-    for(devIdx = 0; devIdx < g_resultArraySize; devIdx++)
+    for(size_t devIdx = 0; devIdx < g_resultArraySize; devIdx++)
     {
         memcpy(g_resultArray[devIdx].deviceId.id,
                pCurDev->doxm->deviceID.id,
@@ -972,38 +943,33 @@ OCStackResult OTMDoOwnershipTransfer(void* ctx,
 
     OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
 
-    return (hasError ? OC_STACK_ERROR : OC_STACK_OK);
+    return (g_hasError ? OC_STACK_ERROR : OC_STACK_OK);
 }
 
 /**
  * Callback handler of SRPFinalizeProvisioning.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
+ * @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 handle,
+static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
-    if (clientResponse)
-    {
-        OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
-        OTMContext_t* otmCtx = (OTMContext_t*)ctx;
-        if(!otmCtx)
-        {
-            OC_LOG(ERROR, TAG, "OTMContext is NULL");
-            return OC_STACK_DELETE_TRANSACTION;
-        }
+    OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
 
-        if(OC_STACK_OK == clientResponse->result)
-        {
-            SetResult(otmCtx, OC_STACK_OK);
-            return OC_STACK_DELETE_TRANSACTION;
-        }
-    }
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
 
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+
+    if(OC_STACK_OK == clientResponse->result)
+    {
+        SetResult(otmCtx, OC_STACK_OK);
+    }
+exit:
     return OC_STACK_DELETE_TRANSACTION;
 }
 
@@ -1011,78 +977,72 @@ static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle han
  * Callback handler of default ACL provisioning.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
+ * @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 handle,
+static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
     OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
 
-    if (clientResponse)
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+    OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+
+    if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
     {
-        OTMContext_t* otmCtx = (OTMContext_t*) ctx;
-        if(!otmCtx)
+        OC_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)
         {
-            OC_LOG(ERROR, TAG, "OTMContext is NULL");
-            return OC_STACK_DELETE_TRANSACTION;
+            OC_LOG(ERROR, TAG, "Failed to memory allocation");
+            return OC_STACK_NO_MEMORY;
         }
-
-        if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+        secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
+        if (NULL == secPayload->securityData)
         {
-            OC_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)
-            {
-                OC_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)
-            {
-                SetResult(otmCtx, OC_STACK_INVALID_JSON);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
-            OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
-
-            char uri[MAX_QUERY_LENGTH] = { 0 };
-            size_t uriLen = sizeof(uri);
-
-            snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
-                    otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_PSTAT_URI);
-            uri[uriLen - 1] = '\0';
-            OCCallbackData cbData = {0,};
-            cbData.cb = &FinalizeProvisioningCB;
-            cbData.context = (void*)otmCtx; // forward context to SRPFinalizeProvisioningCB
-            cbData.cd = NULL;
-
-            // TODO change value of CT_ADAPTER_IP with val from discovery
-            OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, uri, 0, (OCPayload*)secPayload,
-                    CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
-            OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
-            if (ret != OC_STACK_OK)
-            {
-                OC_LOG(ERROR, TAG, "OCStack resource error");
-                SetResult(otmCtx, ret);
-                return OC_STACK_DELETE_TRANSACTION;
-            }
+            OICFree(secPayload);
+            SetResult(otmCtx, OC_STACK_INVALID_JSON);
             return OC_STACK_DELETE_TRANSACTION;
         }
-        else
+        OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
+
+        char uri[MAX_QUERY_LENGTH] = { 0 };
+        size_t uriLen = sizeof(uri);
+
+        snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
+                otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_PSTAT_URI);
+        uri[uriLen - 1] = '\0';
+        OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+        cbData.cb = &FinalizeProvisioningCB;
+        cbData.context = (void*)otmCtx; // forward context to SRPFinalizeProvisioningCB
+        cbData.cd = NULL;
+
+        // TODO change value of CT_ADAPTER_IP with val from discovery
+        OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, uri, 0, (OCPayload*)secPayload,
+                CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+        OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
+        if (ret != OC_STACK_OK)
         {
-            OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
-                                clientResponse->result);
-            SetResult(otmCtx, clientResponse->result);
+            OC_LOG(ERROR, TAG, "OCStack resource error");
+            SetResult(otmCtx, ret);
         }
     }
-
+    else
+    {
+        OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
+                            clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+exit:
     return OC_STACK_DELETE_TRANSACTION;
 }
 
@@ -1104,7 +1064,7 @@ OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
     }
     // Provision Default ACL to device
     OicSecAcl_t defaultAcl =
-    { {},
+    { {.id={0}},
         1,
         NULL,
         0x001F,
@@ -1116,7 +1076,7 @@ OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
         NULL,
     };
 
-    OicUuid_t provTooldeviceID = {{0,}};
+    OicUuid_t provTooldeviceID = {.id={0}};
     if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
     {
         OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
@@ -1149,6 +1109,7 @@ OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
     OICFree(defaultAcl.owners);
     if(!secPayload->securityData)
     {
+        OICFree(secPayload);
         OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
         SetResult(otmCtx, OC_STACK_ERROR);
         return OC_STACK_ERROR;
@@ -1163,7 +1124,7 @@ OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
     uri[uriLen - 1] = '\0';
     OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s",uri);
 
-    OCCallbackData cbData =  {};
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
     cbData.cb = &ProvisionDefaultACLCB;
     cbData.context = (void *)otmCtx;
     cbData.cd = NULL;
index f0bfa9e..ea595c5 100644 (file)
@@ -50,7 +50,7 @@ char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx)
         return NULL;
     }
 
-    OicUuid_t uuidPT = {};
+    OicUuid_t uuidPT = {.id={0}};
 
     if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
     {
@@ -86,16 +86,16 @@ OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
     OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
 
     OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
-    CAEndpoint_t* endpoint = CACloneEndpoint((CAEndpoint_t *)&selDevInfo->endpoint);
+    CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
     if(NULL == endpoint)
     {
         return OC_STACK_NO_MEMORY;
     }
+    memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
     endpoint->port = selDevInfo->securePort;
-    caresult = CAInitiateHandshake(endpoint);
 
+    caresult = CAInitiateHandshake(endpoint);
     OICFree(endpoint);
-
     if (CA_STATUS_OK != caresult)
     {
         OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
@@ -105,4 +105,3 @@ OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
     OC_LOG(INFO, TAG, "OUT CreateSecureSessionJustWorksCallback");
     return OC_STACK_OK;
 }
-
diff --git a/resource/csdk/security/provisioning/src/oxmrandompin.c b/resource/csdk/security/provisioning/src/oxmrandompin.c
new file mode 100644 (file)
index 0000000..ea09fb4
--- /dev/null
@@ -0,0 +1,145 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include <memory.h>
+
+#include "ocstack.h"
+#include "ocsecurityconfig.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "ocrandom.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "pbkdf2.h"
+#include "global.h"
+#include "base64.h"
+#include "oxmrandompin.h"
+#include "ownershiptransfermanager.h"
+#include "pinoxmcommon.h"
+
+#define TAG "OXM_RandomPIN"
+
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RANDOM_DEVICE_PIN;
+
+    OicUuid_t uuidPT = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OC_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);
+}
+
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    OicUuid_t uuidPT = {.id={0}};
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return NULL;
+    }
+    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+    otmCtx->selectedDeviceInfo->doxm->owned = true;
+
+    return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    uint8_t pinData[OXM_RANDOM_PIN_SIZE + 1];
+
+    OCStackResult res = InputPin((char*)pinData, OXM_RANDOM_PIN_SIZE + 1);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG(ERROR, TAG, "Failed to input PIN");
+        return res;
+    }
+
+    OicUuid_t deviceUUID = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&deviceUUID))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+
+    res = AddTmpPskWithPIN(&otmCtx->selectedDeviceInfo->doxm->deviceID,
+                           SYMMETRIC_PAIR_WISE_KEY,
+                           (char*)pinData, OXM_RANDOM_PIN_SIZE,
+                           1, &deviceUUID, &otmCtx->tempCredId);
+    if(res != OC_STACK_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
+    }
+
+    return res;
+}
+
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx)
+{
+    OC_LOG(INFO, TAG, "IN CreateSecureSessionRandomPinCallbak");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
+    CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+    if(NULL == endpoint)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+    memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
+    endpoint->port = selDevInfo->securePort;
+    CAResult_t caresult = CAInitiateHandshake(endpoint);
+    OICFree(endpoint);
+    if (CA_STATUS_OK != caresult)
+    {
+        OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+        return OC_STACK_ERROR;
+    }
+
+    OC_LOG(INFO, TAG, "OUT CreateSecureSessionRandomPinCallbak");
+
+    return OC_STACK_OK;
+}
index a6f6cbb..22c205d 100644 (file)
@@ -172,8 +172,8 @@ void DeleteDeviceList(OCProvisionDev_t **ppDevicesList)
  */
 OCStackResult PMTimeout(unsigned short waittime)
 {
-    struct timespec startTime = {};
-    struct timespec currTime  = {};
+    struct timespec startTime = {.tv_sec=0, .tv_nsec=0};
+    struct timespec currTime  = {.tv_sec=0, .tv_nsec=0};
 
     OCStackResult res = OC_STACK_OK;
 #ifdef _POSIX_MONOTONIC_CLOCK
@@ -268,7 +268,7 @@ uint16_t GetSecurePortFromJSON(char* jsonStr)
  *         OC_STACK_DELETE_TRANSACTION to delete it.
  */
 static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx,
-                                OCDoHandle handle, OCClientResponse *clientResponse)
+                                OCDoHandle UNUSED, OCClientResponse *clientResponse)
 {
     if (ctx == NULL)
     {
@@ -334,7 +334,7 @@ static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx,
  *         OC_STACK_DELETE_TRANSACTION to delete it.
  */
 static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx,
-                                OCDoHandle handle, OCClientResponse *clientResponse)
+                                OCDoHandle UNUSED, OCClientResponse *clientResponse)
 {
     if (ctx == NULL)
     {
@@ -472,4 +472,3 @@ OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisi
 exit:
     return res;
 }
-
index d30b062..a0f4120 100644 (file)
@@ -17,7 +17,6 @@
  * limitations under the License.
  *
  * *****************************************************************/
-
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
@@ -118,12 +117,12 @@ static void registerResultForCredProvisioning(CredentialData_t *credData,
  * Callback handler for handling callback of provisioning device 2.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
+ * @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 provisionCredentialCB2(void *ctx, OCDoHandle handle,
+static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
     VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
@@ -159,12 +158,12 @@ static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle han
  * Callback handler for handling callback of provisioning device 1.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
+ * @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 handle,
+static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
     VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
@@ -241,7 +240,13 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
     }
     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
     secPayload->securityData = BinToCredJSON(cred);
-    VERIFY_NON_NULL(TAG, secPayload->securityData, ERROR, OC_STACK_NO_MEMORY);
+    if(NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Failed to BinToCredJSON");
+        return OC_STACK_NO_MEMORY;
+    }
+
     OC_LOG_V(INFO, TAG, "Credential for provisioning : %s",secPayload->securityData);
     char uri[SRP_MAX_URI_LENGTH] = { 0 };
 
@@ -251,7 +256,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
 
     uri[uriLen - 1] = '\0';
     OC_LOG_V(INFO, TAG, "URI for Credential provisioning : %s",uri);
-    OCCallbackData cbData = { };
+    OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
     cbData.cb = responseHandler;
     cbData.context = (void *) credData;
     cbData.cd = NULL;
@@ -259,7 +264,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred,
     OCDoHandle handle = NULL;
     OCMethod method = OC_REST_POST;
     // TODO replace CT_ADAPTER_IP with value from discovery
-    OCStackResult ret = OCDoResource(&handle, method, uri, 0, secPayload,
+    OCStackResult ret = OCDoResource(&handle, method, uri, 0, (OCPayload*)secPayload,
             CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
     OC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d",ret);
     if (ret != OC_STACK_OK)
@@ -372,12 +377,12 @@ static void registerResultForACLProvisioning(ACLData_t *aclData,
  * Callback handler of SRPProvisionACL.
  *
  * @param[in] ctx             ctx value passed to callback from calling function.
- * @param[in] handle          handle to an invocation
+ * @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 SRPProvisionACLCB(void *ctx, OCDoHandle handle,
+static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
         OCClientResponse *clientResponse)
 {
     OC_LOG_V(INFO, TAG, "Inside SRPProvisionACLCB.");
@@ -423,7 +428,12 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     }
     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
     secPayload->securityData = BinToAclJSON(acl);
-    VERIFY_NON_NULL(TAG, secPayload->securityData, ERROR, OC_STACK_NO_MEMORY);
+    if(NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Failed to BinToAclJSON");
+        return OC_STACK_NO_MEMORY;
+    }
     OC_LOG_V(INFO, TAG, "ACL : %s", secPayload->securityData);
 
     char uri[SRP_MAX_URI_LENGTH] = {0};
@@ -434,11 +444,12 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     uri[uriLen - 1] = '\0';
 
     OC_LOG_V(INFO, TAG, "URI : %s", uri);
-    OCCallbackData cbData =  {0,};
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
     cbData.cb = &SRPProvisionACLCB;
     ACLData_t *aclData = (ACLData_t *) OICMalloc(sizeof(ACLData_t));
     if (aclData == NULL)
     {
+        OICFree(secPayload);
         OC_LOG(ERROR, TAG, "Unable to allocate memory");
         return OC_STACK_NO_MEMORY;
     }
@@ -452,6 +463,7 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     aclData->resArr = (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t)*noOfRiCalls);
     if (aclData->resArr == NULL)
     {
+        OICFree(secPayload);
         OC_LOG(ERROR, TAG, "Unable to allocate memory");
         return OC_STACK_NO_MEMORY;
     }
@@ -464,9 +476,8 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     // TODO replace CT_ADAPTER_IP with value from discovery
 
     OCStackResult ret = OCDoResource(&handle, method, uri,
-            &selectedDeviceInfo->endpoint, secPayload,
+            &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
             CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
-
     if (ret != OC_STACK_OK)
     {
         OICFree(aclData->resArr);
index 0b197c0..9f69a11 100644 (file)
@@ -19,8 +19,7 @@
  * *****************************************************************/
 #include "gtest/gtest.h"
 #include "oxmjustworks.h"
-// TODO: PIN based OxM implementation is required.
-//#include "oxmrandompin.h"
+#include "oxmrandompin.h"
 #include "ownershiptransfermanager.h"
 #include "ocstack.h"
 #include "utlist.h"
@@ -64,8 +63,6 @@ TEST(JustWorksOxMTest, NullParam)
     EXPECT_TRUE(NULL == payloadRes);
 }
 
-// TODO: PIN based OxM implementation is required
-/*
 TEST(RandomPinOxMTest, NullParam)
 {
     OTMContext_t* otmCtx = NULL;
@@ -100,5 +97,4 @@ TEST(RandomPinOxMTest, NullParam)
 
     payloadRes = CreatePinBasedOwnerTransferPayload(&otmCtx2);
     EXPECT_TRUE(NULL == payloadRes);
-}*/
-
+}
index 641820c..bbf365b 100644 (file)
@@ -26,7 +26,8 @@ static OCProvisionDev_t pDev1;
 static OCProvisionDev_t pDev2;
 static OicSecCredType_t credType;
 
-static void provisioningCB (void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+static void provisioningCB (void* UNUSED1, int UNUSED2,
+                            OCProvisionResult_t *UNUSED3, bool UNUSED4)
 {
     //dummy callback
 }
@@ -48,15 +49,21 @@ TEST(SRPProvisionACLTest, NullACL)
 
 TEST(SRPProvisionCredentialsTest, NullDevice1)
 {
-    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType, OWNER_PSK_LENGTH_128, NULL, &pDev2, &provisioningCB));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+                                                              OWNER_PSK_LENGTH_128, NULL,
+                                                              &pDev2, &provisioningCB));
 }
 
 TEST(SRPProvisionCredentialsTest, NullCallback)
 {
-    EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionCredentials(NULL, credType, OWNER_PSK_LENGTH_128, &pDev1, &pDev2, NULL));
+    EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionCredentials(NULL, credType,
+                                                                 OWNER_PSK_LENGTH_128,
+                                                                 &pDev1, &pDev2, NULL));
 }
 
 TEST(SRPProvisionCredentialsTest, InvalidKeySize)
 {
-    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType, 0, &pDev1, &pDev2, &provisioningCB));
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+                                                                0, &pDev1, &pDev2,
+                                                                &provisioningCB));
 }
\ No newline at end of file
index 0714c27..901e5d5 100644 (file)
@@ -33,6 +33,7 @@
 #include "base64.h"
 #include "srmutility.h"
 #include "cainterface.h"
+#include "pbkdf2.h"
 #include <stdlib.h>
 #ifdef WITH_ARDUINO
 #include <string.h>
@@ -306,7 +307,7 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr)
             //Owners -- Mandatory
             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR)
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
             cred->ownersLen = cJSON_GetArraySize(jsonObj);
             VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
             cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
@@ -861,4 +862,61 @@ exit:
     }
     OICFree(caBlob);
 }
+
+/**
+ * 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)
+    {
+        OC_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)
+    {
+        OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
+    }
+
+exit:
+    return ret;
+}
+
 #endif /* __WITH_DTLS__ */
index 8251214..502dc7c 100644 (file)
 #include "credresource.h"
 #include "ocserverrequest.h"
 #include "srmutility.h"
+#include "pinoxmcommon.h"
+
+#ifdef __WITH_DTLS__
+#include "global.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -229,7 +235,7 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
     jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
     if(jsonObj)
     {
-        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
         doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
     }
     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
@@ -242,7 +248,7 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
     jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
     if(jsonObj)
     {
-        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR)
+        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
         doxm->owned = jsonObj->valueint;
     }
     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
@@ -277,16 +283,19 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
         strncpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
     }
 
-    // Owner -- will be empty when device state is unowned.
-    if (true == doxm->owned)
+    //Owner -- will be empty when device status is unowned.
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
+    if(true == doxm->owned)
     {
-        jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
         VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR)
-            outLen = 0;
+    }
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, (cJSON_String == jsonObj->type), ERROR);
+        outLen = 0;
         b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
                 sizeof(base64Buff), &outLen);
-        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->owner.id)), ERROR);
+        VERIFY_SUCCESS(TAG, ((b64Ret == B64_OK) && (outLen <= sizeof(doxm->owner.id))), ERROR);
         memcpy(doxm->owner.id, base64Buff, outLen);
     }
 
@@ -408,6 +417,51 @@ 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);
+
+    OC_LOG (INFO, TAG, PCF("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;
+    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)
 {
@@ -455,40 +509,16 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                  *
                  */
 #ifdef __WITH_DTLS__
-                CAResult_t pskRet;
-
                 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
-                uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
 
                 //Generating OwnerPSK
                 OC_LOG (INFO, TAG, PCF("Doxm EntityHandle  generating OwnerPSK"));
-                pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
-                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS),
-                        newDoxm->owner.id, sizeof(newDoxm->owner.id),
-                        gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
-                        ownerPSK, OWNER_PSK_LENGTH_128);
-
-                VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
-
-                //Generating new credential for provisioning tool
-                size_t ownLen = 1;
-                uint32_t outLen = 0;
 
-                char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
-                B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff,
-                                sizeof(base64Buff), &outLen);
-                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+                //Generate new credential for provisioning tool
+                ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
 
-                OC_LOG (INFO, TAG, PCF("Doxm EntityHandle  generating Credential"));
-                OicSecCred_t *cred = GenerateCredential(&newDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
-                                        NULL, base64Buff, ownLen, &newDoxm->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;
-                memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+                VERIFY_SUCCESS(TAG, ehRet = OC_EH_OK, ERROR);
 
                 // Update new state in persistent storage
                 if (true == UpdatePersistentStorage(gDoxm))
@@ -515,6 +545,75 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
 #endif //__WITH_DTLS__
             }
         }
+        else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
+        {
+            //this temp Credential ID is used to track temporal Cred Id
+            static OicUuid_t tmpCredId = {.id={0}};
+            static bool tmpCredGenFlag = false;
+
+            if ((false == gDoxm->owned) && (false == newDoxm->owned))
+            {
+#ifdef __WITH_DTLS__
+                CAEnableAnonECDHCipherSuite(false);
+                OC_LOG(DEBUG, 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(tmpCredGenFlag)
+                    {
+                       OC_LOG(DEBUG, TAG, "Corrupted PSK is detected!!!");
+                       VERIFY_SUCCESS(TAG,
+                                      OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+                                      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
+                {
+                    OC_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;
+
+                //Remove Temporal Credential resource
+                if(tmpCredGenFlag)
+                {
+                    VERIFY_SUCCESS(TAG,
+                                   OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+                                   ERROR);
+                    tmpCredGenFlag = false;
+                }
+
+                //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
+                ehRet = (UpdatePersistentStorage(gDoxm) == true) ? OC_EH_OK : OC_EH_ERROR;
+#endif
+             }
+        }
     }
 
 exit:
diff --git a/resource/csdk/security/src/oxmpincommon.c b/resource/csdk/security/src/oxmpincommon.c
new file mode 100644 (file)
index 0000000..fc7c0f3
--- /dev/null
@@ -0,0 +1,110 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include "ocstack.h"
+#include "ocrandom.h"
+#include "logger.h"
+#include "pinoxmcommon.h"
+
+#define TAG PCF("PIN_OXM_COMMON")
+
+static GeneratePinCallback gGenPinCallback = NULL;
+static InputPinCallback gInputPinCallback = NULL;
+
+void SetInputPinCB(InputPinCallback pinCB)
+{
+    if(NULL == pinCB)
+    {
+        OC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
+        return;
+    }
+
+    gInputPinCallback = pinCB;
+}
+
+void SetGeneratePinCB(GeneratePinCallback pinCB)
+{
+    if(NULL == pinCB)
+    {
+        OC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
+        return;
+    }
+
+    gGenPinCallback = pinCB;
+}
+
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
+{
+    if(!pinBuffer)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+        return OC_STACK_INVALID_PARAM;
+    }
+    for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
+    {
+        pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
+    }
+    pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
+
+    if(gGenPinCallback)
+    {
+        gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE);
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+        OC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
+        return OC_STACK_ERROR;
+    }
+
+    return OC_STACK_OK;
+}
+
+
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
+{
+    if(!pinBuffer)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if(gInputPinCallback)
+    {
+        gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+        OC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use PIN based OxM.");
+        return OC_STACK_ERROR;
+    }
+
+    return OC_STACK_OK;
+}
diff --git a/resource/csdk/security/src/pbkdf2.c b/resource/csdk/security/src/pbkdf2.c
new file mode 100644 (file)
index 0000000..71b6d02
--- /dev/null
@@ -0,0 +1,149 @@
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include <string.h>
+#include <math.h>
+#include "pbkdf2.h"
+#include "hmac.h"
+#include "debug.h"
+#include "logger.h"
+
+#define TAG "PBDKF2"
+#define XOR_BUF(in, out, bufSize)\
+do{\
+    size_t i=0;\
+    for(i=0; i< (bufSize); i++)\
+    {\
+        (out)[i] = (in)[i] ^ (out)[i];\
+    }\
+}while(0)\
+
+
+static int isLittle()
+{
+    static int a = 1;
+    static int flag = -1;
+    if (flag == -1)
+    {
+        if (  ((uint8_t *)&a)[0]  == 0x1) // little
+            flag = 1;
+        else
+            flag = 0;
+    }
+    return flag;
+}
+
+static void GetBigEndianBuf(uint8_t *buf, int num)
+{
+    uint8_t *nBuf = (uint8_t *)&num;
+    if ( isLittle() == 1 )
+    {
+        int i = 0;
+        for (i = 0; i < sizeof(int); i++)
+        {
+            buf[i] = nBuf[ sizeof(int) - i - 1];
+        }
+    }
+    else
+    {
+        memcpy(buf, nBuf, sizeof(int));
+    }
+}
+
+// TODO: Add comments to explain implementation.
+int DeriveCryptoKeyFromPassword(const unsigned char *passwd, size_t pLen,
+                                const uint8_t *salt, const size_t saltLen,
+                                const size_t iterations,
+                                const size_t keyLen, uint8_t *derivedKey)
+{
+    int res = 0;
+    uint8_t buf[DTLS_HMAC_DIGEST_SIZE];
+    uint8_t uBuf[DTLS_HMAC_DIGEST_SIZE];
+
+    size_t nBlocks = 0;
+    size_t nOctetInLastBlock = 0;
+
+    nBlocks = (size_t)ceil ((double)keyLen / (double)DTLS_HMAC_DIGEST_SIZE);
+    nOctetInLastBlock = keyLen - (nBlocks - 1) * DTLS_HMAC_DIGEST_SIZE;
+
+    dtls_hmac_context_t *ctx = NULL;
+    ctx = dtls_hmac_new( (const unsigned char *)passwd, pLen);
+    if (NULL == ctx)
+    {
+        OC_LOG(ERROR, TAG, "DTLS HMAC Context is NULL");
+        goto bail;
+    }
+
+    size_t i = 1;
+    size_t idx = 0; //index for buffer
+    size_t counter = 0;
+    while (i != nBlocks + 1)
+    {
+        counter = 0 ;
+        dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+        while (counter != iterations)
+        {
+            if (counter == 0)
+            {
+                uint8_t intBuf[4] = {0x00, 0x00, 0x00, 0x00};
+                dtls_hmac_update(ctx, salt, saltLen);
+                GetBigEndianBuf(intBuf, i);
+                dtls_hmac_update(ctx, intBuf, 4);
+
+                int len = dtls_hmac_finalize(ctx, buf);
+                if (DTLS_HMAC_DIGEST_SIZE != len)
+                {
+                    OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+                    res = -1;
+                }
+                memcpy(uBuf, buf, DTLS_HMAC_DIGEST_SIZE);
+            }
+            else
+            {
+                dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+                dtls_hmac_update(ctx, buf, DTLS_HMAC_DIGEST_SIZE);
+                int len = dtls_hmac_finalize(ctx, buf);
+                if (DTLS_HMAC_DIGEST_SIZE != len)
+                {
+                    OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+                    res = -1;
+                }
+                XOR_BUF(buf, uBuf, DTLS_HMAC_DIGEST_SIZE);
+            }
+            counter++;
+        }
+
+
+        if (i == nBlocks)
+        {
+            memcpy(derivedKey + idx, uBuf, nOctetInLastBlock);
+        }
+        else
+        {
+            memcpy(derivedKey + idx, uBuf, DTLS_HMAC_DIGEST_SIZE);
+            idx += DTLS_HMAC_DIGEST_SIZE;
+        }
+        i++;
+    }
+
+bail:
+    dtls_hmac_free(ctx);
+    return res;
+}
+