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