Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / resource / provisioning / src / OCProvisioningManager.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 "ocstack.h"
22 #include "srmutility.h"
23 #include "base64.h"
24 #include "OCProvisioningManager.h"
25
26 namespace OC
27 {
28     OCStackResult OCSecure::provisionInit(const std::string& dbPath)
29     {
30         OCStackResult result;
31         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
32
33         if (cLock)
34         {
35             std::lock_guard<std::recursive_mutex> lock(*cLock);
36             result = OCInitPM(dbPath.c_str());
37         }
38         else
39         {
40             oclog() <<"Mutex not found";
41             result = OC_STACK_ERROR;
42         }
43
44         return result;
45     }
46
47     OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
48             DeviceList_t &list)
49     {
50         OCStackResult result;
51         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
52         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
53         auto cLock = csdkLock.lock();
54
55         if (cLock)
56         {
57             std::lock_guard<std::recursive_mutex> lock(*cLock);
58             result = OCDiscoverUnownedDevices(timeout, &pDevList);
59             if (result == OC_STACK_OK)
60             {
61                 // Create DeviceList of OCSecureResource's
62                 pCurDev = pDevList;
63                 while (pCurDev)
64                 {
65                     tmp = pCurDev;
66                     list.push_back(std::shared_ptr<OCSecureResource>(
67                                 new OCSecureResource(csdkLock, pCurDev)));
68                     pCurDev = pCurDev->next;
69                     tmp->next = nullptr;
70                 }
71             }
72             else
73             {
74                 oclog() <<"Unowned device discovery failed!";
75             }
76         }
77         else
78         {
79             oclog() <<"Mutex not found";
80             result = OC_STACK_ERROR;
81         }
82
83         return result;
84     }
85
86     OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
87             DeviceList_t &list)
88     {
89         OCStackResult result;
90         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
91         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
92         auto cLock = csdkLock.lock();
93
94         if (cLock)
95         {
96             std::lock_guard<std::recursive_mutex> lock(*cLock);
97             result = OCDiscoverOwnedDevices(timeout, &pDevList);
98             if (result == OC_STACK_OK)
99             {
100                 pCurDev = pDevList;
101                 while (pCurDev)
102                 {
103                     tmp = pCurDev;
104                     list.push_back(std::shared_ptr<OCSecureResource>(
105                                 new OCSecureResource(csdkLock, pCurDev)));
106                     pCurDev = pCurDev->next;
107                     tmp->next = nullptr;
108                 }
109             }
110             else
111             {
112                 oclog() <<"Owned device discovery failed!";
113             }
114         }
115         else
116         {
117             oclog() <<"Mutex not found";
118             result = OC_STACK_ERROR;
119         }
120
121         return result;
122     }
123
124     OCStackResult OCSecure::discoverSingleDevice(unsigned short timeout,
125             const OicUuid_t* deviceID,
126             std::shared_ptr<OCSecureResource> &foundDevice)
127     {
128         OCStackResult result;
129         OCProvisionDev_t *pDev = nullptr;
130         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
131         auto cLock = csdkLock.lock();
132
133         if (cLock)
134         {
135             std::lock_guard<std::recursive_mutex> lock(*cLock);
136             result = OCDiscoverSingleDevice(timeout, deviceID, &pDev);
137             if (result == OC_STACK_OK)
138             {
139                 if (pDev)
140                 {
141                     foundDevice.reset(new OCSecureResource(csdkLock, pDev));
142                 }
143                 else
144                 {
145                     oclog() <<"Not found Secure resource!";
146                     foundDevice.reset();
147                 }
148             }
149             else
150             {
151                 oclog() <<"Secure resource discovery failed!";
152             }
153         }
154         else
155         {
156             oclog() <<"Mutex not found";
157             result = OC_STACK_ERROR;
158         }
159
160         return result;
161     }
162
163     OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
164             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
165     {
166         if (NULL == callbackData || oxm >= OIC_OXM_COUNT)
167         {
168             oclog() <<"Invalid callbackData or OXM type";
169             return OC_STACK_INVALID_PARAM;
170         }
171
172         if ((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
173         {
174             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
175             return OC_STACK_INVALID_PARAM;
176         }
177
178         OCStackResult result;
179         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
180
181         if (cLock)
182         {
183             std::lock_guard<std::recursive_mutex> lock(*cLock);
184             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
185             if (result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm))
186             {
187                 SetInputPinCB(inputPin);
188             }
189         }
190         else
191         {
192             oclog() <<"Mutex not found";
193             result = OC_STACK_ERROR;
194         }
195
196         return result;
197
198     }
199
200     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
201             DeviceList_t &ownedDevList,
202             DeviceList_t &unownedDevList)
203     {
204         OCStackResult result = OC_STACK_OK;
205         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
206         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
207         auto cLock = csdkLock.lock();
208
209         if (cLock)
210         {
211             std::lock_guard<std::recursive_mutex> lock(*cLock);
212
213             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
214
215             if (result == OC_STACK_OK)
216             {
217                 dev = owned;
218                 while (dev)
219                 {
220                     tmp = dev;
221                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
222                                 new OCSecureResource(csdkLock, dev)));
223                     dev = dev->next;
224                     tmp->next = nullptr;
225                 }
226
227                 dev = unowned;
228                 while (dev)
229                 {
230                     tmp = dev;
231                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
232                                 new OCSecureResource(csdkLock,  dev)));
233                     dev = dev->next;
234                     tmp->next = nullptr;
235                 }
236             }
237         }
238         else
239         {
240             oclog() <<"Mutex not found";
241             result = OC_STACK_ERROR;
242         }
243
244         return result;
245     }
246
247     OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin)
248     {
249         if (!displayPin)
250         {
251             oclog() <<"displayPin can't be null";
252             return OC_STACK_INVALID_PARAM;
253         }
254
255         OCStackResult result = OC_STACK_OK;
256         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
257
258         if (cLock)
259         {
260             std::lock_guard<std::recursive_mutex> lock(*cLock);
261             SetGeneratePinCB(displayPin);
262         }
263         else
264         {
265             oclog() <<"Mutex not found";
266             result = OC_STACK_ERROR;
267         }
268
269         return result;
270     }
271
272     OCStackResult OCSecure::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
273             std::string uuid,
274             ResultCallBack resultCallback)
275     {
276         if (!resultCallback)
277         {
278             oclog() << "Result calback can't be null";
279             return OC_STACK_INVALID_CALLBACK;
280         }
281
282         OCStackResult result;
283         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
284
285         if (cLock)
286         {
287             ProvisionContext* context = new ProvisionContext(resultCallback);
288
289             std::lock_guard<std::recursive_mutex> lock(*cLock);
290
291             OicUuid_t targetDev;
292             result = ConvertStrToUuid(uuid.c_str(), &targetDev);
293             if(OC_STACK_OK == result)
294             {
295                 result = OCRemoveDeviceWithUuid(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
296                         &targetDev, &OCSecureResource::callbackWrapper);
297             }
298             else
299             {
300                 oclog() <<"Can not convert struuid to uuid";
301             }
302         }
303         else
304         {
305             oclog() <<"Mutex not found";
306             result = OC_STACK_ERROR;
307         }
308         return result;
309     }
310
311 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
312     OCStackResult OCSecure::saveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
313                                         OicEncodingType_t encodingType, uint16_t *credId)
314     {
315         if (!trustCertChain)
316         {
317             oclog() <<"trustCertChain can't be null";
318             return OC_STACK_INVALID_PARAM;
319         }
320         if (!credId)
321         {
322             oclog() <<"cred ID can not be null";
323             return OC_STACK_INVALID_PARAM;
324         }
325
326         OCStackResult result;
327         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
328
329         if (cLock)
330         {
331             std::lock_guard<std::recursive_mutex> lock(*cLock);
332             result = OCSaveTrustCertChain(trustCertChain, chainSize, encodingType, credId );
333         }
334         else
335         {
336             oclog() <<"Mutex not found";
337             result = OC_STACK_ERROR;
338         }
339         return result;
340     }
341 #endif // __WITH_DTLS__ || __WITH_TLS__
342
343     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
344     {
345         PMResultList_t *results = nullptr;
346         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
347
348         try
349         {
350             results = new PMResultList_t;
351         }
352         catch (std::bad_alloc& e)
353         {
354             oclog() <<"Bad alloc exception";
355             return;
356         }
357
358         for (int i = 0; i < nOfRes; i++)
359         {
360             results->push_back(arr[i]);
361         }
362
363         std::thread exec(context->callback, results, hasError);
364         exec.detach();
365
366         delete context;
367     }
368
369     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
370                                         devPtr(nullptr)
371     {
372     }
373
374     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
375             OCProvisionDev_t *dPtr)
376         :m_csdkLock(csdkLock), devPtr(dPtr)
377     {
378     }
379
380     OCSecureResource::~OCSecureResource()
381     {
382         if (devPtr)
383         {
384             OCDeleteDiscoveredDevices(devPtr);
385         }
386     }
387
388     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
389     {
390         if (!resultCallback)
391         {
392             oclog() <<"Result callback can't be null";
393             return OC_STACK_INVALID_CALLBACK;
394         }
395
396         OCStackResult result;
397         auto cLock = m_csdkLock.lock();
398
399         if (cLock)
400         {
401             ProvisionContext* context = new ProvisionContext(resultCallback);
402
403             std::lock_guard<std::recursive_mutex> lock(*cLock);
404             result = OCDoOwnershipTransfer(static_cast<void*>(context),
405                     devPtr, &OCSecureResource::callbackWrapper);
406         }
407         else
408         {
409             oclog() <<"Mutex not found";
410             result = OC_STACK_ERROR;
411         }
412         return result;
413     }
414
415     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
416             ResultCallBack resultCallback)
417     {
418         if (!acl)
419         {
420             oclog() <<"ACL can't be null";
421             return OC_STACK_INVALID_PARAM;
422         }
423         if (!resultCallback)
424         {
425             oclog() <<"result callback can not be null";
426             return OC_STACK_INVALID_CALLBACK;
427         }
428
429         OCStackResult result;
430         auto cLock = m_csdkLock.lock();
431
432         if (cLock)
433         {
434             ProvisionContext* context = new ProvisionContext(resultCallback);
435
436             std::lock_guard<std::recursive_mutex> lock(*cLock);
437             result = OCProvisionACL(static_cast<void*>(context),
438                     devPtr, const_cast<OicSecAcl_t*>(acl),
439                     &OCSecureResource::callbackWrapper);
440         }
441         else
442         {
443             oclog() <<"Mutex not found";
444             result = OC_STACK_ERROR;
445         }
446         return result;
447     }
448
449     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
450             const OCSecureResource &device2, ResultCallBack resultCallback)
451     {
452         if (!resultCallback)
453         {
454             oclog() << "Result calback can't be null";
455             return OC_STACK_INVALID_CALLBACK;
456         }
457
458         OCStackResult result;
459         auto cLock = m_csdkLock.lock();
460
461         if (cLock)
462         {
463             ProvisionContext* context = new ProvisionContext(resultCallback);
464
465             std::lock_guard<std::recursive_mutex> lock(*cLock);
466             result = OCProvisionCredentials(static_cast<void*>(context),
467                     cred.getCredentialType(),
468                     cred.getCredentialKeySize(),
469                     devPtr, device2.getDevPtr(),
470                     &OCSecureResource::callbackWrapper);
471         }
472         else
473         {
474             oclog() <<"Mutex not found";
475             result = OC_STACK_ERROR;
476         }
477         return result;
478     }
479
480     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
481             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
482             ResultCallBack resultCallback)
483     {
484         if (!resultCallback)
485         {
486             oclog() << "Result callback can not be null";
487             return OC_STACK_INVALID_CALLBACK;
488         }
489
490         OCStackResult result;
491         auto cLock = m_csdkLock.lock();
492
493         if (cLock)
494         {
495             ProvisionContext* context = new ProvisionContext(resultCallback);
496
497             std::lock_guard<std::recursive_mutex> lock(*cLock);
498             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
499                     cred.getCredentialType(),
500                     cred.getCredentialKeySize(),
501                     devPtr, const_cast<OicSecAcl_t*>(acl1),
502                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
503                     &OCSecureResource::callbackWrapper);
504         }
505         else
506         {
507             oclog() <<"Mutex not found";
508             result = OC_STACK_ERROR;
509         }
510         return result;
511     }
512
513     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
514             ResultCallBack resultCallback)
515     {
516         if (!resultCallback)
517         {
518             oclog() << "Result calback can't be null";
519             return OC_STACK_INVALID_CALLBACK;
520         }
521
522         OCStackResult result;
523         auto cLock = m_csdkLock.lock();
524
525         if (cLock)
526         {
527             ProvisionContext* context = new ProvisionContext(resultCallback);
528
529             std::lock_guard<std::recursive_mutex> lock(*cLock);
530
531             result = OCUnlinkDevices(static_cast<void*>(context),
532                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
533         }
534         else
535         {
536             oclog() <<"Mutex not found";
537             result = OC_STACK_ERROR;
538         }
539         return result;
540     }
541
542     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
543             ResultCallBack resultCallback)
544     {
545         if (!resultCallback)
546         {
547             oclog() << "Result calback can't be null";
548             return OC_STACK_INVALID_CALLBACK;
549         }
550
551         OCStackResult result;
552         auto cLock = m_csdkLock.lock();
553
554         if (cLock)
555         {
556             ProvisionContext* context = new ProvisionContext(resultCallback);
557
558             std::lock_guard<std::recursive_mutex> lock(*cLock);
559
560             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
561                     devPtr, &OCSecureResource::callbackWrapper);
562         }
563         else
564         {
565             oclog() <<"Mutex not found";
566             result = OC_STACK_ERROR;
567         }
568         return result;
569     }
570
571     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
572     {
573         OCStackResult result;
574         size_t numOfDevices = -1;
575         auto devUuid = devPtr->doxm->deviceID;
576         auto cLock = m_csdkLock.lock();
577
578         if (cLock)
579         {
580             std::lock_guard<std::recursive_mutex> lock(*cLock);
581
582             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
583             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
584             if (result == OC_STACK_OK)
585             {
586                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
587                 {
588                     uuidList.push_back(tmp->dev);
589                 }
590                 OCDeleteUuidList(linkedDevs);
591             }
592         }
593         else
594         {
595             oclog() <<"Mutex not found";
596             result = OC_STACK_ERROR;
597         }
598         return result;
599     }
600
601     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
602             ResultCallBack resultCallback)
603     {
604         if (!pconf)
605         {
606             oclog() <<"PCONF can't be null";
607             return OC_STACK_INVALID_PARAM;
608         }
609         if (!resultCallback)
610         {
611             oclog() <<"result callback can not be null";
612             return OC_STACK_INVALID_CALLBACK;
613         }
614
615         OCStackResult result;
616         auto cLock = m_csdkLock.lock();
617
618         if (cLock)
619         {
620             ProvisionContext* context = new ProvisionContext(resultCallback);
621
622             std::lock_guard<std::recursive_mutex> lock(*cLock);
623             result = OCProvisionDirectPairing(static_cast<void*>(context),
624                     devPtr, const_cast<OicSecPconf_t*>(pconf),
625                     &OCSecureResource::callbackWrapper);
626         }
627         else
628         {
629             oclog() <<"Mutex not found";
630             result = OC_STACK_ERROR;
631         }
632         return result;
633     }
634
635 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
636     OCStackResult OCSecureResource::provisionTrustCertChain(OicSecCredType_t type, uint16_t credId,
637                     ResultCallBack resultCallback)
638     {
639         if (SIGNED_ASYMMETRIC_KEY != type)
640         {
641             oclog() <<"Invalid key type";
642             return OC_STACK_INVALID_PARAM;
643         }
644         if (!resultCallback)
645         {
646             oclog() <<"result callback can not be null";
647             return OC_STACK_INVALID_CALLBACK;
648         }
649
650         OCStackResult result;
651         auto cLock = m_csdkLock.lock();
652
653         if (cLock)
654         {
655             ProvisionContext* context = new ProvisionContext(resultCallback);
656
657             std::lock_guard<std::recursive_mutex> lock(*cLock);
658             result = OCProvisionTrustCertChain(static_cast<void*>(context),
659                     type, credId, devPtr,
660                     &OCSecureResource::callbackWrapper);
661         }
662         else
663         {
664             oclog() <<"Mutex not found";
665             result = OC_STACK_ERROR;
666         }
667         return result;
668     }
669 #endif // __WITH_DTLS__ or __WITH_TLS__
670
671     std::string OCSecureResource::getDeviceID()
672     {
673         std::ostringstream deviceId("");
674         char *devID = nullptr;
675
676         validateSecureResource();
677
678         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
679         {
680             deviceId << devID;
681             free(devID);
682         }
683         else
684         {
685             oclog() <<"Can not convert uuid to struuid";
686         }
687         return deviceId.str();
688     }
689
690     OCProvisionDev_t* OCSecureResource::getDevPtr() const
691     {
692         return devPtr;
693     }
694
695     std::string OCSecureResource::getDevAddr()
696     {
697         validateSecureResource();
698         std::string ipAddr(devPtr->endpoint.addr);
699         return ipAddr;
700     }
701
702     int OCSecureResource::getDeviceStatus()
703     {
704         validateSecureResource();
705         return (int)devPtr->devStatus;
706     }
707
708     bool OCSecureResource::getOwnedStatus()
709     {
710         validateSecureResource();
711         return devPtr->doxm->owned;
712     }
713
714     void OCSecureResource::validateSecureResource()
715     {
716         if (!devPtr)
717         {
718             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
719         }
720     }
721 }