[Update] process of provisioning was split.
[platform/upstream/iotivity.git] / service / easy-setup / mediator / richsdk / src / EnrolleeSecurity.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "base64.h"
22
23 #include "EnrolleeSecurity.h"
24 #include "oxmjustworks.h"
25 #include "oxmrandompin.h"
26 #include "EnrolleeResource.h"
27 #include "logger.h"
28 #include "ESException.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31
32 namespace OIC
33 {
34     namespace Service
35     {
36         #define MAX_PERMISSION_LENGTH (5)
37         #define CREATE (1)
38         #define READ (2)
39         #define UPDATE (4)
40         #define DELETE (8)
41         #define NOTIFY (16)
42         #define DASH '-'
43
44         //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5
45         // The value should be accepted from the application as a parameter during ocplatform
46         // config call
47 #define ES_SEC_DISCOVERY_TIMEOUT 5
48
49         EnrolleeSecurity::EnrolleeSecurity(
50         std::shared_ptr< EnrolleeResource > EnrolleeResource,
51         std::string secDbPath)
52         {
53             m_enrolleeSecState = EnrolleeSecState::ES_SEC_UNKNOWN;
54             m_EnrolleeResource = EnrolleeResource;
55         }
56
57         ESResult EnrolleeSecurity::registerCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb,
58                 SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb)
59
60         {
61             m_enrolleeSecStatusCb = enrolleeSecStatusCb;
62             m_securityPinCb = securityPinCb;
63             m_secProvisioningDbPathCb = secProvisioningDbPathCb;
64
65             return ES_ERROR;
66         }
67
68         std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::getEnrollee(DeviceList_t &list)
69         {
70             for (unsigned int i = 0; i < list.size(); i++)
71             {
72                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
73                         list[i]->getDeviceID().c_str());
74                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());
75
76                 //Always return the first element of the unOwned devices. This is considering that Mediator is
77                 // always connected with only one Enrollee for which ownership transfer is being performed.
78                 // Incase of multiple Enrollee devices connected to the Mediator via any OnBoarding method (SoftAp
79                 // for example), the Enrollee devices will be provisioned in the first come first serve basis in the order
80                 // returned by the security layer.
81                 return list[i];
82             }
83             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
84             return NULL;
85         }
86
87         void EnrolleeSecurity::convertUUIDToString(OicUuid_t uuid, std::string& uuidString)
88         {
89             char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
90             { 0, };
91             uint32_t outLen = 0;
92             B64Result b64Ret = B64_OK;
93             std::ostringstream deviceId("");
94
95             b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
96                     base64Buff, sizeof(base64Buff), &outLen);
97
98             if (B64_OK == b64Ret)
99             {
100                 deviceId << base64Buff;
101             }
102             uuidString =  deviceId.str();
103         }
104
105         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
106         {
107             if (hasError)
108             {
109                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
110
111                 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus = nullptr;
112                 std::string uuid;
113                 convertUUIDToString(result->at(0).deviceId, uuid);
114                 securityProvisioningStatus = std::make_shared< SecProvisioningStatus >(uuid,
115                         ES_ERROR);
116
117                 m_enrolleeSecStatusCb(securityProvisioningStatus);
118                 return;
119             }
120             else
121             {
122                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
123                 for (unsigned int i = 0; i < result->size(); i++)
124                 {
125                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
126                     std::string uuid;
127                     convertUUIDToString(result->at(0).deviceId, uuid);
128
129                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
130                     std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus = nullptr;
131                     securityProvisioningStatus = std::make_shared< SecProvisioningStatus >(uuid,
132                             ES_OK);
133
134                     m_enrolleeSecStatusCb(securityProvisioningStatus);
135                     return;
136                 }
137
138                 delete result;
139             }
140         }
141
142         EasySetupState EnrolleeSecurity::performOwnershipTransfer()
143         {
144             EasySetupState ownershipStatus = DEVICE_NOT_OWNED;
145
146             OC::DeviceList_t pUnownedDevList, pOwnedDevList;
147
148             pOwnedDevList.clear();
149             pUnownedDevList.clear();
150
151             OCStackResult result;
152
153             //Developer note : Always test the mediator and enrollee applications on different devices. Running
154             // Mediator and Enrollee in same device will result in returning the same device as already owned.
155             /*result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
156                     pOwnedDevList);
157             if (result != OC_STACK_OK)
158             {
159                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
160                 ownershipStatus = DEVICE_NOT_OWNED;
161                 //Throw exception
162                 throw ESPlatformException(result);
163                 return ownershipStatus;
164             }
165             else if (pOwnedDevList.size())
166             {
167                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
168                         pOwnedDevList.size());
169                 std::shared_ptr< OC::OCSecureResource > ownedDevice = getEnrollee(pOwnedDevList);
170                 if (ownedDevice)
171                 {
172                     ownershipStatus = DEVICE_OWNED;
173                     return ownershipStatus;
174                 }
175             }
176             else
177             {
178                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No owned devices found.");
179                 ownershipStatus = DEVICE_NOT_OWNED;
180             }*/
181
182             result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
183             if (result != OC_STACK_OK)
184             {
185                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
186                 ownershipStatus = DEVICE_NOT_OWNED;
187                 //Throw exception
188                 throw ESPlatformException(result);
189             }
190             else if (pUnownedDevList.size())
191             {
192                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
193                         pUnownedDevList.size());
194
195                 m_unownedDevice = getEnrollee(pUnownedDevList);
196                 if (m_unownedDevice)
197                 {
198                     OTMCallbackData_t justWorksCBData;
199                     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
200                     justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
201                     justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
202                     justWorksCBData.createOwnerTransferPayloadCB =
203                             CreateJustWorksOwnerTransferPayload;
204                     OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
205
206                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
207                             m_unownedDevice->getDeviceID().c_str());
208
209                     OC::ResultCallBack ownershipTransferCb = std::bind(
210                             &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
211                             std::placeholders::_2);
212
213                     if (m_unownedDevice->doOwnershipTransfer(ownershipTransferCb) != OC_STACK_OK)
214                     {
215                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
216                         ownershipStatus = DEVICE_NOT_OWNED;
217                         return ownershipStatus;
218                     }
219                     ownershipStatus = DEVICE_OWNED;
220                 }
221             }
222             else
223             {
224                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unSecure devices found.");
225                 ownershipStatus = DEVICE_NOT_OWNED;
226
227                 return ownershipStatus;
228             }
229
230             return ownershipStatus;
231         }
232     }
233 }