'connectivity/external/inc',
'security/include',
'security/include/internal',
+ 'security/provisioning/include',
])
if target_os not in ['arduino', 'windows', 'winrt']:
'../connectivity/inc',
'../connectivity/api',
'../security/include',
- '../security/include/internal'
+ '../security/include/internal',
+ '../security/provisioning/include'
])
if target_os not in ['arduino', 'windows', 'winrt']:
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 + '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 = [
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':
--- /dev/null
+/* *****************************************************************\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
--- /dev/null
+/* *****************************************************************\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
--- /dev/null
+/* *****************************************************************\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
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;
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;
//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.
};
#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
OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
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.
*
OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,\r
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 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__
/**
struct OCProvisionDev *next; /**< Next pointer. **/
}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 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
"ownrs" : [
"anVzdHdvcmtzRGV2VVVJRA=="
]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/pconf",
+ "/oic/sec/dpairing"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "anVzdHdvcmtzRGV2VVVJRA=="
+ ]
}
],
"pstat": {
"oxmsel": 0,
"sct": 1,
"owned": false,
- "deviceid": "anVzdHdvcmtzRGV2VVVJRA=="
+ "deviceid": "anVzdHdvcmtzRGV2VVVJRA==",
+ "dpc": true
}
}
"ownrs" : [
"cmFuZG9tUGluRGV2VVVJRA=="
]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/pconf",
+ "/oic/sec/dpairing"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "cmFuZG9tUGluRGV2VVVJRA=="
+ ]
}
],
"pstat": {
"oxmsel": 0,
"sct": 1,
"owned": false,
- "deviceid": "cmFuZG9tUGluRGV2VVVJRA=="
+ "deviceid": "cmFuZG9tUGluRGV2VVVJRA==",
+ "dpc": true
}
}
#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
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
// 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*);
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)
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
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)
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");
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_:
#include "credresource.h"
#include "utlist.h"
#include "aclresource.h" //Note: SRM internal header
+#include "pconfresource.h"
#define TAG "OCPMAPI"
}
+/**
+ * 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.
DeleteACLList(pAcl);
}
+/**
+ * This function deletes PDACL data.
+ *
+ * @param pPdAcl Pointer to OicSecPdAcl_t structure.
+ */
+void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl)
+{
+ FreePdAclList(pPdAcl);
+}
+
#ifdef __WITH_X509__
/**
#include "srmresourcestrings.h"
#include "credresource.h"
#include "doxmresource.h"
+#include "pconfresource.h"
#include "credentialgenerator.h"
#include "cainterface.h"
#include "cJSON.h"
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
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)
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)
--- /dev/null
+/* *****************************************************************\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
SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
false, /* bool owned */
{.id = {0}}, /* OicUuid_t deviceID */
+ false, /* bool dpc */
{.id = {0}}, /* OicUuid_t owner */
};
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,
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)
--- /dev/null
+/* *****************************************************************\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
--- /dev/null
+/* *****************************************************************\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
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);
#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__
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
#endif // __WITH_X509__
DeInitSVCResource();
DeInitAmaclResource();
+//#ifdef DIRECT_PAIRING
+ DeInitPconfResource();
+ DeInitDpairingResource();
+//#endif // DIRECT_PAIRING
return OC_STACK_OK;
}
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
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";
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;
*/
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
/** 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.*/
unsigned char id[MAX_IDENTITY_SIZE];
} 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).
} 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
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
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')
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'))
--- /dev/null
+//******************************************************************\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
--- /dev/null
+{
+ "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=="
+ }
+}
#include "oickeepalive.h"
#endif
+//#ifdef DIRECT_PAIRING
+#include "directpairing.h"
+//#endif
+
#ifdef WITH_ARDUINO
#include "Time.h"
#else
void* defaultDeviceHandlerCallbackParameter = NULL;
static const char COAP_TCP[] = "coap+tcp:";
+//#ifdef DIRECT_PAIRING
+OCDirectPairingCB gDirectpairingCallback = NULL;
+//#endif
+
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
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
//-----------------------------------------------------------------------------