58442523de1775f86f612d827ad063bd36dd2dc5
[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 "global.h"
41
42 #include "srmresourcestrings.h"
43 #include "doxmresource.h"
44 #include "pstatresource.h"
45 #include "credresource.h"
46 #include "aclresource.h"
47 #include "ownershiptransfermanager.h"
48 #include "securevirtualresourcetypes.h"
49 #include "oxmjustworks.h"
50 #include "pmtypes.h"
51 #include "pmutility.h"
52 #include "srmutility.h"
53 #include "provisioningdatabasemanager.h"
54 #include "oxmrandompin.h"
55 #include "ocpayload.h"
56 #include "payload_logging.h"
57 #include "oxmjustworks.h"
58 #include "oxmpreconfpin.h"
59 #include "oxmrandompin.h"
60 #include "otmcontextlist.h"
61
62 #define TAG "OIC_MULTIPLE_OTM"
63
64 /**********************************************************************
65  * API for Super Owner
66  **********************************************************************/
67
68 /**
69  * Callback handler of security resource's POST request.
70  *
71  * @param[in] ctx             ctx value passed to callback from calling function.
72  * @param[in] UNUSED          handle to an invocation
73  * @param[in] clientResponse  Response from queries to remote servers.
74  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
75  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
76  */
77 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
78                                                 OCClientResponse *clientResponse)
79 {
80     OIC_LOG_V(INFO, TAG, "Inside MOTUpdateMomCB.");
81     (void)UNUSED;
82     OTMContext_t *motCtx = (OTMContext_t*)ctx;
83     VERIFY_NON_NULL(TAG, motCtx, ERROR);
84     VERIFY_NON_NULL(TAG, motCtx->ctxResultCallback, ERROR);
85     VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
86
87     if(clientResponse)
88     {
89         memcpy(motCtx->ctxResultArray[0].deviceId.id,
90                motCtx->selectedDeviceInfo->doxm->deviceID.id,
91                sizeof(OicUuid_t));
92         motCtx->ctxResultArray[0].res = clientResponse->result;
93
94         if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
95         {
96             motCtx->ctxHasError = false;
97         }
98         else
99         {
100             motCtx->ctxHasError = true;
101         }
102     }
103     else
104     {
105         OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
106         motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
107         motCtx->ctxHasError = true;
108     }
109
110     motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
111                               motCtx->ctxResultArray, motCtx->ctxHasError);
112
113 exit:
114     if(motCtx)
115     {
116         OICFree(motCtx->ctxResultArray);
117         OICFree(motCtx);
118     }
119     return OC_STACK_DELETE_TRANSACTION;
120 }
121
122 /**
123  * Internal API to send POST doxm request
124  */
125 static OCStackResult MOTSendPostDoxm(void *ctx,
126                                      const OCProvisionDev_t *targetDeviceInfo,
127                                      OCProvisionResultCB resultCallback,
128                                      const OicSecDoxm_t* doxm)
129 {
130     OCStackResult postMomRes = OC_STACK_ERROR;
131     OCSecurityPayload* secPayload = NULL;
132     OTMContext_t *motCtx = NULL;
133     bool freeFlag = true;
134
135     OIC_LOG(DEBUG, TAG, "IN MOTSendPostDoxm");
136
137     //Generate the security payload using updated doxm
138     secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
139     VERIFY_NON_NULL(TAG, secPayload, ERROR);
140     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
141
142     postMomRes = DoxmToCBORPayload(doxm, &secPayload->securityData, &secPayload->payloadSize, true);
143     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
144
145     OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
146     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
147
148     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
149     bool queryGenRes = PMGenerateQuery(true,
150                                        targetDeviceInfo->endpoint.addr,
151                                        targetDeviceInfo->securePort,
152                                        targetDeviceInfo->connType,
153                                        query, sizeof(query), OIC_RSRC_DOXM_URI);
154     VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
155     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
156
157     //Create the MOT Context to handle the response message
158     motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
159     VERIFY_NON_NULL(TAG, motCtx, ERROR);
160     motCtx->selectedDeviceInfo = targetDeviceInfo;
161     motCtx->ctxResultCallback = resultCallback;
162     motCtx->ctxResultArraySize = 1;
163     motCtx->ctxHasError = false;
164     motCtx->userCtx = ctx;
165     motCtx->ctxResultArray= (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
166     VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
167
168     //Send POST request
169     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
170     cbData.cb = &MOTUpdateSecurityResourceCB;
171     cbData.context = (void *)motCtx;
172     OIC_LOG(DEBUG, TAG, "Sending POST 'doxm' request to resource server");
173     postMomRes = OCDoResource(NULL, OC_REST_POST, query,
174                               &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
175                               targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
176     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
177
178     freeFlag = false;
179
180     OIC_LOG(DEBUG, TAG, "OUT MOTSendPostDoxm");
181
182 exit:
183     //If POST request successfully sent, motCtx will be cleaned from response handler.
184     if(freeFlag && motCtx)
185     {
186         OICFree(motCtx->ctxResultArray);
187         OICFree(motCtx);
188     }
189
190     return postMomRes;
191 }
192
193 /**
194  * API to update 'doxm.mom' to resource server.
195  *
196  * @param[in] targetDeviceInfo Selected target device.
197  * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
198  * @param[in] resultCallback callback provided by API user, callback will be called when
199  *            POST 'mom' request recieves a response from resource server.
200  * @return OC_STACK_OK in case of success and other value otherwise.
201  */
202 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
203                             const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
204 {
205     OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
206     OicSecDoxm_t* doxm = NULL;
207     uint8_t* doxmPayload = NULL;
208     size_t doxmPayloadLen = 0;
209
210     OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
211
212     VERIFY_SUCCESS(TAG, (OIC_NUMBER_OF_MOM_TYPE > momType), ERROR);
213     VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
214     postMomRes = OC_STACK_INVALID_CALLBACK;
215     VERIFY_NON_NULL(TAG, resultCallback, ERROR);
216
217     //Dulpicate doxm resource to update the 'mom' property
218     postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
219     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
220
221     postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
222     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
223     VERIFY_NON_NULL(TAG, doxm, ERROR);
224
225     if(NULL == doxm->mom)
226     {
227         postMomRes = OC_STACK_NO_MEMORY;
228         doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
229         VERIFY_NON_NULL(TAG, (doxm->mom), ERROR);
230     }
231     doxm->mom->mode = momType;
232
233     //Send POST reuqest for update doxm
234     postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
235     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
236
237     OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
238
239 exit:
240     OICFree(doxmPayload);
241     DeleteDoxmBinData(doxm);
242     return postMomRes;
243 }
244
245 /**
246  * API to add 'doxm.oxms' to resource server.
247  *
248  * @param[in] targetDeviceInfo Selected target device.
249  * @param[in] newOxm  OxMs to be added (ref. oic.sec.oxm)
250  * @param[in] resultCallback callback provided by API user, callback will be called when
251  *            POST 'oxms' request recieves a response from resource server.
252  * @return OC_STACK_OK in case of success and other value otherwise.
253  */
254 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
255                                  const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
256 {
257     OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
258     OicSecOxm_t* newOxms = NULL;
259     uint8_t* doxmPayload = NULL;
260     size_t doxmPayloadLen = 0;
261
262     OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
263
264     VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > newOxm || OIC_PRECONFIG_PIN == newOxm), ERROR);
265     VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
266     postOxmRes = OC_STACK_INVALID_CALLBACK;
267     VERIFY_NON_NULL(TAG, resultCallback, ERROR);
268     postOxmRes = OC_STACK_NO_MEMORY;
269
270     for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
271     {
272         if(targetDeviceInfo->doxm->oxm[i] == newOxm)
273         {
274             OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
275             OCProvisionResult_t* resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
276             VERIFY_NON_NULL(TAG, resArr, ERROR);
277             resArr->res = OC_STACK_OK;
278             memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
279             resultCallback(ctx, 1, resArr, false);
280             return OC_STACK_OK;
281         }
282     }
283
284     newOxms = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
285     VERIFY_NON_NULL(TAG, newOxms , ERROR);
286
287     for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
288     {
289         newOxms[i] = targetDeviceInfo->doxm->oxm[i];
290     }
291     newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
292     targetDeviceInfo->doxm->oxmLen++;
293     OICFree(targetDeviceInfo->doxm->oxm);
294     targetDeviceInfo->doxm->oxm = newOxms;
295
296     //Send POST reuqest for update doxm
297     postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
298     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
299
300     OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
301
302 exit:
303     OICFree(doxmPayload);
304     return postOxmRes;
305 }
306
307 /**
308  * API to update 'doxm.oxmsel' to resource server.
309  *
310  * @param[in] targetDeviceInfo Selected target device.
311   * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
312  * @param[in] resultCallback callback provided by API user, callback will be called when
313  *            POST 'oxmsel' request recieves a response from resource server.
314  * @return OC_STACK_OK in case of success and other value otherwise.
315  */
316 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
317                                  const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
318 {
319     OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
320     OicSecDoxm_t* doxm = NULL;
321     uint8_t* doxmPayload = NULL;
322     size_t doxmPayloadLen = 0;
323
324     OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
325
326     VERIFY_NON_NULL(TAG, resultCallback, ERROR);
327     postMomRes = OC_STACK_INVALID_PARAM;
328     VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
329
330     bool isValidOxmsel = false;
331     for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
332     {
333         if(targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
334         {
335             isValidOxmsel = true;
336             break;
337         }
338     }
339     VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
340
341     //Dulpicate doxm resource to update the 'oxmsel' property
342     postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
343     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
344
345     postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
346     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
347     VERIFY_NON_NULL(TAG, doxm, ERROR);
348
349     doxm->oxmSel = oxmSelValue;
350
351     //Send POST reuqest for update doxm
352     postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
353     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
354
355     OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
356
357 exit:
358     OICFree(doxmPayload);
359     DeleteDoxmBinData(doxm);
360     return postMomRes;
361 }
362
363 /**
364  * API to provision preconfigured PIN to resource server.
365  *
366  * @param[in] targetDeviceInfo Selected target device.
367  * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
368  * @param[in] preconfPINLen Byte length of preconfig PIN
369  * @param[in] resultCallback callback provided by API user, callback will be called when
370  *            POST credential request recieves a response from resource server.
371  * @return OC_STACK_OK in case of success and other value otherwise.
372  */
373 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
374                                  const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
375 {
376     OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
377     bool freeFlag = true;
378     OCSecurityPayload* secPayload = NULL;
379     OTMContext_t *motCtx = NULL;
380     OicSecCred_t* pinCred = NULL;
381
382     OIC_LOG(DEBUG, TAG, "IN MOTProvisionPreconfigPIN");
383
384     VERIFY_NON_NULL(TAG, resultCallback, ERROR);
385     postCredRes = OC_STACK_INVALID_PARAM;
386     VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
387     VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
388     VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
389     VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
390
391     postCredRes = OC_STACK_NO_MEMORY;
392     //Generate PIN based credential
393     pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
394     VERIFY_NON_NULL(TAG, pinCred, ERROR);
395
396     pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
397     VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
398
399     memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
400     pinCred->privateData.data[preconfPINLen] = '\0';
401     pinCred->privateData.len = preconfPINLen;
402     pinCred->privateData.encoding = OIC_ENCODING_RAW;
403     pinCred->credType = PIN_PASSWORD;
404     OICStrcpy(pinCred->subject.id, sizeof(pinCred->subject.id), WILDCARD_SUBJECT_ID.id);
405
406     //Generate the security payload using updated doxm
407     secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
408     VERIFY_NON_NULL(TAG, secPayload, ERROR);
409     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
410
411     postCredRes = CredToCBORPayload(pinCred, &secPayload->securityData, &secPayload->payloadSize, false);
412     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
413
414     OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
415     OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
416
417     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
418     bool queryGenRes = PMGenerateQuery(true,
419                                        targetDeviceInfo->endpoint.addr,
420                                        targetDeviceInfo->securePort,
421                                        targetDeviceInfo->connType,
422                                        query, sizeof(query), OIC_RSRC_CRED_URI);
423     VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
424     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
425
426     //Create the MOT Context to handle the response message
427     motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
428     VERIFY_NON_NULL(TAG, motCtx, ERROR);
429     motCtx->selectedDeviceInfo= targetDeviceInfo;
430     motCtx->ctxResultCallback = resultCallback;
431     motCtx->ctxResultArraySize =1;
432     motCtx->ctxHasError = false;
433     motCtx->userCtx = ctx;
434     motCtx->ctxResultArray = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
435     VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
436
437     //Send POST request
438     OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
439     cbData.cb = &MOTUpdateSecurityResourceCB;
440     cbData.context = (void *)motCtx;
441     OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
442     postCredRes = OCDoResource(NULL, OC_REST_POST, query,
443                               &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
444                               targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
445     VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
446
447     freeFlag = false;
448
449     OIC_LOG(DEBUG, TAG, "OUT MOTProvisionPreconfigPIN");
450
451     return postCredRes;
452
453 exit:
454     //If POST request successfully sent, motCtx will be cleaned from response handler.
455     if(freeFlag && motCtx)
456     {
457         OICFree(motCtx->ctxResultArray);
458         OICFree(motCtx);
459     }
460     if(pinCred)
461     {
462         OICFree(pinCred->privateData.data);
463         OICFree(pinCred);
464     }
465     return postCredRes;
466 }
467
468
469 /**********************************************************************
470  * API for Sub Owner
471  **********************************************************************/
472
473 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
474                                                     OCProvisionDev_t* selectedDevice);
475
476 static OTMContext_t* g_MotCtx = NULL;
477
478 static bool IsComplete(OTMContext_t* otmCtx)
479 {
480     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
481     {
482         if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
483         {
484             return false;
485         }
486     }
487
488     return true;
489 }
490
491 /**
492  * Function to save the result of multiple ownership transfer.
493  *
494  * @param[in,out] motCtx   Context instance of multiple ownership transfer.
495  * @param[in] res   result of multiple ownership transfer.
496  */
497 static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
498 {
499     OIC_LOG_V(DEBUG, TAG, "IN SetMOTResult : %d ", res);
500     VERIFY_NON_NULL(TAG, motCtx, ERROR);
501
502     if(motCtx->selectedDeviceInfo)
503     {
504         //Revert psk_info callback in case of random PIN OxM
505         if(OIC_RANDOM_DEVICE_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel ||
506            OIC_PRECONFIG_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel)
507         {
508             if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
509             {
510                 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
511             }
512             OicUuid_t emptyUuid = { .id={0}};
513             SetUuidForPinBasedOxm(&emptyUuid);
514         }
515
516         OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
517                                                     PDM_DEVICE_ACTIVE);
518         if (OC_STACK_OK != pdmRetVal)
519         {
520             OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
521         }
522
523         for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
524         {
525             if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
526                       motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
527             {
528                 motCtx->ctxResultArray[i].res = res;
529                 if(OC_STACK_OK != res)
530                 {
531                     motCtx->ctxHasError = true;
532                 }
533             }
534         }
535
536         //Remove the current OTM Context from OTM queue
537         RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
538                          motCtx->selectedDeviceInfo->securePort);
539
540         //If there is a request being performed, cancel it to prevent retransmission.
541         if(motCtx->ocDoHandle)
542         {
543             if (OC_STACK_OK !=  OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
544             {
545                 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
546             }
547             motCtx->ocDoHandle = NULL;
548         }
549
550         //If all request is completed, invoke the user callback.
551         if(IsComplete(motCtx))
552         {
553             motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
554                                        motCtx->ctxResultArray, motCtx->ctxHasError);
555
556             OICFree(motCtx->ctxResultArray);
557             OICFree(motCtx);
558             motCtx = NULL;
559         }
560         else
561         {
562             if(OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
563                                                      motCtx->selectedDeviceInfo->next))
564             {
565                 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
566             }
567         }
568     }
569
570 exit:
571     OIC_LOG(DEBUG, TAG, "OUT SetMOTResult");
572 }
573
574 /**
575  * API to add preconfigured PIN to local SVR DB.
576  *
577  * @param[in] targetDeviceInfo Selected target device.
578  * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
579  * @param[in] preconfPINLen Byte length of preconfig PIN
580  * @param[in] resultCallback callback provided by API user, callback will be called when
581  *            POST credential request recieves a response from resource server.
582  * @return OC_STACK_OK in case of success and other value otherwise.
583  */
584 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
585                                  const char* preconfPIN, size_t preconfPINLen)
586 {
587     OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
588     OicSecCred_t* pinCred = NULL;
589     bool freeFlag = true;
590
591     OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
592
593     VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
594     VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
595     VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
596     VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
597
598     OicSecCred_t* prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
599     if(NULL != prevCred)
600     {
601         OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
602         return OC_STACK_OK;
603     }
604
605     addCredRes = OC_STACK_NO_MEMORY;
606     //Generate PIN based credential
607     pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
608     VERIFY_NON_NULL(TAG, pinCred, ERROR);
609
610     pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
611     VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
612
613     memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
614     pinCred->privateData.data[preconfPINLen] = '\0';
615     pinCred->privateData.len = preconfPINLen;
616     pinCred->privateData.encoding = OIC_ENCODING_RAW;
617     pinCred->credType = PIN_PASSWORD;
618     memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
619
620     addCredRes = AddCredential(pinCred);
621     VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
622
623     OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
624
625     return addCredRes;
626
627 exit:
628     if(pinCred)
629     {
630         OICFree(pinCred->privateData.data);
631         OICFree(pinCred);
632     }
633     return addCredRes;
634 }
635
636 /**
637  * Function to save the SubOwner PSK.
638  *
639  * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
640  * @return  OC_STACK_OK on success
641  */
642 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
643 {
644     OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
645
646     OCStackResult res = OC_STACK_ERROR;
647
648     CAEndpoint_t endpoint;
649     memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
650     OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
651     endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
652     endpoint.port = selectedDeviceInfo->securePort;
653     endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
654
655     OicUuid_t ownerDeviceID = {.id={0}};
656     if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
657     {
658         OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
659         return res;
660     }
661
662     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
663     OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
664
665     //Generating SubOwnerPSK
666     CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
667             (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
668             strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
669             ownerDeviceID.id, sizeof(ownerDeviceID.id),
670             selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
671             ownerPSK, OWNER_PSK_LENGTH_128);
672
673     if (CA_STATUS_OK == pskRet)
674     {
675         OIC_LOG(DEBUG, TAG, "SubOwner PSK dump:");
676         OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
677         //Generating new credential for provisioning tool
678         OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
679                                       SYMMETRIC_PAIR_WISE_KEY, NULL,
680                                       &ownerKey, &ownerDeviceID, &ownerDeviceID);
681         VERIFY_NON_NULL(TAG, cred, ERROR);
682
683         uint32_t outSize = 0;
684         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
685         char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
686         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
687         b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
688
689         OICFree( cred->privateData.data );
690         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
691         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
692
693         strncpy(cred->privateData.data, b64Buf, outSize);
694         cred->privateData.data[outSize] = '\0';
695         cred->privateData.encoding = OIC_ENCODING_BASE64;
696         cred->privateData.len = outSize;
697         OICFree(b64Buf);
698
699         //Add SubOwnerPSK
700         res = AddCredential(cred);
701         if(res != OC_STACK_OK)
702         {
703             DeleteCredList(cred);
704             return res;
705         }
706     }
707     else
708     {
709         OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
710     }
711
712     OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
713 exit:
714     return res;
715 }
716
717
718 /**
719  * Response handler for update subowner crendetial request.
720  *
721  * @param[in] ctx             ctx value passed to callback from calling function.
722  * @param[in] UNUSED          handle to an invocation
723  * @param[in] clientResponse  Response from queries to remote servers.
724  * @return  OC_STACK_DELETE_TRANSACTION to delete the transaction
725  *          and  OC_STACK_KEEP_TRANSACTION to keep it.
726  */
727 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
728                                 OCClientResponse *clientResponse)
729 {
730     VERIFY_NON_NULL(TAG, clientResponse, WARNING);
731     VERIFY_NON_NULL(TAG, ctx, WARNING);
732
733     OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
734     (void)UNUSED;
735     OTMContext_t* motCtx = (OTMContext_t*)ctx;
736
737     if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
738     {
739         if(motCtx && motCtx->selectedDeviceInfo)
740         {
741             //Close the temporal secure session to verify the owner credential
742             CAEndpoint_t* endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
743             endpoint->port = motCtx->selectedDeviceInfo->securePort;
744             CAResult_t caResult = CAcloseSslSession(endpoint);
745             if(CA_STATUS_OK != caResult)
746             {
747                 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
748                 SetMOTResult(motCtx, OC_STACK_ERROR);
749                 return OC_STACK_DELETE_TRANSACTION;
750             }
751
752             // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
753             caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
754             if(CA_STATUS_OK != caResult)
755             {
756                 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
757                 SetMOTResult(motCtx, OC_STACK_ERROR);
758                 return OC_STACK_DELETE_TRANSACTION;
759             }
760
761             SetMOTResult(motCtx, OC_STACK_OK);
762         }
763     }
764     else
765     {
766         OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
767                   clientResponse->result);
768         SetMOTResult(motCtx, clientResponse->result);
769     }
770
771     OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
772
773 exit:
774     return  OC_STACK_DELETE_TRANSACTION;
775 }
776
777
778 static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
779 {
780     OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
781
782     if(!motCtx || !motCtx->selectedDeviceInfo)
783     {
784         OIC_LOG(ERROR, TAG, "Invalid parameters");
785         return OC_STACK_INVALID_PARAM;
786     }
787
788     OCProvisionDev_t* deviceInfo = motCtx->selectedDeviceInfo;
789     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
790
791     if(!PMGenerateQuery(true,
792                         deviceInfo->endpoint.addr, deviceInfo->securePort,
793                         deviceInfo->connType,
794                         query, sizeof(query), OIC_RSRC_CRED_URI))
795     {
796         OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
797         return OC_STACK_ERROR;
798     }
799     OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
800     OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
801     if(!secPayload)
802     {
803         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
804         return OC_STACK_NO_MEMORY;
805     }
806
807     //Generate sub-owner credential for new device
808     secPayload->base.type = PAYLOAD_TYPE_SECURITY;
809     const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
810     if(!ownerCredential)
811     {
812         OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
813         return OC_STACK_NO_RESOURCE;
814     }
815
816     OicUuid_t ownerId = {.id={0}};
817     if(OC_STACK_OK == GetDoxmDeviceID(&ownerId))
818     {
819         OicSecCred_t newCredential;
820         memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
821         newCredential.next = NULL;
822
823         //Set subject ID as SubOwner's ID
824         memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
825
826         //Set eowner ID as SubOwner's ID
827         if(NULL == newCredential.eownerID)
828         {
829             newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
830             if(NULL == newCredential.eownerID)
831             {
832                 return OC_STACK_NO_MEMORY;
833             }
834         }
835         memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
836
837         //Fill private data as empty string
838         newCredential.privateData.data = "";
839         newCredential.privateData.len = 0;
840         newCredential.privateData.encoding = ownerCredential->privateData.encoding;
841
842 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
843         newCredential.publicData.data = NULL;
844         newCredential.publicData.len = 0;
845         newCredential.publicData.encoding = ownerCredential->publicData.encoding;
846 #endif
847         //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
848         if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
849                                         &secPayload->payloadSize, 0))
850         {
851             OICFree(secPayload);
852             OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
853             return OC_STACK_ERROR;
854         }
855         OIC_LOG(DEBUG, TAG, "Cred Payload:");
856         OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
857
858         OCCallbackData cbData;
859         cbData.cb = &SubOwnerCredentialHandler;
860         cbData.context = (void *)motCtx;
861         cbData.cd = NULL;
862         OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
863                                          &deviceInfo->endpoint, (OCPayload*)secPayload,
864                                          deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
865         if (res != OC_STACK_OK)
866         {
867             OIC_LOG(ERROR, TAG, "OCStack resource error");
868         }
869     }
870     else
871     {
872         OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
873         return OC_STACK_NO_RESOURCE;
874     }
875
876     OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
877
878     return OC_STACK_OK;
879 }
880
881
882 /**
883  * Function to handle the handshake result in MOT.
884  * This function will be invoked after DTLS handshake
885  * @param   endPoint  [IN] The remote endpoint.
886  * @param   errorInfo [IN] Error information from the endpoint.
887  * @return  NONE
888  */
889 static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
890 {
891     OIC_LOG(INFO, TAG, "IN MOTDtlsHandshakeCB");
892
893     if(NULL != endpoint && NULL != info)
894     {
895         OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
896                  endpoint->addr, endpoint->port, info->result);
897
898         OTMContext_t* motCtx = GetOTMContext(endpoint->addr, endpoint->port);
899         if(motCtx)
900         {
901             OicSecDoxm_t* newDevDoxm = motCtx->selectedDeviceInfo->doxm;
902
903             if(NULL != newDevDoxm)
904             {
905                 OicUuid_t emptyUuid = {.id={0}};
906
907                 //Make sure the address matches.
908                 if(strncmp(motCtx->selectedDeviceInfo->endpoint.addr,
909                    endpoint->addr,
910                    sizeof(endpoint->addr)) == 0 &&
911                    motCtx->selectedDeviceInfo->securePort == endpoint->port)
912                 {
913                     OCStackResult res = OC_STACK_ERROR;
914
915                     //If temporal secure sesstion established successfully
916                     if(CA_STATUS_OK == info->result)
917                     {
918                         //Delete previous credential such as preconfigured-pin
919                         RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
920
921                         res = SaveSubOwnerPSK(motCtx->selectedDeviceInfo);
922                         if(OC_STACK_OK == res)
923                         {
924                             //POST sub owner credential to new device.
925                             res = PostSubOwnerCredential(motCtx);
926                             if(OC_STACK_OK != res)
927                             {
928                                 OIC_LOG(ERROR, TAG,
929                                         "Failed to send POST request for SubOwner Credential");
930                                 SetMOTResult(motCtx, res);
931                             }
932                         }
933                         else
934                         {
935                             OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
936                             SetMOTResult(motCtx, res);
937                         }
938                     }
939                     //In case of authentication failure
940                     else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
941                     {
942                         //in case of error from wrong PIN, re-start the ownership transfer
943                         if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
944                         {
945                             OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
946
947                             motCtx->attemptCnt++;
948
949                             if(WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
950                             {
951                                 res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
952                                 if(OC_STACK_OK != res)
953                                 {
954                                     SetMOTResult(motCtx, res);
955                                     OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
956                                 }
957                             }
958                             else
959                             {
960                                 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
961                                 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
962                             }
963                         }
964                         else
965                         {
966                             OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
967                             SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
968                         }
969                     }
970                 }
971             }
972         }
973         else
974         {
975             OIC_LOG_V(ERROR, TAG, "Can not find the [%s:%d]'s OTMContext for MOT", endpoint->addr, endpoint->port);
976         }
977     }
978
979     OIC_LOG(INFO, TAG, "OUT MOTDtlsHandshakeCB");
980 }
981
982 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
983                                                     OCProvisionDev_t* selectedDevice)
984 {
985     OIC_LOG(INFO, TAG, "IN StartMultipleOwnershipTransfer");
986     OCStackResult res = OC_STACK_INVALID_PARAM;
987     OicUuid_t myUuid = {.id={0}};
988
989     VERIFY_NON_NULL(TAG, motCtx, ERROR);
990     VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
991     VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
992     motCtx->selectedDeviceInfo = selectedDevice;
993
994     res = GetDoxmDeviceID(&myUuid);
995     if(OC_STACK_OK != res)
996     {
997         OIC_LOG(ERROR, TAG, "Failed to GetDoxmDeviceID");
998         SetMOTResult(motCtx, res);
999         return res;
1000     }
1001     if(memcmp(selectedDevice->doxm->owner.id, myUuid.id, sizeof(myUuid.id)) == 0)
1002     {
1003         res = OC_STACK_INVALID_DEVICE_INFO;
1004         OIC_LOG(ERROR, TAG, "Owner cannot be registered as sub-owner.");
1005         SetMOTResult(motCtx, res);
1006         return res;
1007     }
1008     if (NULL == selectedDevice->doxm->mom ||
1009         (selectedDevice->doxm->mom &&
1010          OIC_MULTIPLE_OWNER_DISABLE == selectedDevice->doxm->mom->mode))
1011     {
1012         res = OC_STACK_NOT_ACCEPTABLE;
1013         OIC_LOG(ERROR, TAG, "Selected device's MOT is disabled.");
1014         SetMOTResult(motCtx, res);
1015         return res;
1016     }
1017
1018     //Checking duplication of Device ID.
1019     char* strUuid = NULL;
1020     PdmDeviceState_t deviceState = PDM_DEVICE_UNKNOWN;
1021     res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &deviceState);
1022     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1023
1024     res = ConvertUuidToStr(&selectedDevice->doxm->deviceID, &strUuid);
1025     if(OC_STACK_OK != res)
1026     {
1027         OIC_LOG(ERROR, TAG, "Failed to convert UUID to str");
1028         SetMOTResult(motCtx, res);
1029         return res;
1030     }
1031
1032     if(PDM_DEVICE_STALE == deviceState)
1033     {
1034         OIC_LOG_V(WARNING, TAG, "Detected duplicated UUID in stale status, "
1035                            "[%s] will be removed from PDM", strUuid);
1036
1037         res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
1038         if(OC_STACK_OK != res)
1039         {
1040             OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
1041             OICFree(strUuid);
1042             SetMOTResult(motCtx, res);
1043         }
1044     }
1045     else if(PDM_DEVICE_INIT == deviceState)
1046     {
1047         OIC_LOG_V(ERROR, TAG, "[%s]'s multiple owner transfer process is already started.", strUuid);
1048         OICFree(strUuid);
1049         SetMOTResult(motCtx, OC_STACK_DUPLICATE_REQUEST);
1050         return OC_STACK_OK;
1051     }
1052
1053     res = PDMAddDevice(&selectedDevice->doxm->deviceID);
1054     if (OC_STACK_OK != res)
1055     {
1056         OIC_LOG_V(INFO, TAG, "Error in PDMAddDevice for [%s]", strUuid);
1057         OICFree(strUuid);
1058         SetMOTResult(motCtx, res);
1059         return res;
1060     }
1061     OICFree(strUuid);
1062
1063     //Register DTLS event handler to catch the dtls event while handshake
1064     if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1065     {
1066         OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1067     }
1068
1069     OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
1070     OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", (int)oxmSel);
1071
1072     if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
1073     {
1074         OIC_LOG(ERROR, TAG, "Unsupported OxM");
1075         return OC_STACK_ERROR;
1076     }
1077
1078     res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
1079     if(OC_STACK_OK != res)
1080     {
1081         OIC_LOG_V(ERROR, TAG, "Error in OTMSetOTCallback : %d", res);
1082         return res;
1083     }
1084     //Only two functions required for MOT
1085     VERIFY_NON_NULL(TAG, motCtx->otmCallback.loadSecretCB, ERROR);
1086     VERIFY_NON_NULL(TAG, motCtx->otmCallback.createSecureSessionCB, ERROR);
1087
1088     if(OIC_RANDOM_DEVICE_PIN == oxmSel)
1089     {
1090         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1091         {
1092             OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
1093         }
1094     }
1095
1096     //Save the current context instance to use on the dtls handshake callback
1097     res = AddOTMContext(motCtx, selectedDevice->endpoint.addr, selectedDevice->securePort);
1098     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1099
1100     res = motCtx->otmCallback.loadSecretCB(motCtx);
1101     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1102
1103     res = motCtx->otmCallback.createSecureSessionCB(motCtx);
1104     VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1105
1106     OIC_LOG(INFO, TAG, "OUT StartMultipleOwnershipTransfer");
1107
1108 exit:
1109     return res;
1110 }
1111
1112 OCStackResult MOTDoOwnershipTransfer(void* ctx,
1113                                      OCProvisionDev_t *selectedDevicelist,
1114                                      OCProvisionResultCB resultCallback)
1115 {
1116     OIC_LOG(DEBUG, TAG, "IN MOTDoOwnershipTransfer");
1117     OCStackResult res = OC_STACK_INVALID_PARAM;
1118     OTMContext_t* motCtx = NULL;
1119     OCProvisionDev_t* pCurDev = NULL;
1120
1121     VERIFY_NON_NULL(TAG, selectedDevicelist, ERROR);
1122     VERIFY_NON_NULL(TAG, resultCallback, ERROR);
1123
1124     res = OC_STACK_NO_MEMORY;
1125     motCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1126     VERIFY_NON_NULL(TAG, motCtx, ERROR);
1127
1128     motCtx->ctxResultCallback = resultCallback;
1129     motCtx->ctxHasError = false;
1130     motCtx->userCtx = ctx;
1131     motCtx->ctxResultArraySize = 0;
1132     LL_FOREACH(selectedDevicelist, pCurDev)
1133     {
1134         motCtx->ctxResultArraySize++;
1135     }
1136
1137     motCtx->ctxResultArray =
1138         (OCProvisionResult_t*)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1139     VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
1140
1141     //Fill the device UUID for result array.
1142     size_t devIdx = 0;
1143     pCurDev = NULL;
1144     LL_FOREACH(selectedDevicelist, pCurDev)
1145     {
1146         memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1147                pCurDev->doxm->deviceID.id,
1148                UUID_LENGTH);
1149         motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1150         devIdx++;
1151     }
1152
1153     motCtx->selectedDeviceInfo = selectedDevicelist;
1154     res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1155
1156     OIC_LOG(DEBUG, TAG, "OUT MOTDoOwnershipTransfer");
1157     return res;
1158 exit:
1159     if(OC_STACK_OK != res)
1160     {
1161         if(motCtx)
1162         {
1163             OICFree(motCtx->ctxResultArray);
1164             OICFree(motCtx);
1165         }
1166     }
1167     return res;
1168 }