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"
43 #include "srmresourcestrings.h"
44 #include "doxmresource.h"
45 #include "pstatresource.h"
46 #include "credresource.h"
47 #include "aclresource.h"
48 #include "ownershiptransfermanager.h"
49 #include "securevirtualresourcetypes.h"
50 #include "oxmjustworks.h"
52 #include "pmutility.h"
53 #include "srmutility.h"
54 #include "provisioningdatabasemanager.h"
55 #include "oxmrandompin.h"
56 #include "ocpayload.h"
57 #include "payload_logging.h"
58 #include "oxmjustworks.h"
59 #include "oxmpreconfpin.h"
60 #include "oxmrandompin.h"
62 #define TAG "MULTIPLE_OTM"
64 /**********************************************************************
66 **********************************************************************/
69 * Structure to carry SuperOwner's multiple ownership transfer API data to callback.
71 typedef struct MOTContext MOTContext_t;
74 void *ctx; /**< Pointer to user context.**/
75 const OCProvisionDev_t *deviceInfo; /**< Pointer to OCProvisionDev_t.**/
76 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
77 OCProvisionResult_t *resArr; /**< Result array.**/
78 int numOfResults; /**< Number of results in result array.**/
79 bool hasError; /**< Does MOT API have any error.. **/
83 * Callback handler of security resource's POST request.
85 * @param[in] ctx ctx value passed to callback from calling function.
86 * @param[in] UNUSED handle to an invocation
87 * @param[in] clientResponse Response from queries to remote servers.
88 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
89 * and OC_STACK_KEEP_TRANSACTION to keep it.
91 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
92 OCClientResponse *clientResponse)
94 OIC_LOG_V(INFO, TAG, "Inside MOTUpdateMomCB.");
96 MOTContext_t *motCtx = (MOTContext_t*)ctx;
97 VERIFY_NON_NULL(TAG, motCtx, ERROR);
98 VERIFY_NON_NULL(TAG, motCtx->resultCallback, ERROR);
99 VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
103 memcpy(motCtx->resArr[0].deviceId.id, motCtx->deviceInfo->doxm->deviceID.id, sizeof(OicUuid_t));
104 motCtx->resArr[0].res = clientResponse->result;
106 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
108 motCtx->hasError = false;
112 motCtx->hasError = true;
117 OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
118 motCtx->resArr[0].res = OC_STACK_ERROR;
119 motCtx->hasError = true;
122 motCtx->resultCallback(motCtx->ctx, motCtx->numOfResults, motCtx->resArr, motCtx->hasError);
127 OICFree(motCtx->resArr);
130 return OC_STACK_DELETE_TRANSACTION;
134 * Internal API to send POST doxm request
136 static OCStackResult MOTSendPostDoxm(void *ctx,
137 const OCProvisionDev_t *targetDeviceInfo,
138 OCProvisionResultCB resultCallback,
139 const OicSecDoxm_t* doxm)
141 OCStackResult postMomRes = OC_STACK_ERROR;
142 OCSecurityPayload* secPayload = NULL;
143 MOTContext_t *motCtx = NULL;
144 bool freeFlag = true;
146 OIC_LOG(DEBUG, TAG, "IN MOTSendPostDoxm");
148 //Generate the security payload using updated doxm
149 secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
150 VERIFY_NON_NULL(TAG, secPayload, ERROR);
151 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
153 postMomRes = DoxmToCBORPayload(doxm, &secPayload->securityData, &secPayload->payloadSize, true);
154 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
156 OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
157 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
159 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
160 bool queryGenRes = PMGenerateQuery(true,
161 targetDeviceInfo->endpoint.addr,
162 targetDeviceInfo->securePort,
163 targetDeviceInfo->connType,
164 query, sizeof(query), OIC_RSRC_DOXM_URI);
165 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
166 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
168 //Create the MOT Context to handle the response message
169 motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
170 VERIFY_NON_NULL(TAG, motCtx, ERROR);
171 motCtx->deviceInfo = targetDeviceInfo;
172 motCtx->resultCallback = resultCallback;
173 motCtx->numOfResults=1;
174 motCtx->hasError = false;
176 motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
177 VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
180 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
181 cbData.cb = &MOTUpdateSecurityResourceCB;
182 cbData.context = (void *)motCtx;
183 OIC_LOG(DEBUG, TAG, "Sending POST 'doxm' request to resource server");
184 postMomRes = OCDoResource(NULL, OC_REST_POST, query,
185 &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
186 targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
187 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
191 OIC_LOG(DEBUG, TAG, "OUT MOTSendPostDoxm");
194 //If POST request successfully sent, motCtx will be cleaned from response handler.
195 if(freeFlag && motCtx)
197 OICFree(motCtx->resArr);
205 * API to update 'doxm.mom' to resource server.
207 * @param[in] targetDeviceInfo Selected target device.
208 * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
209 * @param[in] resultCallback callback provided by API user, callback will be called when
210 * POST 'mom' request recieves a response from resource server.
211 * @return OC_STACK_OK in case of success and other value otherwise.
213 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
214 const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
216 OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
217 OicSecDoxm_t* doxm = NULL;
218 uint8_t* doxmPayload = NULL;
219 size_t doxmPayloadLen = 0;
221 OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
223 VERIFY_SUCCESS(TAG, (OIC_NUMBER_OF_MOM_TYPE > momType), ERROR);
224 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
225 postMomRes = OC_STACK_INVALID_CALLBACK;
226 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
228 //Dulpicate doxm resource to update the 'mom' property
229 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
230 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
232 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
233 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
234 VERIFY_NON_NULL(TAG, doxm, ERROR);
236 if(NULL == doxm->mom)
238 postMomRes = OC_STACK_NO_MEMORY;
239 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
240 VERIFY_NON_NULL(TAG, (doxm->mom), ERROR);
242 doxm->mom->mode = momType;
244 //Send POST reuqest for update doxm
245 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
246 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
248 OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
251 OICFree(doxmPayload);
252 DeleteDoxmBinData(doxm);
257 * API to add 'doxm.oxms' to resource server.
259 * @param[in] targetDeviceInfo Selected target device.
260 * @param[in] newOxm OxMs to be added (ref. oic.sec.oxm)
261 * @param[in] resultCallback callback provided by API user, callback will be called when
262 * POST 'oxms' request recieves a response from resource server.
263 * @return OC_STACK_OK in case of success and other value otherwise.
265 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
266 const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
268 OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
269 OicSecOxm_t* newOxms = NULL;
270 uint8_t* doxmPayload = NULL;
271 size_t doxmPayloadLen = 0;
273 OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
275 VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > newOxm), ERROR);
276 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
277 postOxmRes = OC_STACK_INVALID_CALLBACK;
278 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
279 postOxmRes = OC_STACK_NO_MEMORY;
281 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
283 if(targetDeviceInfo->doxm->oxm[i] == newOxm)
285 OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
286 OCProvisionResult_t* resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
287 VERIFY_NON_NULL(TAG, resArr, ERROR);
288 resArr->res = OC_STACK_OK;
289 memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
290 resultCallback(ctx, 1, resArr, false);
295 newOxms = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
296 VERIFY_NON_NULL(TAG, newOxms , ERROR);
298 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
300 newOxms[i] = targetDeviceInfo->doxm->oxm[i];
302 newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
303 targetDeviceInfo->doxm->oxmLen++;
304 OICFree(targetDeviceInfo->doxm->oxm);
305 targetDeviceInfo->doxm->oxm = newOxms;
307 //Send POST reuqest for update doxm
308 postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
309 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
311 OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
314 OICFree(doxmPayload);
319 * API to update 'doxm.oxmsel' to resource server.
321 * @param[in] targetDeviceInfo Selected target device.
322 * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
323 * @param[in] resultCallback callback provided by API user, callback will be called when
324 * POST 'oxmsel' request recieves a response from resource server.
325 * @return OC_STACK_OK in case of success and other value otherwise.
327 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
328 const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
330 OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
331 OicSecDoxm_t* doxm = NULL;
332 uint8_t* doxmPayload = NULL;
333 size_t doxmPayloadLen = 0;
335 OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
337 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
338 postMomRes = OC_STACK_INVALID_PARAM;
339 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
341 bool isValidOxmsel = false;
342 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
344 if(targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
346 isValidOxmsel = true;
350 VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
352 //Dulpicate doxm resource to update the 'oxmsel' property
353 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
354 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
356 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
357 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
358 VERIFY_NON_NULL(TAG, doxm, ERROR);
360 doxm->oxmSel = oxmSelValue;
362 //Send POST reuqest for update doxm
363 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
364 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
366 OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
369 OICFree(doxmPayload);
370 DeleteDoxmBinData(doxm);
375 * API to provision preconfigured PIN to resource server.
377 * @param[in] targetDeviceInfo Selected target device.
378 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
379 * @param[in] preconfPINLen Byte length of preconfig PIN
380 * @param[in] resultCallback callback provided by API user, callback will be called when
381 * POST credential request recieves a response from resource server.
382 * @return OC_STACK_OK in case of success and other value otherwise.
384 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
385 const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
387 OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
388 bool freeFlag = true;
389 OCSecurityPayload* secPayload = NULL;
390 MOTContext_t *motCtx = NULL;
391 OicSecCred_t* pinCred = NULL;
393 OIC_LOG(DEBUG, TAG, "IN MOTProvisionPreconfigPIN");
395 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
396 postCredRes = OC_STACK_INVALID_PARAM;
397 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
398 VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
399 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
400 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_SIZE >= preconfPINLen), ERROR);
402 postCredRes = OC_STACK_NO_MEMORY;
403 //Generate PIN based credential
404 pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
405 VERIFY_NON_NULL(TAG, pinCred, ERROR);
407 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
408 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
410 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
411 pinCred->privateData.data[preconfPINLen] = '\0';
412 pinCred->privateData.len = preconfPINLen;
413 pinCred->privateData.encoding = OIC_ENCODING_RAW;
414 pinCred->credType = PIN_PASSWORD;
415 OICStrcpy(pinCred->subject.id, sizeof(pinCred->subject.id), WILDCARD_SUBJECT_ID.id);
417 //Generate the security payload using updated doxm
418 secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
419 VERIFY_NON_NULL(TAG, secPayload, ERROR);
420 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
422 postCredRes = CredToCBORPayload(pinCred, &secPayload->securityData, &secPayload->payloadSize, false);
423 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
425 OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
426 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
428 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
429 bool queryGenRes = PMGenerateQuery(true,
430 targetDeviceInfo->endpoint.addr,
431 targetDeviceInfo->securePort,
432 targetDeviceInfo->connType,
433 query, sizeof(query), OIC_RSRC_CRED_URI);
434 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
435 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
437 //Create the MOT Context to handle the response message
438 motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
439 VERIFY_NON_NULL(TAG, motCtx, ERROR);
440 motCtx->deviceInfo = targetDeviceInfo;
441 motCtx->resultCallback = resultCallback;
442 motCtx->numOfResults=1;
443 motCtx->hasError = false;
445 motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
446 VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
449 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
450 cbData.cb = &MOTUpdateSecurityResourceCB;
451 cbData.context = (void *)motCtx;
452 OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
453 postCredRes = OCDoResource(NULL, OC_REST_POST, query,
454 &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
455 targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
456 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
460 OIC_LOG(DEBUG, TAG, "OUT MOTProvisionPreconfigPIN");
465 //If POST request successfully sent, motCtx will be cleaned from response handler.
466 if(freeFlag && motCtx)
468 OICFree(motCtx->resArr);
473 OICFree(pinCred->privateData.data);
480 /**********************************************************************
482 **********************************************************************/
484 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
485 OCProvisionDev_t* selectedDevice);
488 * Array to store the callbacks for each owner transfer method.
490 static OTMCallbackData_t g_MOTCbDatas[OIC_OXM_COUNT] = {
492 {.loadSecretCB = LoadSecretJustWorksCallback,
493 .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
494 .createSelectOxmPayloadCB = NULL,
495 .createOwnerTransferPayloadCB = NULL},
498 {.loadSecretCB = InputPinCodeCallback,
499 .createSecureSessionCB = CreateSecureSessionRandomPinCallback,
500 .createSelectOxmPayloadCB = NULL,
501 .createOwnerTransferPayloadCB = NULL},
504 {.loadSecretCB = NULL,
505 .createSecureSessionCB = NULL,
506 .createSelectOxmPayloadCB = NULL,
507 .createOwnerTransferPayloadCB = NULL},
510 {.loadSecretCB = LoadPreconfPinCodeCallback,
511 .createSecureSessionCB = CreateSecureSessionPreconfPinCallback,
512 .createSelectOxmPayloadCB = NULL,
513 .createOwnerTransferPayloadCB = NULL},
516 static OTMContext_t* g_MotCtx = NULL;
518 static bool IsComplete(OTMContext_t* otmCtx)
520 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
522 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
532 * Function to save the result of multiple ownership transfer.
534 * @param[in,out] motCtx Context instance of multiple ownership transfer.
535 * @param[in] res result of multiple ownership transfer.
537 static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
539 OIC_LOG_V(DEBUG, TAG, "IN SetMOTResult : %d ", res);
541 VERIFY_NON_NULL(TAG, motCtx, ERROR);
543 if(motCtx->selectedDeviceInfo)
545 //Revert psk_info callback in case of random PIN OxM
546 if(OIC_RANDOM_DEVICE_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel ||
547 OIC_PRECONFIG_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel)
549 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
551 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
553 OicUuid_t emptyUuid = { .id={0}};
554 SetUuidForPinBasedOxm(&emptyUuid);
557 for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
559 if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
560 motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
562 motCtx->ctxResultArray[i].res = res;
563 if(OC_STACK_OK != res)
565 motCtx->ctxHasError = true;
572 //If all request is completed, invoke the user callback.
573 if(IsComplete(motCtx))
575 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
576 motCtx->ctxResultArray, motCtx->ctxHasError);
578 OICFree(motCtx->ctxResultArray);
583 if(OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
584 motCtx->selectedDeviceInfo->next))
586 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
592 OIC_LOG(DEBUG, TAG, "OUT SetMOTResult");
596 * API to add preconfigured PIN to local SVR DB.
598 * @param[in] targetDeviceInfo Selected target device.
599 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
600 * @param[in] preconfPINLen Byte length of preconfig PIN
601 * @param[in] resultCallback callback provided by API user, callback will be called when
602 * POST credential request recieves a response from resource server.
603 * @return OC_STACK_OK in case of success and other value otherwise.
605 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
606 const char* preconfPIN, size_t preconfPINLen)
608 OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
609 OicSecCred_t* pinCred = NULL;
610 bool freeFlag = true;
612 OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
614 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
615 VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
616 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
617 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_SIZE >= preconfPINLen), ERROR);
619 OicSecCred_t* prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
622 OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
626 addCredRes = OC_STACK_NO_MEMORY;
627 //Generate PIN based credential
628 pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
629 VERIFY_NON_NULL(TAG, pinCred, ERROR);
631 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
632 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
634 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
635 pinCred->privateData.data[preconfPINLen] = '\0';
636 pinCred->privateData.len = preconfPINLen;
637 pinCred->privateData.encoding = OIC_ENCODING_RAW;
638 pinCred->credType = PIN_PASSWORD;
639 memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
641 addCredRes = AddCredential(pinCred);
642 VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
644 OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
651 OICFree(pinCred->privateData.data);
658 * Function to save the SubOwner PSK.
660 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
661 * @return OC_STACK_OK on success
663 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
665 OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
667 OCStackResult res = OC_STACK_ERROR;
669 CAEndpoint_t endpoint;
670 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
671 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
672 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
673 endpoint.port = selectedDeviceInfo->securePort;
674 endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
676 OicUuid_t ownerDeviceID = {.id={0}};
677 if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
679 OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
683 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
684 OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
686 //Generating SubOwnerPSK
687 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
688 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
689 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
690 ownerDeviceID.id, sizeof(ownerDeviceID.id),
691 selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
692 ownerPSK, OWNER_PSK_LENGTH_128);
694 if (CA_STATUS_OK == pskRet)
696 OIC_LOG(INFO, TAG, "SubOwner PSK dump:");
697 OIC_LOG_BUFFER(INFO, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
698 //Generating new credential for provisioning tool
699 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
700 SYMMETRIC_PAIR_WISE_KEY, NULL,
701 &ownerKey, &ownerDeviceID, &ownerDeviceID);
702 VERIFY_NON_NULL(TAG, cred, ERROR);
704 uint32_t outSize = 0;
705 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
706 char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
707 VERIFY_NON_NULL(TAG, b64Buf, ERROR);
708 b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
710 OICFree( cred->privateData.data );
711 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
712 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
714 strncpy(cred->privateData.data, b64Buf, outSize);
715 cred->privateData.data[outSize] = '\0';
716 cred->privateData.encoding = OIC_ENCODING_BASE64;
717 cred->privateData.len = outSize;
721 res = AddCredential(cred);
722 if(res != OC_STACK_OK)
724 DeleteCredList(cred);
730 OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
733 OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
740 * Response handler for update subowner crendetial request.
742 * @param[in] ctx ctx value passed to callback from calling function.
743 * @param[in] UNUSED handle to an invocation
744 * @param[in] clientResponse Response from queries to remote servers.
745 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
746 * and OC_STACK_KEEP_TRANSACTION to keep it.
748 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
749 OCClientResponse *clientResponse)
751 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
752 VERIFY_NON_NULL(TAG, ctx, WARNING);
754 OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
756 OCStackResult res = OC_STACK_ERROR;
757 OTMContext_t* motCtx = (OTMContext_t*)ctx;
759 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
761 if(motCtx && motCtx->selectedDeviceInfo)
763 //Close the temporal secure session to verify the owner credential
764 CAEndpoint_t* endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
765 endpoint->port = motCtx->selectedDeviceInfo->securePort;
766 CAResult_t caResult = CAcloseSslSession(endpoint);
767 if(CA_STATUS_OK != caResult)
769 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
770 SetMOTResult(motCtx, OC_STACK_ERROR);
771 return OC_STACK_DELETE_TRANSACTION;
774 // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
775 caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
776 if(CA_STATUS_OK != caResult)
778 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
779 SetMOTResult(motCtx, OC_STACK_ERROR);
780 return OC_STACK_DELETE_TRANSACTION;
783 res = PDMAddDevice(&motCtx->selectedDeviceInfo->doxm->deviceID);
784 if (OC_STACK_OK == res)
786 OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
790 OIC_LOG(ERROR, TAG, "MOT is complete but adding information to DB is failed.");
793 SetMOTResult(motCtx, res);
798 res = clientResponse->result;
799 OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d", res);
800 SetMOTResult(motCtx, res);
803 OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
806 return OC_STACK_DELETE_TRANSACTION;
810 static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
812 OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
814 if(!motCtx || !motCtx->selectedDeviceInfo)
816 OIC_LOG(ERROR, TAG, "Invalid parameters");
817 return OC_STACK_INVALID_PARAM;
820 OCProvisionDev_t* deviceInfo = motCtx->selectedDeviceInfo;
821 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
823 if(!PMGenerateQuery(true,
824 deviceInfo->endpoint.addr, deviceInfo->securePort,
825 deviceInfo->connType,
826 query, sizeof(query), OIC_RSRC_CRED_URI))
828 OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
829 return OC_STACK_ERROR;
831 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
832 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
835 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
836 return OC_STACK_NO_MEMORY;
839 //Generate sub-owner credential for new device
840 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
841 const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
844 OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
845 return OC_STACK_NO_RESOURCE;
848 OicUuid_t ownerId = {.id={0}};
849 if(OC_STACK_OK == GetDoxmDeviceID(&ownerId))
851 OicSecCred_t newCredential;
852 memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
853 newCredential.next = NULL;
855 //Set subject ID as SubOwner's ID
856 memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
858 //Set eowner ID as SubOwner's ID
859 if(NULL == newCredential.eownerID)
861 newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
862 if(NULL == newCredential.eownerID)
864 return OC_STACK_NO_MEMORY;
867 memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
869 //Fill private data as empty string
870 newCredential.privateData.data = "";
871 newCredential.privateData.len = 0;
872 newCredential.privateData.encoding = ownerCredential->privateData.encoding;
874 newCredential.publicData.data = NULL;
875 newCredential.publicData.len = 0;
877 //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
878 if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
879 &secPayload->payloadSize, 0))
882 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
883 return OC_STACK_ERROR;
885 OIC_LOG(DEBUG, TAG, "Cred Payload:");
886 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
888 OCCallbackData cbData;
889 cbData.cb = &SubOwnerCredentialHandler;
890 cbData.context = (void *)motCtx;
892 OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
893 &deviceInfo->endpoint, (OCPayload*)secPayload,
894 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
895 if (res != OC_STACK_OK)
897 OIC_LOG(ERROR, TAG, "OCStack resource error");
902 OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
903 return OC_STACK_NO_RESOURCE;
906 OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
913 * Function to handle the handshake result in MOT.
914 * This function will be invoked after DTLS handshake
915 * @param endPoint [IN] The remote endpoint.
916 * @param errorInfo [IN] Error information from the endpoint.
919 static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
921 if(NULL != g_MotCtx && NULL != g_MotCtx->selectedDeviceInfo &&
922 NULL != endpoint && NULL != info)
924 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
925 endpoint->addr, endpoint->port, info->result);
927 OicSecDoxm_t* newDevDoxm = g_MotCtx->selectedDeviceInfo->doxm;
929 if(NULL != newDevDoxm)
931 OicUuid_t emptyUuid = {.id={0}};
933 //Make sure the address matches.
934 if(strncmp(g_MotCtx->selectedDeviceInfo->endpoint.addr,
936 sizeof(endpoint->addr)) == 0 &&
937 g_MotCtx->selectedDeviceInfo->securePort == endpoint->port)
939 OCStackResult res = OC_STACK_ERROR;
941 //If temporal secure sesstion established successfully
942 if(CA_STATUS_OK == info->result)
944 //Delete previous credential such as preconfigured-pin
945 RemoveCredential(&(g_MotCtx->selectedDeviceInfo->doxm->deviceID));
947 res = SaveSubOwnerPSK(g_MotCtx->selectedDeviceInfo);
948 if(OC_STACK_OK == res)
950 //POST sub owner credential to new device.
951 res = PostSubOwnerCredential(g_MotCtx);
952 if(OC_STACK_OK != res)
955 "Failed to send POST request for SubOwner Credential");
956 SetMOTResult(g_MotCtx, res);
961 OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
962 SetMOTResult(g_MotCtx, res);
965 //In case of authentication failure
966 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
968 //in case of error from wrong PIN, re-start the ownership transfer
969 if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
971 OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
973 g_MotCtx->attemptCnt++;
975 if(WRONG_PIN_MAX_ATTEMP > g_MotCtx->attemptCnt)
977 res = StartMultipleOwnershipTransfer(g_MotCtx, g_MotCtx->selectedDeviceInfo);
978 if(OC_STACK_OK != res)
980 SetMOTResult(g_MotCtx, res);
981 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
986 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
987 SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
992 OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
993 SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
1001 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
1002 OCProvisionDev_t* selectedDevice)
1004 OIC_LOG(INFO, TAG, "IN StartMultipleOwnershipTransfer");
1005 OCStackResult res = OC_STACK_INVALID_PARAM;
1007 VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
1008 VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
1010 motCtx->selectedDeviceInfo = selectedDevice;
1012 //Register DTLS event handler to catch the dtls event while handshake
1013 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1015 OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1018 size_t oxmSel = (size_t)(selectedDevice->doxm->oxmSel);
1019 OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", selectedDevice->doxm->oxmSel);
1021 if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
1023 OIC_LOG(ERROR, TAG, "Unsupported OxM");
1024 return OC_STACK_ERROR;
1027 if(OIC_RANDOM_DEVICE_PIN == selectedDevice->doxm->oxmSel)
1029 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1031 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
1035 res = g_MOTCbDatas[oxmSel].loadSecretCB(motCtx);
1036 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1038 //Save the current context instance to use on the dtls handshake callback
1041 res = g_MOTCbDatas[oxmSel].createSecureSessionCB(motCtx);
1042 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1044 OIC_LOG(INFO, TAG, "OUT StartMultipleOwnershipTransfer");
1050 OCStackResult MOTDoOwnershipTransfer(void* ctx,
1051 OCProvisionDev_t *selectedDevicelist,
1052 OCProvisionResultCB resultCallback)
1054 OIC_LOG(DEBUG, TAG, "IN MOTDoOwnershipTransfer");
1055 OCStackResult res = OC_STACK_INVALID_PARAM;
1056 OTMContext_t* motCtx = NULL;
1057 OCProvisionDev_t* pCurDev = NULL;
1059 VERIFY_NON_NULL(TAG, selectedDevicelist, ERROR);
1060 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
1062 res = OC_STACK_NO_MEMORY;
1063 motCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1064 VERIFY_NON_NULL(TAG, motCtx, ERROR);
1066 motCtx->ctxResultCallback = resultCallback;
1067 motCtx->ctxHasError = false;
1068 motCtx->userCtx = ctx;
1069 motCtx->ctxResultArraySize = 0;
1070 LL_FOREACH(selectedDevicelist, pCurDev)
1072 motCtx->ctxResultArraySize++;
1075 motCtx->ctxResultArray =
1076 (OCProvisionResult_t*)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1077 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
1079 //Fill the device UUID for result array.
1083 LL_FOREACH(selectedDevicelist, pCurDev)
1085 //Checking duplication of Device ID.
1086 bool isDuplicate = true;
1087 res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
1088 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1092 bool isStale = false;
1093 res = PDMIsDeviceStale(&pCurDev->doxm->deviceID, &isStale);
1094 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1095 VERIFY_SUCCESS(TAG, isStale, ERROR);
1099 OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "\
1100 "this UUID will be removed from PDM");
1102 res = PDMDeleteDevice(&pCurDev->doxm->deviceID);
1103 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1107 memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1108 pCurDev->doxm->deviceID.id,
1110 motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1114 res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1115 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1117 OIC_LOG(DEBUG, TAG, "OUT MOTDoOwnershipTransfer");
1120 if(OC_STACK_OK != res)
1124 OICFree(motCtx->ctxResultArray);