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 #include "srmresourcestrings.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "credresource.h"
44 #include "aclresource.h"
45 #include "ownershiptransfermanager.h"
46 #include "oxmjustworks.h"
48 #include "pmutility.h"
49 #include "pmutilityinternal.h"
50 #include "srmutility.h"
51 #include "provisioningdatabasemanager.h"
52 #include "oxmrandompin.h"
53 #include "ocpayload.h"
54 #include "payload_logging.h"
55 #include "oxmjustworks.h"
56 #include "oxmpreconfpin.h"
57 #include "oxmrandompin.h"
58 #include "otmcontextlist.h"
59 #include "ocstackinternal.h"
60 #include "mbedtls/ssl_ciphersuites.h"
62 #include "secureresourceprovider.h"
64 #define TAG "OIC_MULTIPLE_OTM"
66 /**********************************************************************
68 **********************************************************************/
71 * Callback handler of security resource's POST request.
73 * @param[in] ctx ctx value passed to callback from calling function.
74 * @param[in] UNUSED handle to an invocation
75 * @param[in] clientResponse Response from queries to remote servers.
76 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
77 * and OC_STACK_KEEP_TRANSACTION to keep it.
79 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle handle,
80 OCClientResponse *clientResponse)
82 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
86 OTMContext_t *motCtx = NULL;
88 VERIFY_NOT_NULL(TAG, ctx, ERROR);
89 VERIFY_NOT_NULL(TAG, ((Data_t *)ctx)->ctx, ERROR);
91 motCtx = (OTMContext_t *)(((Data_t *)ctx)->ctx);
93 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
94 VERIFY_NOT_NULL(TAG, motCtx->ctxResultCallback, ERROR);
95 VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
99 memcpy(motCtx->ctxResultArray[0].deviceId.id,
100 motCtx->selectedDeviceInfo->doxm->deviceID.id,
102 motCtx->ctxResultArray[0].res = clientResponse->result;
103 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
105 motCtx->ctxHasError = false;
109 motCtx->ctxHasError = true;
114 OIC_LOG_V(ERROR, TAG, "%s: received Null clientResponse", __func__);
115 motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
116 motCtx->ctxHasError = true;
119 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
120 motCtx->ctxResultArray, motCtx->ctxHasError);
122 OIC_LOG_V(DEBUG, TAG, "%s: update ok", __func__);
126 PMDeleteDeviceList(motCtx->selectedDeviceInfo);
127 OICFree(motCtx->ctxResultArray);
130 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
131 return OC_STACK_DELETE_TRANSACTION;
135 * Restores pstat after PIN provisioning
137 static OCStackApplicationResult RestoreProvCB(void *ctx, OCDoHandle handle,
138 OCClientResponse *clientResponse)
140 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
143 OC_UNUSED(clientResponse);
145 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
147 if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, MOTUpdateSecurityResourceCB))
149 OIC_LOG_V(ERROR, TAG, "%s: SetDOS", __func__);
152 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
153 return OC_STACK_DELETE_TRANSACTION;
156 static OCStackApplicationResult MOTSendPostDoxmCB(void *ctx, OCDoHandle handle,
157 OCClientResponse *clientResponse)
159 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
162 OC_UNUSED(clientResponse);
164 bool freeFlag = true;
165 OTMContext_t *motCtx = NULL;
166 OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
167 VERIFY_NOT_NULL(TAG, ctx, ERROR);
169 OCSecurityPayload *secPayload = NULL;
171 Data_t *data = (Data_t *) ctx;
172 if (MOT_TYPE != data->type)
174 OIC_LOG(ERROR, TAG, "Invalid type");
178 VERIFY_NOT_NULL(TAG, data->ctx, ERROR);
179 motCtx = (OTMContext_t *) (data->ctx);
181 //Generate the security payload using updated doxm
182 secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
183 VERIFY_NOT_NULL(TAG, secPayload, ERROR);
184 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
186 // This function appears to be called for updating oxmSel, mom, and subOwners,
187 // but it previously was including ALL writeable Properties. So we include
188 // at least those three.
189 bool propertiesToInclude[DOXM_PROPERTY_COUNT];
190 memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
191 propertiesToInclude[DOXM_OXMSEL] = true;
192 propertiesToInclude[DOXM_SUBOWNER] = true;
193 propertiesToInclude[DOXM_MOM] = true;
195 postMomRes = DoxmToCBORPayloadPartial(motCtx->doxm, &secPayload->securityData,
196 &secPayload->payloadSize, propertiesToInclude);
197 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
199 OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
200 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
202 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
203 bool queryGenRes = PMGenerateQuery(true,
204 motCtx->selectedDeviceInfo->endpoint.addr,
205 motCtx->selectedDeviceInfo->securePort,
206 motCtx->selectedDeviceInfo->connType,
207 query, sizeof(query), OIC_RSRC_DOXM_URI);
208 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
209 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
212 OCCallbackData cbData;
213 memset(&cbData, 0, sizeof(cbData));
215 cbData.cb = &RestoreProvCB;
216 cbData.context = ctx;
219 postMomRes = OCDoResource(NULL, OC_REST_POST, query,
220 &(motCtx->selectedDeviceInfo->endpoint), (OCPayload *)secPayload,
221 motCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
222 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
226 OIC_LOG_V(DEBUG, TAG, "%s: Send POST 'doxm' request to resource server", __func__);
229 //If POST request successfully sent, motCtx will be cleaned from response handler.
230 if (freeFlag && motCtx)
232 PMDeleteDeviceList(motCtx->selectedDeviceInfo);
233 OICFree(motCtx->ctxResultArray);
237 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
243 * Internal API to send POST doxm request
245 static OCStackResult MOTSendPostDoxm(void *ctx,
246 const OCProvisionDev_t *targetDeviceInfo,
247 OCProvisionResultCB resultCallback,
250 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
252 OTMContext_t *motCtx = NULL;
253 OCProvisionDev_t *localTargetDeviceInfo = NULL;
254 OCStackResult ret = OC_STACK_ERROR;
256 //Create the MOT Context to handle the response message
257 motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
258 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
260 localTargetDeviceInfo = PMCloneOCProvisionDevList(targetDeviceInfo);
261 VERIFY_NOT_NULL(TAG, localTargetDeviceInfo, ERROR);
263 motCtx->selectedDeviceInfo = localTargetDeviceInfo;
264 motCtx->ctxResultCallback = resultCallback;
265 motCtx->ctxResultArraySize = 1;
266 motCtx->ctxHasError = false;
268 motCtx->userCtx = ctx;
269 motCtx->ctxResultArray = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
270 VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
272 Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
273 VERIFY_NOT_NULL(TAG, data, ERROR);
274 data->type = MOT_TYPE;
277 ret = SetDOS(data, DOS_RFPRO, MOTSendPostDoxmCB);
278 if (OC_STACK_OK != ret)
283 if (OC_STACK_OK != ret)
285 OICFree(motCtx->ctxResultArray);
289 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
295 * API to update 'doxm.mom' to resource server.
297 * @param[in] targetDeviceInfo Selected target device.
298 * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
299 * @param[in] resultCallback callback provided by API user, callback will be called when
300 * POST 'mom' request recieves a response from resource server.
301 * @return OC_STACK_OK in case of success and other value otherwise.
303 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
304 const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
306 OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
307 OicSecDoxm_t *doxm = NULL;
308 uint8_t *doxmPayload = NULL;
309 size_t doxmPayloadLen = 0;
311 OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
313 VERIFY_SUCCESS(TAG, (OIC_NUMBER_OF_MOM_TYPE > momType), ERROR);
314 VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
315 postMomRes = OC_STACK_INVALID_CALLBACK;
316 VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
318 //Dulpicate doxm resource to update the 'mom' property
319 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen);
320 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
322 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
323 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
324 VERIFY_NOT_NULL(TAG, doxm, ERROR);
326 if (NULL == doxm->mom)
328 postMomRes = OC_STACK_NO_MEMORY;
329 doxm->mom = (OicSecMom_t *)OICCalloc(1, sizeof(OicSecMom_t));
330 VERIFY_NOT_NULL(TAG, (doxm->mom), ERROR);
332 doxm->mom->mode = momType;
334 //Send POST reuqest for update doxm
335 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
336 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
338 OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
341 OICFree(doxmPayload);
342 DeleteDoxmBinData(doxm);
347 * API to add 'doxm.oxms' to resource server.
349 * @param[in] targetDeviceInfo Selected target device.
350 * @param[in] newOxm OxMs to be added (ref. oic.sec.doxmtype)
351 * @param[in] resultCallback callback provided by API user, callback will be called when
352 * POST 'oxms' request recieves a response from resource server.
353 * @return OC_STACK_OK in case of success and other value otherwise.
355 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
356 const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
358 OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
359 OicSecOxm_t *newOxms = NULL;
360 uint8_t *doxmPayload = NULL;
362 OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
364 VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > newOxm || OIC_PRECONFIG_PIN == newOxm), ERROR);
365 VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
366 postOxmRes = OC_STACK_INVALID_CALLBACK;
367 VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
368 postOxmRes = OC_STACK_NO_MEMORY;
370 for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
372 if (targetDeviceInfo->doxm->oxm[i] == newOxm)
374 OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
375 OCProvisionResult_t *resArr = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
376 VERIFY_NOT_NULL(TAG, resArr, ERROR);
377 resArr->res = OC_STACK_OK;
378 memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
379 resultCallback(ctx, 1, resArr, false);
384 newOxms = (OicSecOxm_t *)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
385 VERIFY_NOT_NULL(TAG, newOxms, ERROR);
387 for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
389 newOxms[i] = targetDeviceInfo->doxm->oxm[i];
391 newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
392 targetDeviceInfo->doxm->oxmLen++;
393 OICFree(targetDeviceInfo->doxm->oxm);
394 targetDeviceInfo->doxm->oxm = newOxms;
396 //Send POST request for doxm update
397 postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
398 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
400 OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
403 OICFree(doxmPayload);
408 * API to update 'doxm.oxmsel' to resource server.
410 * @param[in] targetDeviceInfo Selected target device.
411 * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.doxmtype)
412 * @param[in] resultCallback callback provided by API user, callback will be called when
413 * POST 'oxmsel' request recieves a response from resource server.
414 * @return OC_STACK_OK in case of success and other value otherwise.
416 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
417 const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
419 OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
420 OicSecDoxm_t *doxm = NULL;
421 uint8_t *doxmPayload = NULL;
422 size_t doxmPayloadLen = 0;
424 OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
426 VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
427 postMomRes = OC_STACK_INVALID_PARAM;
428 VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
430 bool isValidOxmsel = false;
431 for (size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
433 if (targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
435 isValidOxmsel = true;
439 VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
441 //Dulpicate doxm resource to update the 'oxmsel' property
442 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen);
443 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
445 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
446 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
447 VERIFY_NOT_NULL(TAG, doxm, ERROR);
449 doxm->oxmSel = oxmSelValue;
451 //Send POST reuqest for update doxm
452 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
453 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
455 OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
458 OICFree(doxmPayload);
459 DeleteDoxmBinData(doxm);
463 static OCStackApplicationResult MOTProvisionPreconfigPINCB(void *ctx, OCDoHandle handle,
464 OCClientResponse *clientResponse)
466 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
469 OC_UNUSED(clientResponse);
471 bool freeFlag = true;
472 OTMContext_t *motCtx = NULL;
473 OCStackResult postCredRes = OC_STACK_INVALID_PARAM;
474 OCSecurityPayload *secPayload = NULL;
476 VERIFY_NOT_NULL(TAG, ctx, ERROR);
478 Data_t *data = (Data_t *) ctx;
479 if (MOT_TYPE != data->type)
481 OIC_LOG(ERROR, TAG, "Invalid type");
485 VERIFY_NOT_NULL(TAG, data->ctx, ERROR);
486 motCtx = (OTMContext_t *) (data->ctx);
488 //Generate the security payload using updated doxm
489 secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
490 VERIFY_NOT_NULL(TAG, secPayload, ERROR);
491 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
493 postCredRes = CredToCBORPayload(motCtx->cred, &secPayload->securityData, &secPayload->payloadSize,
495 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
497 OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
498 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
500 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
501 bool queryGenRes = PMGenerateQuery(true,
502 motCtx->selectedDeviceInfo->endpoint.addr,
503 motCtx->selectedDeviceInfo->securePort,
504 motCtx->selectedDeviceInfo->connType,
505 query, sizeof(query), OIC_RSRC_CRED_URI);
506 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
507 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
510 OCCallbackData cbData;
511 memset(&cbData, 0, sizeof(cbData));
513 cbData.cb = &RestoreProvCB;
514 cbData.context = ctx;
517 OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
518 postCredRes = OCDoResource(NULL, OC_REST_POST, query,
519 &(motCtx->selectedDeviceInfo->endpoint), (OCPayload *)secPayload,
520 motCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
521 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
526 //If POST request successfully sent, motCtx will be cleaned from response handler.
527 if (freeFlag && motCtx)
529 PMDeleteDeviceList(motCtx->selectedDeviceInfo);
533 OICFree(motCtx->cred->credUsage);
534 OICFree(motCtx->cred->privateData.data);
535 OICFree(motCtx->cred);
538 OICFree(motCtx->ctxResultArray);
542 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
548 * API to provision preconfigured PIN to resource server.
550 * @param[in] targetDeviceInfo Selected target device.
551 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
552 * @param[in] preconfPINLen Byte length of preconfig PIN
553 * @param[in] resultCallback callback provided by API user, callback will be called when
554 * POST credential request recieves a response from resource server.
555 * @return OC_STACK_OK in case of success and other value otherwise.
557 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
558 const char *preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
560 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
562 OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
563 bool freeFlag = true;
564 OTMContext_t *motCtx = NULL;
565 OicSecCred_t *pinCred = NULL;
567 OCProvisionDev_t *localTargetDeviceInfo = NULL;
570 VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
571 postCredRes = OC_STACK_INVALID_PARAM;
572 VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
573 VERIFY_NOT_NULL(TAG, preconfPIN, ERROR);
574 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
575 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
577 postCredRes = OC_STACK_NO_MEMORY;
578 //Generate PIN based credential
579 pinCred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
580 VERIFY_NOT_NULL(TAG, pinCred, ERROR);
582 pinCred->privateData.data = (uint8_t *)OICMalloc(preconfPINLen + 1);
583 VERIFY_NOT_NULL(TAG, pinCred->privateData.data, ERROR);
585 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
586 pinCred->privateData.data[preconfPINLen] = '\0';
587 pinCred->privateData.len = preconfPINLen;
588 pinCred->privateData.encoding = OIC_ENCODING_RAW;
589 pinCred->credType = PIN_PASSWORD;
590 memcpy(&pinCred->subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t));
592 pinCred->credUsage = (char *)OICCalloc(1, (strlen(PRECONFIG_PIN_CRED) + 1));
593 VERIFY_NOT_NULL(TAG, pinCred->credUsage, ERROR);
594 OICStrcpy(pinCred->credUsage, (strlen(PRECONFIG_PIN_CRED) + 1), PRECONFIG_PIN_CRED);
596 //Create the MOT Context to handle the response message
597 motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
598 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
600 localTargetDeviceInfo = PMCloneOCProvisionDevList(targetDeviceInfo);
601 VERIFY_NOT_NULL(TAG, localTargetDeviceInfo, ERROR);
603 motCtx->selectedDeviceInfo = localTargetDeviceInfo;
604 motCtx->ctxResultCallback = resultCallback;
605 motCtx->ctxResultArraySize = 1;
606 motCtx->ctxHasError = false;
607 motCtx->userCtx = ctx;
608 motCtx->cred = pinCred;
609 motCtx->ctxResultArray = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
610 VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
612 data = (Data_t *) OICCalloc(1, sizeof(Data_t));
613 VERIFY_NOT_NULL(TAG, data, ERROR);
614 data->type = MOT_TYPE;
617 if (SetDOS(data, DOS_RFPRO, MOTProvisionPreconfigPINCB) != OC_STACK_OK)
620 postCredRes = OC_STACK_ERROR;
624 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
628 //If POST request successfully sent, motCtx will be cleaned from response handler.
629 if (freeFlag && motCtx)
631 PMDeleteDeviceList(motCtx->selectedDeviceInfo);
635 OICFree(motCtx->cred->credUsage);
636 OICFree(motCtx->cred->privateData.data);
637 OICFree(motCtx->cred);
640 OICFree(motCtx->ctxResultArray);
644 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
650 /**********************************************************************
652 **********************************************************************/
654 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t *motCtx,
655 OCProvisionDev_t *selectedDevice);
657 static bool IsComplete(OTMContext_t *otmCtx)
659 for (size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
661 if (OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
670 int MOTIsSupportedOnboardingType(OicSecDoxm_t *ptrDoxm)
672 OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer type: %u", ptrDoxm->oxmSel);
674 if ((OIC_PRECONFIG_PIN != ptrDoxm->oxmSel) && (OIC_RANDOM_DEVICE_PIN != ptrDoxm->oxmSel))
676 OIC_LOG_V(ERROR, TAG, "Unsupported MOT device");
683 * Function to save the result of multiple ownership transfer.
685 * @param[in,out] motCtx Context instance of multiple ownership transfer.
686 * @param[in] res result of multiple ownership transfer.
688 static void SetMOTResult(OTMContext_t *motCtx, const OCStackResult res)
690 OIC_LOG_V(DEBUG, TAG, "IN %s: %d ", __func__, res);
692 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
694 if (motCtx->selectedDeviceInfo)
696 //Revert psk_info callback in case of random PIN OxM
697 if (!MOTIsSupportedOnboardingType(motCtx->selectedDeviceInfo->doxm))
699 if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
701 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
703 OicUuid_t emptyUuid = { .id = {0}};
704 SetUuidForPinBasedOxm(&emptyUuid);
707 OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
709 if (OC_STACK_OK != pdmRetVal)
711 OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
714 for (size_t i = 0; i < motCtx->ctxResultArraySize; i++)
716 if (memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
717 motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
719 motCtx->ctxResultArray[i].res = res;
720 if (OC_STACK_OK != res)
722 motCtx->ctxHasError = true;
727 //Remove the current OTM Context from OTM queue
728 RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
729 motCtx->selectedDeviceInfo->securePort);
731 //If there is a request being performed, cancel it to prevent retransmission.
732 if (motCtx->ocDoHandle)
734 if (OC_STACK_OK != OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
736 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
738 motCtx->ocDoHandle = NULL;
741 //If all request is completed, invoke the user callback.
742 if (IsComplete(motCtx))
744 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
745 motCtx->ctxResultArray, motCtx->ctxHasError);
747 OICFree(motCtx->ctxResultArray);
753 if (OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
754 motCtx->selectedDeviceInfo->next))
756 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
762 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
766 * API to add preconfigured PIN to local SVR DB.
768 * @param[in] targetDeviceInfo Selected target device.
769 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
770 * @param[in] preconfPINLen Byte length of preconfig PIN
771 * @param[in] resultCallback callback provided by API user, callback will be called when
772 * POST credential request recieves a response from resource server.
773 * @return OC_STACK_OK in case of success and other value otherwise.
775 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
776 const char *preconfPIN, size_t preconfPINLen)
778 OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
779 OicSecCred_t *pinCred = NULL;
781 OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
783 VERIFY_NOT_NULL(TAG, targetDeviceInfo, ERROR);
784 VERIFY_NOT_NULL(TAG, preconfPIN, ERROR);
785 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
786 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
788 OicSecCred_t *prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
789 if (NULL != prevCred)
791 OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
795 addCredRes = OC_STACK_NO_MEMORY;
796 //Generate PIN based credential
797 pinCred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
798 VERIFY_NOT_NULL(TAG, pinCred, ERROR);
800 pinCred->privateData.data = (uint8_t *)OICMalloc(preconfPINLen + 1);
801 VERIFY_NOT_NULL(TAG, pinCred->privateData.data, ERROR);
803 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
804 pinCred->privateData.data[preconfPINLen] = '\0';
805 pinCred->privateData.len = preconfPINLen;
806 pinCred->privateData.encoding = OIC_ENCODING_RAW;
807 pinCred->credType = PIN_PASSWORD;
808 memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
810 addCredRes = AddCredential(pinCred);
811 VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
814 if (OC_STACK_OK != addCredRes)
816 OICFree(pinCred->privateData.data);
820 OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
826 * Function to save the SubOwner PSK.
828 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
829 * @return OC_STACK_OK on success
831 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
833 OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
835 OCStackResult res = OC_STACK_ERROR;
837 CAEndpoint_t endpoint;
838 CopyDevAddrToEndpoint(&selectedDeviceInfo->endpoint, &endpoint);
840 if (CA_ADAPTER_IP == endpoint.adapter)
842 endpoint.port = selectedDeviceInfo->securePort;
845 else if (CA_ADAPTER_TCP == endpoint.adapter)
847 endpoint.port = selectedDeviceInfo->tcpSecurePort;
851 OicUuid_t ownerDeviceID = {.id = {0}};
852 if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
854 OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
858 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
859 OicSecKey_t ownerKey;
860 memset(&ownerKey, 0, sizeof(ownerKey));
861 ownerKey.data = ownerPSK;
862 ownerKey.len = OWNER_PSK_LENGTH_128;
863 ownerKey.encoding = OIC_ENCODING_RAW;
865 //Generating SubOwnerPSK
866 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
867 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
868 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
869 ownerDeviceID.id, sizeof(ownerDeviceID.id),
870 selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
871 ownerPSK, OWNER_PSK_LENGTH_128);
873 if (CA_STATUS_OK == pskRet)
875 OIC_LOG(DEBUG, TAG, "SubOwner PSK dump:");
876 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
877 //Generating new credential for provisioning tool
878 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
879 SYMMETRIC_PAIR_WISE_KEY, NULL,
880 &ownerKey, &ownerDeviceID, &ownerDeviceID);
881 VERIFY_NOT_NULL(TAG, cred, ERROR);
884 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
885 char *b64Buf = (char *)OICCalloc(1, b64BufSize);
886 VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
887 b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
889 OICFree(cred->privateData.data);
890 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
891 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
893 strncpy((char *)(cred->privateData.data), b64Buf, outSize);
894 cred->privateData.data[outSize] = '\0';
895 cred->privateData.encoding = OIC_ENCODING_BASE64;
896 cred->privateData.len = outSize;
900 res = AddCredential(cred);
901 if (OC_STACK_OK != res)
903 OIC_LOG_V(ERROR, TAG, "%s: cannot add credential", __func__);
904 DeleteCredList(cred);
910 OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
914 OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
920 * Response handler for update subowner crendetial request.
922 * @param[in] ctx ctx value passed to callback from calling function.
923 * @param[in] UNUSED handle to an invocation
924 * @param[in] clientResponse Response from queries to remote servers.
925 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
926 * and OC_STACK_KEEP_TRANSACTION to keep it.
928 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle handle,
929 OCClientResponse *clientResponse)
931 OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
935 VERIFY_NOT_NULL(TAG, clientResponse, WARNING);
936 VERIFY_NOT_NULL(TAG, ctx, WARNING);
937 VERIFY_NOT_NULL(TAG, ((Data_t *)ctx)->ctx, ERROR);
939 OTMContext_t *motCtx = (OTMContext_t *)(((Data_t *)ctx)->ctx); //ctx;
941 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
943 if (motCtx && motCtx->selectedDeviceInfo)
945 //Close the temporal secure session to verify the owner credential
946 CAEndpoint_t *endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
947 endpoint->port = motCtx->selectedDeviceInfo->securePort;
948 CAResult_t caResult = CAcloseSslSession(endpoint);
949 if (CA_STATUS_OK != caResult)
951 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
952 SetMOTResult(motCtx, OC_STACK_ERROR);
953 return OC_STACK_DELETE_TRANSACTION;
956 caResult = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, endpoint->adapter);
957 if (CA_STATUS_OK != caResult)
959 OIC_LOG(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256");
960 SetMOTResult(motCtx, OC_STACK_ERROR);
961 return OC_STACK_DELETE_TRANSACTION;
964 SetMOTResult(motCtx, OC_STACK_OK);
969 OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
970 clientResponse->result);
971 SetMOTResult(motCtx, clientResponse->result);
975 OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
977 return OC_STACK_DELETE_TRANSACTION;
981 * Restores pstat after change credential
983 static OCStackApplicationResult RestoreCredCB(void *ctx, OCDoHandle handle,
984 OCClientResponse *clientResponse)
986 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
989 OC_UNUSED(clientResponse);
991 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
993 if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, SubOwnerCredentialHandler))
995 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
996 return OC_STACK_DELETE_TRANSACTION;
999 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1001 return OC_STACK_DELETE_TRANSACTION;
1004 static OCStackApplicationResult PostSubOwnerCredentialCB(void *ctx, OCDoHandle handle,
1005 OCClientResponse *clientResponse)
1007 OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredentialCB");
1010 OC_UNUSED(clientResponse);
1012 Data_t *data = (Data_t *) ctx;
1013 if (MOT_TYPE != data->type)
1015 OIC_LOG(ERROR, TAG, "Invalid type");
1016 return OC_STACK_INVALID_PARAM;
1021 OIC_LOG(ERROR, TAG, "Invalid parameters");
1022 return OC_STACK_INVALID_PARAM;
1025 OTMContext_t *motCtx = (OTMContext_t *) (data->ctx);
1026 if (!motCtx || !motCtx->selectedDeviceInfo)
1028 OIC_LOG(ERROR, TAG, "Invalid parameters");
1029 return OC_STACK_INVALID_PARAM;
1032 OCProvisionDev_t *deviceInfo = motCtx->selectedDeviceInfo;
1033 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1035 if (!PMGenerateQuery(true,
1036 deviceInfo->endpoint.addr, deviceInfo->securePort,
1037 deviceInfo->connType,
1038 query, sizeof(query), OIC_RSRC_CRED_URI))
1040 OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
1041 return OC_STACK_ERROR;
1043 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1044 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1047 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1048 return OC_STACK_NO_MEMORY;
1051 //Generate sub-owner credential for new device
1052 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1053 const OicSecCred_t *ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
1054 if (!ownerCredential)
1056 OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
1057 return OC_STACK_NO_RESOURCE;
1060 OicUuid_t ownerId = {.id = {0}};
1061 if (OC_STACK_OK == GetDoxmDeviceID(&ownerId))
1063 OicSecCred_t newCredential;
1064 memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
1065 newCredential.next = NULL;
1067 //Set subject ID as SubOwner's ID
1068 memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
1070 //Set eowner ID as SubOwner's ID
1071 if (NULL == newCredential.eownerID)
1073 newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
1074 if (NULL == newCredential.eownerID)
1076 return OC_STACK_NO_MEMORY;
1079 memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
1081 //Fill private data as empty string
1082 newCredential.privateData.data = (uint8_t *)"";
1083 newCredential.privateData.len = 0;
1084 newCredential.privateData.encoding = ownerCredential->privateData.encoding;
1086 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1087 newCredential.publicData.data = NULL;
1088 newCredential.publicData.len = 0;
1089 newCredential.publicData.encoding = ownerCredential->publicData.encoding;
1091 //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
1092 if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
1093 &secPayload->payloadSize, 0))
1095 OICFree(secPayload);
1096 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
1097 return OC_STACK_ERROR;
1099 OIC_LOG(DEBUG, TAG, "Cred Payload:");
1100 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1102 OCCallbackData cbData;
1103 cbData.cb = &RestoreCredCB;
1104 cbData.context = ctx;
1106 OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
1107 &deviceInfo->endpoint, (OCPayload *)secPayload,
1108 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1109 if (res != OC_STACK_OK)
1111 OIC_LOG(ERROR, TAG, "OCStack resource error");
1116 OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
1117 return OC_STACK_NO_RESOURCE;
1120 OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredentialCB");
1125 static OCStackResult PostSubOwnerCredential(OTMContext_t *motCtx)
1127 OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
1129 if (!motCtx || !motCtx->selectedDeviceInfo)
1131 OIC_LOG(ERROR, TAG, "Invalid parameters");
1132 return OC_STACK_INVALID_PARAM;
1135 Data_t *data = NULL;
1136 data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1139 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
1140 return OC_STACK_NO_MEMORY;
1142 data->type = MOT_TYPE;
1145 if (SetDOS(data, DOS_RFPRO, PostSubOwnerCredentialCB) != OC_STACK_OK)
1148 return OC_STACK_ERROR;
1151 OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
1156 static void MOTSessionEstablished(const CAEndpoint_t *endpoint, OicSecDoxm_t *newDevDoxm,
1157 OTMContext_t *motCtx)
1159 OC_UNUSED(endpoint);
1160 OC_UNUSED(newDevDoxm);
1162 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1164 // Delete previous credential such as preconfigured-pin
1165 OCStackResult res = RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1166 if (OC_STACK_RESOURCE_DELETED != res)
1168 OIC_LOG(WARNING, TAG, "Cannot find credential.");
1171 res = SaveSubOwnerPSK(motCtx->selectedDeviceInfo);
1172 if (OC_STACK_OK == res)
1174 // POST sub owner credential to new device.
1175 res = PostSubOwnerCredential(motCtx);
1176 if (OC_STACK_OK != res)
1178 OIC_LOG(ERROR, TAG, "Failed to send POST request for SubOwner Credential");
1179 SetMOTResult(motCtx, res);
1184 OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
1185 SetMOTResult(motCtx, res);
1188 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1191 static void MOTSessionFailed(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info,
1192 OicSecDoxm_t *newDevDoxm, OTMContext_t *motCtx)
1194 OC_UNUSED(endpoint);
1196 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1198 if (CA_DTLS_AUTHENTICATION_FAILURE != info->result)
1200 OIC_LOG_V(ERROR, TAG, "Ownership Transfer session establishment failed, error %u", info->result);
1204 // Reset for the next attempt
1205 RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr, motCtx->selectedDeviceInfo->securePort);
1207 OCStackResult res = PDMDeleteDevice(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1208 if (OC_STACK_OK != res)
1210 OIC_LOG(ERROR, TAG, "PDMDeleteDevice failed");
1211 SetMOTResult(motCtx, res);
1215 if (OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
1217 OIC_LOG(DEBUG, TAG, "The PIN may be incorrect.");
1219 motCtx->attemptCnt++;
1221 if (WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
1223 res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
1224 if (OC_STACK_OK != res)
1226 OIC_LOG(ERROR, TAG, "Failed to Re-StartMultipleOwnershipTransfer");
1227 SetMOTResult(motCtx, res);
1232 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
1233 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1236 else if (OIC_PRECONFIG_PIN == newDevDoxm->oxmSel)
1238 OIC_LOG(DEBUG, TAG, "The PIN may be incorrect.");
1240 // Delete previous credential
1241 res = RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
1242 if (OC_STACK_RESOURCE_DELETED != res)
1244 OIC_LOG(WARNING, TAG, "Cannot find credential.");
1247 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1251 OIC_LOG(ERROR, TAG, "Failed to establish secure session.");
1252 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
1256 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1260 * Function to handle the handshake result in MOT.
1261 * This function will be invoked after DTLS handshake
1262 * @param endPoint [IN] The remote endpoint.
1263 * @param errorInfo [IN] Error information from the endpoint.
1266 static CAResult_t MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
1268 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1270 VERIFY_NOT_NULL(TAG, endpoint, ERROR);
1271 VERIFY_NOT_NULL(TAG, info, ERROR);
1273 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
1274 endpoint->addr, endpoint->port, info->result);
1276 OTMContext_t *motCtx = GetOTMContext(endpoint->addr, endpoint->port);
1277 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1279 OicSecDoxm_t *newDevDoxm = motCtx->selectedDeviceInfo->doxm;
1280 VERIFY_NOT_NULL(TAG, newDevDoxm, ERROR);
1282 // Make sure the address matches.
1283 if ((0 != strncmp(motCtx->selectedDeviceInfo->endpoint.addr, endpoint->addr,
1284 sizeof(endpoint->addr))) ||
1285 (motCtx->selectedDeviceInfo->securePort != endpoint->port))
1287 OIC_LOG_V(ERROR, TAG, "Mismatched: expected address %s:%u",
1288 motCtx->selectedDeviceInfo->endpoint.addr, motCtx->selectedDeviceInfo->securePort);
1292 // If temporal secure session established successfully
1293 if (CA_STATUS_OK == info->result)
1295 MOTSessionEstablished(endpoint, newDevDoxm, motCtx);
1299 MOTSessionFailed(endpoint, info, newDevDoxm, motCtx);
1303 OIC_LOG_V(INFO, TAG, "Out %s", __func__);
1304 return CA_STATUS_OK;
1308 * Function to add a device to the provisioning database via the
1309 * Provisioning Database Manager (PDM).
1310 * @param selectedDevice [IN] Device to add to the provisioning database.
1311 * @return OC_STACK_OK in case of success and other values otherwise.
1313 static OCStackResult SetupMOTPDM(OCProvisionDev_t *selectedDevice)
1315 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1317 OCStackResult res = OC_STACK_INVALID_PARAM;
1318 PdmDeviceState_t pdmState = PDM_DEVICE_UNKNOWN;
1319 char deviceId[UUID_STRING_SIZE];
1320 bool isSubowner = false;
1321 bool isDuplicate = true;
1323 VERIFY_NOT_NULL(TAG, selectedDevice, ERROR);
1324 VERIFY_NOT_NULL(TAG, selectedDevice->doxm, ERROR);
1326 res = PMIsSubownerOfDevice(selectedDevice, &isSubowner);
1327 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1329 res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &pdmState);
1330 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1332 if (!OCConvertUuidToString(selectedDevice->doxm->deviceID.id, deviceId))
1334 OIC_LOG(WARNING, TAG, "Failed to covert uuid to string");
1335 return OC_STACK_ERROR;
1338 if ((PDM_DEVICE_ACTIVE == pdmState) && !isSubowner)
1340 OIC_LOG_V(WARNING, TAG, "Not a subowner for device[%s] dectected in PDM.", deviceId);
1341 OIC_LOG_V(WARNING, TAG, "[%s] will be removed from PDM.", deviceId);
1343 res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
1344 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1347 // Checking duplication of Device ID.
1348 res = PDMIsDuplicateDevice(&selectedDevice->doxm->deviceID, &isDuplicate);
1349 if (OC_STACK_OK != res)
1351 OIC_LOG_V(ERROR, TAG, "Internal error in PDMIsDuplicateDevice : %d", res);
1357 if (PDM_DEVICE_STALE == pdmState)
1359 OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "
1360 "device status will revert back to initial status.");
1361 res = PDMSetDeviceState(&selectedDevice->doxm->deviceID, PDM_DEVICE_INIT);
1362 if (OC_STACK_OK != res)
1364 OIC_LOG_V(ERROR, TAG, "Internal error in PDMSetDeviceState : %d", res);
1368 else if (PDM_DEVICE_INIT == pdmState)
1370 OIC_LOG_V(ERROR, TAG, "[%s]'s ownership transfer process is already started.", deviceId);
1371 res = OC_STACK_DUPLICATE_REQUEST;
1376 OIC_LOG(ERROR, TAG, "Unknown device status while OTM.");
1377 res = OC_STACK_ERROR;
1383 res = PDMAddDevice(&selectedDevice->doxm->deviceID);
1384 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1388 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1392 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t *motCtx,
1393 OCProvisionDev_t *selectedDevice)
1395 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1397 OCStackResult res = OC_STACK_INVALID_PARAM;
1398 OicUuid_t myUuid = {.id = {0}};
1400 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1401 VERIFY_NOT_NULL(TAG, selectedDevice, ERROR);
1402 VERIFY_NOT_NULL(TAG, selectedDevice->doxm, ERROR);
1403 motCtx->selectedDeviceInfo = selectedDevice;
1405 res = GetDoxmDeviceID(&myUuid);
1406 if (OC_STACK_OK != res)
1408 OIC_LOG(ERROR, TAG, "Failed to GetDoxmDeviceID");
1409 SetMOTResult(motCtx, res);
1413 if (memcmp(selectedDevice->doxm->owner.id, myUuid.id, sizeof(myUuid.id)) == 0)
1415 res = OC_STACK_INVALID_DEVICE_INFO;
1416 OIC_LOG(ERROR, TAG, "Owner cannot be registered as sub-owner.");
1417 SetMOTResult(motCtx, res);
1421 if ((NULL == selectedDevice->doxm->mom) ||
1422 (selectedDevice->doxm->mom &&
1423 (OIC_MULTIPLE_OWNER_DISABLE == selectedDevice->doxm->mom->mode)))
1425 res = OC_STACK_NOT_ACCEPTABLE;
1426 OIC_LOG(ERROR, TAG, "MOT is disabled for the selected device.");
1427 SetMOTResult(motCtx, res);
1430 // Setup PDM to perform the MOT, PDM will be cleanup if necessary.
1431 res = SetupMOTPDM(selectedDevice);
1432 if (OC_STACK_OK != res)
1434 OIC_LOG_V(ERROR, TAG, "SetupMOTPDM error : %d", res);
1435 SetMOTResult(motCtx, res);
1439 // Register DTLS event handler to catch the dtls event while handshake
1440 if (CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1442 OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1445 OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
1447 VERIFY_SUCCESS(TAG, 0 == MOTIsSupportedOnboardingType(selectedDevice->doxm), ERROR);
1449 res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
1450 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1452 // Only two functions required for MOT
1453 VERIFY_NOT_NULL(TAG, motCtx->otmCallback.loadSecretCB, ERROR);
1454 VERIFY_NOT_NULL(TAG, motCtx->otmCallback.createSecureSessionCB, ERROR);
1456 if (OIC_RANDOM_DEVICE_PIN == oxmSel)
1458 if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1460 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
1464 // Save the current context instance to use on the dtls handshake callback
1465 res = AddOTMContext(motCtx, selectedDevice->endpoint.addr, selectedDevice->securePort);
1466 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1468 res = motCtx->otmCallback.loadSecretCB(motCtx);
1469 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1471 res = motCtx->otmCallback.createSecureSessionCB(motCtx);
1472 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1475 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1479 OCStackResult MOTDoOwnershipTransfer(void *ctx,
1480 OCProvisionDev_t *selectedDevicelist,
1481 OCProvisionResultCB resultCallback)
1483 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1485 OCStackResult res = OC_STACK_INVALID_PARAM;
1486 OTMContext_t *motCtx = NULL;
1487 OCProvisionDev_t *pCurDev = NULL;
1489 VERIFY_NOT_NULL(TAG, selectedDevicelist, ERROR);
1490 VERIFY_NOT_NULL(TAG, resultCallback, ERROR);
1492 res = OC_STACK_NO_MEMORY;
1493 motCtx = (OTMContext_t *)OICCalloc(1, sizeof(OTMContext_t));
1494 VERIFY_NOT_NULL(TAG, motCtx, ERROR);
1496 motCtx->ctxResultCallback = resultCallback;
1497 motCtx->ctxHasError = false;
1498 motCtx->userCtx = ctx;
1499 motCtx->ctxResultArraySize = 0;
1500 LL_FOREACH(selectedDevicelist, pCurDev)
1502 motCtx->ctxResultArraySize++;
1505 motCtx->ctxResultArray =
1506 (OCProvisionResult_t *)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1507 VERIFY_NOT_NULL(TAG, motCtx->ctxResultArray, ERROR);
1509 //Fill the device UUID for result array.
1512 LL_FOREACH(selectedDevicelist, pCurDev)
1514 memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1515 pCurDev->doxm->deviceID.id,
1517 motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1521 motCtx->selectedDeviceInfo = selectedDevicelist;
1522 res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1525 if (OC_STACK_OK != res)
1529 OICFree(motCtx->ctxResultArray);
1535 OIC_LOG_V(DEBUG, TAG, "%s: otm ok", __func__);
1538 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);