1 /* *****************************************************************
3 * Copyright 2015 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 * *****************************************************************/
20 #include "iotivity_config.h"
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
31 #include "oic_malloc.h"
32 #include "oic_string.h"
33 #include "aclresource.h"
34 #include "pstatresource.h"
35 #include "srmresourcestrings.h"
36 #include "credresource.h"
37 #include "csrresource.h"
38 #include "rolesresource.h"
39 #include "doxmresource.h"
40 #include "pconfresource.h"
41 #include "credentialgenerator.h"
42 #include "cainterface.h"
43 #include "oic_string.h"
45 #include "pmutility.h"
46 #include "srmutility.h"
47 #include "provisioningdatabasemanager.h"
50 #include "ocpayload.h"
51 #include "srmutility.h"
52 #include "certhelpers.h"
55 #include "crlresource.h"
58 #define TAG "OIC_SRPAPI"
60 trustCertChainContext_t g_trustCertChainNotifier;
62 // Enum type index for data types.
65 CHAIN_TYPE = 0, /**< Certificate trust chain.**/
66 ACL_TYPE, /**< Access control list.**/
67 PSK_TYPE, /**< Pre-Shared Key.**/
68 CERT_TYPE /**< X.509 certificate.**/
72 * Structure to carry general data to callback.
76 void *ctx; /**< Pointer to user context.**/
77 DataType_t type; /**< Data type of the context.**/
81 * Structure to carry credential data to callback.
83 typedef struct CredentialData
85 void *ctx; /**< Pointer to user context.**/
86 const OCProvisionDev_t *deviceInfo[2]; /**< Array of pointers to OCProvisionDev_t.**/
87 OicSecCred_t *credInfo[2]; /**< Array of pointers to OicSecCred_t.**/
88 int currIndex; /**< Index of current remote device.**/
89 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
90 OCProvisionResult_t *resArr; /**< Result array.**/
91 int numOfResults; /**< Number of results in result array.**/
92 OicSecCredType_t type; /**< Type of credentials to be provisioned to the device.**/
93 size_t keySize; /**< Size of key.**/
94 const char *pemCert; /**< Certificate (SIGNED_ASYMMETRIC_KEY) encoded as PEM.**/
95 const OicSecRole_t *role1; /**< Role of the deviceInfo[0].**/
96 const OicSecRole_t *role2; /**< Role of the deviceInfo[1].**/
100 * Structure to carry ACL provision API data to callback.
102 typedef struct ACLData
104 void *ctx; /**< Pointer to user context.**/
105 const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
106 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
107 OCProvisionResult_t *resArr; /**< Result array.**/
108 int numOfResults; /**< Number of results in result array.**/
110 OicSecAclVersion_t aclVersion;
114 * Structure to carry Trust Chain provision API data to callback.
116 typedef struct TrustChainData
118 void *ctx; /**< Pointer to user context.**/
119 const OCProvisionDev_t *targetDev; /**< Pointer to OCProvisionDev_t.**/
120 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
121 uint16_t credId; /**< Trust chain id to be provisioned.**/
122 OCProvisionResult_t *resArr; /**< Result array.**/
123 int numOfResults; /**< Number of results in result array.**/
127 // Structure to carry get security resource APIs data to callback.
128 typedef struct GetSecData GetSecData_t;
131 const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
132 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
133 OCProvisionResult_t *resArr; /**< Result array.**/
134 int numOfResults; /**< Number of results in result array.**/
137 typedef struct GetCsrData GetCsrData_t;
140 const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
141 OCGetCSRResultCB resultCallback; /**< Pointer to result callback.**/
142 OCPMGetCsrResult_t *resArr; /**< Result array.**/
143 size_t numOfResults; /**< Number of results in result array.**/
146 typedef struct GetRolesData GetRolesData_t;
147 struct GetRolesData {
148 void *ctx; /**< User-provided context **/
149 const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
150 OCGetRolesResultCB resultCallback; /**< Pointer to result callback.**/
151 OCPMGetRolesResult_t *resArr; /**< Result array.**/
152 size_t numOfResults; /**< Number of results in result array.**/
156 * Structure to carry PCONF provision API data to callback.
158 typedef struct PconfData PconfData_t;
161 void *ctx; /**< Pointer to user context.**/
162 const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
163 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
164 OCProvisionResult_t *resArr; /**< Result array.**/
165 int numOfResults; /**< Number of results in result array.**/
168 // Enum type index for unlink callback.
170 IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
171 IDX_SECOND_DEVICE_RES, // index for result of the second device
172 IDX_DB_UPDATE_RES // index for result of updating provisioning database.
175 // Structure to carry unlink APIs data to callback.
176 typedef struct UnlinkData UnlinkData_t;
179 OCProvisionDev_t* unlinkDev; /**< Pointer to OCProvisionDev_t to be unlinked.**/
180 OCProvisionResult_t* unlinkRes; /**< Result array.**/
181 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
182 int numOfResults; /**< Number of results in result array.**/
185 //Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
186 const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
187 const char * SRP_FORM_DELETE_CREDENTIAL_TCP = "coaps+tcp://[%s]:%d%s?%s=%s";
189 // Structure to carry remove APIs data to callback.
190 typedef struct RemoveData RemoveData_t;
193 OCProvisionDev_t* revokeTargetDev; /**< Device which is going to be revoked..**/
194 OCProvisionDev_t* linkedDevList; /**< A list of devices which have invalid credential.**/
195 OCProvisionResult_t* removeRes; /**< Result array.**/
196 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
197 size_t numOfResults; /**< Number of results in result array.**/
198 size_t sizeOfResArray;
203 * Function prototypes
205 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
206 const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler);
207 static OCStackResult provisionCredentials(OicSecCred_t *cred,
208 const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
209 OCClientResponseHandler responseHandler);
210 static OCStackApplicationResult ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
211 OCClientResponse *clientResponse);
212 static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
213 OCClientResponseHandler resultCallback);
218 DEVICE_LOCAL_FINISHED
219 } CredProvisioningResultCause_t;
222 * Deallocates a block of memory.
224 * @param[in] data Pointer to block of memory previously allocated for Data_t.
226 static void FreeData(Data_t *data)
232 TrustChainData_t *chainData = (TrustChainData_t *) data->ctx;
233 OICFree(chainData->resArr);
239 ACLData_t *aclData = (ACLData_t *) data->ctx;
240 OICFree(aclData->resArr);
246 CredentialData_t *pskData = (CredentialData_t *) data->ctx;
247 OICFree(pskData->resArr);
253 OIC_LOG_V(INFO, TAG, "Unknown type %d", data->type);
260 * Internal function to update result in result array.
262 static void registerResultForCredProvisioning(CredentialData_t *credData,
263 OCStackResult stackresult, CredProvisioningResultCause_t cause)
265 OCStackResult res = OC_STACK_ERROR;
266 OIC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
269 case DEVICE_1_FINISHED:
270 memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
271 credData->deviceInfo[0]->doxm->deviceID.id,UUID_LENGTH);
273 case DEVICE_2_FINISHED:
274 memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
275 credData->deviceInfo[1]->doxm->deviceID.id,UUID_LENGTH);
277 case DEVICE_LOCAL_FINISHED:
278 res = GetDoxmDeviceID(&credData->resArr[(credData->numOfResults)].deviceId);
279 if (OC_STACK_OK != res)
281 OIC_LOG_V(WARNING, TAG, "%s: Could not retrieve own device ID to populate result for cred provisioning: %d", __func__, res);
282 memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
286 assert(!"Unknown value for cause");
287 OIC_LOG_V(ERROR, TAG, "%s: unknown value of cause: %d", __func__, cause);
288 memset(credData->resArr[(credData->numOfResults)].deviceId.id, 0, UUID_LENGTH);
291 credData->resArr[(credData->numOfResults)].res = stackresult;
292 ++(credData->numOfResults);
296 * Callback handler for handling callback of provisioning device 2.
298 * @param[in] ctx ctx value passed to callback from calling function.
299 * @param[in] UNUSED handle to an invocation
300 * @param[in] clientResponse Response from queries to remote servers.
301 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
302 * and OC_STACK_KEEP_TRANSACTION to keep it.
304 static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
305 OCClientResponse *clientResponse)
307 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
308 CredentialData_t *credData = (CredentialData_t *) ctx;
311 OCProvisionResultCB resultCallback = credData->resultCallback;
312 OIC_LOG(INFO, TAG, "provisionCredentialCB2 called");
315 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
317 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
318 OCStackResult res = PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
319 &credData->deviceInfo[1]->doxm->deviceID);
320 if (OC_STACK_OK != res)
322 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
323 return OC_STACK_DELETE_TRANSACTION;
325 OIC_LOG(INFO, TAG, "Link created successfully");
327 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
330 OICFree(credData->resArr);
332 return OC_STACK_DELETE_TRANSACTION;
336 OIC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
337 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
338 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
341 OICFree(credData->resArr);
343 return OC_STACK_DELETE_TRANSACTION;
347 * Callback handler for handling callback of provisioning device 1.
349 * @param[in] ctx ctx value passed to callback from calling function.
350 * @param[in] UNUSED handle to an invocation
351 * @param[in] clientResponse Response from queries to remote servers.
352 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
353 * and OC_STACK_KEEP_TRANSACTION to keep it.
355 static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
356 OCClientResponse *clientResponse)
358 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
360 CredentialData_t* credData = (CredentialData_t*) ctx;
361 OICFree(credData->credInfo[0]);
362 const OCProvisionDev_t *deviceInfo = credData->deviceInfo[1];
363 OicSecCred_t *credInfo = credData->credInfo[1];
364 const OCProvisionResultCB resultCallback = credData->resultCallback;
367 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
369 // send credentials to second device
370 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
371 OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
372 provisionCredentialCB2);
373 // If deviceInfo is NULL, this device is the second device. Don't delete the cred
374 // because provisionCredentials added it to the local cred store and it now owns
376 if ((NULL != deviceInfo) || (OC_STACK_OK != res))
378 DeleteCredList(credInfo);
380 if (OC_STACK_OK != res)
382 registerResultForCredProvisioning(credData, res,2);
383 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
386 OICFree(credData->resArr);
393 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
394 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
397 OICFree(credData->resArr);
404 OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
405 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
406 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
409 DeleteCredList(credInfo);
410 OICFree(credData->resArr);
414 return OC_STACK_DELETE_TRANSACTION;
418 * Callback handler for handling callback of provisioning device 2.
420 * @param[in] ctx ctx value passed to callback from calling function.
421 * @param[in] UNUSED handle to an invocation
422 * @param[in] clientResponse Response from queries to remote servers.
423 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
424 * and OC_STACK_KEEP_TRANSACTION to keep it.
426 static OCStackApplicationResult ProvisionCredentialDosCB2(void *ctx, OCDoHandle UNUSED,
427 OCClientResponse *clientResponse)
429 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
430 CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
433 OCProvisionResultCB resultCallback = credData->resultCallback;
434 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
437 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
439 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_2_FINISHED);
440 OCStackResult res = PDMLinkDevices(&credData->deviceInfo[0]->doxm->deviceID,
441 &credData->deviceInfo[1]->doxm->deviceID);
442 if (OC_STACK_OK != res)
444 OIC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
445 return OC_STACK_DELETE_TRANSACTION;
447 OIC_LOG(INFO, TAG, "Link created successfully");
449 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
453 return OC_STACK_DELETE_TRANSACTION;
457 OIC_LOG(INFO, TAG, "ProvisionCredentialDosCB2 received Null clientResponse");
458 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_2_FINISHED);
459 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
463 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
464 return OC_STACK_DELETE_TRANSACTION;
468 * Callback handler for handling callback of provisioning device 1.
470 * @param[in] ctx ctx value passed to callback from calling function.
471 * @param[in] UNUSED handle to an invocation
472 * @param[in] clientResponse Response from queries to remote servers.
473 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
474 * and OC_STACK_KEEP_TRANSACTION to keep it.
476 static OCStackApplicationResult ProvisionCredentialDosCB1(void *ctx, OCDoHandle UNUSED,
477 OCClientResponse *clientResponse)
479 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
480 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
482 CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
483 const OCProvisionResultCB resultCallback = credData->resultCallback;
486 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
488 // send credentials to second device
489 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_1_FINISHED);
490 OCStackResult res = SetDOS((Data_t *) ctx, DOS_RFPRO, ProvisionPskCB);
491 // If deviceInfo is NULL, this device is the second device. Don't delete the cred
492 // because provisionCredentials added it to the local cred store and it now owns
494 if (OC_STACK_OK != res)
496 registerResultForCredProvisioning(credData, res, 2);
497 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
505 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
506 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
514 OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
515 registerResultForCredProvisioning(credData, OC_STACK_ERROR, DEVICE_1_FINISHED);
516 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
521 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
522 return OC_STACK_DELETE_TRANSACTION;
525 * Internal function for handling credential generation and sending credential to resource server.
527 * @param[in] cred Instance of cred resource.
528 * @param[in] deviceInfo information about device to which credential is to be provisioned.
529 * @param[in] responseHandler callbak called by OC stack when request API receives response.
530 * @return OC_STACK_OK in case of success and other value otherwise.
532 static OCStackResult provisionCredentials(OicSecCred_t *cred,
533 const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
534 OCClientResponseHandler responseHandler)
536 OCStackResult res = OC_STACK_OK;
538 if (NULL != deviceInfo)
540 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
543 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
544 return OC_STACK_NO_MEMORY;
546 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
548 res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
549 if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
551 OCPayloadDestroy((OCPayload *)secPayload);
552 OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
553 return OC_STACK_NO_MEMORY;
556 OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
557 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
558 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
559 if (!PMGenerateQuery(true,
560 deviceInfo->endpoint.addr,
561 deviceInfo->securePort,
562 deviceInfo->connType,
563 query, sizeof(query), OIC_RSRC_CRED_URI))
565 OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
566 OCPayloadDestroy((OCPayload *)secPayload);
567 return OC_STACK_ERROR;
569 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
571 OCCallbackData cbData;
572 memset(&cbData, 0, sizeof(cbData));
573 cbData.cb = responseHandler;
574 cbData.context = (void *)credData;
577 OCDoHandle handle = NULL;
578 OCMethod method = OC_REST_POST;
579 res = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
580 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
581 OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
582 if (res != OC_STACK_OK)
584 OIC_LOG(ERROR, TAG, "OCStack resource error");
591 /* Provision this credential to the local cred store. On success, the cred resource takes
592 * ownership of the memory. On failure, provisionCredentialCB1 will delete the cred object.
594 res = AddCredential(cred);
595 /* Call the result callback directly. */
596 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
597 (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
602 * Internal function for handling credential generation and sending credential to resource server.
604 * @param[in] cred Instance of cred resource.
605 * @param[in] deviceInfo information about device to which credential is to be provisioned.
606 * @param[in] responseHandler callbak called by OC stack when request API receives response.
607 * @return OC_STACK_OK in case of success and other value otherwise.
609 static OCStackResult ProvisionCredentialsDos(void *ctx, OicSecCred_t *cred,
610 const OCProvisionDev_t *deviceInfo, OCClientResponseHandler responseHandler)
612 OCStackResult res = OC_STACK_OK;
613 CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
615 if (NULL != deviceInfo)
617 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
620 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
621 return OC_STACK_NO_MEMORY;
623 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
625 res = CredToCBORPayload(cred, &secPayload->securityData, &secPayload->payloadSize, secureFlag);
626 if ((OC_STACK_OK != res) && (NULL == secPayload->securityData))
628 OCPayloadDestroy((OCPayload *)secPayload);
629 OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
630 return OC_STACK_NO_MEMORY;
633 OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
634 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
635 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 };
636 if (!PMGenerateQuery(true,
637 deviceInfo->endpoint.addr,
638 deviceInfo->securePort,
639 deviceInfo->connType,
640 query, sizeof(query), OIC_RSRC_CRED_URI))
642 OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
643 OCPayloadDestroy((OCPayload *)secPayload);
644 return OC_STACK_ERROR;
646 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
648 OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
649 cbData.cb = responseHandler;
650 cbData.context = ctx;
653 OCDoHandle handle = NULL;
654 OCMethod method = OC_REST_POST;
655 res = OCDoResource(&handle, method, query, 0, (OCPayload *)secPayload,
656 deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
657 OIC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d", res);
658 if (res != OC_STACK_OK)
660 OIC_LOG(ERROR, TAG, "OCStack resource error");
667 /* Provision this credential to the local cred store. On success, the cred resource takes
668 * ownership of the memory. On failure, ProvisionCredentialDosCB1 will delete the cred object.
670 res = AddCredential(cred);
671 /* Call the result callback directly. */
672 registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CHANGED, DEVICE_LOCAL_FINISHED);
673 (credData->resultCallback)(credData->ctx, credData->numOfResults, credData->resArr, false);
679 * Updates result in result array of the target device.
681 static void RegisterProvResult(const OCProvisionDev_t *targetDev, OCProvisionResult_t *resArr,
682 int *numOfResults, OCStackResult stackResult);
684 * Callback handler for handling callback of posting DOS_RFNOP.
686 * @param[in] ctx ctx value passed to callback from calling function.
687 * @param[in] UNUSED handle to an invocation
688 * @param[in] clientResponse Response from queries to remote servers.
689 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
690 * and OC_STACK_KEEP_TRANSACTION to keep it.
692 static OCStackApplicationResult SetReadyForNormalOperationCB(void *ctx, OCDoHandle handler,
693 OCClientResponse *clientResponse)
695 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
696 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
697 DataType_t dataType = ((Data_t *) ctx)->type;
699 OCProvisionResultCB resultCallback = NULL;
700 const OCProvisionDev_t *targetDev = NULL;
701 OCProvisionResult_t *resArr = NULL;
702 int *numOfResults = NULL;
704 void *dataCtx = NULL;
705 OIC_LOG_V(DEBUG, TAG, "Data type %d", dataType);
711 TrustChainData_t *chainData = (TrustChainData_t *) ((Data_t *) ctx)->ctx;
712 resultCallback = chainData->resultCallback;
713 targetDev = chainData->targetDev;
714 resArr = chainData->resArr;
715 numOfResults = &(chainData->numOfResults);
716 dataCtx = chainData->ctx;
721 ACLData_t *aclData = (ACLData_t *) ((Data_t *) ctx)->ctx;
722 resultCallback = aclData->resultCallback;
723 targetDev = aclData->deviceInfo;
724 resArr = aclData->resArr;
725 numOfResults = &(aclData->numOfResults);
726 dataCtx = aclData->ctx;
731 CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
732 resArr = pskData->resArr;
733 numOfResults = &(pskData->numOfResults);
734 dataCtx = pskData->ctx;
735 OIC_LOG_V(DEBUG, TAG, "PSK index %d", pskData->currIndex);
740 OIC_LOG_V(ERROR, TAG, "Not implemented type %d", dataType);
741 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
742 return OC_STACK_DELETE_TRANSACTION;
746 OIC_LOG_V(ERROR, TAG, "Unknown type %d", dataType);
747 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
748 return OC_STACK_DELETE_TRANSACTION;
752 if (dataType != PSK_TYPE)
754 RegisterProvResult(targetDev, resArr, numOfResults, clientResponse->result);
755 resultCallback(dataCtx, *numOfResults, resArr, clientResponse->result != OC_STACK_RESOURCE_CHANGED);
760 CredentialData_t *pskData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
761 if (pskData->currIndex == 0)
763 pskData->currIndex = 1;
764 ProvisionCredentialDosCB1(ctx, handler, clientResponse);
768 ProvisionCredentialDosCB2(ctx, handler, clientResponse);
772 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
773 return OC_STACK_DELETE_TRANSACTION;
777 * Updates pstat resource of server.
779 static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t dos,
780 OCClientResponseHandler resultCallback)
782 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
783 if (NULL == data || NULL == resultCallback)
785 OIC_LOG(ERROR, TAG, "NULL parameters");
786 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
787 return OC_STACK_INVALID_PARAM;
791 const OCProvisionDev_t *pTargetDev = NULL;
797 pTargetDev = ((TrustChainData_t *)data->ctx)->targetDev;
802 pTargetDev = ((ACLData_t *)data->ctx)->deviceInfo;
807 CredentialData_t *credData = ((CredentialData_t *)data)->ctx;
808 pTargetDev = credData->deviceInfo[credData->currIndex];
813 // TODO check cert provision flow
814 OIC_LOG_V(ERROR, TAG, "Not implemented type: %d", data->type);
815 return OC_STACK_INVALID_PARAM;
819 OIC_LOG_V(ERROR, TAG, "Unknown type: %d", data->type);
820 return OC_STACK_INVALID_PARAM;
824 OCStackResult res = OC_STACK_ERROR;
825 OicSecPstat_t *pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
828 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
829 return OC_STACK_NO_MEMORY;
832 pstat->dos.state = dos;
834 OCSecurityPayload *secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
837 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
838 res = OC_STACK_NO_MEMORY;
841 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
843 // Note [IOT-2052] all the POST payloads in the provisioningclient app
844 // should be updated to use the Partial payload APIs for the SVRs, so they
845 // do not include read-only Properties for the Server device current
847 bool propertiesToInclude[PSTAT_PROPERTY_COUNT] = {false};
848 propertiesToInclude[PSTAT_DOS] = true;
850 if (OC_STACK_OK != PstatToCBORPayloadPartial(pstat, &(secPayload->securityData),
851 &(secPayload->payloadSize), propertiesToInclude))
853 OCPayloadDestroy((OCPayload *) secPayload);
854 OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
855 res = OC_STACK_NO_MEMORY;
858 OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
859 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
861 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
862 if (!PMGenerateQuery(true,
863 pTargetDev->endpoint.addr,
864 pTargetDev->securePort,
865 pTargetDev->connType,
866 query, sizeof(query), OIC_RSRC_PSTAT_URI))
868 OIC_LOG(ERROR, TAG, "Failed to generate query");
869 OCPayloadDestroy((OCPayload *) secPayload);
870 res = OC_STACK_ERROR;
873 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
875 OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
876 OCMethod method = OC_REST_POST;
877 OCDoHandle handle = NULL;
878 OCProvisionDev_t *targetDev = NULL;
880 targetDev = PMCloneOCProvisionDev(pTargetDev);
882 if (NULL == targetDev)
884 OIC_LOG(ERROR, TAG, "target dev is null");
885 res = OC_STACK_ERROR;
888 cbData.cb = resultCallback;
889 cbData.context = (void *) data;
891 OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
892 res = OCDoResource(&handle, method, query,
893 &targetDev->endpoint, (OCPayload *)secPayload,
894 targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
895 if (OC_STACK_OK != res)
897 OIC_LOG(ERROR, TAG, "OCStack resource error");
902 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
907 * Restores pstat after provisioning.
909 static OCStackApplicationResult ProvisionCB(void *ctx, OCDoHandle UNUSED,
910 OCClientResponse *clientResponse)
912 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
913 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
915 if (clientResponse && OC_STACK_RESOURCE_CHANGED != clientResponse->result)
917 OIC_LOG_V(ERROR, TAG, "Responce result: %d", clientResponse->result);
919 if (OC_STACK_OK != SetDOS(ctx, DOS_RFNOP, SetReadyForNormalOperationCB))
921 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
922 return OC_STACK_DELETE_TRANSACTION;
925 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
926 return OC_STACK_DELETE_TRANSACTION;
929 * Callback for PSK provisioning.
931 static OCStackApplicationResult ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
932 OCClientResponse *clientResponse)
934 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
936 CredentialData_t *credData = (CredentialData_t *) ((Data_t *) ctx)->ctx;
937 const OCProvisionDev_t *device = credData->deviceInfo[credData->currIndex];
938 OicSecCred_t *cred = credData->credInfo[credData->currIndex];
939 const OCProvisionResultCB resultCallback = credData->resultCallback;
943 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
945 OCStackResult res = ProvisionCredentialsDos(ctx, cred, device, ProvisionCB);
946 if (OC_STACK_OK != res)
948 registerResultForCredProvisioning(credData, res, 2);
949 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
950 credData->resArr, true);
952 return OC_STACK_DELETE_TRANSACTION;
957 registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
958 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
966 OIC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
967 registerResultForCredProvisioning(credData, OC_STACK_ERROR, credData->currIndex);
968 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
974 return OC_STACK_DELETE_TRANSACTION;
978 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
980 * Structure to carry certificate data to callback.
982 typedef struct CertificateData CertData_t;
983 struct CertificateData
985 void *ctx; /**< Pointer to user context.**/
986 const OCProvisionDev_t *deviceInfo; /**< Pointer to OCProvisionDev_t.**/
987 OicSecCred_t *credInfo; /**< Pointer to OicSecCred_t.**/
988 OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
989 OCProvisionResult_t *resArr; /**< Result array.**/
990 int numOfResults; /**< Number of results in result array.**/
993 OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
995 if (g_trustCertChainNotifier.callback)
997 OIC_LOG(ERROR, TAG, "Can't register Notifier, Unregister previous one");
998 return OC_STACK_ERROR;
1001 g_trustCertChainNotifier.callback = callback;
1002 g_trustCertChainNotifier.context = ctx;
1006 void SRPRemoveTrustCertChainNotifier()
1008 g_trustCertChainNotifier.callback = NULL;
1009 g_trustCertChainNotifier.context = NULL;
1013 static OCStackApplicationResult provisionCertificateCB(void *ctx, OCDoHandle UNUSED,
1014 OCClientResponse *clientResponse)
1016 // Just call the callback provided to SRProvisionCredentials
1017 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1018 CredentialData_t* credData = (CredentialData_t *)ctx;
1022 // We expect OC_STACK_RESOURCE_CHANGED, anything else is an error
1023 if (clientResponse && (OC_STACK_RESOURCE_CHANGED == clientResponse->result))
1032 OCProvisionResultCB resultCallback = credData->resultCallback;
1033 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_DELETE_TRANSACTION);
1035 ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
1036 credData->resArr, hasError);
1040 return OC_STACK_DELETE_TRANSACTION;
1044 * Callback for Trust Chain provisioning.
1046 static OCStackApplicationResult ProvisionTrustChainCB(void *ctx, OCDoHandle UNUSED,
1047 OCClientResponse *clientResponse)
1049 OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1053 OIC_LOG(ERROR, TAG, "Context is NULL");
1054 return OC_STACK_INVALID_PARAM;
1056 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1058 Data_t *data = (Data_t *) ctx;
1059 if (CHAIN_TYPE != data->type)
1061 OIC_LOG(ERROR, TAG, "Invalid type");
1062 return OC_STACK_INVALID_PARAM;
1064 TrustChainData_t *chainData = (TrustChainData_t *) (data->ctx);
1065 OicSecCred_t *trustCertChainCred = GetCredEntryByCredId(chainData->credId);
1066 if (NULL == trustCertChainCred)
1068 OIC_LOG(ERROR, TAG, "Can not find matched Trust Cert. Chain.");
1069 return OC_STACK_NO_RESOURCE;
1072 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
1075 DeleteCredList(trustCertChainCred);
1076 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1077 return OC_STACK_NO_MEMORY;
1079 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1080 int secureFlag = 1; /* Don't send the private key to the device, if it happens to be present */
1081 if (OC_STACK_OK != CredToCBORPayload(trustCertChainCred, &secPayload->securityData,
1082 &secPayload->payloadSize, secureFlag))
1084 DeleteCredList(trustCertChainCred);
1085 OCPayloadDestroy((OCPayload *)secPayload);
1086 OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
1087 return OC_STACK_NO_MEMORY;
1089 DeleteCredList(trustCertChainCred);
1090 OIC_LOG(DEBUG, TAG, "Created payload for Cred:");
1091 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1093 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1094 if (!PMGenerateQuery(true,
1095 chainData->targetDev->endpoint.addr,
1096 chainData->targetDev->securePort,
1097 chainData->targetDev->connType,
1098 query, sizeof(query), OIC_RSRC_CRED_URI))
1100 OIC_LOG(ERROR, TAG, "Failed to generate query");
1101 OCPayloadDestroy((OCPayload *)secPayload);
1102 return OC_STACK_ERROR;
1104 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1106 OCCallbackData cbData = {.context = NULL, .cb = NULL, .cd = NULL};
1107 cbData.cb = ProvisionCB;
1108 cbData.context = ctx;
1110 OCMethod method = OC_REST_POST;
1111 OCDoHandle handle = NULL;
1112 OIC_LOG(DEBUG, TAG, "Sending Cred info to resource server");
1113 OCStackResult ret = OCDoResource(&handle, method, query,
1114 &chainData->targetDev->endpoint, (OCPayload *)secPayload,
1115 chainData->targetDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1116 if (ret != OC_STACK_OK)
1118 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1124 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1125 return OC_STACK_ERROR;
1128 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1132 OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId,
1133 const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback)
1135 OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1136 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
1137 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
1138 if (SIGNED_ASYMMETRIC_KEY != type)
1140 OIC_LOG(INFO, TAG, "Invalid key type");
1141 return OC_STACK_INVALID_PARAM;
1144 TrustChainData_t *chainData = (TrustChainData_t *) OICCalloc(1, sizeof(TrustChainData_t));
1145 if (NULL == chainData)
1147 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1148 return OC_STACK_NO_MEMORY;
1150 chainData->targetDev = selectedDeviceInfo;
1151 chainData->resultCallback = resultCallback;
1152 chainData->credId = credId;
1153 chainData->ctx = ctx;
1154 chainData->numOfResults = 0;
1156 int noOfRiCalls = 1;
1157 chainData->resArr = (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1158 if (chainData->resArr == NULL)
1161 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1162 return OC_STACK_NO_MEMORY;
1165 Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1166 data->type = CHAIN_TYPE;
1167 data->ctx = chainData;
1169 if (SetDOS(data, DOS_RFPRO, ProvisionTrustChainCB) != OC_STACK_OK)
1172 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1173 return OC_STACK_ERROR;
1176 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1180 OCStackResult SRPSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainSize,
1181 OicEncodingType_t encodingType, uint16_t *credId)
1183 OIC_LOG(DEBUG, TAG, "IN SRPSaveTrustCertChain");
1184 VERIFY_NOT_NULL_RETURN(TAG, trustCertChain, ERROR, OC_STACK_INVALID_PARAM);
1185 VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR, OC_STACK_INVALID_PARAM);
1187 OCStackResult res = OC_STACK_ERROR;
1189 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1190 VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1192 res = GetDoxmDeviceID(&cred->subject);
1193 if (OC_STACK_OK != res)
1195 OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1196 DeleteCredList(cred);
1200 cred->credUsage= (char *)OICCalloc(1, strlen(TRUST_CA) + 1);
1201 VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1202 OICStrcpy(cred->credUsage, strlen(TRUST_CA) + 1, TRUST_CA);
1204 cred->credType = SIGNED_ASYMMETRIC_KEY;
1206 if (encodingType == OIC_ENCODING_PEM)
1208 cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize + 1);
1209 VERIFY_NOT_NULL_RETURN(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
1210 cred->optionalData.len = chainSize + 1;
1212 else if (encodingType == OIC_ENCODING_DER)
1214 cred->optionalData.data = (uint8_t *)OICCalloc(1, chainSize);
1215 VERIFY_NOT_NULL_RETURN(TAG, cred->optionalData.data, ERROR, OC_STACK_NO_MEMORY);
1216 cred->optionalData.len = chainSize;
1220 OIC_LOG_V(ERROR, TAG, "Unknown encoding in %s", __func__);
1221 DeleteCredList(cred);
1222 return OC_STACK_INVALID_PARAM;
1224 memcpy(cred->optionalData.data, trustCertChain, chainSize);
1225 cred->optionalData.encoding = encodingType;
1226 cred->optionalData.revstat = false;
1228 res = AddCredential(cred);
1229 if(res != OC_STACK_OK)
1231 DeleteCredList(cred);
1234 *credId = cred->credId;
1236 if (g_trustCertChainNotifier.callback)
1238 uint8_t *certChain = (uint8_t*)OICCalloc(1, sizeof(uint8_t) * chainSize);
1239 VERIFY_NOT_NULL_RETURN(TAG, certChain, ERROR, OC_STACK_NO_MEMORY);
1240 memcpy(certChain, trustCertChain, chainSize);
1241 g_trustCertChainNotifier.callback(g_trustCertChainNotifier.context, *credId,
1242 certChain, chainSize);
1246 OIC_LOG(DEBUG, TAG, "OUT SRPSaveTrustCertChain");
1251 static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId, const char* usage)
1253 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
1254 VERIFY_NOT_NULL_RETURN(TAG, cert, ERROR, OC_STACK_INVALID_PARAM);
1255 VERIFY_NOT_NULL_RETURN(TAG, cert->data, ERROR, OC_STACK_INVALID_PARAM);
1257 VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR, OC_STACK_INVALID_PARAM);
1258 VERIFY_NOT_NULL_RETURN(TAG, usage, ERROR, OC_STACK_INVALID_PARAM);
1260 if (NULL == key && PRIMARY_CERT == usage)
1262 OIC_LOG_V(ERROR, TAG, "Key is NULL, but it is mandatory if usage is %s", PRIMARY_CERT);
1263 return OC_STACK_INVALID_PARAM;
1268 /* Key is optional. */
1269 VERIFY_NOT_NULL_RETURN(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM);
1272 OCStackResult res = OC_STACK_ERROR;
1274 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1275 VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_NO_MEMORY);
1277 OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
1279 res = GetDoxmDeviceID(&cred->subject);
1280 if (OC_STACK_OK != res)
1282 OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)");
1283 DeleteCredList(cred);
1287 cred->credUsage= (char *)OICCalloc(1, strlen(usage) + 1);
1288 VERIFY_NOT_NULL_RETURN(TAG, cred->credUsage, ERROR, OC_STACK_NO_MEMORY);
1289 OICStrcpy(cred->credUsage, strlen(usage) + 1, usage);
1291 cred->credType = SIGNED_ASYMMETRIC_KEY;
1293 OicSecKey_t *publicData = &cred->publicData;
1294 publicData->data = (uint8_t *)OICCalloc(1, cert->len);
1295 VERIFY_NOT_NULL_RETURN(TAG, publicData->data, ERROR, OC_STACK_NO_MEMORY);
1296 memcpy(publicData->data, cert->data, cert->len);
1297 publicData->len = cert->len;
1298 publicData->encoding = cert->encoding;
1302 OicSecKey_t *privateData = &cred->privateData;
1303 privateData->data = (uint8_t *)OICCalloc(1, key->len);
1304 VERIFY_NOT_NULL_RETURN(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY);
1305 memcpy(privateData->data, key->data, key->len);
1306 privateData->len = key->len;
1307 privateData->encoding = key->encoding;
1310 res = AddCredential(cred);
1311 if(res != OC_STACK_OK)
1313 DeleteCredList(cred);
1316 *credId = cred->credId;
1318 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
1323 OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId)
1325 return saveCertChain(cert, key, credId, PRIMARY_CERT);
1328 OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId)
1330 return saveCertChain(cert, NULL, credId, ROLE_CERT);
1333 #endif // __WITH_DTLS__ || __WITH_TLS__
1335 OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
1336 const OCProvisionDev_t *pDev1,
1337 const OCProvisionDev_t *pDev2,
1338 const char* pemCert,
1339 const OicSecRole_t *role1,
1340 const OicSecRole_t *role2,
1341 OCProvisionResultCB resultCallback)
1343 VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR, OC_STACK_INVALID_PARAM);
1344 if (!resultCallback)
1346 OIC_LOG(INFO, TAG, "SRPProvisionCredentials: NULL Callback");
1347 return OC_STACK_INVALID_CALLBACK;
1349 if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1351 (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1353 OIC_LOG(INFO, TAG, "SRPProvisionCredentials : Same device ID");
1354 return OC_STACK_INVALID_PARAM;
1357 if (SYMMETRIC_PAIR_WISE_KEY == type &&
1358 !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1360 OIC_LOG(INFO, TAG, "Invalid key size");
1361 return OC_STACK_INVALID_PARAM;
1364 OIC_LOG(INFO, TAG, "In SRPProvisionCredentials");
1366 if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1368 bool linkExisits = true;
1369 OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1371 if (res != OC_STACK_OK)
1373 OIC_LOG(ERROR, TAG, "Internal error occured");
1378 OIC_LOG(ERROR, TAG, "Link already exists");
1379 return OC_STACK_INVALID_PARAM;
1383 OicUuid_t provTooldeviceID = {{0,}};
1384 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1386 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1387 return OC_STACK_ERROR;
1389 OIC_LOG(INFO, TAG, "retrieved deviceid");
1392 case SYMMETRIC_PAIR_WISE_KEY:
1394 const OCProvisionDev_t *firstDevice = pDev1;
1395 const OCProvisionDev_t *secondDevice = pDev2;
1397 OicSecCred_t *firstCred = NULL;
1398 OicSecCred_t *secondCred = NULL;
1399 OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
1400 &firstDevice->doxm->deviceID, (NULL != secondDevice) ? &secondDevice->doxm->deviceID : &provTooldeviceID,
1402 &firstCred, &secondCred);
1403 VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1404 OIC_LOG(INFO, TAG, "Credentials generated successfully");
1405 CredentialData_t *credData =
1406 (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1407 if (NULL == credData)
1410 OICFree(secondCred);
1411 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1412 return OC_STACK_NO_MEMORY;
1414 credData->deviceInfo[0] = firstDevice;
1415 credData->deviceInfo[1] = secondDevice;
1416 credData->credInfo[1] = secondCred;
1417 credData->ctx = ctx;
1418 credData->credInfo[0] = firstCred;
1419 credData->numOfResults = 0;
1420 credData->resultCallback = resultCallback;
1421 // first call to provision creds to device1.
1422 // second call to provision creds to device2.
1423 int noOfRiCalls = 2;
1425 (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1426 if (NULL == credData->resArr)
1429 OICFree(secondCred);
1431 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1432 return OC_STACK_NO_MEMORY;
1434 res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
1435 if (OC_STACK_OK != res)
1437 DeleteCredList(firstCred);
1438 DeleteCredList(secondCred);
1439 OICFree(credData->resArr);
1442 OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
1443 VERIFY_SUCCESS_RETURN(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
1446 case SIGNED_ASYMMETRIC_KEY:
1448 /* pDev1 is the device to be provisioned, checked non-null above */
1449 /* pDev2 is not used, should be NULL */
1450 /* size param is not used. */
1451 /* pemCert is the cerficiate to be provisioned */
1452 VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR, OC_STACK_INVALID_PARAM);
1454 OicSecKey_t deviceCert = { 0 };
1455 deviceCert.data = (uint8_t*) pemCert; /* Casting away const is OK here */
1456 deviceCert.len = strlen(pemCert) + 1;
1457 deviceCert.encoding = OIC_ENCODING_PEM;
1459 /* Create a credential object */
1460 OicSecCred_t* cred = GenerateCredential(&pDev1->doxm->deviceID, SIGNED_ASYMMETRIC_KEY,
1461 &deviceCert, NULL, // oic.sec.cred.publicdata = deviceCert, .privatedata = NULL
1462 &provTooldeviceID, NULL); // rowner is the provisioning tool and no eowner
1463 VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_ERROR);
1465 cred->publicData.encoding = OIC_ENCODING_PEM;
1467 if (OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL) == OC_STACK_OK)
1469 cred->credUsage = OICStrdup(ROLE_CERT);
1473 cred->credUsage = OICStrdup(PRIMARY_CERT);
1476 /* Create credential data (used by the response handler provisionCertificateCB and freed there) */
1477 CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t));
1478 if ((NULL == credData) || (NULL == cred->credUsage))
1480 DeleteCredList(cred);
1481 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1482 return OC_STACK_NO_MEMORY;
1484 credData->deviceInfo[0] = pDev1;
1485 credData->deviceInfo[1] = NULL;
1486 credData->credInfo[1] = cred;
1487 credData->ctx = ctx;
1488 credData->credInfo[0] = cred;
1489 credData->numOfResults = 0;
1490 credData->resultCallback = resultCallback;
1491 credData->resArr = NULL;
1493 /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls resultCallback */
1494 OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionCertificateCB);
1495 if (res != OC_STACK_OK)
1500 DeleteCredList(cred);
1505 OIC_LOG(ERROR, TAG, "Invalid option.");
1506 return OC_STACK_INVALID_PARAM;
1511 OCStackResult SRPProvisionCredentialsDos(void *ctx, OicSecCredType_t type, size_t keySize,
1512 const OCProvisionDev_t *pDev1,
1513 const OCProvisionDev_t *pDev2,
1514 OCProvisionResultCB resultCallback)
1516 VERIFY_NOT_NULL_RETURN(TAG, pDev1, ERROR, OC_STACK_INVALID_PARAM);
1517 if (!resultCallback)
1519 OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos: NULL Callback");
1520 return OC_STACK_INVALID_CALLBACK;
1522 if ((SYMMETRIC_PAIR_WISE_KEY == type) &&
1524 (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t))))
1526 OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : Same device ID");
1527 return OC_STACK_INVALID_PARAM;
1529 if (SYMMETRIC_PAIR_WISE_KEY == type && NULL == pDev2)
1531 OIC_LOG(INFO, TAG, "SRPProvisionCredentialsDos : NULL device");
1532 return OC_STACK_INVALID_PARAM;
1535 if (SYMMETRIC_PAIR_WISE_KEY == type &&
1536 !(OWNER_PSK_LENGTH_128 == keySize || OWNER_PSK_LENGTH_256 == keySize))
1538 OIC_LOG(INFO, TAG, "Invalid key size");
1539 return OC_STACK_INVALID_PARAM;
1542 OIC_LOG(INFO, TAG, "In SRPProvisionCredentialsDos");
1544 if ((SYMMETRIC_PAIR_WISE_KEY == type) && (NULL != pDev2))
1546 bool linkExisits = true;
1547 OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExisits);
1549 if (res != OC_STACK_OK)
1551 OIC_LOG(ERROR, TAG, "Internal error occured");
1556 OIC_LOG(ERROR, TAG, "Link already exists");
1557 return OC_STACK_INVALID_PARAM;
1561 OicUuid_t provTooldeviceID = {{0,}};
1562 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1564 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1565 return OC_STACK_ERROR;
1567 OIC_LOG(INFO, TAG, "retrieved deviceid");
1569 CredentialData_t *credData = (CredentialData_t *) OICCalloc(1, sizeof(CredentialData_t));
1570 Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1571 if (NULL == credData || NULL == data)
1576 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1577 return OC_STACK_NO_MEMORY;
1580 data->ctx = credData;
1584 case SYMMETRIC_PAIR_WISE_KEY:
1586 data->type = PSK_TYPE;
1587 OicSecCred_t *firstCred = NULL;
1588 OicSecCred_t *secondCred = NULL;
1589 OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
1590 &pDev1->doxm->deviceID, (NULL != pDev2) ? &pDev2->doxm->deviceID :
1593 &firstCred, &secondCred);
1594 VERIFY_SUCCESS_RETURN(TAG, (res == OC_STACK_OK), ERROR, OC_STACK_ERROR);
1595 OIC_LOG(INFO, TAG, "Credentials generated successfully");
1597 credData->deviceInfo[0] = pDev1;
1598 credData->deviceInfo[1] = pDev2;
1599 credData->credInfo[0] = firstCred;
1600 credData->credInfo[1] = secondCred;
1601 credData->ctx = ctx;
1602 credData->currIndex = 0;
1603 credData->numOfResults = 0;
1604 credData->resultCallback = resultCallback;
1605 // first call to provision creds to device1.
1606 // second call to provision creds to device2.
1607 int noOfRiCalls = 2;
1609 (OCProvisionResult_t *)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1610 if (NULL == credData->resArr)
1613 OICFree(secondCred);
1615 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1616 return OC_STACK_NO_MEMORY;
1619 res = SetDOS(data, DOS_RFPRO, ProvisionPskCB);
1621 if (OC_STACK_OK != res)
1623 DeleteCredList(firstCred);
1624 DeleteCredList(secondCred);
1626 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1629 OIC_LOG_V(INFO, TAG, "provisionCredentials returned: %d", res);
1634 OIC_LOG(ERROR, TAG, "Invalid option.");
1635 return OC_STACK_INVALID_PARAM;
1640 * Callback for ACL provisioning.
1642 static OCStackApplicationResult ProvisionAclCB(void *ctx, OCDoHandle UNUSED,
1643 OCClientResponse *clientResponse);
1645 OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
1646 OicSecAcl_t *acl, OicSecAclVersion_t aclVersion, OCProvisionResultCB resultCallback)
1648 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
1649 VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR, OC_STACK_INVALID_PARAM);
1650 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
1651 OIC_LOG_V(INFO, TAG, "IN %s", __func__);
1654 ACLData_t *aclData = (ACLData_t *) OICCalloc(1, sizeof(ACLData_t));
1655 if (NULL == aclData)
1657 OIC_LOG(ERROR, TAG, "Memory allocation problem");
1658 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1659 return OC_STACK_NO_MEMORY;
1661 aclData->deviceInfo = selectedDeviceInfo;
1662 aclData->resultCallback = resultCallback;
1663 aclData->aclVersion = aclVersion;
1666 aclData->numOfResults = 0;
1668 aclData->resArr = (OCProvisionResult_t *) OICCalloc(1, sizeof(OCProvisionResult_t));
1669 if (aclData->resArr == NULL)
1672 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1673 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1674 return OC_STACK_NO_MEMORY;
1677 Data_t *data = (Data_t *) OICCalloc(1, sizeof(Data_t));
1680 OICFree(aclData->resArr);
1682 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1683 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1684 return OC_STACK_NO_MEMORY;
1686 data->type = ACL_TYPE;
1687 data->ctx = aclData;
1689 if (SetDOS(data, DOS_RFPRO, ProvisionAclCB) != OC_STACK_OK)
1692 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
1693 return OC_STACK_ERROR;
1696 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
1700 OCStackResult SRPSaveACL(const OicSecAcl_t *acl)
1702 OIC_LOG(DEBUG, TAG, "IN SRPSaveACL");
1703 VERIFY_NOT_NULL_RETURN(TAG, acl, ERROR, OC_STACK_INVALID_PARAM);
1705 OCStackResult res = InstallACL(acl);
1707 OIC_LOG(DEBUG, TAG, "OUT SRPSaveACL");
1712 * Internal Function to store results in result array during Direct-Pairing provisioning.
1714 static void registerResultForDirectPairingProvisioning(PconfData_t *pconfData,
1715 OCStackResult stackresult)
1717 OIC_LOG_V(INFO, TAG, "Inside registerResultForDirectPairingProvisioning "
1718 "pconfData->numOfResults is %d", pconfData->numOfResults);
1719 memcpy(pconfData->resArr[(pconfData->numOfResults)].deviceId.id,
1720 pconfData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
1721 pconfData->resArr[(pconfData->numOfResults)].res = stackresult;
1722 ++(pconfData->numOfResults);
1726 * Callback handler of SRPProvisionDirectPairing.
1728 * @param[in] ctx ctx value passed to callback from calling function.
1729 * @param[in] UNUSED handle to an invocation
1730 * @param[in] clientResponse Response from queries to remote servers.
1731 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
1732 * and OC_STACK_KEEP_TRANSACTION to keep it.
1734 static OCStackApplicationResult SRPProvisionDirectPairingCB(void *ctx, OCDoHandle UNUSED,
1735 OCClientResponse *clientResponse)
1737 OIC_LOG_V(INFO, TAG, "Inside SRPProvisionDirectPairingCB.");
1739 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
1740 PconfData_t *pconfData = (PconfData_t*)ctx;
1741 OCProvisionResultCB resultCallback = pconfData->resultCallback;
1745 if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
1747 registerResultForDirectPairingProvisioning(pconfData, OC_STACK_OK);
1748 ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1751 OICFree(pconfData->resArr);
1753 return OC_STACK_DELETE_TRANSACTION;
1756 registerResultForDirectPairingProvisioning(pconfData, OC_STACK_ERROR);
1757 ((OCProvisionResultCB)(resultCallback))(pconfData->ctx, pconfData->numOfResults,
1760 OIC_LOG_V(ERROR, TAG, "SRPProvisionDirectPairingCB received Null clientResponse");
1761 OICFree(pconfData->resArr);
1763 return OC_STACK_DELETE_TRANSACTION;
1766 OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
1767 OicSecPconf_t *pconf, OCProvisionResultCB resultCallback)
1769 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
1770 VERIFY_NOT_NULL_RETURN(TAG, pconf, ERROR, OC_STACK_INVALID_PARAM);
1771 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
1773 // check direct-pairing capability
1774 if (true != selectedDeviceInfo->doxm->dpc)
1776 OIC_LOG(ERROR, TAG, "Resouce server does not have Direct-Pairing Capability ");
1777 return OC_STACK_UNAUTHORIZED_REQ;
1780 OicUuid_t provTooldeviceID = {.id={0}};
1781 if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
1783 OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
1784 return OC_STACK_ERROR;
1786 memcpy(&pconf->rownerID, &provTooldeviceID, sizeof(OicUuid_t));
1788 OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
1791 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
1792 return OC_STACK_NO_MEMORY;
1794 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
1796 if (OC_STACK_OK != PconfToCBORPayload(pconf, &(secPayload->securityData),
1797 &(secPayload->payloadSize)))
1799 OCPayloadDestroy((OCPayload*)secPayload);
1800 OIC_LOG(ERROR, TAG, "Failed to PconfToCborPayload");
1801 return OC_STACK_NO_MEMORY;
1803 OIC_LOG(DEBUG, TAG, "Created payload for pconf set");
1804 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
1806 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1807 if(!PMGenerateQuery(true,
1808 selectedDeviceInfo->endpoint.addr,
1809 selectedDeviceInfo->securePort,
1810 selectedDeviceInfo->connType,
1811 query, sizeof(query), OIC_RSRC_PCONF_URI))
1813 OIC_LOG(ERROR, TAG, "SRPProvisionDirectPairing : Failed to generate query");
1814 return OC_STACK_ERROR;
1816 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
1818 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
1819 cbData.cb = &SRPProvisionDirectPairingCB;
1820 PconfData_t *pconfData = (PconfData_t *) OICCalloc(1, sizeof(PconfData_t));
1821 if (NULL == pconfData)
1823 OCPayloadDestroy((OCPayload*)secPayload);
1824 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1825 return OC_STACK_NO_MEMORY;
1827 pconfData->deviceInfo = selectedDeviceInfo;
1828 pconfData->resultCallback = resultCallback;
1829 pconfData->numOfResults=0;
1830 pconfData->ctx = ctx;
1831 // call to provision PCONF to device1.
1832 int noOfRiCalls = 1;
1833 pconfData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
1834 if (NULL == pconfData->resArr)
1837 OCPayloadDestroy((OCPayload*)secPayload);
1838 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
1839 return OC_STACK_NO_MEMORY;
1841 cbData.context = (void *)pconfData;
1843 OCMethod method = OC_REST_POST;
1844 OCDoHandle handle = NULL;
1845 OIC_LOG(DEBUG, TAG, "Sending PCONF info to resource server");
1846 OCStackResult ret = OCDoResource(&handle, method, query,
1847 &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
1848 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
1849 if (OC_STACK_OK != ret)
1851 OICFree(pconfData->resArr);
1854 VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
1858 static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
1862 OICFree(unlinkData->unlinkDev);
1863 OICFree(unlinkData->unlinkRes);
1864 OICFree(unlinkData);
1868 static void registerResultForUnlinkDevices(UnlinkData_t *unlinkData, OCStackResult stackresult,
1871 if (NULL != unlinkData)
1873 OIC_LOG_V(INFO, TAG, "Inside registerResultForUnlinkDevices unlinkData->numOfResults is %d",
1874 unlinkData->numOfResults);
1875 OIC_LOG_V(INFO, TAG, "Stack result :: %d", stackresult);
1877 OicUuid_t *pUuid = &unlinkData->unlinkRes[(unlinkData->numOfResults)].deviceId;
1879 // Set result in the result array according to the position (devNum).
1880 if (idx != IDX_DB_UPDATE_RES)
1882 memcpy(pUuid->id, unlinkData->unlinkDev[idx].doxm->deviceID.id, sizeof(pUuid->id));
1885 { // When deivce ID is 000... this means it's the result of database update.
1886 memset(pUuid->id, 0, sizeof(pUuid->id));
1888 unlinkData->unlinkRes[(unlinkData->numOfResults)].res = stackresult;
1889 ++(unlinkData->numOfResults);
1890 OIC_LOG (INFO, TAG, "Out registerResultForUnlinkDevices");
1894 static OCStackResult SendDeleteCredentialRequest(void* ctx,
1895 OCClientResponseHandler respHandler,
1896 const OCProvisionDev_t* revokedDev,
1897 const OCProvisionDev_t* destDev)
1899 OIC_LOG(DEBUG, TAG, "IN SendDeleteCredentialRequest");
1901 if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1903 return OC_STACK_INVALID_PARAM;
1907 OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1908 if(OC_STACK_OK != ret)
1910 OIC_LOG(ERROR, TAG, "SendDeleteCredentialRequest : Failed to canonical UUID encoding");
1911 return OC_STACK_ERROR;
1914 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1915 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1916 sizeof(addressEncoded),
1917 destDev->endpoint.addr);
1918 if (OC_STACK_OK != result)
1920 OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
1921 return OC_STACK_ERROR;
1924 char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
1926 //coaps://0.0.0.0:5684/oic/sec/cred?subjectid=(Canonical ENCODED UUID)
1927 const char *srpUri = SRP_FORM_DELETE_CREDENTIAL;
1929 if((int)CA_ADAPTER_TCP == (int)destDev->endpoint.adapter)
1931 srpUri = SRP_FORM_DELETE_CREDENTIAL_TCP;
1935 snRet = snprintf(reqBuf, sizeof(reqBuf), srpUri, addressEncoded,
1936 destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECTID_NAME, subID);
1940 OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error (snprintf) %d", snRet);
1941 return OC_STACK_ERROR;
1943 else if ((size_t)snRet >= sizeof(reqBuf))
1945 OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Truncated (snprintf) %d", snRet);
1946 return OC_STACK_ERROR;
1949 OCCallbackData cbData;
1950 memset(&cbData, 0, sizeof(cbData));
1951 cbData.context = ctx;
1952 cbData.cb = respHandler;
1954 OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
1956 OIC_LOG(DEBUG, TAG, "Sending remove credential request to resource server");
1958 ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
1959 &destDev->endpoint, NULL,
1960 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
1961 if (OC_STACK_OK != ret)
1963 OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error in OCDoResource %d", ret);
1965 OIC_LOG(DEBUG, TAG, "OUT SendDeleteCredentialRequest");
1970 static OCStackResult SendDeleteACLRequest(void* ctx,
1971 OCClientResponseHandler respHandler,
1972 const OCProvisionDev_t* revokedDev,
1973 const OCProvisionDev_t* destDev)
1975 OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
1977 if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
1979 return OC_STACK_INVALID_PARAM;
1983 OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
1984 if(OC_STACK_OK != ret)
1986 OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
1987 return OC_STACK_ERROR;
1990 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1991 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1992 sizeof(addressEncoded),
1993 destDev->endpoint.addr);
1994 if (OC_STACK_OK != result)
1996 OIC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : encoding error %d", result);
1997 return OC_STACK_ERROR;
2000 char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
2002 //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
2003 snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, addressEncoded,
2004 destDev->securePort, OIC_RSRC_ACL2_URI, OIC_JSON_SUBJECTID_NAME, subID);
2008 OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d", snRet);
2009 return OC_STACK_ERROR;
2011 else if ((size_t)snRet >= sizeof(reqBuf))
2013 OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d", snRet);
2014 return OC_STACK_ERROR;
2017 OCCallbackData cbData;
2018 memset(&cbData, 0, sizeof(cbData));
2019 cbData.context = ctx;
2020 cbData.cb = respHandler;
2022 OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
2024 OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
2026 ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
2027 &destDev->endpoint, NULL,
2028 CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
2029 if (OC_STACK_OK != ret)
2031 OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
2033 OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
2039 * Callback handler of unlink second device.
2041 * @param[in] ctx ctx value passed to callback from calling function.
2042 * @param[in] handle handle to an invocation
2043 * @param[in] clientResponse Response from queries to remote servers.
2044 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and
2045 * OC_STACK_KEEP_TRANSACTION to keep it.
2047 static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
2048 OCClientResponse *clientResponse)
2051 OIC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
2052 VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2053 UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2057 OIC_LOG(DEBUG, TAG, "Valid client response for device 2");
2058 registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
2060 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2062 OIC_LOG(DEBUG, TAG, "Credential of device2 revoked");
2066 OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
2067 unlinkData->resultCallback(unlinkData->ctx,
2068 unlinkData->numOfResults, unlinkData->unlinkRes, true);
2074 registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2075 IDX_SECOND_DEVICE_RES);
2076 unlinkData->resultCallback(unlinkData->ctx,
2077 unlinkData->numOfResults, unlinkData->unlinkRes, true);
2078 OIC_LOG(ERROR, TAG, "SRPUnlinkDevice2CB received Null clientResponse");
2082 //Update provisioning DB when succes case.
2083 if (OC_STACK_OK != PDMUnlinkDevices(&unlinkData->unlinkDev[0].doxm->deviceID,
2084 &unlinkData->unlinkDev[1].doxm->deviceID))
2086 OIC_LOG(FATAL, TAG, "All requests are successfully done but update provisioning DB FAILED.");
2087 registerResultForUnlinkDevices(unlinkData, OC_STACK_INCONSISTENT_DB, IDX_DB_UPDATE_RES);
2088 unlinkData->resultCallback(unlinkData->ctx,
2089 unlinkData->numOfResults, unlinkData->unlinkRes, true);
2092 unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults, unlinkData->unlinkRes,
2096 DeleteUnlinkData_t(unlinkData);
2097 OIC_LOG(DEBUG, TAG, "OUT SRPUnlinkDevice2CB");
2098 return OC_STACK_DELETE_TRANSACTION;
2103 * Callback handler of unlink first device.
2105 * @param[in] ctx ctx value passed to callback from calling function.
2106 * @param[in] handle handle to an invocation
2107 * @param[in] clientResponse Response from queries to remote servers.
2108 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and
2109 * OC_STACK_KEEP_TRANSACTION to keep it.
2111 static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle handle,
2112 OCClientResponse *clientResponse)
2114 OIC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
2115 VERIFY_NOT_NULL_RETURN(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2116 UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
2121 OIC_LOG(DEBUG, TAG, "Valid client response for device 1");
2122 registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_FIRST_DEVICE_RES);
2124 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2126 OIC_LOG(DEBUG, TAG, "Credential of device 1 is revoked");
2128 // Second revocation request to second device.
2129 OCStackResult res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice2CB,
2130 &unlinkData->unlinkDev[0],
2131 &unlinkData->unlinkDev[1] /*Dest*/);
2132 OIC_LOG_V(DEBUG, TAG, "Credential revocation request device 2, result :: %d",res);
2133 if (OC_STACK_OK != res)
2135 OIC_LOG(ERROR, TAG, "Error while sending revocation request for device 2");
2136 registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2137 IDX_SECOND_DEVICE_RES);
2138 unlinkData->resultCallback(unlinkData->ctx,
2139 unlinkData->numOfResults, unlinkData->unlinkRes, true);
2144 OIC_LOG(DEBUG, TAG, "Request for credential revocation successfully sent");
2145 return OC_STACK_DELETE_TRANSACTION;
2150 OIC_LOG(ERROR, TAG, "Unable to delete credential information from device 1");
2152 unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults,
2153 unlinkData->unlinkRes, true);
2159 OIC_LOG(DEBUG, TAG, "Invalid response from server");
2160 registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
2161 IDX_FIRST_DEVICE_RES );
2162 unlinkData->resultCallback(unlinkData->ctx,
2163 unlinkData->numOfResults, unlinkData->unlinkRes,
2165 OIC_LOG(ERROR, TAG, "SRPUnlinkDevice1CB received Null clientResponse");
2169 OIC_LOG_V(INFO, TAG, "Out SRPUnlinkDevice1CB");
2170 DeleteUnlinkData_t(unlinkData);
2171 return OC_STACK_DELETE_TRANSACTION;
2175 * Function to unlink devices.
2176 * This function will remove the credential & relationship between the two devices.
2178 * @param[in] ctx Application context would be returned in result callback
2179 * @param[in] pTargetDev1 first device information to be unlinked.
2180 * @param[in] pTargetDev2 second device information to be unlinked.
2181 * @param[in] resultCallback callback provided by API user, callback will be called when
2182 * device unlink is finished.
2183 * @return OC_STACK_OK in case of success and other value otherwise.
2185 OCStackResult SRPUnlinkDevices(void* ctx,
2186 const OCProvisionDev_t* pTargetDev1,
2187 const OCProvisionDev_t* pTargetDev2,
2188 OCProvisionResultCB resultCallback)
2190 OIC_LOG(INFO, TAG, "IN SRPUnlinkDevices");
2192 if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
2194 OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL parameters");
2195 return OC_STACK_INVALID_PARAM;
2197 if (!resultCallback)
2199 OIC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL Callback");
2200 return OC_STACK_INVALID_CALLBACK;
2202 if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
2204 OIC_LOG(INFO, TAG, "SRPUnlinkDevices : Same device ID");
2205 return OC_STACK_INVALID_PARAM;
2208 OIC_LOG(INFO, TAG, "Unlinking following devices: ");
2209 PMPrintOCProvisionDev(pTargetDev1);
2210 PMPrintOCProvisionDev(pTargetDev2);
2212 // Mark the link status stale
2213 OCStackResult res = PDMSetLinkStale(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID);
2214 if (OC_STACK_OK != res)
2216 OIC_LOG(FATAL, TAG, "unable to update DB. Try again.");
2220 UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
2221 VERIFY_NOT_NULL_RETURN(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
2223 //Initialize unlink data
2224 unlinkData->ctx = ctx;
2225 unlinkData->unlinkDev = (OCProvisionDev_t*)OICCalloc(2, sizeof(OCProvisionDev_t));
2226 if (NULL == unlinkData->unlinkDev)
2228 OIC_LOG(ERROR, TAG, "Memory allocation failed");
2229 res = OC_STACK_NO_MEMORY;
2233 unlinkData->unlinkRes = (OCProvisionResult_t*)OICCalloc(3, sizeof(OCProvisionResult_t));
2234 if (NULL == unlinkData->unlinkRes)
2236 OIC_LOG(ERROR, TAG, "Memory allocation failed");
2237 res = OC_STACK_NO_MEMORY;
2241 memcpy(&unlinkData->unlinkDev[0], pTargetDev1, sizeof(OCProvisionDev_t));
2242 memcpy(&unlinkData->unlinkDev[1], pTargetDev2, sizeof(OCProvisionDev_t));
2244 unlinkData->numOfResults = 0;
2245 unlinkData->resultCallback = resultCallback;
2247 res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice1CB,
2248 &unlinkData->unlinkDev[1], &unlinkData->unlinkDev[0]);
2249 if (OC_STACK_OK != res)
2251 OIC_LOG(ERROR, TAG, "SRPUnlinkDevices : SendDeleteCredentialRequest failed");
2258 OIC_LOG(INFO, TAG, "OUT SRPUnlinkDevices");
2259 DeleteUnlinkData_t(unlinkData);
2263 static void DeleteRemoveData_t(RemoveData_t* pRemoveData)
2267 OICFree(pRemoveData->revokeTargetDev);
2268 OCDeleteDiscoveredDevices(pRemoveData->linkedDevList);
2269 OICFree(pRemoveData->removeRes);
2270 OICFree(pRemoveData);
2274 static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2275 OCStackResult stackresult, bool hasError)
2277 OIC_LOG_V(INFO, TAG, "Inside registerResultForRemoveDevice removeData->numOfResults is %" PRIuPTR,
2278 removeData->numOfResults + 1);
2281 memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2282 &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2286 memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2287 0, sizeof(pLinkedDevId->id) );
2289 removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2290 removeData->hasError = hasError;
2291 ++(removeData->numOfResults);
2293 // If we get suffcient result from linked devices, we have to call user callback and do free
2294 if (removeData->sizeOfResArray == removeData->numOfResults)
2296 if(!removeData->hasError)
2298 // Remove device info from prvisioning database
2299 if (OC_STACK_OK != PDMDeleteDevice(&removeData->revokeTargetDev->doxm->deviceID))
2301 OIC_LOG(ERROR, TAG, "ResultForRemoveDevice : Failed to remove device in PDM.");
2302 removeData->hasError = true;
2305 removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2306 removeData->hasError);
2307 DeleteRemoveData_t(removeData);
2311 static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
2312 OCStackResult stackresult, bool hasError)
2314 OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %" PRIuPTR,
2315 removeData->numOfResults + 1);
2318 memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2319 &pLinkedDevId->id, sizeof(pLinkedDevId->id));
2323 memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
2324 0, sizeof(pLinkedDevId->id) );
2326 removeData->removeRes[(removeData->numOfResults)].res = stackresult;
2327 removeData->hasError = hasError;
2328 ++(removeData->numOfResults);
2330 // If we get suffcient result from linked devices, we have to call user callback and do free
2331 if (removeData->sizeOfResArray == removeData->numOfResults)
2333 removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
2334 removeData->hasError);
2335 DeleteRemoveData_t(removeData);
2340 * Callback handler of unlink first device.
2342 * @param[in] ctx ctx value passed to callback from calling function.
2343 * @param[in] handle handle to an invocation
2344 * @param[in] clientResponse Response from queries to remote servers.
2345 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
2346 * and OC_STACK_KEEP_TRANSACTION to keep it.
2348 static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle handle,
2349 OCClientResponse *clientResponse)
2351 //Update the delete credential into delete device context
2352 //Save the deleted status in delDevCtx
2354 OIC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
2355 VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2356 OCStackResult res = OC_STACK_ERROR;
2358 RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2362 OicUuid_t revDevUuid = {.id={0}};
2363 if(UUID_LENGTH == clientResponse->identity.id_length)
2365 memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2366 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2368 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2369 if (OC_STACK_OK != res)
2371 OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2372 registerResultForRemoveDevice(removeData, &revDevUuid,
2373 OC_STACK_INCONSISTENT_DB, true);
2375 return OC_STACK_DELETE_TRANSACTION;
2378 registerResultForRemoveDevice(removeData, &revDevUuid,
2379 OC_STACK_RESOURCE_DELETED, false);
2383 registerResultForRemoveDevice(removeData, &revDevUuid,
2384 clientResponse->result, true);
2385 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2390 OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2391 clientResponse->devAddr.addr, clientResponse->devAddr.port);
2393 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2396 * Since server's credential was deleted,
2397 * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2399 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2400 registerResultForRemoveDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2404 registerResultForRemoveDevice(removeData, NULL, clientResponse->result, true);
2410 registerResultForRemoveDevice(removeData, NULL, OC_STACK_ERROR, true);
2411 OIC_LOG(ERROR, TAG, "SRPRemoveDevices received Null clientResponse");
2414 return OC_STACK_DELETE_TRANSACTION;
2418 * Callback handler of reset device.
2420 * @param[in] ctx ctx value passed to callback from calling function.
2421 * @param[in] handle handle to an invocation
2422 * @param[in] clientResponse Response from queries to remote servers.
2423 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
2424 * and OC_STACK_KEEP_TRANSACTION to keep it.
2426 static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
2427 OCClientResponse *clientResponse)
2429 //Update the delete credential into delete device context
2430 //Save the deleted status in delDevCtx
2432 OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
2433 VERIFY_NOT_NULL_RETURN(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
2434 OCStackResult res = OC_STACK_ERROR;
2436 RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
2437 OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
2438 OCProvisionResultCB resultCallback = removeData->resultCallback;
2441 OicUuid_t revDevUuid = {.id={0}};
2442 if(UUID_LENGTH == clientResponse->identity.id_length)
2444 memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
2445 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2447 res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
2448 if (OC_STACK_OK != res)
2450 OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2451 registerResultForResetDevice(removeData, &revDevUuid,
2452 OC_STACK_INCONSISTENT_DB, true);
2454 return OC_STACK_DELETE_TRANSACTION;
2457 registerResultForResetDevice(removeData, &revDevUuid,
2458 OC_STACK_RESOURCE_DELETED, false);
2462 registerResultForResetDevice(removeData, &revDevUuid,
2463 clientResponse->result, false);
2464 OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
2469 OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
2470 clientResponse->devAddr.addr, clientResponse->devAddr.port);
2472 if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
2475 * Since server's credential was deleted,
2476 * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
2478 OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
2479 registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
2483 registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
2489 registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
2490 OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
2493 SRPResetDevice(pTargetDev, resultCallback);
2495 return OC_STACK_DELETE_TRANSACTION;
2499 * Callback handler of reset device sync-up
2501 * @param[in] ctx ctx value passed to callback from calling function.
2502 * @param[in] handle handle to an invocation
2503 * @param[in] clientResponse Response from queries to remote servers.
2504 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
2505 * and OC_STACK_KEEP_TRANSACTION to keep it.
2507 static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle UNUSED,
2508 OCClientResponse *clientResponse)
2512 (void)clientResponse;
2513 return OC_STACK_DELETE_TRANSACTION;
2517 * Callback handler of device remote reset.
2519 * @param[in] ctx ctx value passed to callback from calling function.
2520 * @param[in] UNUSED handle to an invocation
2521 * @param[in] clientResponse Response from queries to remote servers.
2522 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
2523 * and OC_STACK_KEEP_TRANSACTION to keep it.
2525 static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle UNUSED,
2526 OCClientResponse *clientResponse)
2528 OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
2530 if(OC_STACK_OK == clientResponse->result)
2532 OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
2535 // Delete Cred and ACL related to the target device.
2536 const OicSecCred_t *cred = NULL;
2537 OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
2538 cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
2541 OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
2545 OCStackResult res = RemoveCredential(&cred->subject);
2546 if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2548 OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
2552 res = RemoveACE(&cred->subject, NULL);
2553 if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
2555 OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
2558 if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
2560 OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
2563 //Close the DTLS session of the reset device.
2564 CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr;
2565 CAResult_t caResult = CAcloseSslSession(endpoint);
2566 if(CA_STATUS_OK != caResult)
2568 OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
2572 * If there is no linked device, PM does not send any request.
2573 * So we should directly invoke the result callback to inform the result of OCResetDevice.
2575 if(OC_STACK_NO_RESOURCE == res)
2581 OICFree(pTargetDev);
2582 return OC_STACK_DELETE_TRANSACTION;
2586 static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
2587 const OCProvisionDev_t* pOwnedDevList,
2588 OCUuidList_t* pLinkedUuidList,
2589 OCProvisionDev_t** ppLinkedDevList,
2590 size_t *numOfLinkedDev)
2592 // pOwnedDevList could be NULL. It means no alived and owned device now.
2593 if (pRevokeTargetDev == NULL || pLinkedUuidList == NULL ||\
2594 ppLinkedDevList == NULL || numOfLinkedDev == NULL)
2596 return OC_STACK_INVALID_PARAM;
2600 OCUuidList_t *curUuid = NULL, *tmpUuid = NULL;
2601 LL_FOREACH_SAFE(pLinkedUuidList, curUuid, tmpUuid)
2603 // Mark the link status stale.
2604 OCStackResult res = PDMSetLinkStale(&curUuid->dev, &pRevokeTargetDev->doxm->deviceID);
2605 if (OC_STACK_OK != res)
2607 OIC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
2608 return OC_STACK_INCONSISTENT_DB;
2613 // If this linked device is alive (power-on), add the deivce to the list.
2614 const OCProvisionDev_t *curDev = NULL;
2615 const OCProvisionDev_t *tmpDev = NULL;
2616 LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
2618 if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
2620 OCProvisionDev_t* targetDev = PMCloneOCProvisionDev(curDev);
2621 if (NULL == targetDev)
2623 OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Cloning OCProvisionDev_t Failed.");
2624 return OC_STACK_NO_MEMORY;
2627 LL_PREPEND(*ppLinkedDevList, targetDev);
2634 *numOfLinkedDev = cnt;
2639 * Function to device revocation
2640 * This function will remove credential of target device from all devices in subnet.
2642 * @param[in] ctx Application context would be returned in result callback
2643 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2644 * @param[in] pTargetDev Device information to be revoked.
2645 * @param[in] resultCallback callback provided by API user, callback will be called when
2646 * credential revocation is finished.
2647 * @return OC_STACK_OK in case of success and other value otherwise.
2648 * If OC_STACK_OK is returned, the caller of this API should wait for callback.
2649 * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2651 OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2652 const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2654 OIC_LOG(INFO, TAG, "IN SRPRemoveDevice");
2656 if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
2658 OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL parameters");
2659 return OC_STACK_INVALID_PARAM;
2661 if (!resultCallback)
2663 OIC_LOG(INFO, TAG, "SRPRemoveDevice : NULL Callback");
2664 return OC_STACK_INVALID_CALLBACK;
2667 // Declare variables in here to handle error cases with goto statement.
2668 OCProvisionDev_t* pOwnedDevList = NULL;
2669 OCProvisionDev_t* pLinkedDevList = NULL;
2670 RemoveData_t* removeData = NULL;
2672 //1. Find all devices that has a credential of the revoked device
2673 OCUuidList_t* pLinkedUuidList = NULL;
2674 size_t numOfDevices = 0;
2675 OCStackResult res = OC_STACK_ERROR;
2676 res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2677 if (OC_STACK_OK != res)
2679 OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to get linked devices information");
2682 // if there is no related device, we can skip further process.
2683 if (0 == numOfDevices)
2685 OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No linked device found.");
2686 res = OC_STACK_CONTINUE;
2690 //2. Find owned device from the network
2691 res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2692 if (OC_STACK_OK != res)
2694 OIC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to PMDeviceDiscovery");
2698 //3. Make a list of devices to send DELETE credential request
2699 // by comparing owned devices from provisioning database with mutlicast discovery result.
2700 size_t numOfLinkedDev = 0;
2701 res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2702 &pLinkedDevList, &numOfLinkedDev);
2703 if (OC_STACK_OK != res)
2705 OIC_LOG(ERROR, TAG, "SRPRemoveDevice : GetListofDevToReqDeleteCred() failed");
2708 if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2709 { // So we don't have to send request message.
2710 OIC_LOG(DEBUG, TAG, "SRPRemoveDevice : No alived & linked device found.");
2711 res = OC_STACK_CONTINUE;
2715 // 4. Prepare RemoveData Context data.
2716 removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2719 OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2720 res = OC_STACK_NO_MEMORY;
2724 removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2725 if (!removeData->revokeTargetDev)
2727 OIC_LOG(ERROR, TAG, "SRPRemoveDevices : PMCloneOCProvisionDev Failed");
2728 res = OC_STACK_NO_MEMORY;
2732 removeData->removeRes =
2733 (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2734 if (!removeData->removeRes)
2736 OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory");
2737 res = OC_STACK_NO_MEMORY;
2741 removeData->ctx = ctx;
2742 removeData->linkedDevList = pLinkedDevList;
2743 removeData->resultCallback = resultCallback;
2744 removeData->numOfResults = 0;
2745 removeData->sizeOfResArray = numOfLinkedDev;
2746 removeData->hasError = false;
2748 // 5. Send DELETE credential request to linked devices.
2749 OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2750 OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */
2751 LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2753 res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2754 removeData->revokeTargetDev, curDev);
2755 if (OC_STACK_OK != res)
2757 OIC_LOG_V(ERROR, TAG, "SRPRemoveDevice : Fail to send the DELETE credential request to\
2758 %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2762 totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2766 PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2767 PMDeleteDeviceList(pOwnedDevList);
2768 OIC_LOG(INFO, TAG, "OUT SRPRemoveDevice");
2770 return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2773 PDMDestoryOicUuidLinkList(pLinkedUuidList);
2774 PMDeleteDeviceList(pOwnedDevList);
2775 PMDeleteDeviceList(pLinkedDevList);
2778 OICFree(removeData->revokeTargetDev);
2779 OICFree(removeData->removeRes);
2780 OICFree(removeData);
2782 OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
2787 * Function to device revocation
2788 * This function will remove credential of target device from all devices in subnet.
2790 * @param[in] ctx Application context would be returned in result callback
2791 * @param[in] pOwnedDevList List of owned devices
2792 * @param[in] pTargetDev Device information to be revoked.
2793 * @param[in] resultCallback callback provided by API user, callback will be called when
2794 * credential revocation is finished.
2795 * @return OC_STACK_OK in case of success and other value otherwise.
2796 * If OC_STACK_OK is returned, the caller of this API should wait for callback.
2797 * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2799 OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* pOwnedDevList,
2800 const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2802 OIC_LOG(INFO, TAG, "IN SRPRemoveDeviceWithoutDiscovery");
2806 OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Owned Device List is empty");
2807 return OC_STACK_CONTINUE;
2811 OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL parameters");
2812 return OC_STACK_INVALID_PARAM;
2814 if (!resultCallback)
2816 OIC_LOG(INFO, TAG, "SRPRemoveDeviceWithoutDiscovery : NULL Callback");
2817 return OC_STACK_INVALID_CALLBACK;
2820 // Declare variables in here to handle error cases with goto statement.
2821 OCProvisionDev_t* pLinkedDevList = NULL;
2822 RemoveData_t* removeData = NULL;
2824 //1. Find all devices that has a credential of the revoked device
2825 OCUuidList_t* pLinkedUuidList = NULL;
2826 size_t numOfDevices = 0;
2827 OCStackResult res = OC_STACK_ERROR;
2828 res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2829 if (OC_STACK_OK != res)
2831 OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to get linked devices information");
2832 return OC_STACK_CONTINUE;
2834 // if there is no related device, we can skip further process.
2835 if (0 == numOfDevices)
2837 OIC_LOG(WARNING, TAG, "SRPRemoveDeviceWithoutDiscovery : No linked device found.");
2838 return OC_STACK_CONTINUE;
2841 //2. Make a list of devices to send DELETE credential request
2842 // by comparing owned devices from provisioning database with mutlicast discovery result.
2843 size_t numOfLinkedDev = 0;
2844 res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2845 &pLinkedDevList, &numOfLinkedDev);
2846 if (OC_STACK_OK != res)
2848 OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : GetListofDevToReqDeleteCred() failed");
2851 if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2852 { // So we don't have to send request message.
2853 OIC_LOG(DEBUG, TAG, "SRPRemoveDeviceWithoutDiscovery : No alived & linked device found.");
2854 return OC_STACK_CONTINUE;
2857 // 3. Prepare RemoveData Context data.
2858 removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
2861 OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
2862 res = OC_STACK_NO_MEMORY;
2866 removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
2867 if (!removeData->revokeTargetDev)
2869 OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : PMCloneOCProvisionDev Failed");
2870 res = OC_STACK_NO_MEMORY;
2874 removeData->removeRes =
2875 (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
2876 if (!removeData->removeRes)
2878 OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory");
2879 res = OC_STACK_NO_MEMORY;
2883 removeData->ctx = ctx;
2884 removeData->linkedDevList = pLinkedDevList;
2885 removeData->resultCallback = resultCallback;
2886 removeData->numOfResults = 0;
2887 removeData->sizeOfResArray = numOfLinkedDev;
2888 removeData->hasError = false;
2890 // 5. Send DELETE credential request to linked devices.
2891 OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
2892 OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */
2893 LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
2895 res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
2896 removeData->revokeTargetDev, curDev);
2897 if (OC_STACK_OK != res)
2899 OIC_LOG_V(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Fail to send the DELETE credential request to\
2900 %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
2904 totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
2908 PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
2909 OIC_LOG(INFO, TAG, "OUT SRPRemoveDeviceWithoutDiscovery");
2911 return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
2914 PDMDestoryOicUuidLinkList(pLinkedUuidList);
2915 PMDeleteDeviceList(pLinkedDevList);
2918 OICFree(removeData->revokeTargetDev);
2919 OICFree(removeData->removeRes);
2920 OICFree(removeData);
2922 OIC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDeviceWithoutDiscovery");
2927 * Function to sync-up credential and ACL of the target device.
2928 * This function will remove credential and ACL of target device from all devices in subnet.
2930 * @param[in] ctx Application context would be returned in result callback
2931 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
2932 * @param[in] pTargetDev Device information to be revoked.
2933 * @param[in] resultCallback callback provided by API user, callback will be called when
2934 * credential revocation is finished.
2935 * when there is an error, this user callback is called immediately.
2936 * @return OC_STACK_OK in case of success and other value otherwise.
2937 * If OC_STACK_OK is returned, the caller of this API should wait for callback.
2938 * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
2940 OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
2941 const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
2943 OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
2944 if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
2946 OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
2947 return OC_STACK_INVALID_PARAM;
2949 if (!resultCallback)
2951 OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
2952 return OC_STACK_INVALID_CALLBACK;
2955 // Declare variables in here to handle error cases with goto statement.
2956 OCProvisionDev_t* pOwnedDevList = NULL;
2957 OCProvisionDev_t* pLinkedDevList = NULL;
2958 RemoveData_t* removeData = NULL;
2960 //1. Find all devices that has a credential of the revoked device
2961 OCUuidList_t* pLinkedUuidList = NULL;
2962 size_t numOfDevices = 0;
2963 OCStackResult res = OC_STACK_ERROR;
2964 res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
2965 if (OC_STACK_OK != res)
2967 OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
2970 // if there is no related device, we can skip further process.
2971 if (0 == numOfDevices)
2973 OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
2974 res = OC_STACK_CONTINUE;
2978 //2. Find owned device from the network
2979 res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
2980 if (OC_STACK_OK != res)
2982 OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
2986 //3. Make a list of devices to send DELETE credential request
2987 // by comparing owned devices from provisioning database with mutlicast discovery result.
2988 size_t numOfLinkedDev = 0;
2989 res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
2990 &pLinkedDevList, &numOfLinkedDev);
2991 if (OC_STACK_OK != res)
2993 OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
2996 if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
2997 { // So we don't have to send request message.
2998 OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
2999 res = OC_STACK_CONTINUE;
3003 // 4. Prepare RemoveData Context data.
3004 removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
3007 OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3008 res = OC_STACK_NO_MEMORY;
3012 removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
3013 if (!removeData->revokeTargetDev)
3015 OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
3016 res = OC_STACK_NO_MEMORY;
3020 removeData->removeRes =
3021 (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
3022 if (!removeData->removeRes)
3024 OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
3025 res = OC_STACK_NO_MEMORY;
3029 removeData->ctx = ctx;
3030 removeData->linkedDevList = pLinkedDevList;
3031 removeData->resultCallback = resultCallback;
3032 removeData->numOfResults = 0;
3033 removeData->sizeOfResArray = numOfLinkedDev;
3034 removeData->hasError = false;
3036 // 5. Send DELETE credential request to linked devices.
3037 OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
3038 OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */
3039 LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
3041 res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
3042 removeData->revokeTargetDev, curDev);
3043 if (OC_STACK_OK != res)
3045 OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
3046 %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3049 res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
3050 removeData->revokeTargetDev, curDev);
3051 if (OC_STACK_OK != res)
3053 OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
3054 %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
3055 totalRes = OC_STACK_ERROR;
3059 totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
3063 PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
3064 PMDeleteDeviceList(pOwnedDevList);
3065 OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
3067 return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
3070 PDMDestoryOicUuidLinkList(pLinkedUuidList);
3071 PMDeleteDeviceList(pOwnedDevList);
3072 PMDeleteDeviceList(pLinkedDevList);
3075 OICFree(removeData->revokeTargetDev);
3076 OICFree(removeData->removeRes);
3077 OICFree(removeData);
3079 OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
3084 * Function for remote reset
3085 * This function will send pstat PUT message to the target device to initiate remote reset.
3087 * @param[in] pTargetDev Device information to be revoked.
3088 * @param[in] resultCallback callback provided by API user, callback will be called when
3089 * credential revocation is finished.
3090 * when there is an error, this user callback is called immediately.
3091 * @return OC_STACK_OK in case of success and other value otherwise.
3092 * If OC_STACK_OK is returned, the caller of this API should wait for callback.
3093 * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
3095 OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
3096 OCProvisionResultCB resultCallback)
3098 OIC_LOG(INFO, TAG, "IN SRPResetDevice");
3101 OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
3102 return OC_STACK_INVALID_PARAM;
3104 if (!resultCallback)
3106 OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
3107 return OC_STACK_INVALID_CALLBACK;
3110 OCStackResult res = OC_STACK_ERROR;
3111 OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
3114 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3115 return OC_STACK_NO_MEMORY;
3118 pstat->dos.state = DOS_RESET; // TODO IOT-2052 in OCF 1.0 this is the only
3119 // value that needs to be set to cause RESET
3121 pstat->isOp = false;
3122 pstat->tm = TAKE_OWNER;
3123 pstat->om = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
3125 pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
3126 if (NULL == pstat->sm)
3128 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3130 return OC_STACK_NO_MEMORY;
3132 pstat->sm[0] = (OicSecDpom_t)(SINGLE_SERVICE_CLIENT_DRIVEN); // the only mode IoTivity supports currently
3134 OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
3137 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3138 res = OC_STACK_NO_MEMORY;
3141 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
3143 // Note [IOT-2052] all the POST payloads in the provisioningclient app
3144 // should be updated to use the Partial payload APIs for the SVRs, so they
3145 // do not include read-only Properties for the Server device current
3147 bool propertiesToInclude[PSTAT_PROPERTY_COUNT];
3148 memset(propertiesToInclude, 0, sizeof(propertiesToInclude));
3149 propertiesToInclude[PSTAT_DOS] = true;
3151 if (OC_STACK_OK != PstatToCBORPayloadPartial(pstat, &(secPayload->securityData),
3152 &(secPayload->payloadSize), propertiesToInclude))
3154 OCPayloadDestroy((OCPayload *) secPayload);
3155 OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
3156 res = OC_STACK_NO_MEMORY;
3159 OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
3160 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
3162 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3163 if (!PMGenerateQuery(true,
3164 pTargetDev->endpoint.addr,
3165 pTargetDev->securePort,
3166 pTargetDev->connType,
3167 query, sizeof(query), OIC_RSRC_PSTAT_URI))
3169 OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query");
3170 OCPayloadDestroy((OCPayload *) secPayload);
3171 res = OC_STACK_ERROR;
3174 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3176 OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
3177 OCMethod method = OC_REST_POST;
3178 OCDoHandle handle = NULL;
3179 OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
3180 if (NULL == targetDev)
3182 OIC_LOG(ERROR, TAG, "target dev is null");
3183 res = OC_STACK_ERROR;
3186 cbData.cb = &SRPResetDeviceCB;
3187 cbData.context = (void *) targetDev;
3189 OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
3190 res = OCDoResource(&handle, method, query,
3191 &targetDev->endpoint, (OCPayload *)secPayload,
3192 targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\
3193 if (OC_STACK_OK != res)
3195 OIC_LOG(ERROR, TAG, "OCStack resource error");
3201 OIC_LOG(INFO, TAG, "OUT SRPResetDevice");
3206 * Internal Function to store results in result array during GetCredResourceCB.
3208 static void registerResultForGetCredResourceCB(GetSecData_t *GetSecData,
3209 OCStackResult stackresult)
3211 OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCredResourceCB "
3212 "GetSecData->numOfResults is %d", GetSecData->numOfResults);
3213 memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
3214 GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3215 GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
3216 ++(GetSecData->numOfResults);
3220 * Callback handler of SRPGetCredResource.
3222 * @param[in] ctx ctx value passed to callback from calling function.
3223 * @param[in] UNUSED handle to an invocation
3224 * @param[in] clientResponse Response from queries to remote servers.
3225 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
3226 * and OC_STACK_KEEP_TRANSACTION to keep it.
3228 static OCStackApplicationResult SRPGetCredResourceCB(void *ctx, OCDoHandle UNUSED,
3229 OCClientResponse *clientResponse)
3231 OIC_LOG_V(INFO, TAG, "Inside SRPGetCredResourceCB.");
3233 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3234 GetSecData_t *GetSecData = (GetSecData_t*)ctx;
3235 OCProvisionResultCB resultCallback = GetSecData->resultCallback;
3239 if(OC_STACK_OK == clientResponse->result)
3241 uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3242 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3244 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3248 registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
3249 ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3252 OICFree(GetSecData->resArr);
3253 OICFree(GetSecData);
3255 return OC_STACK_DELETE_TRANSACTION;
3258 registerResultForGetCredResourceCB(GetSecData, OC_STACK_OK);
3259 ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3262 OIC_LOG_V(ERROR, TAG, "SRPGetCredResourceCB received Null clientResponse");
3263 OICFree(GetSecData->resArr);
3264 OICFree(GetSecData);
3266 return OC_STACK_DELETE_TRANSACTION;
3269 OCStackResult SRPGetCredResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3270 OCProvisionResultCB resultCallback)
3272 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
3273 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
3275 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3276 if(!PMGenerateQuery(true,
3277 selectedDeviceInfo->endpoint.addr,
3278 selectedDeviceInfo->securePort,
3279 selectedDeviceInfo->connType,
3280 query, sizeof(query), OIC_RSRC_CRED_URI))
3282 OIC_LOG(ERROR, TAG, "SRPGetCredResource : Failed to generate query");
3283 return OC_STACK_ERROR;
3285 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3287 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
3288 cbData.cb = &SRPGetCredResourceCB;
3289 GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3290 if (NULL == GetSecData)
3292 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3293 return OC_STACK_NO_MEMORY;
3295 GetSecData->deviceInfo = selectedDeviceInfo;
3296 GetSecData->resultCallback = resultCallback;
3297 GetSecData->numOfResults=0;
3298 GetSecData->ctx = ctx;
3300 int noOfRiCalls = 1;
3301 GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
3302 if (NULL == GetSecData->resArr)
3304 OICFree(GetSecData);
3305 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3306 return OC_STACK_NO_MEMORY;
3308 cbData.context = (void *)GetSecData;
3310 OCMethod method = OC_REST_GET;
3311 OCDoHandle handle = NULL;
3312 OIC_LOG(DEBUG, TAG, "Sending Get Cred to resource server");
3313 OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3314 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3315 if (OC_STACK_OK != ret)
3317 OIC_LOG(ERROR, TAG, "OCStack resource error");
3318 OICFree(GetSecData->resArr);
3319 OICFree(GetSecData);
3321 VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
3322 OIC_LOG(DEBUG, TAG, "OUT SRPGetCredResource");
3328 * Internal Function to store results in result array during GetACLResourceCB.
3330 static void registerResultForGetACLResourceCB(GetSecData_t *GetSecData,
3331 OCStackResult stackresult)
3333 OIC_LOG_V(INFO, TAG, "Inside registerResultForGetACLResourceCB "
3334 "GetSecData->numOfResults is %d", GetSecData->numOfResults);
3335 memcpy(GetSecData->resArr[(GetSecData->numOfResults)].deviceId.id,
3336 GetSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3337 GetSecData->resArr[(GetSecData->numOfResults)].res = stackresult;
3338 ++(GetSecData->numOfResults);
3342 * Callback handler of SRPGetACLResource.
3344 * @param[in] ctx ctx value passed to callback from calling function.
3345 * @param[in] UNUSED handle to an invocation
3346 * @param[in] clientResponse Response from queries to remote servers.
3347 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
3348 * and OC_STACK_KEEP_TRANSACTION to keep it.
3350 static OCStackApplicationResult SRPGetACLResourceCB(void *ctx, OCDoHandle UNUSED,
3351 OCClientResponse *clientResponse)
3353 OIC_LOG_V(INFO, TAG, "Inside SRPGetACLResourceCB.");
3355 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3356 GetSecData_t *GetSecData = (GetSecData_t*)ctx;
3357 OCProvisionResultCB resultCallback = GetSecData->resultCallback;
3361 if(OC_STACK_OK == clientResponse->result)
3363 uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3364 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3366 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3370 registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
3371 ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3374 OICFree(GetSecData->resArr);
3375 OICFree(GetSecData);
3377 return OC_STACK_DELETE_TRANSACTION;
3380 registerResultForGetACLResourceCB(GetSecData, OC_STACK_OK);
3381 ((OCProvisionResultCB)(resultCallback))(GetSecData->ctx, GetSecData->numOfResults,
3384 OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
3385 OICFree(GetSecData->resArr);
3386 OICFree(GetSecData);
3388 return OC_STACK_DELETE_TRANSACTION;
3391 OCStackResult SRPGetACLResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3392 OicSecAclVersion_t aclVersion, OCProvisionResultCB resultCallback)
3394 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
3395 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
3397 const char *uri = NULL;
3401 case OIC_SEC_ACL_V1:
3402 OIC_LOG_V(WARNING, TAG, "%s using ACL v1... this should only be used for provisioning OIC 1.1 and earlier Servers.", __func__);
3403 uri = OIC_RSRC_ACL_URI;
3405 case OIC_SEC_ACL_V2:
3406 uri = OIC_RSRC_ACL2_URI;
3409 return OC_STACK_INVALID_PARAM;
3412 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3413 if(!PMGenerateQuery(true,
3414 selectedDeviceInfo->endpoint.addr,
3415 selectedDeviceInfo->securePort,
3416 selectedDeviceInfo->connType,
3417 query, sizeof(query), uri))
3419 OIC_LOG(ERROR, TAG, "SRPGetACLResource : Failed to generate query");
3420 return OC_STACK_ERROR;
3422 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3424 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
3425 cbData.cb = &SRPGetACLResourceCB;
3426 GetSecData_t* GetSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3427 if (NULL == GetSecData)
3429 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3430 return OC_STACK_NO_MEMORY;
3432 GetSecData->deviceInfo = selectedDeviceInfo;
3433 GetSecData->resultCallback = resultCallback;
3434 GetSecData->numOfResults=0;
3435 GetSecData->ctx = ctx;
3437 int noOfRiCalls = 1;
3438 GetSecData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t));
3439 if (NULL == GetSecData->resArr)
3441 OICFree(GetSecData);
3442 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3443 return OC_STACK_NO_MEMORY;
3445 cbData.context = (void *)GetSecData;
3447 OCMethod method = OC_REST_GET;
3448 OCDoHandle handle = NULL;
3449 OIC_LOG(DEBUG, TAG, "Sending Get ACL to resource server");
3450 OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3451 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3452 if (OC_STACK_OK != ret)
3454 OIC_LOG(ERROR, TAG, "OCStack resource error");
3455 OICFree(GetSecData->resArr);
3456 OICFree(GetSecData);
3458 VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
3459 OIC_LOG(DEBUG, TAG, "OUT SRPGetACLResource");
3465 * Internal Function to store results in result array during GetCSRResourceCB.
3467 static void registerResultForGetCSRResourceCB(GetCsrData_t *getCsrData,
3468 OCStackResult stackresult,
3469 const uint8_t *payload,
3472 /* SRPGetCSRResource allocates the memory for getCsrData. When it calls this callback,
3473 * numOfResults points to the current entry we're filling out. Later when this structure
3474 * gets returned to the caller, that's when it actually reflects the number of
3477 OCPMGetCsrResult_t* currentEntry = &getCsrData->resArr[getCsrData->numOfResults];
3478 OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCSRResourceCB "
3479 "getCsrData->numOfResults is %zu\n", getCsrData->numOfResults);
3480 memcpy(currentEntry->deviceId.id,
3481 getCsrData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3482 currentEntry->res = stackresult;
3484 if (OC_STACK_OK == stackresult)
3486 OCStackResult res = CBORPayloadToCSR(payload, payloadSize,
3488 ¤tEntry->csrLen,
3489 ¤tEntry->encoding);
3490 if (OC_STACK_OK != res)
3492 currentEntry->res = res;
3493 currentEntry->csr = NULL;
3494 currentEntry->csrLen = 0;
3495 currentEntry->encoding = OIC_ENCODING_UNKNOW;
3499 ++(getCsrData->numOfResults);
3503 * Callback handler of SRPGetCSRResource.
3505 * @param[in] ctx ctx value passed to callback from calling function.
3506 * @param[in] UNUSED handle to an invocation
3507 * @param[in] clientResponse Response from queries to remote servers.
3508 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
3509 * and OC_STACK_KEEP_TRANSACTION to keep it.
3511 static OCStackApplicationResult SRPGetCSRResourceCB(void *ctx, OCDoHandle UNUSED,
3512 OCClientResponse *clientResponse)
3515 OIC_LOG_V(INFO, TAG, "IN %s", __func__);
3517 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3518 GetCsrData_t *getCsrData = (GetCsrData_t*)ctx;
3519 OCGetCSRResultCB resultCallback = getCsrData->resultCallback;
3523 if (OC_STACK_OK == clientResponse->result)
3525 uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3526 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3528 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3530 registerResultForGetCSRResourceCB(getCsrData, OC_STACK_OK, payload, size);
3535 registerResultForGetCSRResourceCB(getCsrData, OC_STACK_ERROR, NULL, 0);
3538 ((OCGetCSRResultCB)(resultCallback))(getCsrData->ctx, getCsrData->numOfResults,
3541 OIC_LOG_V(ERROR, TAG, "%s: received Null clientResponse", __func__);
3542 for (i = 0; i < getCsrData->numOfResults; i++)
3544 OICFree(getCsrData->resArr[i].csr);
3546 OICFree(getCsrData->resArr);
3547 OICFree(getCsrData);
3548 OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
3550 return OC_STACK_DELETE_TRANSACTION;
3553 OCStackResult SRPGetCSRResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3554 OCGetCSRResultCB resultCallback)
3556 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
3557 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
3559 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3560 if (!PMGenerateQuery(true,
3561 selectedDeviceInfo->endpoint.addr,
3562 selectedDeviceInfo->securePort,
3563 selectedDeviceInfo->connType,
3564 query, sizeof(query), OIC_RSRC_CSR_URI))
3566 OIC_LOG(ERROR, TAG, "SRPGetCSRResource : Failed to generate query");
3567 return OC_STACK_ERROR;
3569 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3571 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
3572 cbData.cb = &SRPGetCSRResourceCB;
3573 GetCsrData_t* getCsrData = (GetCsrData_t*)OICCalloc(1, sizeof(GetCsrData_t));
3574 if (NULL == getCsrData)
3576 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3577 return OC_STACK_NO_MEMORY;
3579 getCsrData->deviceInfo = selectedDeviceInfo;
3580 getCsrData->resultCallback = resultCallback;
3581 getCsrData->numOfResults=0;
3582 getCsrData->ctx = ctx;
3584 int noOfRiCalls = 1;
3585 getCsrData->resArr = (OCPMGetCsrResult_t*)OICCalloc(noOfRiCalls, sizeof(OCPMGetCsrResult_t));
3586 if (NULL == getCsrData->resArr)
3588 OICFree(getCsrData);
3589 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3590 return OC_STACK_NO_MEMORY;
3592 cbData.context = (void *)getCsrData;
3593 OCMethod method = OC_REST_GET;
3594 OCDoHandle handle = NULL;
3595 OIC_LOG(DEBUG, TAG, "Sending Get CSR to resource server");
3596 OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3597 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3598 if (OC_STACK_OK != ret)
3600 OIC_LOG(ERROR, TAG, "OCStack resource error");
3601 OICFree(getCsrData->resArr);
3602 OICFree(getCsrData);
3604 OIC_LOG(DEBUG, TAG, "OUT SRPGetCSRResource");
3610 * Internal Function to store results in result array during GetRolesResourceCB.
3612 static void registerResultForGetRolesResourceCB(GetRolesData_t *getRolesData,
3613 OCStackResult stackresult,
3614 const uint8_t *payload,
3617 /* SRPGetRolesResource allocates the memory for getRolesData. When it calls this callback,
3618 * numOfResults points to the current entry we're filling out. Later when this structure
3619 * gets returned to the caller, that's when it actually reflects the number of
3622 OCPMGetRolesResult_t* currentEntry = &getRolesData->resArr[getRolesData->numOfResults];
3623 OIC_LOG_V(INFO, TAG, "Inside registerResultForGetCSRResourceCB "
3624 "getRolesData->numOfResults is %zu\n", getRolesData->numOfResults);
3625 memcpy(currentEntry->deviceId.id,
3626 getRolesData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3627 currentEntry->res = stackresult;
3628 currentEntry->chainsLength = 0;
3630 if (OC_STACK_OK == stackresult)
3632 RoleCertChain_t *chains = NULL;
3633 OCStackResult res = CBORPayloadToRoles(payload, payloadSize, &chains);
3634 if (OC_STACK_OK != res)
3636 currentEntry->res = res;
3637 currentEntry->chains = NULL;
3641 RoleCertChain_t *curr = NULL;
3642 for (curr = chains; NULL != curr; curr = curr->next)
3644 currentEntry->chainsLength++;
3646 currentEntry->chains = (OCPMRoleCertChain_t *)OICCalloc(currentEntry->chainsLength, sizeof(OCPMRoleCertChain_t));
3647 if (NULL == currentEntry->chains)
3649 OIC_LOG(ERROR, TAG, "No memory allocating role chains");
3650 currentEntry->chainsLength = 0;
3651 currentEntry->res = OC_STACK_NO_MEMORY;
3656 for (i = 0, curr = chains; NULL != curr; curr = curr->next, i++)
3658 currentEntry->chains[i].credId = curr->credId;
3659 /* Take ownership of the buffers from certificate and optData, rather than copy. */
3660 currentEntry->chains[i].certificate = curr->certificate;
3661 currentEntry->chains[i].optData = curr->optData;
3663 curr->certificate.data = NULL;
3664 curr->certificate.len = 0;
3665 curr->optData.data = NULL;
3666 curr->optData.len = 0;
3669 FreeRoleCertChainList(chains);
3673 ++(getRolesData->numOfResults);
3677 * Callback handler of SRPGetRolesResource.
3679 * @param[in] ctx ctx value passed to callback from calling function.
3680 * @param[in] UNUSED handle to an invocation
3681 * @param[in] clientResponse Response from queries to remote servers.
3682 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
3683 * and OC_STACK_KEEP_TRANSACTION to keep it.
3685 static OCStackApplicationResult SRPGetRolesResourceCB(void *ctx, OCDoHandle handle,
3686 OCClientResponse *clientResponse)
3688 OIC_LOG(INFO, TAG, "Inside SRPGetRolesResourceCB.");
3690 VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
3691 GetRolesData_t *getRolesData = (GetRolesData_t*)ctx;
3692 OCGetRolesResultCB resultCallback = getRolesData->resultCallback;
3696 if (OC_STACK_OK == clientResponse->result)
3698 uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
3699 size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
3701 OIC_LOG_BUFFER(DEBUG, TAG, payload, size);
3703 registerResultForGetRolesResourceCB(getRolesData, OC_STACK_OK, payload, size);
3708 OIC_LOG(ERROR, TAG, "SRPGetRolesResourceCB received Null clientResponse");
3709 registerResultForGetRolesResourceCB(getRolesData, OC_STACK_ERROR, NULL, 0);
3712 resultCallback(getRolesData->ctx, getRolesData->numOfResults,
3713 getRolesData->resArr,
3715 for (size_t i = 0; i < getRolesData->numOfResults; i++)
3717 /* We took ownership of certificate.data and optData.data, so we must free them.
3718 * These are allocated internally by tinycbor, which uses malloc and free, so we call
3719 * free directly for those.
3721 for (size_t j = 0; j < getRolesData->resArr[i].chainsLength; j++)
3723 free(getRolesData->resArr[i].chains[j].certificate.data);
3724 free(getRolesData->resArr[i].chains[j].optData.data);
3726 OICFree(getRolesData->resArr[i].chains);
3728 OICFree(getRolesData->resArr);
3729 OICFree(getRolesData);
3731 return OC_STACK_DELETE_TRANSACTION;
3734 OCStackResult SRPGetRolesResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
3735 OCGetRolesResultCB resultCallback)
3737 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
3738 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
3740 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3741 if (!PMGenerateQuery(true,
3742 selectedDeviceInfo->endpoint.addr,
3743 selectedDeviceInfo->securePort,
3744 selectedDeviceInfo->connType,
3745 query, sizeof(query), OIC_RSRC_ROLES_URI))
3747 OIC_LOG(ERROR, TAG, "SRPGetRolesResource : Failed to generate query");
3748 return OC_STACK_ERROR;
3750 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3752 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
3753 cbData.cb = &SRPGetRolesResourceCB;
3754 GetRolesData_t *getRolesData = (GetRolesData_t*)OICCalloc(1, sizeof(GetRolesData_t));
3755 if (NULL == getRolesData)
3757 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3758 return OC_STACK_NO_MEMORY;
3760 getRolesData->deviceInfo = selectedDeviceInfo;
3761 getRolesData->resultCallback = resultCallback;
3762 getRolesData->numOfResults = 0;
3763 getRolesData->ctx = ctx;
3765 getRolesData->resArr = (OCPMGetRolesResult_t*)OICCalloc(1, sizeof(OCPMGetRolesResult_t));
3766 if (NULL == getRolesData->resArr)
3768 OICFree(getRolesData);
3769 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3770 return OC_STACK_NO_MEMORY;
3772 cbData.context = (void *)getRolesData;
3773 OCDoHandle handle = NULL;
3774 OIC_LOG(DEBUG, TAG, "Sending Get Roles to resource server");
3775 OCStackResult ret = OCDoResource(&handle, OC_REST_GET, query, NULL, NULL,
3776 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3777 if (OC_STACK_OK != ret)
3779 OIC_LOG(ERROR, TAG, "OCStack resource error");
3780 OICFree(getRolesData->resArr);
3781 OICFree(getRolesData);
3783 OIC_LOG(DEBUG, TAG, "OUT SRPGetRolesResource");
3789 * Callback handler of SRPDeleteRoleCertificateByCredId.
3791 * @param[in] ctx ctx value passed to callback from calling function.
3792 * @param[in] UNUSED handle to an invocation
3793 * @param[in] clientResponse Response from queries to remote servers.
3794 * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
3795 * and OC_STACK_KEEP_TRANSACTION to keep it.
3797 static OCStackApplicationResult SRPDeleteRoleCertificateCB(void *ctx, OCDoHandle UNUSED,
3798 OCClientResponse *clientResponse)
3801 GetSecData_t *getSecData = (GetSecData_t *)ctx;
3802 OCProvisionResultCB resultCallback = getSecData->resultCallback;
3804 OIC_LOG(DEBUG, TAG, "SRPDeleteRoleCertificateCB IN");
3806 if (NULL != clientResponse)
3808 memcpy(getSecData->resArr[(getSecData->numOfResults)].deviceId.id,
3809 getSecData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
3810 getSecData->resArr[(getSecData->numOfResults)].res = clientResponse->result;
3811 ++(getSecData->numOfResults);
3812 resultCallback(getSecData->ctx, getSecData->numOfResults, getSecData->resArr, false);
3815 OIC_LOG(DEBUG, TAG, "SRPDeleteRoleCertificateCB OUT");
3817 return OC_STACK_DELETE_TRANSACTION;
3820 OCStackResult SRPDeleteRoleCertificateByCredId(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
3821 OCProvisionResultCB resultCallback, uint32_t credId)
3823 VERIFY_NOT_NULL_RETURN(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
3824 VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
3826 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3827 if (!PMGenerateQuery(true,
3828 selectedDeviceInfo->endpoint.addr,
3829 selectedDeviceInfo->securePort,
3830 selectedDeviceInfo->connType,
3831 query, sizeof(query), OIC_RSRC_ROLES_URI))
3833 OIC_LOG(ERROR, TAG, "SRPDeleteRoleCertificateByCredId : Failed to generate query");
3834 return OC_STACK_ERROR;
3836 size_t queryLen = strlen(query);
3837 int snRet = snprintf(query + queryLen, sizeof(query) - queryLen, "?credId=%u", credId);
3841 OIC_LOG_V(ERROR, TAG, "snprintf returned error: %d", snRet);
3842 return OC_STACK_ERROR;
3844 else if ((size_t)snRet >= (sizeof(query) - queryLen))
3846 OIC_LOG_V(ERROR, TAG, "snprintf truncated");
3847 return OC_STACK_ERROR;
3850 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
3852 OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
3853 cbData.cb = &SRPDeleteRoleCertificateCB;
3854 GetSecData_t *getSecData = (GetSecData_t*)OICCalloc(1, sizeof(GetSecData_t));
3855 if (NULL == getSecData)
3857 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3858 return OC_STACK_NO_MEMORY;
3860 getSecData->deviceInfo = selectedDeviceInfo;
3861 getSecData->resultCallback = resultCallback;
3862 getSecData->numOfResults = 0;
3863 getSecData->ctx = ctx;
3865 getSecData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
3866 if (NULL == getSecData->resArr)
3868 OICFree(getSecData);
3869 OIC_LOG(ERROR, TAG, "Unable to allocate memory");
3870 return OC_STACK_NO_MEMORY;
3872 cbData.context = (void *)getSecData;
3873 OCMethod method = OC_REST_DELETE;
3874 OCDoHandle handle = NULL;
3875 OIC_LOG(DEBUG, TAG, "Sending Delete Roles to resource server");
3876 OCStackResult ret = OCDoResource(&handle, method, query, NULL, NULL,
3877 selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
3878 if (OC_STACK_OK != ret)
3880 OIC_LOG(ERROR, TAG, "OCStack resource error");
3881 OICFree(getSecData->resArr);
3882 OICFree(getSecData);
3884 OIC_LOG(DEBUG, TAG, "OUT SRPGetRolesResource");
3889 OCStackResult SRPReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
3892 OIC_LOG(DEBUG, TAG, "IN SRPReadTrustCertChain");
3894 OCStackResult res = OC_STACK_ERROR;
3896 OicSecCred_t* credData = GetCredEntryByCredId(credId);
3899 res = CredToCBORPayload((const OicSecCred_t*) credData, trustCertChain,
3900 chainSize, secureFlag);
3901 if(OC_STACK_OK != res)
3903 OIC_LOG(INFO, TAG, "CredToCBORPayload failed");
3906 DeleteCredList(credData);
3912 * Updates provisioning result.
3914 static void RegisterProvResult(const OCProvisionDev_t *targetDev, OCProvisionResult_t *resArr,
3915 int *numOfResults, OCStackResult stackResult)
3918 OIC_LOG_V(INFO, TAG, "value of numOfResults is %d", *numOfResults);
3919 memcpy(resArr[*numOfResults].deviceId.id, targetDev->doxm->deviceID.id, UUID_LENGTH);
3920 resArr[*numOfResults].res = stackResult;
3924 static OCStackApplicationResult ProvisionAclCB(void *ctx, OCDoHandle UNUSED,
3925 OCClientResponse *clientResponse)
3927 if (NULL == ctx || NULL == clientResponse)
3929 OIC_LOG_V(ERROR, TAG, " ctx: %p, clientResponse: %p", ctx, clientResponse);
3930 return OC_STACK_INVALID_PARAM;
3933 if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
3935 Data_t *data = (Data_t *) ctx;
3936 if (ACL_TYPE != data->type)
3938 OIC_LOG(ERROR, TAG, "Invalid type");
3939 return OC_STACK_INVALID_PARAM;
3942 ACLData_t *aclData = (ACLData_t *) (data->ctx);
3944 const char *uri = NULL;
3946 switch (aclData->aclVersion)
3948 case OIC_SEC_ACL_V1:
3949 OIC_LOG(WARNING, TAG,
3950 "%s using ACL v1... this should only be used for provisioning OIC 1.1 and earlier Servers.");
3951 uri = OIC_RSRC_ACL_URI;
3953 case OIC_SEC_ACL_V2:
3954 uri = OIC_RSRC_ACL2_URI;
3957 return OC_STACK_INVALID_PARAM;
3960 // if rowneruuid is empty, set it to device ID
3961 OicUuid_t emptyOwner = {.id = {0} };
3962 if (memcmp(&(aclData->acl->rownerID.id), &emptyOwner, UUID_IDENTITY_SIZE) == 0)
3964 OIC_LOG(DEBUG, TAG, "Set Rowner to PT's deviceId, because Rowner of ACL is empty");
3967 if (OC_STACK_OK == GetDoxmDeviceID(&oicUuid))
3969 memcpy(&(aclData->acl->rownerID.id), &oicUuid, UUID_IDENTITY_SIZE);
3973 OIC_LOG(ERROR, TAG, "Failed to set Rowner to PT's deviceID\
3974 becuase it failed to retrieve Doxm DeviceID");
3975 return OC_STACK_ERROR;
3979 OCSecurityPayload *secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
3982 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3983 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
3984 return OC_STACK_NO_MEMORY;
3986 secPayload->base.type = PAYLOAD_TYPE_SECURITY;
3987 if (OC_STACK_OK != AclToCBORPayload(aclData->acl, aclData->aclVersion, &secPayload->securityData,
3988 &secPayload->payloadSize))
3990 OCPayloadDestroy((OCPayload *)secPayload);
3991 OIC_LOG(ERROR, TAG, "Failed to AclToCBORPayload");
3992 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
3993 return OC_STACK_NO_MEMORY;
3995 OIC_LOG(DEBUG, TAG, "Created payload for ACL:");
3996 OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
3998 char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
3999 if (!PMGenerateQuery(true,
4000 aclData->deviceInfo->endpoint.addr,
4001 aclData->deviceInfo->securePort,
4002 aclData->deviceInfo->connType,
4003 query, sizeof(query), uri))
4005 OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
4006 return OC_STACK_ERROR;
4008 OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
4010 OCCallbackData cbData = {.context = NULL, .cb = NULL, .cd = NULL};
4011 cbData.cb = ProvisionCB;
4012 cbData.context = ctx;
4014 OCMethod method = OC_REST_POST;
4015 OCDoHandle handle = NULL;
4016 OIC_LOG(DEBUG, TAG, "Sending ACL info to resource server");
4017 OCStackResult ret = OCDoResource(&handle, method, query,
4018 &aclData->deviceInfo->endpoint, (OCPayload *)secPayload,
4019 aclData->deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
4020 if (ret != OC_STACK_OK)
4022 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
4023 return OC_STACK_ERROR;
4028 OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
4029 return OC_STACK_ERROR;
4031 OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);