+ if (((OIC_MANUFACTURER_CERTIFICATE == otmCtx->selectedDeviceInfo->doxm->oxmSel) ||
+ (OIC_CON_MFG_CERT == otmCtx->selectedDeviceInfo->doxm->oxmSel)) &&
+ OC_STACK_NOT_ACCEPTABLE == clientResponse->result)
+ {
+ res = OC_STACK_USER_DENIED_REQ;
+ OIC_LOG_V(ERROR, TAG,
+ "OwnerUuidUpdateHandler : Denied Request(%d)", res);
+ }
+ else if (OC_STACK_GATEWAY_TIMEOUT == clientResponse->result)
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG,
+ "OwnerUuidUpdateHandler : Timeout:No Response Received(%d)", res);
+ }
+ else
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG, "OwnerUuidUpdateHandler : Unexpected result(%d)", res);
+ }
+ SetResult(otmCtx, res);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT OwnerUuidUpdateHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/*
+ * Invokes Callback to load Random PIN
+ */
+void *LoadRandomPin(void *ctx)
+{
+ OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ OCStackResult res = OC_STACK_ERROR;
+ res = otmCtx->otmCallback.loadSecretCB(otmCtx);
+
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s : Failed to load secret", __func__);
+ SetResult(otmCtx, res);
+ OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+ return NULL;
+ }
+
+ //Save the current context instance to use on the dtls handshake callback
+ if(OC_STACK_OK != AddOTMContext(otmCtx,
+ otmCtx->selectedDeviceInfo->endpoint.addr,
+ otmCtx->selectedDeviceInfo->securePort))
+ {
+ OIC_LOG_V(ERROR, TAG, "%s : Failed to add OTM Context into OTM List.", __func__);
+ SetResult(otmCtx, res);
+ OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+ return NULL;
+ }
+
+ //Try DTLS handshake to generate secure session
+ if(otmCtx->otmCallback.createSecureSessionCB)
+ {
+ res = otmCtx->otmCallback.createSecureSessionCB(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s : Failed to create DTLS session", __func__);
+ SetResult(otmCtx, res);
+ }
+ }
+ OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+ return NULL;
+}
+
+/**
+ * Response handler for update operation mode.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OIC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
+
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ otmCtx->ocDoHandle = NULL;
+ (void) UNUSED;
+ if (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ OCStackResult res = OC_STACK_ERROR;
+
+ //DTLS Handshake
+ //Load secret for temporal secure session.
+ if(otmCtx->otmCallback.loadSecretCB)
+ {
+ if (OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+ {
+ pthread_t p_thread;
+ int thr_result;
+ thr_result = pthread_create(&p_thread, NULL, LoadRandomPin, (void *) otmCtx);
+ if (0 != thr_result)
+ {
+ OIC_LOG_V(ERROR, TAG, "pthread_create Error with code %d", thr_result);
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ OIC_LOG(INFO, TAG, "Random Pin loadSecretCB Thread Created");
+ }
+ else
+ {
+ res = otmCtx->otmCallback.loadSecretCB(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ //Save the current context instance to use on the dtls handshake callback
+ if(OC_STACK_OK != AddOTMContext(otmCtx,
+ otmCtx->selectedDeviceInfo->endpoint.addr,
+ otmCtx->selectedDeviceInfo->securePort))
+ {
+ OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to add OTM Context into OTM List.");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ //Try DTLS handshake to generate secure session
+ if(otmCtx->otmCallback.createSecureSessionCB)
+ {
+ res = otmCtx->otmCallback.createSecureSessionCB(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Error while update operation mode");
+ SetResult(otmCtx, clientResponse->result);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Response handler for update owner crendetial request.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OIC_LOG(DEBUG, TAG, "IN OwnerCredentialHandler");
+ (void)UNUSED;
+ OCStackResult res = OC_STACK_OK;
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ otmCtx->ocDoHandle = NULL;
+
+ if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ if(otmCtx && otmCtx->selectedDeviceInfo)
+ {
+ //Close the temporal secure session to verify the owner credential
+ CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
+ endpoint->port = otmCtx->selectedDeviceInfo->securePort;
+ CAResult_t caResult = CA_STATUS_OK;
+ caResult = CAcloseSslConnection(endpoint);
+
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
+ SetResult(otmCtx, caResult);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ /**
+ * If we select NULL cipher,
+ * client will select appropriate cipher suite according to server's cipher-suite list.
+ */
+ // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
+ caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
+ SetResult(otmCtx, caResult);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ /**
+ * in case of random PIN based OxM,
+ * revert get_psk_info callback of tinyDTLS to use owner credential.
+ */
+ if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+ {
+ OicUuid_t emptyUuid = { .id={0}};
+ SetUuidForPinBasedOxm(&emptyUuid);
+
+ caResult = CAregisterPskCredentialsHandler(GetDtlsPskCredentials);
+
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
+ SetResult(otmCtx, OC_STACK_INVALID_CALLBACK);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+#ifdef __WITH_TLS__
+ otmCtx->selectedDeviceInfo->connType |= CT_FLAG_SECURE;
+#endif
+ res = PostOwnerAcl(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to update owner ACL to new device");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ }
+ else
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG, "OwnerCredentialHandler : Unexpected result %d", res);
+ SetResult(otmCtx, res);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT OwnerCredentialHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Response handler for update owner ACL request.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OwnerAclHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OIC_LOG(DEBUG, TAG, "IN OwnerAclHandler");
+ (void)UNUSED;
+ OCStackResult res = OC_STACK_OK;
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ otmCtx->ocDoHandle = NULL;
+
+ if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ if(otmCtx && otmCtx->selectedDeviceInfo)
+ {
+ //POST /oic/sec/doxm [{ ..., "owned":"TRUE" }]
+ res = PostOwnershipInformation(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to update ownership information to new device");
+ SetResult(otmCtx, res);
+ }
+ }
+ }
+ else
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG, "OwnerAclHandler : Unexpected result %d", res);
+ SetResult(otmCtx, res);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT OwnerAclHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+/**
+ * Response handler for update owner information request.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OIC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+ (void)UNUSED;
+ OCStackResult res = OC_STACK_OK;
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ otmCtx->ocDoHandle = NULL;
+
+ if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ if(otmCtx && otmCtx->selectedDeviceInfo)
+ {
+ OIC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
+ OIC_LOG(INFO, TAG, "Set Ready for provisioning state .");
+
+ res = PostProvisioningStatus(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to update pstat");
+ SetResult(otmCtx, res);
+ }
+ }
+ }
+ else
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG, "OwnershipInformationHandler : Unexpected result %d", res);
+ SetResult(otmCtx, res);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+