From: Jongmin Choi Date: Tue, 6 Dec 2016 09:38:51 +0000 (+0900) Subject: Vendor-specific OTM: Mutual Verified Just-Works & Confirmed MFG Cert X-Git-Tag: 1.3.0~1049^2~37 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=76b8ae67f529708d716998150437b884018b9cf1;p=platform%2Fupstream%2Fiotivity.git Vendor-specific OTM: Mutual Verified Just-Works & Confirmed MFG Cert This patch adds vendor-specific Ownership Transfer Methods, Mutual Verified Just-Works, which works the same as https://gerrit.iotivity.org/gerrit/#/c/14359/7 and Confirmed Manufacturer Certificate Due to difference between this method and Verified Just-Works (CR29) this method has been implemented as a separate vendor-specific OTM. Also confirmation on server side has been added to manufacturer certificate to make a new vendor-specific OTM: confirmed manufacturer certificate Cherry-picked from https://gerrit.iotivity.org/gerrit/#/c/14739/ Change-Id: I80d77b6e36cc857916f3e89f36d2c1f4dfbc5215 Signed-off-by: Jongmin Choi Reviewed-on: https://gerrit.iotivity.org/gerrit/15187 Tested-by: jenkins-iotivity Reviewed-by: Randeep Singh --- diff --git a/resource/csdk/octbstack_product_secured.def b/resource/csdk/octbstack_product_secured.def index c11c83e..65d655f 100644 --- a/resource/csdk/octbstack_product_secured.def +++ b/resource/csdk/octbstack_product_secured.def @@ -3,6 +3,8 @@ CreateJustWorksOwnerTransferPayload CreateJustWorksSelectOxmPayload +CreateMVJustWorksSelectOxmPayload +CreateConMCertificateBasedSelectOxmPayload CreatePinBasedSelectOxmPayload CreatePinBasedOwnerTransferPayload CreateSecureSessionJustWorksCallback @@ -37,6 +39,12 @@ OCSetOxmAllowStatus SetGeneratePinCB SetInputPinCB SetRandomPinPolicy +SetDisplayNumCB +UnsetDisplayNumCB +SetUserConfirmCB +UnsetUserConfirmCB +SetVerifyOption +VerifyOwnershipTransfer registerTimer unregisterTimer diff --git a/resource/csdk/security/SConscript b/resource/csdk/security/SConscript index f0b347b..ab26e3a 100644 --- a/resource/csdk/security/SConscript +++ b/resource/csdk/security/SConscript @@ -118,7 +118,8 @@ libocsrm_src = [ if libocsrm_env.get('SECURED') == '1': libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmpincommon.c', OCSRM_SRC + 'pbkdf2.c'] - libocsrm_src = libocsrm_src + [OCSRM_SRC + 'crlresource.c', OCSRM_SRC + 'pkix_interface.c'] + libocsrm_src = libocsrm_src + [OCSRM_SRC + 'crlresource.c', OCSRM_SRC + 'pkix_interface.c'] + libocsrm_src = libocsrm_src + [OCSRM_SRC + 'oxmverifycommon.c'] if target_os in ['windows', 'msys_nt']: libocsrm_src = libocsrm_src + [OCSRM_SRC + 'strptime.c'] diff --git a/resource/csdk/security/include/internal/srmresourcestrings.h b/resource/csdk/security/include/internal/srmresourcestrings.h index 5dbf7e0..2076e87 100644 --- a/resource/csdk/security/include/internal/srmresourcestrings.h +++ b/resource/csdk/security/include/internal/srmresourcestrings.h @@ -181,6 +181,11 @@ extern const char * OXM_MANUFACTURER_CERTIFICATE; #ifdef MULTIPLE_OWNER extern const char * OXM_PRECONF_PIN; #endif //MULTIPLE_OWNER +extern const char * OXM_MV_JUST_WORKS; +extern const char * OXM_CON_MFG_CERT; + +//Mutual Verified Just-Works Message Prefix +extern const char * MUTUAL_VERIF_NUM; extern const char * OIC_SEC_ENCODING_BASE64; extern const char * OIC_SEC_ENCODING_RAW; diff --git a/resource/csdk/security/include/oxmverifycommon.h b/resource/csdk/security/include/oxmverifycommon.h new file mode 100644 index 0000000..a90eaef --- /dev/null +++ b/resource/csdk/security/include/oxmverifycommon.h @@ -0,0 +1,112 @@ +//****************************************************************** +// +// Copyright 2016 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_VERIFY_COMMON_ +#define _OXM_VERIFY_COMMON_ + +#include "securevirtualresourcetypes.h" +#include "casecurityinterface.h" + +#ifdef __cplusplus + extern "C" { +#endif // __cplusplus + +/** Verification Number Length */ +#define MUTUAL_VERIF_NUM_LEN (3) + +/** Label Length */ +#define LABEL_LEN (30) + +/* Verification Method Option definition + * This type supports multiple bit set. + */ + typedef enum VerifyOptionBitmask +{ + NOT_APPLICABLE = 0x0, + DISPLAY_NUM = (0x1 << 0), + USER_CONFIRM = (0x1 << 1) +} VerifyOptionBitmask_t; + +/** + * Function pointer to display verification PIN + */ +typedef OCStackResult (*DisplayNumCallback)(void * ctx, uint8_t verifNum[MUTUAL_VERIF_NUM_LEN]); + +/* + * Function pointer to get user confirmation + */ +typedef OCStackResult (*UserConfirmCallback)(void * ctx); + +/** + * Context for displaying verification PIN + */ +typedef struct DisplayNumContext +{ + DisplayNumCallback callback; + void * context; +} DisplayNumContext_t; + +/** + * Context for getting user confirmation + */ +typedef struct UserConfirmContext +{ + UserConfirmCallback callback; + void * context; +} UserConfirmContext_t; + +/* + * Set Callback for displaying verification PIN + */ +void SetDisplayNumCB(void * ptr, DisplayNumCallback displayNumCB); + +/* + * Unset Callback for displaying verification PIN + */ +void UnsetDisplayNumCB(); + +/* + * Set Callback for getting user confirmation + */ +void SetUserConfirmCB(void * ptr, UserConfirmCallback userConfirmCB); + +/* + * Unset Callback for getting user confirmation + */ +void UnsetUserConfirmCB(); + +/* + * Set verification method option. + * The default is both display PIN and get user confirmation. + */ +void SetVerifyOption(VerifyOptionBitmask_t verifyOption); + +/* + * Call the Callback for Verifying Ownership Transfer process. + */ +OCStackResult VerifyOwnershipTransfer(uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN], + VerifyOptionBitmask_t verifyOption); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/resource/csdk/security/include/securevirtualresourcetypes.h b/resource/csdk/security/include/securevirtualresourcetypes.h index 3a48a18..46b1af6 100644 --- a/resource/csdk/security/include/securevirtualresourcetypes.h +++ b/resource/csdk/security/include/securevirtualresourcetypes.h @@ -276,6 +276,8 @@ typedef enum #ifdef MULTIPLE_OWNER OIC_PRECONFIG_PIN = 0xFF00, #endif //MULTIPLE_OWNER + OIC_MV_JUST_WORKS = 0xFF01, + OIC_CON_MFG_CERT = 0xFF02, }OicSecOxm_t; typedef enum diff --git a/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h b/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h index 2df0540..5778ea0 100644 --- a/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h +++ b/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h @@ -36,6 +36,21 @@ extern "C" { typedef struct OTMCallbackData OTMCallbackData_t; typedef struct OTMContext OTMContext_t; + +typedef enum OxmAllowTableIdx { + OXM_IDX_JUST_WORKS = 0, + OXM_IDX_MV_JUST_WORKS, +#ifdef MULTIPLE_OWNER + OXM_IDX_PRECONFIG_PIN, +#endif + OXM_IDX_RANDOM_DEVICE_PIN, + OXM_IDX_MANUFACTURER_CERTIFICATE, + OXM_IDX_CON_MFG_CERT, + OXM_IDX_DECENTRALIZED_PUBLIC_KEY, + OXM_IDX_COUNT, + OXM_IDX_UNKNOWN +}OxmAllowTableIdx_t; + /** * Do ownership transfer for the unowned devices. * diff --git a/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h b/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h index 0b9f81e..f2fc932 100644 --- a/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h +++ b/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h @@ -74,6 +74,20 @@ OCStackResult CreateJustWorksSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cb */ OCStackResult CreateJustWorksOwnerTransferPayload(OTMContext_t *otmCtx, uint8_t **cborPayload, size_t *cborSize); + +/** + * Generate payload for select OxM request for Mutual Verified Just-Works. + * + * @param otmCtx Context of OTM, It includes current device information. + * @param cborPayload is the DOXM CBOR payload including the selected OxM. + * @note Returned memory should be deallocated by caller. + * @param cborSize is the size of the cborPayload. + * + * @return ::OC_STACK_SUCCESS in case of success and other value otherwise. + */ +OCStackResult CreateMVJustWorksSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cborPayload, + size_t *cborSize); + #ifdef __cplusplus } #endif diff --git a/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h b/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h index 0a9bca7..cff6467 100644 --- a/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h +++ b/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h @@ -62,6 +62,19 @@ OCStackResult CreateMCertificateBasedSelectOxmPayload(OTMContext_t *otmCtx, uint size_t *cborSize); /** + * Generate payload for select OxM request for confirmed manufactrer certificate method. + * + * @param otmCtx Context of OTM, It includes current device information. + * @param cborPayload is the DOXM CBOR payload including the selected OxM. + * @note Returned memory should be deallocated by caller. + * @param cborSize is the size of the cborPayload. + * + * @return ::OC_STACK_SUCCESS in case of success and other value otherwise. + */ +OCStackResult CreateConMCertificateBasedSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cborPayload, + size_t *cborSize); + +/** * Generate payload for owner transfer request. * * @param otmCtx Context of OTM, It includes current device information. diff --git a/resource/csdk/security/provisioning/sample/SConscript b/resource/csdk/security/provisioning/sample/SConscript index 947182d..7a4887b 100644 --- a/resource/csdk/security/provisioning/sample/SConscript +++ b/resource/csdk/security/provisioning/sample/SConscript @@ -103,6 +103,7 @@ provisioningclient = provisioning_env.Program('provisioningclient', 'provisionin sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp') sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp') sampleserver_mfg = provisioning_env.Program('sampleserver_mfg', 'sampleserver_mfg.cpp') +sampleserver_mvjustworks = provisioning_env.Program('sampleserver_mvjustworks', 'sampleserver_mvjustworks.cpp') if provisioning_env.get('MULTIPLE_OWNER') == '1': subownerclient = provisioning_env.Program('subownerclient', 'subownerclient.c') @@ -131,6 +132,8 @@ mfgdat = provisioning_env.Install(sec_provisioning_build_dir, sec_provisioning_src_dir+ 'oic_svr_db_server_mfg.dat') randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_dir, sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat') +mvjustworksdat = provisioning_env.Install(sec_provisioning_build_dir, + sec_provisioning_src_dir + 'oic_svr_db_server_mvjustworks.dat') if provisioning_env.get('MULTIPLE_OWNER') == '1': subownerclientdat = provisioning_env.Install(sec_provisioning_build_dir, @@ -148,15 +151,18 @@ if provisioning_env.get('MULTIPLE_OWNER') == '1': Alias("samples", [ provisioningclient, subownerclient, sampleserver_justworks, sampleserver_randompin, sampleserver_mfg, - clientdat, subownerclientdat, - justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat + sampleserver_preconfpin, + clientdat, subownerclientdat, preconfserverdat, + justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat, + mvjustworksdat ]) else: Alias("samples", [ provisioningclient, sampleserver_justworks, sampleserver_randompin, sampleserver_mfg, clientdat, - justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat + justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat, + mvjustworksdat ]) provisioning_env.AppendTarget('samples') diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.dat b/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.dat new file mode 100644 index 0000000..2fa0b63 Binary files /dev/null and b/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.dat differ diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.json new file mode 100644 index 0000000..fd3fb33 --- /dev/null +++ b/resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.json @@ -0,0 +1,79 @@ +{ + "acl": { + "aclist": { + "aces": [ + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/res", + "rel": "", + "rt": ["oic.wk.res"], + "if": ["oic.if.ll"] + },{ + "href": "/oic/d", + "rel": "", + "rt": ["oic.wk.d"], + "if": ["oic.if.baseline", "oic.if.r"] + },{ + "href": "/oic/p", + "rel": "", + "rt": ["oic.wk.p"], + "if": ["oic.if.baseline", "oic.if.r"] + } + ], + "permission": 2 + }, + { + "subjectuuid": "*", + "resources": [ + { + "href": "/oic/sec/doxm", + "rel": "", + "rt": ["oic.r.doxm"], + "if": ["oic.if.baseline"] + }, + { + "href": "/oic/sec/pstat", + "rel": "", + "rt": ["oic.r.pstat"], + "if": ["oic.if.baseline"] + }, + { + "href": "/oic/sec/acl", + "rel": "", + "rt": ["oic.r.acl"], + "if": ["oic.if.baseline"] + }, + { + "href": "/oic/sec/cred", + "rel": "", + "rt": ["oic.r.cred"], + "if": ["oic.if.baseline"] + } + ], + "permission": 6 + } + ] + }, + "rowneruuid" : "6D766A75-7374-776F-726B-735575696430" + }, + "pstat": { + "isop": false, + "deviceuuid": "6D766A75-7374-776F-726B-735575696430", + "rowneruuid": "6D766A75-7374-776F-726B-735575696430", + "cm": 2, + "tm": 0, + "om": 4, + "sm": 4 + }, + "doxm": { + "oxms": [0, 65281], + "oxmsel": 0, + "sct": 1, + "owned": false, + "deviceuuid": "6D766A75-7374-776F-726B-735575696430", + "devowneruuid": "", + "rowneruuid": "6D766A75-7374-776F-726B-735575696430" + } +} diff --git a/resource/csdk/security/provisioning/sample/provisioningclient.c b/resource/csdk/security/provisioning/sample/provisioningclient.c index db31e88..90c18b9 100644 --- a/resource/csdk/security/provisioning/sample/provisioningclient.c +++ b/resource/csdk/security/provisioning/sample/provisioningclient.c @@ -36,6 +36,7 @@ #include "securevirtualresourcetypes.h" #include "srmutility.h" #include "pmtypes.h" +#include "oxmverifycommon.h" #ifdef __cplusplus extern "C" @@ -69,6 +70,7 @@ extern "C" #define _72_MOT_OXM_SEL_ 72 #endif //MULTIPLE_OWNER #define _80_SELECT_PROTOCOL_ 80 +#define _81_SELECT_VERIF_METHOD_ 81 #define _99_EXIT_PRVN_CLT_ 99 #define ACL_RESRC_MAX_NUM 16 @@ -1206,6 +1208,51 @@ static int removeDeviceWithUuid(void) return 0; } +OCStackResult displayNumCB(void * ctx, uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN]) +{ + OIC_LOG(INFO, TAG, "IN displayMutualVerifNumCB"); + if (NULL != mutualVerifNum) + { + OIC_LOG(INFO, TAG, "############ mutualVerifNum ############"); + OIC_LOG_BUFFER(INFO, TAG, mutualVerifNum, MUTUAL_VERIF_NUM_LEN); + OIC_LOG(INFO, TAG, "############ mutualVerifNum ############"); + OIC_LOG(INFO, TAG, "OUT displayMutualVerifNumCB"); + } + else + { + OIC_LOG(INFO, TAG, "############ Confirm on the Server side ############"); + } + return OC_STACK_OK; +} + +OCStackResult confirmNumCB(void * ctx) +{ + for (;;) + { + int userConfirm; + + printf(" > Press 1 if the mutual verification numbers are the same\n"); + printf(" > Press 0 if the mutual verification numbers are not the same\n"); + + for (int ret=0; 1!=ret; ) + { + ret = scanf("%d", &userConfirm); + for (; 0x20<=getchar(); ); // for removing overflow garbage + // '0x20<=code' is character region + } + if (1 == userConfirm) + { + break; + } + else if (0 == userConfirm) + { + return OC_STACK_USER_DENIED_REQ; + } + printf(" Entered Wrong Number. Please Enter Again\n"); + } + return OC_STACK_OK; +} + #ifdef MULTIPLE_OWNER static int changeMultipleOwnershipTrnasferMode(void) { @@ -2009,6 +2056,30 @@ static void selectSecureProtocol() } #endif +static void selectVerifMethod() +{ + int option; + printf(" Select verification method for ownership transfer\n"); + printf(" 0 - No verification\n"); + printf(" 1 - Display only\n"); + printf(" 2 - Confirm only\n"); + printf(" 3 - Both Display and Confirm\n"); + + for(int ret=0; 1!=ret; ) + { + ret = scanf("%d",&option); + for( ; 0x20<=getchar(); ); // for removing overflow garbages + // '0x20<=code' is character region + } + + if(0 > option || 3 < option) + { + printf("Invalid option!"); + } + SetVerifyOption((VerifyOptionBitmask_t) option); + printf("Option %d chosen!", option); +} + static void printMenu(void) { printf("************************************************************\n"); @@ -2056,13 +2127,14 @@ static void printMenu(void) #endif //MULTIPLE_OWNER #ifdef __WITH_TLS__ - printf("** [H] SELECT SECURE PROTOCOL DTLS/TLS\n"); - printf("** 80. Select secure protocol(default DTLS)\n\n"); - - printf("** [I] EXIT PROVISIONING CLIENT\n"); + printf("** [H] SELECT SECURE PROTOCOL DTLS/TLS AND OTHERS\n"); + printf("** 80. Select secure protocol(default DTLS)\n"); + printf("** 81. Select verification method\n\n"); #else - printf("** [H] EXIT PROVISIONING CLIENT\n"); + printf("** [H] SELECT VERIFICATION OPTION\n"); + printf("** 81. Select verification method\n\n"); #endif + printf("** [I] EXIT PROVISIONING CLIENT\n"); printf("** 99. Exit Provisionong Client\n\n"); @@ -2105,6 +2177,10 @@ int main() OIC_LOG(WARNING, TAG, "Failed to disable OIC_DECENTRALIZED_PUBLIC_KEY OxM"); } + // set callbacks for verification options + SetDisplayNumCB(NULL, displayNumCB); + SetUserConfirmCB(NULL, confirmNumCB); + #ifdef MULTIPLE_OWNER SetPreconfigPin("12341234", 8); #endif //MULTIPLE_OWNER @@ -2254,6 +2330,9 @@ int main() selectSecureProtocol(); break; #endif + case _81_SELECT_VERIF_METHOD_: + selectVerifMethod(); + break; case _99_EXIT_PRVN_CLT_: goto PMCLT_ERROR; default: diff --git a/resource/csdk/security/provisioning/sample/sampleserver_mvjustworks.cpp b/resource/csdk/security/provisioning/sample/sampleserver_mvjustworks.cpp new file mode 100644 index 0000000..c45fb2d --- /dev/null +++ b/resource/csdk/security/provisioning/sample/sampleserver_mvjustworks.cpp @@ -0,0 +1,529 @@ +/****************************************************************** +* +* 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 "iotivity_config.h" +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif +#include +#include "ocstack.h" +#include "ocpayload.h" +#include "pinoxmcommon.h" +#include "oxmverifycommon.h" + +#ifdef HAVE_WINDOWS_H +#include +/** @todo stop-gap for naming issue. Windows.h does not like us to use ERROR */ +#ifdef ERROR +#undef ERROR +#endif //ERROR +#endif //HAVE_WINDOWS_H +#include "platform_features.h" +#include "logger.h" + + +#define TAG "SAMPLE_MV_JUSTWORKS" + +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_mvjustworks.dat"; + +/* 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) + { + OIC_LOG(ERROR, TAG, "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) + { + OIC_LOG(ERROR, TAG, "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)) + { + OIC_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 + { + OIC_LOG_V (INFO, TAG, "Payload was NULL"); + ehResult = OC_EH_ERROR; + } + + return ehResult; +} + +OCEntityHandlerResult +OCEntityHandlerCb (OCEntityHandlerFlag flag, + OCEntityHandlerRequest *entityHandlerRequest, + void* callbackParam) +{ + OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag); + (void)callbackParam; + OCEntityHandlerResult ehResult = OC_EH_ERROR; + + OCEntityHandlerResponse response; + memset(&response, 0, sizeof(response)); + + // Validate pointer + if (!entityHandlerRequest) + { + OIC_LOG (ERROR, TAG, "Invalid request pointer"); + return OC_EH_ERROR; + } + + OCRepPayload* payload = NULL; + + if (flag & OC_REQUEST_FLAG) + { + OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG"); + if (entityHandlerRequest) + { + if (OC_REST_GET == entityHandlerRequest->method) + { + OIC_LOG (INFO, TAG, "Received OC_REST_GET from client"); + ehResult = ProcessGetRequest (entityHandlerRequest, &payload); + } + else if (OC_REST_PUT == entityHandlerRequest->method) + { + OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client"); + ehResult = ProcessPutRequest (entityHandlerRequest, &payload); + } + else if (OC_REST_POST == entityHandlerRequest->method) + { + OIC_LOG (INFO, TAG, "Received OC_REST_POST from client"); + ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload); + } + else + { + OIC_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) + { + OIC_LOG(ERROR, TAG, "Error sending response"); + ehResult = OC_EH_ERROR; + } + } + } + } + + OCPayloadDestroy(response.payload); + return ehResult; +} + +OCStackResult displayNumCB(void * ctx, uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN]) +{ + OIC_LOG(INFO, TAG, "IN displayNumCB"); + OIC_LOG(INFO, TAG, "############ mutualVerifNum ############"); + OIC_LOG_BUFFER(INFO, TAG, mutualVerifNum, MUTUAL_VERIF_NUM_LEN); + OIC_LOG(INFO, TAG, "############ mutualVerifNum ############"); + OIC_LOG(INFO, TAG, "OUT displayNumCB"); + return OC_STACK_OK; +} + +OCStackResult confirmNumCB(void * ctx) +{ + for (;;) + { + int userConfirm; + + printf(" > Press 1 for confirmation\n"); + printf(" > Press 0 otherwise\n"); + + for (int ret=0; 1!=ret; ) + { + ret = scanf("%d", &userConfirm); + for (; 0x20<=getchar(); ); // for removing overflow garbage + // '0x20<=code' is character region + } + if (1 == userConfirm) + { + break; + } + else if (0 == userConfirm) + { + return OC_STACK_ERROR; + } + printf(" Entered Wrong Number. Please Enter Again\n"); + } + return OC_STACK_OK; +} + +/* 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); +} + +int main() +{ + struct timespec timeout; + + OIC_LOG(DEBUG, TAG, "OCServer is starting..."); + + // Set callbacks for verification + SetDisplayNumCB(NULL, displayNumCB); + SetUserConfirmCB(NULL, confirmNumCB); + + // Set Verification Option for ownership transfer + // Currently, BOTH display AND confirm + SetVerifyOption((VerifyOptionBitmask_t)(DISPLAY_NUM | USER_CONFIRM)); + + // Initialize Persistent Storage for SVR database + OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink}; + + OCRegisterPersistentStorageHandler(&ps); + + if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK) + { + OIC_LOG(ERROR, TAG, "OCStack init error"); + return 0; + } + + /* + * 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 + OIC_LOG(INFO, TAG, "Entering ocserver main loop..."); + signal(SIGINT, handleSigInt); + while (!gQuitFlag) + { + if (OCProcess() != OC_STACK_OK) + { + OIC_LOG(ERROR, TAG, "OCStack process error"); + return 0; + } + nanosleep(&timeout, NULL); + } + + OIC_LOG(INFO, TAG, "Exiting ocserver main loop..."); + + if (OCStop() != OC_STACK_OK) + { + OIC_LOG(ERROR, TAG, "OCStack process error"); + } + + return 0; +} + +int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower) +{ + if (!uri) + { + OIC_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); + OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res)); + + return 0; +} diff --git a/resource/csdk/security/provisioning/src/ownershiptransfermanager.c b/resource/csdk/security/provisioning/src/ownershiptransfermanager.c index 5e3b2f3..cecd40c 100644 --- a/resource/csdk/security/provisioning/src/ownershiptransfermanager.c +++ b/resource/csdk/security/provisioning/src/ownershiptransfermanager.c @@ -72,6 +72,7 @@ #include "ocpayload.h" #include "payload_logging.h" #include "pkix_interface.h" +#include "oxmverifycommon.h" #define TAG "OIC_OTM" @@ -83,7 +84,14 @@ * List of allowed oxm list. * All oxm methods are allowed as default. */ -static uint8_t g_OxmAllowStatus[OIC_OXM_COUNT] = {ALLOWED_OXM, ALLOWED_OXM, ALLOWED_OXM, NOT_ALLOWED_OXM}; +#ifdef MULTIPLE_OWNER +static uint8_t g_OxmAllowStatus[OXM_IDX_COUNT] = {ALLOWED_OXM, ALLOWED_OXM, ALLOWED_OXM, + ALLOWED_OXM, ALLOWED_OXM, ALLOWED_OXM, + NOT_ALLOWED_OXM}; +#else +static uint8_t g_OxmAllowStatus[OXM_IDX_COUNT] = {ALLOWED_OXM, ALLOWED_OXM, ALLOWED_OXM, + ALLOWED_OXM, ALLOWED_OXM, NOT_ALLOWED_OXM}; +#endif /** * Variables for pointing the OTMContext to be used in the DTLS handshake result callback. @@ -97,11 +105,13 @@ OCStackResult OTMSetOTCallback(OicSecOxm_t oxm, OTMCallbackData_t* callbacks) OIC_LOG(INFO, TAG, "IN OTMSetOTCallback"); VERIFY_NON_NULL(TAG, callbacks, ERROR); + #ifdef MULTIPLE_OWNER - VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm || OIC_PRECONFIG_PIN == oxm), ERROR); + VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm || OIC_PRECONFIG_PIN == oxm || OIC_MV_JUST_WORKS == oxm + || OIC_CON_MFG_CERT == oxm), ERROR); #else - VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm), ERROR); -#endif //MULTIPLE_OWNER + VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > oxm || OIC_MV_JUST_WORKS == oxm || OIC_CON_MFG_CERT == oxm), ERROR); +#endif // MULTIPLE_OWNER switch(oxm) { @@ -134,6 +144,18 @@ OCStackResult OTMSetOTCallback(OicSecOxm_t oxm, OTMCallbackData_t* callbacks) callbacks->createOwnerTransferPayloadCB = CreatePreconfigPinBasedOwnerTransferPayload; break; #endif //MULTIPLE_OWNER + case OIC_MV_JUST_WORKS: + callbacks->loadSecretCB = LoadSecretJustWorksCallback; + callbacks->createSecureSessionCB = CreateSecureSessionJustWorksCallback; + callbacks->createSelectOxmPayloadCB = CreateMVJustWorksSelectOxmPayload; + callbacks->createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload; + break; + case OIC_CON_MFG_CERT: + callbacks->loadSecretCB = PrepareMCertificateCallback; + callbacks->createSecureSessionCB = CreateSecureSessionMCertificateCallback; + callbacks->createSelectOxmPayloadCB = CreateConMCertificateBasedSelectOxmPayload; + callbacks->createOwnerTransferPayloadCB = CreateMCertificateBasedOwnerTransferPayload; + break; default: OIC_LOG_V(ERROR, TAG, "Unknown OxM : %d", (int)oxm); return OC_STACK_INVALID_PARAM; @@ -147,6 +169,34 @@ exit: } /** + * Internal API to convert OxM value to index of oxm allow table. + */ +static OxmAllowTableIdx_t GetOxmAllowTableIdx(OicSecOxm_t oxm) +{ + switch(oxm) + { + case OIC_JUST_WORKS: + return OXM_IDX_JUST_WORKS; + case OIC_RANDOM_DEVICE_PIN: + return OXM_IDX_RANDOM_DEVICE_PIN; + case OIC_MANUFACTURER_CERTIFICATE: + return OXM_IDX_MANUFACTURER_CERTIFICATE; + case OIC_DECENTRALIZED_PUBLIC_KEY: + return OXM_IDX_DECENTRALIZED_PUBLIC_KEY; + case OIC_MV_JUST_WORKS: + return OXM_IDX_MV_JUST_WORKS; + case OIC_CON_MFG_CERT: + return OXM_IDX_CON_MFG_CERT; +#ifdef MULTIPLE_OWNER + case OIC_PRECONFIG_PIN: + return OXM_IDX_PRECONFIG_PIN; +#endif + default: + return OXM_IDX_UNKNOWN; + } +} + +/** * Function to select appropriate provisioning method. * * @param[in] supportedMethods Array of supported methods @@ -158,6 +208,8 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod size_t numberOfMethods, OicSecOxm_t *selectedMethod) { bool isOxmSelected = false; + OxmAllowTableIdx_t oxmIdx = OXM_IDX_UNKNOWN; + OxmAllowTableIdx_t selectedOxmIdx = OXM_IDX_UNKNOWN; OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod"); @@ -169,11 +221,22 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod for(size_t i = 0; i < numberOfMethods; i++) { - if(ALLOWED_OXM == g_OxmAllowStatus[supportedMethods[i]]) + selectedOxmIdx = GetOxmAllowTableIdx(supportedMethods[i]); + if(OXM_IDX_COUNT <= selectedOxmIdx) + { + OIC_LOG(ERROR, TAG, "Invalid oxm index to access OxM allow table"); + return OC_STACK_ERROR; + } + +#ifdef MULTIPLE_OWNER + if(ALLOWED_OXM == g_OxmAllowStatus[selectedOxmIdx] && + OXM_IDX_PRECONFIG_PIN != selectedOxmIdx) +#else + if(ALLOWED_OXM == g_OxmAllowStatus[selectedOxmIdx]) +#endif //MULTIPLE_OWNER { *selectedMethod = supportedMethods[i]; isOxmSelected = true; - break; } } if(!isOxmSelected) @@ -182,20 +245,12 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod return OC_STACK_NOT_ALLOWED_OXM; } - for(size_t i = 0; i < numberOfMethods; i++) - { - if(*selectedMethod < supportedMethods[i] && - ALLOWED_OXM == g_OxmAllowStatus[supportedMethods[i]]) - { - *selectedMethod = supportedMethods[i]; - } - } - OIC_LOG(DEBUG, TAG, "OUT SelectProvisioningMethod"); return OC_STACK_OK; } + /** * Function to select operation mode.This function will return most secure common operation mode. * @@ -465,6 +520,52 @@ void DTLSHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info) false == newDevDoxm->owned && memcmp(&(newDevDoxm->owner), &emptyUuid, sizeof(OicUuid_t)) == 0) { + //In case of Mutual Verified Just-Works, display mutualVerifNum + if (OIC_MV_JUST_WORKS == newDevDoxm->oxmSel) + { + uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0}; + uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0}; + OicUuid_t deviceID = {.id = {0}}; + + //Generate mutualVerifNum + char label[LABEL_LEN] = {0}; + snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS); + if (OC_STACK_OK != GetDoxmDeviceID(&deviceID)) + { + OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID"); + return; + } + + CAResult_t pskRet = CAGenerateOwnerPSK(endpoint, + (uint8_t *)label, + strlen(label), + deviceID.id, sizeof(deviceID.id), + newDevDoxm->deviceID.id, sizeof(newDevDoxm->deviceID.id), + preMutualVerifNum, OWNER_PSK_LENGTH_128); + if (CA_STATUS_OK != pskRet) + { + OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential"); + return; + } + + memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum), + sizeof(mutualVerifNum)); + if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM)) + { + OIC_LOG(ERROR, TAG, "Error while displaying mutualVerifNum"); + return; + } + } + //In case of confirmed manufacturer cert, display message + else if (OIC_CON_MFG_CERT == newDevDoxm->oxmSel) + { + if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, DISPLAY_NUM)) + { + OIC_LOG(ERROR, TAG, "Error while displaying message"); + return; + } + } + //Send request : POST /oic/sec/doxm [{... , "devowner":"PT's UUID"}] res = PostOwnerUuid(otmCtx); if(OC_STACK_OK != res) @@ -796,6 +897,16 @@ static OCStackApplicationResult OwnerUuidUpdateHandler(void *ctx, OCDoHandle UNU { if(otmCtx && otmCtx->selectedDeviceInfo) { + //In case of Mutual Verified Just-Works, wait for user confirmation + if (OIC_MV_JUST_WORKS == otmCtx->selectedDeviceInfo->doxm->oxmSel) + { + res = VerifyOwnershipTransfer(NULL, USER_CONFIRM); + if (OC_STACK_OK != res) + { + SRPResetDevice(otmCtx->selectedDeviceInfo, otmCtx->ctxResultCallback); + } + } + res = SaveOwnerPSK(otmCtx->selectedDeviceInfo); if(OC_STACK_OK != res) { @@ -1914,12 +2025,22 @@ OCStackResult OTMSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus OIC_LOG_V(INFO, TAG, "IN %s : oxm=%d, allow status=%s", __func__, oxm, (allowStatus ? "true" : "false")); - if(OIC_OXM_COUNT <= oxm) +#ifdef MULTIPLE_OWNER + if(OIC_OXM_COUNT <= oxm && OIC_MV_JUST_WORKS != oxm && OIC_PRECONFIG_PIN != oxm && OIC_CON_MFG_CERT != oxm) +#else + if(OIC_OXM_COUNT <= oxm && OIC_MV_JUST_WORKS != oxm && OIC_CON_MFG_CERT != oxm) +#endif { return OC_STACK_INVALID_PARAM; } - g_OxmAllowStatus[oxm] = (allowStatus ? ALLOWED_OXM : NOT_ALLOWED_OXM); + OxmAllowTableIdx_t oxmIdx = GetOxmAllowTableIdx(oxm); + if(OXM_IDX_COUNT <= oxmIdx) + { + OIC_LOG(ERROR, TAG, "Invalid oxm index to access oxm allow table."); + return OC_STACK_ERROR; + } + g_OxmAllowStatus[oxmIdx] = (allowStatus ? ALLOWED_OXM : NOT_ALLOWED_OXM); OIC_LOG_V(INFO, TAG, "OUT %s", __func__); diff --git a/resource/csdk/security/provisioning/src/oxmjustworks.c b/resource/csdk/security/provisioning/src/oxmjustworks.c index 90ee407..1844249 100644 --- a/resource/csdk/security/provisioning/src/oxmjustworks.c +++ b/resource/csdk/security/provisioning/src/oxmjustworks.c @@ -133,3 +133,19 @@ OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx) OIC_LOG(INFO, TAG, "OUT CreateSecureSessionJustWorksCallback"); return OC_STACK_OK; } + +OCStackResult CreateMVJustWorksSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cborPayload, + size_t *cborSize) +{ + if (!otmCtx || !otmCtx->selectedDeviceInfo || !cborPayload || *cborPayload || !cborSize) + { + return OC_STACK_INVALID_PARAM; + } + + otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_MV_JUST_WORKS; + *cborPayload = NULL; + *cborSize = 0; + + return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, cborPayload, cborSize, true); +} + diff --git a/resource/csdk/security/provisioning/src/oxmmanufacturercert.c b/resource/csdk/security/provisioning/src/oxmmanufacturercert.c index 7a24e99..77d658c 100644 --- a/resource/csdk/security/provisioning/src/oxmmanufacturercert.c +++ b/resource/csdk/security/provisioning/src/oxmmanufacturercert.c @@ -53,6 +53,18 @@ OCStackResult CreateMCertificateBasedSelectOxmPayload(OTMContext_t* otmCtx, uint return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true); } +OCStackResult CreateConMCertificateBasedSelectOxmPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size) +{ + if (!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size) + { + return OC_STACK_INVALID_PARAM; + } + + otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_CON_MFG_CERT; + + return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true); +} + OCStackResult CreateMCertificateBasedOwnerTransferPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size) { if (!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size) diff --git a/resource/csdk/security/src/doxmresource.c b/resource/csdk/security/src/doxmresource.c index 0dda37c..05f9d7e 100644 --- a/resource/csdk/security/src/doxmresource.c +++ b/resource/csdk/security/src/doxmresource.c @@ -51,6 +51,7 @@ #include "credresource.h" #include "srmutility.h" #include "pinoxmcommon.h" +#include "oxmverifycommon.h" #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) #include "pkix_interface.h" @@ -1097,7 +1098,7 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe goto exit; } - if (OIC_JUST_WORKS == newDoxm->oxmSel) + if (OIC_JUST_WORKS == newDoxm->oxmSel || OIC_MV_JUST_WORKS == newDoxm->oxmSel) { /* * If current state of the device is un-owned, enable @@ -1106,6 +1107,17 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe */ if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0) { + gDoxm->oxmSel = newDoxm->oxmSel; + //Update new state in persistent storage + if ((UpdatePersistentStorage(gDoxm) == true)) + { + ehRet = OC_EH_OK; + } + else + { + OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage"); + ehRet = OC_EH_ERROR; + } OIC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite"); #if defined(__WITH_DTLS__) || defined(__WITH_TLS__) ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR; @@ -1138,6 +1150,55 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED"); + //In case of Mutual Verified Just-Works, verify mutualVerifNum + if (OIC_MV_JUST_WORKS == newDoxm->oxmSel && false == newDoxm->owned && + previousMsgId != ehRequest->messageID) + { + uint8_t preMutualVerifNum[OWNER_PSK_LENGTH_128] = {0}; + uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN] = {0}; + OicUuid_t deviceID = {.id = {0}}; + + //Generate mutualVerifNum + OCServerRequest * request = GetServerRequestUsingHandle(ehRequest->requestHandle); + + char label[LABEL_LEN] = {0}; + snprintf(label, LABEL_LEN, "%s%s", MUTUAL_VERIF_NUM, OXM_MV_JUST_WORKS); + if (OC_STACK_OK != GetDoxmDeviceID(&deviceID)) + { + OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID"); + ehRet = OC_EH_ERROR; + goto exit; + + } + + CAResult_t pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr, + (uint8_t *)label, + strlen(label), + gDoxm->owner.id, sizeof(gDoxm->owner.id), + gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id), + preMutualVerifNum, OWNER_PSK_LENGTH_128); + if (CA_STATUS_OK != pskRet) + { + OIC_LOG(WARNING, TAG, "Failed to remove the invaild owner credential"); + ehRet = OC_EH_ERROR; + goto exit; + + } + + memcpy(mutualVerifNum, preMutualVerifNum + OWNER_PSK_LENGTH_128 - sizeof(mutualVerifNum), + sizeof(mutualVerifNum)); + + //Wait for user confirmation + if (OC_STACK_OK != VerifyOwnershipTransfer(mutualVerifNum, DISPLAY_NUM | USER_CONFIRM)) + { + ehRet = OC_EH_NOT_ACCEPTABLE; + } + else + { + ehRet = OC_EH_OK; + } + } + #endif // __WITH_DTLS__ or __WITH_TLS__ } } @@ -1242,27 +1303,47 @@ static OCEntityHandlerResult HandleDoxmPostRequest(OCEntityHandlerRequest * ehRe #endif // __WITH_DTLS__ or __WITH_TLS__ } #if defined(__WITH_DTLS__) || defined (__WITH_TLS__) - else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel) + else if (OIC_MANUFACTURER_CERTIFICATE == newDoxm->oxmSel || OIC_CON_MFG_CERT == newDoxm->oxmSel) { - //Save the owner's UUID to derive owner credential - memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)); - gDoxm->oxmSel = newDoxm->oxmSel; - //Update new state in persistent storage - if (UpdatePersistentStorage(gDoxm)) + if (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0) { - ehRet = OC_EH_OK; + //Save the owner's UUID to derive owner credential + memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)); + gDoxm->oxmSel = newDoxm->oxmSel; + //Update new state in persistent storage + if (UpdatePersistentStorage(gDoxm)) + { + ehRet = OC_EH_OK; + } + else + { + OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage"); + ehRet = OC_EH_ERROR; + } + CAResult_t caRes = CAEnableAnonECDHCipherSuite(false); + VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); + OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED"); + + VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR); + VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR); } else { - OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage"); - ehRet = OC_EH_ERROR; + //In case of Confirm Manufacturer Cert, get user confirmation + if (OIC_CON_MFG_CERT == newDoxm->oxmSel && false == newDoxm->owned && + previousMsgId != ehRequest->messageID) + { + if (OC_STACK_OK != VerifyOwnershipTransfer(NULL, USER_CONFIRM)) + { + ehRet = OC_EH_NOT_ACCEPTABLE; + } + else + { + ehRet = OC_EH_OK; + } + } } - CAResult_t caRes = CAEnableAnonECDHCipherSuite(false); - VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); - OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED"); - VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR); - VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR); } #endif // __WITH_DTLS__ or __WITH_TLS__ } diff --git a/resource/csdk/security/src/oxmverifycommon.c b/resource/csdk/security/src/oxmverifycommon.c new file mode 100644 index 0000000..3f13ed7 --- /dev/null +++ b/resource/csdk/security/src/oxmverifycommon.c @@ -0,0 +1,104 @@ +//****************************************************************** +// +// Copyright 2016 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 "logger.h" +#include "base64.h" +#include "securevirtualresourcetypes.h" +#include "srmresourcestrings.h" +#include "cainterface.h" +#include "oxmverifycommon.h" + +#define TAG "OIC_VERIFY_COMMON" + +static VerifyOptionBitmask_t gVerifyOption = (DISPLAY_NUM | USER_CONFIRM); + +static DisplayNumContext_t gDisplayNumContext = { .callback = NULL, .context = NULL }; +static UserConfirmContext_t gUserConfirmContext = { .callback = NULL, .context = NULL }; + +void SetDisplayNumCB(void * ptr, DisplayNumCallback displayNumCB) +{ + if (NULL == displayNumCB) + { + OIC_LOG(ERROR, TAG, "Failed to set callback for displaying mutualVerifNum"); + return; + } + gDisplayNumContext.callback = displayNumCB; + gDisplayNumContext.context = ptr; +} + +void UnsetDisplayNumCB() +{ + gDisplayNumContext.callback = NULL; +} + +void SetUserConfirmCB(void * ptr, UserConfirmCallback userConfirmCB) +{ + if (NULL == userConfirmCB) + { + OIC_LOG(ERROR, TAG, "Failed to set callback to confirm mutualVerifNum"); + return; + } + gUserConfirmContext.callback = userConfirmCB; + gUserConfirmContext.context = ptr; +} + +void UnsetUserConfirmCB() +{ + gUserConfirmContext.callback = NULL; +} + +void SetVerifyOption(VerifyOptionBitmask_t verifyOption) +{ + gVerifyOption = verifyOption; +} + +OCStackResult VerifyOwnershipTransfer(uint8_t mutualVerifNum [MUTUAL_VERIF_NUM_LEN], + VerifyOptionBitmask_t verifyOption) +{ + verifyOption = (VerifyOptionBitmask_t)(verifyOption & gVerifyOption); + if (verifyOption & DISPLAY_NUM) + { + if (!gDisplayNumContext.callback) + { + OIC_LOG(ERROR, TAG, "Callback for displaying verification PIN not registered"); + return OC_STACK_ERROR; + } + if (OC_STACK_OK != gDisplayNumContext.callback(gDisplayNumContext.context, mutualVerifNum)) + { + OIC_LOG(ERROR, TAG, "Failed to display verification PIN"); + return OC_STACK_ERROR; + } + } + if (verifyOption & USER_CONFIRM) + { + if (!gUserConfirmContext.callback) + { + OIC_LOG(ERROR, TAG, "Callback to get user confirmation not registered"); + return OC_STACK_ERROR; + } + if (OC_STACK_OK != gUserConfirmContext.callback(gUserConfirmContext.context)) + { + OIC_LOG(ERROR, TAG, "Failed to get user confirmation"); + return OC_STACK_USER_DENIED_REQ; + } + } + return OC_STACK_OK; +} diff --git a/resource/csdk/security/src/srmresourcestrings.c b/resource/csdk/security/src/srmresourcestrings.c index 55cfe25..d07d938 100644 --- a/resource/csdk/security/src/srmresourcestrings.c +++ b/resource/csdk/security/src/srmresourcestrings.c @@ -174,8 +174,13 @@ const char * OXM_JUST_WORKS = "oic.sec.doxm.jw"; const char * OXM_RANDOM_DEVICE_PIN = "oic.sec.doxm.rdp"; const char * OXM_MANUFACTURER_CERTIFICATE = "oic.sec.doxm.mfgcert"; #ifdef MULTIPLE_OWNER -const char * OXM_PRECONF_PIN = "oic.sec..doxm.pcp"; +const char * OXM_PRECONF_PIN = "oic.sec.doxm.pcp"; #endif //MULTIPLE_OWNER +const char * OXM_MV_JUST_WORKS = "oic.sec.doxm.mvjw"; +const char * OXM_CON_MFG_CERT = "oic.sec.doxm.conmfgcert"; + +//Mutual Verified Just-Works Message Prefix +const char * MUTUAL_VERIF_NUM = "mutualVerifNum"; //Credential data encoding methods const char * OIC_SEC_ENCODING_BASE64 = "oic.sec.encoding.base64"; diff --git a/resource/csdk/security/src/srmutility.c b/resource/csdk/security/src/srmutility.c index 6badf34..93d1e45 100644 --- a/resource/csdk/security/src/srmutility.c +++ b/resource/csdk/security/src/srmutility.c @@ -95,6 +95,10 @@ const char* GetOxmString(OicSecOxm_t oxmType) case OIC_PRECONFIG_PIN: return OXM_PRECONF_PIN; #endif //MULTIPLE_OWNER + case OIC_MV_JUST_WORKS: + return OXM_MV_JUST_WORKS; + case OIC_CON_MFG_CERT: + return OXM_CON_MFG_CERT; default: return NULL; } diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index 4c26bf7..5338a2e 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -1008,6 +1008,9 @@ typedef enum OC_STACK_PRESENCE_DO_NOT_HANDLE, #endif + /** Request is denied by the user*/ + OC_STACK_USER_DENIED_REQ, + /** ERROR code from server */ OC_STACK_FORBIDDEN_REQ, /** 403*/ OC_STACK_INTERNAL_SERVER_ERROR, /** 500*/ diff --git a/resource/include/StringConstants.h b/resource/include/StringConstants.h index 177bd1d..9dbd42c 100644 --- a/resource/include/StringConstants.h +++ b/resource/include/StringConstants.h @@ -126,6 +126,7 @@ namespace OC static const char INCONSISTENT_DB[] = "Data in provisioning DB is inconsistent"; static const char AUTHENTICATION_FAILURE[] = "Authentication failure"; static const char NOT_ALLOWED_OXM[] = "Not allowed ownership transfer method"; + static const char USER_DENIED_REQ[] = "Request denied by User"; static const char PUBLISH_RESOURCE_FAILED[] = "Publish Resource failure"; static const char FORBIDDEN_REQ[] = "Forbidden request"; static const char INTERNAL_SERVER_ERROR[] = "Internal server error"; diff --git a/resource/src/OCException.cpp b/resource/src/OCException.cpp index 6f2f6b6..a21dbc8 100644 --- a/resource/src/OCException.cpp +++ b/resource/src/OCException.cpp @@ -111,6 +111,8 @@ std::string OC::OCException::reason(const OCStackResult sr) return OC::Exception::AUTHENTICATION_FAILURE; case OC_STACK_NOT_ALLOWED_OXM: return OC::Exception::NOT_ALLOWED_OXM; + case OC_STACK_USER_DENIED_REQ: + return OC::Exception::USER_DENIED_REQ; case OC_STACK_FORBIDDEN_REQ: return OC::Exception::FORBIDDEN_REQ; case OC_STACK_INTERNAL_SERVER_ERROR: diff --git a/resource/unittests/OCExceptionTest.cpp b/resource/unittests/OCExceptionTest.cpp index 3c4fcf0..a8c1b79 100644 --- a/resource/unittests/OCExceptionTest.cpp +++ b/resource/unittests/OCExceptionTest.cpp @@ -75,6 +75,7 @@ namespace OC OC_STACK_INCONSISTENT_DB, OC_STACK_AUTHENTICATION_FAILURE, OC_STACK_NOT_ALLOWED_OXM, + OC_STACK_USER_DENIED_REQ, OC_STACK_FORBIDDEN_REQ, OC_STACK_INTERNAL_SERVER_ERROR }; @@ -123,6 +124,7 @@ namespace OC OC::Exception::INCONSISTENT_DB, OC::Exception::AUTHENTICATION_FAILURE, OC::Exception::NOT_ALLOWED_OXM, + OC::Exception::USER_DENIED_REQ, OC::Exception::FORBIDDEN_REQ, OC::Exception::INTERNAL_SERVER_ERROR };