Add direct-pairing feature
authorJoonghwan Lee <jh05.lee@samsung.com>
Thu, 10 Mar 2016 05:57:03 +0000 (14:57 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Fri, 11 Mar 2016 12:25:28 +0000 (12:25 +0000)
 <contents of modification/addition>
 : Added direct-pairing resouces and related types
 : Added direct-pairing provisioning feature for provisioning tool
 : Added D2D pairing operation feature(discovery, pairing) for client
 : Added RI layer APIs and data types for direct-pairing client
 : Modified provisioning tool for direct-pairing feature and created new sample client

-Patch 1: Initial
-Patch 2: Fix OSX build error.
-Patch 3: Add DPC(Direct Pairing Capability) resource and processing logic
-Patch 4: Fix dpc parse error when loading svr db
-Patch 5: Fix unnormal processing when duplicated request on dpairing resource & Change DPC default value as true
-Patch 6: Fix SVACE warning & Divide pconf and dpairing resource into another ACL entry in svr db
-Patch 7: Fix SVACE warning's positive false
-Patch 8: Fix device list management

Change-Id: I461626fe041a5927c0e27e78e63e74e215d61cd5
Signed-off-by: Joonghwan Lee <jh05.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5673
Reviewed-by: Jongsung Lee <js126.lee@samsung.com>
Reviewed-by: Kyungsun Cho <goodsun.cho@samsung.com>
Reviewed-by: Chul Lee <chuls.lee@samsung.com>
Reviewed-by: dongik Lee <dongik.lee@samsung.com>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
Tested-by: Randeep Singh <randeep.s@samsung.com>
30 files changed:
resource/csdk/SConscript
resource/csdk/security/SConscript
resource/csdk/security/include/internal/directpairing.h [new file with mode: 0644]
resource/csdk/security/include/internal/dpairingresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/pconfresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
resource/csdk/security/provisioning/include/ocprovisioningmanager.h
resource/csdk/security/provisioning/include/pmtypes.h
resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json [changed mode: 0644->0755]
resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/credresource.c
resource/csdk/security/src/directpairing.c [new file with mode: 0644]
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/dpairingresource.c [new file with mode: 0755]
resource/csdk/security/src/pconfresource.c [new file with mode: 0644]
resource/csdk/security/src/psinterface.c
resource/csdk/security/src/resourcemanager.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/samples/linux/secure/SConscript
resource/csdk/stack/samples/linux/secure/occlientdirectpairing.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/oic_svr_db_client_directpairing.json [new file with mode: 0644]
resource/csdk/stack/src/ocstack.c

index b6f83ba..37dc29b 100644 (file)
@@ -55,6 +55,7 @@ liboctbstack_env.PrependUnique(CPPPATH = [
                'connectivity/external/inc',
                'security/include',
                'security/include/internal',
+               'security/provisioning/include',
                ])
 
 if target_os not in ['arduino', 'windows', 'winrt']:
index 276c2b3..f2aed83 100644 (file)
@@ -52,7 +52,8 @@ libocsrm_env.PrependUnique(CPPPATH = [
                '../connectivity/inc',
                '../connectivity/api',
                '../security/include',
-               '../security/include/internal'
+               '../security/include/internal',
+               '../security/provisioning/include'
                ])
 
 if target_os not in ['arduino', 'windows', 'winrt']:
@@ -97,6 +98,8 @@ if env.get('SECURED') == '1':
                OCSRM_SRC + 'doxmresource.c',
                OCSRM_SRC + 'credresource.c',
                OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'pconfresource.c',
+               OCSRM_SRC + 'dpairingresource.c',
                OCSRM_SRC + 'policyengine.c',
                OCSRM_SRC + 'psinterface.c',
                OCSRM_SRC + 'srmresourcestrings.c',
@@ -106,7 +109,8 @@ if env.get('SECURED') == '1':
                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'
+               OCSRM_SRC + 'pbkdf2.c',
+               OCSRM_SRC + 'directpairing.c'
                ]
 else:
        libocsrm_src = [
@@ -119,12 +123,15 @@ else:
                OCSRM_SRC + 'doxmresource.c',
                OCSRM_SRC + 'credresource.c',
                OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'pconfresource.c',
+               OCSRM_SRC + 'dpairingresource.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'
+               OCSRM_SRC + 'base64.c',
+               OCSRM_SRC + 'directpairing.c'
                ]
 
 if env.get('DTLS_WITH_X509') == '1' and env.get('SECURED') == '1':
diff --git a/resource/csdk/security/include/internal/directpairing.h b/resource/csdk/security/include/internal/directpairing.h
new file mode 100644 (file)
index 0000000..e884c9a
--- /dev/null
@@ -0,0 +1,82 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#ifndef _DIRECT_PAIRING_H_\r
+#define _DIRECT_PAIRING_H_\r
+\r
+#include <stdbool.h>\r
+#include "ocstack.h"\r
+#include "pmtypes.h"\r
+#include "securevirtualresourcetypes.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+/**\r
+ * Discover direct-pairing devices in the same IP subnet. .\r
+ *\r
+ * @param[in] waittime  Timeout in seconds.\r
+ *\r
+ * @return OC_STACK_OK on success otherwise error.\r
+ */\r
+OCStackResult DPDeviceDiscovery(unsigned short waittime);\r
+\r
+/**\r
+ * Start direct-pairing processes.\r
+ *\r
+ * @param[in] peer  target device to establish direct-pairing.\r
+ * @param[in] pmSel  selected pairing method.\r
+ * @param[in] pinNumber  secret value for dtls connection.\r
+ * @param[in] resultCallback  result event callback.\r
+ *\r
+ * @return OC_STACK_OK on success otherwise error.\r
+ */\r
+OCStackResult DPDirectPairing(OCDirectPairingDev_t* peer, OicSecPrm_t pmSel, char *pinNumber,\r
+                                                     OCDirectPairingResultCB resultCallback);\r
+\r
+/**\r
+ * This function returns discovered devices list in direct-pairing discovery\r
+ * Caller must NOT free returned constant pointer\r
+ *\r
+ * @return OCDirectPairingDev_t pointer on success otherwise NULL.\r
+ */\r
+const OCDirectPairingDev_t* DPGetDiscoveredDevices();\r
+\r
+/**\r
+ * This function returns paired devices list until now\r
+ * Caller must NOT free returned constant pointer\r
+ *\r
+ * @return OCDirectPairingDev_t pointer on success otherwise NULL.\r
+ */\r
+const OCDirectPairingDev_t* DPGetPairedDevices();\r
+\r
+/**\r
+ * This function delete both discovered devices and paired devices list\r
+ *\r
+ */\r
+void DPDeleteLists();\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif //_DIRECT_PAIRING_H_\r
+\r
diff --git a/resource/csdk/security/include/internal/dpairingresource.h b/resource/csdk/security/include/internal/dpairingresource.h
new file mode 100644 (file)
index 0000000..dbb5ce9
--- /dev/null
@@ -0,0 +1,99 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#ifndef IOTVT_SRM_DPAIRING_H\r
+#define IOTVT_SRM_DPAIRING_H\r
+\r
+#include "octypes.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/**\r
+ * Initialize DPAIRING resource by loading data from persistent storage.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult InitDpairingResource();\r
+\r
+/**\r
+ * Perform cleanup for DPAIRING resources.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult DeInitDpairingResource();\r
+\r
+/**\r
+ * This method converts JSON DPAIRING into binary DPAIRING.\r
+ * The JSON DPAIRING can be from persistent database or\r
+ * or received as POST request.\r
+ *\r
+ * @param[in] jsonStr  pconf data in json string.\r
+ * @return pointer to OicSecDpairing_t.\r
+ *\r
+ * @note Caller needs to invoke OCFree after done\r
+ *       using the return pointer\r
+ */\r
+OicSecDpairing_t * JSONToDpairingBin(const char * jsonStr);\r
+\r
+/**\r
+ * This method converts DPAIRING data into JSON format.\r
+ * Caller needs to invoke 'free' when finished done using\r
+ * return string\r
+ *\r
+ * @param[in] dpair  Pointer to OicSecDpairing_t.\r
+ * @return pointer to json string.\r
+ *\r
+ * @note Caller needs to invoke OCFree after done\r
+ *       using the return pointer\r
+ */\r
+char * BinToDpairingJSON(const OicSecDpairing_t * dpair);\r
+\r
+/** This function deallocates the memory for OicSecPconf_t .\r
+ *\r
+ * @param[in] dpair  Pointer to OicSecDpairing_t.\r
+ */\r
+void DeleteDpairingBinData(OicSecDpairing_t* dpair);\r
+\r
+#ifdef __WITH_DTLS__\r
+/**\r
+ * Function to save PairingPSK.\r
+ *\r
+ * @param[in] endpoint   current endpoint.\r
+ * @param[in] peerDevID   peer device indentitiy.\r
+ * @param[in] isPairingServer   indicate if it generates PairingPSK for server or client.\r
+ *\r
+ * @return  OC_STACK_OK on success\r
+ */\r
+OCStackResult SavePairingPSK(OCDevAddr *endpoint,\r
+            OicUuid_t *peerDevID, OicUuid_t *owner, bool isPairingServer);\r
+#endif // __WITH_DTLS__\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif //IOTVT_SRM_DPAIRING_H\r
+\r
+\r
+\r
+\r
diff --git a/resource/csdk/security/include/internal/pconfresource.h b/resource/csdk/security/include/internal/pconfresource.h
new file mode 100644 (file)
index 0000000..70366ac
--- /dev/null
@@ -0,0 +1,124 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#ifndef IOTVT_SRM_PCONF_H\r
+#define IOTVT_SRM_PCONF_H\r
+\r
+#include "octypes.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/**\r
+ * Initialize PCONF resource by loading data from persistent storage.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult InitPconfResource();\r
+\r
+/**\r
+ * Perform cleanup for PCONF resources.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult DeInitPconfResource();\r
+\r
+/**\r
+ * This method is used by SRM to retrieve PCONF resource data..\r
+ *\r
+ * @retval  reference to @ref OicSecPconf_t, binary format of Pconf resource data\r
+ */\r
+const OicSecPconf_t* GetPconfResourceData();\r
+\r
+/**\r
+ * This method converts JSON PCONF into binary PCONF.\r
+ * The JSON PCONF can be from persistent database or\r
+ * or received as PUT request.\r
+ *\r
+ * @param[in] jsonStr  pconf data in json string.\r
+ * @return pointer to OicSecPconf_t.\r
+ *\r
+ * @note Caller needs to invoke OCFree after done\r
+ *       using the return pointer\r
+ */\r
+OicSecPconf_t * JSONToPconfBin(const char * jsonStr);\r
+\r
+/**\r
+ * This method converts PCONF data into JSON format.\r
+ * Caller needs to invoke 'free' when finished done using\r
+ * return string\r
+ *\r
+ * @param[in] pconf  Pointer to OicSecPconf_t.\r
+ * @return pointer to json string.\r
+ *\r
+ * @note Caller needs to invoke OCFree after done\r
+ *       using the return pointer\r
+ */\r
+char * BinToPconfJSON(const OicSecPconf_t * pconf);\r
+\r
+/**\r
+ * This method might be used to add a paired device id after direct-pairing process complete.\r
+ *\r
+ * @param pdeviceId ID of the paired device.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult AddPairedDevice(OicUuid_t *pdeviceId);\r
+\r
+/**\r
+ * This method might be used by PolicyEngine to retrieve PDACL for a Subject.\r
+ *\r
+ * @param subjectId ID of the subject for which PDACL is required.\r
+ * @param savePtr is used internally by @ref GetACLResourceData to maintain index between\r
+ *                successive calls for same subjectId.\r
+ *\r
+ * @retval  reference to @ref OicSecPdAcl_t if PDACL is found, else NULL\r
+ */\r
+const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr);\r
+\r
+/**\r
+ * This method return whether device is paired or not.\r
+ *\r
+ * @param pdeviceId Target device ID to find in paired list.\r
+ * @retval  ture if device is already paired, else false\r
+ */\r
+bool IsPairedDevice(const OicUuid_t* pdeviceId);\r
+\r
+/** This function deallocates the memory for OicSecPconf_t .\r
+ *\r
+ * @param[in] pconf  Pointer to OicSecPconf_t.\r
+ */\r
+void DeletePconfBinData(OicSecPconf_t* pconf);\r
+\r
+/**\r
+ * This function frees OicSecPdAcl_t object's fields and object itself.\r
+ */\r
+void FreePdAclList(OicSecPdAcl_t* pdacls);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif //IOTVT_SRM_PCONF_H\r
+\r
+\r
+\r
index 1ac3fb0..568bfa4 100644 (file)
@@ -62,6 +62,16 @@ extern const char * OIC_RSRC_TYPE_SEC_SVC;
 extern const char * OIC_RSRC_SVC_URI;
 extern const char * OIC_JSON_SVC_NAME;
 
+//PCONF
+extern const char * OIC_RSRC_TYPE_SEC_PCONF;
+extern const char * OIC_RSRC_PCONF_URI;
+extern const char * OIC_JSON_PCONF_NAME;
+
+//DPAIRING
+extern const char * OIC_RSRC_TYPE_SEC_DPAIRING;
+extern const char * OIC_RSRC_DPAIRING_URI;
+extern const char * OIC_JSON_DPAIRING_NAME;
+
 extern const char * OIC_JSON_SUBJECT_NAME;
 extern const char * OIC_JSON_RESOURCES_NAME;
 extern const char * OIC_JSON_AMSS_NAME;
@@ -91,6 +101,15 @@ extern const char * OIC_JSON_SM_NAME;
 extern const char * OIC_JSON_SERVICE_DEVICE_ID;
 extern const char * OIC_JSON_SERVICE_TYPE;
 extern const char * OIC_JSON_SUPPORTED_CRED_TYPE_NAME;
+extern const char * OIC_JSON_DPC_NAME;
+extern const char * OIC_JSON_EDP_NAME;
+extern const char * OIC_JSON_PIN_NAME;
+extern const char * OIC_JSON_PDACL_NAME;
+extern const char * OIC_JSON_PDDEV_LIST_NAME;
+extern const char * OIC_JSON_ROWNER_NAME;
+extern const char * OIC_JSON_PRM_NAME;
+extern const char * OIC_JSON_SPM_NAME;
+extern const char * OIC_JSON_PDEVICE_ID_NAME;
 
 extern OicUuid_t WILDCARD_SUBJECT_ID;
 extern size_t WILDCARD_SUBJECT_ID_LEN;
index 83dc60f..d8f7048 100644 (file)
@@ -379,6 +379,7 @@ struct OicSecDoxm
     //TODO: Need more clarification on deviceIDFormat field type.
     //OicSecDvcIdFrmt_t   deviceIDFormat; // 5:R:S:Y:UINT8
     OicUuid_t           deviceID;       // 6:R:S:Y:oic.uuid
+    bool                   dpc;             // 7:R:S:Y:Boolean
     OicUuid_t           owner;         // 7:R:S:Y:oic.uuid
     // NOTE: we are using UUID for Owner instead of Svc type for mid-April
     // SRM version only; this will change to Svc type for full implementation.
@@ -451,6 +452,83 @@ struct OicSecCrl
 };
 #endif /* __WITH_X509__ */
 
+/**
+ * @brief   direct pairing data type
+ */
+typedef struct OicPin OicDpPin_t;
+
+typedef struct OicSecPdAcl OicSecPdAcl_t;
+
+typedef struct OicSecPconf OicSecPconf_t;
+
+typedef struct OicSecDpairing OicSecDpairing_t;
+
+#define DP_PIN_LENGTH 8 // temporary length
+
+/**
+ * @brief   /oic/sec/prmtype (Pairing Method Type) data type.
+ *              0:  not allowed
+ *              1:  pre-configured pin
+ *              2:  random pin
+ */
+typedef enum PRMBitmask
+{
+    PRM_NOT_ALLOWED             = 0x0,
+    PRM_PRE_CONFIGURED        = (0x1 << 0),
+    PRM_RANDOM_PIN               = (0x1 << 1),
+} PRMBitmask_t;
+
+typedef PRMBitmask_t OicSecPrm_t;
+
+
+struct OicPin
+{
+    uint8_t             val[DP_PIN_LENGTH+1];
+};
+
+/**
+ * @brief   oic.sec.dpacltype (Device Pairing Access Control List) data type.
+ */
+struct OicSecPdAcl
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    char                  **resources;        // 0:R:M:Y:String
+    size_t                resourcesLen;      // the number of elts in Resources
+    uint16_t             permission;        // 1:R:S:Y:UINT16
+    char                  **periods;            // 2:R:M*:N:String (<--M*; see Spec)
+    char                  **recurrences;    // 3:R:M:N:String
+    size_t                prdRecrLen;         // the number of elts in Periods/Recurrences
+    OicSecPdAcl_t    *next;
+};
+
+/**
+ * @brief   /oic/sec/pconf (Pairing Configuration) data type
+ */
+struct OicSecPconf
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    bool                  edp;                // 0:W:S:M:Boolean
+    OicSecPrm_t      *prm;              // 1:R:M:N:UINT16
+    size_t                prmLen;          // the number of elts in Prm
+    OicDpPin_t          pin;               // 2:R:S:Y:String
+    OicSecPdAcl_t    *pdacls;         // 3:R:M:Y:oic.sec.pdacltype
+    OicUuid_t           *pddevs;        // 4:R:M:Y:oic.uuid
+    size_t                 pddevLen;     // the number of elts in pddev
+    OicUuid_t           deviceID;       // 5:R:S:Y:oic.uuid
+    OicUuid_t           rowner;          // 6:R:S:Y:oic.uuid
+};
+
+/**
+ * @brief   /oic/sec/dpairing (Device Pairing) data type
+ */
+struct OicSecDpairing
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    OicSecPrm_t      spm;               // 0:R/W:S:Y:UINT16
+    OicUuid_t           pdeviceID;     // 1:R:S:Y:oic.uuid
+    OicUuid_t           rowner;          // 2:R:S:Y:oic.uuid
+};
+
 #ifdef __cplusplus
 }
 #endif
index 2fff7f7..df55c0b 100644 (file)
@@ -43,6 +43,18 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
                                         OicSecAcl_t *acl, OCProvisionResultCB resultCallback);
 
 /**
+ * API to send Direct-Pairing Configuration to a device.
+ *
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] pconf PCONF pointer.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+                                        OicSecPconf_t *pconf, OCProvisionResultCB resultCallback);
+
+/**
  * API to provision credential to devices.
  *
  * @param[in] type Type of credentials to be provisioned to the device.
index f5a057e..54a5267 100644 (file)
@@ -117,6 +117,19 @@ OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceIn
                              OCProvisionResultCB resultCallback);\r
 \r
 /**\r
+ * this function sends Direct-Pairing Configuration to a device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] selectedDeviceInfo Selected target device.\r
+ * @param[in] pconf PCONF pointer.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning\r
+              request recieves a response from resource server.\r
+ * @return  OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf,\r
+                             OCProvisionResultCB resultCallback);\r
+\r
+/**\r
  * API to provision credential to devices.\r
  *\r
  * @param[in] ctx Application context would be returned in result callback.\r
@@ -216,6 +229,13 @@ void OCDeleteUuidList(OCUuidList_t* pList);
  * @param pAcl Pointer to OicSecAcl_t structure.\r
  */\r
 void OCDeleteACLList(OicSecAcl_t* pAcl);
+\r
+/**\r
+ * This function deletes PDACL data.\r
+ *\r
+ * @param pPdAcl Pointer to OicSecPdAcl_t structure.\r
+ */\r
+void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl);\r
 
 #ifdef __WITH_X509__
 /**
index 4313e36..2f23125 100644 (file)
@@ -72,6 +72,22 @@ typedef struct OCProvisionDev
 }OCProvisionDev_t;
 
 /**
+ * Device Information of discoverd direct pairing device(s).
+ */
+typedef struct OCDirectPairingDev
+{
+    OCDevAddr               endpoint;
+    OCConnectivityType   connType;
+    uint16_t                     securePort;
+    bool              edp;
+    OicSecPrm_t  *prm;
+    size_t            prmLen;
+    OicUuid_t       deviceID;
+    OicUuid_t       rowner;
+    struct OCDirectPairingDev *next;
+} OCDirectPairingDev_t;
+
+/**
  * Result information for each target device.
  */
 typedef struct OCPMResult{
@@ -90,6 +106,17 @@ typedef struct OCPMResult{
  */
 typedef void (*OCProvisionResultCB)(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError);
 
+
+/**
+ * Callback function definition of direct-pairing
+ *
+ * @param[OUT] peer - pairing device info.
+ * @param[OUT} result - It's returned with 'OC_STACK_XXX'. It will return 'OC_STACK_OK'
+ *                                   if D2D pairing is success without error
+ */
+typedef void (*OCDirectPairingResultCB)(OCDirectPairingDev_t *peer, OCStackResult result);
+
+
 #ifdef __cplusplus
 }
 #endif
old mode 100644 (file)
new mode 100755 (executable)
index bde9010..8dc08f6
              "ownrs" : [
                  "anVzdHdvcmtzRGV2VVVJRA=="
              ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/pconf",
+                "/oic/sec/dpairing"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "anVzdHdvcmtzRGV2VVVJRA=="
+             ]
         }
        ],
        "pstat":        {
@@ -41,6 +52,7 @@
                "oxmsel": 0,
                "sct": 1,
                "owned": false,
-               "deviceid":     "anVzdHdvcmtzRGV2VVVJRA=="
+               "deviceid":     "anVzdHdvcmtzRGV2VVVJRA==",
+               "dpc": true
        }
 }
index a79a2b2..4caf960 100644 (file)
              "ownrs" : [
                  "cmFuZG9tUGluRGV2VVVJRA=="
              ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/pconf",
+                "/oic/sec/dpairing"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "cmFuZG9tUGluRGV2VVVJRA=="
+             ]
         }
        ],
        "pstat":        {
@@ -41,6 +52,7 @@
                "oxmsel": 0,
                "sct": 1,
                "owned": false,
-               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA=="
+               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA==",
+               "dpc": true
        }
 }
index 7e6919d..48c016e 100644 (file)
@@ -46,7 +46,8 @@ extern "C"
 #define _30_PROVIS_PAIR_DEVS_   30
 #define _31_PROVIS_CRED_        31
 #define _32_PROVIS_ACL_         32
-#define _33_CHECK_LINK_STATUS_  33
+#define _33_PROVIS_DP_           33
+#define _34_CHECK_LINK_STATUS_  34
 #define _40_UNLINK_PAIR_DEVS_   40
 #define _50_REMOVE_SELEC_DEV_   50
 #define _99_EXIT_PRVN_CLT_      99
@@ -62,6 +63,11 @@ static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY
 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.json";
         // '_' for separaing from the same constant variable in |srmresourcestrings.c|
 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
+static const OicSecPrm_t  SUPPORTED_PRMS[1] =
+{
+    PRM_PRE_CONFIGURED,
+};
+
 // |g_ctx| means provision manager application context and
 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
 // for accessing all function(s) for these, they are declared on global domain
@@ -76,6 +82,7 @@ static bool g_doneCB;
 
 // function declaration(s) for calling them before implementing
 static OicSecAcl_t* createAcl(const int);
+static OicSecPdAcl_t* createPdAcl(const int);
 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
 static int printDevList(const OCProvisionDev_t*);
 static size_t printUuidList(const OCUuidList_t*);
@@ -142,6 +149,20 @@ static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool
     g_doneCB = true;
 }
 
+static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+    if(!hasError)
+    {
+        OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
+        printResultList((const OCProvisionResult_t*) arr, nOfRes);
+    }
+    g_doneCB = true;
+}
+
 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
 {
     if(!hasError)
@@ -589,6 +610,104 @@ PVACL_ERROR:
     return -1;
 }
 
+static int provisionDirectPairing(void)
+{
+    // check |own_list| for provisioning direct-pairing
+    if(!g_own_list || 1>g_own_cnt)
+    {
+        printf("   > Owned Device List, to Provision ACL, is Empty\n");
+        printf("   > Please Register Unowned Devices first, with [20] Menu\n");
+        return 0;  // normal case
+    }
+
+    // select device for provisioning direct-pairing
+    int dev_num = 0;
+    for( ; ; )
+    {
+        printf("   > Enter Device Number, for Provisioning Direct-Pairing: ");
+        for(int ret=0; 1!=ret; )
+        {
+            ret = scanf("%d", &dev_num);
+            for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                        // '0x20<=code' is character region
+        }
+        if(0<dev_num && g_own_cnt>=dev_num)
+        {
+            break;
+        }
+        printf("     Entered Wrong Number. Please Enter Again\n");
+    }
+
+    // create Direct-Pairing Configuration(PIN, PDACL) for selected device
+    // TODO: default acl -> input from user !
+    OicSecPconf_t pconf;
+    memset(&pconf, 0, sizeof(OicSecPconf_t));
+
+    // set enable dp
+    pconf.edp = true;
+
+    // set default supported PRM types
+    pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
+    pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
+    if(pconf.prm)
+    {
+        for (size_t i=0; i<pconf.prmLen; i++)
+        {
+            pconf.prm[i] = SUPPORTED_PRMS[i];
+        }
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "create prm error return");
+        goto PVDP_ERROR;
+    }
+
+    // set default pin
+    const char DP_DEFAULT_PIN[] = "00000000";
+    memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
+
+    // set default pdacl
+    pconf.pdacls = createPdAcl(dev_num);
+    if(!pconf.pdacls)
+    {
+        OIC_LOG(ERROR, TAG, "createPdAcl error return");
+        goto PVDP_ERROR;
+    }
+
+    // call |OCProvisionDirectPairing| API actually
+    // calling this API with callback actually acts like blocking
+    // for error checking, the return value saved and printed
+    g_doneCB = false;
+    printf("   Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
+    OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
+                                       getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
+                                       &pconf, provisionDPCB);
+    if(OC_STACK_OK != rst)
+    {
+        OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
+        if (OC_STACK_UNAUTHORIZED_REQ == rst)
+        {
+            OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
+        }
+        goto PVDP_ERROR;
+    }
+    if(waitCallbackRet())  // input |g_doneCB| flag implicitly
+    {
+        OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+        goto PVDP_ERROR;
+    }
+    OCDeletePdAclList(pconf.pdacls);
+
+    // display the PCONF-provisioned result
+    printf("   > SUCCESS to provision Direct-Pairing !!\n");
+
+    return 0;
+
+PVDP_ERROR:
+    OCDeletePdAclList(pconf.pdacls);  // after here |acl| points nothing
+    return -1;
+}
+
 static int checkLinkedStatus(void)
 {
     // check |own_list| for checking selected link status on PRVN DB
@@ -923,6 +1042,59 @@ CRACL_ERROR:
     return NULL;
 }
 
+static OicSecPdAcl_t* createPdAcl(const int dev_num)
+{
+    if(0>=dev_num || g_own_cnt<dev_num)
+    {
+        OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
+        return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
+    }
+
+    // allocate memory for |pdacl| struct
+    printf("   **** Create PDACL for the Selected Device[%d]\n", dev_num);
+    OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
+    if(!pdAcl)
+    {
+        OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+        return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
+    }
+
+
+    // number of resources
+    char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
+    pdAcl->resourcesLen = 1;
+
+    // resource
+    int num = pdAcl->resourcesLen;
+    pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
+    if(!pdAcl->resources)
+    {
+        OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
+        goto CRPDACL_ERROR;
+    }
+    for(int i=0; num>i; ++i)
+    {
+        size_t len = strlen(rsrc_in[i])+1;  // '1' for null termination
+        char* rsrc = (char*) OICCalloc(len, sizeof(char));
+        if(!rsrc)
+        {
+            OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
+            goto CRPDACL_ERROR;
+        }
+        OICStrcpy(rsrc, len, rsrc_in[i]);
+        pdAcl->resources[i] = rsrc;  // after here, |rsrc| points nothing
+    }
+
+    // permission
+    pdAcl->permission = PERMISSION_FULL_CONTROL;
+
+    return pdAcl;
+
+CRPDACL_ERROR:
+    OCDeletePdAclList(pdAcl);
+    return NULL;
+}
+
 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
 {
     if(!dev_lst || 0>=dev_num)
@@ -1101,7 +1273,8 @@ static void printMenu(void)
     printf("** 30. Provision/Link Pairwise Things\n");
     printf("** 31. Provision Credentials for Pairwise Things\n");
     printf("** 32. Provision the Selected Access Control List(ACL)\n");
-    printf("** 33. Check Linked Status of the Selected Device on PRVN DB\n\n");
+    printf("** 33. Provision Direct-Pairing Configuration\n");
+    printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
 
     printf("** [D] UNLINK PAIRWISE THINGS\n");
     printf("** 40. Unlink Pairwise Things\n\n");
@@ -1203,10 +1376,16 @@ int main()
                 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
             }
             break;
-        case _33_CHECK_LINK_STATUS_:
+        case _33_PROVIS_DP_:
+            if(provisionDirectPairing())
+            {
+                OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
+            }
+            break;
+        case _34_CHECK_LINK_STATUS_:
             if(checkLinkedStatus())
             {
-                OIC_LOG(ERROR, TAG, "_33_CHECK_LINK_STATUS_: error");
+                OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
             }
             break;
         case _40_UNLINK_PAIR_DEVS_:
index 9886923..9153740 100644 (file)
@@ -30,6 +30,7 @@
 #include "credresource.h"
 #include "utlist.h"
 #include "aclresource.h" //Note: SRM internal header
+#include "pconfresource.h"
 
 #define TAG "OCPMAPI"
 
@@ -178,6 +179,22 @@ OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t ke
 
 }
 
+/**
+ * this function sends Direct-Pairing Configuration to a device.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] pconf PCONF pointer.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+              request recieves a response from resource server.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf,
+                             OCProvisionResultCB resultCallback)
+{
+    return SRPProvisionDirectPairing(ctx, selectedDeviceInfo, pconf, resultCallback);
+}
+
 /*
 * Function to unlink devices.
 * This function will remove the credential & relationship between the two devices.
@@ -715,6 +732,16 @@ void OCDeleteACLList(OicSecAcl_t* pAcl)
     DeleteACLList(pAcl);
 }
 
+/**
+ * This function deletes PDACL data.
+ *
+ * @param pPdAcl Pointer to OicSecPdAcl_t structure.
+ */
+void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl)
+{
+    FreePdAclList(pPdAcl);
+}
+
 
 #ifdef __WITH_X509__
 /**
index fbf90c2..d3056c0 100644 (file)
@@ -31,6 +31,7 @@
 #include "srmresourcestrings.h"
 #include "credresource.h"
 #include "doxmresource.h"
+#include "pconfresource.h"
 #include "credentialgenerator.h"
 #include "cainterface.h"
 #include "cJSON.h"
@@ -89,6 +90,19 @@ struct ACLData
     int numOfResults;                           /**< Number of results in result array.**/
 };
 
+/**
+ * Structure to carry PCONF provision API data to callback.
+ */
+typedef struct PconfData PconfData_t;
+struct PconfData
+{
+    void *ctx;                                  /**< Pointer to user context.**/
+    const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
+    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
+    OCProvisionResult_t *resArr;                /**< Result array.**/
+    int numOfResults;                           /**< Number of results in result array.**/
+};
+
 // Enum type index for unlink callback.
 typedef enum {
     IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
@@ -897,6 +911,153 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI
     return OC_STACK_OK;
 }
 
+/**
+ * Internal Function to store results in result array during Direct-Pairing provisioning.
+ */
+static void registerResultForDirectPairingProvisioning(PconfData_t *pconfData,
+                                             OCStackResult stackresult)
+{
+   OIC_LOG_V(INFO, TAG, "Inside registerResultForDirectPairingProvisioning pconfData->numOfResults is %d\n",
+                       pconfData->numOfResults);
+   memcpy(pconfData->resArr[(pconfData->numOfResults)].deviceId.id,
+          pconfData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+   pconfData->resArr[(pconfData->numOfResults)].res = stackresult;
+   ++(pconfData->numOfResults);
+}
+
+/**
+ * Callback handler of SRPProvisionDirectPairing.
+ *
+ * @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 SRPProvisionDirectPairingCB(void *ctx, OCDoHandle UNUSED,
+                                                  OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "Inside SRPProvisionDirectPairingCB.");
+    (void)UNUSED;
+    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    PconfData_t *pconfData = (PconfData_t*)ctx;
+    OCProvisionResultCB resultCallback = pconfData->resultCallback;
+
+    if (clientResponse)
+    {
+        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        {
+            registerResultForDirectPairingProvisioning(pconfData, OC_STACK_RESOURCE_CREATED);
+            ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
+                                                    pconfData->resArr,
+                                                    false);
+             OICFree(pconfData->resArr);
+             OICFree(pconfData);
+             return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    registerResultForDirectPairingProvisioning(pconfData, OC_STACK_ERROR);
+    ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
+                                            pconfData->resArr,
+                                            true);
+    OIC_LOG_V(ERROR, TAG, "SRPProvisionDirectPairingCB received Null clientResponse");
+    OICFree(pconfData->resArr);
+    OICFree(pconfData);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+        OicSecPconf_t *pconf, OCProvisionResultCB resultCallback)
+{
+    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, pconf, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    // check direct-pairing capability
+    if (true != selectedDeviceInfo->doxm->dpc)
+    {
+        OIC_LOG(ERROR, TAG, "Resouce server does not have Direct-Pairing Capability ");
+        return OC_STACK_UNAUTHORIZED_REQ;
+    }
+
+    OicUuid_t provTooldeviceID =   {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+    {
+        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+    memcpy(&pconf->rowner, &provTooldeviceID, sizeof(OicUuid_t));
+
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToPconfJSON(pconf);
+    if(NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OIC_LOG(ERROR, TAG, "Failed to BinToPconfJSON");
+        return OC_STACK_NO_MEMORY;
+    }
+    OIC_LOG_V(INFO, TAG, "PCONF : %s", secPayload->securityData);
+
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+    if(!PMGenerateQuery(true,
+                        selectedDeviceInfo->endpoint.addr,
+                        selectedDeviceInfo->securePort,
+                        selectedDeviceInfo->connType,
+                        query, sizeof(query), OIC_RSRC_PCONF_URI))
+    {
+        OIC_LOG(ERROR, TAG, "SRPProvisionDirectPairing : Failed to generate query");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = &SRPProvisionDirectPairingCB;
+    PconfData_t *pconfData = (PconfData_t *) OICCalloc(1, sizeof(PconfData_t));
+    if (NULL == pconfData)
+    {
+        OICFree(secPayload->securityData);
+        OICFree(secPayload);
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    pconfData->deviceInfo = selectedDeviceInfo;
+    pconfData->resultCallback = resultCallback;
+    pconfData->numOfResults=0;
+    pconfData->ctx = ctx;
+    // call to provision PCONF to device1.
+    int noOfRiCalls = 1;
+    pconfData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
+    if (NULL == pconfData->resArr)
+    {
+        OICFree(pconfData);
+        OICFree(secPayload->securityData);
+        OICFree(secPayload);
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    cbData.context = (void *)pconfData;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_POST;
+    OCDoHandle handle = NULL;
+    OIC_LOG(DEBUG, TAG, "Sending PCONF info to resource server");
+    OCStackResult ret = OCDoResource(&handle, method, query,
+            &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+            selectedDeviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        OICFree(pconfData->resArr);
+        OICFree(pconfData);
+    }
+    VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
+
 static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
 {
     if (unlinkData)
index 4bc220b..54f17b4 100644 (file)
@@ -1192,6 +1192,63 @@ int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
     return ret;
 }
 
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+                            const char * pin, size_t pinSize,
+                            size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
+    {
+        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, (0 == dtlsRes) , ERROR);
+
+    uint32_t outLen = 0;
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+    B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
+                                sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
+
+    OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
+                                            base64Buff, ownersLen, owners);
+    if(NULL == cred)
+    {
+        OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
+        return OC_STACK_ERROR;
+    }
+
+    memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
+
+    ret = AddCredential(cred);
+    if( OC_STACK_OK != ret)
+    {
+        RemoveCredential(tmpSubject);
+        OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
+    }
+
+exit:
+    return ret;
+}
+
 #endif /* __WITH_DTLS__ */
 #ifdef __WITH_X509__
 #define CERT_LEN_PREFIX (3)
diff --git a/resource/csdk/security/src/directpairing.c b/resource/csdk/security/src/directpairing.c
new file mode 100644 (file)
index 0000000..dd1d85c
--- /dev/null
@@ -0,0 +1,1052 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+#ifndef _POSIX_C_SOURCE\r
+#define _POSIX_C_SOURCE 200112L\r
+#endif\r
+\r
+#include <unistd.h>\r
+#include <string.h>\r
+#include <time.h>\r
+#include <sys/time.h>\r
+\r
+#include "ocstack.h"\r
+#include "oic_malloc.h"\r
+#include "oic_string.h"\r
+#include "logger.h"\r
+#include "cJSON.h"\r
+#include "utlist.h"\r
+#include "ocpayload.h"\r
+#include "payload_logging.h"\r
+#include "cainterface.h"\r
+\r
+#include "directpairing.h"\r
+#include "srmresourcestrings.h" //@note: SRM's internal header\r
+#include "doxmresource.h"       //@note: SRM's internal header\r
+#include "pconfresource.h"       //@note: SRM's internal header\r
+#include "dpairingresource.h"       //@note: SRM's internal header\r
+#include "credresource.h"\r
+\r
+#include "pmtypes.h"\r
+#include "pmutility.h"\r
+\r
+#include "srmutility.h"\r
+\r
+#ifdef __WITH_DTLS__\r
+#include "global.h"\r
+#endif\r
+\r
+\r
+#define TAG ("DP")\r
+\r
+/**\r
+ * Structure to carry direct-pairing API data to callback.\r
+ */\r
+typedef struct DPairData\r
+{\r
+    OCDirectPairingDev_t        *peer;                         /**< Pointer to pairing target info.**/\r
+    char                                  pin[DP_PIN_LENGTH];  /**< PIN **/\r
+    OCDirectPairingResultCB    resultCallback;           /**< Pointer to result callback.**/\r
+} DPairData_t;\r
+\r
+static OCDirectPairingDev_t *g_dp_paired = NULL;\r
+static OCDirectPairingDev_t *g_dp_discover = NULL;\r
+static DPairData_t *g_dp_proceed_ctx = NULL;\r
+\r
+\r
+const char *getResult(OCStackResult result) {\r
+    switch (result) {\r
+    case OC_STACK_OK:\r
+        return "OC_STACK_OK";\r
+    case OC_STACK_RESOURCE_CREATED:\r
+        return "OC_STACK_RESOURCE_CREATED";\r
+    case OC_STACK_RESOURCE_DELETED:\r
+        return "OC_STACK_RESOURCE_DELETED";\r
+    case OC_STACK_INVALID_URI:\r
+        return "OC_STACK_INVALID_URI";\r
+    case OC_STACK_INVALID_QUERY:\r
+        return "OC_STACK_INVALID_QUERY";\r
+    case OC_STACK_INVALID_IP:\r
+        return "OC_STACK_INVALID_IP";\r
+    case OC_STACK_INVALID_PORT:\r
+        return "OC_STACK_INVALID_PORT";\r
+    case OC_STACK_INVALID_CALLBACK:\r
+        return "OC_STACK_INVALID_CALLBACK";\r
+    case OC_STACK_INVALID_METHOD:\r
+        return "OC_STACK_INVALID_METHOD";\r
+    case OC_STACK_NO_MEMORY:\r
+        return "OC_STACK_NO_MEMORY";\r
+    case OC_STACK_COMM_ERROR:\r
+        return "OC_STACK_COMM_ERROR";\r
+    case OC_STACK_INVALID_PARAM:\r
+        return "OC_STACK_INVALID_PARAM";\r
+    case OC_STACK_NOTIMPL:\r
+        return "OC_STACK_NOTIMPL";\r
+    case OC_STACK_NO_RESOURCE:\r
+        return "OC_STACK_NO_RESOURCE";\r
+    case OC_STACK_RESOURCE_ERROR:\r
+        return "OC_STACK_RESOURCE_ERROR";\r
+    case OC_STACK_SLOW_RESOURCE:\r
+        return "OC_STACK_SLOW_RESOURCE";\r
+    case OC_STACK_NO_OBSERVERS:\r
+        return "OC_STACK_NO_OBSERVERS";\r
+    case OC_STACK_UNAUTHORIZED_REQ:\r
+        return "OC_STACK_UNAUTHORIZED_REQ";\r
+    #ifdef WITH_PRESENCE\r
+    case OC_STACK_PRESENCE_STOPPED:\r
+        return "OC_STACK_PRESENCE_STOPPED";\r
+    #endif\r
+    case OC_STACK_ERROR:\r
+        return "OC_STACK_ERROR";\r
+    default:\r
+        return "UNKNOWN";\r
+    }\r
+}\r
+\r
+/**\r
+ * Function to search node in linked list that matches given IP and port.\r
+ *\r
+ * @param[in] pList         List of OCProvisionDev_t.\r
+ * @param[in] addr          address of target device.\r
+ * @param[in] port          port of remote server.\r
+ *\r
+ * @return pointer of OCProvisionDev_t if exist, otherwise NULL\r
+ */\r
+OCDirectPairingDev_t* getDev(OCDirectPairingDev_t **ppList, const char* addr, const uint16_t port)\r
+{\r
+    if(NULL == addr)\r
+    {\r
+        OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);\r
+        return NULL;\r
+    }\r
+\r
+    OCDirectPairingDev_t *ptr = NULL;\r
+    LL_FOREACH(*ppList, ptr)\r
+    {\r
+        if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)\r
+        {\r
+            return ptr;\r
+        }\r
+    }\r
+\r
+    return NULL;\r
+}\r
+\r
+\r
+\r
+/**\r
+ * Add device information to list.\r
+ *\r
+ * @param[in] pList         List of OCProvisionDev_t.\r
+ * @param[in] addr          address of target device.\r
+ * @param[in] port          port of remote server.\r
+ * @param[in] adapter       adapter type of endpoint.\r
+ * @param[in] doxm          pointer to doxm instance.\r
+ * @param[in] connType  connectivity type of endpoint\r
+ *\r
+ * @return OC_STACK_OK for success and errorcode otherwise.\r
+ */\r
+OCStackResult addDev(OCDirectPairingDev_t **ppList, OCDevAddr *endpoint,\r
+                                      OCConnectivityType conn, OicSecPconf_t *pconf)\r
+{\r
+    if(NULL == endpoint || NULL == pconf)\r
+    {\r
+        OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    OCDirectPairingDev_t *ptr = getDev(ppList, endpoint->addr, endpoint->port);\r
+    if(!ptr)\r
+    {\r
+        ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));\r
+        if (NULL == ptr)\r
+        {\r
+            OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");\r
+            return OC_STACK_NO_MEMORY;\r
+        }\r
+\r
+        memcpy(&ptr->endpoint, endpoint, sizeof(OCDevAddr));\r
+        ptr->connType = conn;\r
+        ptr->securePort = DEFAULT_SECURE_PORT;\r
+        ptr->edp = pconf->edp;\r
+        ptr->prm = pconf->prm;\r
+        pconf->prm = NULL;  // to prevent free\r
+        ptr->prmLen = pconf->prmLen;\r
+        memcpy(&ptr->deviceID, &pconf->deviceID, sizeof(OicUuid_t));\r
+        memcpy(&ptr->rowner, &pconf->rowner, sizeof(OicUuid_t));\r
+        ptr->next = NULL;\r
+\r
+        LL_PREPEND(*ppList, ptr);\r
+        OIC_LOG(INFO, TAG, "device added !");\r
+    }\r
+\r
+    return OC_STACK_OK;\r
+}\r
+\r
+\r
+/**\r
+ * Add device information to list.\r
+ *\r
+ * @param[in] ppList         List of OCProvisionDev_t.\r
+ * @param[in] pDev          target device.\r
+ *\r
+ * @return OC_STACK_OK for success and errorcode otherwise.\r
+ */\r
+OCStackResult addDev2(OCDirectPairingDev_t **ppList, OCDirectPairingDev_t *pDev)\r
+{\r
+    if(NULL == pDev)\r
+    {\r
+        OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    OCDirectPairingDev_t *ptr = getDev(ppList, pDev->endpoint.addr, pDev->endpoint.port);\r
+    if(!ptr)\r
+    {\r
+        ptr = (OCDirectPairingDev_t *)OICCalloc(1, sizeof (OCDirectPairingDev_t));\r
+        if (NULL == ptr)\r
+        {\r
+            OIC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");\r
+            return OC_STACK_NO_MEMORY;\r
+        }\r
+\r
+        memcpy(&ptr->endpoint, &pDev->endpoint, sizeof(OCDevAddr));\r
+        ptr->connType = pDev->connType;\r
+        ptr->securePort = pDev->securePort;\r
+        ptr->edp = pDev->edp;\r
+        ptr->prmLen = pDev->prmLen;\r
+        ptr->prm = (OicSecPrm_t*)OICCalloc(ptr->prmLen, sizeof (OicSecPrm_t));\r
+        if (NULL == ptr->prm)\r
+        {\r
+            OIC_LOG(ERROR, TAG, "Error while allocating memory for prm !!");\r
+            return OC_STACK_NO_MEMORY;\r
+        }\r
+        memcpy(ptr->prm, pDev->prm, sizeof(OicSecPrm_t)*ptr->prmLen);\r
+        memcpy(&ptr->deviceID, &pDev->deviceID, sizeof(OicUuid_t));\r
+        memcpy(&ptr->rowner, &pDev->rowner, sizeof(OicUuid_t));\r
+        ptr->next = NULL;\r
+\r
+        LL_PREPEND(*ppList, ptr);\r
+        OIC_LOG(INFO, TAG, "device added !");\r
+    }\r
+\r
+    return OC_STACK_OK;\r
+}\r
+\r
+\r
+\r
+/**\r
+ * This function deletes list of provision target devices\r
+ *\r
+ * @param[in] pDevicesList         List of OCProvisionDev_t.\r
+ */\r
+void delList(OCDirectPairingDev_t *pList)\r
+{\r
+    if(pList)\r
+    {\r
+        OCDirectPairingDev_t *del = NULL, *tmp = NULL;\r
+        LL_FOREACH_SAFE(pList, del, tmp)\r
+        {\r
+            LL_DELETE(pList, del);\r
+            if (del && del->prm)\r
+            {\r
+                OICFree(del->prm);\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+bool DPGenerateQuery(bool isSecure,\r
+                     const char* address, const uint16_t port,\r
+                     const OCConnectivityType connType,\r
+                     char* buffer, size_t bufferSize, const char* uri)\r
+{\r
+    if(!address || !buffer || !uri)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "DPGenerateQuery : Invalid parameters.");\r
+        return false;\r
+    }\r
+\r
+    static char QPREFIX_COAP[] =  "coap://";\r
+    static char QPREFIX_COAPS[] = "coaps://";\r
+\r
+    int snRet = 0;\r
+    char* prefix = (isSecure == true) ? QPREFIX_COAPS : QPREFIX_COAP;\r
+\r
+    switch(connType & CT_MASK_ADAPTER)\r
+    {\r
+        case CT_ADAPTER_IP:\r
+            switch(connType & CT_MASK_FLAGS & ~CT_FLAG_SECURE)\r
+            {\r
+                case CT_IP_USE_V4:\r
+                        snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",\r
+                                         prefix, address, port, uri);\r
+                    break;\r
+                case CT_IP_USE_V6:\r
+                        snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",\r
+                                         prefix, address, port, uri);\r
+                    break;\r
+                default:\r
+                    OIC_LOG(ERROR, TAG, "Unknown address format.");\r
+                    return false;\r
+            }\r
+            // snprintf return value check\r
+            if (snRet < 0)\r
+            {\r
+                OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Error (snprintf) %d\n", snRet);\r
+                return false;\r
+            }\r
+            else if ((size_t)snRet >= bufferSize)\r
+            {\r
+                OIC_LOG_V(ERROR, TAG, "DPGenerateQuery : Truncated (snprintf) %d\n", snRet);\r
+                return false;\r
+            }\r
+\r
+            break;\r
+        // TODO: We need to verify tinyDTLS in below cases\r
+        case CT_ADAPTER_GATT_BTLE:\r
+        case CT_ADAPTER_RFCOMM_BTEDR:\r
+            OIC_LOG(ERROR, TAG, "Not supported connectivity adapter.");\r
+            return false;\r
+            break;\r
+        default:\r
+            OIC_LOG(ERROR, TAG, "Unknown connectivity adapter.");\r
+            return false;\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+const OCDirectPairingDev_t* DPGetDiscoveredDevices()\r
+{\r
+    return g_dp_discover;\r
+}\r
+\r
+const OCDirectPairingDev_t* DPGetPairedDevices()\r
+{\r
+    return g_dp_paired;\r
+}\r
+\r
+void DPDeleteLists()\r
+{\r
+    delList(g_dp_discover);\r
+    delList(g_dp_paired);\r
+}\r
+\r
+/**\r
+ * Callback handler of FinalizeDirectPairing.\r
+ *\r
+ * @param[in] ctx             ctx value passed to callback from calling function.\r
+ * @param[in] UNUSED          handle to an invocation\r
+ * @param[in] clientResponse  Response from queries to remote servers.\r
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction\r
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.\r
+ */\r
+static OCStackApplicationResult DirectPairingFinalizeHandler(void *ctx, OCDoHandle UNUSED,\r
+                                                  OCClientResponse *clientResponse)\r
+{\r
+    OIC_LOG_V(INFO, TAG, "IN DirectPairingFinalizeHandler()");\r
+    (void)UNUSED;\r
+    if(NULL == ctx)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Context is Null");\r
+        return OC_STACK_DELETE_TRANSACTION;\r
+    }\r
+\r
+    OCStackResult res;\r
+    DPairData_t *dpairData = (DPairData_t*)ctx;\r
+    OCDirectPairingDev_t *peer = dpairData->peer;\r
+    OCDirectPairingResultCB resultCallback = dpairData->resultCallback;\r
+\r
+    if (clientResponse)\r
+    {\r
+        if(OC_STACK_OK == clientResponse->result)\r
+        {\r
+            // result\r
+            OIC_LOG(INFO, TAG, "DirectPairingFinalizeHandler : success PUT request to /oic/sec/dpairing");\r
+\r
+            CAEndpoint_t endpoint;\r
+            memset(&endpoint, 0x00, sizeof(CAEndpoint_t));\r
+            OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, peer->endpoint.addr);\r
+            endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';\r
+            endpoint.port = peer->securePort;\r
+\r
+            OicUuid_t ptDeviceID = {.id={0}};\r
+            if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");\r
+                resultCallback(peer, OC_STACK_ERROR);\r
+                return OC_STACK_DELETE_TRANSACTION;\r
+            }\r
+\r
+#ifdef __WITH_DTLS__\r
+            res = SavePairingPSK((OCDevAddr*)&endpoint, &peer->deviceID, &ptDeviceID, false);\r
+            if(OC_STACK_OK != res)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Failed to PairingPSK generation");\r
+                resultCallback(peer, res);\r
+                return OC_STACK_DELETE_TRANSACTION;\r
+            }\r
+\r
+            //  close temporary sesion\r
+            CAResult_t caResult = CACloseDtlsSession((const CAEndpoint_t*)&endpoint);\r
+            if(CA_STATUS_OK != caResult)\r
+            {\r
+                OIC_LOG(INFO, TAG, "Fail to close temporary dtls session");\r
+            }\r
+\r
+            caResult = CASelectCipherSuite(TLS_NULL_WITH_NULL_NULL);\r
+            if(CA_STATUS_OK != caResult)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");\r
+            }\r
+#endif // __WITH_DTLS__\r
+\r
+            OIC_LOG(INFO, TAG, "Direct-Papring was successfully completed.");\r
+\r
+            // update paired list\r
+            OCDirectPairingDev_t *dev = getDev(&g_dp_discover, peer->endpoint.addr, peer->endpoint.port);\r
+            res = addDev2(&g_dp_paired, dev);\r
+            if (OC_STACK_OK != res)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Error while adding a device to paired list.");\r
+            }\r
+\r
+            resultCallback(peer, OC_STACK_OK);\r
+\r
+            return OC_STACK_DELETE_TRANSACTION;\r
+        }\r
+        else\r
+        {\r
+            OIC_LOG(INFO, TAG, "Direct-Papring received error response.");\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(ERROR, TAG, "DirectPairingFinalizeHandler received Null clientResponse");\r
+    }\r
+\r
+    resultCallback(peer, OC_STACK_ERROR);\r
+    OICFree(dpairData);\r
+    return OC_STACK_DELETE_TRANSACTION;\r
+}\r
+\r
+/**\r
+ * Finalize direct-pairing .\r
+ *\r
+ * @param[in] peer  target device to establish direct-pairing.\r
+ * @param[in] resultCallback  result event callback.\r
+ *\r
+ * @return OC_STACK_OK on success otherwise error.\r
+ */\r
+OCStackResult FinalizeDirectPairing(OCDirectPairingDev_t* peer,\r
+                                                     OCDirectPairingResultCB resultCallback)\r
+{\r
+    if(NULL == peer)\r
+    {\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    OicUuid_t deviceID =   {.id={0}};\r
+    if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Error while retrieving device ID");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    OicSecDpairing_t dpair;\r
+    memset(&dpair, 0, sizeof(OicSecDpairing_t));\r
+    dpair.spm = (OicSecPrm_t)PRM_NOT_ALLOWED;\r
+    memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));\r
+\r
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));\r
+    if(!secPayload)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;\r
+    secPayload->securityData = BinToDpairingJSON(&dpair);\r
+    if(NULL == secPayload->securityData)\r
+    {\r
+        OICFree(secPayload);\r
+        OIC_LOG(ERROR, TAG, "Failed to BinToDpairingJSON");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    OIC_LOG_V(INFO, TAG, "DPARING : %s", secPayload->securityData);\r
+\r
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};\r
+    if(!DPGenerateQuery(true,\r
+                        peer->endpoint.addr,\r
+                        peer->securePort,\r
+                        peer->connType,\r
+                        query, sizeof(query), OIC_RSRC_DPAIRING_URI))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");\r
+        return OC_STACK_ERROR;\r
+    }\r
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);\r
+\r
+    DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));\r
+    if (dpairData == NULL)\r
+    {\r
+        OICFree(secPayload->securityData);\r
+        OICFree(secPayload);\r
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    dpairData->peer = peer;\r
+    dpairData->resultCallback = resultCallback;\r
+\r
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};\r
+    cbData.cb = DirectPairingFinalizeHandler;\r
+    cbData.context = (void*)dpairData;\r
+    cbData.cd = NULL;\r
+\r
+    OCMethod method = OC_REST_PUT;\r
+    OCDoHandle handle = NULL;\r
+    OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");\r
+    OCStackResult ret = OCDoResource(&handle, method, query,\r
+            &peer->endpoint, (OCPayload*)secPayload,\r
+            peer->connType, OC_LOW_QOS, &cbData, NULL, 0);\r
+    if(OC_STACK_OK != ret)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "error in OCDoResource");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    return OC_STACK_OK;\r
+ }\r
+\r
+/**\r
+ * Function to handle the handshake result in Direct-Pairing.\r
+ * This function will be invoked after DTLS handshake\r
+ * @param   endPoint  [IN] The remote endpoint.\r
+ * @param   errorInfo [IN] Error information from the endpoint.\r
+ * @return  NONE\r
+ */\r
+void DirectPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)\r
+{\r
+    OIC_LOG_V(INFO, TAG, "IN DirectPairingDTLSHandshakeCB");\r
+\r
+\r
+    if(g_dp_proceed_ctx && g_dp_proceed_ctx->peer && endpoint && info)\r
+    {\r
+        OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",\r
+                 endpoint->addr, endpoint->port, info->result);\r
+\r
+        OCDirectPairingDev_t *peer = g_dp_proceed_ctx->peer;\r
+        OCDirectPairingResultCB resultCallback = g_dp_proceed_ctx->resultCallback;\r
+        OCStackResult res;\r
+\r
+        //Make sure the address matches.\r
+        if(strncmp(peer->endpoint.addr, endpoint->addr, sizeof(endpoint->addr)) == 0 &&\r
+                         peer->securePort == endpoint->port)\r
+        {\r
+            //In case of success, send next coaps request.\r
+            if(CA_STATUS_OK == info->result)\r
+            {\r
+                OIC_LOG(INFO, TAG, "Now, finalize Direct-Pairing procedure.");\r
+\r
+                res = FinalizeDirectPairing(peer, resultCallback);\r
+                if(OC_STACK_OK != res)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Failed to finalize direct-pairing");\r
+                    resultCallback(peer, res);\r
+                }\r
+            }\r
+            else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)\r
+            {\r
+                OIC_LOG(INFO, TAG, "DirectPairingDTLSHandshakeCB - Authentication failed");\r
+                resultCallback(peer, OC_STACK_AUTHENTICATION_FAILURE);\r
+            }\r
+\r
+#ifdef __WITH_DTLS__\r
+            CARegisterDTLSHandshakeCallback(NULL);\r
+#endif // __WITH_DTLS__\r
+            res = RemoveCredential(&peer->deviceID);\r
+            if(OC_STACK_RESOURCE_DELETED != res)\r
+            {\r
+                OIC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);\r
+            }\r
+\r
+            OICFree(g_dp_proceed_ctx);\r
+            g_dp_proceed_ctx = NULL;\r
+        }\r
+        else\r
+        {\r
+            OIC_LOG_V(INFO, TAG, "DirectPairingDTLSHandshakeCB - Not matched to peer address");\r
+        }\r
+    }\r
+\r
+    OIC_LOG_V(INFO, TAG, "OUT DirectPairingDTLSHandshakeCB");\r
+}\r
+\r
+/**\r
+ * Callback handler of DPDirectPairing.\r
+ *\r
+ * @param[in] ctx             ctx value passed to callback from calling function.\r
+ * @param[in] UNUSED          handle to an invocation\r
+ * @param[in] clientResponse  Response from queries to remote servers.\r
+ * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction\r
+ *          and  OC_STACK_KEEP_TRANSACTION to keep it.\r
+ */\r
+static OCStackApplicationResult DirectPairingHandler(void *ctx, OCDoHandle UNUSED,\r
+                                                  OCClientResponse *clientResponse)\r
+{\r
+    OIC_LOG_V(INFO, TAG, "IN DirectPairingHandler.");\r
+    (void)UNUSED;\r
+    if(NULL == ctx)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Context is Null");\r
+        return OC_STACK_DELETE_TRANSACTION;\r
+    }\r
+\r
+    OCStackResult res = OC_STACK_ERROR;\r
+    DPairData_t *dpairData = (DPairData_t*)ctx;\r
+    OCDirectPairingResultCB resultCallback = (OCDirectPairingResultCB)dpairData->resultCallback;\r
+    OicUuid_t subjectId = {.id={0}};\r
+\r
+    if (clientResponse)\r
+    {\r
+        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)\r
+        {\r
+            // result\r
+            OIC_LOG(INFO, TAG, "DirectPairingHandler : success POST request to /oic/sec/dpairing");\r
+\r
+#ifdef __WITH_DTLS__\r
+            // Add temporary psk\r
+            res = AddTmpPskWithPIN(&dpairData->peer->deviceID,\r
+                           SYMMETRIC_PAIR_WISE_KEY,\r
+                           (char*)dpairData->pin, DP_PIN_LENGTH,\r
+                           1, &dpairData->peer->rowner, &subjectId);\r
+            VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);\r
+\r
+\r
+            // Start to establish a secure channel with Pin-based PSK cipher suite\r
+            CAResult_t caresult;\r
+\r
+            caresult = CAEnableAnonECDHCipherSuite(false);\r
+            VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
+\r
+            caresult = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);\r
+            VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
+\r
+            //Register proceeding peer info. & DTLS event handler to catch the dtls event while handshake\r
+            g_dp_proceed_ctx = dpairData;\r
+            res = CARegisterDTLSHandshakeCallback(DirectPairingDTLSHandshakeCB);\r
+            VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
+\r
+            // initiate dtls\r
+            CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));\r
+            VERIFY_NON_NULL(TAG, endpoint, FATAL);\r
+            memcpy(endpoint,&dpairData->peer->endpoint,sizeof(CAEndpoint_t));\r
+            endpoint->port = dpairData->peer->securePort;\r
+            OIC_LOG_V(INFO, TAG, "Initiate DTLS handshake to %s(%d)", endpoint->addr, endpoint->port);\r
+\r
+            caresult = CAInitiateHandshake(endpoint);\r
+            OICFree(endpoint);\r
+            VERIFY_SUCCESS(TAG, CA_STATUS_OK == caresult, ERROR);\r
+#endif // __WITH_DTLS__\r
+\r
+            res = OC_STACK_OK;\r
+        }\r
+        else\r
+        {\r
+            // result\r
+            OIC_LOG(INFO, TAG, "DirectPairingHandler : fail POST request to /oic/sec/dpairing");\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(ERROR, TAG, "DirectPairingHandler received Null clientResponse");\r
+    }\r
+\r
+#ifdef __WITH_DTLS__\r
+exit:\r
+#endif // __WITH_DTLS__\r
+\r
+    if (OC_STACK_OK != res)\r
+    {\r
+        if (0 < strlen((const char*)subjectId.id))\r
+        {\r
+            RemoveCredential(&dpairData->peer->deviceID);\r
+            OICFree(dpairData);\r
+            g_dp_proceed_ctx = NULL;\r
+        }\r
+\r
+        resultCallback(dpairData->peer, res);\r
+    }\r
+    OIC_LOG_V(INFO, TAG, "OUT DirectPairingHandler.");\r
+    return OC_STACK_DELETE_TRANSACTION;\r
+}\r
+\r
+/**\r
+ * Start direct-pairing .\r
+ *\r
+ * @param[in] peer  target device to establish direct-pairing.\r
+ * @param[in] pmSel  selected pairing method.\r
+ * @param[in] pinNumber  secret value for dtls connection.\r
+ *\r
+ * @return OC_STACK_OK on success otherwise error.\r
+ */\r
+OCStackResult DPDirectPairing(OCDirectPairingDev_t* peer, OicSecPrm_t pmSel, char *pinNumber,\r
+                                                     OCDirectPairingResultCB resultCallback)\r
+{\r
+    if(NULL == peer || NULL == pinNumber)\r
+    {\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    OicUuid_t deviceID =   {.id={0}};\r
+    if (OC_STACK_OK != GetDoxmDeviceID(&deviceID))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Error while retrieving device ID");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    OicSecDpairing_t dpair;\r
+    memset(&dpair, 0, sizeof(OicSecDpairing_t));\r
+    dpair.spm = pmSel;\r
+    memcpy(&dpair.pdeviceID, &deviceID, sizeof(OicUuid_t));\r
+\r
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));\r
+    if(!secPayload)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Failed to memory allocation");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;\r
+    secPayload->securityData = BinToDpairingJSON(&dpair);\r
+    if(NULL == secPayload->securityData)\r
+    {\r
+        OICFree(secPayload);\r
+        OIC_LOG(ERROR, TAG, "Failed to BinToDpairingJSON");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    OIC_LOG_V(INFO, TAG, "DPAIRING : %s", secPayload->securityData);\r
+\r
+    char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};\r
+    if(!DPGenerateQuery(false,\r
+                        peer->endpoint.addr,\r
+                        peer->endpoint.port,\r
+                        //peer->securePort,\r
+                        peer->connType,\r
+                        query, sizeof(query), OIC_RSRC_DPAIRING_URI))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "DPDirectPairing : Failed to generate query");\r
+        return OC_STACK_ERROR;\r
+    }\r
+    OIC_LOG_V(DEBUG, TAG, "Query=%s", query);\r
+\r
+    DPairData_t *dpairData = (DPairData_t *) OICCalloc(1, sizeof(DPairData_t));\r
+    if (dpairData == NULL)\r
+    {\r
+        OICFree(secPayload->securityData);\r
+        OICFree(secPayload);\r
+        OIC_LOG(ERROR, TAG, "Unable to allocate memory");\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    dpairData->peer = peer;\r
+    memcpy(dpairData->pin, pinNumber, DP_PIN_LENGTH);\r
+    dpairData->resultCallback = resultCallback;\r
+\r
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};\r
+    cbData.cb = DirectPairingHandler;\r
+    cbData.context = (void*)dpairData;\r
+    cbData.cd = NULL;\r
+\r
+    OCMethod method = OC_REST_POST;\r
+    OCDoHandle handle = NULL;\r
+    OIC_LOG(DEBUG, TAG, "Sending DPAIRNG setting to resource server");\r
+    OCStackResult ret = OCDoResource(&handle, method, query,\r
+            &peer->endpoint, (OCPayload*)secPayload,\r
+            peer->connType, OC_LOW_QOS, &cbData, NULL, 0);\r
+    if(OC_STACK_OK != ret)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "error in OCDoResource");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    return OC_STACK_OK;\r
+\r
+ }\r
+\r
+/**\r
+ * Callback handler for getting secure port information using /oic/res discovery.\r
+ *\r
+ * @param[in] ctx             user context\r
+ * @param[in] handle          Handle for response\r
+ * @param[in] clientResponse  Response information(It will contain payload)\r
+ *\r
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and\r
+ *         OC_STACK_DELETE_TRANSACTION to delete it.\r
+ */\r
+static OCStackApplicationResult DirectPairingPortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,\r
+                                 OCClientResponse *clientResponse)\r
+{\r
+    OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing Secure Port DISCOVER query recvd successfully");\r
+\r
+    (void)ctx;\r
+    (void)UNUSED;\r
+    if (clientResponse)\r
+    {\r
+        if  (NULL == clientResponse->payload)\r
+        {\r
+            OIC_LOG(INFO, TAG, "Skiping Null payload");\r
+        }\r
+        else\r
+        {\r
+            if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)\r
+            {\r
+                OIC_LOG(INFO, TAG, "Wrong payload type");\r
+                return OC_STACK_DELETE_TRANSACTION;\r
+            }\r
+\r
+            uint16_t securePort = 0;\r
+            OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;\r
+            OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
+\r
+            if (resPayload && resPayload->secure)\r
+            {\r
+                securePort = resPayload->port;\r
+            }\r
+            else\r
+            {\r
+                OIC_LOG(INFO, TAG, "Can not find secure port information.");\r
+                return OC_STACK_DELETE_TRANSACTION;\r
+            }\r
+\r
+            OCDirectPairingDev_t *ptr = getDev(&g_dp_discover,\r
+                    clientResponse->devAddr.addr, clientResponse->devAddr.port);\r
+            if(!ptr)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");\r
+                return OC_STACK_DELETE_TRANSACTION;\r
+            }\r
+            ptr->securePort = securePort;\r
+\r
+            OIC_LOG(INFO, TAG, "Exiting DirectPairingPortDiscoveryHandler.");\r
+        }\r
+\r
+        return  OC_STACK_DELETE_TRANSACTION;\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(INFO, TAG, "Skiping Null response");\r
+    }\r
+    return  OC_STACK_DELETE_TRANSACTION;\r
+}\r
+\r
+/**\r
+ * Callback handler for DPDeviceDiscovery API.\r
+ *\r
+ * @param[in] ctx             User context\r
+ * @param[in] handle          Handler for response\r
+ * @param[in] clientResponse  Response information (It will contain payload)\r
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and\r
+ *         OC_STACK_DELETE_TRANSACTION to delete it.\r
+ */\r
+static OCStackApplicationResult DirectPairingDiscoveryHandler(void* ctx, OCDoHandle UNUSED,\r
+        OCClientResponse * clientResponse)\r
+{\r
+    OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing DISCOVER query recvd successfully");\r
+\r
+    (void)ctx;\r
+    (void)UNUSED;\r
+    if (clientResponse)\r
+    {\r
+        OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));\r
+        OIC_LOG_V(INFO, TAG,\r
+                "Device =============> Discovered @ %s:%d",\r
+                clientResponse->devAddr.addr,\r
+                clientResponse->devAddr.port);\r
+\r
+        if  (NULL == clientResponse->payload)\r
+        {\r
+            OIC_LOG(INFO, TAG, "Skiping Null payload");\r
+            return OC_STACK_KEEP_TRANSACTION;\r
+        }\r
+        if (OC_STACK_OK != clientResponse->result)\r
+        {\r
+            OIC_LOG(INFO, TAG, "Error in response");\r
+            return OC_STACK_KEEP_TRANSACTION;\r
+        }\r
+\r
+        OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
+        OicSecPconf_t *pconf = JSONToPconfBin(\r
+                    ((OCSecurityPayload*)clientResponse->payload)->securityData);\r
+        if (NULL == pconf)\r
+        {\r
+            OIC_LOG(INFO, TAG, "Ignoring malformed JSON");\r
+            return OC_STACK_KEEP_TRANSACTION;\r
+        }\r
+        else\r
+        {\r
+            OCDevAddr endpoint;\r
+            memcpy(&endpoint, &clientResponse->devAddr, sizeof(OCDevAddr));\r
+\r
+            OCStackResult res = addDev(&g_dp_discover, &endpoint,\r
+                        clientResponse->connType, pconf);\r
+            DeletePconfBinData(pconf);\r
+            if (OC_STACK_OK != res)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");\r
+                return OC_STACK_KEEP_TRANSACTION;\r
+            }\r
+\r
+\r
+            char rsrc_uri[MAX_URI_LENGTH+1] = {0};\r
+            int wr_len = snprintf(rsrc_uri, sizeof(rsrc_uri), "%s?%s=%s",\r
+                      OC_RSRVD_WELL_KNOWN_URI, OC_RSRVD_RESOURCE_TYPE, OIC_RSRC_TYPE_SEC_DPAIRING);\r
+            if(wr_len <= 0 || (size_t)wr_len >= sizeof(rsrc_uri))\r
+            {\r
+                OIC_LOG(ERROR, TAG, "rsrc_uri_string_print failed");\r
+                return OC_STACK_ERROR;\r
+            }\r
+\r
+            //Try to the unicast discovery to getting secure port\r
+            char query[MAX_URI_LENGTH+MAX_QUERY_LENGTH+1] = {0};\r
+            if(!DPGenerateQuery(false,\r
+                                clientResponse->devAddr.addr, clientResponse->devAddr.port,\r
+                                clientResponse->connType,\r
+                                query, sizeof(query), rsrc_uri))\r
+            {\r
+                OIC_LOG(ERROR, TAG, "DirectPairingDiscoveryHandler : Failed to generate query");\r
+                return OC_STACK_KEEP_TRANSACTION;\r
+            }\r
+            OIC_LOG_V(DEBUG, TAG, "Query=%s", query);\r
+\r
+            OCCallbackData cbData;\r
+            cbData.cb = &DirectPairingPortDiscoveryHandler;\r
+            cbData.context = NULL;\r
+            cbData.cd = NULL;\r
+            OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,\r
+                    clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0);\r
+            if(OC_STACK_OK != ret)\r
+            {\r
+                OIC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");\r
+                return OC_STACK_KEEP_TRANSACTION;\r
+            }\r
+            else\r
+            {\r
+                OIC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);\r
+            }\r
+\r
+            return  OC_STACK_KEEP_TRANSACTION;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(INFO, TAG, "Skiping Null response");\r
+    }\r
+\r
+    return OC_STACK_DELETE_TRANSACTION;\r
+}\r
+\r
+/**\r
+ * Discover direct-pairing devices in the same IP subnet. .\r
+ *\r
+ * @param[in] waittime  Timeout in seconds.\r
+ *\r
+ * @return OC_STACK_OK on success otherwise error.\r
+ */\r
+OCStackResult DPDeviceDiscovery(unsigned short waittime)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "IN DPDeviceDiscovery");\r
+\r
+    if (g_dp_discover)\r
+    {\r
+        delList(g_dp_discover);\r
+        g_dp_discover = NULL;\r
+    }\r
+\r
+    OCStackResult ret;\r
+    struct timespec startTime = {.tv_sec=0, .tv_nsec=0};\r
+    struct timespec currTime  = {.tv_sec=0, .tv_nsec=0};\r
+    struct timespec timeout;\r
+\r
+    const char DP_DISCOVERY_QUERY[] = "/oic/sec/pconf";\r
+\r
+    OCCallbackData cbData;\r
+    cbData.cb = DirectPairingDiscoveryHandler;\r
+    cbData.context = NULL;\r
+    cbData.cd = NULL;\r
+\r
+    /* Start a DP discovery query*/\r
+    OIC_LOG_V(INFO, TAG, "Initiating Direct-Pairing Discovery : %s\n", DP_DISCOVERY_QUERY);\r
+    OCDoHandle handle = NULL;\r
+    ret = OCDoResource(&handle, OC_REST_DISCOVER, DP_DISCOVERY_QUERY, 0, 0, CT_DEFAULT,\r
+                       OC_LOW_QOS, &cbData, NULL, 0);\r
+    if (ret != OC_STACK_OK)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCStack resource error");\r
+        return ret;\r
+    }\r
+\r
+    // wait..\r
+    timeout.tv_sec  = 0;\r
+    timeout.tv_nsec = 100000000L;\r
+\r
+    int clock_res = -1;\r
+#if defined(__ANDROID__) || _POSIX_TIMERS > 0\r
+    clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);\r
+#endif\r
+    if (0 != clock_res)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "clock error");\r
+        if(OC_STACK_OK !=  OCCancel(handle, OC_LOW_QOS, NULL, 0))\r
+        {\r
+            OIC_LOG(ERROR, TAG, "Failed to remove registered callback");\r
+        }\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    while (1)\r
+    {\r
+#if defined(__ANDROID__) || _POSIX_TIMERS > 0\r
+        clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);\r
+#endif\r
+        if (0 != clock_res)\r
+        {\r
+            OIC_LOG(ERROR, TAG, "clock error");\r
+            ret = OC_STACK_ERROR;\r
+            break;\r
+        }\r
+        long elapsed = (currTime.tv_sec - startTime.tv_sec);\r
+        if (elapsed > waittime)\r
+        {\r
+            break;\r
+        }\r
+        else\r
+        {\r
+            nanosleep(&timeout, NULL);\r
+        }\r
+    }\r
+\r
+    //Waiting for each response.\r
+    ret = OCCancel(handle, OC_LOW_QOS, NULL, 0);\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Failed to remove registered callback");\r
+    }\r
+    OIC_LOG(DEBUG, TAG, "OUT DPDeviceDiscovery");\r
+    return ret;\r
+}\r
+\r
index 74d28ac..860a78d 100644 (file)
@@ -65,6 +65,7 @@ static OicSecDoxm_t gDefaultDoxm =
     SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
     false,                  /* bool owned */
     {.id = {0}},            /* OicUuid_t deviceID */
+    false,                  /* bool dpc */
     {.id = {0}},            /* OicUuid_t owner */
 };
 
@@ -153,6 +154,9 @@ char * BinToDoxmJSON(const OicSecDoxm_t * doxm)
     VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
     cJSON_AddStringToObject(jsonDoxm, OIC_JSON_DEVICE_ID_NAME, base64Buff);
 
+    //DPC -- Mandatory
+    cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_DPC_NAME, doxm->dpc);
+
     //Owner -- Mandatory
     outLen = 0;
     b64Ret = b64Encode(doxm->owner.id, sizeof(doxm->owner.id), base64Buff,
@@ -301,6 +305,25 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
         memcpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
     }
 
+    //DPC -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DPC_NAME);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
+        doxm->dpc = jsonObj->valueint;
+    }
+    else // PUT/POST JSON may not have owned so set it to the gDomx->dpc
+    {
+        if(NULL != gDoxm)
+        {
+            doxm->dpc = gDoxm->dpc;
+        }
+        else
+        {
+            doxm->dpc = false; // default is false
+        }
+    }
+
     //Owner -- will be empty when device status is unowned.
     jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
     if(true == doxm->owned)
diff --git a/resource/csdk/security/src/dpairingresource.c b/resource/csdk/security/src/dpairingresource.c
new file mode 100755 (executable)
index 0000000..ca01c1d
--- /dev/null
@@ -0,0 +1,668 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "ocstack.h"\r
+#include "logger.h"\r
+#include "oic_malloc.h"\r
+#include "oic_string.h"\r
+#include "cJSON.h"\r
+#include "base64.h"\r
+#include "resourcemanager.h"\r
+#include "dpairingresource.h"\r
+#include "psinterface.h"\r
+#include "utlist.h"\r
+#include "srmresourcestrings.h"\r
+#include "cainterface.h"\r
+#include "doxmresource.h"\r
+#include "pconfresource.h"\r
+#include "credresource.h"\r
+#include "aclresource.h"\r
+#include "srmutility.h"\r
+#include "ocserverrequest.h"\r
+#include <stdlib.h>\r
+#ifdef WITH_ARDUINO\r
+#include <string.h>\r
+#else\r
+#include <strings.h>\r
+#endif\r
+\r
+#ifdef __WITH_DTLS__\r
+#include "global.h"\r
+#endif\r
+\r
+#define TAG  "SRM-DPAIRING"\r
+\r
+\r
+static OicSecDpairing_t     *gDpair = NULL;\r
+static OCResourceHandle   gDpairHandle = NULL;\r
+static OicSecDpairing_t      gDefaultDpair =\r
+{\r
+    PRM_NOT_ALLOWED,       /* OicSecPrm_t spm */\r
+    {.id = {0}},                   /* OicUuid_t pdeviceID */\r
+    {.id = {0}},                   /* OicUuid_t rowner */\r
+};\r
+\r
+void DeleteDpairingBinData(OicSecDpairing_t* dpair)\r
+{\r
+    if (dpair)\r
+    {\r
+        //Clean dpairing itself\r
+        OICFree(dpair);\r
+    }\r
+}\r
+\r
+/**\r
+ * Get the default value.\r
+ * @retval  the gDefaultDpair pointer;\r
+ */\r
+static OicSecDpairing_t* GetDpairingDefault()\r
+{\r
+    OIC_LOG (DEBUG, TAG, "GetDpairingDefault");\r
+\r
+    return &gDefaultDpair;\r
+}\r
+\r
+/**\r
+ * This method is used by SRM to retrieve Dpairing resource data..\r
+ */\r
+void SetDpairingResourceOwner(OicUuid_t *rowner)\r
+{\r
+    OIC_LOG (DEBUG, TAG, "SetDpairingResourceOwner");\r
+    if (gDpair)\r
+    {\r
+        memcpy(&gDpair->rowner, rowner, sizeof(OicUuid_t));\r
+    }\r
+}\r
+\r
+#ifdef __WITH_DTLS__\r
+/**\r
+ * Function to save PairingPSK.\r
+ *\r
+ * @param[in] endpoint   current endpoint.\r
+ * @param[in] peerDevID   peer device indentitiy.\r
+ * @param[in] isPairingServer   indicate if it generates PairingPSK for server or client.\r
+ *\r
+ * @return  OC_STACK_OK on success\r
+ */\r
+OCStackResult SavePairingPSK(OCDevAddr *endpoint,\r
+            OicUuid_t *peerDevID, OicUuid_t *owner, bool isPairingServer)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "IN SavePairingPSK");\r
+\r
+    if(NULL == endpoint || NULL == peerDevID || NULL == owner)\r
+    {\r
+        OIC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    OCStackResult res = OC_STACK_ERROR;\r
+\r
+    OicUuid_t ptDeviceID = {.id={0}};\r
+    if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");\r
+        return res;\r
+    }\r
+\r
+    uint8_t pairingPSK[OWNER_PSK_LENGTH_128] = {0};\r
+\r
+    //Generating PairingPSK using OwnerPSK scheme\r
+    CAResult_t pskRet = CAGenerateOwnerPSK((const CAEndpoint_t *)endpoint,\r
+            (uint8_t *)OIC_RSRC_TYPE_SEC_DPAIRING,\r
+            strlen(OIC_RSRC_TYPE_SEC_DPAIRING),\r
+            (isPairingServer ? ptDeviceID.id : peerDevID->id), sizeof(OicUuid_t), // server\r
+            (isPairingServer ? peerDevID->id : ptDeviceID.id), sizeof(OicUuid_t), // client\r
+            pairingPSK, OWNER_PSK_LENGTH_128);\r
+\r
+    if (CA_STATUS_OK == pskRet)\r
+    {\r
+        OIC_LOG(INFO, TAG, "pairingPSK dump:\n");\r
+        OIC_LOG_BUFFER(INFO, TAG, pairingPSK, OWNER_PSK_LENGTH_128);\r
+        //Generating new credential for direct-pairing client\r
+        size_t ownLen = 1;\r
+        uint32_t outLen = 0;\r
+\r
+        char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(pairingPSK)) + 1] = {};\r
+        B64Result b64Ret = b64Encode(pairingPSK, sizeof(pairingPSK), base64Buff, sizeof(base64Buff),\r
+                &outLen);\r
+        VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);\r
+\r
+        OicSecCred_t *cred = GenerateCredential(peerDevID,\r
+                SYMMETRIC_PAIR_WISE_KEY, NULL,\r
+                base64Buff, ownLen, owner);\r
+        VERIFY_NON_NULL(TAG, cred, ERROR);\r
+\r
+        res = AddCredential(cred);\r
+        if(res != OC_STACK_OK)\r
+        {\r
+            DeleteCredList(cred);\r
+            return res;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");\r
+    }\r
+\r
+    OIC_LOG(DEBUG, TAG, "OUT SavePairingPSK");\r
+exit:\r
+    return res;\r
+}\r
+#endif // __WITH_DTLS__\r
+\r
+/*\r
+ * This internal method converts DPairing data into JSON format.\r
+ * Does not error-check here, but check it in caller\r
+ *\r
+ * Note: Caller needs to invoke 'free' when finished done using\r
+ * return string.\r
+ */\r
+char * BinToDpairingJSON(const OicSecDpairing_t * dpair)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "BinToDpairingJSON() IN");\r
+\r
+    if (NULL == dpair)\r
+    {\r
+        return NULL;\r
+    }\r
+\r
+    char *jsonStr = NULL;\r
+    cJSON *jsonDpair = NULL;\r
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};\r
+    uint32_t outLen = 0;\r
+    B64Result b64Ret = B64_OK;\r
+\r
+    cJSON *jsonRoot = cJSON_CreateObject();\r
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
+\r
+    jsonDpair = cJSON_CreateObject();\r
+    VERIFY_NON_NULL(TAG, jsonDpair, ERROR);\r
+    cJSON_AddItemToObject(jsonRoot, OIC_JSON_DPAIRING_NAME, jsonDpair );\r
+\r
+    //SPM -- Mandatory\r
+    if(PRM_RANDOM_PIN >= dpair->spm) // don't need to check "PRM_NOT_ALLOWED <= dpair->spm" because of always true\r
+    {\r
+        cJSON_AddNumberToObject(jsonDpair, OIC_JSON_SPM_NAME, (int)dpair->spm);\r
+    }\r
+\r
+    //PDeviceID -- Mandatory\r
+    //There may not be paired devices if it did not be received pairing request\r
+    if ('\0' != (char)dpair->pdeviceID.id[0])\r
+    {\r
+        outLen = 0;\r
+        b64Ret = b64Encode(dpair->pdeviceID.id, sizeof(dpair->pdeviceID.id), base64Buff,\r
+                    sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
+        cJSON_AddStringToObject(jsonDpair, OIC_JSON_PDEVICE_ID_NAME, base64Buff);\r
+    }\r
+\r
+    //ROwner -- Mandatory\r
+    if ('\0' != (char)dpair->rowner.id[0])\r
+    {\r
+        outLen = 0;\r
+        b64Ret = b64Encode(dpair->rowner.id, sizeof(dpair->rowner.id), base64Buff,\r
+                    sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
+        cJSON_AddStringToObject(jsonDpair, OIC_JSON_ROWNER_NAME, base64Buff);\r
+    }\r
+\r
+\r
+    jsonStr = cJSON_PrintUnformatted(jsonRoot);\r
+\r
+exit:\r
+    if (jsonRoot)\r
+    {\r
+        cJSON_Delete(jsonRoot);\r
+    }\r
+    return jsonStr;\r
+}\r
+\r
+/*\r
+ * This internal method converts JSON Dpairing into binary Dpairing.\r
+ * Does not error-check here, but check it in caller\r
+ */\r
+OicSecDpairing_t* JSONToDpairingBin(const char * jsonStr)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "JSONToDpairingBin() IN");\r
+\r
+    OCStackResult ret = OC_STACK_ERROR;\r
+    OicSecDpairing_t *dpair =  NULL;\r
+    cJSON *jsonRoot = NULL;\r
+    cJSON *jsonDpair = NULL;\r
+    cJSON *jsonObj = NULL;\r
+\r
+    unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};\r
+    uint32_t outLen = 0;\r
+    B64Result b64Ret = B64_OK;\r
+\r
+\r
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);\r
+\r
+    jsonRoot = cJSON_Parse(jsonStr);\r
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
+\r
+    jsonDpair = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DPAIRING_NAME);\r
+    VERIFY_NON_NULL(TAG, jsonDpair, ERROR);\r
+\r
+    dpair = (OicSecDpairing_t*)OICCalloc(1, sizeof(OicSecDpairing_t));\r
+    VERIFY_NON_NULL(TAG, dpair, ERROR);\r
+\r
+    //SPM -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_SPM_NAME);\r
+    if (jsonObj && cJSON_Number == jsonObj->type)\r
+    {\r
+        dpair->spm = (OicSecPrm_t)jsonObj->valueint;\r
+        OIC_LOG_V (DEBUG, TAG, "jsonObj->valueint = %d", jsonObj->valueint);\r
+        OIC_LOG_V (DEBUG, TAG, "dpair->spm = %d", dpair->spm);\r
+\r
+        // don't need to check "PRM_NOT_ALLOWED <= dpair->spm" because of always true\r
+        VERIFY_SUCCESS(TAG, (PRM_RANDOM_PIN >= dpair->spm), ERROR);\r
+    }\r
+    else\r
+    {\r
+        dpair->spm = PRM_NOT_ALLOWED;\r
+    }\r
+\r
+    //PDeviceId -- Mandatory\r
+    outLen = 0;\r
+    jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_PDEVICE_ID_NAME);\r
+    if (jsonObj && cJSON_String == jsonObj->type)\r
+    {\r
+        b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
+                sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(dpair->pdeviceID.id)), ERROR);\r
+        memcpy(dpair->pdeviceID.id, base64Buff, outLen);\r
+    }\r
+    else\r
+    {\r
+        memset(&dpair->pdeviceID, 0, sizeof(OicUuid_t));\r
+    }\r
+\r
+    // ROwner -- Mandatory\r
+    outLen = 0;\r
+    jsonObj = cJSON_GetObjectItem(jsonDpair, OIC_JSON_ROWNER_NAME);\r
+    if (jsonObj && cJSON_String == jsonObj->type)\r
+    {\r
+        b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
+                sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(dpair->rowner.id)), ERROR);\r
+        memcpy(dpair->rowner.id, base64Buff, outLen);\r
+    }\r
+    else\r
+    {\r
+        memset(&dpair->rowner, 0, sizeof(OicUuid_t));\r
+    }\r
+\r
+    ret = OC_STACK_OK;\r
+\r
+exit:\r
+    cJSON_Delete(jsonRoot);\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        DeleteDpairingBinData(dpair);\r
+        dpair = NULL;\r
+    }\r
+\r
+    OIC_LOG(DEBUG, TAG, "JSONToDpairingBin() OUT");\r
+    return dpair;\r
+}\r
+\r
+/**\r
+ * Function to handle the handshake result in Direct-Pairing.\r
+ * This function will be invoked after DTLS handshake\r
+ * @param   endPoint  [IN] The remote endpoint.\r
+ * @param   errorInfo [IN] Error information from the endpoint.\r
+ * @return  NONE\r
+ */\r
+void DPairingDTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)\r
+{\r
+    OIC_LOG_V(INFO, TAG, "IN DPairingDTLSHandshakeCB");\r
+\r
+    if(gDpair && endpoint && info)\r
+    {\r
+        OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",\r
+                 endpoint->addr, endpoint->port, info->result);\r
+\r
+        if(CA_STATUS_OK == info->result)\r
+        {\r
+            OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Connection success.");\r
+        }\r
+        else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)\r
+        {\r
+            OIC_LOG(INFO, TAG, "DPairingDTLSHandshakeCB - Authentication failed");\r
+\r
+        }\r
+\r
+#ifdef __WITH_DTLS__\r
+        CARegisterDTLSHandshakeCallback(NULL);\r
+#endif // __WITH_DTLS__\r
+\r
+        // delete temporary key\r
+        RemoveCredential(&gDpair->pdeviceID);\r
+    }\r
+\r
+    OIC_LOG_V(INFO, TAG, "OUT DPairingDTLSHandshakeCB");\r
+}\r
+\r
+static OCEntityHandlerResult HandleDpairingPostRequest (const OCEntityHandlerRequest * ehRequest)\r
+{\r
+    OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing POST request");\r
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
+    OicSecDpairing_t* newDpair = NULL;\r
+\r
+    const OicSecPconf_t *pconf = GetPconfResourceData();\r
+    if (true == pconf->edp)\r
+    {\r
+        // Convert JSON DPAIRING data into binary. This will also validate the DPAIRING data received.\r
+        newDpair = JSONToDpairingBin(((OCSecurityPayload*)ehRequest->payload)->securityData);\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");\r
+        ehRet = OC_EH_ERROR;\r
+    }\r
+\r
+    if (newDpair && false == IsPairedDevice(&newDpair->pdeviceID))\r
+    {\r
+        // Check if valid Post request\r
+        bool prmMached = false;\r
+        for (size_t i=0; i<pconf->prmLen; i++)\r
+        {\r
+            if (newDpair->spm == pconf->prm[i])\r
+            {\r
+                prmMached = true;\r
+                break;\r
+            }\r
+        }\r
+        OIC_LOG_V(DEBUG, TAG, "Parsed spm is %s", prmMached ? "valid" : "invalid, send error response");\r
+\r
+        // Update local Dpairing with new Dpairing & prepare dtls session\r
+        if (prmMached && '\0' != (char)newDpair->pdeviceID.id[0])\r
+        {\r
+            if(!gDpair)\r
+            {\r
+                gDpair = GetDpairingDefault();\r
+            }\r
+            gDpair->spm = newDpair->spm;\r
+            memcpy(&gDpair->pdeviceID, &newDpair->pdeviceID, sizeof(OicUuid_t));\r
+            memcpy(&gDpair->rowner, &pconf->rowner, sizeof(OicUuid_t));\r
+\r
+#ifdef __WITH_DTLS__\r
+            // Add temporary psk\r
+            OCStackResult res;\r
+            OicUuid_t subjectId = {.id={0}};\r
+            res = AddTmpPskWithPIN(&gDpair->pdeviceID,\r
+                           SYMMETRIC_PAIR_WISE_KEY,\r
+                           (char*)pconf->pin.val, DP_PIN_LENGTH,\r
+                           1, &gDpair->rowner, &subjectId);\r
+            if(res != OC_STACK_OK ||\r
+                    memcmp(&gDpair->pdeviceID, &subjectId, sizeof(OicUuid_t)))\r
+            {\r
+                OIC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);\r
+                goto exit;\r
+            }\r
+\r
+            // Prepare to establish a secure channel with Pin-based PSK cipher suite\r
+            if (CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false) ||\r
+                CA_STATUS_OK != CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))\r
+            {\r
+                OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");\r
+                goto exit;\r
+            }\r
+\r
+            if(CA_STATUS_OK != CARegisterDTLSHandshakeCallback(DPairingDTLSHandshakeCB))\r
+            {\r
+                OIC_LOG(WARNING, TAG, "DirectPairingHandler : Failed to register DTLS handshake callback.");\r
+                goto exit;\r
+            }\r
+#endif // __WITH_DTLS__\r
+\r
+            // should be lock /oic/sec/dpairing resource if Direct-Pairing starts normally ?\r
+            OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource created");\r
+\r
+            ehRet = OC_EH_RESOURCE_CREATED;\r
+        }\r
+        else\r
+        {\r
+            OIC_LOG(ERROR, TAG, "Error in request check");\r
+        }\r
+    }\r
+\r
+\r
+#ifdef __WITH_DTLS__\r
+exit:\r
+#endif // __WITH_DTLS__\r
+\r
+    if (OC_EH_ERROR == ehRet && gDpair)\r
+    {\r
+        RemoveCredential(&gDpair->pdeviceID);\r
+        gDpair = NULL;\r
+    }\r
+\r
+    // Send payload to request originator\r
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))\r
+    {\r
+        OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPostRequest");\r
+    }\r
+\r
+    DeleteDpairingBinData(newDpair);\r
+    OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);\r
+    return ehRet;\r
+}\r
+\r
+static OCEntityHandlerResult HandleDpairingPutRequest (const OCEntityHandlerRequest * ehRequest)\r
+{\r
+    OIC_LOG (DEBUG, TAG, "Dpairing EntityHandle  processing PUT request (Comfirmation)");\r
+\r
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
+    OicSecDpairing_t* newDpair = NULL;\r
+\r
+    const OicSecPconf_t *pconf = GetPconfResourceData();\r
+    if (true == pconf->edp)\r
+    {\r
+        // Convert JSON DPAIRING data into binary. This will also validate the DPAIRING data received.\r
+        newDpair = JSONToDpairingBin(((OCSecurityPayload*)ehRequest->payload)->securityData);\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "EDP == false : Direct-Pairing Disabled");\r
+        ehRet = OC_EH_ERROR;\r
+    }\r
+\r
+    if (gDpair && newDpair)\r
+    {\r
+        OIC_LOG(DEBUG, TAG, "Received direct-pairing finalization request");\r
+\r
+        // Check if valid Put request\r
+        VERIFY_SUCCESS(TAG, PRM_NOT_ALLOWED == newDpair->spm, ERROR);\r
+\r
+        const OicSecPconf_t *pconf = GetPconfResourceData();\r
+        VERIFY_NON_NULL(TAG, pconf, ERROR);\r
+\r
+#ifdef __WITH_DTLS__\r
+        OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;\r
+        VERIFY_SUCCESS(TAG, (request->devAddr.flags | OC_FLAG_SECURE), ERROR);\r
+\r
+        //Generate new credential\r
+        OIC_LOG_V(INFO, TAG, "SavePairingPSK for %s(%d)", request->devAddr.addr, request->devAddr.port);\r
+        OCStackResult res = SavePairingPSK(&request->devAddr, &newDpair->pdeviceID,\r
+                                                                  (OicUuid_t *)&pconf->rowner, true);\r
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);\r
+#endif //__WITH_DTLS__\r
+\r
+        //Generate new acl\r
+        OicSecPdAcl_t *pdAcl;\r
+        LL_FOREACH(pconf->pdacls, pdAcl)\r
+        {\r
+            OicSecAcl_t acl;\r
+            memset(&acl, 0, sizeof(OicSecAcl_t));\r
+            memcpy(&acl.subject, &gDpair->pdeviceID, sizeof(OicUuid_t));\r
+            acl.resources = pdAcl->resources;\r
+            acl.resourcesLen = pdAcl->resourcesLen;\r
+            acl.owners = (OicUuid_t*)&pconf->rowner;\r
+            acl.ownersLen = 1;\r
+            acl.permission = pdAcl->permission;\r
+            acl.periods = pdAcl->periods;\r
+            acl.recurrences = pdAcl->recurrences;\r
+            acl.prdRecrLen = pdAcl->prdRecrLen;\r
+\r
+            char* aclJson = BinToAclJSON(&acl);\r
+            if (aclJson)\r
+            {\r
+                InstallNewACL(aclJson);\r
+                OICFree(aclJson);\r
+            }\r
+        }\r
+\r
+        //update pconf device list\r
+        AddPairedDevice(&newDpair->pdeviceID);\r
+\r
+        //Initialize dpairing resource\r
+        gDpair = NULL;\r
+\r
+        OIC_LOG (DEBUG, TAG, "/oic/sec/dpairing resource updated, direct-pairing finalization success");\r
+        ehRet = OC_EH_OK;\r
+    }\r
+\r
+exit:\r
+\r
+    //Send payload to request originator\r
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))\r
+    {\r
+        OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingPutRequest");\r
+    }\r
+\r
+    DeleteDpairingBinData(newDpair);\r
+    OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);\r
+    return ehRet;\r
+}\r
+/*\r
+ * This internal method is the entity handler for Dpairing resources and\r
+ * will handle REST request (GET/POST) for them.\r
+ */\r
+OCEntityHandlerResult DpairingEntityHandler (OCEntityHandlerFlag flag,\r
+                                        OCEntityHandlerRequest * ehRequest,\r
+                                        void* callbackParameter)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "Received request DpairingEntityHandler");\r
+    (void)callbackParameter;\r
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
+\r
+    if (!ehRequest)\r
+    {\r
+        return ehRet;\r
+    }\r
+\r
+    if (flag & OC_REQUEST_FLAG)\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");\r
+        switch (ehRequest->method)\r
+        {\r
+            case OC_REST_GET:\r
+                break;\r
+\r
+            case OC_REST_POST:\r
+                ehRet = HandleDpairingPostRequest(ehRequest);\r
+                break;\r
+\r
+            case OC_REST_PUT:\r
+                ehRet = HandleDpairingPutRequest(ehRequest);\r
+                break;\r
+\r
+            case OC_REST_DELETE:\r
+                break;\r
+\r
+            default:\r
+                ehRet = OC_EH_ERROR;\r
+                SendSRMResponse(ehRequest, ehRet, NULL);\r
+        }\r
+    }\r
+\r
+    return ehRet;\r
+}\r
+\r
+/*\r
+ * This internal method is used to create '/oic/sec/dpairing' resource.\r
+ */\r
+OCStackResult CreateDpairingResource()\r
+{\r
+    OCStackResult ret;\r
+\r
+    ret = OCCreateResource(&gDpairHandle,\r
+                           OIC_RSRC_TYPE_SEC_DPAIRING,\r
+                           OIC_MI_DEF,\r
+                           OIC_RSRC_DPAIRING_URI,\r
+                           DpairingEntityHandler,\r
+                           NULL,\r
+                           OC_SECURE | OC_EXPLICIT_DISCOVERABLE);\r
+\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        OIC_LOG (ERROR, TAG, "Unable to instantiate Dpairing resource");\r
+        DeInitDpairingResource();\r
+    }\r
+    return ret;\r
+}\r
+\r
+/**\r
+ * Initialize Dpairing resource by loading data from persistent storage.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult InitDpairingResource()\r
+{\r
+    OCStackResult ret = OC_STACK_ERROR;\r
+\r
+    // Instantiate 'oic.sec.dpairing'\r
+    ret = CreateDpairingResource();\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        DeInitDpairingResource();\r
+    }\r
+    return ret;\r
+}\r
+\r
+/**\r
+ * Perform cleanup for Dpairing resources.\r
+ *\r
+ * @return\r
+ * OC_STACK_OK    - no error\r
+ * OC_STACK_ERROR - stack process error\r
+ *\r
+ */\r
+OCStackResult DeInitDpairingResource()\r
+{\r
+    OCStackResult ret = OCDeleteResource(gDpairHandle);\r
+    gDpair = NULL;\r
+\r
+    if(OC_STACK_OK == ret)\r
+    {\r
+        return OC_STACK_OK;\r
+    }\r
+    else\r
+    {\r
+        return OC_STACK_ERROR;\r
+    }\r
+}\r
+\r
+\r
+\r
diff --git a/resource/csdk/security/src/pconfresource.c b/resource/csdk/security/src/pconfresource.c
new file mode 100644 (file)
index 0000000..f1764c1
--- /dev/null
@@ -0,0 +1,981 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2016 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include "ocstack.h"\r
+#include "logger.h"\r
+#include "oic_malloc.h"\r
+#include "oic_string.h"\r
+#include "cJSON.h"\r
+#include "base64.h"\r
+#include "resourcemanager.h"\r
+#include "pconfresource.h"\r
+#include "psinterface.h"\r
+#include "utlist.h"\r
+#include "srmresourcestrings.h"\r
+#include "doxmresource.h"\r
+#include "srmutility.h"\r
+#include "ocserverrequest.h"\r
+#include <stdlib.h>\r
+#ifdef WITH_ARDUINO\r
+#include <string.h>\r
+#else\r
+#include <strings.h>\r
+#endif\r
+\r
+#define TAG  "SRM-PCONF"\r
+\r
+\r
+static OicSecPconf_t          *gPconf = NULL;\r
+static OCResourceHandle   gPconfHandle = NULL;\r
+static OicSecPconf_t         gDefaultPconf =\r
+{\r
+    false,                  /* bool edp */\r
+    NULL,                  /* OicSecPrm *prm */\r
+    0,                       /* size_t prmLen */\r
+    {.val = {0}},       /* OicDpPin_t pin */\r
+    NULL,                  /* OicSecPdAcl_t *pdacls */\r
+    NULL,                  /* OicUuid_t *pddevs */\r
+    0,                       /* size_t pddevLen */\r
+    {.id = {0}},        /* OicUuid_t deviceID */\r
+    {.id = {0}},        /* OicUuid_t rowner */\r
+};\r
+\r
+/**\r
+ * This function frees OicSecPdAcl_t object's fields and object itself.\r
+ */\r
+void FreePdAclList(OicSecPdAcl_t* pdacls)\r
+{\r
+    if (pdacls)\r
+    {\r
+        size_t i = 0;\r
+\r
+        //Clean pdacl objecs\r
+        OicSecPdAcl_t *aclTmp1 = NULL;\r
+        OicSecPdAcl_t *aclTmp2 = NULL;\r
+        LL_FOREACH_SAFE(pdacls, aclTmp1, aclTmp2)\r
+        {\r
+            LL_DELETE(pdacls, aclTmp1);\r
+\r
+            // Clean Resources\r
+            for (i = 0; i < aclTmp1->resourcesLen; i++)\r
+            {\r
+                OICFree(aclTmp1->resources[i]);\r
+            }\r
+            OICFree(aclTmp1->resources);\r
+\r
+            //Clean Period\r
+            if(aclTmp1->periods)\r
+            {\r
+                for(i = 0; i < aclTmp1->prdRecrLen; i++)\r
+                {\r
+                    OICFree(aclTmp1->periods[i]);\r
+                }\r
+                OICFree(aclTmp1->periods);\r
+            }\r
+\r
+            //Clean Recurrence\r
+            if(aclTmp1->recurrences)\r
+            {\r
+                for(i = 0; i < aclTmp1->prdRecrLen; i++)\r
+                {\r
+                    OICFree(aclTmp1->recurrences[i]);\r
+                }\r
+                OICFree(aclTmp1->recurrences);\r
+            }\r
+        }\r
+\r
+        //Clean pconf itself\r
+        OICFree(pdacls);\r
+    }\r
+}\r
+\r
+void DeletePconfBinData(OicSecPconf_t* pconf)\r
+{\r
+    if (pconf)\r
+    {\r
+        //Clean prm\r
+        OICFree(pconf->prm);\r
+\r
+        //Clean pdacl\r
+        if (pconf->pdacls)\r
+        {\r
+            FreePdAclList(pconf->pdacls);\r
+        }\r
+\r
+        //Clean pddev\r
+        OICFree(pconf->pddevs);\r
+\r
+        //Clean pconf itself\r
+        OICFree(pconf);\r
+    }\r
+}\r
+\r
+/*\r
+ * This internal method converts PCONF data into JSON format.\r
+ *\r
+ * Note: Caller needs to invoke 'free' when finished done using\r
+ * return string.\r
+ */\r
+char * BinToPconfJSON(const OicSecPconf_t * pconf)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "BinToPconfJSON() IN");\r
+\r
+    if (NULL == pconf)\r
+    {\r
+        return NULL;\r
+    }\r
+\r
+    char *jsonStr = NULL;\r
+    cJSON *jsonPconf = NULL;\r
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};\r
+    uint32_t outLen = 0;\r
+    B64Result b64Ret = B64_OK;\r
+\r
+    cJSON *jsonRoot = cJSON_CreateObject();\r
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
+\r
+    jsonPconf = cJSON_CreateObject();\r
+    VERIFY_NON_NULL(TAG, jsonPconf, ERROR);\r
+    cJSON_AddItemToObject(jsonRoot, OIC_JSON_PCONF_NAME, jsonPconf );\r
+\r
+\r
+    //EDP -- Mandatory\r
+    cJSON_AddBoolToObject(jsonPconf, OIC_JSON_EDP_NAME, pconf->edp);\r
+\r
+    //PRM type -- Mandatory\r
+    if(0< pconf->prmLen)\r
+    {\r
+        cJSON *jsonPrmArray = cJSON_CreateArray();\r
+        VERIFY_NON_NULL(TAG, jsonPrmArray, ERROR);\r
+        cJSON_AddItemToObject (jsonPconf, OIC_JSON_PRM_NAME, jsonPrmArray);\r
+        OIC_LOG_V (DEBUG, TAG, "pconf->prmLen = %d", (int)pconf->prmLen);\r
+        for (size_t i = 0; i < pconf->prmLen; i++)\r
+        {\r
+            OIC_LOG_V (DEBUG, TAG, "pconf->prm[%d] = %d", (int)i, pconf->prm[i]);\r
+            cJSON_AddItemToArray (jsonPrmArray, cJSON_CreateNumber(pconf->prm[i]));\r
+        }\r
+    }\r
+\r
+    //PIN -- Mandatory\r
+    if(DP_PIN_LENGTH == strlen((const char*)pconf->pin.val))\r
+    {\r
+        cJSON_AddStringToObject(jsonPconf, OIC_JSON_PIN_NAME, (char*)pconf->pin.val);\r
+    }\r
+\r
+    //PDACL -- Mandatory\r
+    if(pconf->pdacls)\r
+    {\r
+        cJSON *jsonAclArray = NULL;\r
+        OicSecPdAcl_t *pdacl = NULL;\r
+        cJSON_AddItemToObject (jsonPconf, OIC_JSON_PDACL_NAME,\r
+                jsonAclArray = cJSON_CreateArray());\r
+        VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);\r
+\r
+        pdacl = pconf->pdacls;\r
+        while(pdacl)\r
+        {\r
+            cJSON *jsonAcl = cJSON_CreateObject();\r
+\r
+            // Resources -- Mandatory\r
+            cJSON *jsonRsrcArray = NULL;\r
+            cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME,\r
+                    jsonRsrcArray = cJSON_CreateArray());\r
+            VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);\r
+            for (size_t i = 0; i < pdacl->resourcesLen; i++)\r
+            {\r
+                cJSON_AddItemToArray (jsonRsrcArray,\r
+                        cJSON_CreateString(pdacl->resources[i]));\r
+            }\r
+\r
+            // Permissions -- Mandatory\r
+            cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, pdacl->permission);\r
+\r
+            //Period & Recurrence -- Not Mandatory\r
+            if(0 != pdacl->prdRecrLen && pdacl->periods)\r
+            {\r
+                cJSON *jsonPeriodArray = NULL;\r
+                cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,\r
+                        jsonPeriodArray = cJSON_CreateArray());\r
+                VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);\r
+                for (size_t i = 0; i < pdacl->prdRecrLen; i++)\r
+                {\r
+                    cJSON_AddItemToArray (jsonPeriodArray,\r
+                            cJSON_CreateString(pdacl->periods[i]));\r
+                }\r
+            }\r
+\r
+            //Recurrence -- Not Mandatory\r
+            if(0 != pdacl->prdRecrLen && pdacl->recurrences)\r
+            {\r
+                cJSON *jsonRecurArray  = NULL;\r
+                cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,\r
+                        jsonRecurArray = cJSON_CreateArray());\r
+                VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);\r
+                for (size_t i = 0; i < pdacl->prdRecrLen; i++)\r
+                {\r
+                    cJSON_AddItemToArray (jsonRecurArray,\r
+                            cJSON_CreateString(pdacl->recurrences[i]));\r
+                }\r
+            }\r
+\r
+            // Attach current acl node to Acl Array\r
+            cJSON_AddItemToArray(jsonAclArray, jsonAcl);\r
+            pdacl = pdacl->next;\r
+        }\r
+    }\r
+\r
+    //PDDev -- Mandatory\r
+    //There may not be paired devices if it did not pairing before\r
+    if (pconf->pddevs && 0 < pconf->pddevLen)\r
+    {\r
+        cJSON *jsonPdDevArray = cJSON_CreateArray();\r
+        VERIFY_NON_NULL(TAG, jsonPdDevArray, ERROR);\r
+        cJSON_AddItemToObject (jsonPconf, OIC_JSON_PDDEV_LIST_NAME, jsonPdDevArray );\r
+        for (size_t i = 0; i < pconf->pddevLen; i++)\r
+        {\r
+            outLen = 0;\r
+            b64Ret = b64Encode(pconf->pddevs[i].id, sizeof(pconf->pddevs[i].id), base64Buff,\r
+                        sizeof(base64Buff), &outLen);\r
+            VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
+            cJSON_AddItemToArray (jsonPdDevArray, cJSON_CreateString(base64Buff));\r
+        }\r
+    }\r
+\r
+    //DeviceId -- Mandatory\r
+    //There may not be devicd id if caller is provisoning tool\r
+    if ('\0' != (char)pconf->deviceID.id[0])\r
+    {\r
+        outLen = 0;\r
+        b64Ret = b64Encode(pconf->deviceID.id, sizeof(pconf->deviceID.id), base64Buff,\r
+                    sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
+        cJSON_AddStringToObject(jsonPconf, OIC_JSON_DEVICE_ID_NAME, base64Buff);\r
+    }\r
+\r
+    //ROwner -- Mandatory\r
+    VERIFY_SUCCESS(TAG, '\0' != (char)pconf->rowner.id[0], ERROR);\r
+    outLen = 0;\r
+    b64Ret = b64Encode(pconf->rowner.id, sizeof(pconf->rowner.id), base64Buff,\r
+                    sizeof(base64Buff), &outLen);\r
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);\r
+    cJSON_AddStringToObject(jsonPconf, OIC_JSON_ROWNER_NAME, base64Buff);\r
+\r
+\r
+    jsonStr = cJSON_PrintUnformatted(jsonRoot);\r
+\r
+exit:\r
+    if (jsonRoot)\r
+    {\r
+        cJSON_Delete(jsonRoot);\r
+    }\r
+    return jsonStr;\r
+}\r
+\r
+/*\r
+ * This internal method converts JSON PCONF into binary PCONF.\r
+ */\r
+OicSecPconf_t * JSONToPconfBin(const char * jsonStr)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "JSONToPconfBin() IN");\r
+\r
+    OCStackResult ret = OC_STACK_ERROR;\r
+    OicSecPconf_t * pconf =  NULL;\r
+    cJSON *jsonRoot = NULL;\r
+    cJSON *jsonPconf = NULL;\r
+    cJSON *jsonObj = NULL;\r
+    size_t jsonObjLen = 0;\r
+\r
+    unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};\r
+    uint32_t outLen = 0;\r
+    B64Result b64Ret = B64_OK;\r
+\r
+\r
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);\r
+\r
+    jsonRoot = cJSON_Parse(jsonStr);\r
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);\r
+\r
+    jsonPconf = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PCONF_NAME);\r
+    VERIFY_NON_NULL(TAG, jsonPconf, ERROR);\r
+\r
+    pconf = (OicSecPconf_t*)OICCalloc(1, sizeof(OicSecPconf_t));\r
+    VERIFY_NON_NULL(TAG, pconf, ERROR);\r
+\r
+    //EDP -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_EDP_NAME);\r
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);\r
+    VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type) , ERROR);\r
+    pconf->edp = jsonObj->valueint;\r
+\r
+    //PRM type -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_PRM_NAME);\r
+    if (jsonObj && cJSON_Array == jsonObj->type)\r
+    {\r
+        int arrLen = cJSON_GetArraySize(jsonObj);\r
+        if(0 < arrLen)\r
+        {\r
+            pconf->prmLen = (size_t)arrLen;\r
+            pconf->prm = (OicSecPrm_t *)OICCalloc(pconf->prmLen, sizeof(OicSecPrm_t));\r
+            VERIFY_NON_NULL(TAG, pconf->prm, ERROR);\r
+\r
+            for (size_t i  = 0; i < pconf->prmLen ; i++)\r
+            {\r
+                cJSON *jsonPrm = cJSON_GetArrayItem(jsonObj, i);\r
+                VERIFY_NON_NULL(TAG, jsonPrm, ERROR);\r
+                pconf->prm[i] = (OicSecPrm_t)jsonPrm->valueint;\r
+                OIC_LOG_V (DEBUG, TAG, "jsonPrm->valueint = %d", jsonPrm->valueint);\r
+                OIC_LOG_V (DEBUG, TAG, "pconf->prm[%d] = %d", (int)i, pconf->prm[i]);\r
+            }\r
+        }\r
+    }\r
+\r
+    //PIN -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_PIN_NAME);\r
+    if (jsonObj)\r
+    {\r
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);\r
+        VERIFY_SUCCESS(TAG, DP_PIN_LENGTH == strlen(jsonObj->valuestring), ERROR);\r
+        OICStrcpy((char*)pconf->pin.val, DP_PIN_LENGTH + 1, (char*)jsonObj->valuestring);\r
+    }\r
+    else\r
+    {\r
+        memset(pconf->pin.val, 0, DP_PIN_LENGTH+1);\r
+    }\r
+\r
+    //PDACL -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_PDACL_NAME);\r
+    if (jsonObj)\r
+    {\r
+        VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);\r
+\r
+        OicSecPdAcl_t * headAcl = NULL;\r
+        OicSecPdAcl_t * prevAcl = NULL;\r
+        int numPdAcl = cJSON_GetArraySize(jsonObj);\r
+        int idx = 0;\r
+\r
+        while(idx < numPdAcl)\r
+        {\r
+            cJSON *jsonPdAcl = cJSON_GetArrayItem(jsonObj, idx);\r
+            VERIFY_NON_NULL(TAG, jsonPdAcl, ERROR);\r
+\r
+            OicSecPdAcl_t *pdacl = (OicSecPdAcl_t*)OICCalloc(1, sizeof(OicSecPdAcl_t));\r
+            VERIFY_NON_NULL(TAG, pdacl, ERROR);\r
+\r
+            headAcl = (headAcl) ? headAcl : pdacl;\r
+            if (prevAcl)\r
+            {\r
+                prevAcl->next = pdacl;\r
+            }\r
+\r
+            cJSON *jsonAclObj = NULL;\r
+\r
+            // Resources -- Mandatory\r
+            jsonAclObj = cJSON_GetObjectItem(jsonPdAcl, OIC_JSON_RESOURCES_NAME);\r
+            VERIFY_NON_NULL(TAG, jsonAclObj, ERROR);\r
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonAclObj->type, ERROR);\r
+\r
+            pdacl->resourcesLen = (size_t)cJSON_GetArraySize(jsonAclObj);\r
+            VERIFY_SUCCESS(TAG, pdacl->resourcesLen > 0, ERROR);\r
+            pdacl->resources = (char**)OICCalloc(pdacl->resourcesLen, sizeof(char*));\r
+            VERIFY_NON_NULL(TAG, (pdacl->resources), ERROR);\r
+\r
+            size_t idxx = 0;\r
+            do\r
+            {\r
+                cJSON *jsonRsrc = cJSON_GetArrayItem(jsonAclObj, idxx);\r
+                VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);\r
+\r
+                jsonObjLen = strlen(jsonRsrc->valuestring) + 1;\r
+                pdacl->resources[idxx] = (char*)OICMalloc(jsonObjLen);\r
+                VERIFY_NON_NULL(TAG, (pdacl->resources[idxx]), ERROR);\r
+                OICStrcpy(pdacl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);\r
+            } while ( ++idxx < pdacl->resourcesLen);\r
+\r
+            // Permissions -- Mandatory\r
+            jsonAclObj = cJSON_GetObjectItem(jsonPdAcl,\r
+                                OIC_JSON_PERMISSION_NAME);\r
+            VERIFY_NON_NULL(TAG, jsonAclObj, ERROR);\r
+            VERIFY_SUCCESS(TAG, cJSON_Number == jsonAclObj->type, ERROR);\r
+            pdacl->permission = jsonAclObj->valueint;\r
+\r
+            //Period -- Not Mandatory\r
+            cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonPdAcl,\r
+                    OIC_JSON_PERIODS_NAME);\r
+            if(jsonPeriodObj)\r
+            {\r
+                VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,\r
+                               ERROR);\r
+                pdacl->prdRecrLen = (size_t)cJSON_GetArraySize(jsonPeriodObj);\r
+                if(pdacl->prdRecrLen > 0)\r
+                {\r
+                    pdacl->periods = (char**)OICCalloc(pdacl->prdRecrLen,\r
+                                    sizeof(char*));\r
+                    VERIFY_NON_NULL(TAG, pdacl->periods, ERROR);\r
+\r
+                    cJSON *jsonPeriod = NULL;\r
+                    for(size_t i = 0; i < pdacl->prdRecrLen; i++)\r
+                    {\r
+                        jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);\r
+                        VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);\r
+\r
+                        jsonObjLen = strlen(jsonPeriod->valuestring) + 1;\r
+                        pdacl->periods[i] = (char*)OICMalloc(jsonObjLen);\r
+                        VERIFY_NON_NULL(TAG, pdacl->periods[i], ERROR);\r
+                        OICStrcpy(pdacl->periods[i], jsonObjLen,\r
+                                  jsonPeriod->valuestring);\r
+                    }\r
+                }\r
+            }\r
+\r
+            //Recurrence -- Not mandatory\r
+            cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonPdAcl,\r
+                                        OIC_JSON_RECURRENCES_NAME);\r
+            if(jsonRecurObj)\r
+            {\r
+                VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,\r
+                               ERROR);\r
+\r
+                if(pdacl->prdRecrLen > 0)\r
+                {\r
+                    pdacl->recurrences = (char**)OICCalloc(pdacl->prdRecrLen,\r
+                                             sizeof(char*));\r
+                    VERIFY_NON_NULL(TAG, pdacl->recurrences, ERROR);\r
+\r
+                    cJSON *jsonRecur = NULL;\r
+                    for(size_t i = 0; i < pdacl->prdRecrLen; i++)\r
+                    {\r
+                        jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);\r
+                        VERIFY_NON_NULL(TAG, jsonRecur, ERROR);\r
+                        jsonObjLen = strlen(jsonRecur->valuestring) + 1;\r
+                        pdacl->recurrences[i] = (char*)OICMalloc(jsonObjLen);\r
+                        VERIFY_NON_NULL(TAG, pdacl->recurrences[i], ERROR);\r
+                        OICStrcpy(pdacl->recurrences[i], jsonObjLen,\r
+                              jsonRecur->valuestring);\r
+                    }\r
+                }\r
+            }\r
+\r
+            prevAcl = pdacl;\r
+            idx++;\r
+        }\r
+\r
+        pconf->pdacls = headAcl;\r
+    }\r
+    else\r
+    {\r
+        pconf->pdacls = NULL;\r
+    }\r
+\r
+    //PDDev -- Mandatory\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_PDDEV_LIST_NAME);\r
+    if (jsonObj && cJSON_Array == jsonObj->type)\r
+    {\r
+        pconf->pddevLen = (size_t)cJSON_GetArraySize(jsonObj);\r
+        if(0 < pconf->pddevLen)\r
+        {\r
+            pconf->pddevs = (OicUuid_t *)OICCalloc(pconf->pddevLen, sizeof(OicUuid_t));\r
+            VERIFY_NON_NULL(TAG, pconf->pddevs, ERROR);\r
+\r
+            for (size_t i  = 0; i < pconf->pddevLen ; i++)\r
+            {\r
+                cJSON *jsonPdDev = cJSON_GetArrayItem(jsonObj, i);\r
+                VERIFY_NON_NULL(TAG, jsonPdDev, ERROR);\r
+\r
+                outLen = 0;\r
+                b64Ret = b64Decode(jsonPdDev->valuestring, strlen(jsonPdDev->valuestring), base64Buff,\r
+                        sizeof(base64Buff), &outLen);\r
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pconf->pddevs[i].id)), ERROR);\r
+                memcpy(pconf->pddevs[i].id, base64Buff, outLen);\r
+            }\r
+        }\r
+    }\r
+    else\r
+    {\r
+        pconf->pddevs = NULL;\r
+        pconf->pddevLen = 0;\r
+    }\r
+\r
+    //DeviceId -- Mandatory\r
+    outLen = 0;\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_DEVICE_ID_NAME);\r
+    if (jsonObj && cJSON_String == jsonObj->type)\r
+    {\r
+        b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
+                sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pconf->deviceID.id)), ERROR);\r
+        memcpy(pconf->deviceID.id, base64Buff, outLen);\r
+    }\r
+    else\r
+    {\r
+        OicUuid_t deviceId = {.id = {0}};\r
+        OCStackResult ret = GetDoxmDeviceID( &deviceId);\r
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);\r
+        memcpy(&pconf->deviceID, &deviceId, sizeof(OicUuid_t));\r
+    }\r
+\r
+    // ROwner -- Mandatory\r
+    outLen = 0;\r
+    jsonObj = cJSON_GetObjectItem(jsonPconf, OIC_JSON_ROWNER_NAME);\r
+    if (jsonObj && cJSON_String == jsonObj->type)\r
+    {\r
+        b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,\r
+                sizeof(base64Buff), &outLen);\r
+        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pconf->rowner.id)), ERROR);\r
+        memcpy(pconf->rowner.id, base64Buff, outLen);\r
+    }\r
+    else\r
+    {\r
+        memset(&pconf->rowner, 0, sizeof(OicUuid_t));\r
+    }\r
+\r
+    ret = OC_STACK_OK;\r
+\r
+exit:\r
+    cJSON_Delete(jsonRoot);\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        DeletePconfBinData(pconf);\r
+        pconf = NULL;\r
+    }\r
+\r
+    OIC_LOG(DEBUG, TAG, "JSONToPconfBin() OUT");\r
+    return pconf;\r
+}\r
+\r
+static bool UpdatePersistentStorage(const OicSecPconf_t * pconf)\r
+{\r
+    bool ret = false;\r
+\r
+    // Convert PCONF data into JSON for update to persistent storage\r
+    char *jsonStr = BinToPconfJSON(pconf);\r
+    if (jsonStr)\r
+    {\r
+        cJSON *jsonPconf = cJSON_Parse(jsonStr);\r
+        OICFree(jsonStr);\r
+\r
+        if ((jsonPconf) &&\r
+                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PCONF_NAME, jsonPconf)))\r
+        {\r
+            ret = true;\r
+        }\r
+        cJSON_Delete(jsonPconf);\r
+    }\r
+    return ret;\r
+}\r
+\r
+static OCEntityHandlerResult HandlePconfGetRequest (const OCEntityHandlerRequest * ehRequest)\r
+{\r
+    char* jsonStr = NULL;\r
+    OCEntityHandlerResult ehRet = OC_EH_OK;\r
+\r
+    OicSecPconf_t pconf;\r
+    memset(&pconf, 0, sizeof(OicSecPconf_t));\r
+\r
+    OIC_LOG (DEBUG, TAG, "Pconf EntityHandle processing GET request");\r
+\r
+    if (true == GetDoxmResourceData()->dpc)\r
+    {\r
+        //Making response elements for Get request\r
+        if( (true == gPconf->edp) && (gPconf->prm && 0 < gPconf->prmLen) &&\r
+            (0 < strlen((const char*)gPconf->deviceID.id)) && (0 < strlen((const char*)gPconf->rowner.id)))\r
+        {\r
+            pconf.edp = true;\r
+            pconf.prm = gPconf->prm;\r
+            pconf.prmLen = gPconf->prmLen;\r
+            memcpy(&pconf.deviceID, &gPconf->deviceID, sizeof(OicUuid_t));\r
+            memcpy(&pconf.rowner, &gPconf->rowner, sizeof(OicUuid_t));\r
+            OIC_LOG (DEBUG, TAG, "PCONF - direct pairing enabled");\r
+        }\r
+        else if (false == gPconf->edp)\r
+        {\r
+            pconf.edp = false;\r
+            memcpy(&pconf.rowner, &gPconf->rowner, sizeof(OicUuid_t));\r
+            OIC_LOG (DEBUG, TAG, "PCONF - direct pairing disable");\r
+        }\r
+        else\r
+        {\r
+            ehRet= OC_EH_ERROR;\r
+            OIC_LOG (DEBUG, TAG, "PCONF - error");\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");\r
+        ehRet = OC_EH_ERROR;\r
+    }\r
+\r
+    jsonStr = (ehRet == OC_EH_OK) ? BinToPconfJSON(&pconf) : NULL;\r
+\r
+    // Send response payload to request originator\r
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, jsonStr))\r
+    {\r
+        OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDpairingGetRequest");\r
+    }\r
+\r
+    OICFree(jsonStr);\r
+\r
+    return ehRet;\r
+}\r
+\r
+static OCEntityHandlerResult HandlePconfPostRequest (const OCEntityHandlerRequest * ehRequest)\r
+{\r
+    OCEntityHandlerResult ehRet = OC_EH_OK;\r
+    OicSecPconf_t* newPconf = NULL;\r
+\r
+    if (true == GetDoxmResourceData()->dpc)\r
+    {\r
+        // Convert JSON PCONF data into binary. This will also validate the PCONF data received.\r
+        newPconf = JSONToPconfBin(((OCSecurityPayload*)ehRequest->payload)->securityData);\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "DPC == false : Direct-Pairing Disabled");\r
+        ehRet = OC_EH_ERROR;\r
+    }\r
+\r
+    if (newPconf)\r
+    {\r
+        // Check if valid Post request\r
+        if ((true == newPconf->edp) && (0 < newPconf->prmLen) &&\r
+                DP_PIN_LENGTH == strlen((const char*)newPconf->pin.val))\r
+        {\r
+            OicSecPrm_t *oldPrm = gPconf->prm;\r
+            OicSecPdAcl_t *oldPdacl = gPconf->pdacls;\r
+\r
+            // Update local PCONF with new PCONF\r
+            gPconf->edp = true;\r
+            memcpy(&gPconf->pin, &newPconf->pin, sizeof(OicDpPin_t));\r
+            gPconf->prm = newPconf->prm;\r
+            gPconf->prmLen = newPconf->prmLen;\r
+            gPconf->pdacls = newPconf->pdacls;\r
+            memcpy(&gPconf->rowner, &newPconf->rowner, sizeof(OicUuid_t));\r
+\r
+            // to delete old value(prm, pdacl)\r
+            newPconf->prm = oldPrm;\r
+            newPconf->pdacls = oldPdacl;\r
+        }\r
+        else if (false == newPconf->edp)\r
+        {\r
+            gPconf->edp = false;\r
+        }\r
+        else\r
+        {\r
+            ehRet = OC_EH_ERROR;\r
+        }\r
+\r
+        // Update storage\r
+        if(OC_EH_ERROR != ehRet && true == UpdatePersistentStorage(gPconf))\r
+        {\r
+            ehRet = OC_EH_RESOURCE_CREATED;\r
+        }\r
+\r
+        DeletePconfBinData(newPconf);\r
+    }\r
+    else\r
+    {\r
+        ehRet = OC_EH_ERROR;\r
+    }\r
+\r
+    // Send payload to request originator\r
+    SendSRMResponse(ehRequest, ehRet, NULL);\r
+\r
+    OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);\r
+    return ehRet;\r
+}\r
+\r
+/*\r
+ * This internal method is the entity handler for PCONF resources and\r
+ * will handle REST request (POST) for them.\r
+ */\r
+OCEntityHandlerResult PconfEntityHandler (OCEntityHandlerFlag flag,\r
+                                        OCEntityHandlerRequest * ehRequest,\r
+                                        void* callbackParameter)\r
+{\r
+    OIC_LOG(DEBUG, TAG, "Received request PconfEntityHandler");\r
+    (void)callbackParameter;\r
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;\r
+\r
+    if (!ehRequest)\r
+    {\r
+        return ehRet;\r
+    }\r
+\r
+    if (flag & OC_REQUEST_FLAG)\r
+    {\r
+        OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");\r
+        switch (ehRequest->method)\r
+        {\r
+            case OC_REST_GET:\r
+                ehRet = HandlePconfGetRequest(ehRequest);\r
+                break;\r
+\r
+            case OC_REST_POST:\r
+                ehRet = HandlePconfPostRequest(ehRequest);\r
+                break;\r
+\r
+            case OC_REST_DELETE:\r
+                break;\r
+\r
+            default:\r
+                ehRet = OC_EH_ERROR;\r
+                SendSRMResponse(ehRequest, ehRet, NULL);\r
+        }\r
+    }\r
+\r
+    return ehRet;\r
+}\r
+\r
+/*\r
+ * This internal method is used to create '/oic/sec/pconf' resource.\r
+ */\r
+OCStackResult CreatePconfResource()\r
+{\r
+    OCStackResult ret;\r
+\r
+    ret = OCCreateResource(&gPconfHandle,\r
+                           OIC_RSRC_TYPE_SEC_PCONF,\r
+                           OIC_MI_DEF,\r
+                           OIC_RSRC_PCONF_URI,\r
+                           PconfEntityHandler,\r
+                           NULL,\r
+                           OC_SECURE | OC_EXPLICIT_DISCOVERABLE);\r
+\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        OIC_LOG (ERROR, TAG, "Unable to instantiate PCONF resource");\r
+        DeInitPconfResource();\r
+    }\r
+    return ret;\r
+}\r
+\r
+/**\r
+ * Get the default value.\r
+ * @retval  the gDefaultPconf pointer;\r
+ */\r
+static OicSecPconf_t* GetPconfDefault()\r
+{\r
+    OIC_LOG (DEBUG, TAG, "GetPconfDefault");\r
+\r
+    return &gDefaultPconf;\r
+}\r
+\r
+/**\r
+ * This method is used by SRM to retrieve PCONF resource data..\r
+ *\r
+ * @retval  reference to @ref OicSecPconf_t, binary format of Pconf resource data\r
+ */\r
+const OicSecPconf_t* GetPconfResourceData()\r
+{\r
+    return gPconf;\r
+}\r
+\r
+/**\r
+ * Initialize PCONF resource by loading data from persistent storage.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult InitPconfResource()\r
+{\r
+    OCStackResult ret = OC_STACK_ERROR;\r
+\r
+    // Read PCONF resource from PS\r
+    char* jsonSVRDatabase = GetSVRDatabase();\r
+\r
+    if (jsonSVRDatabase)\r
+    {\r
+        // Convert JSON PCONF into binary format\r
+        gPconf = JSONToPconfBin(jsonSVRDatabase);\r
+    }\r
+\r
+    if(!jsonSVRDatabase || !gPconf)\r
+    {\r
+        gPconf = GetPconfDefault();\r
+\r
+        // device id from doxm\r
+        OicUuid_t deviceId = {.id = {0}};\r
+        OCStackResult ret = GetDoxmDeviceID( &deviceId);\r
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);\r
+        memcpy(&gPconf->deviceID, &deviceId, sizeof(OicUuid_t));\r
+    }\r
+    VERIFY_NON_NULL(TAG, gPconf, ERROR);\r
+\r
+    // Instantiate 'oic.sec.pconf'\r
+    ret = CreatePconfResource();\r
+\r
+exit:\r
+    if (OC_STACK_OK != ret)\r
+    {\r
+        DeInitPconfResource();\r
+    }\r
+    OICFree(jsonSVRDatabase);\r
+    return ret;\r
+}\r
+\r
+/**\r
+ * Perform cleanup for PCONF resources.\r
+ *\r
+ * @return\r
+ * OC_STACK_OK    - no error\r
+ * OC_STACK_ERROR - stack process error\r
+ *\r
+ */\r
+OCStackResult DeInitPconfResource()\r
+{\r
+    OCStackResult ret = OCDeleteResource(gPconfHandle);\r
+    if(gPconf!= &gDefaultPconf)\r
+    {\r
+        DeletePconfBinData(gPconf);\r
+    }\r
+    gPconf = NULL;\r
+\r
+    if(OC_STACK_OK == ret)\r
+    {\r
+        return OC_STACK_OK;\r
+    }\r
+    else\r
+    {\r
+        return OC_STACK_ERROR;\r
+    }\r
+}\r
+\r
+/**\r
+ * This method might be used to add a paired device id after direct-pairing process complete.\r
+ *\r
+ * @param pdeviceId ID of the paired device.\r
+ *\r
+ * @retval  OC_STACK_OK for Success, otherwise some error value\r
+ */\r
+OCStackResult AddPairedDevice(OicUuid_t *pdeviceId)\r
+{\r
+    if (!gPconf || !pdeviceId)\r
+    {\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+\r
+    OicUuid_t *prevList = gPconf->pddevs;\r
+    gPconf->pddevs = (OicUuid_t *)OICCalloc(gPconf->pddevLen+1, sizeof(OicUuid_t));\r
+    if(!gPconf->pddevs)\r
+    {\r
+        return OC_STACK_NO_MEMORY;\r
+    }\r
+    for (size_t i=0; i<gPconf->pddevLen; i++)\r
+    {\r
+        memcpy(&gPconf->pddevs[i], &prevList[i], sizeof(OicUuid_t));\r
+    }\r
+\r
+    // add new paired device id\r
+    memcpy(&gPconf->pddevs[gPconf->pddevLen], pdeviceId, sizeof(OicUuid_t));\r
+    gPconf->pddevLen++;\r
+\r
+    // Update storage\r
+    if(true != UpdatePersistentStorage(gPconf))\r
+    {\r
+        OIC_LOG (ERROR, TAG, "Fail to update pconf resource");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    OIC_LOG (ERROR, TAG, "Add paired device success");\r
+    return OC_STACK_OK;\r
+}\r
+\r
+/**\r
+ * This method might be used by PolicyEngine to retrieve PDACL for a Subject.\r
+ *\r
+ * @param subjectId ID of the subject for which PDACL is required.\r
+ * @param savePtr is used internally by @ref GetACLResourceData to maintain index between\r
+ *                successive calls for same subjectId.\r
+ *\r
+ * @retval  reference to @ref OicSecPdAcl_t if PDACL is found, else NULL\r
+ */\r
+const OicSecPdAcl_t* GetPdAclData(const OicUuid_t* subjectId, OicSecPdAcl_t **savePtr)\r
+{\r
+    OicSecPdAcl_t *pdacl = NULL;\r
+\r
+    if ( NULL == subjectId)\r
+    {\r
+        return NULL;\r
+    }\r
+\r
+    /*\r
+     * savePtr MUST point to NULL if this is the 'first' call to retrieve PDACL for\r
+     * subjectID.\r
+     */\r
+    if (NULL == *savePtr)\r
+    {\r
+        pdacl = gPconf->pdacls;\r
+\r
+        // Find if 'subjectID' is in paired device list.\r
+        for(size_t i=0; i<gPconf->pddevLen; i++)\r
+        {\r
+            if (memcmp(&(gPconf->pddevs[i]), subjectId, sizeof(OicUuid_t)) == 0)\r
+            {\r
+                *savePtr = pdacl;\r
+                return pdacl;\r
+            }\r
+        }\r
+    }\r
+    else\r
+    {\r
+        OicSecPdAcl_t *temp = NULL;\r
+\r
+        /*\r
+         * If this is a 'successive' call, search for location pointed by\r
+         * savePtr and assign 'begin' to the next PDACL after it in the linked\r
+         * list and start searching from there.\r
+         */\r
+        LL_FOREACH(gPconf->pdacls, temp)\r
+        {\r
+            if (temp == *savePtr)\r
+            {\r
+                pdacl = temp->next;\r
+                *savePtr = pdacl;\r
+                return pdacl;\r
+            }\r
+        }\r
+    }\r
+\r
+    // Cleanup in case no PDACL is found\r
+    *savePtr = NULL;\r
+    return NULL;\r
+}\r
+\r
+/**\r
+ * This method return whether device is paired or not.\r
+ *\r
+ * @param pdeviceId Target device ID to find in paired list.\r
+ * @retval  ture if device is already paired, else false\r
+ */\r
+bool IsPairedDevice(const OicUuid_t* pdeviceId)\r
+{\r
+    // Find if 'pdeviceId' is in paired device list.\r
+    for(size_t i=0; i<gPconf->pddevLen; i++)\r
+    {\r
+        if (memcmp(&(gPconf->pddevs[i]), pdeviceId, sizeof(OicUuid_t)) == 0)\r
+        {\r
+            return true;\r
+        }\r
+    }\r
+    return false;\r
+}\r
+\r
+\r
index 7c7cf18..719d51b 100644 (file)
@@ -159,8 +159,10 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
          ACL, PStat & Doxm resources at least have default entries in the database but
          Cred resource may have no entries. The first cred resource entry (for provisioning tool)
          is created when the device is owned by provisioning tool and it's ownerpsk is generated.*/
-        if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0 || strcmp(rsrcName, OIC_JSON_CRL_NAME) == 0)
-                                                                                    && (!jsonObj))
+        if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0 ||
+                strcmp(rsrcName, OIC_JSON_CRL_NAME) == 0 ||
+                strcmp(rsrcName, OIC_JSON_PCONF_NAME) == 0 ||
+                strcmp(rsrcName, OIC_JSON_DPAIRING_NAME) == 0) && (!jsonObj))
         {
             // Add the fist cred object in existing SVR database json
             cJSON_AddItemToObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
index fe097e6..339ea48 100644 (file)
 #include "utlist.h"
 #include <string.h>
 
+//#ifdef DIRECT_PAIRING
+#include "pconfresource.h"
+#include "dpairingresource.h"
+//#endif // DIRECT_PAIRING
+
 #define TAG "SRM-RM"
 
 #ifdef __WITH_X509__
@@ -106,11 +111,21 @@ OCStackResult InitSecureResources( )
     if(OC_STACK_OK == ret)
     {
         ret = InitSVCResource();
-       }
-       if(OC_STACK_OK == ret)
+    }
+    if(OC_STACK_OK == ret)
     {
         ret = InitAmaclResource();
     }
+//#ifdef DIRECT_PAIRING
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitPconfResource();
+    }
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitDpairingResource();
+    }
+//#endif // DIRECT_PAIRING
     if(OC_STACK_OK != ret)
     {
         //TODO: Update the default behavior if one of the SVR fails
@@ -135,6 +150,10 @@ OCStackResult DestroySecureResources( )
 #endif // __WITH_X509__
     DeInitSVCResource();
     DeInitAmaclResource();
+//#ifdef DIRECT_PAIRING
+    DeInitPconfResource();
+    DeInitDpairingResource();
+//#endif // DIRECT_PAIRING
 
     return OC_STACK_OK;
 }
index e2bec48..02fe6ed 100644 (file)
@@ -402,6 +402,8 @@ bool SRMIsSecurityResourceURI(const char* uri)
         OIC_RSRC_ACL_URI,
         OIC_RSRC_DOXM_URI,
         OIC_RSRC_PSTAT_URI,
+        OIC_RSRC_PCONF_URI,
+        OIC_RSRC_DPAIRING_URI,
     };
 
     // Remove query from Uri for resource string comparison
index be72bf3..34e92aa 100644 (file)
@@ -58,6 +58,16 @@ const char * OIC_RSRC_TYPE_SEC_SVC = "oic.sec.svc";
 const char * OIC_RSRC_SVC_URI =  "/oic/sec/svc";
 const char * OIC_JSON_SVC_NAME = "svc";
 
+//pconf
+const char * OIC_RSRC_TYPE_SEC_PCONF = "oic.sec.pconf";
+const char * OIC_RSRC_PCONF_URI =  "/oic/sec/pconf";
+const char * OIC_JSON_PCONF_NAME = "pconf";
+
+//dpairing
+const char * OIC_RSRC_TYPE_SEC_DPAIRING = "oic.sec.dpairing";
+const char * OIC_RSRC_DPAIRING_URI =  "/oic/sec/dpairing";
+const char * OIC_JSON_DPAIRING_NAME = "dpairing";
+
 
 const char * OIC_JSON_SUBJECT_NAME = "sub";
 const char * OIC_JSON_RESOURCES_NAME = "rsrc";
@@ -89,6 +99,15 @@ const char * OIC_JSON_PERIOD_NAME = "prd";
 const char * OIC_JSON_PERIODS_NAME = "prds";
 const char * OIC_JSON_RECURRENCES_NAME = "recurs";
 const char * OIC_JSON_SUPPORTED_CRED_TYPE_NAME = "sct";
+const char * OIC_JSON_DPC_NAME = "dpc";
+const char * OIC_JSON_EDP_NAME = "edp";
+const char * OIC_JSON_PIN_NAME = "pin";
+const char * OIC_JSON_PDACL_NAME = "pdacl";
+const char * OIC_JSON_PDDEV_LIST_NAME = "pddev";
+const char * OIC_JSON_ROWNER_NAME = "rowner";
+const char * OIC_JSON_PRM_NAME = "prm";
+const char * OIC_JSON_SPM_NAME = "spm";
+const char * OIC_JSON_PDEVICE_ID_NAME = "pdeviceid";
 
 OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
 size_t WILDCARD_SUBJECT_ID_LEN = 1;
index d03d5f9..9eeae7e 100644 (file)
@@ -516,6 +516,41 @@ OCNotifyListOfObservers (OCResourceHandle handle,
  */
 OCStackResult OCDoResponse(OCEntityHandlerResponse *response);
 
+//#ifdef DIRECT_PAIRING
+/**
+ * The function is responsible for discovery of direct-pairing device is current subnet. It will list
+ * all the device in subnet which support direct-pairing.
+ * Caller must NOT free returned constant pointer
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ *                    client before returning the list of devices.
+ * @return OCDirectPairingDev_t pointer in case of success and NULL otherwise.
+ */
+const OCDPDev_t* OCDiscoverDirectPairingDevices(unsigned short waittime);
+
+/**
+ * The function is responsible for return of paired device list via direct-pairing. It will list
+ * all the device which is previousely paired with client.
+ * Caller must NOT free returned constant pointer
+ *
+ * @return OCDirectPairingDev_t pointer in case of success and NULL otherwise.
+ */
+const OCDPDev_t* OCGetDirectPairedDevices();
+
+/**
+ * The function is responsible for establishment of direct-pairing. It will proceed mode negotiation
+ * and connect PIN based dtls session.
+ *
+ * @param[in] peer Target device to establish direct-pairing.
+ * @param[in] pmSel Selected mode of pairing.
+ * @param[in] pinNumber PIN number for authentication, pin lenght is defined DP_PIN_LENGTH(8).
+ * @param[in] resultCallback Callback fucntion to event status of process.
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDoDirectPairing(OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber,
+                                                     OCDirectPairingCB resultCallback);
+//#endif // DIRECT_PAIRING
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 3159bd8..919900f 100644 (file)
@@ -284,6 +284,9 @@ extern "C" {
 /** Max identity size. */
 #define MAX_IDENTITY_SIZE (32)
 
+/** Universal unique identity size. */
+#define UUID_IDENTITY_SIZE (128/8)
+
 /** Resource Directory */
 
 /** Resource Directory URI used to Discover RD and Publish resources.*/
@@ -419,6 +422,15 @@ typedef struct
 } OCIdentity;
 
 /**
+ * Universally unique identifier.
+ */
+typedef struct
+{
+    /** identitifier string.*/
+    unsigned char id[UUID_IDENTITY_SIZE];
+} OCUUIdentity;
+
+/**
  * Data structure to encapsulate IPv4/IPv6/Contiki/lwIP device addresses.
  * OCDevAddr must be the same as CAEndpoint (in CACommon.h).
  */
@@ -1321,6 +1333,37 @@ typedef enum
 } OCStackApplicationResult;
 
 
+//#ifdef DIRECT_PAIRING
+/**
+ * @brief   direct pairing Method Type.
+ *              0:  not allowed
+ *              1:  pre-configured pin
+ *              2:  random pin
+ */
+typedef enum OCPrm
+{
+    DP_NOT_ALLOWED             = 0x0,
+    DP_PRE_CONFIGURED        = (0x1 << 0),
+    DP_RANDOM_PIN               = (0x1 << 1),
+} OCPrm_t;
+
+/**
+ * Device Information of discoverd direct pairing device(s).
+ */
+typedef struct OCDPDev
+{
+    OCDevAddr               endpoint;
+    OCConnectivityType   connType;
+    uint16_t                     securePort;
+    bool                  edp;
+    OCPrm_t           *prm;
+    size_t                prmLen;
+    OCUUIdentity     deviceID;
+    OCUUIdentity     rowner;
+    struct OCDPDev *next;
+} OCDPDev_t;
+//#endif // DIRECT_PAIRING
+
 /*
  * -------------------------------------------------------------------------------------------
  * Callback function definitions
@@ -1373,6 +1416,17 @@ typedef OCEntityHandlerResult (*OCEntityHandler)
 typedef OCEntityHandlerResult (*OCDeviceEntityHandler)
 (OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest, char* uri, void* callbackParam);
 
+//#ifdef DIRECT_PAIRING
+/**
+ * Callback function definition of direct-pairing
+ *
+ * @param[OUT] peer - pairing device info.
+ * @param[OUT} result - It's returned with 'OC_STACK_XXX'. It will return 'OC_STACK_OK' 
+ *                                   if D2D pairing is success without error
+ */
+typedef void (*OCDirectPairingCB)(OCDPDev_t *peer, OCStackResult result);
+//#endif // DIRECT_PAIRING
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index db10b49..53be70f 100644 (file)
@@ -67,8 +67,11 @@ samples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 ocserverbasicops = samples_env.Program('ocserverbasicops', ['common.cpp', 'ocserverbasicops.cpp'])
 occlientbasicops = samples_env.Program('occlientbasicops', ['common.cpp', 'occlientbasicops.cpp'])
 ocamsservice = samples_env.Program('ocamsservice', ['common.cpp', 'ocamsservice.cpp'])
-
-Alias("samples", [ocserverbasicops, occlientbasicops, ocamsservice])
+if env.get('SECURED') == '1':
+       occlientdirectpairing = samples_env.Program('occlientdirectpairing', 'occlientdirectpairing.cpp')
+       Alias("samples", [ocserverbasicops, occlientbasicops, ocamsservice, occlientdirectpairing])
+else:
+       Alias("samples", [ocserverbasicops, occlientbasicops, ocamsservice])
 
 env.AppendTarget('samples')
 
@@ -82,4 +85,7 @@ samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_svr_db_client.json'))
 samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
     sec_samples_src_dir + 'oic_amss_db.json'))
+if env.get('SECURED') == '1':
+       samples_env.Alias("install", samples_env.Install( sec_samples_build_dir,
+               sec_samples_src_dir + 'oic_svr_db_client_directpairing.json'))
 
diff --git a/resource/csdk/stack/samples/linux/secure/occlientdirectpairing.cpp b/resource/csdk/stack/samples/linux/secure/occlientdirectpairing.cpp
new file mode 100644 (file)
index 0000000..827342f
--- /dev/null
@@ -0,0 +1,641 @@
+//******************************************************************\r
+//\r
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+//      http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <signal.h>\r
+#include <unistd.h>\r
+#include <pthread.h>\r
+#include <iostream>\r
+#include <sstream>\r
+#include "ocstack.h"\r
+#include "logger.h"\r
+#include "ocpayload.h"\r
+#include "payload_logging.h"\r
+#include "oic_malloc.h"\r
+#include "oic_string.h"\r
+#include "utlist.h"\r
+\r
+#define TAG "occlient-directpairing"\r
+\r
+#define BOLD_BEGIN    "\033[1m"\r
+#define RED_BEGIN      "\033[1;31m"\r
+#define GREEN_BEGIN  "\033[1;92m"\r
+#define COLOR_END      "\033[0m"\r
+#define MAX_LINE (1024)\r
+#define DP_DISCOVERY_TIMEOUT   3  // 3 sec\r
+#define DP_PIN_LENGTH 8 // 8 digit\r
+\r
+static char DISCOVERY_QUERY[] = "%s/oic/res";\r
+\r
+//Secure Virtual Resource database for Iotivity Client application\r
+//It contains Client's Identity and the PSK credentials\r
+//of other devices which the client trusts\r
+static char CRED_FILE[] = "oic_svr_db_client_directpairing.json";\r
+\r
+static const OCDPDev_t *discoveredDevs = NULL;\r
+static const OCDPDev_t *pairedDevs = NULL;\r
+\r
+int gQuitFlag = 0;\r
+\r
+//-----------------------------------------------------------------------------\r
+// Function prototype\r
+//-----------------------------------------------------------------------------\r
+\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Function body\r
+//-----------------------------------------------------------------------------\r
+\r
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */\r
+void handleSigInt(int signum)\r
+{\r
+    if (signum == SIGINT)\r
+    {\r
+        gQuitFlag = 1;\r
+    }\r
+}\r
+\r
+const char *readline(const char *in, const char *defaultStr)\r
+{\r
+    static char rbuffer[MAX_LINE] = {0,};\r
+    char *cptr, *p;\r
+\r
+    size_t in_len = strlen(in);\r
+    for (size_t i=0; i<in_len; i++)\r
+    {\r
+        fprintf(stdout, "%c", in[i]);\r
+    }\r
+\r
+    if (NULL != (cptr = fgets(rbuffer, MAX_LINE, stdin)))\r
+    {\r
+        /* kill preceding whitespace but leave \n so we're guaranteed to have something */\r
+        /*while(*cptr == ' ' || *cptr == '\t')\r
+        {\r
+            cptr++;\r
+        }*/\r
+\r
+        if ( (p = strchr(cptr, '\n')) != NULL )\r
+        {\r
+            *p = '\0';\r
+        }\r
+\r
+        if (strlen(cptr)==0 && defaultStr)\r
+        {\r
+            return defaultStr;\r
+        }\r
+        return cptr;\r
+    }\r
+    else\r
+    {\r
+        return 0;\r
+    }\r
+}\r
+\r
+const char *getResult(OCStackResult result) {\r
+    switch (result) {\r
+    case OC_STACK_OK:\r
+        return "OC_STACK_OK";\r
+    case OC_STACK_RESOURCE_CREATED:\r
+        return "OC_STACK_RESOURCE_CREATED";\r
+    case OC_STACK_RESOURCE_DELETED:\r
+        return "OC_STACK_RESOURCE_DELETED";\r
+    case OC_STACK_INVALID_URI:\r
+        return "OC_STACK_INVALID_URI";\r
+    case OC_STACK_INVALID_QUERY:\r
+        return "OC_STACK_INVALID_QUERY";\r
+    case OC_STACK_INVALID_IP:\r
+        return "OC_STACK_INVALID_IP";\r
+    case OC_STACK_INVALID_PORT:\r
+        return "OC_STACK_INVALID_PORT";\r
+    case OC_STACK_INVALID_CALLBACK:\r
+        return "OC_STACK_INVALID_CALLBACK";\r
+    case OC_STACK_INVALID_METHOD:\r
+        return "OC_STACK_INVALID_METHOD";\r
+    case OC_STACK_NO_MEMORY:\r
+        return "OC_STACK_NO_MEMORY";\r
+    case OC_STACK_COMM_ERROR:\r
+        return "OC_STACK_COMM_ERROR";\r
+    case OC_STACK_INVALID_PARAM:\r
+        return "OC_STACK_INVALID_PARAM";\r
+    case OC_STACK_NOTIMPL:\r
+        return "OC_STACK_NOTIMPL";\r
+    case OC_STACK_NO_RESOURCE:\r
+        return "OC_STACK_NO_RESOURCE";\r
+    case OC_STACK_RESOURCE_ERROR:\r
+        return "OC_STACK_RESOURCE_ERROR";\r
+    case OC_STACK_SLOW_RESOURCE:\r
+        return "OC_STACK_SLOW_RESOURCE";\r
+    case OC_STACK_NO_OBSERVERS:\r
+        return "OC_STACK_NO_OBSERVERS";\r
+    #ifdef WITH_PRESENCE\r
+    case OC_STACK_PRESENCE_STOPPED:\r
+        return "OC_STACK_PRESENCE_STOPPED";\r
+    #endif\r
+    case OC_STACK_ERROR:\r
+        return "OC_STACK_ERROR";\r
+    default:\r
+        return "UNKNOWN";\r
+    }\r
+}\r
+\r
+OCDPDev_t* getDev(const OCDPDev_t* pList, const uint32_t dev_num)\r
+{\r
+    if(NULL == pList)\r
+    {\r
+        printf("     Device List is Empty..\n");\r
+        return NULL;\r
+    }\r
+\r
+    OCDPDev_t* lst =  (OCDPDev_t*)pList;\r
+    for(size_t i=0; lst; )\r
+    {\r
+        if(dev_num == ++i)\r
+        {\r
+            return lst;\r
+        }\r
+        lst = lst->next;\r
+    }\r
+\r
+    return NULL;  // in here |lst| is always |NULL|\r
+}\r
+\r
+int printList(const OCDPDev_t* pList)\r
+{\r
+    if(!pList)\r
+    {\r
+        printf("     Device List is Empty..\n\n");\r
+        return 0;\r
+    }\r
+\r
+    const OCDPDev_t* lst = pList;\r
+    int lst_cnt = 0;\r
+    for( ; lst; )\r
+    {\r
+        printf("     [%d] ", ++lst_cnt);\r
+        for(int i=0; i<UUID_IDENTITY_SIZE; i++)\r
+        {\r
+            fprintf(stdout, "%c", (char)lst->deviceID.id[i]);\r
+        }\r
+        printf("\n");\r
+        lst = lst->next;\r
+    }\r
+    printf("\n");\r
+\r
+    return lst_cnt;\r
+}\r
+\r
+bool printPairingMethod(const OCDPDev_t* pDev)\r
+{\r
+    printf("\n   * List of supported pairing method\n");\r
+\r
+    if(!pDev || false == pDev->edp)\r
+    {\r
+        printf("     Invalid device or Not support direct-pairing..\n\n");\r
+        return false;\r
+    }\r
+\r
+    if(!pDev->prm || 0 == pDev->prmLen)\r
+    {\r
+        printf("     Not exist any support method..\n\n");\r
+        return false;\r
+    }\r
+\r
+    bool bAvailable = true;\r
+    for(size_t i=0; i<pDev->prmLen; i++)\r
+    {\r
+        printf("     [%ld] ", i+1);\r
+        switch (pDev->prm[i])\r
+        {\r
+            case DP_PRE_CONFIGURED:\r
+                printf("Pre-Configured PIN");\r
+                break;\r
+            case DP_RANDOM_PIN:\r
+                printf("Random PIN");\r
+                break;\r
+            default:\r
+                printf("NOT Allowed (%d)", pDev->prm[i]);\r
+                bAvailable = false;\r
+                break;\r
+        }\r
+        printf("\n");\r
+    }\r
+    printf("\n");\r
+\r
+    return bAvailable;\r
+}\r
+\r
+// This is a function called back when a device is discovered\r
+OCStackApplicationResult discoveryReqCB(void*, OCDoHandle,\r
+        OCClientResponse * clientResponse)\r
+{\r
+    OIC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");\r
+\r
+    if (clientResponse)\r
+    {\r
+        OIC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));\r
+        OIC_LOG_V(INFO, TAG,\r
+                "Device =============> Discovered @ %s:%d",\r
+                clientResponse->devAddr.addr,\r
+                clientResponse->devAddr.port);\r
+\r
+        if (clientResponse->result == OC_STACK_OK)\r
+        {\r
+            OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
+        }\r
+    }\r
+\r
+    return OC_STACK_DELETE_TRANSACTION;\r
+\r
+}\r
+\r
+// This is a function called back when direct-pairing status is changed\r
+void pairingReqCB(OCDPDev_t* peer, OCStackResult result)\r
+{\r
+    OIC_LOG(INFO, TAG, "Callback Context for Direct-Pairing establishment\n");\r
+\r
+    if (OC_STACK_OK == result)\r
+    {\r
+        OIC_LOG_V(INFO, TAG,\r
+                "Direct-Pairing SUCCESS =============> Target @ %s:%d\n",\r
+                peer->endpoint.addr,\r
+                peer->endpoint.port);\r
+    }\r
+    else\r
+    {\r
+        OIC_LOG(ERROR, TAG, "Direct-Pairing FAILED..\n");\r
+    }\r
+}\r
+\r
+OCStackApplicationResult getReqCB(void * ctx, OCDoHandle handle, OCClientResponse *clientResponse)\r
+{\r
+    OIC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");\r
+\r
+    (void)ctx;\r
+    (void)handle;\r
+    if (clientResponse)\r
+    {\r
+        OIC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));\r
+        OIC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);\r
+        OIC_LOG_PAYLOAD(INFO, clientResponse->payload);\r
+        if ((OCSecurityPayload*)clientResponse->payload)\r
+        {\r
+            OIC_LOG(INFO, TAG, PCF("=============> Get Response"));\r
+        }\r
+    }\r
+    return OC_STACK_DELETE_TRANSACTION;\r
+}\r
+\r
+int DeviceDiscovery()\r
+{\r
+    OCStackResult ret;\r
+    OCCallbackData cbData;\r
+    char queryUri[200];\r
+    char ipaddr[100] = { '\0' };\r
+\r
+    snprintf(queryUri, sizeof (queryUri), DISCOVERY_QUERY, ipaddr);\r
+\r
+    cbData.cb = discoveryReqCB;\r
+    cbData.context = NULL;\r
+    cbData.cd = NULL;\r
+\r
+    /* Start a discovery query*/\r
+    OIC_LOG_V(INFO, TAG, "Resource Discovery : %s\n", queryUri);\r
+\r
+    ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,\r
+                       OC_LOW_QOS, &cbData, NULL, 0);\r
+    if (ret != OC_STACK_OK)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCStack resource error");\r
+    }\r
+    return ret;\r
+}\r
+\r
+OCStackResult DirectPairingDiscovery()\r
+{\r
+    // initiate direct pairing discovery\r
+    OIC_LOG(INFO, TAG, "   Discovering Only Owned Devices on Network..");\r
+    discoveredDevs = OCDiscoverDirectPairingDevices(DP_DISCOVERY_TIMEOUT);\r
+    if(NULL == discoveredDevs)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCDiscoverDirectPairingDevices API error");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    // display the discovered unowned list\r
+    printf("   > Discovered Direct-Pairing Support Devices\n");\r
+    printList(discoveredDevs);\r
+\r
+    return OC_STACK_OK;\r
+}\r
+\r
+OCStackResult DoDirectPairing(OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber)\r
+{\r
+    if (NULL == peer || NULL == pinNumber)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "invalid parameter");\r
+        return OC_STACK_INVALID_PARAM;\r
+    }\r
+\r
+    // start direct pairing\r
+    OIC_LOG(INFO, TAG, "   Start Direct Pairing..");\r
+    if(OC_STACK_OK != OCDoDirectPairing(peer, pmSel, pinNumber, pairingReqCB))\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCDoDirectPairing API error");\r
+        return OC_STACK_ERROR;\r
+    }\r
+\r
+    return OC_STACK_OK;\r
+}\r
+\r
+OCStackResult SendGetRequest(OCDPDev_t* peer)\r
+{\r
+    OIC_LOG(INFO, TAG, "Send Get REQ to Led server");\r
+\r
+    char szQueryUri[] = "/a/led";\r
+    OCDoHandle handle;\r
+    OCCallbackData cbData;\r
+    OCDevAddr endpoint;\r
+    OCStackResult ret;\r
+\r
+    memcpy(&endpoint, &peer->endpoint, sizeof(OCDevAddr));\r
+    endpoint.port = peer->securePort;\r
+    endpoint.flags = (OCTransportFlags)(endpoint.flags | OC_SECURE);\r
+\r
+    cbData.cb = getReqCB;\r
+    cbData.context = NULL;\r
+    cbData.cd = NULL;\r
+\r
+    OIC_LOG(INFO, TAG, "Request to /a/light ");\r
+    ret = OCDoResource(&handle, OC_REST_GET, szQueryUri,\r
+               &endpoint, NULL, peer->connType, OC_LOW_QOS, &cbData, NULL, 0);\r
+    if (ret != OC_STACK_OK)\r
+    {\r
+        OIC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, OC_REST_GET);\r
+    }\r
+\r
+    return ret;\r
+}\r
+\r
+FILE* client_fopen(const char *path, const char *mode)\r
+{\r
+    (void)path;\r
+    return fopen(CRED_FILE, mode);\r
+}\r
+\r
+void *CLInterface(void *data)\r
+{\r
+    printf(RED_BEGIN"#Ready to operation ('h' for help)#\n"COLOR_END);\r
+\r
+    (void)data;\r
+    OCStackResult ret;\r
+    char query[MAX_LINE] = {0,};\r
+    const char prompt[] = BOLD_BEGIN"IoTivity-DP#"COLOR_END" ";\r
+    const char* helpmsg[6] = {\r
+            GREEN_BEGIN"# h  (or help) : show help message"COLOR_END,\r
+            GREEN_BEGIN"# dd (DP device discovery) : discover Direct-Pairing devices"COLOR_END,\r
+            GREEN_BEGIN"# dp (start Direct-Pairing) : negotiate DP method & start Direct-Pairing"COLOR_END,\r
+            GREEN_BEGIN"# sd (send data) : send data to device"COLOR_END,\r
+            GREEN_BEGIN"# ll (list all device) : list all discovered/paired devices"COLOR_END,\r
+            GREEN_BEGIN"# q  (quit) : quit test"COLOR_END,\r
+        };\r
+\r
+    for (size_t i=0; i<(sizeof(helpmsg)/sizeof(char*)); i++)\r
+    {\r
+        fprintf(stderr, "%s\n", helpmsg[i]);\r
+    }\r
+    printf("\n");\r
+\r
+    // cli\r
+    for (;;)\r
+    {\r
+        const char *input = readline(prompt, NULL);\r
+        if (!input) {\r
+            continue;\r
+        }\r
+\r
+        strncpy(query, input, MAX_LINE);\r
+        if (!strlen(query))\r
+        {\r
+            continue;\r
+        }\r
+        else if (!strcmp(query, "h") || !strcmp(query, "help"))\r
+        {\r
+            for (size_t i=0; i<(sizeof(helpmsg)/sizeof(char*)); i++)\r
+            {\r
+                fprintf(stderr, "%s\n", helpmsg[i]);\r
+            }\r
+            continue;\r
+        }\r
+        else\r
+        {\r
+            if (!strcmp(query, "dd"))\r
+            {\r
+                OIC_LOG(INFO, TAG, "- Direct-Pairing device discovery -");\r
+\r
+                ret = DirectPairingDiscovery();\r
+                if (OC_STACK_OK != ret)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Error in DirectPairingDiscovery()");\r
+                }\r
+            }\r
+            else if (!strcmp(query, "dp"))\r
+            {\r
+                OIC_LOG(INFO, TAG, "- Negotiate DP method & Start Direct-Pairing -");\r
+\r
+                printf("\n   * List of  discovered device\n");\r
+                printList(discoveredDevs);\r
+\r
+                // target peer\r
+                OCDPDev_t *peer = NULL;\r
+                long peerIdx;\r
+                input = readline("   > Enter Peer Device Number to initiate Direct-Pairing: ", NULL);\r
+                if (!input || !strlen(input))\r
+                {\r
+                    continue;\r
+                }\r
+                char *ptr;\r
+                peerIdx = strtol(input, &ptr, 10);\r
+\r
+                peer = getDev(discoveredDevs, (uint32_t)peerIdx);\r
+                if (NULL == peer)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Not found the peer in discovered list");\r
+                    continue;\r
+                }\r
+\r
+                // get pairing method\r
+                long pmIdx;\r
+                OCPrm_t pmSel = DP_NOT_ALLOWED;\r
+                if (false == printPairingMethod(peer))\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Target does not support the Direct-Pairing");\r
+                    continue;\r
+                }\r
+                input = readline("   > Enter pairing method: ", NULL);\r
+                if (!input || !strlen(input))\r
+                {\r
+                    continue;\r
+                }\r
+                pmIdx = strtol(input, &ptr, 10);\r
+                printf("\n");\r
+                if (0 >= pmIdx || peer->prmLen+1 < (size_t)pmIdx)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Invalid mode selection");\r
+                    continue;\r
+                }\r
+                pmSel = peer->prm[pmIdx-1];\r
+\r
+                // get PIN\r
+                char pinNumber[DP_PIN_LENGTH+1];\r
+                input = readline("   > Enter PIN Number for authentication (ex - '00000000' [8 digit] ): ", NULL);\r
+                if (!input || DP_PIN_LENGTH != strlen(input))\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Invalid PIN");\r
+                    continue;\r
+                }\r
+                sscanf(input, "%9s", pinNumber);\r
+                printf("\n");\r
+\r
+                ret = DoDirectPairing(peer, pmSel, pinNumber);\r
+                if (OC_STACK_OK != ret)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Error in DoDirectPairing()");\r
+                }\r
+            }\r
+            else if (!strcmp(query, "sd"))\r
+            {\r
+                OIC_LOG(INFO, TAG, "- Send data(GET Request) to device(led server) -");\r
+\r
+                //pairedDevs = OCGetDirectPairedDevices();\r
+                //printList(pairedDevs);\r
+                printList(discoveredDevs);\r
+\r
+                // target peer\r
+                OCDPDev_t *peer = NULL;\r
+                long peerIdx;\r
+                input = readline("   > Enter Peer Device Number to initiate Direct-Pairing: ", NULL);\r
+                if (!input || !strlen(input))\r
+                {\r
+                    continue;\r
+                }\r
+                char *ptr;\r
+                peerIdx = strtol(input, &ptr, 10);\r
+\r
+                //peer = getDev(pairedDevs, peerIdx);\r
+                peer = getDev(discoveredDevs, (uint32_t)peerIdx);\r
+                if (NULL == peer)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Not found the peer in discovered list");\r
+                    continue;\r
+                }\r
+\r
+                // send Get Req\r
+                ret = SendGetRequest(peer);\r
+                if (OC_STACK_OK != ret)\r
+                {\r
+                    OIC_LOG(ERROR, TAG, "Error in SendGetRequest()");\r
+                }\r
+            }\r
+            else if (!strcmp(query, "ll"))\r
+            {\r
+                OIC_LOG(INFO, TAG, "- List all discovered and paired devices) -");\r
+\r
+                printf("  > List of discovered devices\n");\r
+                printList(discoveredDevs);\r
+                printf("\n");\r
+\r
+                printf("  > List of paired devices\n");\r
+                pairedDevs = OCGetDirectPairedDevices();\r
+                printList(pairedDevs);\r
+                printf("\n");\r
+            }\r
+            else if (!strcmp(query, "q"))\r
+            {\r
+                printf("QUIT\n");\r
+                gQuitFlag = 1;\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+int main(void)\r
+{\r
+    struct timespec timeout;\r
+\r
+    // Initialize Persistent Storage for SVR database\r
+    OCPersistentStorage ps = { client_fopen, fread, fwrite, fclose, unlink };\r
+    OCRegisterPersistentStorageHandler(&ps);\r
+\r
+    /* Initialize OCStack*/\r
+    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCStack init error");\r
+        return 0;\r
+    }\r
+\r
+//    DeviceDiscovery();\r
+\r
+    timeout.tv_sec  = 0;\r
+    timeout.tv_nsec = 100000000L;\r
+\r
+    // Break from loop with Ctrl+C\r
+    OIC_LOG(INFO, TAG, "Entering occlient main loop...");\r
+    signal(SIGINT, handleSigInt);\r
+\r
+    // CLI\r
+    int thr_id;\r
+    pthread_t p_thread;\r
+    thr_id = pthread_create(&p_thread, NULL, CLInterface, (void *)NULL);\r
+    if (thr_id < 0)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "create CLI Thread error");\r
+        return 0;\r
+    }\r
+\r
+    // loop\r
+    while (!gQuitFlag)\r
+    {\r
+        if (OCProcess() != OC_STACK_OK)\r
+        {\r
+            OIC_LOG(ERROR, TAG, "OCStack process error");\r
+            return 0;\r
+        }\r
+\r
+        nanosleep(&timeout, NULL);\r
+    }\r
+    OIC_LOG(INFO, TAG, "Exiting occlient main loop...");\r
+\r
+    if (OCStop() != OC_STACK_OK)\r
+    {\r
+        OIC_LOG(ERROR, TAG, "OCStack stop error");\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+\r
+\r
diff --git a/resource/csdk/stack/samples/linux/secure/oic_svr_db_client_directpairing.json b/resource/csdk/stack/samples/linux/secure/oic_svr_db_client_directpairing.json
new file mode 100644 (file)
index 0000000..e819a71
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "ZGlyZWN0cGFpcmluZ0Rldg=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "ZGlyZWN0cGFpcmluZ0Rldg=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "ZGlyZWN0cGFpcmluZ0Rldg==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "sct": 1,
+               "owned": false,
+               "deviceid":     "ZGlyZWN0cGFpcmluZ0Rldg=="
+       }
+}
index d55baf6..dca4363 100644 (file)
 #include "oickeepalive.h"
 #endif
 
+//#ifdef DIRECT_PAIRING
+#include "directpairing.h"
+//#endif
+
 #ifdef WITH_ARDUINO
 #include "Time.h"
 #else
@@ -128,6 +132,10 @@ OCDeviceEntityHandler defaultDeviceHandler;
 void* defaultDeviceHandlerCallbackParameter = NULL;
 static const char COAP_TCP[] = "coap+tcp:";
 
+//#ifdef DIRECT_PAIRING
+OCDirectPairingCB gDirectpairingCallback = NULL;
+//#endif
+
 //-----------------------------------------------------------------------------
 // Macros
 //-----------------------------------------------------------------------------
@@ -3871,6 +3879,49 @@ OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
     return result;
 }
 
+//#ifdef DIRECT_PAIRING
+const OCDPDev_t* OCDiscoverDirectPairingDevices(unsigned short waittime)
+{
+    OIC_LOG(INFO, TAG, "Start OCDiscoverDirectPairingDevices");
+    if(OC_STACK_OK != DPDeviceDiscovery(waittime))
+    {
+        OIC_LOG(ERROR, TAG, "Fail to discover Direct-Pairing device");
+        return NULL;
+    }
+
+    return (const OCDPDev_t*)DPGetDiscoveredDevices();
+}
+
+const OCDPDev_t* OCGetDirectPairedDevices()
+{
+    return (const OCDPDev_t*)DPGetPairedDevices();
+}
+
+void DirectPairingCB (OCDirectPairingDev_t * peer, OCStackResult result)
+{
+    if (gDirectpairingCallback)
+    {
+        gDirectpairingCallback((OCDPDev_t*)peer, result);
+        gDirectpairingCallback = NULL;
+    }
+}
+
+OCStackResult OCDoDirectPairing(OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber,
+                                                     OCDirectPairingCB resultCallback)
+{
+    OIC_LOG(INFO, TAG, "Start OCDoDirectPairing");
+    if(NULL ==  peer || NULL == resultCallback)
+    {
+        OIC_LOG(ERROR, TAG, "Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    gDirectpairingCallback = resultCallback;
+    return DPDirectPairing((OCDirectPairingDev_t*)peer, (OicSecPrm_t)pmSel,
+                                           pinNumber, DirectPairingCB);
+}
+//#endif // DIRECT_PAIRING
+
 //-----------------------------------------------------------------------------
 // Private internal function definitions
 //-----------------------------------------------------------------------------