1 /* *****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
27 #ifdef HAVE_SYS_TIME_H
35 #include "oic_malloc.h"
36 #include "oic_string.h"
38 #include "cainterface.h"
40 #if defined (__TIZENRT__)
41 #include <apps/netutils/cJSON.h>
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"
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"
66 #define TAG "OIC_MULTIPLE_OTM"
68 /**********************************************************************
70 **********************************************************************/
73 * Callback handler of security resource's POST request.
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.
81 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
82 OCClientResponse *clientResponse)
84 OIC_LOG_V(INFO, TAG, "In %s", __func__);
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);
93 memcpy(motCtx->ctxResultArray[0].deviceId.id,
94 motCtx->selectedDeviceInfo->doxm->deviceID.id,
96 motCtx->ctxResultArray[0].res = clientResponse->result;
98 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
100 motCtx->ctxHasError = false;
104 motCtx->ctxHasError = true;
109 OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
110 motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
111 motCtx->ctxHasError = true;
114 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
115 motCtx->ctxResultArray, motCtx->ctxHasError);
120 OICFree(motCtx->ctxResultArray);
123 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
124 return OC_STACK_DELETE_TRANSACTION;
128 * Callback handler of security resource's DELETE request.
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.
136 static OCStackApplicationResult MOTDeleteSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
137 OCClientResponse *clientResponse)
139 OIC_LOG_V(INFO, TAG, "In %s", __func__);
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);
148 memcpy(motCtx->ctxResultArray[0].deviceId.id,
149 motCtx->selectedDeviceInfo->doxm->deviceID.id,
151 motCtx->ctxResultArray[0].res = clientResponse->result;
153 if(OC_STACK_RESOURCE_DELETED == clientResponse->result)
155 motCtx->ctxHasError = false;
159 motCtx->ctxHasError = true;
164 OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
165 motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
166 motCtx->ctxHasError = true;
169 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
170 motCtx->ctxResultArray, motCtx->ctxHasError);
175 OICFree(motCtx->ctxResultArray);
178 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
180 return OC_STACK_DELETE_TRANSACTION;
185 * Internal API to send POST doxm request
187 static OCStackResult MOTSendPostDoxm(void *ctx,
188 const OCProvisionDev_t *targetDeviceInfo,
189 OCProvisionResultCB resultCallback,
190 const OicSecDoxm_t* doxm)
192 OCStackResult postMomRes = OC_STACK_ERROR;
193 OCSecurityPayload* secPayload = NULL;
194 OTMContext_t *motCtx = NULL;
195 bool freeFlag = true;
197 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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;
204 postMomRes = DoxmToCBORPayload(doxm, &secPayload->securityData, &secPayload->payloadSize, true);
205 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
207 OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
208 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
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);
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);
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);
243 //If POST request successfully sent, motCtx will be cleaned from response handler.
244 if(freeFlag && motCtx)
246 OICFree(motCtx->ctxResultArray);
249 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
254 * API to update 'doxm.mom' to resource server.
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.
262 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
263 const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
265 OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
266 OicSecDoxm_t* doxm = NULL;
267 uint8_t* doxmPayload = NULL;
268 size_t doxmPayloadLen = 0;
270 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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);
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);
281 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
282 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
283 VERIFY_NON_NULL(TAG, doxm, ERROR);
285 if(NULL == doxm->mom)
287 postMomRes = OC_STACK_NO_MEMORY;
288 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
289 VERIFY_NON_NULL(TAG, (doxm->mom), ERROR);
291 doxm->mom->mode = momType;
293 //Send POST reuqest for update doxm
294 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
295 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
298 OICFree(doxmPayload);
299 DeleteDoxmBinData(doxm);
300 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
305 * API to add 'doxm.oxms' to resource server.
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.
313 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
314 const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
316 OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
317 OicSecOxm_t* newOxms = NULL;
318 uint8_t* doxmPayload = NULL;
319 size_t doxmPayloadLen = 0;
321 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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;
329 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
331 if(targetDeviceInfo->doxm->oxm[i] == newOxm)
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);
343 newOxms = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
344 VERIFY_NON_NULL(TAG, newOxms , ERROR);
346 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
348 newOxms[i] = targetDeviceInfo->doxm->oxm[i];
350 newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
351 targetDeviceInfo->doxm->oxmLen++;
352 OICFree(targetDeviceInfo->doxm->oxm);
353 targetDeviceInfo->doxm->oxm = newOxms;
355 //Send POST reuqest for update doxm
356 postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
357 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
360 OICFree(doxmPayload);
361 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
366 * API to update 'doxm.oxmsel' to resource server.
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.
374 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
375 const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
377 OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
378 OicSecDoxm_t* doxm = NULL;
379 uint8_t* doxmPayload = NULL;
380 size_t doxmPayloadLen = 0;
382 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
384 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
385 postMomRes = OC_STACK_INVALID_PARAM;
386 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
388 bool isValidOxmsel = false;
389 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
391 if(targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
393 isValidOxmsel = true;
397 VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
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);
403 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
404 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
405 VERIFY_NON_NULL(TAG, doxm, ERROR);
407 doxm->oxmSel = oxmSelValue;
409 //Send POST reuqest for update doxm
410 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
411 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
414 OICFree(doxmPayload);
415 DeleteDoxmBinData(doxm);
416 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
421 * API to provision preconfigured PIN to resource server.
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.
430 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
431 const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
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;
439 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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);
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);
453 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
454 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
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);
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;
468 postCredRes = CredToCBORPayload(pinCred, &secPayload->securityData, &secPayload->payloadSize, false);
469 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
471 OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
472 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
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);
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);
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);
506 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
511 //If POST request successfully sent, motCtx will be cleaned from response handler.
512 if(freeFlag && motCtx)
514 OICFree(motCtx->ctxResultArray);
519 OICFree(pinCred->privateData.data);
522 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, postCredRes);
527 /**********************************************************************
529 **********************************************************************/
531 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
532 OCProvisionDev_t* selectedDevice);
534 static OTMContext_t* g_MotCtx = NULL;
536 static bool IsComplete(OTMContext_t* otmCtx)
538 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
540 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
550 * Function to save the result of multiple ownership transfer.
552 * @param[in,out] motCtx Context instance of multiple ownership transfer.
553 * @param[in] res result of multiple ownership transfer.
555 static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
557 OIC_LOG_V(DEBUG, TAG, "IN %s : %d ", __func__, res);
558 VERIFY_NON_NULL(TAG, motCtx, ERROR);
560 if(motCtx->selectedDeviceInfo)
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)
566 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
568 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
570 OicUuid_t emptyUuid = { .id={0}};
571 SetUuidForPinBasedOxm(&emptyUuid);
574 OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
576 if (OC_STACK_OK != pdmRetVal)
578 OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
581 for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
583 if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
584 motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
586 motCtx->ctxResultArray[i].res = res;
587 if(OC_STACK_OK != res)
589 motCtx->ctxHasError = true;
594 //Remove the current OTM Context from OTM queue
595 RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
596 motCtx->selectedDeviceInfo->securePort);
598 //If there is a request being performed, cancel it to prevent retransmission.
599 if(motCtx->ocDoHandle)
601 if (OC_STACK_OK != OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
603 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
605 motCtx->ocDoHandle = NULL;
608 //If all request is completed, invoke the user callback.
609 if(IsComplete(motCtx))
611 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
612 motCtx->ctxResultArray, motCtx->ctxHasError);
614 OICFree(motCtx->ctxResultArray);
620 if(OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
621 motCtx->selectedDeviceInfo->next))
623 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
629 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
633 * API to add preconfigured PIN to local SVR DB.
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.
642 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
643 const char* preconfPIN, size_t preconfPINLen)
645 OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
646 OicSecCred_t* pinCred = NULL;
647 bool freeFlag = true;
649 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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);
656 OicSecCred_t* prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
659 OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
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);
668 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
669 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
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));
678 addCredRes = AddCredential(pinCred);
679 VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
681 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
688 OICFree(pinCred->privateData.data);
691 OIC_LOG_V(DEBUG, TAG, "In %s : %d", __func__, addCredRes);
696 * Function to save the SubOwner PSK.
698 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
699 * @return OC_STACK_OK on success
701 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
703 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
705 OCStackResult res = OC_STACK_ERROR;
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;
714 OicUuid_t ownerDeviceID = {.id={0}};
715 if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
717 OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
721 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
722 OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
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);
732 if (CA_STATUS_OK == pskRet)
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);
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);
748 OICFree( cred->privateData.data );
749 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
750 if (NULL == cred->privateData.data)
753 DeleteCredList(cred);
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;
764 res = AddCredential(cred);
765 if(res != OC_STACK_OK)
767 DeleteCredList(cred);
773 OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
776 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, res);
783 * Response handler for update subowner crendetial request.
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.
791 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
792 OCClientResponse *clientResponse)
794 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
795 VERIFY_NON_NULL(TAG, ctx, WARNING);
797 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
800 OTMContext_t* motCtx = (OTMContext_t*)ctx;
802 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
804 if(motCtx && motCtx->selectedDeviceInfo)
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)
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)
817 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
818 SetMOTResult(motCtx, OC_STACK_ERROR);
819 return OC_STACK_DELETE_TRANSACTION;
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)
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;
831 SetMOTResult(motCtx, OC_STACK_OK);
835 OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
836 SetMOTResult(motCtx, res);
837 return OC_STACK_DELETE_TRANSACTION;
843 OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
844 clientResponse->result);
845 SetMOTResult(motCtx, clientResponse->result);
848 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
851 return OC_STACK_DELETE_TRANSACTION;
855 static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
857 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
859 if(!motCtx || !motCtx->selectedDeviceInfo)
861 OIC_LOG(ERROR, TAG, "Invalid parameters");
862 return OC_STACK_INVALID_PARAM;
865 OCProvisionDev_t* deviceInfo = motCtx->selectedDeviceInfo;
866 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
868 if(!PMGenerateQuery(true,
869 deviceInfo->endpoint.addr, deviceInfo->securePort,
870 deviceInfo->connType,
871 query, sizeof(query), OIC_RSRC_CRED_URI))
873 OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
874 return OC_STACK_ERROR;
876 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
877 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
880 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
881 return OC_STACK_NO_MEMORY;
884 //Generate sub-owner credential for new device
885 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
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.
891 OicUuid_t ownerId = {.id={0}};
892 if(OC_STACK_OK == GetDoxmDeviceID(&ownerId))
894 OicSecCred_t newCredential;
895 memset(&newCredential, 0x0, sizeof(OicSecCred_t));
896 newCredential.next = NULL;
897 newCredential.credType = SYMMETRIC_PAIR_WISE_KEY;
899 //Set subject ID as SubOwner's ID
900 memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
902 //Set eowner ID as SubOwner's ID
903 if(NULL == newCredential.eownerID)
905 newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
906 if(NULL == newCredential.eownerID)
909 return OC_STACK_NO_MEMORY;
912 memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
914 //Fill private data as empty string
915 newCredential.privateData.data = "";
916 newCredential.privateData.len = 0;
917 newCredential.privateData.encoding = OIC_ENCODING_BASE64;
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;
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))
929 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
930 return OC_STACK_ERROR;
932 OIC_LOG(DEBUG, TAG, "Cred Payload:");
933 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
934 OICFree(newCredential.eownerID);
936 OCCallbackData cbData;
937 cbData.cb = &SubOwnerCredentialHandler;
938 cbData.context = (void *)motCtx;
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)
945 OIC_LOG(ERROR, TAG, "OCStack resource error");
950 OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
951 return OC_STACK_NO_RESOURCE;
954 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
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.
967 static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
969 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
971 if(NULL != endpoint && NULL != info)
973 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
974 endpoint->addr, endpoint->port, info->result);
976 OTMContext_t* motCtx = GetOTMContext(endpoint->addr, endpoint->port);
979 OicSecDoxm_t* newDevDoxm = motCtx->selectedDeviceInfo->doxm;
981 if(NULL != newDevDoxm)
983 OicUuid_t emptyUuid = {.id={0}};
985 //Make sure the address matches.
986 if(strncmp(motCtx->selectedDeviceInfo->endpoint.addr,
988 sizeof(endpoint->addr)) == 0 &&
989 motCtx->selectedDeviceInfo->securePort == endpoint->port)
991 OCStackResult res = OC_STACK_ERROR;
993 //If temporal secure sesstion established successfully
994 if(CA_STATUS_OK == info->result)
996 //POST sub owner credential to new device.
997 res = PostSubOwnerCredential(motCtx);
998 if(OC_STACK_OK != res)
1001 "Failed to send POST request for SubOwner Credential");
1002 SetMOTResult(motCtx, res);
1005 //In case of authentication failure
1006 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
1008 //in case of error from wrong PIN, re-start the ownership transfer
1009 if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
1011 OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
1013 motCtx->attemptCnt++;
1015 if(WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
1017 res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
1018 if(OC_STACK_OK != res)
1020 SetMOTResult(motCtx, res);
1021 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
1026 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
1027 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1032 OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
1033 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1041 OIC_LOG_V(ERROR, TAG, "Can not find the [%s:%d]'s OTMContext for MOT", endpoint->addr, endpoint->port);
1045 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1048 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
1049 OCProvisionDev_t* selectedDevice)
1051 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
1052 OCStackResult res = OC_STACK_INVALID_PARAM;
1053 OicUuid_t myUuid = {.id={0}};
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;
1060 res = GetDoxmDeviceID(&myUuid);
1061 if(OC_STACK_OK != res)
1063 OIC_LOG(ERROR, TAG, "Failed to GetDoxmDeviceID");
1064 SetMOTResult(motCtx, res);
1067 if(memcmp(selectedDevice->doxm->owner.id, myUuid.id, sizeof(myUuid.id)) == 0)
1069 res = OC_STACK_INVALID_DEVICE_INFO;
1070 OIC_LOG(ERROR, TAG, "Owner cannot be registered as sub-owner.");
1071 SetMOTResult(motCtx, res);
1074 if (NULL == selectedDevice->doxm->mom ||
1075 (selectedDevice->doxm->mom &&
1076 OIC_MULTIPLE_OWNER_DISABLE == selectedDevice->doxm->mom->mode))
1078 res = OC_STACK_NOT_ACCEPTABLE;
1079 OIC_LOG(ERROR, TAG, "Selected device's MOT is disabled.");
1080 SetMOTResult(motCtx, res);
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);
1090 res = ConvertUuidToStr(&selectedDevice->doxm->deviceID, &strUuid);
1091 if(OC_STACK_OK != res)
1093 OIC_LOG(ERROR, TAG, "Failed to convert UUID to str");
1095 SetMOTResult(motCtx, res);
1099 if(PDM_DEVICE_STALE == deviceState)
1101 OIC_LOG_V(WARNING, TAG, "Detected duplicated UUID in stale status, "
1102 "[%s] will be removed from PDM", strUuid);
1104 res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
1105 if(OC_STACK_OK != res)
1107 OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
1109 SetMOTResult(motCtx, res);
1113 else if(PDM_DEVICE_INIT == deviceState)
1115 OIC_LOG_V(ERROR, TAG, "[%s]'s multiple owner transfer process is already started.", strUuid);
1117 SetMOTResult(motCtx, OC_STACK_DUPLICATE_REQUEST);
1121 res = PDMAddDevice(&selectedDevice->doxm->deviceID);
1122 if (OC_STACK_OK != res)
1124 OIC_LOG_V(INFO, TAG, "Error in PDMAddDevice for [%s]", strUuid);
1126 SetMOTResult(motCtx, res);
1131 //Register DTLS event handler to catch the dtls event while handshake
1132 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1134 OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1137 OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
1138 OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", (int)oxmSel);
1140 if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
1142 OIC_LOG(ERROR, TAG, "Unsupported OxM");
1143 return OC_STACK_ERROR;
1146 res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
1147 if(OC_STACK_OK != res)
1149 OIC_LOG_V(ERROR, TAG, "Error in OTMSetOTCallback : %d", res);
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);
1156 if(OIC_RANDOM_DEVICE_PIN == oxmSel)
1158 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1160 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
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);
1168 res = motCtx->otmCallback.loadSecretCB(motCtx);
1169 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1171 res = motCtx->otmCallback.createSecureSessionCB(motCtx);
1172 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1174 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1180 OCStackResult MOTDoOwnershipTransfer(void* ctx,
1181 OCProvisionDev_t *selectedDevicelist,
1182 OCProvisionResultCB resultCallback)
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;
1189 VERIFY_NON_NULL(TAG, selectedDevicelist, ERROR);
1190 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
1192 res = OC_STACK_NO_MEMORY;
1193 motCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1194 VERIFY_NON_NULL(TAG, motCtx, ERROR);
1196 motCtx->ctxResultCallback = resultCallback;
1197 motCtx->ctxHasError = false;
1198 motCtx->userCtx = ctx;
1199 motCtx->ctxResultArraySize = 0;
1200 LL_FOREACH(selectedDevicelist, pCurDev)
1202 motCtx->ctxResultArraySize++;
1205 motCtx->ctxResultArray =
1206 (OCProvisionResult_t*)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1207 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
1209 //Fill the device UUID for result array.
1212 LL_FOREACH(selectedDevicelist, pCurDev)
1214 memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1215 pCurDev->doxm->deviceID.id,
1217 motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1221 motCtx->selectedDeviceInfo = selectedDevicelist;
1222 res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1224 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1228 if(OC_STACK_OK != res)
1232 OICFree(motCtx->ctxResultArray);
1236 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, res);
1241 OCStackResult MOTRemoveSubOwner(void* ctx,
1242 const OCProvisionDev_t *targetDeviceInfo,
1243 const OicUuid_t* subOwner,
1244 OCProvisionResultCB resultCallback)
1246 OCStackResult deleteSubOwnerRes = OC_STACK_INVALID_CALLBACK;
1247 OTMContext_t *motCtx = NULL;
1248 char* strUuid = NULL;
1250 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
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);
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)
1261 strUuid = OICStrdup(WILDCARD_RESOURCE_URI);
1262 VERIFY_NON_NULL(TAG, strUuid, ERROR);
1266 VERIFY_SUCCESS(TAG, (OC_STACK_OK == ConvertUuidToStr(subOwner, &strUuid)), ERROR);
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);
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);
1279 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
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);
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);
1302 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
1306 return deleteSubOwnerRes;
1309 //If DELETE request successfully sent, motCtx will be cleaned from response handler.
1313 OICFree(motCtx->ctxResultArray);
1316 OIC_LOG_V(DEBUG, TAG, "Out %s : %d", __func__, deleteSubOwnerRes);
1317 return deleteSubOwnerRes;