Function to read Trust certificate chain from SVR
[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     OCStackResult OCSecure::saveACL(const OicSecAcl_t* acl)
312     {
313         if (!acl)
314         {
315             oclog() <<"ACL can't be null";
316             return OC_STACK_INVALID_PARAM;
317         }
318
319         OCStackResult result;
320         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
321
322         if (cLock)
323         {
324             std::lock_guard<std::recursive_mutex> lock(*cLock);
325             result = OCSaveACL(const_cast<OicSecAcl_t*>(acl));
326         }
327         else
328         {
329             oclog() <<"Mutex not found";
330             result = OC_STACK_ERROR;
331         }
332         return result;
333     }
334
335 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
336     OCStackResult OCSecure::saveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
337                                         OicEncodingType_t encodingType, uint16_t *credId)
338     {
339         if (!trustCertChain)
340         {
341             oclog() <<"trustCertChain can't be null";
342             return OC_STACK_INVALID_PARAM;
343         }
344         if (!credId)
345         {
346             oclog() <<"cred ID can not be null";
347             return OC_STACK_INVALID_PARAM;
348         }
349
350         OCStackResult result;
351         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
352
353         if (cLock)
354         {
355             std::lock_guard<std::recursive_mutex> lock(*cLock);
356             result = OCSaveTrustCertChain(trustCertChain, chainSize, encodingType, credId );
357         }
358         else
359         {
360             oclog() <<"Mutex not found";
361             result = OC_STACK_ERROR;
362         }
363         return result;
364     }
365
366     OCStackResult OCSecure::readTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
367                                                  size_t *chainSize)
368     {
369         OCStackResult result;
370         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
371
372         if (cLock)
373         {
374             std::lock_guard<std::recursive_mutex> lock(*cLock);
375             result = OCReadTrustCertChain(credId, trustCertChain, chainSize);
376         }
377         else
378         {
379             oclog() <<"Mutex not found";
380             result = OC_STACK_ERROR;
381         }
382         return result;
383     }
384 #endif // __WITH_DTLS__ || __WITH_TLS__
385
386     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
387     {
388         PMResultList_t *results = nullptr;
389         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
390
391         try
392         {
393             results = new PMResultList_t;
394         }
395         catch (std::bad_alloc& e)
396         {
397             oclog() <<"Bad alloc exception";
398             return;
399         }
400
401         for (int i = 0; i < nOfRes; i++)
402         {
403             results->push_back(arr[i]);
404         }
405
406         std::thread exec(context->callback, results, hasError);
407         exec.detach();
408
409         delete context;
410     }
411
412     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
413                                         devPtr(nullptr)
414     {
415     }
416
417     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
418             OCProvisionDev_t *dPtr)
419         :m_csdkLock(csdkLock), devPtr(dPtr)
420     {
421     }
422
423     OCSecureResource::~OCSecureResource()
424     {
425         if (devPtr)
426         {
427             OCDeleteDiscoveredDevices(devPtr);
428         }
429     }
430
431     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
432     {
433         if (!resultCallback)
434         {
435             oclog() <<"Result callback can't be null";
436             return OC_STACK_INVALID_CALLBACK;
437         }
438
439         OCStackResult result;
440         auto cLock = m_csdkLock.lock();
441
442         if (cLock)
443         {
444             ProvisionContext* context = new ProvisionContext(resultCallback);
445
446             std::lock_guard<std::recursive_mutex> lock(*cLock);
447             result = OCDoOwnershipTransfer(static_cast<void*>(context),
448                     devPtr, &OCSecureResource::callbackWrapper);
449         }
450         else
451         {
452             oclog() <<"Mutex not found";
453             result = OC_STACK_ERROR;
454         }
455         return result;
456     }
457
458     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
459             ResultCallBack resultCallback)
460     {
461         if (!acl)
462         {
463             oclog() <<"ACL can't be null";
464             return OC_STACK_INVALID_PARAM;
465         }
466         if (!resultCallback)
467         {
468             oclog() <<"result callback can not be null";
469             return OC_STACK_INVALID_CALLBACK;
470         }
471
472         OCStackResult result;
473         auto cLock = m_csdkLock.lock();
474
475         if (cLock)
476         {
477             ProvisionContext* context = new ProvisionContext(resultCallback);
478
479             std::lock_guard<std::recursive_mutex> lock(*cLock);
480             result = OCProvisionACL(static_cast<void*>(context),
481                     devPtr, const_cast<OicSecAcl_t*>(acl),
482                     &OCSecureResource::callbackWrapper);
483         }
484         else
485         {
486             oclog() <<"Mutex not found";
487             result = OC_STACK_ERROR;
488         }
489         return result;
490     }
491
492     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
493             const OCSecureResource &device2, ResultCallBack resultCallback)
494     {
495         if (!resultCallback)
496         {
497             oclog() << "Result calback can't be null";
498             return OC_STACK_INVALID_CALLBACK;
499         }
500
501         OCStackResult result;
502         auto cLock = m_csdkLock.lock();
503
504         if (cLock)
505         {
506             ProvisionContext* context = new ProvisionContext(resultCallback);
507
508             std::lock_guard<std::recursive_mutex> lock(*cLock);
509             result = OCProvisionCredentials(static_cast<void*>(context),
510                     cred.getCredentialType(),
511                     cred.getCredentialKeySize(),
512                     devPtr, device2.getDevPtr(),
513                     &OCSecureResource::callbackWrapper);
514         }
515         else
516         {
517             oclog() <<"Mutex not found";
518             result = OC_STACK_ERROR;
519         }
520         return result;
521     }
522
523     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
524             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
525             ResultCallBack resultCallback)
526     {
527         if (!resultCallback)
528         {
529             oclog() << "Result callback can not be null";
530             return OC_STACK_INVALID_CALLBACK;
531         }
532
533         OCStackResult result;
534         auto cLock = m_csdkLock.lock();
535
536         if (cLock)
537         {
538             ProvisionContext* context = new ProvisionContext(resultCallback);
539
540             std::lock_guard<std::recursive_mutex> lock(*cLock);
541             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
542                     cred.getCredentialType(),
543                     cred.getCredentialKeySize(),
544                     devPtr, const_cast<OicSecAcl_t*>(acl1),
545                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
546                     &OCSecureResource::callbackWrapper);
547         }
548         else
549         {
550             oclog() <<"Mutex not found";
551             result = OC_STACK_ERROR;
552         }
553         return result;
554     }
555
556     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
557             ResultCallBack resultCallback)
558     {
559         if (!resultCallback)
560         {
561             oclog() << "Result calback can't be null";
562             return OC_STACK_INVALID_CALLBACK;
563         }
564
565         OCStackResult result;
566         auto cLock = m_csdkLock.lock();
567
568         if (cLock)
569         {
570             ProvisionContext* context = new ProvisionContext(resultCallback);
571
572             std::lock_guard<std::recursive_mutex> lock(*cLock);
573
574             result = OCUnlinkDevices(static_cast<void*>(context),
575                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
576         }
577         else
578         {
579             oclog() <<"Mutex not found";
580             result = OC_STACK_ERROR;
581         }
582         return result;
583     }
584
585     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
586             ResultCallBack resultCallback)
587     {
588         if (!resultCallback)
589         {
590             oclog() << "Result calback can't be null";
591             return OC_STACK_INVALID_CALLBACK;
592         }
593
594         OCStackResult result;
595         auto cLock = m_csdkLock.lock();
596
597         if (cLock)
598         {
599             ProvisionContext* context = new ProvisionContext(resultCallback);
600
601             std::lock_guard<std::recursive_mutex> lock(*cLock);
602
603             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
604                     devPtr, &OCSecureResource::callbackWrapper);
605         }
606         else
607         {
608             oclog() <<"Mutex not found";
609             result = OC_STACK_ERROR;
610         }
611         return result;
612     }
613
614     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
615     {
616         OCStackResult result;
617         size_t numOfDevices = -1;
618         auto devUuid = devPtr->doxm->deviceID;
619         auto cLock = m_csdkLock.lock();
620
621         if (cLock)
622         {
623             std::lock_guard<std::recursive_mutex> lock(*cLock);
624
625             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
626             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
627             if (result == OC_STACK_OK)
628             {
629                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
630                 {
631                     uuidList.push_back(tmp->dev);
632                 }
633                 OCDeleteUuidList(linkedDevs);
634             }
635         }
636         else
637         {
638             oclog() <<"Mutex not found";
639             result = OC_STACK_ERROR;
640         }
641         return result;
642     }
643
644     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
645             ResultCallBack resultCallback)
646     {
647         if (!pconf)
648         {
649             oclog() <<"PCONF can't be null";
650             return OC_STACK_INVALID_PARAM;
651         }
652         if (!resultCallback)
653         {
654             oclog() <<"result callback can not be null";
655             return OC_STACK_INVALID_CALLBACK;
656         }
657
658         OCStackResult result;
659         auto cLock = m_csdkLock.lock();
660
661         if (cLock)
662         {
663             ProvisionContext* context = new ProvisionContext(resultCallback);
664
665             std::lock_guard<std::recursive_mutex> lock(*cLock);
666             result = OCProvisionDirectPairing(static_cast<void*>(context),
667                     devPtr, const_cast<OicSecPconf_t*>(pconf),
668                     &OCSecureResource::callbackWrapper);
669         }
670         else
671         {
672             oclog() <<"Mutex not found";
673             result = OC_STACK_ERROR;
674         }
675         return result;
676     }
677
678 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
679     OCStackResult OCSecureResource::provisionTrustCertChain(OicSecCredType_t type, uint16_t credId,
680                     ResultCallBack resultCallback)
681     {
682         if (SIGNED_ASYMMETRIC_KEY != type)
683         {
684             oclog() <<"Invalid key type";
685             return OC_STACK_INVALID_PARAM;
686         }
687         if (!resultCallback)
688         {
689             oclog() <<"result callback can not be null";
690             return OC_STACK_INVALID_CALLBACK;
691         }
692
693         OCStackResult result;
694         auto cLock = m_csdkLock.lock();
695
696         if (cLock)
697         {
698             ProvisionContext* context = new ProvisionContext(resultCallback);
699
700             std::lock_guard<std::recursive_mutex> lock(*cLock);
701             result = OCProvisionTrustCertChain(static_cast<void*>(context),
702                     type, credId, devPtr,
703                     &OCSecureResource::callbackWrapper);
704         }
705         else
706         {
707             oclog() <<"Mutex not found";
708             result = OC_STACK_ERROR;
709         }
710         return result;
711     }
712 #endif // __WITH_DTLS__ or __WITH_TLS__
713
714     std::string OCSecureResource::getDeviceID()
715     {
716         std::ostringstream deviceId("");
717         char *devID = nullptr;
718
719         validateSecureResource();
720
721         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
722         {
723             deviceId << devID;
724             free(devID);
725         }
726         else
727         {
728             oclog() <<"Can not convert uuid to struuid";
729         }
730         return deviceId.str();
731     }
732
733     OCProvisionDev_t* OCSecureResource::getDevPtr() const
734     {
735         return devPtr;
736     }
737
738     std::string OCSecureResource::getDevAddr()
739     {
740         validateSecureResource();
741         std::string ipAddr(devPtr->endpoint.addr);
742         return ipAddr;
743     }
744
745     int OCSecureResource::getDeviceStatus()
746     {
747         validateSecureResource();
748         return (int)devPtr->devStatus;
749     }
750
751     bool OCSecureResource::getOwnedStatus()
752     {
753         validateSecureResource();
754         return devPtr->doxm->owned;
755     }
756
757     void OCSecureResource::validateSecureResource()
758     {
759         if (!devPtr)
760         {
761             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
762         }
763     }
764 }