Vendor-specific OTM: Mutual Verified Just-Works & Confirmed MFG Cert
authorJongmin Choi <jminl.choi@samsung.com>
Tue, 6 Dec 2016 09:38:51 +0000 (18:38 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Tue, 6 Dec 2016 11:09:31 +0000 (11:09 +0000)
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 <jminl.choi@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15187
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
24 files changed:
resource/csdk/octbstack_product_secured.def
resource/csdk/security/SConscript
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/include/oxmverifycommon.h [new file with mode: 0644]
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h
resource/csdk/security/provisioning/include/oxm/oxmjustworks.h
resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.dat [new file with mode: 0644]
resource/csdk/security/provisioning/sample/oic_svr_db_server_mvjustworks.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/sample/sampleserver_mvjustworks.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmjustworks.c
resource/csdk/security/provisioning/src/oxmmanufacturercert.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/oxmverifycommon.c [new file with mode: 0644]
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/security/src/srmutility.c
resource/csdk/stack/include/octypes.h
resource/include/StringConstants.h
resource/src/OCException.cpp
resource/unittests/OCExceptionTest.cpp

index c11c83e..65d655f 100644 (file)
@@ -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
index f0b347b..ab26e3a 100644 (file)
@@ -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']
index 5dbf7e0..2076e87 100644 (file)
@@ -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 (file)
index 0000000..a90eaef
--- /dev/null
@@ -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
+
index 3a48a18..46b1af6 100644 (file)
@@ -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
index 2df0540..5778ea0 100644 (file)
@@ -36,6 +36,21 @@ extern "C" {
 typedef struct OTMCallbackData OTMCallbackData_t;\r
 typedef struct OTMContext OTMContext_t;\r
 \r
+\r
+typedef enum OxmAllowTableIdx {\r
+    OXM_IDX_JUST_WORKS = 0,\r
+    OXM_IDX_MV_JUST_WORKS,\r
+#ifdef MULTIPLE_OWNER\r
+    OXM_IDX_PRECONFIG_PIN,\r
+#endif\r
+    OXM_IDX_RANDOM_DEVICE_PIN,\r
+    OXM_IDX_MANUFACTURER_CERTIFICATE,\r
+    OXM_IDX_CON_MFG_CERT,\r
+    OXM_IDX_DECENTRALIZED_PUBLIC_KEY,\r
+    OXM_IDX_COUNT,\r
+    OXM_IDX_UNKNOWN\r
+}OxmAllowTableIdx_t;\r
+\r
 /**\r
  * Do ownership transfer for the unowned devices.\r
  *\r
index 0b9f81e..f2fc932 100644 (file)
@@ -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
index 0a9bca7..cff6467 100644 (file)
@@ -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.
index 947182d..7a4887b 100644 (file)
@@ -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 (file)
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 (file)
index 0000000..fd3fb33
--- /dev/null
@@ -0,0 +1,79 @@
+{\r
+    "acl": {\r
+        "aclist": {\r
+            "aces": [\r
+                {\r
+                    "subjectuuid": "*",\r
+                    "resources": [\r
+                        {\r
+                            "href": "/oic/res",\r
+                            "rel": "",\r
+                            "rt": ["oic.wk.res"],\r
+                            "if": ["oic.if.ll"]\r
+                        },{\r
+                            "href": "/oic/d",\r
+                            "rel": "",\r
+                            "rt": ["oic.wk.d"],\r
+                            "if": ["oic.if.baseline", "oic.if.r"]\r
+                        },{\r
+                            "href": "/oic/p",\r
+                            "rel": "",\r
+                            "rt": ["oic.wk.p"],\r
+                            "if": ["oic.if.baseline", "oic.if.r"]\r
+                        }\r
+                    ],\r
+                    "permission": 2\r
+                },\r
+                {\r
+                    "subjectuuid": "*",\r
+                    "resources": [\r
+                        {\r
+                            "href": "/oic/sec/doxm",\r
+                            "rel": "",\r
+                            "rt": ["oic.r.doxm"],\r
+                            "if": ["oic.if.baseline"]\r
+                        },\r
+                        {\r
+                            "href": "/oic/sec/pstat",\r
+                            "rel": "",\r
+                            "rt": ["oic.r.pstat"],\r
+                            "if": ["oic.if.baseline"]\r
+                        },\r
+                        {\r
+                            "href": "/oic/sec/acl",\r
+                            "rel": "",\r
+                            "rt": ["oic.r.acl"],\r
+                            "if": ["oic.if.baseline"]\r
+                        },\r
+                        {\r
+                            "href": "/oic/sec/cred",\r
+                            "rel": "",\r
+                            "rt": ["oic.r.cred"],\r
+                            "if": ["oic.if.baseline"]\r
+                        }\r
+                    ],\r
+                    "permission": 6\r
+                }\r
+            ]\r
+        },\r
+        "rowneruuid" : "6D766A75-7374-776F-726B-735575696430"\r
+    },\r
+    "pstat": {\r
+        "isop": false,\r
+        "deviceuuid": "6D766A75-7374-776F-726B-735575696430",\r
+        "rowneruuid": "6D766A75-7374-776F-726B-735575696430",\r
+        "cm": 2,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4\r
+        },\r
+    "doxm": {\r
+        "oxms": [0, 65281],\r
+        "oxmsel": 0,\r
+        "sct": 1,\r
+        "owned": false,\r
+        "deviceuuid": "6D766A75-7374-776F-726B-735575696430",\r
+        "devowneruuid": "",\r
+        "rowneruuid": "6D766A75-7374-776F-726B-735575696430"\r
+    }\r
+}\r
index db31e88..90c18b9 100644 (file)
@@ -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 (file)
index 0000000..c45fb2d
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include <signal.h>
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "pinoxmcommon.h"
+#include "oxmverifycommon.h"
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+/** @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;
+}
index 5e3b2f3..cecd40c 100644 (file)
@@ -72,6 +72,7 @@
 #include "ocpayload.h"
 #include "payload_logging.h"
 #include "pkix_interface.h"
+#include "oxmverifycommon.h"
 
 #define TAG "OIC_OTM"
 
  * 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__);
 
index 90ee407..1844249 100644 (file)
@@ -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);
+}
+
index 7a24e99..77d658c 100644 (file)
@@ -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)
index 0dda37c..05f9d7e 100644 (file)
@@ -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 (file)
index 0000000..3f13ed7
--- /dev/null
@@ -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;
+}
index 55cfe25..d07d938 100644 (file)
@@ -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";
index 6badf34..93d1e45 100644 (file)
@@ -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;
     }
index 4c26bf7..5338a2e 100644 (file)
@@ -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*/
index 177bd1d..9dbd42c 100644 (file)
@@ -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";
index 6f2f6b6..a21dbc8 100644 (file)
@@ -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:
index 3c4fcf0..a8c1b79 100644 (file)
@@ -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
             };