Merge branch 'master' into extended-easysetup
[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< OC::OCResource > resource,
51         std::string secDbPath)
52         {
53             m_ocResource = resource;
54         }
55
56         void EnrolleeSecurity::registerCallbackHandler(SecurityProvStatusCb securityProvStatusCb,
57                 SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb)
58         {
59             m_securityProvStatusCb = securityProvStatusCb;
60             m_securityPinCb = securityPinCb;
61             m_secProvisioningDbPathCb = secProvisioningDbPathCb;
62         }
63
64         std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::getEnrollee(DeviceList_t &list)
65         {
66             for (unsigned int i = 0; i < list.size(); i++)
67             {
68                 if(m_ocResource->sid() == list[i]->getDeviceID().c_str())
69                 {
70                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1,
71                             list[i]->getDeviceID().c_str());
72                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str());
73                     return list[i];
74                 }
75                 //Always return the first element of the unOwned devices. This is considering that Mediator is
76                 // always connected with only one Enrollee for which ownership transfer is being performed.
77                 // Incase of multiple Enrollee devices connected to the Mediator via any OnBoarding method (SoftAp
78                 // for example), the Enrollee devices will be provisioned in the first come first serve basis in the order
79                 // returned by the security layer.
80
81             }
82             OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! DeviceList_t is NULL");
83             return NULL;
84         }
85
86         void EnrolleeSecurity::convertUUIDToString(OicUuid_t uuid, std::string& uuidString)
87         {
88             char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] =
89             { 0, };
90             uint32_t outLen = 0;
91             B64Result b64Ret = B64_OK;
92             std::ostringstream deviceId("");
93
94             b64Ret = b64Encode(uuid.id, sizeof(uuid.id),
95                     base64Buff, sizeof(base64Buff), &outLen);
96
97             if (B64_OK == b64Ret)
98             {
99                 deviceId << base64Buff;
100             }
101             uuidString =  deviceId.str();
102         }
103
104         void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError)
105         {
106             if (hasError)
107             {
108                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer");
109
110                 std::string uuid;
111                 convertUUIDToString(result->at(0).deviceId, uuid);
112                 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
113                         std::make_shared< SecProvisioningStatus >(uuid, ES_ERROR);
114                 m_securityProvStatusCb(securityProvisioningStatus);
115                 return;
116             }
117             else
118             {
119                 OIC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "ownershipTransferCb : Received provisioning results: ");
120                 for (unsigned int i = 0; i < result->size(); i++)
121                 {
122                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res);
123                     std::string uuid;
124                     convertUUIDToString(result->at(0).deviceId, uuid);
125
126                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",uuid.c_str());
127                     std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
128                             std::make_shared< SecProvisioningStatus >(uuid, ES_OK);
129                     m_securityProvStatusCb(securityProvisioningStatus);
130                     return;
131                 }
132
133                 delete result;
134             }
135         }
136
137         void EnrolleeSecurity::performOwnershipTransfer()
138         {
139             OC::DeviceList_t pUnownedDevList, pOwnedDevList;
140
141             pOwnedDevList.clear();
142             pUnownedDevList.clear();
143
144             OCStackResult result;
145             /*
146             result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT,
147                     pOwnedDevList);
148             if (result != OC_STACK_OK)
149             {
150                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed.");
151                 //Throw exception
152                 throw ESPlatformException(result);
153             }
154             else if (pOwnedDevList.size())
155             {
156                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d",
157                         pOwnedDevList.size());
158                 std::shared_ptr< OC::OCSecureResource > ownedDevice = getEnrollee(pOwnedDevList);
159
160                 if (ownedDevice)
161                 {
162                     std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
163                             std::make_shared< SecProvisioningStatus >(ownedDevice->getDeviceID(), ES_OK);
164                     m_securityProvStatusCb(securityProvisioningStatus);
165                     return;
166                 }
167             }
168             */
169             result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, pUnownedDevList);
170             if (result != OC_STACK_OK)
171             {
172                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed.");
173                 //Throw exception
174                 throw ESPlatformException(result);
175             }
176             else if (pUnownedDevList.size())
177             {
178                 OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d",
179                         pUnownedDevList.size());
180
181                 m_unownedDevice = getEnrollee(pUnownedDevList);
182                 if (m_unownedDevice)
183                 {
184                     OTMCallbackData_t justWorksCBData;
185                     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
186                     justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
187                     justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
188                     justWorksCBData.createOwnerTransferPayloadCB =
189                             CreateJustWorksOwnerTransferPayload;
190                     OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL);
191
192                     OIC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ",
193                             m_unownedDevice->getDeviceID().c_str());
194
195                     OC::ResultCallBack ownershipTransferCb = std::bind(
196                             &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1,
197                             std::placeholders::_2);
198
199                     result = m_unownedDevice->doOwnershipTransfer(ownershipTransferCb);
200                     if (result != OC_STACK_OK)
201                     {
202                         OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed");
203                         throw ESPlatformException(result);
204                     }
205                 }
206             }
207             else
208             {
209                 OIC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No unOwned devices found.");
210                 throw ESException("No unOwned devices found.");
211             }
212         }
213     }
214 }