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