OicSecCred_t **firstCred,
OicSecCred_t **secondCred);
+/**
+ * Function to generate certificate credentials.
+ *
+ * @param[in] ptDeviceId Device ID of provisioning tool.
+ * @param[in] deviceId DeviceID of the device.
+ * @param[out] cred Generated credential for device.
+ * @return OC_STACK_OK on success
+ */
+OCStackResult PMGenerateCertificateCredentials(const OicUuid_t *ptDeviceId,
+ const OicUuid_t *deviceId, OicSecCred_t **cred);
+
#ifdef __cplusplus
}
#endif
-/* *****************************************************************\r
- *\r
- * Copyright 2015 Samsung Electronics All Rights Reserved.\r
- *\r
- *\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- * *****************************************************************/\r
-\r
-#ifndef OCPROVISIONINGMANAGER_H_\r
-#define OCPROVISIONINGMANAGER_H_\r
-\r
-#include "octypes.h"\r
-#include "pmtypes.h"\r
-#include "ownershiptransfermanager.h"\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif // __cplusplus\r
-\r
-/**\r
- * The function is responsible for initializaton of the provisioning manager. It will load\r
- * provisioning database which have owned device's list and their linked status.\r
- * In addition, if there is a device(s) which has not up-to-date credentials, this function will\r
- * automatically try to update the deivce(s).\r
- *\r
- * @param[in] dbPath file path of the sqlite3 db\r
- *\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCProvisionInit(const char* dbPath);\r
-\r
-/**\r
- * The function is responsible for discovery of device is current subnet. It will list\r
- * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as\r
- * OCMode.\r
- *\r
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
- * client before returning the list of devices.\r
- * @param[out] ppList List of candidate devices to be provisioned\r
- * @return OTM_SUCCESS in case of success and other value otherwise.\r
- */\r
-OCStackResult OCDiscoverUnownedDevices(unsigned short waittime, OCProvisionDev_t **ppList);\r
-\r
-/**\r
- * Do ownership transfer for un-owned device.\r
- *\r
- * @param[in] ctx Application context would be returned in result callback\r
- * @param[in] targetDevices List of devices to perform ownership transfer.\r
- * @param[in] resultCallback Result callback function to be invoked when ownership transfer finished.\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCDoOwnershipTransfer(void* ctx,\r
- OCProvisionDev_t *targetDevices,\r
- OCProvisionResultCB resultCallback);\r
-\r
-/**\r
- * API to register for particular OxM.\r
- *\r
- * @param[in] Ownership transfer method.\r
- * @param[in] Implementation of callback functions for owership transfer.\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);\r
-\r
-/**\r
- * The function is responsible for discovery of owned device is current subnet. It will list\r
- * all the device in subnet which are owned by calling provisioning client.\r
- *\r
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
- * client before returning the list of devices.\r
- * @param[out] ppList List of device owned by provisioning tool.\r
- * @return OTM_SUCCESS in case of success and other value otherwise.\r
- */\r
-OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
-\r
-/**\r
- * API to provision credentials between two devices and ACLs for the devices who act as a server.\r
- *\r
- * @param[in] ctx Application context would be returned in result callback.\r
- * @param[in] type Type of credentials to be provisioned to the device.\r
- * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
- * @param[in] acl ACL for device 1. If this is not required set NULL.\r
- * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
- * @param[in] acl ACL for device 2. If this is not required set NULL.\r
- * @param[in] resultCallback callback provided by API user, callback will be called when\r
- * provisioning request recieves a response from first resource server.\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,\r
- const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,\r
- const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,\r
- OCProvisionResultCB resultCallback);\r
-\r
-/**\r
- * API to send ACL information to device.\r
- *\r
- * @param[in] ctx Application context would be returned in result callback.\r
- * @param[in] selectedDeviceInfo Selected target device.\r
- * @param[in] acl ACL to provision.\r
- * @param[in] resultCallback callback provided by API user, callback will be called when provisioning\r
- request recieves a response from resource server.\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,\r
- OCProvisionResultCB resultCallback);\r
-\r
-/**\r
- * API to provision credential to devices.\r
- *\r
- * @param[in] ctx Application context would be returned in result callback.\r
- * @param[in] type Type of credentials to be provisioned to the device.\r
- * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\r
- @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\r
- * @param[in] resultCallback callback provided by API user, callback will be called when\r
- * provisioning request recieves a response from first resource server.\r
- * @return OC_STACK_OK in case of success and other value otherwise.\r
- */\r
-OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,\r
- const OCProvisionDev_t *pDev1,\r
- const OCProvisionDev_t *pDev2,\r
- OCProvisionResultCB resultCallback);\r
-\r
-/**\r
- * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API.\r
- *\r
- * @param[in] ppList Pointer to OCProvisionDev_t which should be deleted.\r
- */\r
-void OCDeleteDiscoveredDevices(OCProvisionDev_t **ppList);\r
-\r
-/**\r
- * API to delete memory allocated to OCProvisionResult_t list in callback function.\r
- *\r
- * @note: This function must be called in the callback implementation after checking results.\r
- *\r
- * @param[in] pList Pointer to OCProvisionResult_t list which should be deleted.\r
- */\r
-void OCDeleteProvisionResults(OCProvisionResult_t *pList);\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif // __cplusplus\r
-\r
-#endif /* OCPROVISIONINGMANAGER_H_ */\r
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#ifndef OCPROVISIONINGMANAGER_H_
+#define OCPROVISIONINGMANAGER_H_
+
+#include "octypes.h"
+#include "pmtypes.h"
+#include "ownershiptransfermanager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * The function is responsible for initializaton of the provisioning manager. It will load
+ * provisioning database which have owned device's list and their linked status.
+ * In addition, if there is a device(s) which has not up-to-date credentials, this function will
+ * automatically try to update the deivce(s).
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionInit(const char* dbPath);
+
+/**
+ * The function is responsible for discovery of device is current subnet. It will list
+ * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
+ * OCMode.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * client before returning the list of devices.
+ * @param[out] ppList List of candidate devices to be provisioned
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverUnownedDevices(unsigned short waittime, OCProvisionDev_t **ppList);
+
+/**
+ * Do ownership transfer for un-owned device.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] targetDevices List of devices to perform ownership transfer.
+ * @param[in] resultCallback Result callback function to be invoked when ownership transfer finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCDoOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *targetDevices,
+ OCProvisionResultCB resultCallback);
+
+/**
+ * API to register for particular OxM.
+ *
+ * @param[in] Ownership transfer method.
+ * @param[in] Implementation of callback functions for owership transfer.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);
+
+/**
+ * The function is responsible for discovery of owned device is current subnet. It will list
+ * all the device in subnet which are owned by calling provisioning client.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * client before returning the list of devices.
+ * @param[out] ppList List of device owned by provisioning tool.
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);
+
+/**
+ * API to provision credentials between two devices and ACLs for the devices who act as a server.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.
+ * @param[in] acl ACL for device 1. If this is not required set NULL.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.
+ * @param[in] acl ACL for device 2. If this is not required set NULL.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,
+ const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,
+ OCProvisionResultCB resultCallback);
+
+/**
+ * API to send ACL information to device.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+ request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,
+ OCProvisionResultCB resultCallback);
+
+/**
+ * API to provision credential to devices.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ OCProvisionResultCB resultCallback);
+
+/**
+ * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API.
+ *
+ * @param[in] ppList Pointer to OCProvisionDev_t which should be deleted.
+ */
+void OCDeleteDiscoveredDevices(OCProvisionDev_t **ppList);
+
+/**
+ * API to delete memory allocated to OCProvisionResult_t list in callback function.
+ *
+ * @note: This function must be called in the callback implementation after checking results.
+ *
+ * @param[in] pList Pointer to OCProvisionResult_t list which should be deleted.
+ */
+void OCDeleteProvisionResults(OCProvisionResult_t *pList);
+
+#ifdef __WITH_X509__
+/**
+ * this function sends CRL information to resource.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] crl CRL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+ request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionCRL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecCrl_t *crl,
+ OCProvisionResultCB resultCallback);
+#endif // __WITH_X509__
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* OCPROVISIONINGMANAGER_H_ */
#include <string.h>
#include "credentialgenerator.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#include "logger.h"
#include "credresource.h"
#include "ocrandom.h"
#include "base64.h"
#include "stdbool.h"
#include "securevirtualresourcetypes.h"
+#ifdef __WITH_X509__
+#include "ck_manager.h"
+
+#define CHAIN_LEN (2) //TODO: replace by external define or a runtime value
+#endif //__WITH_X509__
#define TAG "SRPAPI-CG"
return res;
}
+
+#ifdef __WITH_X509__
+/**
+ * Function to compose JSON Web Key (JWK) string from a certificate and a public key.
+ *
+ * @param[in] certificateChain Array of Base64 encoded certificate strings.
+ * @param[in] chainLength Number of the certificates in certificateChain.
+ * @return Valid JWK string on success, or NULL on fail.
+ */
+static char *CreateCertificatePublicJWK(const char *const *certificateChain,
+ const size_t chainLength)
+{
+ if (NULL == certificateChain || chainLength == 0)
+ {
+ OC_LOG(ERROR, TAG, "Error CreateCertificatePublicJWK: Invalid params");
+ return NULL;
+ }
+
+ size_t certChainSize = 0;
+ for (size_t i = 0; i < chainLength; ++i)
+ {
+ if (NULL != certificateChain[i])
+ {
+ certChainSize += strlen(certificateChain[i]);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error CreateCertificatePublicJWK: Invalid params");
+ return NULL;
+ }
+
+ }
+ /* certificates in the json array taken in quotes and separated by a comma
+ * so we have to count the number of characters (number of commas and quotes) required
+ * for embedding certificates in the array depending on the number of certificates in chain
+ * each certificate except last embeded in "\"%s\"," */
+ const int numCommasAndQuotes = chainLength * 3 - 1;
+ const char firstPart[] = "{\"kty\":\"EC\",\"crv\":\"P-256\",\"x5c\":[";
+ const char secondPart[] = "]}";
+ /* to calculate the size of JWK public part we need to add the value of first and second parts,
+ * size of certificate chain, number of additional commas and quotes and 1 for string termination symbol */
+ size_t certPubJWKLen = strlen(firstPart) + strlen(secondPart)
+ + certChainSize + numCommasAndQuotes + 1;
+ char *certPubJWK = (char *)OICMalloc(certPubJWKLen);
+
+ if (NULL != certPubJWK)
+ {
+ OICStrcpy(certPubJWK, certPubJWKLen, firstPart);
+ size_t offset = strlen(firstPart);
+ for (size_t i = 0; i < chainLength; ++i)
+ {
+ offset += sprintf(certPubJWK + offset, "\"%s\",", certificateChain[i]);
+ }
+ sprintf(certPubJWK + offset - 1, secondPart);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ }
+ return certPubJWK;
+}
+
+/**
+ * Function to compose JWK string from a private key.
+ *
+ * @param[in] privateKey Base64 encoded private key.
+ * @return Valid JWK string on success, or NULL on fail.
+ */
+static char *CreateCertificatePrivateJWK(const char *privateKey)
+{
+ if (NULL == privateKey)
+ {
+ OC_LOG(ERROR, TAG, "Error privateKey is NULL");
+ return NULL;
+ }
+ const char firstPart[] = "{\"kty\":\"EC\",\"crv\":\"P-256\",\"d\":\"";
+ const char secondPart[] = "\"}";
+ char *certPrivJWK = (char *)OICMalloc(strlen(firstPart) + strlen(secondPart) + strlen(
+ privateKey) + 1);
+
+ if (NULL != certPrivJWK)
+ {
+ sprintf(certPrivJWK, "%s%s%s", firstPart, privateKey, secondPart);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ }
+ return certPrivJWK;
+}
+
+
+/**
+ * Function to generate Base64 encoded credential data for device.
+ *
+ * @param[in] subject Device id.
+ * @param[out] certificateChain Pointer to Array of Base64 encoded certificate strings.
+ * @param[out] chainLength Pointer to number of the certificates in certificateChain.
+ * @param[out] privKey Pointer to Base64 encoded private key.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult GenerateCertificateAndKeys(const OicUuid_t * subject, char *** const certificateChain,
+ size_t * const chainLength, char ** const privKey)
+{
+ if (NULL == subject || NULL == certificateChain || NULL == chainLength || NULL == privKey)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ *certificateChain = NULL;
+ *privKey = NULL;
+
+ ByteArray pubKeyBA = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyBA = BYTE_ARRAY_INITIALIZER;
+ ByteArray cert[CHAIN_LEN];
+
+ uint8_t pubKeyData[PUBLIC_KEY_SIZE] = {0};
+ uint8_t privKeyData[PRIVATE_KEY_SIZE] = {0};
+ uint8_t certData[ISSUER_MAX_CERT_SIZE * CHAIN_LEN] = {0};
+ uint8_t subjName[UUID_LENGTH + 1] = {0};
+
+ pubKeyBA.data = pubKeyData;
+ pubKeyBA.len = PUBLIC_KEY_SIZE;
+ privKeyBA.data = privKeyData;
+ privKeyBA.len = PRIVATE_KEY_SIZE;
+ for (size_t i = 0; i < CHAIN_LEN; ++i)
+ {
+ cert[i].data = certData + ISSUER_MAX_CERT_SIZE * i;
+ cert[i].len = ISSUER_MAX_CERT_SIZE;
+ }
+
+ memcpy(subjName, subject->id, UUID_LENGTH);
+ subjName[UUID_LENGTH] = '\0';
+
+ if (PKI_SUCCESS != GenerateKeyPair(&privKeyBA, &pubKeyBA))
+ {
+ OC_LOG(ERROR, TAG, "Error generating keys.");
+ return OC_STACK_ERROR;
+ }
+ if (PKI_SUCCESS != CKMIssueDeviceCertificate(subjName, NULL, NULL, pubKeyBA.data, cert))
+ {
+ OC_LOG(ERROR, TAG, "Error generating certificate.");
+ return OC_STACK_ERROR;
+ }
+
+ char privB64buf[B64ENCODE_OUT_SAFESIZE(PRIVATE_KEY_SIZE) + 1] = {0};
+ uint32_t privB64len = 0;
+ if (B64_OK != b64Encode(privKeyBA.data, privKeyBA.len, privB64buf,
+ B64ENCODE_OUT_SAFESIZE(PRIVATE_KEY_SIZE) + 1, &privB64len))
+ {
+ OC_LOG(ERROR, TAG, "Error while encoding key");
+ return OC_STACK_ERROR;
+ }
+
+ if (PKI_SUCCESS != GetCAChain(chainLength , cert + 1))
+ {
+ OC_LOG(ERROR, TAG, "Error getting CA certificate chain.");
+ return OC_STACK_ERROR;
+ }
+
+ ++(*chainLength);
+ *certificateChain = (char **)OICMalloc(sizeof(char *) * (*chainLength));
+
+ OCStackResult ret = OC_STACK_NO_MEMORY;
+ if (NULL == *certificateChain)
+ {
+ goto memclean;
+ }
+
+
+ for (size_t i = 0; i < *chainLength; ++i)
+ {
+ (*certificateChain)[i] = NULL;
+
+ char certB64buf[B64ENCODE_OUT_SAFESIZE(ISSUER_MAX_CERT_SIZE) + 1] = {0};
+ uint32_t certB64len = 0;
+ if (B64_OK != b64Encode(cert[i].data, cert[i].len, certB64buf,
+ B64ENCODE_OUT_SAFESIZE(ISSUER_MAX_CERT_SIZE) + 1, &certB64len))
+ {
+ OC_LOG(ERROR, TAG, "Error while encoding certificate");
+ ret = OC_STACK_ERROR;
+ goto memclean;
+ }
+
+ (*certificateChain)[i] = (char *) OICMalloc(certB64len + 1);
+ if (NULL == (*certificateChain)[i])
+ {
+ goto memclean;
+ }
+
+ memcpy((*certificateChain)[i], certB64buf, certB64len + 1);
+ }
+
+
+ *privKey = (char *)OICMalloc(privB64len + 1);
+
+ if (NULL == *privKey)
+ {
+memclean:
+ if (NULL != *certificateChain)
+ {
+ for (size_t i = 0; i < *chainLength; ++i)
+ {
+ OICFree((*certificateChain)[i]);
+ }
+ }
+ OICFree(*certificateChain);
+ *certificateChain = NULL;
+ *privKey = NULL;
+ *chainLength = 0;
+ if (OC_STACK_NO_MEMORY == ret)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ }
+ return ret;
+ }
+
+ memcpy(*privKey, privB64buf, privB64len + 1);
+
+ return OC_STACK_OK;
+}
+
+
+OCStackResult PMGenerateCertificateCredentials(const OicUuid_t *ptDeviceId,
+ const OicUuid_t *deviceId, OicSecCred_t **const cred)
+{
+ if (NULL == ptDeviceId || NULL == deviceId || NULL == cred)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ char **certificateChain = NULL;
+ char *privKey = NULL;
+ size_t certChainLen = 0;
+ if (OC_STACK_OK != GenerateCertificateAndKeys(deviceId, &certificateChain,
+ &certChainLen, &privKey))
+ {
+ OC_LOG(ERROR, TAG, "Error while generating credential data.");
+ return OC_STACK_ERROR;
+ }
+
+ char *publicJWK = CreateCertificatePublicJWK(certificateChain, certChainLen);
+ char *privateJWK = CreateCertificatePrivateJWK(privKey);
+ for (size_t i = 0; i < certChainLen; ++i)
+ {
+ OICFree(certificateChain[i]);
+ }
+ OICFree(certificateChain);
+ OICFree(privKey);
+ if (NULL == publicJWK || NULL == privateJWK)
+ {
+ OICFree(publicJWK);
+ OICFree(privateJWK);
+ OC_LOG(ERROR, TAG, "Error while converting keys to JWK format.");
+ return OC_STACK_ERROR;
+ }
+
+ OicSecCred_t *tempCred = GenerateCredential(deviceId, SIGNED_ASYMMETRIC_KEY, publicJWK,
+ privateJWK, 1, ptDeviceId);
+ OICFree(publicJWK);
+ OICFree(privateJWK);
+ if (NULL == tempCred)
+ {
+ OC_LOG(ERROR, TAG, "Error while generating credential.");
+ return OC_STACK_ERROR;
+ }
+ *cred = tempCred;
+ return OC_STACK_OK;
+}
+#endif // __WITH_X509__
return res;
}
+#ifdef __WITH_X509__
+/**
+ * this function sends CRL information to resource.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] crl CRL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+ request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionCRL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecCrl_t *crl,
+ OCProvisionResultCB resultCallback)
+{
+ return SRPProvisionCRL(ctx, selectedDeviceInfo, crl, resultCallback);
+}
+#endif // __WITH_X509__
#include "pmtypes.h"
#include "pmutility.h"
+#ifdef __WITH_X509__
+#include "crlresource.h"
+#endif // WITH_X509__
+
#define SRP_MAX_URI_LENGTH 512
#define TAG "SRPAPI"
return OC_STACK_OK;
}
+#ifdef __WITH_X509__
+/**
+ * Structure to carry certificate data to callback.
+ */
+typedef struct CertificateData CertData_t;
+struct CertificateData
+{
+ void *ctx; /**< Pointer to user context.**/
+ const OCProvisionDev_t *deviceInfo; /**< Pointer to OCProvisionDev_t.**/
+ OicSecCred_t *credInfo; /**< Pointer to OicSecCred_t.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ OCProvisionResult_t *resArr; /**< Result array.**/
+ int numOfResults; /**< Number of results in result array.**/
+};
+
+/**
+ * Structure to carry CRL provision API data to callback.
+ */
+typedef struct CRLData CRLData_t;
+struct CRLData
+{
+ void *ctx; /**< Pointer to user context.**/
+ const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ OCProvisionResult_t *resArr; /**< Result array.**/
+ int numOfResults; /**< Number of results in result array.**/
+};
+
+/**
+ * Internal function to update result in result array.
+ */
+static void registerResultForCertProvisioning(CertData_t *certData,
+ OCStackResult stackresult)
+{
+
+ OC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",certData->numOfResults);
+ memcpy(certData->resArr[(certData->numOfResults)].deviceId.id,
+ certData->deviceInfo->doxm->deviceID.id,UUID_LENGTH);
+ certData->resArr[(certData->numOfResults)].res = stackresult;
+ ++(certData->numOfResults);
+}
+
+/**
+ * Internal Function to store results in result array during ACL provisioning.
+ */
+static void registerResultForCRLProvisioning(CRLData_t *crlData,
+ OCStackResult stackresult)
+{
+ OC_LOG_V(INFO, TAG, "Inside registerResultForCRLProvisioning crlData->numOfResults is %d\n",
+ crlData->numOfResults);
+ memcpy(crlData->resArr[(crlData->numOfResults)].deviceId.id,
+ crlData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+ crlData->resArr[(crlData->numOfResults)].res = stackresult;
+ ++(crlData->numOfResults);
+}
+
+
+/**
+ * Callback handler of SRPProvisionCRL.
+ *
+ * @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 SRPProvisionCRLCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG_V(INFO, TAG, "Inside SRPProvisionCRLCB.");
+ (void)UNUSED;
+ VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ CRLData_t *crlData = (CRLData_t*)ctx;
+ OCProvisionResultCB resultCallback = crlData->resultCallback;
+
+ if (clientResponse)
+ {
+ if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ registerResultForCRLProvisioning(crlData, OC_STACK_RESOURCE_CREATED);
+ ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
+ crlData->resArr,
+ false);
+ OICFree(crlData->resArr);
+ OICFree(crlData);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ registerResultForCRLProvisioning(crlData, OC_STACK_ERROR);
+ ((OCProvisionResultCB)(resultCallback))(crlData->ctx, crlData->numOfResults,
+ crlData->resArr,
+ true);
+ OC_LOG_V(ERROR, TAG, "SRPProvisionCRLCB received Null clientResponse");
+ OICFree(crlData->resArr);
+ OICFree(crlData);
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult SRPProvisionCRL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+ OicSecCrl_t *crl, OCProvisionResultCB resultCallback)
+{
+ VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, crl, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
+
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if (!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToCrlJSON(crl);
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Failed to BinToCrlJSON");
+ return OC_STACK_NO_MEMORY;
+ }
+ OC_LOG_V(INFO, TAG, "CRL : %s", secPayload->securityData);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ selectedDeviceInfo->endpoint.addr,
+ selectedDeviceInfo->securePort,
+ selectedDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRL_URI))
+ {
+ OC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+ OICFree(secPayload->securityData);
+ OICFree(secPayload);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &SRPProvisionCRLCB;
+ CRLData_t *crlData = (CRLData_t *) OICCalloc(1, sizeof(CRLData_t));
+ if (crlData == NULL)
+ {
+ OICFree(secPayload->securityData);
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Unable to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ crlData->deviceInfo = selectedDeviceInfo;
+ crlData->resultCallback = resultCallback;
+ crlData->numOfResults=0;
+ crlData->ctx = ctx;
+
+ crlData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+ if (crlData->resArr == NULL)
+ {
+ OICFree(secPayload->securityData);
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Unable to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ cbData.context = (void *)crlData;
+ cbData.cd = NULL;
+ OCMethod method = OC_REST_POST;
+ OCDoHandle handle = NULL;
+ OC_LOG(DEBUG, TAG, "Sending CRL info to resource server");
+
+ OCStackResult ret = OCDoResource(&handle, method, query,
+ &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+ selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+
+ if (ret != OC_STACK_OK)
+ {
+ OICFree(crlData->resArr);
+ OICFree(crlData);
+ }
+
+ return ret;
+}
+
+/**
+ * Internal function for handling credential generation and sending cretificate credential.
+ *
+ * @param[in] cred Instance of cred resource.
+ * @param[in] deviceInfo information about device to which credential is to be provisioned.
+ * @param[in] responseHandler callbak called by OC stack when request API receives response.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+static OCStackResult provisionCertCred(const OicSecCred_t *cred,
+ const OCProvisionDev_t *deviceInfo, CertData_t *certData,
+ OCClientResponseHandler responseHandler)
+{
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToCredJSON(cred);
+
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Failed to BinToCredJSON");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ OC_LOG_V(INFO, TAG, "Credential for provisioning : %s",secPayload->securityData);
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ deviceInfo->endpoint.addr,
+ deviceInfo->securePort,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRED_URI))
+ {
+ OC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+ OICFree(secPayload->securityData);
+ OICFree(secPayload);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = responseHandler;
+ cbData.context = (void *) certData;
+ cbData.cd = NULL;
+
+ OCDoHandle handle = NULL;
+ OCMethod method = OC_REST_POST;
+ OCStackResult ret = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ OC_LOG_V(INFO, TAG, "OCDoResource::Certificate provisioning returned : %d",ret);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ return ret;
+}
+
+/**
+ * Callback handler for handling callback of certificate provisioning device.
+ *
+ * @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 provisionCertCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ CertData_t *certData = (CertData_t *) ctx;
+ (void)UNUSED;
+
+ OCProvisionResultCB resultCallback = certData->resultCallback;
+ OC_LOG(INFO, TAG, "provisionCertCred called");
+ if (clientResponse)
+ {
+ if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ registerResultForCertProvisioning(certData, OC_STACK_RESOURCE_CREATED);
+ ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
+ certData->resArr,
+ false);
+ OICFree(certData->resArr);
+ OICFree(certData);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ }
+ OC_LOG(INFO, TAG, "provisionCertCredCB received Null clientResponse");
+ registerResultForCertProvisioning(certData, OC_STACK_ERROR);
+ ((OCProvisionResultCB)(resultCallback))(certData->ctx, certData->numOfResults,
+ certData->resArr,
+ true);
+ OICFree(certData->resArr);
+ OICFree(certData);
+ return OC_STACK_DELETE_TRANSACTION;
+}
+#endif // __WITH_X509__
+
OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
const OCProvisionDev_t *pDev1,
const OCProvisionDev_t *pDev2,
OCProvisionResultCB resultCallback)
{
VERIFY_NON_NULL(TAG, pDev1, ERROR, OC_STACK_INVALID_PARAM);
+ if (type == SYMMETRIC_PAIR_WISE_KEY)
VERIFY_NON_NULL(TAG, pDev2, ERROR, OC_STACK_INVALID_PARAM);
VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
- if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
+ if (type == SYMMETRIC_PAIR_WISE_KEY &&
+ !(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
{
OC_LOG(INFO, TAG, "Invalid key size");
return OC_STACK_INVALID_PARAM;
VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
return res;
}
+#ifdef __WITH_X509__
+ case SIGNED_ASYMMETRIC_KEY:
+ {
+ const OCProvisionDev_t *firstDevice = pDev1;
+ OicSecCred_t *cred = NULL;
+ OCStackResult res = PMGenerateCertificateCredentials(&provTooldeviceID,
+ &firstDevice->doxm->deviceID,&cred);
+ VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+ OC_LOG(INFO, TAG, "Certificate credentials generated successfully");
+ CertData_t *certData = (CertData_t *) OICCalloc(1, sizeof(CertData_t));
+ if (NULL == certData)
+ {
+ OC_LOG(ERROR, TAG, "Memory allocation problem");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ certData->deviceInfo = firstDevice;
+ certData->ctx = ctx;
+ certData->credInfo = cred;
+ certData->numOfResults = 0;
+ certData->resultCallback = resultCallback;
+
+ certData->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+ if (NULL == certData->resArr)
+ {
+ DeleteCredList(cred);
+ OICFree(certData);
+ OC_LOG(ERROR, TAG, "Memory allocation problem");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ res = provisionCertCred(cred, firstDevice, certData, &provisionCertCB);
+ if (OC_STACK_OK != res)
+ {
+ OICFree(certData->resArr);
+ OICFree(certData);
+ }
+ DeleteCredList(cred);
+ OC_LOG_V(INFO, TAG, "provisionCertCredentials returned: %d",res);
+
+ return res;
+ }
+#endif
default:
{
OC_LOG(ERROR, TAG, "Invalid option.");