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"
61 #include "otmcontextlist.h"
63 #define TAG "OIC_MULTIPLE_OTM"
65 /**********************************************************************
67 **********************************************************************/
70 * Callback handler of security resource's POST request.
72 * @param[in] ctx ctx value passed to callback from calling function.
73 * @param[in] UNUSED handle to an invocation
74 * @param[in] clientResponse Response from queries to remote servers.
75 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
76 * and OC_STACK_KEEP_TRANSACTION to keep it.
78 static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
79 OCClientResponse *clientResponse)
81 OIC_LOG_V(INFO, TAG, "Inside MOTUpdateMomCB.");
83 OTMContext_t *motCtx = (OTMContext_t*)ctx;
84 VERIFY_NON_NULL(TAG, motCtx, ERROR);
85 VERIFY_NON_NULL(TAG, motCtx->ctxResultCallback, ERROR);
86 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
90 memcpy(motCtx->ctxResultArray[0].deviceId.id,
91 motCtx->selectedDeviceInfo->doxm->deviceID.id,
93 motCtx->ctxResultArray[0].res = clientResponse->result;
95 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
97 motCtx->ctxHasError = false;
101 motCtx->ctxHasError = true;
106 OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
107 motCtx->ctxResultArray[0].res = OC_STACK_ERROR;
108 motCtx->ctxHasError = true;
111 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
112 motCtx->ctxResultArray, motCtx->ctxHasError);
117 OICFree(motCtx->ctxResultArray);
120 return OC_STACK_DELETE_TRANSACTION;
124 * Internal API to send POST doxm request
126 static OCStackResult MOTSendPostDoxm(void *ctx,
127 const OCProvisionDev_t *targetDeviceInfo,
128 OCProvisionResultCB resultCallback,
129 const OicSecDoxm_t* doxm)
131 OCStackResult postMomRes = OC_STACK_ERROR;
132 OCSecurityPayload* secPayload = NULL;
133 OTMContext_t *motCtx = NULL;
134 bool freeFlag = true;
136 OIC_LOG(DEBUG, TAG, "IN MOTSendPostDoxm");
138 //Generate the security payload using updated doxm
139 secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
140 VERIFY_NON_NULL(TAG, secPayload, ERROR);
141 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
143 postMomRes = DoxmToCBORPayload(doxm, &secPayload->securityData, &secPayload->payloadSize, true);
144 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
146 OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
147 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
149 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
150 bool queryGenRes = PMGenerateQuery(true,
151 targetDeviceInfo->endpoint.addr,
152 targetDeviceInfo->securePort,
153 targetDeviceInfo->connType,
154 query, sizeof(query), OIC_RSRC_DOXM_URI);
155 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
156 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
158 //Create the MOT Context to handle the response message
159 motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
160 VERIFY_NON_NULL(TAG, motCtx, ERROR);
161 motCtx->selectedDeviceInfo = targetDeviceInfo;
162 motCtx->ctxResultCallback = resultCallback;
163 motCtx->ctxResultArraySize = 1;
164 motCtx->ctxHasError = false;
165 motCtx->userCtx = ctx;
166 motCtx->ctxResultArray= (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
167 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
170 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
171 cbData.cb = &MOTUpdateSecurityResourceCB;
172 cbData.context = (void *)motCtx;
173 OIC_LOG(DEBUG, TAG, "Sending POST 'doxm' request to resource server");
174 postMomRes = OCDoResource(NULL, OC_REST_POST, query,
175 &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
176 targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
177 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
181 OIC_LOG(DEBUG, TAG, "OUT MOTSendPostDoxm");
184 //If POST request successfully sent, motCtx will be cleaned from response handler.
185 if(freeFlag && motCtx)
187 OICFree(motCtx->ctxResultArray);
195 * API to update 'doxm.mom' to resource server.
197 * @param[in] targetDeviceInfo Selected target device.
198 * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
199 * @param[in] resultCallback callback provided by API user, callback will be called when
200 * POST 'mom' request recieves a response from resource server.
201 * @return OC_STACK_OK in case of success and other value otherwise.
203 OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
204 const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
206 OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
207 OicSecDoxm_t* doxm = NULL;
208 uint8_t* doxmPayload = NULL;
209 size_t doxmPayloadLen = 0;
211 OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
213 VERIFY_SUCCESS(TAG, (OIC_NUMBER_OF_MOM_TYPE > momType), ERROR);
214 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
215 postMomRes = OC_STACK_INVALID_CALLBACK;
216 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
218 //Dulpicate doxm resource to update the 'mom' property
219 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
220 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
222 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
223 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
224 VERIFY_NON_NULL(TAG, doxm, ERROR);
226 if(NULL == doxm->mom)
228 postMomRes = OC_STACK_NO_MEMORY;
229 doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
230 VERIFY_NON_NULL(TAG, (doxm->mom), ERROR);
232 doxm->mom->mode = momType;
234 //Send POST reuqest for update doxm
235 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
236 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
238 OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
241 OICFree(doxmPayload);
242 DeleteDoxmBinData(doxm);
247 * API to add 'doxm.oxms' to resource server.
249 * @param[in] targetDeviceInfo Selected target device.
250 * @param[in] newOxm OxMs to be added (ref. oic.sec.oxm)
251 * @param[in] resultCallback callback provided by API user, callback will be called when
252 * POST 'oxms' request recieves a response from resource server.
253 * @return OC_STACK_OK in case of success and other value otherwise.
255 OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
256 const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
258 OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
259 OicSecOxm_t* newOxms = NULL;
260 uint8_t* doxmPayload = NULL;
261 size_t doxmPayloadLen = 0;
263 OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
265 VERIFY_SUCCESS(TAG, (OIC_OXM_COUNT > newOxm || OIC_PRECONFIG_PIN == newOxm), ERROR);
266 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
267 postOxmRes = OC_STACK_INVALID_CALLBACK;
268 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
269 postOxmRes = OC_STACK_NO_MEMORY;
271 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
273 if(targetDeviceInfo->doxm->oxm[i] == newOxm)
275 OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
276 OCProvisionResult_t* resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
277 VERIFY_NON_NULL(TAG, resArr, ERROR);
278 resArr->res = OC_STACK_OK;
279 memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
280 resultCallback(ctx, 1, resArr, false);
285 newOxms = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
286 VERIFY_NON_NULL(TAG, newOxms , ERROR);
288 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
290 newOxms[i] = targetDeviceInfo->doxm->oxm[i];
292 newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
293 targetDeviceInfo->doxm->oxmLen++;
294 OICFree(targetDeviceInfo->doxm->oxm);
295 targetDeviceInfo->doxm->oxm = newOxms;
297 //Send POST reuqest for update doxm
298 postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
299 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
301 OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
304 OICFree(doxmPayload);
309 * API to update 'doxm.oxmsel' to resource server.
311 * @param[in] targetDeviceInfo Selected target device.
312 * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
313 * @param[in] resultCallback callback provided by API user, callback will be called when
314 * POST 'oxmsel' request recieves a response from resource server.
315 * @return OC_STACK_OK in case of success and other value otherwise.
317 OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
318 const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
320 OCStackResult postMomRes = OC_STACK_INVALID_CALLBACK;
321 OicSecDoxm_t* doxm = NULL;
322 uint8_t* doxmPayload = NULL;
323 size_t doxmPayloadLen = 0;
325 OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
327 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
328 postMomRes = OC_STACK_INVALID_PARAM;
329 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
331 bool isValidOxmsel = false;
332 for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
334 if(targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
336 isValidOxmsel = true;
340 VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
342 //Dulpicate doxm resource to update the 'oxmsel' property
343 postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
344 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
346 postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
347 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
348 VERIFY_NON_NULL(TAG, doxm, ERROR);
350 doxm->oxmSel = oxmSelValue;
352 //Send POST reuqest for update doxm
353 postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
354 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
356 OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
359 OICFree(doxmPayload);
360 DeleteDoxmBinData(doxm);
365 * API to provision preconfigured PIN to resource server.
367 * @param[in] targetDeviceInfo Selected target device.
368 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
369 * @param[in] preconfPINLen Byte length of preconfig PIN
370 * @param[in] resultCallback callback provided by API user, callback will be called when
371 * POST credential request recieves a response from resource server.
372 * @return OC_STACK_OK in case of success and other value otherwise.
374 OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
375 const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
377 OCStackResult postCredRes = OC_STACK_INVALID_CALLBACK;
378 bool freeFlag = true;
379 OCSecurityPayload* secPayload = NULL;
380 OTMContext_t *motCtx = NULL;
381 OicSecCred_t* pinCred = NULL;
383 OIC_LOG(DEBUG, TAG, "IN MOTProvisionPreconfigPIN");
385 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
386 postCredRes = OC_STACK_INVALID_PARAM;
387 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
388 VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
389 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
390 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
392 postCredRes = OC_STACK_NO_MEMORY;
393 //Generate PIN based credential
394 pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
395 VERIFY_NON_NULL(TAG, pinCred, ERROR);
397 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
398 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
400 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
401 pinCred->privateData.data[preconfPINLen] = '\0';
402 pinCred->privateData.len = preconfPINLen;
403 pinCred->privateData.encoding = OIC_ENCODING_RAW;
404 pinCred->credType = PIN_PASSWORD;
405 OICStrcpy(pinCred->subject.id, sizeof(pinCred->subject.id), WILDCARD_SUBJECT_ID.id);
407 //Generate the security payload using updated doxm
408 secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
409 VERIFY_NON_NULL(TAG, secPayload, ERROR);
410 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
412 postCredRes = CredToCBORPayload(pinCred, &secPayload->securityData, &secPayload->payloadSize, false);
413 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
415 OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
416 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
418 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
419 bool queryGenRes = PMGenerateQuery(true,
420 targetDeviceInfo->endpoint.addr,
421 targetDeviceInfo->securePort,
422 targetDeviceInfo->connType,
423 query, sizeof(query), OIC_RSRC_CRED_URI);
424 VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
425 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
427 //Create the MOT Context to handle the response message
428 motCtx = (OTMContext_t*)OICCalloc(1, sizeof(OTMContext_t));
429 VERIFY_NON_NULL(TAG, motCtx, ERROR);
430 motCtx->selectedDeviceInfo= targetDeviceInfo;
431 motCtx->ctxResultCallback = resultCallback;
432 motCtx->ctxResultArraySize =1;
433 motCtx->ctxHasError = false;
434 motCtx->userCtx = ctx;
435 motCtx->ctxResultArray = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
436 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
439 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
440 cbData.cb = &MOTUpdateSecurityResourceCB;
441 cbData.context = (void *)motCtx;
442 OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
443 postCredRes = OCDoResource(NULL, OC_REST_POST, query,
444 &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
445 targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
446 VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
450 OIC_LOG(DEBUG, TAG, "OUT MOTProvisionPreconfigPIN");
455 //If POST request successfully sent, motCtx will be cleaned from response handler.
456 if(freeFlag && motCtx)
458 OICFree(motCtx->ctxResultArray);
463 OICFree(pinCred->privateData.data);
470 /**********************************************************************
472 **********************************************************************/
474 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
475 OCProvisionDev_t* selectedDevice);
477 static OTMContext_t* g_MotCtx = NULL;
479 static bool IsComplete(OTMContext_t* otmCtx)
481 for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
483 if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
493 * Function to save the result of multiple ownership transfer.
495 * @param[in,out] motCtx Context instance of multiple ownership transfer.
496 * @param[in] res result of multiple ownership transfer.
498 static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
500 OIC_LOG_V(DEBUG, TAG, "IN SetMOTResult : %d ", res);
501 VERIFY_NON_NULL(TAG, motCtx, ERROR);
503 if(motCtx->selectedDeviceInfo)
505 //Revert psk_info callback in case of random PIN OxM
506 if(OIC_RANDOM_DEVICE_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel ||
507 OIC_PRECONFIG_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel)
509 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
511 OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
513 OicUuid_t emptyUuid = { .id={0}};
514 SetUuidForPinBasedOxm(&emptyUuid);
517 OCStackResult pdmRetVal = PDMSetDeviceState(&motCtx->selectedDeviceInfo->doxm->deviceID,
519 if (OC_STACK_OK != pdmRetVal)
521 OIC_LOG_V(ERROR, TAG, "Failed to add device information into PDM_DB : %d", res);
524 for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
526 if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
527 motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
529 motCtx->ctxResultArray[i].res = res;
530 if(OC_STACK_OK != res)
532 motCtx->ctxHasError = true;
537 //Remove the current OTM Context from OTM queue
538 RemoveOTMContext(motCtx->selectedDeviceInfo->endpoint.addr,
539 motCtx->selectedDeviceInfo->securePort);
541 //If there is a request being performed, cancel it to prevent retransmission.
542 if(motCtx->ocDoHandle)
544 if (OC_STACK_OK != OCCancel(motCtx->ocDoHandle, OC_HIGH_QOS, NULL, 0))
546 OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
548 motCtx->ocDoHandle = NULL;
551 //If all request is completed, invoke the user callback.
552 if(IsComplete(motCtx))
554 motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
555 motCtx->ctxResultArray, motCtx->ctxHasError);
557 OICFree(motCtx->ctxResultArray);
562 if(OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
563 motCtx->selectedDeviceInfo->next))
565 OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
571 OIC_LOG(DEBUG, TAG, "OUT SetMOTResult");
575 * API to add preconfigured PIN to local SVR DB.
577 * @param[in] targetDeviceInfo Selected target device.
578 * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
579 * @param[in] preconfPINLen Byte length of preconfig PIN
580 * @param[in] resultCallback callback provided by API user, callback will be called when
581 * POST credential request recieves a response from resource server.
582 * @return OC_STACK_OK in case of success and other value otherwise.
584 OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
585 const char* preconfPIN, size_t preconfPINLen)
587 OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
588 OicSecCred_t* pinCred = NULL;
589 bool freeFlag = true;
591 OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
593 VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
594 VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
595 VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
596 VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_MAX_SIZE >= preconfPINLen), ERROR);
598 OicSecCred_t* prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
601 OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
605 addCredRes = OC_STACK_NO_MEMORY;
606 //Generate PIN based credential
607 pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
608 VERIFY_NON_NULL(TAG, pinCred, ERROR);
610 pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
611 VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
613 memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
614 pinCred->privateData.data[preconfPINLen] = '\0';
615 pinCred->privateData.len = preconfPINLen;
616 pinCred->privateData.encoding = OIC_ENCODING_RAW;
617 pinCred->credType = PIN_PASSWORD;
618 memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
620 addCredRes = AddCredential(pinCred);
621 VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
623 OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
630 OICFree(pinCred->privateData.data);
637 * Function to save the SubOwner PSK.
639 * @param[in] selectedDeviceInfo selected device information to performing provisioning.
640 * @return OC_STACK_OK on success
642 static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
644 OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
646 OCStackResult res = OC_STACK_ERROR;
648 CAEndpoint_t endpoint;
649 memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
650 OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
651 endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
652 endpoint.port = selectedDeviceInfo->securePort;
653 endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
655 OicUuid_t ownerDeviceID = {.id={0}};
656 if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
658 OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
662 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
663 OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
665 //Generating SubOwnerPSK
666 CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
667 (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
668 strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
669 ownerDeviceID.id, sizeof(ownerDeviceID.id),
670 selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
671 ownerPSK, OWNER_PSK_LENGTH_128);
673 if (CA_STATUS_OK == pskRet)
675 OIC_LOG(DEBUG, TAG, "SubOwner PSK dump:");
676 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
677 //Generating new credential for provisioning tool
678 OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
679 SYMMETRIC_PAIR_WISE_KEY, NULL,
680 &ownerKey, &ownerDeviceID, &ownerDeviceID);
681 VERIFY_NON_NULL(TAG, cred, ERROR);
683 uint32_t outSize = 0;
684 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
685 char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
686 VERIFY_NON_NULL(TAG, b64Buf, ERROR);
687 b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
689 OICFree( cred->privateData.data );
690 cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
691 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
693 strncpy(cred->privateData.data, b64Buf, outSize);
694 cred->privateData.data[outSize] = '\0';
695 cred->privateData.encoding = OIC_ENCODING_BASE64;
696 cred->privateData.len = outSize;
700 res = AddCredential(cred);
701 if(res != OC_STACK_OK)
703 DeleteCredList(cred);
709 OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
712 OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
719 * Response handler for update subowner crendetial request.
721 * @param[in] ctx ctx value passed to callback from calling function.
722 * @param[in] UNUSED handle to an invocation
723 * @param[in] clientResponse Response from queries to remote servers.
724 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
725 * and OC_STACK_KEEP_TRANSACTION to keep it.
727 static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
728 OCClientResponse *clientResponse)
730 VERIFY_NON_NULL(TAG, clientResponse, WARNING);
731 VERIFY_NON_NULL(TAG, ctx, WARNING);
733 OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
735 OTMContext_t* motCtx = (OTMContext_t*)ctx;
737 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
739 if(motCtx && motCtx->selectedDeviceInfo)
741 //Close the temporal secure session to verify the owner credential
742 CAEndpoint_t* endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
743 endpoint->port = motCtx->selectedDeviceInfo->securePort;
744 CAResult_t caResult = CAcloseSslSession(endpoint);
745 if(CA_STATUS_OK != caResult)
747 OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
748 SetMOTResult(motCtx, OC_STACK_ERROR);
749 return OC_STACK_DELETE_TRANSACTION;
752 // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
753 caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
754 if(CA_STATUS_OK != caResult)
756 OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
757 SetMOTResult(motCtx, OC_STACK_ERROR);
758 return OC_STACK_DELETE_TRANSACTION;
761 SetMOTResult(motCtx, OC_STACK_OK);
766 OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d",
767 clientResponse->result);
768 SetMOTResult(motCtx, clientResponse->result);
771 OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
774 return OC_STACK_DELETE_TRANSACTION;
778 static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
780 OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
782 if(!motCtx || !motCtx->selectedDeviceInfo)
784 OIC_LOG(ERROR, TAG, "Invalid parameters");
785 return OC_STACK_INVALID_PARAM;
788 OCProvisionDev_t* deviceInfo = motCtx->selectedDeviceInfo;
789 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
791 if(!PMGenerateQuery(true,
792 deviceInfo->endpoint.addr, deviceInfo->securePort,
793 deviceInfo->connType,
794 query, sizeof(query), OIC_RSRC_CRED_URI))
796 OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
797 return OC_STACK_ERROR;
799 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
800 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
803 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
804 return OC_STACK_NO_MEMORY;
807 //Generate sub-owner credential for new device
808 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
809 const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
812 OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
813 return OC_STACK_NO_RESOURCE;
816 OicUuid_t ownerId = {.id={0}};
817 if(OC_STACK_OK == GetDoxmDeviceID(&ownerId))
819 OicSecCred_t newCredential;
820 memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
821 newCredential.next = NULL;
823 //Set subject ID as SubOwner's ID
824 memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
826 //Set eowner ID as SubOwner's ID
827 if(NULL == newCredential.eownerID)
829 newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
830 if(NULL == newCredential.eownerID)
832 return OC_STACK_NO_MEMORY;
835 memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
837 //Fill private data as empty string
838 newCredential.privateData.data = "";
839 newCredential.privateData.len = 0;
840 newCredential.privateData.encoding = ownerCredential->privateData.encoding;
842 newCredential.publicData.data = NULL;
843 newCredential.publicData.len = 0;
845 //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
846 if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
847 &secPayload->payloadSize, 0))
850 OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
851 return OC_STACK_ERROR;
853 OIC_LOG(DEBUG, TAG, "Cred Payload:");
854 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
856 OCCallbackData cbData;
857 cbData.cb = &SubOwnerCredentialHandler;
858 cbData.context = (void *)motCtx;
860 OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
861 &deviceInfo->endpoint, (OCPayload*)secPayload,
862 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
863 if (res != OC_STACK_OK)
865 OIC_LOG(ERROR, TAG, "OCStack resource error");
870 OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
871 return OC_STACK_NO_RESOURCE;
874 OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
881 * Function to handle the handshake result in MOT.
882 * This function will be invoked after DTLS handshake
883 * @param endPoint [IN] The remote endpoint.
884 * @param errorInfo [IN] Error information from the endpoint.
887 static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
889 OIC_LOG(INFO, TAG, "IN MOTDtlsHandshakeCB");
891 if(NULL != endpoint && NULL != info)
893 OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
894 endpoint->addr, endpoint->port, info->result);
896 OTMContext_t* motCtx = GetOTMContext(endpoint->addr, endpoint->port);
899 OicSecDoxm_t* newDevDoxm = motCtx->selectedDeviceInfo->doxm;
901 if(NULL != newDevDoxm)
903 OicUuid_t emptyUuid = {.id={0}};
905 //Make sure the address matches.
906 if(strncmp(motCtx->selectedDeviceInfo->endpoint.addr,
908 sizeof(endpoint->addr)) == 0 &&
909 motCtx->selectedDeviceInfo->securePort == endpoint->port)
911 OCStackResult res = OC_STACK_ERROR;
913 //If temporal secure sesstion established successfully
914 if(CA_STATUS_OK == info->result)
916 //Delete previous credential such as preconfigured-pin
917 RemoveCredential(&(motCtx->selectedDeviceInfo->doxm->deviceID));
919 res = SaveSubOwnerPSK(motCtx->selectedDeviceInfo);
920 if(OC_STACK_OK == res)
922 //POST sub owner credential to new device.
923 res = PostSubOwnerCredential(motCtx);
924 if(OC_STACK_OK != res)
927 "Failed to send POST request for SubOwner Credential");
928 SetMOTResult(motCtx, res);
933 OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
934 SetMOTResult(motCtx, res);
937 //In case of authentication failure
938 else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
940 //in case of error from wrong PIN, re-start the ownership transfer
941 if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
943 OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
945 motCtx->attemptCnt++;
947 if(WRONG_PIN_MAX_ATTEMP > motCtx->attemptCnt)
949 res = StartMultipleOwnershipTransfer(motCtx, motCtx->selectedDeviceInfo);
950 if(OC_STACK_OK != res)
952 SetMOTResult(motCtx, res);
953 OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
958 OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
959 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
964 OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
965 SetMOTResult(motCtx, OC_STACK_AUTHENTICATION_FAILURE);
973 OIC_LOG_V(ERROR, TAG, "Can not find the [%s:%d]'s OTMContext for MOT", endpoint->addr, endpoint->port);
977 OIC_LOG(INFO, TAG, "OUT MOTDtlsHandshakeCB");
980 static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
981 OCProvisionDev_t* selectedDevice)
983 OIC_LOG(INFO, TAG, "IN StartMultipleOwnershipTransfer");
984 OCStackResult res = OC_STACK_INVALID_PARAM;
986 VERIFY_NON_NULL(TAG, motCtx, ERROR);
987 VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
988 VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
989 motCtx->selectedDeviceInfo = selectedDevice;
991 //Checking duplication of Device ID.
992 char* strUuid = NULL;
993 PdmDeviceState_t deviceState = PDM_DEVICE_UNKNOWN;
994 res = PDMGetDeviceState(&selectedDevice->doxm->deviceID, &deviceState);
995 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
997 res = ConvertUuidToStr(&selectedDevice->doxm->deviceID, &strUuid);
998 if(OC_STACK_OK != res)
1000 OIC_LOG(ERROR, TAG, "Failed to convert UUID to str");
1001 SetMOTResult(motCtx, res);
1005 if(PDM_DEVICE_STALE == deviceState)
1007 OIC_LOG_V(WARNING, TAG, "Detected duplicated UUID in stale status, "
1008 "[%s] will be removed from PDM", strUuid);
1010 res = PDMDeleteDevice(&selectedDevice->doxm->deviceID);
1011 if(OC_STACK_OK != res)
1013 OIC_LOG(ERROR, TAG, "Internal error in PDMDeleteDevice");
1015 SetMOTResult(motCtx, res);
1018 else if(PDM_DEVICE_INIT == deviceState)
1020 OIC_LOG_V(ERROR, TAG, "[%s]'s multiple owner transfer process is already started.", strUuid);
1022 SetMOTResult(motCtx, OC_STACK_DUPLICATE_REQUEST);
1026 res = PDMAddDevice(&selectedDevice->doxm->deviceID);
1027 if (OC_STACK_OK != res)
1029 OIC_LOG_V(INFO, TAG, "Error in PDMAddDevice for [%s]", strUuid);
1031 SetMOTResult(motCtx, res);
1036 //Register DTLS event handler to catch the dtls event while handshake
1037 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
1039 OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
1042 OicSecOxm_t oxmSel = selectedDevice->doxm->oxmSel;
1043 OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", (int)oxmSel);
1045 if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
1047 OIC_LOG(ERROR, TAG, "Unsupported OxM");
1048 return OC_STACK_ERROR;
1051 res = OTMSetOTCallback(selectedDevice->doxm->oxmSel, &motCtx->otmCallback);
1052 if(OC_STACK_OK != res)
1054 OIC_LOG_V(ERROR, TAG, "Error in OTMSetOTCallback : %d", res);
1057 //Only two functions required for MOT
1058 VERIFY_NON_NULL(TAG, motCtx->otmCallback.loadSecretCB, ERROR);
1059 VERIFY_NON_NULL(TAG, motCtx->otmCallback.createSecureSessionCB, ERROR);
1061 if(OIC_RANDOM_DEVICE_PIN == oxmSel)
1063 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
1065 OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
1069 //Save the current context instance to use on the dtls handshake callback
1070 res = AddOTMContext(motCtx, selectedDevice->endpoint.addr, selectedDevice->securePort);
1071 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1073 res = motCtx->otmCallback.loadSecretCB(motCtx);
1074 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1076 res = motCtx->otmCallback.createSecureSessionCB(motCtx);
1077 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1079 OIC_LOG(INFO, TAG, "OUT StartMultipleOwnershipTransfer");
1085 OCStackResult MOTDoOwnershipTransfer(void* ctx,
1086 OCProvisionDev_t *selectedDevicelist,
1087 OCProvisionResultCB resultCallback)
1089 OIC_LOG(DEBUG, TAG, "IN MOTDoOwnershipTransfer");
1090 OCStackResult res = OC_STACK_INVALID_PARAM;
1091 OTMContext_t* motCtx = NULL;
1092 OCProvisionDev_t* pCurDev = NULL;
1094 VERIFY_NON_NULL(TAG, selectedDevicelist, ERROR);
1095 VERIFY_NON_NULL(TAG, resultCallback, ERROR);
1097 res = OC_STACK_NO_MEMORY;
1098 motCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
1099 VERIFY_NON_NULL(TAG, motCtx, ERROR);
1101 motCtx->ctxResultCallback = resultCallback;
1102 motCtx->ctxHasError = false;
1103 motCtx->userCtx = ctx;
1104 motCtx->ctxResultArraySize = 0;
1105 LL_FOREACH(selectedDevicelist, pCurDev)
1107 motCtx->ctxResultArraySize++;
1110 motCtx->ctxResultArray =
1111 (OCProvisionResult_t*)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
1112 VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
1114 //Fill the device UUID for result array.
1117 LL_FOREACH(selectedDevicelist, pCurDev)
1119 memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
1120 pCurDev->doxm->deviceID.id,
1122 motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
1126 motCtx->selectedDeviceInfo = selectedDevicelist;
1127 res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
1128 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1130 OIC_LOG(DEBUG, TAG, "OUT MOTDoOwnershipTransfer");
1133 if(OC_STACK_OK != res)
1137 OICFree(motCtx->ctxResultArray);