201ea0bdbd29cf491cfcb440dff8d63c5fbab5bb
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / multipleownershiptransfermanager.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 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 #ifdef HAVE_TIME_H
22 #include <time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_SYS_TIME_H
28 #include <sys/time.h>
29 #endif
30 #include <stdbool.h>
31 #include <string.h>
32
33 #include "utlist.h"
34 #include "logger.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37 #include "cacommon.h"
38 #include "cainterface.h"
39 #include "base64.h"
40 #include "srmresourcestrings.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "credresource.h"
44 #include "aclresource.h"
45 #include "ownershiptransfermanager.h"
46 #include "oxmjustworks.h"
47 #include "pmtypes.h"
48 #include "pmutility.h"
49 #include "pmutilityinternal.h"
50 #include "srmutility.h"
51 #include "provisioningdatabasemanager.h"
52 #include "oxmrandompin.h"
53 #include "ocpayload.h"
54 #include "payload_logging.h"
55 #include "oxmjustworks.h"
56 #include "oxmpreconfpin.h"
57 #include "oxmrandompin.h"
58 #include "otmcontextlist.h"
59 #include "ocstackinternal.h"
60 #include "mbedtls/ssl_ciphersuites.h"
61 #include "ocrandom.h"
62 #include "secureresourceprovider.h"
63
64 #define TAG "OIC_MULTIPLE_OTM"
65
66 /**********************************************************************
67  * API for Super Owner
68  **********************************************************************/
69
70 /**
71  * Callback handler of security resource's POST request.
72  *
73  * @param[in] ctx             ctx value passed to callback from calling function.
74  * @param[in] UNUSED          handle to an invocation
75  * @param[in] clientResponse  Response from queries to remote servers.
76  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
77  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
78  */
79 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle handle,
80         OCClientResponse *clientResponse)
81 {
82     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
83
84     OC_UNUSED(handle);
85
86     OTMContext_t *motCtx = NULL;
87
88     VERIFY_NOT_NULL(TAG, ctx, ERROR);
89     VERIFY_NOT_NULL(TAG, ((Data_t *)ctx)->ctx, ERROR);
90
91     motCtx = (OTMContext_t *)(((Data_t *)ctx)->ctx);
92
93     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
94     VERIFY_NOT_NULL(TAG, motCtx->ctxResultCallback, ERROR);
95     VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
96
97     if (clientResponse)
98     {
99         memcpy(motCtx->ctxResultArray[0].deviceId.id,
100                motCtx->selectedDeviceInfo->doxm->deviceID.id,
101                sizeof(OicUuid_t));
102         motCtx->ctxResultArray[0].res = clientResponse->result;
103         if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
104         {
105             motCtx->ctxHasError = false;
106         }
107         else
108         {
109             motCtx->ctxHasError = true;
110         }
111     }
112     else
113     {
114         OIC_LOG_V(ERROR, TAG, "%s: received Null clientResponse", __func__);
115         motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
116         motCtx->ctxHasError = true;
117     }
118
119     motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
120                               motCtx->ctxResultArray, motCtx->ctxHasError);
121
122     OIC_LOG_V(DEBUG, TAG, "%s: update ok", __func__);
123 exit:
124     if (motCtx)
125     {
126         PMDeleteDeviceList(motCtx->selectedDeviceInfo);
127         OICFree(motCtx->ctxResultArray);
128         OICFree(motCtx);
129     }
130     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
131     return OC_STACK_DELETE_TRANSACTION;
132 }
133
134 /**
135  * Restores pstat after PIN provisioning
136  */
137 static OCStackApplicationResult RestoreProvCB(void *ctx, OCDoHandle handle,
138         OCClientResponse *clientResponse)
139 {
140     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
141
142     OC_UNUSED(handle);
143     OC_UNUSED(clientResponse);
144
145     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
146
147     if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, MOTUpdateSecurityResourceCB))
148     {
149         OIC_LOG_V(ERROR, TAG, "%s: SetDOS", __func__);
150     }
151
152     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
153     return OC_STACK_DELETE_TRANSACTION;
154 }
155
156 static OCStackApplicationResult MOTSendPostDoxmCB(void *ctx, OCDoHandle handle,
157         OCClientResponse *clientResponse)
158 {
159     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
160
161     OC_UNUSED(handle);
162     OC_UNUSED(clientResponse);
163
164     bool freeFlag = true;
165     OTMContext_t *motCtx = NULL;
166     OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
167     VERIFY_NOT_NULL(TAG, ctx, ERROR);
168
169     OCSecurityPayload *secPayload = NULL;
170
171     Data_t *data = (Data_t *) ctx;
172     if (MOT_TYPE != data->type)
173     {
174         OIC_LOG(ERROR, TAG, "Invalid type");
175         goto exit;
176     }
177
178     VERIFY_NOT_NULL(TAG, data->ctx, ERROR);
179     motCtx = (OTMContext_t *) (data->ctx);
180
181     //Generate the security payload using updated doxm
182     secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
183     VERIFY_NOT_NULL(TAG, secPayload, ERROR);
184     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
185
186     // This function appears to be called for updating oxmSel, mom, and subOwners,
187     // but it previously was including ALL writeable Properties.  So we include
188     // at least those three.
189     bool propertiesToInclude[DOXM_PROPERTY_COUNT];
190     memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
191     propertiesToInclude[DOXM_OXMSEL] = true;
192     propertiesToInclude[DOXM_SUBOWNER] = true;
193     propertiesToInclude[DOXM_MOM] = true;
194
195     postMomRes = DoxmToCBORPayloadPartial(motCtx->doxm, &secPayload->securityData,
196                                           &secPayload->payloadSize, propertiesToInclude);
197     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
198
199     OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
200     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
201
202     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
203     bool queryGenRes = PMGenerateQuery(true,
204                                        motCtx->selectedDeviceInfo->endpoint.addr,
205                                        motCtx->selectedDeviceInfo->securePort,
206                                        motCtx->selectedDeviceInfo->connType,
207                                        query, sizeof(query), OIC_RSRC_DOXM_URI);
208     VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
209     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
210
211     //Send POST request
212     OCCallbackData cbData;
213     memset(&cbData, 0, sizeof(cbData));
214
215     cbData.cb = &RestoreProvCB;
216     cbData.context = ctx;
217     cbData.cd = NULL;
218
219     postMomRes = OCDoResource(NULL, OC_REST_POST, query,
220                               &(motCtx->selectedDeviceInfo->endpoint), (OCPayload *)secPayload,
221                               motCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
222     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
223
224     freeFlag = false;
225
226     OIC_LOG_V(DEBUG, TAG, "%s: Send POST 'doxm' request to resource server", __func__);
227
228 exit:
229     //If POST request successfully sent, motCtx will be cleaned from response handler.
230     if (freeFlag && motCtx)
231     {
232         PMDeleteDeviceList(motCtx->selectedDeviceInfo);
233         OICFree(motCtx->ctxResultArray);
234         OICFree(motCtx);
235     }
236
237     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
238
239     return postMomRes;
240 }
241
242 /**
243  * Internal API to send POST doxm request
244  */
245 static OCStackResult MOTSendPostDoxm(void *ctx,
246                                      const OCProvisionDev_t *targetDeviceInfo,
247                                      OCProvisionResultCB resultCallback,
248                                      OicSecDoxm_t *doxm)
249 {
250     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
251
252     OTMContext_t *motCtx = NULL;
253     OCProvisionDev_t *localTargetDeviceInfo = NULL;
254     OCStackResult ret =  OC_STACK_ERROR;
255
256     //Create the MOT Context to handle the response message
257     motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
258     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
259
260     localTargetDeviceInfo = PMCloneOCProvisionDevList(targetDeviceInfo);
261     VERIFY_NOT_NULL(TAG, localTargetDeviceInfo, ERROR);
262
263     motCtx->selectedDeviceInfo = localTargetDeviceInfo;
264     motCtx->ctxResultCallback = resultCallback;
265     motCtx->ctxResultArraySize = 1;
266     motCtx->ctxHasError = false;
267     motCtx->doxm = doxm;
268     motCtx->userCtx = ctx;
269     motCtx->ctxResultArray = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
270     VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
271
272     Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
273     VERIFY_NOT_NULL(TAG, data, ERROR);
274     data->type = MOT_TYPE;
275     data->ctx = motCtx;
276
277     ret =  SetDOS(data, DOS_RFPRO, MOTSendPostDoxmCB);
278     if (OC_STACK_OK != ret)
279     {
280         FreeData(data);
281     }
282 exit:
283     if (OC_STACK_OK != ret)
284     {
285         OICFree(motCtx->ctxResultArray);
286         OICFree(motCtx);
287     }
288
289     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
290
291     return ret;
292 }
293
294 /**
295  * API to update 'doxm.mom' to resource server.
296  *
297  * @param[in] targetDeviceInfo Selected target device.
298  * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
299  * @param[in] resultCallback callback provided by API user, callback will be called when
300  *            POST 'mom' request recieves a response from resource server.
301  * @return OC_STACK_OK in case of success and other value otherwise.
302  */
303 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
304                             const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
305 {
306     OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
307     OicSecDoxm_t *doxm = NULL;
308     uint8_t *doxmPayload = NULL;
309     size_t doxmPayloadLen = 0;
310
311     OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
312
313     VERIFY_SUCCESS(TAG, (OIC_NUMBER_OF_MOM_TYPE > momType), ERROR);
314     VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
315     postMomRes = OC_STACK_INVALID_CALLBACK;
316     VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
317
318     //Dulpicate doxm resource to update the 'mom' property
319     postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen);
320     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
321
322     postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
323     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
324     VERIFY_NOT_NULL(TAG, doxm, ERROR);
325
326     if (NULL == doxm->mom)
327     {
328         postMomRes = OC_STACK_NO_MEMORY;
329         doxm->mom = (OicSecMom_t *)OICCalloc(1, sizeof(OicSecMom_t));
330         VERIFY_NOT_NULL(TAG, (doxm->mom), ERROR);
331     }
332     doxm->mom->mode = momType;
333
334     //Send POST reuqest for update doxm
335     postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
336     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
337
338     OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
339
340 exit:
341     OICFree(doxmPayload);
342     DeleteDoxmBinData(doxm);
343     return postMomRes;
344 }
345
346 /**
347  * API to add 'doxm.oxms' to resource server.
348  *
349  * @param[in] targetDeviceInfo Selected target device.
350  * @param[in] newOxm  OxMs to be added (ref. oic.sec.doxmtype)
351  * @param[in] resultCallback callback provided by API user, callback will be called when
352  *            POST 'oxms' request recieves a response from resource server.
353  * @return OC_STACK_OK in case of success and other value otherwise.
354  */
355 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
356                               const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
357 {
358     OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
359     OicSecOxm_t *newOxms = NULL;
360     uint8_t *doxmPayload = NULL;
361
362     OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
363
364     VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > newOxm || OIC_PRECONFIG_PIN == newOxm), ERROR);
365     VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
366     postOxmRes = OC_STACK_INVALID_CALLBACK;
367     VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
368     postOxmRes = OC_STACK_NO_MEMORY;
369
370     for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
371     {
372         if (targetDeviceInfo->doxm->oxm[i] == newOxm)
373         {
374             OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
375             OCProvisionResult_t *resArr = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
376             VERIFY_NOT_NULL(TAG, resArr, ERROR);
377             resArr->res = OC_STACK_OK;
378             memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
379             resultCallback(ctx, 1, resArr, false);
380             return OC_STACK_OK;
381         }
382     }
383
384     newOxms = (OicSecOxm_t *)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
385     VERIFY_NOT_NULL(TAG, newOxms, ERROR);
386
387     for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
388     {
389         newOxms[i] = targetDeviceInfo->doxm->oxm[i];
390     }
391     newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
392     targetDeviceInfo->doxm->oxmLen++;
393     OICFree(targetDeviceInfo->doxm->oxm);
394     targetDeviceInfo->doxm->oxm = newOxms;
395
396     //Send POST request for doxm update
397     postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
398     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
399
400     OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
401
402 exit:
403     OICFree(doxmPayload);
404     return postOxmRes;
405 }
406
407 /**
408  * API to update 'doxm.oxmsel' to resource server.
409  *
410  * @param[in] targetDeviceInfo Selected target device.
411  * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.doxmtype)
412  * @param[in] resultCallback callback provided by API user, callback will be called when
413  *            POST 'oxmsel' request recieves a response from resource server.
414  * @return OC_STACK_OK in case of success and other value otherwise.
415  */
416 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
417                                  const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
418 {
419     OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
420     OicSecDoxm_t *doxm = NULL;
421     uint8_t *doxmPayload = NULL;
422     size_t doxmPayloadLen = 0;
423
424     OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
425
426     VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
427     postMomRes = OC_STACK_INVALID_PARAM;
428     VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
429
430     bool isValidOxmsel = false;
431     for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
432     {
433         if (targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
434         {
435             isValidOxmsel = true;
436             break;
437         }
438     }
439     VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
440
441     //Dulpicate doxm resource to update the 'oxmsel' property
442     postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen);
443     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
444
445     postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
446     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
447     VERIFY_NOT_NULL(TAG, doxm, ERROR);
448
449     doxm->oxmSel = oxmSelValue;
450
451     //Send POST reuqest for update doxm
452     postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
453     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
454
455     OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
456
457 exit:
458     OICFree(doxmPayload);
459     DeleteDoxmBinData(doxm);
460     return postMomRes;
461 }
462
463 static OCStackApplicationResult MOTProvisionPreconfigPINCB(void *ctx, OCDoHandle handle,
464         OCClientResponse *clientResponse)
465 {
466     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
467
468     OC_UNUSED(handle);
469     OC_UNUSED(clientResponse);
470
471     bool freeFlag = true;
472     OTMContext_t *motCtx = NULL;
473     OCStackResult postCredRes = OC_STACK_INVALID_PARAM;
474     OCSecurityPayload *secPayload = NULL;
475
476     VERIFY_NOT_NULL(TAG, ctx, ERROR);
477
478     Data_t *data = (Data_t *) ctx;
479     if (MOT_TYPE != data->type)
480     {
481         OIC_LOG(ERROR, TAG, "Invalid type");
482         goto exit;
483     }
484
485     VERIFY_NOT_NULL(TAG, data->ctx, ERROR);
486     motCtx = (OTMContext_t *) (data->ctx);
487
488     //Generate the security payload using updated doxm
489     secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
490     VERIFY_NOT_NULL(TAG, secPayload, ERROR);
491     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
492
493     postCredRes = CredToCBORPayload(motCtx->cred, &secPayload->securityData, &secPayload->payloadSize,
494                                     false);
495     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
496
497     OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
498     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
499
500     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
501     bool queryGenRes = PMGenerateQuery(true,
502                                        motCtx->selectedDeviceInfo->endpoint.addr,
503                                        motCtx->selectedDeviceInfo->securePort,
504                                        motCtx->selectedDeviceInfo->connType,
505                                        query, sizeof(query), OIC_RSRC_CRED_URI);
506     VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
507     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
508
509     //Send POST request
510     OCCallbackData cbData;
511     memset(&cbData, 0, sizeof(cbData));
512
513     cbData.cb = &RestoreProvCB;
514     cbData.context = ctx;
515     cbData.cd = NULL;
516
517     OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
518     postCredRes = OCDoResource(NULL, OC_REST_POST, query,
519                                &(motCtx->selectedDeviceInfo->endpoint), (OCPayload *)secPayload,
520                                motCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
521     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
522
523     freeFlag = false;
524
525 exit:
526     //If POST request successfully sent, motCtx will be cleaned from response handler.
527     if (freeFlag && motCtx)
528     {
529         PMDeleteDeviceList(motCtx->selectedDeviceInfo);
530
531         if (motCtx->cred)
532         {
533             OICFree(motCtx->cred->credUsage);
534             OICFree(motCtx->cred->privateData.data);
535             OICFree(motCtx->cred);
536         }
537
538         OICFree(motCtx->ctxResultArray);
539         OICFree(motCtx);
540     }
541
542     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
543
544     return postCredRes;
545 }
546
547 /**
548  * API to provision preconfigured PIN to resource server.
549  *
550  * @param[in] targetDeviceInfo Selected target device.
551  * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
552  * @param[in] preconfPINLen Byte length of preconfig PIN
553  * @param[in] resultCallback callback provided by API user, callback will be called when
554  *            POST credential request recieves a response from resource server.
555  * @return OC_STACK_OK in case of success and other value otherwise.
556  */
557 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
558                                        const char *preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
559 {
560     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
561
562     OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
563     bool freeFlag = true;
564     OTMContext_t *motCtx = NULL;
565     OicSecCred_t *pinCred = NULL;
566     Data_t *data = NULL;
567     OCProvisionDev_t *localTargetDeviceInfo = NULL;
568
569
570     VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
571     postCredRes = OC_STACK_INVALID_PARAM;
572     VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
573     VERIFY_NOT_NULL(TAG, preconfPIN, ERROR);
574     VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
575     VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
576
577     postCredRes = OC_STACK_NO_MEMORY;
578     //Generate PIN based credential
579     pinCred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
580     VERIFY_NOT_NULL(TAG, pinCred, ERROR);
581
582     pinCred->privateData.data = (uint8_t *)OICMalloc(preconfPINLen + 1);
583     VERIFY_NOT_NULL(TAG, pinCred->privateData.data, ERROR);
584
585     memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
586     pinCred->privateData.data[preconfPINLen] = '\0';
587     pinCred->privateData.len = preconfPINLen;
588     pinCred->privateData.encoding = OIC_ENCODING_RAW;
589     pinCred->credType = PIN_PASSWORD;
590     memcpy(&pinCred->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t));
591
592     pinCred->credUsage = (char *)OICCalloc(1, (strlen(PRECONFIG_PIN_CRED) + 1));
593     VERIFY_NOT_NULL(TAG, pinCred->credUsage, ERROR);
594     OICStrcpy(pinCred->credUsage, (strlen(PRECONFIG_PIN_CRED) + 1), PRECONFIG_PIN_CRED);
595
596     //Create the MOT Context to handle the response message
597     motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
598     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
599
600     localTargetDeviceInfo = PMCloneOCProvisionDevList(targetDeviceInfo);
601     VERIFY_NOT_NULL(TAG, localTargetDeviceInfo, ERROR);
602
603     motCtx->selectedDeviceInfo = localTargetDeviceInfo;
604     motCtx->ctxResultCallback = resultCallback;
605     motCtx->ctxResultArraySize = 1;
606     motCtx->ctxHasError = false;
607     motCtx->userCtx = ctx;
608     motCtx->cred = pinCred;
609     motCtx->ctxResultArray = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
610     VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
611
612     data = (Data_t *) OICCalloc(1, sizeof(Data_t));
613     VERIFY_NOT_NULL(TAG, data, ERROR);
614     data->type = MOT_TYPE;
615     data->ctx = motCtx;
616
617     if (SetDOS(data, DOS_RFPRO, MOTProvisionPreconfigPINCB) != OC_STACK_OK)
618     {
619         FreeData(data);
620         postCredRes = OC_STACK_ERROR;
621         goto exit;
622     }
623
624     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
625     return OC_STACK_OK;
626
627 exit:
628     //If POST request successfully sent, motCtx will be cleaned from response handler.
629     if (freeFlag && motCtx)
630     {
631         PMDeleteDeviceList(motCtx->selectedDeviceInfo);
632
633         if (motCtx->cred)
634         {
635             OICFree(motCtx->cred->credUsage);
636             OICFree(motCtx->cred->privateData.data);
637             OICFree(motCtx->cred);
638         }
639
640         OICFree(motCtx->ctxResultArray);
641         OICFree(motCtx);
642     }
643
644     OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
645
646     return postCredRes;
647 }
648
649
650 /**********************************************************************
651  * API for Sub Owner
652  **********************************************************************/
653
654 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t *motCtx,
655         OCProvisionDev_t *selectedDevice);
656
657 static bool IsComplete(OTMContext_t *otmCtx)
658 {
659     for (size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
660     {
661         if (OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
662         {
663             return false;
664         }
665     }
666
667     return true;
668 }
669
670 int MOTIsSupportedOnboardingType(OicSecDoxm_t *ptrDoxm)
671 {
672     OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer type: %u", ptrDoxm->oxmSel);
673
674     if ((OIC_PRECONFIG_PIN != ptrDoxm->oxmSel) && (OIC_RANDOM_DEVICE_PIN != ptrDoxm->oxmSel))
675     {
676         OIC_LOG_V(ERROR, TAG, "Unsupported MOT device");
677         return 1;
678     }
679     return 0;
680 }
681
682 /**
683  * Function to save the result of multiple ownership transfer.
684  *
685  * @param[in,out] motCtx   Context instance of multiple ownership transfer.
686  * @param[in] res   result of multiple ownership transfer.
687  */
688 static void SetMOTResult(OTMContext_t *motCtx, const OCStackResult res)
689 {
690     OIC_LOG_V(DEBUG, TAG, "IN %s: %d ", __func__, res);
691
692     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
693
694     if (motCtx->selectedDeviceInfo)
695     {
696         //Revert psk_info callback in case of random PIN OxM
697         if (!MOTIsSupportedOnboardingType(motCtx->selectedDeviceInfo->doxm))
698         {
699             if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
700             {
701                 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
702             }
703             OicUuid_t emptyUuid = { .id = {0}};
704             SetUuidForPinBasedOxm(&emptyUuid);
705         }
706
707         OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
708                                   PDM_DEVICE_ACTIVE);
709         if (OC_STACK_OK != pdmRetVal)
710         {
711             OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
712         }
713
714         for (size_t i = 0; i < motCtx->ctxResultArraySize; i++)
715         {
716             if (memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
717                        motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
718             {
719                 motCtx->ctxResultArray[i].res = res;
720                 if (OC_STACK_OK != res)
721                 {
722                     motCtx->ctxHasError = true;
723                 }
724             }
725         }
726
727         //Remove the current OTM Context from OTM queue
728         RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
729                          motCtx->selectedDeviceInfo->securePort);
730
731         //If there is a request being performed, cancel it to prevent retransmission.
732         if (motCtx->ocDoHandle)
733         {
734             if (OC_STACK_OK !=  OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
735             {
736                 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
737             }
738             motCtx->ocDoHandle = NULL;
739         }
740
741         //If all request is completed, invoke the user callback.
742         if (IsComplete(motCtx))
743         {
744             motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
745                                       motCtx->ctxResultArray, motCtx->ctxHasError);
746
747             OICFree(motCtx->ctxResultArray);
748             OICFree(motCtx);
749             motCtx = NULL;
750         }
751         else
752         {
753             if (OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
754                     motCtx->selectedDeviceInfo->next))
755             {
756                 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
757             }
758         }
759     }
760
761 exit:
762     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
763 }
764
765 /**
766  * API to add preconfigured PIN to local SVR DB.
767  *
768  * @param[in] targetDeviceInfo Selected target device.
769  * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
770  * @param[in] preconfPINLen Byte length of preconfig PIN
771  * @param[in] resultCallback callback provided by API user, callback will be called when
772  *            POST credential request recieves a response from resource server.
773  * @return OC_STACK_OK in case of success and other value otherwise.
774  */
775 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
776                                  const char *preconfPIN, size_t preconfPINLen)
777 {
778     OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
779     OicSecCred_t *pinCred = NULL;
780
781     OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
782
783     VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
784     VERIFY_NOT_NULL(TAG, preconfPIN, ERROR);
785     VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
786     VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
787
788     OicSecCred_t *prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
789     if (NULL != prevCred)
790     {
791         OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
792         return OC_STACK_OK;
793     }
794
795     addCredRes = OC_STACK_NO_MEMORY;
796     //Generate PIN based credential
797     pinCred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
798     VERIFY_NOT_NULL(TAG, pinCred, ERROR);
799
800     pinCred->privateData.data = (uint8_t *)OICMalloc(preconfPINLen + 1);
801     VERIFY_NOT_NULL(TAG, pinCred->privateData.data, ERROR);
802
803     memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
804     pinCred->privateData.data[preconfPINLen] = '\0';
805     pinCred->privateData.len = preconfPINLen;
806     pinCred->privateData.encoding = OIC_ENCODING_RAW;
807     pinCred->credType = PIN_PASSWORD;
808     memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
809
810     addCredRes = AddCredential(pinCred);
811     VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
812
813 exit:
814     if (OC_STACK_OK != addCredRes)
815     {
816         OICFree(pinCred->privateData.data);
817         OICFree(pinCred);
818     }
819
820     OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
821
822     return addCredRes;
823 }
824
825 /**
826  * Function to save the SubOwner PSK.
827  *
828  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
829  * @return  OC_STACK_OK on success
830  */
831 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
832 {
833     OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
834
835     OCStackResult res = OC_STACK_ERROR;
836
837     CAEndpoint_t endpoint;
838     CopyDevAddrToEndpoint(&selectedDeviceInfo->endpoint, &endpoint);
839
840     if (CA_ADAPTER_IP == endpoint.adapter)
841     {
842         endpoint.port = selectedDeviceInfo->securePort;
843     }
844 #ifdef WITH_TCP
845     else if (CA_ADAPTER_TCP == endpoint.adapter)
846     {
847         endpoint.port = selectedDeviceInfo->tcpSecurePort;
848     }
849 #endif
850
851     OicUuid_t ownerDeviceID = {.id = {0}};
852     if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
853     {
854         OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
855         return res;
856     }
857
858     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
859     OicSecKey_t ownerKey;
860     memset(&ownerKey, 0, sizeof(ownerKey));
861     ownerKey.data = ownerPSK;
862     ownerKey.len = OWNER_PSK_LENGTH_128;
863     ownerKey.encoding = OIC_ENCODING_RAW;
864
865     //Generating SubOwnerPSK
866     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
867                                            (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
868                                            strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
869                                            ownerDeviceID.id, sizeof(ownerDeviceID.id),
870                                            selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
871                                            ownerPSK, OWNER_PSK_LENGTH_128);
872
873     if (CA_STATUS_OK == pskRet)
874     {
875         OIC_LOG(DEBUG, TAG, "SubOwner PSK dump:");
876         OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
877         //Generating new credential for provisioning tool
878         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
879                                                 SYMMETRIC_PAIR_WISE_KEY, NULL,
880                                                 &ownerKey, &ownerDeviceID, &ownerDeviceID);
881         VERIFY_NOT_NULL(TAG, cred, ERROR);
882
883         size_t outSize = 0;
884         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
885         char *b64Buf = (char *)OICCalloc(1, b64BufSize);
886         VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
887         b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
888
889         OICFree(cred->privateData.data);
890         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
891         VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
892
893         strncpy((char *)(cred->privateData.data), b64Buf, outSize);
894         cred->privateData.data[outSize] = '\0';
895         cred->privateData.encoding = OIC_ENCODING_BASE64;
896         cred->privateData.len = outSize;
897         OICFree(b64Buf);
898
899         //Add SubOwnerPSK
900         res = AddCredential(cred);
901         if (OC_STACK_OK != res)
902         {
903             OIC_LOG_V(ERROR, TAG, "%s: cannot add credential", __func__);
904             DeleteCredList(cred);
905             goto exit;
906         }
907     }
908     else
909     {
910         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
911     }
912
913 exit:
914     OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
915     return res;
916 }
917
918
919 /**
920  * Response handler for update subowner crendetial request.
921  *
922  * @param[in] ctx             ctx value passed to callback from calling function.
923  * @param[in] UNUSED          handle to an invocation
924  * @param[in] clientResponse  Response from queries to remote servers.
925  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
926  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
927  */
928 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle handle,
929         OCClientResponse *clientResponse)
930 {
931     OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
932
933     OC_UNUSED(handle);
934
935     VERIFY_NOT_NULL(TAG, clientResponse, WARNING);
936     VERIFY_NOT_NULL(TAG, ctx, WARNING);
937     VERIFY_NOT_NULL(TAG, ((Data_t *)ctx)->ctx, ERROR);
938
939     OTMContext_t *motCtx = (OTMContext_t *)(((Data_t *)ctx)->ctx); //ctx;
940
941     if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
942     {
943         if (motCtx && motCtx->selectedDeviceInfo)
944         {
945             //Close the temporal secure session to verify the owner credential
946             CAEndpoint_t *endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
947             endpoint->port = motCtx->selectedDeviceInfo->securePort;
948             CAResult_t caResult = CAcloseSslSession(endpoint);
949             if (CA_STATUS_OK != caResult)
950             {
951                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
952                 SetMOTResult(motCtx, OC_STACK_ERROR);
953                 return OC_STACK_DELETE_TRANSACTION;
954             }
955
956             caResult = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, endpoint->adapter);
957             if (CA_STATUS_OK != caResult)
958             {
959                 OIC_LOG(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
960                 SetMOTResult(motCtx, OC_STACK_ERROR);
961                 return OC_STACK_DELETE_TRANSACTION;
962             }
963
964             SetMOTResult(motCtx, OC_STACK_OK);
965         }
966     }
967     else
968     {
969         OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
970                   clientResponse->result);
971         SetMOTResult(motCtx, clientResponse->result);
972     }
973
974 exit:
975     OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
976
977     return  OC_STACK_DELETE_TRANSACTION;
978 }
979
980 /**
981  * Restores pstat after change credential
982  */
983 static OCStackApplicationResult RestoreCredCB(void *ctx, OCDoHandle handle,
984         OCClientResponse *clientResponse)
985 {
986     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
987
988     OC_UNUSED(handle);
989     OC_UNUSED(clientResponse);
990
991     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
992
993     if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, SubOwnerCredentialHandler))
994     {
995         OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
996         return OC_STACK_DELETE_TRANSACTION;
997     }
998
999     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1000
1001     return OC_STACK_DELETE_TRANSACTION;
1002 }
1003
1004 static OCStackApplicationResult PostSubOwnerCredentialCB(void *ctx, OCDoHandle handle,
1005         OCClientResponse *clientResponse)
1006 {
1007     OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredentialCB");
1008
1009     OC_UNUSED(handle);
1010     OC_UNUSED(clientResponse);
1011
1012     Data_t *data = (Data_t *) ctx;
1013     if (MOT_TYPE != data->type)
1014     {
1015         OIC_LOG(ERROR, TAG, "Invalid type");
1016         return OC_STACK_INVALID_PARAM;
1017     }
1018
1019     if (!(data->ctx))
1020     {
1021         OIC_LOG(ERROR, TAG, "Invalid parameters");
1022         return OC_STACK_INVALID_PARAM;
1023     }
1024
1025     OTMContext_t *motCtx = (OTMContext_t *) (data->ctx);
1026     if (!motCtx || !motCtx->selectedDeviceInfo)
1027     {
1028         OIC_LOG(ERROR, TAG, "Invalid parameters");
1029         return OC_STACK_INVALID_PARAM;
1030     }
1031
1032     OCProvisionDev_t *deviceInfo = motCtx->selectedDeviceInfo;
1033     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1034
1035     if (!PMGenerateQuery(true,
1036                          deviceInfo->endpoint.addr, deviceInfo->securePort,
1037                          deviceInfo->connType,
1038                          query, sizeof(query), OIC_RSRC_CRED_URI))
1039     {
1040         OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
1041         return OC_STACK_ERROR;
1042     }
1043     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1044     OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1045     if (!secPayload)
1046     {
1047         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1048         return OC_STACK_NO_MEMORY;
1049     }
1050
1051     //Generate sub-owner credential for new device
1052     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1053     const OicSecCred_t *ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
1054     if (!ownerCredential)
1055     {
1056         OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
1057         return OC_STACK_NO_RESOURCE;
1058     }
1059
1060     OicUuid_t ownerId = {.id = {0}};
1061     if (OC_STACK_OK == GetDoxmDeviceID(&ownerId))
1062     {
1063         OicSecCred_t newCredential;
1064         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
1065         newCredential.next = NULL;
1066
1067         //Set subject ID as SubOwner's ID
1068         memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
1069
1070         //Set eowner ID as SubOwner's ID
1071         if (NULL == newCredential.eownerID)
1072         {
1073             newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
1074             if (NULL == newCredential.eownerID)
1075             {
1076                 return OC_STACK_NO_MEMORY;
1077             }
1078         }
1079         memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
1080
1081         //Fill private data as empty string
1082         newCredential.privateData.data = (uint8_t *)"";
1083         newCredential.privateData.len = 0;
1084         newCredential.privateData.encoding = ownerCredential->privateData.encoding;
1085
1086 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1087         newCredential.publicData.data = NULL;
1088         newCredential.publicData.len = 0;
1089         newCredential.publicData.encoding = ownerCredential->publicData.encoding;
1090 #endif
1091         //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
1092         if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
1093                                              &secPayload->payloadSize, 0))
1094         {
1095             OICFree(secPayload);
1096             OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
1097             return OC_STACK_ERROR;
1098         }
1099         OIC_LOG(DEBUG, TAG, "Cred Payload:");
1100         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1101
1102         OCCallbackData cbData;
1103         cbData.cb = &RestoreCredCB;
1104         cbData.context = ctx;
1105         cbData.cd = NULL;
1106         OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
1107                                          &deviceInfo->endpoint, (OCPayload *)secPayload,
1108                                          deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1109         if (res != OC_STACK_OK)
1110         {
1111             OIC_LOG(ERROR, TAG, "OCStack resource error");
1112         }
1113     }
1114     else
1115     {
1116         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
1117         return OC_STACK_NO_RESOURCE;
1118     }
1119
1120     OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredentialCB");
1121
1122     return OC_STACK_OK;
1123 }
1124
1125 static OCStackResult PostSubOwnerCredential(OTMContext_t *motCtx)
1126 {
1127     OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
1128
1129     if (!motCtx || !motCtx->selectedDeviceInfo)
1130     {
1131         OIC_LOG(ERROR, TAG, "Invalid parameters");
1132         return OC_STACK_INVALID_PARAM;
1133     }
1134
1135     Data_t *data = NULL;
1136     data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1137     if (!data)
1138     {
1139         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1140         return OC_STACK_NO_MEMORY;
1141     }
1142     data->type = MOT_TYPE;
1143     data->ctx = motCtx;
1144
1145     if (SetDOS(data, DOS_RFPRO, PostSubOwnerCredentialCB) != OC_STACK_OK)
1146     {
1147         FreeData(data);
1148         return OC_STACK_ERROR;
1149     }
1150
1151     OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
1152
1153     return OC_STACK_OK;
1154 }
1155
1156 static void MOTSessionEstablished(const CAEndpoint_t *endpoint, OicSecDoxm_t *newDevDoxm,
1157                                   OTMContext_t *motCtx)
1158 {
1159     OC_UNUSED(endpoint);
1160     OC_UNUSED(newDevDoxm);
1161
1162     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1163
1164     // Delete previous credential such as preconfigured-pin
1165     OCStackResult res = RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1166     if (OC_STACK_RESOURCE_DELETED != res)
1167     {
1168         OIC_LOG(WARNING, TAG, "Cannot find credential.");
1169     }
1170
1171     res = SaveSubOwnerPSK(motCtx->selectedDeviceInfo);
1172     if (OC_STACK_OK == res)
1173     {
1174         // POST sub owner credential to new device.
1175         res = PostSubOwnerCredential(motCtx);
1176         if (OC_STACK_OK != res)
1177         {
1178             OIC_LOG(ERROR, TAG, "Failed to send POST request for SubOwner Credential");
1179             SetMOTResult(motCtx, res);
1180         }
1181     }
1182     else
1183     {
1184         OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
1185         SetMOTResult(motCtx, res);
1186     }
1187
1188     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1189 }
1190
1191 static void MOTSessionFailed(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info,
1192                              OicSecDoxm_t *newDevDoxm, OTMContext_t *motCtx)
1193 {
1194     OC_UNUSED(endpoint);
1195
1196     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1197
1198     if (CA_DTLS_AUTHENTICATION_FAILURE != info->result)
1199     {
1200         OIC_LOG_V(ERROR, TAG, "Ownership Transfer session establishment failed, error %u", info->result);
1201         goto exit;
1202     }
1203
1204     // Reset for the next attempt
1205     RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr, motCtx->selectedDeviceInfo->securePort);
1206
1207     OCStackResult res = PDMDeleteDevice(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1208     if (OC_STACK_OK != res)
1209     {
1210         OIC_LOG(ERROR, TAG, "PDMDeleteDevice failed");
1211         SetMOTResult(motCtx, res);
1212         goto exit;
1213     }
1214
1215     if (OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
1216     {
1217         OIC_LOG(DEBUG, TAG, "The PIN may be incorrect.");
1218
1219         motCtx->attemptCnt++;
1220
1221         if (WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
1222         {
1223             res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
1224             if (OC_STACK_OK != res)
1225             {
1226                 OIC_LOG(ERROR, TAG, "Failed to Re-StartMultipleOwnershipTransfer");
1227                 SetMOTResult(motCtx, res);
1228             }
1229         }
1230         else
1231         {
1232             OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
1233             SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1234         }
1235     }
1236     else if (OIC_PRECONFIG_PIN == newDevDoxm->oxmSel)
1237     {
1238         OIC_LOG(DEBUG, TAG, "The PIN may be incorrect.");
1239
1240         // Delete previous credential
1241         res = RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1242         if (OC_STACK_RESOURCE_DELETED != res)
1243         {
1244             OIC_LOG(WARNING, TAG, "Cannot find credential.");
1245         }
1246
1247         SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1248     }
1249     else
1250     {
1251         OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
1252         SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1253     }
1254
1255 exit:
1256     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1257 }
1258
1259 /**
1260  * Function to handle the handshake result in MOT.
1261  * This function will be invoked after DTLS handshake
1262  * @param   endPoint  [IN] The remote endpoint.
1263  * @param   errorInfo [IN] Error information from the endpoint.
1264  * @return  NONE
1265  */
1266 static CAResult_t MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
1267 {
1268     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1269
1270     VERIFY_NOT_NULL(TAG, endpoint, ERROR);
1271     VERIFY_NOT_NULL(TAG, info, ERROR);
1272
1273     OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
1274               endpoint->addr, endpoint->port, info->result);
1275
1276     OTMContext_t *motCtx = GetOTMContext(endpoint->addr, endpoint->port);
1277     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1278
1279     OicSecDoxm_t *newDevDoxm = motCtx->selectedDeviceInfo->doxm;
1280     VERIFY_NOT_NULL(TAG, newDevDoxm, ERROR);
1281
1282     // Make sure the address matches.
1283     if ((0 != strncmp(motCtx->selectedDeviceInfo->endpoint.addr, endpoint->addr,
1284                       sizeof(endpoint->addr))) ||
1285         (motCtx->selectedDeviceInfo->securePort != endpoint->port))
1286     {
1287         OIC_LOG_V(ERROR, TAG, "Mismatched: expected address %s:%u",
1288                   motCtx->selectedDeviceInfo->endpoint.addr, motCtx->selectedDeviceInfo->securePort);
1289         goto exit;
1290     }
1291
1292     // If temporal secure session established successfully
1293     if (CA_STATUS_OK == info->result)
1294     {
1295         MOTSessionEstablished(endpoint, newDevDoxm, motCtx);
1296     }
1297     else
1298     {
1299         MOTSessionFailed(endpoint, info, newDevDoxm, motCtx);
1300     }
1301
1302 exit:
1303     OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1304     return CA_STATUS_OK;
1305 }
1306
1307 /**
1308  * Function to add a device to the provisioning database via the
1309  * Provisioning Database Manager (PDM).
1310  * @param  selectedDevice [IN] Device to add to the provisioning database.
1311  * @return OC_STACK_OK in case of success and other values otherwise.
1312  */
1313 static OCStackResult SetupMOTPDM(OCProvisionDev_t *selectedDevice)
1314 {
1315     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1316
1317     OCStackResult res = OC_STACK_INVALID_PARAM;
1318     PdmDeviceState_t pdmState = PDM_DEVICE_UNKNOWN;
1319     char deviceId[UUID_STRING_SIZE];
1320     bool isSubowner = false;
1321     bool isDuplicate = true;
1322
1323     VERIFY_NOT_NULL(TAG, selectedDevice, ERROR);
1324     VERIFY_NOT_NULL(TAG, selectedDevice->doxm, ERROR);
1325
1326     res = PMIsSubownerOfDevice(selectedDevice, &isSubowner);
1327     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1328
1329     res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &pdmState);
1330     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1331
1332     if (!OCConvertUuidToString(selectedDevice->doxm->deviceID.id, deviceId))
1333     {
1334         OIC_LOG(WARNING, TAG, "Failed to covert uuid to string");
1335         return OC_STACK_ERROR;
1336     }
1337
1338     if ((PDM_DEVICE_ACTIVE == pdmState) && !isSubowner)
1339     {
1340         OIC_LOG_V(WARNING, TAG, "Not a subowner for device[%s] dectected in PDM.", deviceId);
1341         OIC_LOG_V(WARNING, TAG, "[%s] will be removed from PDM.", deviceId);
1342
1343         res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
1344         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1345     }
1346
1347     // Checking duplication of Device ID.
1348     res = PDMIsDuplicateDevice(&selectedDevice->doxm->deviceID, &isDuplicate);
1349     if (OC_STACK_OK != res)
1350     {
1351         OIC_LOG_V(ERROR, TAG, "Internal error in PDMIsDuplicateDevice : %d", res);
1352         goto exit;
1353     }
1354
1355     if (isDuplicate)
1356     {
1357         if (PDM_DEVICE_STALE == pdmState)
1358         {
1359             OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "
1360                     "device status will revert back to initial status.");
1361             res = PDMSetDeviceState(&selectedDevice->doxm->deviceID, PDM_DEVICE_INIT);
1362             if (OC_STACK_OK != res)
1363             {
1364                 OIC_LOG_V(ERROR, TAG, "Internal error in PDMSetDeviceState : %d", res);
1365                 goto exit;
1366             }
1367         }
1368         else if (PDM_DEVICE_INIT == pdmState)
1369         {
1370             OIC_LOG_V(ERROR, TAG, "[%s]'s ownership transfer process is already started.", deviceId);
1371             res = OC_STACK_DUPLICATE_REQUEST;
1372             goto exit;
1373         }
1374         else
1375         {
1376             OIC_LOG(ERROR, TAG, "Unknown device status while OTM.");
1377             res = OC_STACK_ERROR;
1378             goto exit;
1379         }
1380     }
1381     else
1382     {
1383         res = PDMAddDevice(&selectedDevice->doxm->deviceID);
1384         VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1385     }
1386
1387 exit:
1388     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1389     return res;
1390 }
1391
1392 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t *motCtx,
1393         OCProvisionDev_t *selectedDevice)
1394 {
1395     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1396
1397     OCStackResult res = OC_STACK_INVALID_PARAM;
1398     OicUuid_t myUuid = {.id = {0}};
1399
1400     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1401     VERIFY_NOT_NULL(TAG, selectedDevice, ERROR);
1402     VERIFY_NOT_NULL(TAG, selectedDevice->doxm, ERROR);
1403     motCtx->selectedDeviceInfo = selectedDevice;
1404
1405     res = GetDoxmDeviceID(&myUuid);
1406     if (OC_STACK_OK != res)
1407     {
1408         OIC_LOG(ERROR, TAG, "Failed to GetDoxmDeviceID");
1409         SetMOTResult(motCtx, res);
1410         return res;
1411     }
1412
1413     if (memcmp(selectedDevice->doxm->owner.id, myUuid.id, sizeof(myUuid.id)) == 0)
1414     {
1415         res = OC_STACK_INVALID_DEVICE_INFO;
1416         OIC_LOG(ERROR, TAG, "Owner cannot be registered as sub-owner.");
1417         SetMOTResult(motCtx, res);
1418         return res;
1419     }
1420
1421     if ((NULL == selectedDevice->doxm->mom) ||
1422         (selectedDevice->doxm->mom &&
1423          (OIC_MULTIPLE_OWNER_DISABLE == selectedDevice->doxm->mom->mode)))
1424     {
1425         res = OC_STACK_NOT_ACCEPTABLE;
1426         OIC_LOG(ERROR, TAG, "MOT is disabled for the selected device.");
1427         SetMOTResult(motCtx, res);
1428         return res;
1429     }
1430     // Setup PDM to perform the MOT, PDM will be cleanup if necessary.
1431     res = SetupMOTPDM(selectedDevice);
1432     if (OC_STACK_OK != res)
1433     {
1434         OIC_LOG_V(ERROR, TAG, "SetupMOTPDM error : %d", res);
1435         SetMOTResult(motCtx, res);
1436         return res;
1437     }
1438
1439     // Register DTLS event handler to catch the dtls event while handshake
1440     if (CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1441     {
1442         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1443     }
1444
1445     OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
1446
1447     VERIFY_SUCCESS(TAG, 0 == MOTIsSupportedOnboardingType(selectedDevice->doxm), ERROR);
1448
1449     res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
1450     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1451
1452     // Only two functions required for MOT
1453     VERIFY_NOT_NULL(TAG, motCtx->otmCallback.loadSecretCB, ERROR);
1454     VERIFY_NOT_NULL(TAG, motCtx->otmCallback.createSecureSessionCB, ERROR);
1455
1456     if (OIC_RANDOM_DEVICE_PIN == oxmSel)
1457     {
1458         if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1459         {
1460             OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
1461         }
1462     }
1463
1464     // Save the current context instance to use on the dtls handshake callback
1465     res = AddOTMContext(motCtx, selectedDevice->endpoint.addr, selectedDevice->securePort);
1466     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1467
1468     res = motCtx->otmCallback.loadSecretCB(motCtx);
1469     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1470
1471     res = motCtx->otmCallback.createSecureSessionCB(motCtx);
1472     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1473
1474 exit:
1475     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1476     return res;
1477 }
1478
1479 OCStackResult MOTDoOwnershipTransfer(void *ctx,
1480                                      OCProvisionDev_t *selectedDevicelist,
1481                                      OCProvisionResultCB resultCallback)
1482 {
1483     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1484
1485     OCStackResult res = OC_STACK_INVALID_PARAM;
1486     OTMContext_t *motCtx = NULL;
1487     OCProvisionDev_t *pCurDev = NULL;
1488
1489     VERIFY_NOT_NULL(TAG, selectedDevicelist, ERROR);
1490     VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
1491
1492     res = OC_STACK_NO_MEMORY;
1493     motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
1494     VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1495
1496     motCtx->ctxResultCallback = resultCallback;
1497     motCtx->ctxHasError = false;
1498     motCtx->userCtx = ctx;
1499     motCtx->ctxResultArraySize = 0;
1500     LL_FOREACH(selectedDevicelist, pCurDev)
1501     {
1502         motCtx->ctxResultArraySize++;
1503     }
1504
1505     motCtx->ctxResultArray =
1506         (OCProvisionResult_t *)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1507     VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
1508
1509     //Fill the device UUID for result array.
1510     size_t devIdx = 0;
1511     pCurDev = NULL;
1512     LL_FOREACH(selectedDevicelist, pCurDev)
1513     {
1514         memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1515                pCurDev->doxm->deviceID.id,
1516                UUID_LENGTH);
1517         motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1518         devIdx++;
1519     }
1520
1521     motCtx->selectedDeviceInfo = selectedDevicelist;
1522     res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1523
1524 exit:
1525     if (OC_STACK_OK != res)
1526     {
1527         if (motCtx)
1528         {
1529             OICFree(motCtx->ctxResultArray);
1530             OICFree(motCtx);
1531         }
1532     }
1533     else
1534     {
1535         OIC_LOG_V(DEBUG, TAG, "%s: otm ok", __func__);
1536     }
1537
1538     OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1539
1540     return res;
1541 }