replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / provisioning / examples / provisioningclient.cpp
index ad53059..9c20bdd 100644 (file)
 #include "oic_string.h"
 #include "OCPlatform.h"
 #include "OCApi.h"
-#include "OCProvisioningManager.h"
+#include "OCProvisioningManager.hpp"
 #include "oxmjustworks.h"
 #include "oxmrandompin.h"
+#include "aclresource.h"
+#include "utlist.h"
+#include "mbedtls/x509_crt.h"
 
-#define MAX_URI_LENGTH (64)
 #define MAX_PERMISSION_LENGTH (5)
+#define ACL_RESRC_ARRAY_SIZE (3)
 #define CREATE (1)
 #define READ (2)
 #define UPDATE (4)
@@ -63,9 +66,10 @@ static const OicSecPrm_t  SUPPORTED_PRMS[1] =
 
 using namespace OC;
 
-DeviceList_t pUnownedDevList, pOwnedDevList;
+DeviceList_t pUnownedDevList, pOwnedDevList, pMOTEnabledDeviceList;
 static int transferDevIdx, ask = 1;
 static OicSecPconf_t g_pconf;
+static uint16_t g_credId = 0;
 
 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
 {
@@ -84,10 +88,26 @@ void printMenu()
     std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
     std::cout << "   7. Unlink Devices"<<std::endl;
     std::cout << "   8. Remove Device"<<std::endl;
-    std::cout << "   9. Get Linked Devices"<<std::endl;
-    std::cout << "  10. Get Device Status"<<std::endl;
-    std::cout << "  11. Provision Direct-Pairing Configuration"<<std::endl;
-    std::cout << "  12. Exit loop"<<std::endl;
+    std::cout << "   9. Remove Device using UUID"<<std::endl;
+    std::cout << "  10. Get Linked Devices"<<std::endl;
+    std::cout << "  11. Get Device Status"<<std::endl;
+    std::cout << "  12. Provision Direct-Pairing Configuration"<<std::endl;
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+    std::cout << "  13. Save the Trust Cert. Chain into Cred of SVR"<<std::endl;
+    std::cout << "  14. Provision the Trust Cert. Chain"<<std::endl;
+    std::cout << "  15. Read trust cert chain"<<std::endl;
+#endif // __WITH_DTLS__ || __WITH_TLS__
+#ifdef MULTIPLE_OWNER
+    std::cout << "  16. Change Multiple Ownership Transfer Mode"<<std::endl;
+    std::cout << "  17. Select OxM method for Multiple Ownership Transfer"<<std::endl;
+    std::cout << "  18. Multiple Ownership Transfer Enabled Devices Discovery"<<std::endl;
+    std::cout << "  19. Provision pre configure PIN for Multiple Ownership Transfer Mode"<<std::endl;
+    std::cout << "  20. Add pre configure PIN for Multiple Ownership Transfer Mode"<<std::endl;
+    std::cout << "  21. Remove Sub-Owner from Resource Server"<<std::endl;
+    std::cout << "  22. Remove All Sub-Owner from Resource Server"<<std::endl;
+#endif
+    std::cout << "  30. Configure SVRdb as Self-OwnerShip"<<std::endl;
+    std::cout << "  99. Exit loop"<<std::endl;
 }
 
 void moveTransferredDevice()
@@ -117,6 +137,19 @@ void printUuid(OicUuid_t uuid)
     std::cout<<std::endl;
 }
 
+
+static OCStackResult peerCertCallback(const mbedtls_x509_crt *cert, int depth)
+{
+    OIC_LOG_V(DEBUG, TAG, "Depth : %d", depth);
+    OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
+    OIC_LOG(DEBUG, TAG, "***** Serial number of peer certificate is below *****");
+    OIC_LOG_BUFFER(DEBUG, TAG, cert->serial.p, cert->serial.len);
+    OIC_LOG(DEBUG, TAG, "***** Serial number of peer certificate is above *****");
+    OIC_LOG_V(DEBUG, TAG, "OUT%s", __func__);
+
+    return OC_STACK_OK;
+}
+
 void ownershipTransferCB(PMResultList_t *result, int hasError)
 {
     if (hasError)
@@ -270,19 +303,8 @@ int readDeviceNumber(DeviceList_t &list, int count, int *out)
  */
 static void deleteACL(OicSecAcl_t *acl)
 {
-    if (acl)
-    {
-        /* Clean Resources */
-        for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
-        {
-            OICFree((acl)->resources[i]);
-        }
-        OICFree((acl)->resources);
+    DeleteACLList(acl);
 
-        /* Clean ACL node itself */
-        /* Required only if acl was created in heap */
-        OICFree((acl));
-    }
 }
 
 /**
@@ -369,39 +391,54 @@ static int InputACL(OicSecAcl_t *acl)
     printf("Subject : ");
     ret = scanf("%19ms", &temp_id);
 
+    OicSecAce_t* ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
+    if(NULL == ace)
+    {
+        OIC_LOG(ERROR, TAG, "Error while memory allocation");
+        return -1;
+    }
+    LL_APPEND(acl->aces, ace);
+
     if (1 == ret)
     {
         for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
         {
             if (DASH != temp_id[i])
-                acl->subject.id[j++] = temp_id[i];
+                ace->subjectuuid.id[j++] = temp_id[i];
         }
         OICFree(temp_id);
     }
     else
     {
+        deleteACL(acl);
         printf("Error while input\n");
         return -1;
     }
 
     //Set Resource.
+    size_t resourcesLen = 0;
     printf("Num. of Resource : ");
-    ret = scanf("%zu", &acl->resourcesLen);
-    if ((1 != ret) || (acl->resourcesLen <= 0 || acl->resourcesLen > 50))
+    ret = scanf("%zu", &resourcesLen);
+    if ((1 != ret) || (resourcesLen <= 0 || resourcesLen > 50))
     {
+        deleteACL(acl);
         printf("Error while input\n");
         return -1;
     }
     printf("-URI of resource\n");
-    printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
-    acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
-    if (NULL == acl->resources)
-    {
-        OIC_LOG(ERROR, TAG, "Error while memory allocation");
-        return -1;
-    }
-    for (size_t i = 0; i < acl->resourcesLen; i++)
+    printf("ex)/oic/sh/temp/0 (Max_URI_Length: %d Byte )\n", MAX_URI_LENGTH);
+    for(size_t i = 0; i < resourcesLen; i++)
     {
+        OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+        if(NULL == rsrc)
+        {
+            deleteACL(acl);
+            OIC_LOG(ERROR, TAG, "Error while memory allocation");
+            return -1;
+        }
+
+        LL_APPEND(ace->resources, rsrc);
+
         printf("[%zu]Resource : ", i + 1);
         ret = scanf("%64ms", &temp_rsc);
         if (1 != ret)
@@ -410,14 +447,97 @@ static int InputACL(OicSecAcl_t *acl)
             return -1;
         }
 
-        acl->resources[i] = OICStrdup(temp_rsc);
+        rsrc->href = OICStrdup(temp_rsc);
         OICFree(temp_rsc);
-        if (NULL == acl->resources[i])
+
+        char* rsrc_in = NULL;
+        size_t arrLen = 0;
+        while(1)
         {
-            OIC_LOG(ERROR, TAG, "Error while memory allocation");
-            return -1;
+            printf("         Enter Number of resource type for [%s]: ", rsrc->href);
+            for(int ret=0; 1!=ret; )
+            {
+                ret = scanf("%zu", &arrLen);
+                for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                            // '0x20<=code' is character region
+            }
+            if(ACL_RESRC_ARRAY_SIZE >= arrLen)
+            {
+                break;
+            }
+            printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
         }
+
+        rsrc->typeLen = arrLen;
+        rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
+        if(!rsrc->types)
+        {
+            OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+            goto error;
+        }
+
+        for(unsigned int i = 0; i < arrLen; i++)
+        {
+            printf("         Enter ResourceType[%d] Name (e.g. core.led): ", i+1);
+            for(int ret=0; 1!=ret; )
+            {
+                ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
+                for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                            // '0x20<=code' is character region
+            }
+            rsrc->types[i] = OICStrdup(rsrc_in);
+            OICFree(rsrc_in);
+            if(!rsrc->types[i])
+            {
+                OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
+                goto error;
+            }
+        }
+
+        while(1)
+        {
+            printf("         Enter Number of interface name for [%s]: ", rsrc->href);
+            for(int ret=0; 1!=ret; )
+            {
+                ret = scanf("%zu", &arrLen);
+                for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                            // '0x20<=code' is character region
+            }
+            if(ACL_RESRC_ARRAY_SIZE >= arrLen)
+            {
+                break;
+            }
+            printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
+        }
+
+        rsrc->interfaceLen = arrLen;
+        rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
+        if(!rsrc->interfaces)
+        {
+            OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+            goto error;
+        }
+
+        for(unsigned int i = 0; i < arrLen; i++)
+        {
+            printf("         Enter interfnace[%d] Name (e.g. oic.if.baseline): ", i+1);
+            for(int ret=0; 1!=ret; )
+            {
+                ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
+                for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                            // '0x20<=code' is character region
+            }
+            rsrc->interfaces[i] = OICStrdup(rsrc_in);
+            OICFree(rsrc_in);
+            if(!rsrc->interfaces[i])
+            {
+                OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
+                goto error;
+            }
+        }
+
     }
+
     // Set Permission
     do
     {
@@ -428,9 +548,9 @@ static int InputACL(OicSecAcl_t *acl)
         if (1 != ret)
         {
             printf("Error while input\n");
-            return -1;
+            goto error;
         }
-        ret = CalculateAclPermission(temp_pms, &(acl->permission));
+        ret = CalculateAclPermission(temp_pms, &(ace->permission));
         OICFree(temp_pms);
     } while (0 != ret );
 
@@ -443,7 +563,7 @@ static int InputACL(OicSecAcl_t *acl)
     if (1 != ret)
     {
         printf("Error while input\n");
-        return -1;
+        goto error;
     }
 
     for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
@@ -456,6 +576,10 @@ static int InputACL(OicSecAcl_t *acl)
     OICFree(temp_id);
 
     return 0;
+
+error:
+    DeleteACLList(acl);
+    return -1;
 }
 
 static int InputCredentials(Credential &cred)
@@ -558,7 +682,7 @@ static OicSecPdAcl_t* InputPdACL()
         return NULL;
     }
     printf("-URI of resource\n");
-    printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
+    printf("ex)/oic/sh/temp/0 (Max_URI_Length: %d Byte )\n", MAX_URI_LENGTH);
     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
     if (NULL == acl->resources)
     {
@@ -701,9 +825,135 @@ PVDP_ERROR:
     ask = 1;
 }
 
+OCStackResult displayMutualVerifNumCB(uint8_t mutualVerifNum[MUTUAL_VERIF_NUM_LEN])
+{
+    OIC_LOG(INFO, TAG, "IN displayMutualVerifNumCB");
+    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");
+    return OC_STACK_OK;
+}
+
+OCStackResult confirmMutualVerifNumCB(void)
+{
+    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;
+}
+
+
+
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+static int saveTrustCert(void)
+{
+
+    // call |OCSaveTrustCertChainBin| API actually
+    printf("   Save Trust Cert. Chain into Cred of SVR.\n");
+
+    ByteArray trustCertChainArray = {0, 0};
+
+    FILE *fp = fopen("rootca.crt", "rb+");
+
+    if (fp)
+    {
+        int fsize;
+        if (fseeko(fp, 0, SEEK_END) == 0 && (fsize = ftello(fp)) >= 0)
+        {
+            trustCertChainArray.data = (uint8_t*)OICCalloc(1, fsize);
+            trustCertChainArray.len = fsize;
+            if (NULL == trustCertChainArray.data)
+            {
+                OIC_LOG(ERROR,TAG,"Failed to allocate memory");
+                fclose(fp);
+                return -1;
+            }
+            rewind(fp);
+            fsize = fread(trustCertChainArray.data, 1, fsize, fp);
+            if(0 == fsize)
+            {
+                OIC_LOG(ERROR,TAG,"Read error");
+            }
+        }
+        fclose(fp);
+    }
+    OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.data, trustCertChainArray.len);
+
+    if(OC_STACK_OK != OCSecure::saveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len,
+                        OIC_ENCODING_PEM,&g_credId))
+    {
+        OIC_LOG(ERROR, TAG, "OCSaveTrustCertChainBin API error");
+        return -1;
+    }
+    printf("CredId of Saved Trust Cert. Chain into Cred of SVR : %d.\n", g_credId);
+
+    return 0;
+}
+
+void certChainCallBack(uint16_t credId, uint8_t *trustCertChain,size_t chainSize)
+{
+    OIC_LOG_V(INFO, TAG, "trustCertChain Changed for credId %u", credId);
+    OC_UNUSED(trustCertChain);
+    OC_UNUSED(chainSize);
+    return;
+}
+#endif // __WITH_DTLS__ or __WITH_TLS__
+
+#ifdef MULTIPLE_OWNER
+void MOTMethodCB(PMResultList_t *result, int hasError)
+{
+    if (hasError)
+    {
+        std::cout << "Error!!! in callback"<<std::endl;
+    }
+    else
+    {
+        std::cout<< "callback successfull"<<std::endl;
+        delete result;
+    }
+}
+
+void MOTRemoveSubOwnerCB(PMResultList_t *result, int hasError)
+{
+    if (hasError)
+    {
+        std::cout << "Error!!! in callback"<<std::endl;
+    }
+    else
+    {
+        std::cout<< "callback successfull"<<std::endl;
+        delete result;
+    }
+}
+
+#endif // MULTIPLE_OWNER
+
 int main(void)
 {
-    OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+    OCStackResult result;
+    OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink, NULL, NULL};
 
     // Create PlatformConfig object
     PlatformConfig cfg {
@@ -727,6 +977,20 @@ int main(void)
             return 1;
         }
 
+        result = OCSecure::registerDisplayNumCallback(displayMutualVerifNumCB);
+        if (result != OC_STACK_OK)
+        {
+            std::cout<< "!!Error - setDisplayVerifNumCB failed."<<std::endl;
+        }
+
+        result = OCSecure::registerUserConfirmCallback(confirmMutualVerifNumCB);
+        if (result != OC_STACK_OK)
+        {
+            std::cout<< "!!Error - setConfirmVerifNumCB failed."<<std::endl;
+        }
+
+        OCSecure::setPeerCertCallback(peerCertCallback);
+
         for (int out = 0; !out;)
         {
             while (!ask)
@@ -822,32 +1086,7 @@ int main(void)
 
                         //register callbacks for JUST WORKS and PIN methods
                         std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
-
-                        {
-                            OTMCallbackData_t justWorksCBData;
-                            justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
-                            justWorksCBData.createSecureSessionCB =
-                                CreateSecureSessionJustWorksCallback;
-                            justWorksCBData.createSelectOxmPayloadCB =
-                                CreateJustWorksSelectOxmPayload;
-                            justWorksCBData.createOwnerTransferPayloadCB =
-                                CreateJustWorksOwnerTransferPayload;
-                            OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
-                                    &justWorksCBData, NULL);
-                        }
-
-                        {
-                            OTMCallbackData_t pinBasedCBData;
-                            pinBasedCBData.loadSecretCB = InputPinCodeCallback;
-                            pinBasedCBData.createSecureSessionCB =
-                                CreateSecureSessionRandomPinCallback;
-                            pinBasedCBData.createSelectOxmPayloadCB =
-                                CreatePinBasedSelectOxmPayload;
-                            pinBasedCBData.createOwnerTransferPayloadCB =
-                                CreatePinBasedOwnerTransferPayload;
-                            OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
-                                    &pinBasedCBData, InputPinCB);
-                        }
+                        OCSecure::setInputPinCallback(InputPinCB);
 
                         ask = 0;
                         std::cout << "Transfering ownership for : "<<
@@ -1013,7 +1252,28 @@ int main(void)
                         }
                         break;
                     }
-                case 9: //Get Linked devices
+                case 9: //Remove Device using UUID
+                    {
+                        int index;
+
+                        if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+                        std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+                        ask = 0;
+
+                        if (OCSecure::removeDeviceWithUuid(DISCOVERY_TIMEOUT,
+                                                                       pOwnedDevList[index]->getDeviceID(),
+                                                                       provisionCB)
+                                != OC_STACK_OK)
+                        {
+                            ask = 1;
+                            std::cout <<"removeDevice is failed"<< std::endl;
+                        }
+                        break;
+                    }
+
+                case 10: //Get Linked devices
                     {
                         UuidList_t linkedUuid;
                         unsigned int devNum;
@@ -1058,7 +1318,7 @@ int main(void)
                         }
                         break;
                     }
-                case 10: //Get device' status
+                case 11: //Get device' status
                     {
                         DeviceList_t unownedList, ownedList;
 
@@ -1086,7 +1346,7 @@ int main(void)
                         break;
                     }
 
-                case 11:
+                case 12:
                     {
                         unsigned int devNum;
 
@@ -1116,7 +1376,407 @@ int main(void)
 
                         break;
                     }
-                case 12:
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+                case 13:
+                    {
+                        std::cout<< "registering cert chain change notifier"<<std::endl;
+                        OCSecure::registerTrustCertChangeNotifier(certChainCallBack);
+                        if(saveTrustCert())
+                        {
+                            std::cout<<"Error in saving cert"<<std::endl;
+                        }
+                        std::cout<< "Unregister notifier"<<std::endl;
+                        OCSecure::removeTrustCertChangeNotifier();
+                        break;
+                    }
+                case 14:
+                    {
+                        int index;
+
+                        if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+                        std::cout << "Provision cert for : "<<
+                            pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+                        ask = 0;
+
+                        if (pOwnedDevList[index]->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
+                                                                    g_credId,provisionCB ) != OC_STACK_OK)
+                        {
+                            ask = 1;
+                            std::cout <<"provision cert is failed"<< std::endl;
+                        }
+                        break;
+                    }
+                case 15:
+                    {
+                        if (0==g_credId)
+                        {
+                            std::cout<<"please save cert using option 13.";
+                        }
+                        else
+                        {
+                            uint8_t *trustCertChain = NULL;
+                            size_t chainSize = 0;
+                            if (OC_STACK_OK != OCSecure::readTrustCertChain(g_credId, &trustCertChain,&chainSize))
+                            {
+                                std::cout <<"issue in read trust chain"<< std::endl;
+                            }
+                            else
+                            {
+                                std::cout<<"size of cert : "<<chainSize<<std::endl;
+                            }
+                        }
+                        break;
+                    }
+#endif //__WITH_DTLS__ || __WITH_TLS__
+#ifdef MULTIPLE_OWNER
+                 case 16:
+                    {
+                        if (!pOwnedDevList.size() && !pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Owned device list and MOT device list both are empty."<<std::endl;
+                            break;
+                        }
+                        unsigned int dev_count = 0;
+                        if (pOwnedDevList.size())
+                        {
+                            dev_count = pOwnedDevList.size();
+                            printDevices(pOwnedDevList);
+                        }
+
+                        if (pMOTEnabledDeviceList.size())
+                        {
+                            dev_count += pMOTEnabledDeviceList.size();
+                            for (unsigned int i = 0; i < pMOTEnabledDeviceList.size(); i++ )
+                            {
+                                std::cout << "Device ";
+                                std::cout <<((dev_count - pMOTEnabledDeviceList.size())+ i + 1) ;
+                                std::cout <<" ID : ";
+                                std::cout << pMOTEnabledDeviceList[i]->getDeviceID()<<" From IP: ";
+                                std::cout << pMOTEnabledDeviceList[i]->getDevAddr() << std::endl;
+                            }
+                        }
+
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, to change the mode: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num && dev_count >= dev_num)
+                            {
+                                break;
+                            }
+                            std::cout << "   Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        OicSecMomType_t momType = OIC_MULTIPLE_OWNER_ENABLE;
+                        int mom = 0;
+                        for( ; ; )
+                        {
+                            std::cout <<"   0. Disable Multiple Ownership Transfer"<<std::endl;
+                            std::cout <<"   1. Enable Multiple Ownership Transfer "<<std::endl;
+                            std::cout <<"> Enter Mode of Multiple Ownership Transfer :"<<std::endl;
+                            for(int ret=0; 1!=ret; )
+                            {
+                                ret = scanf("%d", &mom);
+                                for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                                            // '0x20<=code' is character region
+                            }
+                            if(mom == 0)
+                            {
+                                momType = OIC_MULTIPLE_OWNER_DISABLE;
+                                break;
+                            }
+                            if(mom == 1)
+                            {
+                                momType = OIC_MULTIPLE_OWNER_ENABLE;
+                                break;
+                            }
+                            std::cout <<"     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        if (!pOwnedDevList.size())
+                        {
+                            if(OC_STACK_OK != pMOTEnabledDeviceList[dev_num-1]->changeMOTMode(
+                            (const OicSecMomType_t)momType,MOTMethodCB))
+                            {
+                                OIC_LOG(ERROR, TAG, "changeMOTMode API error");
+                            }
+                        }
+                        else
+                        {
+                            if(dev_num <= pOwnedDevList.size())
+                            {
+                                if(OC_STACK_OK != pOwnedDevList[dev_num-1]->changeMOTMode(momType,
+                                MOTMethodCB))
+                                {
+                                    OIC_LOG(ERROR, TAG, "changeMOTMode API error");
+                                }
+                            }
+                            else
+                            {
+                                if(OC_STACK_OK != pMOTEnabledDeviceList[(dev_num -
+                                pOwnedDevList.size() - 1)]->changeMOTMode(momType,
+                                MOTMethodCB))
+                                {
+                                    OIC_LOG(ERROR, TAG, "changeMOTMode API error");
+                                }
+                            }
+                        }
+                         break;
+                    }
+                case 17:
+                    {
+                        if (!pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Please discover the MOT device first. Use option 18"<<std::endl;
+                            break;
+                        }
+
+                        printDevices(pMOTEnabledDeviceList);
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, for MOT Device: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num &&  pMOTEnabledDeviceList.size() >=dev_num)
+                            {
+                                break;
+                            }
+                                              std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        int oxm = 0;
+                        OicSecOxm_t secOxm = OIC_PRECONFIG_PIN;
+                        std::cout << "Select method for  Multiple Ownership Transfer: "<<std::endl;
+                        for( ; ; )
+                        {
+                            std::cout << "  0. Random PIN OxM "<<std::endl;
+                            std::cout << "  1. Pre-Configured PIN OxM "<<std::endl;
+                            std::cout << "   > Enter Number of  OxM for Multiple Ownership Transfer : "<<std::endl;
+                            std::cin >> oxm;
+                            if(0 == oxm)
+                            {
+                                secOxm = OIC_RANDOM_DEVICE_PIN;
+                                break;
+                            }
+                            if(1 == oxm)
+                            {
+                                secOxm = OIC_PRECONFIG_PIN;
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        if(OC_STACK_OK != pMOTEnabledDeviceList[dev_num-1]->selectMOTMethod((const OicSecOxm_t)secOxm,
+                                              MOTMethodCB))
+                        {
+                            OIC_LOG(ERROR, TAG, "selectMOTMethod API error");
+                        }
+                         break;
+                    }
+                case 18:
+                    {
+                        pMOTEnabledDeviceList.clear();
+                        std::cout << "Started MOT Enabled device discovery..." <<std::endl;
+                        OCStackResult result = OCSecure::discoverMultipleOwnerEnabledDevices
+                            (DISCOVERY_TIMEOUT, pMOTEnabledDeviceList);
+                        if (result != OC_STACK_OK)
+                        {
+                            std::cout<< "!!Error - MOT Enabled dev Discovery failed."<<std::endl;
+                        }
+                        else if (pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Found MOT enabled devices, count = " <<
+                                pMOTEnabledDeviceList.size() << std::endl;
+                            printDevices(pMOTEnabledDeviceList);
+                        }
+                        else
+                        {
+                            std::cout <<"No MOT enabled Secure devices found"<<std::endl;
+                        }
+                        break;
+                    }
+                case 19:
+                    {
+                        if (!pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Please discover the MOT device first. Use option 16"<<std::endl;
+                            break;
+                        }
+
+                        printDevices(pMOTEnabledDeviceList);
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, for MOT Device: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num && pMOTEnabledDeviceList.size() >=dev_num)
+                            {
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        char preconfigPin[9] = {0};
+                        std::cout << "   > Input the 8 digit PreconfigPin (e.g. 12341234) :" <<std::endl;
+                        for(int ret=0; 1!=ret; )
+                        {
+                            ret = scanf("%8s", preconfigPin);
+                            for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                                        // '0x20<=code' is character region
+                        }
+                        size_t preconfPinLength = strlen(preconfigPin);
+                        if(OC_STACK_OK != pMOTEnabledDeviceList[dev_num-1]->provisionPreconfPin(preconfigPin,
+                            preconfPinLength, MOTMethodCB))
+                        {
+                            OIC_LOG(ERROR, TAG, "provisionPreconfPin API error");
+                        }
+                        break;
+                    }
+                    case 20:
+                    {
+                        if (!pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Please discover the MOT device first. Use option 16"<<std::endl;
+                            break;
+                        }
+
+                        printDevices(pMOTEnabledDeviceList);
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, for MOT Device: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num && pMOTEnabledDeviceList.size() >=dev_num)
+                            {
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        char preconfPIN[9] = {0};
+                        std::cout << "   > Input the 8 digit preconfPIN (e.g. 12341234) :" <<std::endl;
+                        for(int ret=0; 1!=ret; )
+                        {
+                            ret = scanf("%8s", preconfPIN);
+                            for( ; 0x20<=getchar(); );  // for removing overflow garbages
+                                                        // '0x20<=code' is character region
+                        }
+                        size_t preconfPinLength = strlen(preconfPIN);
+                        if(OC_STACK_OK != pMOTEnabledDeviceList[dev_num-1]->addPreconfigPIN(preconfPIN,
+                            preconfPinLength))
+                        {
+                            OIC_LOG(ERROR, TAG, "addPreconfigPIN API error");
+                        }
+                        break;
+                    }
+                    case 21: //Remove sub-owner
+                    {
+                        if (!pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Please discover the MOT device first. Use option 16"<<std::endl;
+                            break;
+                        }
+
+                        printDevices(pMOTEnabledDeviceList);
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, for MOT Device: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num && pMOTEnabledDeviceList.size() >=dev_num)
+                            {
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        UuidList_t subOwenrList;
+                        pMOTEnabledDeviceList[dev_num - 1]->getSubOwnerList(subOwenrList);
+                        if (0 == subOwenrList.size())
+                        {
+                            std::cout << "SubOwner List is empty."<<std::endl;
+                        }
+                        else
+                        {
+                            //display the Linked devices (UUIDs)
+                            for(unsigned int i = 0; i < subOwenrList.size(); i++)
+                            {
+                                printUuid(subOwenrList[i]);
+                            }
+                        }
+                        unsigned int so_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter SubOwner Number to be Removed: "<<std::endl;
+                            std::cin >> so_num;
+                            if(0 < so_num && subOwenrList.size() >=so_num)
+                            {
+                                pMOTEnabledDeviceList[dev_num - 1]->removeSubOwner(&subOwenrList[so_num], MOTRemoveSubOwnerCB);
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        break;
+                    }
+                    case 22: //Remove all sub-owner
+                    {
+                        if (!pMOTEnabledDeviceList.size())
+                        {
+                            std::cout <<"Please discover the MOT device first. Use option 16"<<std::endl;
+                            break;
+                        }
+
+                        printDevices(pMOTEnabledDeviceList);
+                        // select device
+                        unsigned int dev_num = 0;
+                        for( ; ; )
+                        {
+                            std::cout << "Enter Device Number, for MOT Device: "<<std::endl;
+                            std::cin >> dev_num;
+                            if(0 < dev_num && pMOTEnabledDeviceList.size() >=dev_num)
+                            {
+                                break;
+                            }
+                            std::cout << "     Entered Wrong Number. Please Enter Again"<<std::endl;
+                        }
+
+                        UuidList_t subOwenrList;
+                        pMOTEnabledDeviceList[dev_num - 1]->getSubOwnerList(subOwenrList);
+                        if (0 == subOwenrList.size())
+                        {
+                            std::cout << "SubOwner List is empty."<<std::endl;
+                        }
+                        else
+                        {
+                            pMOTEnabledDeviceList[dev_num - 1]->removeAllSubOwner(MOTRemoveSubOwnerCB);
+                        }
+                        break;
+                    }
+#endif //MULTIPLE_OWNER
+                case 30:
+                    {
+                        OCStackResult result;
+                        result = OCSecure::configSelfOwnership();
+                        if (OC_STACK_OK != result)
+                        {
+                            std::cout<<"configSelfOwnership API error. Please check SVR DB"<<std::endl;
+                        }
+                        else
+                        {
+                            std::cout<<"Success to configures SVR DB as self-ownership"<<std::endl;
+                        }
+                        break;
+                    }
+                case 99:
                 default:
                     out = 1;
                     break;