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