diff --git a/resource/csdk/security/include/internal/credresource.h b/resource/csdk/security/include/internal/credresource.h index 876af2f88cdaf7ec30cf54738aa0362d440b3628..486ec8a9a3152adb220b031fdf29f3df14f01843 100644 --- a/resource/csdk/security/include/internal/credresource.h +++ b/resource/csdk/security/include/internal/credresource.h @@ -24,6 +24,7 @@ #include "cainterface.h" #include "securevirtualresourcetypes.h" #include "octypes.h" +#include "rolesresource.h" #include #ifdef __cplusplus @@ -125,13 +126,13 @@ OCStackResult AddCredential(OicSecCred_t * cred); /** * Function to remove credentials from the SVR DB for the given subject UUID. - * If multiple credentials exist for the UUID, they will all be removed. + * If multiple credentials exist for the UUID, they will all be removed. * * @param subject is the Credential Subject to be deleted. * - * @return ::OC_STACK_RESOURCE_DELETED if credentials were removed, or + * @return ::OC_STACK_RESOURCE_DELETED if credentials were removed, or * if there are no credentials with the given UUID. An error is returned if - * removing credentials failed. + * removing credentials failed. */ OCStackResult RemoveCredential(const OicUuid_t *subject); @@ -221,6 +222,18 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid); * @param[in] usage credential usage string. */ OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage); + +/** + * Get a list of all role certificates. Used when asserting roles. + * + * @param[out] roleCerts list of role certificates + * @return When ::OC_STACK_OK is returned, a list of certificates (roleCerts) + * that must be freed with FreeRoleCertChainList. roleCerts can still + * be NULL in this case, if no role certs are installed. On error, an + * error value is returned and roleCerts is NULL. + */ +OCStackResult GetAllRoleCerts(RoleCertChain_t** roleCerts); + /** * Used by mbedTLS to retrieve own certificate chain * diff --git a/resource/csdk/security/include/internal/rolesresource.h b/resource/csdk/security/include/internal/rolesresource.h index 9a7149adbc4c0d75a7e7392b1d740f26cd9bea34..252bd2cfd9c6c844a7839c9c3f1ba19e97b915bf 100644 --- a/resource/csdk/security/include/internal/rolesresource.h +++ b/resource/csdk/security/include/internal/rolesresource.h @@ -61,7 +61,7 @@ OCStackResult DeInitRolesResource(); * On success, caller must free the received array with OICFree when finished * @param[out] roleCount Variable to receive length of roles array. * - * @note If the endpoint is found but has not asserted any roles with certificates, + * @note If the endpoint is found but has not asserted any roles with certificates, * OC_STACK_OK will be returned, but NULL will be returned in roles and 0 in roleCount. * * @return OC_STACK_OK if list of roles is successfully populated; error otherwise. @@ -76,10 +76,24 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role * @param[in] size Size of cborPayload * @param[out] roleCertList Pointer to receive linked list of RoleCertChain_t objects * On success, caller must call FreeRoleCertChainList on *roleCertList when finished + * * @return OC_STACK_OK if payload is successfully converted; error code otherwise */ OCStackResult CBORPayloadToRoles(const uint8_t *cborPayload, size_t size, RoleCertChain_t **roleCertList); +/** + * This function converts a list of role certificates into a CBOR payload. + * Caller needs to call 'OICFree' on *cborPayload after use. + * + * @param[in] roles Linked list of RoleCertChain_t objects + * @param[out] cborPayload Pointer to receive the CBOR payload + * On success, caller must call OICFree on *cborPayload when finished + * @param[out] size Pointer to receive size of cborPayload + * + * @return OC_STACK_OK if payload is successfully converted; error code otherwise + */ +OCStackResult RolesToCBORPayload(const RoleCertChain_t *roles, uint8_t **cborPayload, size_t *cborSize); + /** * Free the memory used by a list of RoleCertChain_t objects created by CBORPayloadToRoles. * diff --git a/resource/csdk/security/include/internal/srmresourcestrings.h b/resource/csdk/security/include/internal/srmresourcestrings.h index 78a5167252fe4ad9042a6f7b5b498008c6cfd310..b1b59b2ba89379f1ba47913f040a93c0d4f4ad28 100644 --- a/resource/csdk/security/include/internal/srmresourcestrings.h +++ b/resource/csdk/security/include/internal/srmresourcestrings.h @@ -181,6 +181,7 @@ extern const char * OIC_JSON_EMPTY_STRING; extern const char * TRUST_CA; extern const char * PRIMARY_CERT; extern const char * PRIMARY_KEY; +extern const char * ROLE_CERT; // Certificates provided by manufacturer extern const char * MF_TRUST_CA; diff --git a/resource/csdk/security/include/occertutility.h b/resource/csdk/security/include/occertutility.h index 7962cd0c5837a0b9a604e54e863f1d19abb4526f..12f936d28efbbf18d08be27477960a1012a83e95 100644 --- a/resource/csdk/security/include/occertutility.h +++ b/resource/csdk/security/include/occertutility.h @@ -132,7 +132,7 @@ OCStackResult OCGenerateIdentityCertificate( size_t *certificateLen); /** - * Generate a certificate for a device's role. + * Generate a role certificate for a device. * * @param subjectUuid UUID for the device to use the certificate. * @param subjectPublicKey Subject's public key in PEM format @@ -176,7 +176,7 @@ OCStackResult OCGenerateRoleCertificate( * @param[in] csr The CSR containing the UUID as null-terminated PEM. * @param[out] uuid The UUID in the CSR * - * @return 0 on success, nonzero otherwise + * @return OC_STACK_OK if successful, error code otherwise */ OCStackResult OCGetUuidFromCSR(const char* csr, OicUuid_t* uuid); @@ -187,7 +187,7 @@ OCStackResult OCGetUuidFromCSR(const char* csr, OicUuid_t* uuid); * @param[out] publicKey The public key is output here as null-terminated PEM. * Callers must call OICFree when finished. * - * @return 0 on success, nonzero otherwise + * @return OC_STACK_OK if successful, error code otherwise */ OCStackResult OCGetPublicKeyFromCSR(const char* csr, char** publicKey); @@ -196,7 +196,7 @@ OCStackResult OCGetPublicKeyFromCSR(const char* csr, char** publicKey); * * @param[in] csr The CSR to check, as null-terminated PEM. * - * @returns 0 on success, nonzero otherwise + * @return OC_STACK_OK if successful, error code otherwise * * @remark Requires that ECDSA with SHA-256 be used for the signature. */ @@ -207,11 +207,11 @@ OCStackResult OCVerifyCSRSignature(const char* csr); * * @param[in] derCSR The CSR to convert, encoded as DER * @param[in] derCSRLen Then number of bytes in derCSR - * @param[out] pemCSR The output, PEM encoded, null-terminated CSR. Callers - * call OICFree when finished. + * @param[out] pemCSR The output, PEM encoded, null-terminated CSR. Callers + * call OICFree when finished. * - * @returns 0 on success, nonzero otherwise -*/ + * @return OC_STACK_OK if successful, error code otherwise + */ OCStackResult OCConvertDerCSRToPem(const char* derCSR, size_t derCSRLen, char** pemCSR); #ifdef __cplusplus diff --git a/resource/csdk/security/include/securevirtualresourcetypes.h b/resource/csdk/security/include/securevirtualresourcetypes.h index 8ebe4f4c13d7c598713a9ad97e6d303481d30703..55a02f1f2a47674cde2c79f00c4f8f00cd5c2eea 100644 --- a/resource/csdk/security/include/securevirtualresourcetypes.h +++ b/resource/csdk/security/include/securevirtualresourcetypes.h @@ -293,14 +293,15 @@ enum OIC_R_AMACL_TYPE, OIC_R_CRED_TYPE, OIC_R_CRL_TYPE, - OIC_R_CSR_TYPE, OIC_R_DOXM_TYPE, OIC_R_DPAIRING_TYPE, OIC_R_PCONF_TYPE, OIC_R_PSTAT_TYPE, - OIC_R_ROLES_TYPE, OIC_R_SACL_TYPE, OIC_R_SVC_TYPE, + OIC_R_CSR_TYPE, + OIC_R_ACL2_TYPE, + OIC_R_ROLES_TYPE, OIC_SEC_SVR_TYPE_COUNT, //define the value to number of SVR NOT_A_SVR_RESOURCE = 99 }; diff --git a/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h b/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h index 3a140c82ba42b245cd43abd632c8ae00883933c1..9e7c0111a8568558c0e18b178460bf9c8d090c0d 100644 --- a/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h +++ b/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h @@ -156,6 +156,31 @@ OCStackResult SRPSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainS */ OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_t *credId); +/** + * function to save own role certificate into Cred of SVR. + * + * @param[in] cert Certificate chain to be saved in Cred of SVR + * @param[out] credId CredId of saved trust certificate chain in Cred of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + * + * @note The certificate public key must be the same as public key in the identity + * certificate (installed by SRPSaveOwnCertChain). + */ +OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId); + +/** + * Assert all roles to a device. This POSTs all role certificates from the + * local cred resource to /oic/sec/roles. + * + * @param[in] ctx User context to be passed. + * @param[in] device The device to assert the roles to + * @param[in] resultCallback Callback that is called with the response from the device + * @return OC_STACK_OK in case of success and other value otherwise. + * + * @note If no role certificates are installed, this will fail. See GetAllRoleCerts in credresource.h + */ +OCStackResult SRPAssertRoles(void *ctx, const OCProvisionDev_t *device, OCProvisionResultCB resultCallback); + /** * function to register callback, for getting notification for TrustCertChain change. * @@ -204,8 +229,8 @@ OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selec * @param[in] keySize size of key * @param[in] pDev1 Pointer to PMOwnedDeviceInfo_t instance, respresenting resource to be provsioned. * @param[in] pDev2 Pointer to PMOwnedDeviceInfo_t instance, respresenting resource to be provsioned. - * @param[in] pemCert When provisioning a certificate (type is SIGNED_ASYMMETRIC_KEY), this is the - * certificate, encoded as PEM. + * @param[in] pemCert When provisioning a certificate (type is SIGNED_ASYMMETRIC_KEY), this is the + * certificate, encoded as PEM. * @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. diff --git a/resource/csdk/security/provisioning/include/ocprovisioningmanager.h b/resource/csdk/security/provisioning/include/ocprovisioningmanager.h index 790a55bed4446e774262044b65b226e24d26d8f5..1441bb6565d38f226fa370c806b6091a68f969c5 100644 --- a/resource/csdk/security/provisioning/include/ocprovisioningmanager.h +++ b/resource/csdk/security/provisioning/include/ocprovisioningmanager.h @@ -1,673 +1,685 @@ -/* ***************************************************************** - * - * 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 MULTIPLE_OWNER -#include "securevirtualresourcetypes.h" -#endif //MULTIPLE_OWNER - -#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. - * TODO: 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 OCInitPM(const char* dbPath); - -/** - * API to cleanup PDM in case of timeout. - * It will remove the PDM_DEVICE_INIT state devices from PDM. - * - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCPDMCleanupForTimeout(); - -/** - * The function is responsible for discovery of owned/unowned device is specified endpoint/deviceID. - * It will return the found device even though timeout is not exceeded. - * - * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * server before returning the device. - * @param[in] deviceID deviceID of target device. - * @param[out] ppFoundDevice OCProvisionDev_t of found device - * @return OTM_SUCCESS in case of success and other value otherwise. - */ -OCStackResult OCDiscoverSingleDevice(unsigned short timeout, const OicUuid_t* deviceID, - OCProvisionDev_t **ppFoundDevice); - -/** - * The function is responsible for discovery of owned/unowned device is specified endpoint/MAC - * address. - * It will return the found device even though timeout is not exceeded. - * - * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * server before returning the device. - * @param[in] deviceID deviceID of target device. - * @param[in] hostAddress MAC address of target device. - * @param[in] connType ConnectivityType for discovery. - * @param[out] ppFoundDevice OCProvisionDev_t of found device. - * @return OTM_SUCCESS in case of success and other value otherwise. - */ -OCStackResult OCDiscoverSingleDeviceInUnicast(unsigned short timeout, const OicUuid_t* deviceID, - const char* hostAddress, OCConnectivityType connType, - OCProvisionDev_t **ppFoundDevice); - -/** - * 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] waittime Timeout in seconds, value till which function will listen to responses from - * server 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 set a allow status of OxM - * - * @param[in] oxm Owership transfer method (ref. OicSecOxm_t) - * @param[in] allowStatus allow status (true = allow, false = not allow) - * - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus); - -#ifdef MULTIPLE_OWNER -/** - * API to perfrom multiple ownership transfer for MOT enabled 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 OCDoMultipleOwnershipTransfer(void* ctx, - OCProvisionDev_t *targetDevices, - OCProvisionResultCB resultCallback); -#endif //MULTIPLE_OWNER - -/** - * API to register for particular OxM. - * - * @param[in] oxm transfer method. - * @param[in] callbackData 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 - * server 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); - -#ifdef MULTIPLE_OWNER -/** - * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID. - * The function will return when security information for device with deviceID has been obtained or the - * timeout has been exceeded. - * - * @param[in] timeoutSeconds Maximum time, in seconds, this function will listen for responses from - * servers before returning. - * @param[in] deviceID deviceID of target device. - * @param[out] ppFoundDevice OCProvisionDev_t of discovered device. Caller should use - * OCDeleteDiscoveredDevices to delete the device. - * @return OC_STACK_OK in case of success and other values otherwise. - */ -OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds, - const OicUuid_t *deviceID, - OCProvisionDev_t **ppFoundDevice); - -/** - * The function is responsible for discovery of MOT enabled device is current subnet. - * - * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * server before returning the list of devices. - * @param[out] ppList List of MOT enabled devices. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCProvisionDev_t **ppList); - -/** - * The function is responsible for discovery of Multiple Owned device is current subnet. - * - * @param[in] timeout Timeout in seconds, value till which function will listen to responses from - * server before returning the list of devices. - * @param[out] ppList List of Multiple Owned devices. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList); - -/** - * The function is responsible for determining if the caller is a subowner of the specified device. - * - * @param[in] device MOT enabled device that contains a list of subowners. - * @param[out] isSubowner Bool indicating whether the caller is a subowner of device. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner); -#endif //MULTIPLE_OWNER - -/** - * API to provision credentials between two devices and ACLs for the devices who act as a server. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] type Type of credentials to be provisioned to the device. +/* ***************************************************************** + * + * 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 MULTIPLE_OWNER +#include "securevirtualresourcetypes.h" +#endif //MULTIPLE_OWNER + +#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. + * TODO: 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 OCInitPM(const char* dbPath); + +/** + * API to cleanup PDM in case of timeout. + * It will remove the PDM_DEVICE_INIT state devices from PDM. + * + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCPDMCleanupForTimeout(); + +/** + * The function is responsible for discovery of owned/unowned device is specified endpoint/deviceID. + * It will return the found device even though timeout is not exceeded. + * + * @param[in] timeout Timeout in seconds, value till which function will listen to responses from + * server before returning the device. + * @param[in] deviceID deviceID of target device. + * @param[out] ppFoundDevice OCProvisionDev_t of found device + * @return OTM_SUCCESS in case of success and other value otherwise. + */ +OCStackResult OCDiscoverSingleDevice(unsigned short timeout, const OicUuid_t* deviceID, + OCProvisionDev_t **ppFoundDevice); + +/** + * The function is responsible for discovery of owned/unowned device is specified endpoint/MAC + * address. + * It will return the found device even though timeout is not exceeded. + * + * @param[in] timeout Timeout in seconds, value till which function will listen to responses from + * server before returning the device. + * @param[in] deviceID deviceID of target device. + * @param[in] hostAddress MAC address of target device. + * @param[in] connType ConnectivityType for discovery. + * @param[out] ppFoundDevice OCProvisionDev_t of found device. + * @return OTM_SUCCESS in case of success and other value otherwise. + */ +OCStackResult OCDiscoverSingleDeviceInUnicast(unsigned short timeout, const OicUuid_t* deviceID, + const char* hostAddress, OCConnectivityType connType, + OCProvisionDev_t **ppFoundDevice); + +/** + * 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] waittime Timeout in seconds, value till which function will listen to responses from + * server 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 set a allow status of OxM + * + * @param[in] oxm Owership transfer method (ref. OicSecOxm_t) + * @param[in] allowStatus allow status (true = allow, false = not allow) + * + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus); + +#ifdef MULTIPLE_OWNER +/** + * API to perfrom multiple ownership transfer for MOT enabled 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 OCDoMultipleOwnershipTransfer(void* ctx, + OCProvisionDev_t *targetDevices, + OCProvisionResultCB resultCallback); +#endif //MULTIPLE_OWNER + +/** + * API to register for particular OxM. + * + * @param[in] oxm transfer method. + * @param[in] callbackData 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 + * server 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); + +#ifdef MULTIPLE_OWNER +/** + * The function is responsible for the discovery of an MOT-enabled device with the specified deviceID. + * The function will return when security information for device with deviceID has been obtained or the + * timeout has been exceeded. + * + * @param[in] timeoutSeconds Maximum time, in seconds, this function will listen for responses from + * servers before returning. + * @param[in] deviceID deviceID of target device. + * @param[out] ppFoundDevice OCProvisionDev_t of discovered device. Caller should use + * OCDeleteDiscoveredDevices to delete the device. + * @return OC_STACK_OK in case of success and other values otherwise. + */ +OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds, + const OicUuid_t *deviceID, + OCProvisionDev_t **ppFoundDevice); + +/** + * The function is responsible for discovery of MOT enabled device is current subnet. + * + * @param[in] timeout Timeout in seconds, value till which function will listen to responses from + * server before returning the list of devices. + * @param[out] ppList List of MOT enabled devices. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCProvisionDev_t **ppList); + +/** + * The function is responsible for discovery of Multiple Owned device is current subnet. + * + * @param[in] timeout Timeout in seconds, value till which function will listen to responses from + * server before returning the list of devices. + * @param[out] ppList List of Multiple Owned devices. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList); + +/** + * The function is responsible for determining if the caller is a subowner of the specified device. + * + * @param[in] device MOT enabled device that contains a list of subowners. + * @param[out] isSubowner Bool indicating whether the caller is a subowner of device. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCIsSubownerOfDevice(OCProvisionDev_t *device, bool *isSubowner); +#endif //MULTIPLE_OWNER + +/** + * API to provision credentials between two devices and ACLs for the devices who act as a server. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] type Type of credentials to be provisioned to the device. * @param[in] keySize size of key - * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned. - * @param[in] pDev1Acl 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] pDev2Acl 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 version 1 ACL information to device. - * - * @param[in] ctx Application context returned in the 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 send version 2 ACL information to device. - * - * @param[in] ctx Application context returned in the 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. - */ + * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned. + * @param[in] pDev1Acl 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] pDev2Acl 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 version 1 ACL information to device. + * + * @param[in] ctx Application context returned in the 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 send version 2 ACL information to device. + * + * @param[in] ctx Application context returned in the 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 OCProvisionACL2(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl, - OCProvisionResultCB resultCallback); - -/** - * function to save ACL which has several ACE into Acl of SVR. - * - * @param acl ACL to be saved in Acl of SVR. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCSaveACL(const OicSecAcl_t* acl); - -/** - * this function requests CRED information to resource. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @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 OCGetCredResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCProvisionResultCB resultCallback); - -/** - * this function requests version 1 ACL information to resource. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @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 OCGetACLResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCProvisionResultCB resultCallback); - -/** - * this function requests version 2 ACL information to resource. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @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 OCGetACL2Resource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCProvisionResultCB resultCallback); - -/** - * This function requests the device provide its Certificate Signing Request (CSR). - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @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 OCGetCSRResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCGetCSRResultCB resultCallback); - -/** - * This function requests the device provide its roles resource, listing the role certificates - * it has for the local requestor. - * - * @param[in] ctx Application context that is returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @param[in] resultCallback callback provided by the API user. Callback will be called when provisioning - * request receives a response from the resource server. - * @return OC_STACK_OK in case of success, and error value otherwise. - */ -OCStackResult OCGetRolesResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCGetRolesResultCB resultCallback); - -/** - * This function requests the device delete a particular role certificate by credId. - * - * @param[in] ctx Application context that is returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @param[in] resultCallback callback provided by the API user. Callback will be called when request receives - * a response from the resource server. - * @param[in] credId credId to request be deleted. If 0, delete all role certificates for this peer. - * - * @return OC_STACK_OK in case of success, and error value otherwise. - */ -OCStackResult OCDeleteRoleCertificateByCredId(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, - OCProvisionResultCB resultCallback, uint32_t credId); - -/** - * this function sends Direct-Pairing Configuration to a device. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] selectedDeviceInfo Selected target device. - * @param[in] pconf PCONF pointer. - * @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 OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf, - OCProvisionResultCB resultCallback); - -/** - * API to provision credential to devices. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] type Type of credentials to be provisioned to the device. + OCProvisionResultCB resultCallback); + +/** + * function to save ACL which has several ACE into Acl of SVR. + * + * @param acl ACL to be saved in Acl of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCSaveACL(const OicSecAcl_t* acl); + +/** + * this function requests CRED information to resource. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @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 OCGetCredResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCProvisionResultCB resultCallback); + +/** + * this function requests version 1 ACL information to resource. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @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 OCGetACLResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCProvisionResultCB resultCallback); + +/** + * this function requests version 2 ACL information to resource. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @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 OCGetACL2Resource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCProvisionResultCB resultCallback); + +/** + * This function requests the device provide its Certificate Signing Request (CSR). + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @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 OCGetCSRResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCGetCSRResultCB resultCallback); + +/** + * This function requests the device provide its roles resource, listing the role certificates + * it has for the local requestor. + * + * @param[in] ctx Application context that is returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @param[in] resultCallback callback provided by the API user. Callback will be called when provisioning + * request receives a response from the resource server. + * @return OC_STACK_OK in case of success, and error value otherwise. + */ +OCStackResult OCGetRolesResource(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCGetRolesResultCB resultCallback); + +/** + * This function requests the device delete a particular role certificate by credId. + * + * @param[in] ctx Application context that is returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @param[in] resultCallback callback provided by the API user. Callback will be called when request receives + * a response from the resource server. + * @param[in] credId credId to request be deleted. If 0, delete all role certificates for this peer. + * + * @return OC_STACK_OK in case of success, and error value otherwise. + */ +OCStackResult OCDeleteRoleCertificateByCredId(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, + OCProvisionResultCB resultCallback, uint32_t credId); + +/** + * this function sends Direct-Pairing Configuration to a device. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] selectedDeviceInfo Selected target device. + * @param[in] pconf PCONF pointer. + * @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 OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf, + OCProvisionResultCB resultCallback); + +/** + * API to provision credential to devices. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] type Type of credentials to be provisioned to the device. * @param[in] keySize size of key - * @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 provision a certificate to a device. - * - * @param[in] ctx Application context returned in result callback. - * @param[in] pDev Pointer to OCProvisionDev_t instance, respresenting the device to be provsioned. - * @param[in] pemCert Certificate to provision, encoded as PEM - * @param[in] resultCallback callback provided by API user, callback will be called when - * provisioning request receives a response from first resource server. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCProvisionCertificate(void *ctx, - const OCProvisionDev_t *pDev, - const char* pemCert, - OCProvisionResultCB resultCallback); - -#ifdef MULTIPLE_OWNER -/** - * API to provision preconfigured PIN to device(NOT LIST). - * If device does not support the Preconfigured PIN OxM, - * OCProvisionPreconfigPin API will update the device's Doxm - * and then try preconfigured PIN provisioning once again. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] targetDeviceInfo Selected target device. - * @param[in] preconfigPin string of preconfigured PIN. - * @param[in] preconfigPinLen string length of 'preconfigPin'. - * @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 OCProvisionPreconfigPin(void *ctx, - OCProvisionDev_t *targetDeviceInfo, - const char *preconfigPin, - size_t preconfigPinLen, - OCProvisionResultCB resultCallback); - -/** - * API to add preconfigured PIN to local SVR DB. - * - * @param[in] targetDeviceInfo Selected target device. - * @param[in] preconfigPin Preconfig PIN which is used while multiple owner authentication - * @param[in] preconfigPinLen Byte length of preconfigPin - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCAddPreconfigPin(const OCProvisionDev_t *targetDeviceInfo, - const char *preconfigPin, - size_t preconfigPinLen); - -/** - * API to update 'doxm.mom' to resource server. - * - * @param[in] targetDeviceInfo Selected target device. - * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom) - * @param[in] resultCallback callback provided by API user, callback will be called when - * POST 'mom' request recieves a response from resource server. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCChangeMOTMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo, - const OicSecMomType_t momType, OCProvisionResultCB resultCallback); - -/** - * API to update 'doxm.oxmsel' to resource server. - * - * @param[in] targetDeviceInfo Selected target device. - * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.doxmtype) - * @param[in] resultCallback callback provided by API user, callback will be called when - * POST 'oxmsel' request recieves a response from resource server. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo, - const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback); -#endif //MULTIPLE_OWNER - -/** - * Function to unlink devices. - * This function will remove the credential & relasionship between the two devices. - * - * @param[in] ctx Application context would be returned in result callback - * @param[in] pTargetDev1 fitst device information to be unlinked. - * @param[in] pTargetDev2 second device information to be unlinked. - * @param[in] resultCallback callback provided by API user, callback will be called when - * device unlink is finished. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCUnlinkDevices(void* ctx, - const OCProvisionDev_t* pTargetDev1, - const OCProvisionDev_t* pTargetDev2, - OCProvisionResultCB resultCallback); - -/** - * Function for device revocation - * This function will remove credential of target device from all devices in subnet. - * - * @param[in] ctx Application context would be returned in result callback - * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) - * @param[in] pTargetDev Device information to be revoked. - * @param[in] resultCallback callback provided by API user, callback will be called when - * credential revocation is finished. - * @return OC_STACK_OK in case of success and other value otherwise. - * if OC_STACK_OK is returned, the caller of this API should wait for callback. - * OC_STACK_CONTINUE means operation is success but no need to wait for callback. - */ -OCStackResult OCRemoveDevice(void* ctx, - unsigned short waitTimeForOwnedDeviceDiscovery, - const OCProvisionDev_t* pTargetDev, - OCProvisionResultCB resultCallback); - -/** - * Function to device revocation - * This function will remove credential of target device from all devices in subnet. - * - * @param[in] ctx Application context would be returned in result callback - * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) - * @param[in] pTargetUuid Device information to be revoked. - * @param[in] resultCallback callback provided by API user, callback will be called when - * credential revocation is finished. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCRemoveDeviceWithUuid(void* ctx, - unsigned short waitTimeForOwnedDeviceDiscovery, - const OicUuid_t* pTargetUuid, - OCProvisionResultCB resultCallback); - -/** - * Function to reset the target device. - * This function will remove credential and ACL of target device from all devices in subnet. - * - * @param[in] ctx Application context would be returned in result callback - * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) - * @param[in] pTargetDev Device information to be revoked. - * @param[in] resultCallback callback provided by API user, callback will be called when - * credential revocation is finished. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery, - const OCProvisionDev_t* pTargetDev, - OCProvisionResultCB resultCallback); - -/** - * This function resets SVR DB to its factory setting. - * - *@return OC_STACK_OK in case of successful reset and other value otherwise. - */ -OCStackResult OCResetSVRDB(void); - -/** - * This function configures SVR DB as self-ownership. - * - *@return OC_STACK_OK in case of successful configue and other value otherwise. - */ -OCStackResult OCConfigSelfOwnership(void); - -/** - * API to get status of all the devices in current subnet. The status include endpoint information - * and doxm information which can be extracted duing owned and unowned discovery. Along with this - * information. The API will provide information about devices' status - * Device can have following states - * - ON/OFF: Device is switched on or off. - * - * NOTE: Caller need to call OCDeleteDiscoveredDevices to delete memory allocated by this API for out - * variables pOwnedDevList and pUnownedDevList. - * - * @param[in] waittime Wait time for the API. The wait time will be divided by 2, and half of wait time - * will be used for unowned discovery and remaining half for owned discovery. So the wait time should be - * equal to or more than 2. - * @param[out] pOwnedDevList list of owned devices. - * @param[out] pUnownedDevList list of unowned devices. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime, - OCProvisionDev_t** pOwnedDevList, - OCProvisionDev_t** pUnownedDevList); -/** - * This method is used to get linked devices' IDs. - * - * @param[in] uuidOfDevice a target device's uuid. - * @param[out] uuidList information about the list of linked devices' uuids. - * @param[out] numOfDevices total number of linked devices. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice, - OCUuidList_t** uuidList, - size_t* numOfDevices); - -/** - * Remove locally stored credentials with the specified subject UUID. - * - * @param[in] subjectUuid The subject UUID of the credentials to remove - * + * @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 provision a certificate to a device. + * + * @param[in] ctx Application context returned in result callback. + * @param[in] pDev Pointer to OCProvisionDev_t instance, respresenting the device to be provsioned. + * @param[in] pemCert Certificate to provision, encoded as PEM + * @param[in] resultCallback callback provided by API user, callback will be called when + * provisioning request receives a response from first resource server. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCProvisionCertificate(void *ctx, + const OCProvisionDev_t *pDev, + const char* pemCert, + OCProvisionResultCB resultCallback); + +#ifdef MULTIPLE_OWNER +/** + * API to provision preconfigured PIN to device(NOT LIST). + * If device does not support the Preconfigured PIN OxM, + * OCProvisionPreconfigPin API will update the device's Doxm + * and then try preconfigured PIN provisioning once again. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] targetDeviceInfo Selected target device. + * @param[in] preconfigPin string of preconfigured PIN. + * @param[in] preconfigPinLen string length of 'preconfigPin'. + * @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 OCProvisionPreconfigPin(void *ctx, + OCProvisionDev_t *targetDeviceInfo, + const char *preconfigPin, + size_t preconfigPinLen, + OCProvisionResultCB resultCallback); + +/** + * API to add preconfigured PIN to local SVR DB. + * + * @param[in] targetDeviceInfo Selected target device. + * @param[in] preconfigPin Preconfig PIN which is used while multiple owner authentication + * @param[in] preconfigPinLen Byte length of preconfigPin + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCAddPreconfigPin(const OCProvisionDev_t *targetDeviceInfo, + const char *preconfigPin, + size_t preconfigPinLen); + +/** + * API to update 'doxm.mom' to resource server. + * + * @param[in] targetDeviceInfo Selected target device. + * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom) + * @param[in] resultCallback callback provided by API user, callback will be called when + * POST 'mom' request recieves a response from resource server. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCChangeMOTMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo, + const OicSecMomType_t momType, OCProvisionResultCB resultCallback); + +/** + * API to update 'doxm.oxmsel' to resource server. + * + * @param[in] targetDeviceInfo Selected target device. + * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.doxmtype) + * @param[in] resultCallback callback provided by API user, callback will be called when + * POST 'oxmsel' request recieves a response from resource server. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo, + const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback); +#endif //MULTIPLE_OWNER + +/** + * Function to unlink devices. + * This function will remove the credential & relasionship between the two devices. + * + * @param[in] ctx Application context would be returned in result callback + * @param[in] pTargetDev1 fitst device information to be unlinked. + * @param[in] pTargetDev2 second device information to be unlinked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * device unlink is finished. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCUnlinkDevices(void* ctx, + const OCProvisionDev_t* pTargetDev1, + const OCProvisionDev_t* pTargetDev2, + OCProvisionResultCB resultCallback); + +/** + * Function for device revocation + * This function will remove credential of target device from all devices in subnet. + * + * @param[in] ctx Application context would be returned in result callback + * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) + * @param[in] pTargetDev Device information to be revoked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * credential revocation is finished. + * @return OC_STACK_OK in case of success and other value otherwise. + * if OC_STACK_OK is returned, the caller of this API should wait for callback. + * OC_STACK_CONTINUE means operation is success but no need to wait for callback. + */ +OCStackResult OCRemoveDevice(void* ctx, + unsigned short waitTimeForOwnedDeviceDiscovery, + const OCProvisionDev_t* pTargetDev, + OCProvisionResultCB resultCallback); + +/** + * Function to device revocation + * This function will remove credential of target device from all devices in subnet. + * + * @param[in] ctx Application context would be returned in result callback + * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) + * @param[in] pTargetUuid Device information to be revoked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * credential revocation is finished. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCRemoveDeviceWithUuid(void* ctx, + unsigned short waitTimeForOwnedDeviceDiscovery, + const OicUuid_t* pTargetUuid, + OCProvisionResultCB resultCallback); + +/** + * Function to reset the target device. + * This function will remove credential and ACL of target device from all devices in subnet. + * + * @param[in] ctx Application context would be returned in result callback + * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds) + * @param[in] pTargetDev Device information to be revoked. + * @param[in] resultCallback callback provided by API user, callback will be called when + * credential revocation is finished. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery, + const OCProvisionDev_t* pTargetDev, + OCProvisionResultCB resultCallback); + +/** + * This function resets SVR DB to its factory setting. + * + *@return OC_STACK_OK in case of successful reset and other value otherwise. + */ +OCStackResult OCResetSVRDB(void); + +/** + * This function configures SVR DB as self-ownership. + * + *@return OC_STACK_OK in case of successful configue and other value otherwise. + */ +OCStackResult OCConfigSelfOwnership(void); + +/** + * API to get status of all the devices in current subnet. The status include endpoint information + * and doxm information which can be extracted duing owned and unowned discovery. Along with this + * information. The API will provide information about devices' status + * Device can have following states + * - ON/OFF: Device is switched on or off. + * + * NOTE: Caller need to call OCDeleteDiscoveredDevices to delete memory allocated by this API for out + * variables pOwnedDevList and pUnownedDevList. + * + * @param[in] waittime Wait time for the API. The wait time will be divided by 2, and half of wait time + * will be used for unowned discovery and remaining half for owned discovery. So the wait time should be + * equal to or more than 2. + * @param[out] pOwnedDevList list of owned devices. + * @param[out] pUnownedDevList list of unowned devices. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime, + OCProvisionDev_t** pOwnedDevList, + OCProvisionDev_t** pUnownedDevList); +/** + * This method is used to get linked devices' IDs. + * + * @param[in] uuidOfDevice a target device's uuid. + * @param[out] uuidList information about the list of linked devices' uuids. + * @param[out] numOfDevices total number of linked devices. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice, + OCUuidList_t** uuidList, + size_t* numOfDevices); + +/** + * Remove locally stored credentials with the specified subject UUID. + * + * @param[in] subjectUuid The subject UUID of the credentials to remove + * * @return OC_STACK_RESOURCE_DELETED if credentials were removed, or - * OC_STACK_ERROR if no credentials were removed. - */ -OCStackResult OCRemoveCredential(const OicUuid_t* subjectUuid); - -/** - * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API. - * - * @param[in] pList Pointer to OCProvisionDev_t which should be deleted. - */ -void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList); - -/** - * API to delete memory allocated to OicUuid_t list. - * - * @param[in] pList Pointer to OicUuid_t list which should be deleted. - */ -void OCDeleteUuidList(OCUuidList_t* pList); - -/** - * This function deletes ACL data. - * - * @param pAcl Pointer to OicSecAcl_t structure. - */ -void OCDeleteACLList(OicSecAcl_t* pAcl); - -/** - * This function deletes PDACL data. - * - * @param pPdAcl Pointer to OicSecPdAcl_t structure. - */ -void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl); - -#if defined(__WITH_DTLS__) || defined(__WITH_TLS__) -/** - * this function sends CRL information to resource. - * - * @param[in] ctx Application context returned in the 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); - -/** - * function to provision Trust certificate chain to devices. - * - * @param[in] ctx Application context returned in the result callback. - * @param[in] type Type of credentials to be provisioned to the device. - * @param[in] credId CredId of trust certificate chain to be provisioned to the device. - * @param[in] selectedDeviceInfo 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 OCProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId, - const OCProvisionDev_t *selectedDeviceInfo, - OCProvisionResultCB resultCallback); -/** - * function to save Trust certificate chain into Cred of SVR. - * - * @param[in] trustCertChain Trust certificate chain to be saved in Cred of SVR. - * @param[in] chainSize Size of trust certificate chain to be saved in Cred of SVR - * @param[in] encodingType Encoding type of trust certificate chain to be saved in Cred of SVR - * @param[out] credId CredId of saved trust certificate chain in Cred of SVR. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainSize, - OicEncodingType_t encodingType, uint16_t *credId); - -/** - * Function to save an identity certificate chain into Cred of SVR. - * - * @param[in] cert Certificate chain to be saved in Cred of SVR, PEM encoded, null terminated - * @param[in] key private key corresponding to the certificate, PEM encoded, null terminated - * @param[out] credId CredId of saved certificate chain in Cred of SVR. - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCSaveOwnCertChain(const char* cert, const char* key, uint16_t *credId); - -/** - * function to register callback, for getting notification for TrustCertChain change. - * - * @param[in] TrustCertChainChangeCB notifier callback function - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCRegisterTrustCertChainNotifier(void *cb, TrustCertChainChangeCB CB); - -/** - * function to de-register TrustCertChain notification callback. - */ -void OCRemoveTrustCertChainNotifier(void); - -/** - * Function to read Trust certificate chain from SVR. - * Caller must free when done using the returned trust certificate - * @param[in] credId CredId of trust certificate chain in SVR. - * @param[out] trustCertChain Trust certificate chain. - * @param[out] chainSize Size of trust certificate chain - * @return OC_STACK_OK in case of success and other value otherwise. - */ -OCStackResult OCReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain, - size_t *chainSize); - -/** - * Function to select appropriate security provisioning method. - * - * @param[in] supportedMethods Array of supported methods - * @param[in] numberOfMethods number of supported methods - * @param[out] selectedMethod Selected methods - * @param[in] ownerType type of owner device (SUPER_OWNER or SUB_OWNER) - * @return OC_STACK_OK on success - */ -OCStackResult OCSelectOwnershipTransferMethod(const OicSecOxm_t *supportedMethods, - size_t numberOfMethods, OicSecOxm_t *selectedMethod, OwnerType_t ownerType); - -#endif // __WITH_DTLS__ || __WITH_TLS__ - - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* OCPROVISIONINGMANAGER_H_ */ + * OC_STACK_ERROR if no credentials were removed. + */ +OCStackResult OCRemoveCredential(const OicUuid_t* subjectUuid); + +/** + * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API. + * + * @param[in] pList Pointer to OCProvisionDev_t which should be deleted. + */ +void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList); + +/** + * API to delete memory allocated to OicUuid_t list. + * + * @param[in] pList Pointer to OicUuid_t list which should be deleted. + */ +void OCDeleteUuidList(OCUuidList_t* pList); + +/** + * This function deletes ACL data. + * + * @param pAcl Pointer to OicSecAcl_t structure. + */ +void OCDeleteACLList(OicSecAcl_t* pAcl); + +/** + * This function deletes PDACL data. + * + * @param pPdAcl Pointer to OicSecPdAcl_t structure. + */ +void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl); + +#if defined(__WITH_DTLS__) || defined(__WITH_TLS__) +/** + * this function sends CRL information to resource. + * + * @param[in] ctx Application context returned in the 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); + +/** + * function to provision Trust certificate chain to devices. + * + * @param[in] ctx Application context returned in the result callback. + * @param[in] type Type of credentials to be provisioned to the device. + * @param[in] credId CredId of trust certificate chain to be provisioned to the device. + * @param[in] selectedDeviceInfo 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 OCProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint16_t credId, + const OCProvisionDev_t *selectedDeviceInfo, + OCProvisionResultCB resultCallback); +/** + * function to save Trust certificate chain into Cred of SVR. + * + * @param[in] trustCertChain Trust certificate chain to be saved in Cred of SVR. + * @param[in] chainSize Size of trust certificate chain to be saved in Cred of SVR + * @param[in] encodingType Encoding type of trust certificate chain to be saved in Cred of SVR + * @param[out] credId CredId of saved trust certificate chain in Cred of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCSaveTrustCertChain(const uint8_t *trustCertChain, size_t chainSize, + OicEncodingType_t encodingType, uint16_t *credId); + +/** + * Function to save an identity certificate chain into Cred of SVR. + * + * @param[in] cert Certificate chain to be saved in Cred of SVR, PEM encoded, null terminated + * @param[in] key private key corresponding to the certificate, PEM encoded, null terminated + * @param[out] credId CredId of saved certificate chain in Cred of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCSaveOwnCertChain(const char* cert, const char* key, uint16_t *credId); + +/** + * Function to save own role certificate into Cred of SVR. + * + * @param[in] cert Certificate chain to be saved in Cred of SVR, PEM encoded, null terminated + * @param[out] credId CredId of saved trust certificate chain in Cred of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + * + * @note The certificate public key must be the same as public key in the identity + * certificate (installed by OCSaveOwnCertChain). + */ +OCStackResult OCSaveOwnRoleCert(const char* cert, uint16_t *credId); + +/** + * function to register callback, for getting notification for TrustCertChain change. + * + * @param[in] TrustCertChainChangeCB notifier callback function + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCRegisterTrustCertChainNotifier(void *cb, TrustCertChainChangeCB CB); + +/** + * function to de-register TrustCertChain notification callback. + */ +void OCRemoveTrustCertChainNotifier(void); + +/** + * Function to read Trust certificate chain from SVR. + * Caller must free when done using the returned trust certificate + * @param[in] credId CredId of trust certificate chain in SVR. + * @param[out] trustCertChain Trust certificate chain. + * @param[out] chainSize Size of trust certificate chain + * @return OC_STACK_OK in case of success and other value otherwise. + */ +OCStackResult OCReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain, + size_t *chainSize); + +/** + * Function to select appropriate security provisioning method. + * + * @param[in] supportedMethods Array of supported methods + * @param[in] numberOfMethods number of supported methods + * @param[out] selectedMethod Selected methods + * @param[in] ownerType type of owner device (SUPER_OWNER or SUB_OWNER) + * @return OC_STACK_OK on success + */ +OCStackResult OCSelectOwnershipTransferMethod(const OicSecOxm_t *supportedMethods, + size_t numberOfMethods, OicSecOxm_t *selectedMethod, OwnerType_t ownerType); + +#endif // __WITH_DTLS__ || __WITH_TLS__ + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* OCPROVISIONINGMANAGER_H_ */ diff --git a/resource/csdk/security/provisioning/sample/autoprovisioningclient.c b/resource/csdk/security/provisioning/sample/autoprovisioningclient.c index 783d54233fec6757e0b338962a8f23d5ff636bde..c05411ec906ea45ec69aa9e058748229750932ad 100644 --- a/resource/csdk/security/provisioning/sample/autoprovisioningclient.c +++ b/resource/csdk/security/provisioning/sample/autoprovisioningclient.c @@ -50,6 +50,9 @@ #include "occertutility.h" #include "pmutility.h" +#include "secureresourceprovider.h" /* @todo: For SRPAssertRoles. Remove once IOT-1952 is resolved. */ + + #ifdef _MSC_VER #include @@ -64,7 +67,7 @@ extern "C" #define DISCOVERY_TIMEOUT 3 // 3 sec #define CALLBACK_TIMEOUT 60 // 1 min -#define TAG "provisioningclient" +#define TAG "autoprovisioningclient" static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat"; // '_' for separaing from the same constant variable in |srmresourcestrings.c| @@ -72,6 +75,12 @@ static const char* PRVN_DB_FILE_NAME = "oic_autoprvn_mng.db"; static const char* TEST_CERT_NOT_BEFORE = "20170101000000"; // Not before field for certificates, in format YYYYMMDDhhmmss static const char* TEST_CERT_NOT_AFTER = "20270101000000"; // + ten years +static const char* TEST_CERT_ROLE1 = "IoTivity-test-role1"; +static const char* TEST_CERT_ROLE2 = "IoTivity-test-role2"; +static const char* TEST_CERT_AUTHORITY = "IoTivity-test-OBT-authority-name"; + +static OicUuid_t WILDCARD_SUBJECT_ID = { "*" }; +static size_t WILDCARD_SUBJECT_ID_LEN = 1; // |g_ctx| means provision manager application context and // the following, includes |un/own_list|, could be variables, which |g_ctx| has, @@ -85,6 +94,7 @@ static int g_own_cnt; static int g_unown_cnt; static char* g_csr; /* Certificate signing request from device */ static OicUuid_t g_uuidDev1; +static char* g_idPublicKey = NULL; static volatile bool g_doneCB; /* Set to true by the callback to indicate it completed. */ static bool g_successCB; /* Set to true by the callback to indicate success. */ @@ -103,28 +113,28 @@ static int waitCallbackRet(void); * Test CA key and certificate created with * iotivity/resource/csdk/security/scripts/test_cert_generation.sh */ -static const char* g_caCertPem = "-----BEGIN CERTIFICATE-----\n" -"MIIBfjCCASSgAwIBAgIJAPQXoGTceaW5MAoGCCqGSM49BAMCMBkxFzAVBgNVBAoM\n" -"DklvVGl2aXR5VGVzdENBMB4XDTE3MDMxNTAwNTExOVoXDTMwMTEyMjAwNTExOVow\n" -"GTEXMBUGA1UECgwOSW9UaXZpdHlUZXN0Q0EwWTATBgcqhkjOPQIBBggqhkjOPQMB\n" -"BwNCAARvYPdt+LjqASlHoc2zrjo3hHGjZsI31c+bg9AwINW5TuRZsE03w/Ejotza\n" -"y4VDLImMlDhGP+K/f6OmKD3FNHhKo1UwUzAhBgNVHSUEGjAYBgorBgEEAYLefAEG\n" -"BgorBgEEAYLefAEHMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNw+hm69Rxb5\n" -"UpclERf5r85g1nwmMAoGCCqGSM49BAMCA0gAMEUCIQDbvNLA3ZkwEzuoH6XUR6JS\n" -"UzZTVgsDgnJcOqtqOg0qEAIgUJR2g8XlMxqiuXP7JdwALdtnvCQTlJQbuD1gu+Jy\n" -"AdQ=\n" +static const char* g_caCertPem = "-----BEGIN CERTIFICATE-----\n" +"MIIBfjCCASSgAwIBAgIJAPQXoGTceaW5MAoGCCqGSM49BAMCMBkxFzAVBgNVBAoM\n" +"DklvVGl2aXR5VGVzdENBMB4XDTE3MDMxNTAwNTExOVoXDTMwMTEyMjAwNTExOVow\n" +"GTEXMBUGA1UECgwOSW9UaXZpdHlUZXN0Q0EwWTATBgcqhkjOPQIBBggqhkjOPQMB\n" +"BwNCAARvYPdt+LjqASlHoc2zrjo3hHGjZsI31c+bg9AwINW5TuRZsE03w/Ejotza\n" +"y4VDLImMlDhGP+K/f6OmKD3FNHhKo1UwUzAhBgNVHSUEGjAYBgorBgEEAYLefAEG\n" +"BgorBgEEAYLefAEHMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNw+hm69Rxb5\n" +"UpclERf5r85g1nwmMAoGCCqGSM49BAMCA0gAMEUCIQDbvNLA3ZkwEzuoH6XUR6JS\n" +"UzZTVgsDgnJcOqtqOg0qEAIgUJR2g8XlMxqiuXP7JdwALdtnvCQTlJQbuD1gu+Jy\n" +"AdQ=\n" "-----END CERTIFICATE-----\n"; -static const char* g_caKeyPem = "-----BEGIN EC PRIVATE KEY-----\n" -"MHcCAQEEILx9VOHDrMYuan6SXN4CQIHHXNq6SjzanaDFDgIaOaXloAoGCCqGSM49\n" -"AwEHoUQDQgAEb2D3bfi46gEpR6HNs646N4Rxo2bCN9XPm4PQMCDVuU7kWbBNN8Px\n" -"I6Lc2suFQyyJjJQ4Rj/iv3+jpig9xTR4Sg==\n" +static const char* g_caKeyPem = "-----BEGIN EC PRIVATE KEY-----\n" +"MHcCAQEEILx9VOHDrMYuan6SXN4CQIHHXNq6SjzanaDFDgIaOaXloAoGCCqGSM49\n" +"AwEHoUQDQgAEb2D3bfi46gEpR6HNs646N4Rxo2bCN9XPm4PQMCDVuU7kWbBNN8Px\n" +"I6Lc2suFQyyJjJQ4Rj/iv3+jpig9xTR4Sg==\n" "-----END EC PRIVATE KEY-----\n"; -/* At a few places in this file, warning 4028 is incorrectly produced, disable it for the whole file. */ -#ifdef _MSC_VER -#pragma warning( disable : 4028) +/* At a few places in this file, warning 4028 is incorrectly produced, disable it for the whole file. */ +#ifdef _MSC_VER +#pragma warning( disable : 4028) #endif // callback function(s) for provisioning client using C-level provisioning API @@ -274,6 +284,22 @@ static void provisionAclCB(void* ctx, size_t nOfRes, OCProvisionResult_t* arr, b g_doneCB = true; } +static void assertRolesCB(void* ctx, size_t nOfRes, OCProvisionResult_t* arr, bool hasError) +{ + if (!hasError) + { + OIC_LOG_V(INFO, TAG, "Asserting roles SUCCEEDED - ctx: %s", (char*)ctx); + g_successCB = true; + } + else + { + OIC_LOG_V(ERROR, TAG, "Asserting roles FAILED - ctx: %s", (char*)ctx); + printResultList((const OCProvisionResult_t*)arr, nOfRes); + g_successCB = false; + } + g_doneCB = true; +} + // function(s) for provisioning client using C-level provisioning API static int initProvisionClient(void) { @@ -647,11 +673,13 @@ static int provisionCert(int dev_num, char* cert) } /* - * Create an identity certificate for a device, based on the information in its CSR. - * Assumes the csr has already been validated wtih OCVerifyCSRSignature. + * Create a role or identity certificate for a device, based on the information in its CSR. + * Assumes the CSR has already been validated wtih OCVerifyCSRSignature. + * If role is not NULL, a role certificate is created, otherwise an identity certificate + * is created. */ -static int createIdentityCertFromCSR(const char* caKeyPem, const char* caCertPem, char* csr, - char** deviceCert) +static int createCertFromCSR(const char* caKeyPem, const char* caCertPem, char* csr, + const char* role, const char* authority, char** deviceCert) { char* publicKey = NULL; char* serial = NULL; @@ -682,20 +710,37 @@ static int createIdentityCertFromCSR(const char* caKeyPem, const char* caCertPem } size_t deviceCertLen; - res = OCGenerateIdentityCertificate( - &uuid, - publicKey, - caCertPem, - caKeyPem, - serial, - TEST_CERT_NOT_BEFORE, - TEST_CERT_NOT_AFTER, - deviceCert, - &deviceCertLen); - + if (role != NULL) + { + res = OCGenerateRoleCertificate( + &uuid, + publicKey, + caCertPem, + caKeyPem, + serial, + TEST_CERT_NOT_BEFORE, + TEST_CERT_NOT_AFTER, + role, + authority, + deviceCert, + &deviceCertLen); + } + else + { + res = OCGenerateIdentityCertificate( + &uuid, + publicKey, + caCertPem, + caKeyPem, + serial, + TEST_CERT_NOT_BEFORE, + TEST_CERT_NOT_AFTER, + deviceCert, + &deviceCertLen); + } if (res != OC_STACK_OK) { - OIC_LOG_V(ERROR, TAG, "OCGenerateIdentityCertificate failed, error: %d", res); + OIC_LOG_V(ERROR, TAG, "Failed generating certificate, error: %d", res); goto exit; } @@ -712,7 +757,6 @@ static int setupOwnCert(OicUuid_t* inputUuid) uint16_t caCredId; char* serial = NULL; size_t serialLen = 0; - char* idPublicKey = NULL; size_t idPublicKeyLen = 0; char* idKey = NULL; size_t idKeyLen = 0; @@ -721,7 +765,7 @@ static int setupOwnCert(OicUuid_t* inputUuid) OIC_LOG_V(DEBUG, TAG, "In %s", __func__); - /* Set our own trust anchor so that we trust certs we've issued. */ + /* Set our own trust anchor so that we trust certs we've issued. */ OCStackResult res = OCSaveTrustCertChain((const uint8_t*)g_caCertPem, strlen(g_caCertPem)+1, OIC_ENCODING_PEM, &caCredId); if (OC_STACK_OK != res) { @@ -730,7 +774,7 @@ static int setupOwnCert(OicUuid_t* inputUuid) } /* Create identity certificate for use by the CA. */ - res = OCGenerateKeyPair(&idPublicKey, &idPublicKeyLen, &idKey, &idKeyLen); + res = OCGenerateKeyPair(&g_idPublicKey, &idPublicKeyLen, &idKey, &idKeyLen); if (res != OC_STACK_OK) { OIC_LOG_V(ERROR, TAG, "OCGenerateKeyPair failed, error: %d", res); @@ -763,7 +807,7 @@ static int setupOwnCert(OicUuid_t* inputUuid) res = OCGenerateIdentityCertificate( uuidForCert, - idPublicKey, + g_idPublicKey, g_caCertPem, g_caKeyPem, serial, @@ -787,7 +831,6 @@ static int setupOwnCert(OicUuid_t* inputUuid) exit: OICFree(serial); - OICFree(idPublicKey); if (idKey != NULL) { OICClearMemory(idKey, idKeyLen); @@ -800,8 +843,89 @@ exit: return (res == OC_STACK_OK) ? 0 : -1; } -// Caller must call OCDeleteACLList(newAcl) -static int createLedAcl(OicSecAcl_t** newAcl) +static int setupOwnRoleCert(OicUuid_t* inputUuid, const char* role, const char* authority) +{ + OCUUIdentity deviceId = { 0 }; + char* serial = NULL; + size_t serialLen = 0; + char* roleCert = NULL; + size_t roleCertLen = 0; + + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + + if (g_idPublicKey == NULL) + { + OIC_LOG_V(ERROR, TAG, "%s failed because own public key is NULL, has setupOwnCert been called?", __func__); + return -1; + } + + /* Create role certificate. */ + OCStackResult res = OCGenerateRandomSerialNumber(&serial, &serialLen); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "OCGenerateRandomSerialNumber failed, error: %d", res); + goto exit; + } + + OicUuid_t* uuidForCert = inputUuid; + OicUuid_t uuid = { 0 }; + if (inputUuid == NULL) + { + res = OCGetDeviceId(&deviceId); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res); + goto exit; + } + memcpy(uuid.id, deviceId.id, sizeof(uuid.id)); + uuidForCert = &uuid; + } + + OIC_LOG(DEBUG, TAG, "Creating own role cert with UUID:"); + printUuid(uuidForCert); + + res = OCGenerateRoleCertificate( + uuidForCert, + g_idPublicKey, + g_caCertPem, + g_caKeyPem, + serial, + TEST_CERT_NOT_BEFORE, + TEST_CERT_NOT_AFTER, + role, + authority, + &roleCert, + &roleCertLen); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "Failed to create role cert, error: %d", res); + goto exit; + } + + uint16_t roleCertCredId = 0; + res = OCSaveOwnRoleCert(roleCert, &roleCertCredId); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "Failed to save role cert, error: %d", res); + goto exit; + } + +exit: + OICFree(serial); + OICFree(roleCert); + + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + + return (res == OC_STACK_OK) ? 0 : -1; +} + +/* + * Create an ACL for the /a/led resource. + * Caller must call OCDeleteACLList(newAcl). + * The role and authority parameters are optional. If role is not NULL, a + * role-based ACL will be created. Otherwise a subject-based ACL is created. + */ +static int createLedAcl(OicSecAcl_t** newAcl, const char* role, const char* authority) { int ret = -1; OCUUIdentity ownUuid = { 0 }; @@ -828,20 +952,122 @@ static int createLedAcl(OicSecAcl_t** newAcl) } LL_APPEND(acl->aces, ace); - /* Set uuid to our own */ - OCStackResult res = OCGetDeviceId(&ownUuid); - if (res != OC_STACK_OK) + if (role != NULL) /* Create a role-based ACL */ + { + ace->subjectType = OicSecAceRoleSubject; + assert(strlen(role) + 1 < ROLEID_LENGTH); + memcpy(ace->subjectRole.id, role, strlen(role) + 1); + + if (authority != NULL) + { + assert(strlen(authority) + 1 < ROLEAUTHORITY_LENGTH); + memcpy(ace->subjectRole.authority, role, strlen(authority) + 1); + } + OIC_LOG_V(DEBUG, TAG, "Creating ACE with role id = %s, authority = %s:", ace->subjectRole.id, ace->subjectRole.authority); + } + else /* Create a subject based ACL */ + { + /* Set uuid to our own */ + OCStackResult res = OCGetDeviceId(&ownUuid); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res); + goto exit; + } + ace->subjectType = OicSecAceUuidSubject; + memcpy(ace->subjectuuid.id, ownUuid.id, sizeof(ace->subjectuuid.id)); + + OicUuid_t uuid = { 0 }; + memcpy(uuid.id, ownUuid.id, sizeof(uuid.id)); + OIC_LOG(DEBUG, TAG, "Creating ACE with UUID:"); + printUuid(&uuid); + } + + /* Add a resource (e.g. '/a/led') to the ACE */ + rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t)); + if (!rsrc) { - OIC_LOG_V(ERROR, TAG, "Failed to get own UUID, error: %d", res); + OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc)", __func__); goto exit; } + LL_APPEND(ace->resources, rsrc); + rsrc->href = OICStrdup(resource); + + /* Set resource type, e.g., 'core.led' */ + rsrc->typeLen = 1; + rsrc->types = (char**)OICCalloc(rsrc->typeLen, sizeof(char*)); + if (!rsrc->types) + { + OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc->types)", __func__); + goto exit; + } + rsrc->types[0] = OICStrdup(resource_type); + + /* Set interface, e.g., 'oic.if.baseline' */ + rsrc->interfaceLen = 1; + rsrc->interfaces = (char**)OICCalloc(rsrc->interfaceLen, sizeof(char*)); + if (!rsrc->interfaces) + { + OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (rsrc->interfaces)", __func__); + goto exit; + } + rsrc->interfaces[0] = OICStrdup(resource_interface); + + if (!rsrc->href || !rsrc->types[0] || !rsrc->interfaces[0]) + { + OIC_LOG_V(ERROR, TAG, "%s: OICStrdup failed", __func__); + goto exit; + } + + /* Set permission for the ACE */ + ace->permission = perms; + + ret = 0; /* success */ + *newAcl = acl; + +exit: + + if (ret != 0) + { + *newAcl = NULL; + OCDeleteACLList(acl); + } + + return ret; +} + +/* Once IOT-1950 is resolved, this can be removed. */ +static int createRolesAcl(OicSecAcl_t** newAcl) +{ + int ret = -1; + OicSecAcl_t* acl = NULL; + OicSecAce_t* ace = NULL; + OicSecRsrc_t* rsrc = NULL; + const char* resource = "/oic/sec/roles"; + const char* resource_type = "oic.sec.role"; + const char* resource_interface = "oic.if.baseline"; + uint16_t perms = PERMISSION_FULL_CONTROL; + + /* Create an ACL with one ACE */ + acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t)); + if (!acl) + { + OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (acl)", __func__); + goto exit; + } + ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t)); + if (!ace) + { + OIC_LOG_V(ERROR, TAG, "%s: OICCalloc failed (ace)", __func__); + goto exit; + } + LL_APPEND(acl->aces, ace); + + /* Set uuid to "*", everyone */ ace->subjectType = OicSecAceUuidSubject; - memcpy(ace->subjectuuid.id, ownUuid.id, sizeof(ace->subjectuuid.id)); + memcpy(&ace->subjectuuid, &WILDCARD_SUBJECT_ID, WILDCARD_SUBJECT_ID_LEN); - OicUuid_t uuid = { 0 }; - memcpy(uuid.id, ownUuid.id, sizeof(uuid.id)); - OIC_LOG(DEBUG, TAG, "Creating ACE with UUID:"); - printUuid(&uuid); + OIC_LOG(DEBUG, TAG, "Creating ACE with wildcard UUID"); /* Add a resource (e.g. '/a/led') to the ACE */ rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t)); @@ -931,7 +1157,9 @@ exit: } -/* Fucntion to work around IOT-1927. The ocrandom.h include is only required for the workaround. */ +/* Function to work around IOT-1927. The ocrandom.h include is only required for the workaround. + * @todo: when IOT-1927 is resolved remove this function + */ #include "ocrandom.h" int workAroundBug() { @@ -980,7 +1208,7 @@ static int testCertUse(int dev_num) return -1; } - int ret = createIdentityCertFromCSR(g_caKeyPem, g_caCertPem, csr, &deviceCert); + int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &deviceCert); if (ret != 0) { OIC_LOG_V(ERROR, TAG, "Failed to create identity certificate", __func__); @@ -1002,7 +1230,7 @@ static int testCertUse(int dev_num) goto exit; } - ret = createLedAcl(&acl); + ret = createLedAcl(&acl, NULL, NULL); if (ret != 0) { OIC_LOG_V(ERROR, TAG, "%s failed to create ACL", __func__); @@ -1029,7 +1257,7 @@ static int testCertUse(int dev_num) /* * Work around bug IOT-1927 - * When that bug is resolved, remove this call and the function workAroundBug + * @todo: When that bug is resolved, remove this call and the function workAroundBug */ if (workAroundBug() != 0) { @@ -1050,7 +1278,7 @@ static int testCertUse(int dev_num) ret = doGetRequest(uri, dev_num); if (ret == 0) { - OIC_LOG_V(ERROR, TAG, "%s Get request to %s suceeded, but should have failed", __func__, uri); + OIC_LOG_V(ERROR, TAG, "%s Get request to %s succeeded, but should have failed", __func__, uri); goto exit; } @@ -1070,7 +1298,6 @@ static int testCertUse(int dev_num) goto exit; } - /* Try a get request, expect success */ ret = doGetRequest(uri, dev_num); if (ret != 0) @@ -1088,8 +1315,265 @@ exit: return ret; } +static int testRoleProvisioning(int dev_num) +{ + char* csr = NULL; + char* idCert = NULL; + char* roleCert = NULL; + + // Make sure we own at least one device to provision + if (!g_own_list || g_own_cnt == 0) + { + OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first"); + return -1; // Error, we should have registered unowned devices already + } + + /* Provision the device with the CA root, and issue it a role and identity cert. */ + if (provisionTrustAnchor(dev_num) != 0) + { + return -1; + } + + if (getCsr(dev_num, &csr) != 0) + { + return -1; + } + + int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &idCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to create identity certificate", __func__); + goto exit; + } + + ret = provisionCert(dev_num, idCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to provision id certificate", __func__); + goto exit; + } + + /* The first role cert will have no authority field (it's optional) */ + ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, TEST_CERT_ROLE1, NULL, &roleCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to create role certificate", __func__); + goto exit; + } + + ret = provisionCert(dev_num, roleCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to provision role certificate", __func__); + goto exit; + } + OICFreeAndSetToNull(&roleCert); + + /* The second will have the authority field set */ + ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, TEST_CERT_ROLE2, TEST_CERT_AUTHORITY, &roleCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to create role certificate", __func__); + goto exit; + } + + ret = provisionCert(dev_num, roleCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to provision role certificate", __func__); + goto exit; + } + +exit: + + OICFree(csr); + OICFree(idCert); + OICFree(roleCert); + + return ret; +} + +static int testRoleAssertionAndUse(int dev_num) +{ + char* csr = NULL; + char* idCert = NULL; + char* roleCert = NULL; + const char* uri = "/a/led"; + OicSecAcl_t* acl = NULL; + + // Make sure we own at least one device to provision + if (!g_own_list || g_own_cnt == 0) + { + OIC_LOG(ERROR, TAG, "Owned device list empty, must discover unowned devices first"); + return -1; // Error, we should have registered unowned devices already + } + + /* Provision the device with the CA root, and issue it an identity cert. */ + if (provisionTrustAnchor(dev_num) != 0) + { + return -1; + } + + if (getCsr(dev_num, &csr) != 0) + { + return -1; + } + + int ret = createCertFromCSR(g_caKeyPem, g_caCertPem, csr, NULL, NULL, &idCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to create identity certificate", __func__); + goto exit; + } + + ret = provisionCert(dev_num, idCert); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "Failed to provision id certificate", __func__); + goto exit; + } + + /* Create and provision a role-based ACL allowing ROLE1 to access '/a/led'. */ + ret = createLedAcl(&acl, TEST_CERT_ROLE1, NULL); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to create led ACL", __func__); + goto exit; + } + + ret = provisionAcl(dev_num, acl); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to provision led ACL", __func__); + goto exit; + } + + /* Create and provision an ACL to allow anyone access to the roles resource. Since all actions + * on the roles resource first requires authentication by public key, this is effectively "any + * authenticated" access. + * @todo: This should be done by default and not be necessary here (IOT-1950). + */ + OCDeleteACLList(acl); + acl = NULL; + ret = createRolesAcl(&acl); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to create roles ACL", __func__); + goto exit; + } + + ret = provisionAcl(dev_num, acl); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to provision roles ACL", __func__); + goto exit; + } + + /* Provision ourselves an identity and role cert. + * For the identity cert we use a random UUID, since the server has an ACE granting our UUID + * access to everything (as owner). We don't want to remove this ACE because it would lock + * us out. Using another UUID makes us appear as another device on the network. + */ + OicUuid_t notOurUuid; + (void) OCGenerateUuid(notOurUuid.id); + ret = setupOwnCert(¬OurUuid); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__); + goto exit; + } + + ret = setupOwnRoleCert(NULL, TEST_CERT_ROLE1, NULL); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s Failed to self-provision a key/certificate", __func__); + goto exit; + } + + /* Remove the owner credential so that we don't use it when asserting role certs. */ + OCStackResult res = OCRemoveCredential(&g_uuidDev1); + if (res != OC_STACK_RESOURCE_DELETED) + { + OIC_LOG_V(ERROR, TAG, "%s failed to remove owner credential for subject UUID: ", __func__); + OIC_LOG_BUFFER(DEBUG, TAG, g_uuidDev1.id, UUID_LENGTH); + ret = -1; + goto exit; + } + + /* + * Work around bug IOT-1927 + * @todo: When that bug is resolved, remove this call and the function workAroundBug + */ + if (workAroundBug() != 0) + { + OIC_LOG_V(ERROR, TAG, "%s bug workaround failed: ", __func__); + ret = -1; + goto exit; + } + + /* Close all secure sessions*/ + if (closeAllSessions() != 0) + { + OIC_LOG_V(ERROR, TAG, "%s Failed to close sessions", __func__); + ret = -1; + goto exit; + } + + /* Try a GET request, expect failure, we haven't asserted our role cert yet. */ + ret = doGetRequest(uri, dev_num); + if (ret == 0) + { + OIC_LOG_V(ERROR, TAG, "%s Get request to %s succeeded, but should have failed", __func__, uri); + goto exit; + } + + /* Assert our role cert. (@todo: This should be done automatically, IOT-1952) */ + OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num); + if (!dev) + { + OIC_LOG(ERROR, TAG, "getDevInst: device instance empty"); + return -1; + } + + g_doneCB = false; + res = SRPAssertRoles(g_ctx, dev, &assertRolesCB); + if (res != OC_STACK_OK) + { + OIC_LOG_V(ERROR, TAG, "%s Failed assert roles", __func__); + ret = -1; + goto exit; + } + if (waitCallbackRet()) + { + OIC_LOG(ERROR, TAG, "SRPAssertRoles callback error"); + goto exit; + } + if (!g_successCB) + { + OIC_LOG_V(ERROR, TAG, "%s callback completed, but failed", __func__); + goto exit; + } + + /* Try a get request, expect success */ + ret = doGetRequest(uri, dev_num); + if (ret != 0) + { + OIC_LOG_V(ERROR, TAG, "%s Get request to %s failed, but should have succeeded", __func__, uri); + goto exit; + } + +exit: + OICFree(csr); + OICFree(idCert); + OICFree(roleCert); + OCDeleteACLList(acl); + + return ret; +} + /* Get a specific device from the provided device list. The devices in the list - * are numbered starting from 1. */ + * are numbered starting from 1. + */ static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num) { if (!dev_lst || 0 >= dev_num) @@ -1289,7 +1773,7 @@ int TestTrustAnchorProvisioning() if(initDiscoverRegisterAllDevices()) { - OIC_LOG_V(ERROR, TAG, "%s: Failed discover and provision devices", __func__); + OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__); goto exit; } @@ -1317,7 +1801,7 @@ int TestCSRResource() if(initDiscoverRegisterAllDevices()) { - OIC_LOG_V(ERROR, TAG, "%s: Failed discover and provision devices", __func__); + OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__); goto exit; } @@ -1345,7 +1829,7 @@ int TestCertUse() if (initDiscoverRegisterAllDevices()) { - OIC_LOG_V(ERROR, TAG, "%s: Failed discover and provision devices", __func__); + OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__); goto exit; } @@ -1365,6 +1849,62 @@ exit: return ret; } +int TestRoleProvisioning() +{ + int ret = -1; + + OIC_LOG_V(ERROR, TAG, "Running %s", __func__); + + if (initDiscoverRegisterAllDevices()) + { + OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__); + goto exit; + } + + /* There should be one owned device with number 1. */ + if (testRoleProvisioning(1)) + { + OIC_LOG(ERROR, TAG, "Failed to provision roles to device"); + goto exit; + } + + ret = 0; + +exit: + + shutdownProvisionClient(); + + return ret; +} + +int TestRoleAssertionAndUse() +{ + int ret = -1; + + OIC_LOG_V(ERROR, TAG, "Running %s", __func__); + + if (initDiscoverRegisterAllDevices()) + { + OIC_LOG_V(ERROR, TAG, "%s: Failed to discover and provision devices", __func__); + goto exit; + } + + /* There should be one owned device with number 1. */ + if (testRoleAssertionAndUse(1)) + { + OIC_LOG(ERROR, TAG, "Failed to assert and use roles"); + goto exit; + } + + ret = 0; + +exit: + + shutdownProvisionClient(); + + return ret; +} + // main function for provisioning client using C-level provisioning API int main(int argc, char** argv) { @@ -1383,6 +1923,10 @@ int main(int argc, char** argv) return TestCSRResource(); case 3: return TestCertUse(); + case 4: + return TestRoleProvisioning(); + case 5: + return TestRoleAssertionAndUse(); default: printf("%s: Invalid test number\n", argv[0]); return 1; diff --git a/resource/csdk/security/provisioning/sample/provisioningTest.py b/resource/csdk/security/provisioning/sample/provisioningTest.py index b9354960298df7b459237112bbb353c80291fbf4..93d428297daf2d121431830fcb97ee4142fcac8f 100644 --- a/resource/csdk/security/provisioning/sample/provisioningTest.py +++ b/resource/csdk/security/provisioning/sample/provisioningTest.py @@ -21,26 +21,29 @@ def cleanup(iotivity_base_path, exe_path): dat_file_src = os.path.join(iotivity_base_path, 'resource', 'csdk', 'security', 'provisioning', 'sample', 'oic_svr_db_server_justworks.dat' ) dat_file_dest = exe_path shutil.copy(dat_file_src, dat_file_dest) - - # Copy fresh oic_svr_db_client.dat - dat_file_src = os.path.join(iotivity_base_path, 'resource', 'examples', 'oic_svr_db_client.dat' ) - dat_file_dest = exe_path - shutil.copy(dat_file_src, dat_file_dest) - - #Delete provisioning DB file - db_file = os.path.join(exe_path, 'oic_autoprvn_mng.db') - if os.path.isfile(db_file): - os.unlink(db_file) - + + # Copy fresh oic_svr_db_client.dat + dat_file_src = os.path.join(iotivity_base_path, 'resource', 'examples', 'oic_svr_db_client.dat' ) + dat_file_dest = exe_path + shutil.copy(dat_file_src, dat_file_dest) + + #Delete provisioning DB file + db_file = os.path.join(exe_path, 'oic_autoprvn_mng.db') + if os.path.isfile(db_file): + os.unlink(db_file) + # Print the environment variables (useful for debugging) def print_environment(): - for key in os.environ.keys(): - print "%30s %s \n" % (key,os.environ[key]) + for key in os.environ.keys(): + print "%30s %s \n" % (key,os.environ[key]) print 'current PATH is %s' % sys.path ### main ### +# Number of unit tests in autoprovisioningclient +NUM_TESTS = 5 + usage = ''' Run end-to-end certificate tests between autoprovisioningclient and sampleserver_justworks Usage Notes @@ -58,14 +61,12 @@ parser = argparse.ArgumentParser( description=usage ) -parser.add_argument('--arch', nargs='?', choices = ['amd64', 'x86', 'arm'], help= 'Architecture, one of x86, amd64 or arm. Defaults to amd64', default='amd64') -parser.add_argument('--build', nargs='?', choices = ['debug', 'release'], help= 'Build type, one of debug or release. Defaults to debug', default='debug') +parser.add_argument('--arch', nargs='?', choices = ['amd64', 'x86', 'arm'], help= 'Architecture, one of x86, amd64 or arm. Defaults to amd64.', default='amd64') +parser.add_argument('--build', nargs='?', choices = ['debug', 'release'], help= 'Build type, one of debug or release. Defaults to debug.', default='debug') +parser.add_argument('--onetest', nargs='?', choices = ['1', '...', str(NUM_TESTS)], help= 'Run a single test, specified by number. By default all tests are run.') args = parser.parse_args() -# Number of unit tests in autoprovisioningclient -NUM_TESTS = 3 - iotivity_base_path = os.getcwd() os_name = platform.system() if os_name == 'Windows': @@ -85,36 +86,45 @@ os.chdir(exe_path) output_text = "" num_failures = 0 -for i in range(1, NUM_TESTS + 1): - print '\nRunning test %d...\n' % i - - # Clear state from previous test - cleanup(iotivity_base_path, exe_path) - - # Start the device/server with a non-blocking call - #note: Popen can take file descriptors to redirect the processes stdin, stdout, stderr - try: - server_process = subprocess.Popen('sampleserver_justworks') - except: - print 'Failed to start sampleserver_justworks', sys.exc_info()[0] - sys.exit(-1) - - # Run the auto provisioning client with the test number as argument, block until it returns - return_code = subprocess.call(["autoprovisioningclient", str(i)]) - - if return_code != 0: - num_failures += 1 - print "Test %d failed" % i - output_text += "Test %d failed\n" % i - else: - print "Test %d passed" % i - - - server_process.kill() + +test_range = range(1, NUM_TESTS + 1) #default to running all tests +if args.onetest: + try: + test_range = range(int(args.onetest), int(args.onetest) + 1) + except ValueError: + print 'invalid argument to --onetest' + sys.exit(-1) + +for i in test_range: + print '\nRunning test %d...\n' % i + + # Clear state from previous test + cleanup(iotivity_base_path, exe_path) + + # Start the device/server with a non-blocking call + #note: Popen can take file descriptors to redirect the processes stdin, stdout, stderr + try: + server_process = subprocess.Popen('sampleserver_justworks') + except: + print 'Failed to start sampleserver_justworks', sys.exc_info()[0] + sys.exit(-1) + + # Run the auto provisioning client with the test number as argument, block until it returns + return_code = subprocess.call(["autoprovisioningclient", str(i)]) + + if return_code != 0: + num_failures += 1 + print "Test %d failed" % i + output_text += "Test %d failed\n" % i + else: + print "Test %d passed" % i + + + server_process.kill() print "\n------------------------------------" -print " Test Results: %d of %d tests passed" % (NUM_TESTS - num_failures, NUM_TESTS) +print " Test Results: %d of %d tests passed" % (len(test_range) - num_failures, len(test_range)) print "------------------------------------" print output_text print '\n' diff --git a/resource/csdk/security/provisioning/src/ocprovisioningmanager.c b/resource/csdk/security/provisioning/src/ocprovisioningmanager.c index 9dad739c9e9f84c5d222d5146442590a07488f29..3269355329a947e890b4fddf51c3e34b8cee4f7f 100644 --- a/resource/csdk/security/provisioning/src/ocprovisioningmanager.c +++ b/resource/csdk/security/provisioning/src/ocprovisioningmanager.c @@ -179,7 +179,7 @@ OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t ** * The function will return when security information for device with deviceID has been obtained or the * timeout has been exceeded. * - * @param[in] timeoutSeconds Maximum time, in seconds, this function will listen for responses from + * @param[in] timeoutSeconds Maximum time, in seconds, this function will listen for responses from * servers before returning. * @param[in] deviceID deviceID of target device. * @param[out] ppFoundDevice OCProvisionDev_t of discovered device. Caller should use @@ -187,7 +187,7 @@ OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t ** * @return OC_STACK_OK in case of success and other values otherwise. */ OCStackResult OCDiscoverMultipleOwnerEnabledSingleDevice(unsigned short timeoutSeconds, - const OicUuid_t* deviceID, + const OicUuid_t* deviceID, OCProvisionDev_t **ppFoundDevice) { if ((NULL == ppFoundDevice) || (NULL != *ppFoundDevice) || (0 == timeoutSeconds) || (NULL == deviceID)) @@ -340,29 +340,49 @@ void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList) } /** - * this function sends ACL information to resource. + * This function sends ACL information to resource. * * @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. + * request receives 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) { - return SRPProvisionACL(ctx, selectedDeviceInfo, acl, OIC_SEC_ACL_V1, resultCallback); + /* + * Determine whether this is a version 1 or version 2 ACL. We can't just always use V2 here + * since we may be provisioning an IoTivity 1.2 device. + */ + + OicSecAclVersion_t aclVersion = OIC_SEC_ACL_V1; /* default to v1 */ + if (acl->aces != NULL) + { + /* If any of the aces have the role subject, the ACL is v2 */ + OicSecAce_t* ace = NULL; + LL_FOREACH(acl->aces, ace) + { + if (ace->subjectType == OicSecAceRoleSubject) + { + aclVersion = OIC_SEC_ACL_V2; + break; + } + } + } + + return SRPProvisionACL(ctx, selectedDeviceInfo, acl, aclVersion, resultCallback); } /** - * this function sends ACL information to resource. + * This function sends ACL information to resource. * * @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. + * request recieves a response from resource server. * @return OC_STACK_OK in case of success and other value otherwise. */ OCStackResult OCProvisionACL2(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl, @@ -412,7 +432,7 @@ OCStackResult OCGetACLResource(void* ctx, const OCProvisionDev_t *selectedDevice return SRPGetACLResource(ctx, selectedDeviceInfo, OIC_SEC_ACL_V1, resultCallback); } -OCStackResult OCGetACL2Resource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, +OCStackResult OCGetACL2Resource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OCProvisionResultCB resultCallback) { return SRPGetACLResource(ctx, selectedDeviceInfo, OIC_SEC_ACL_V2, resultCallback); @@ -1503,6 +1523,26 @@ OCStackResult OCSaveOwnCertChain(const char* cert, const char* key, uint16_t *cr return SRPSaveOwnCertChain(&ownCert, &ownKey, credId); } +/** + * Function to save own role certificate into Cred of SVR. + * + * @param[in] cert own role certificate to be saved in Cred of SVR. + * @param[out] credId CredId of saved trust certificate chain in Cred of SVR. + * @return OC_STACK_OK in case of success and other value otherwise. + * + * @note The certificate public key must be the same as public key in the identity + * certificate (installed by OCSaveOwnCertChain). + */ +OCStackResult OCSaveOwnRoleCert(const char* cert, uint16_t *credId) +{ + OicSecKey_t ownCert = { 0 }; + ownCert.data = (uint8_t*)cert; + ownCert.len = strlen(cert) + 1; + ownCert.encoding = OIC_ENCODING_PEM; + + return SRPSaveOwnRoleCert(&ownCert, credId); +} + /** * function to register notifier for Trustcertchain change. * diff --git a/resource/csdk/security/provisioning/src/secureresourceprovider.c b/resource/csdk/security/provisioning/src/secureresourceprovider.c index 3ffcea477d53ab58b767e6ecbceb1fe0020e5f04..1333caba64ae26d56888b0a8c39efa0fac97ec88 100644 --- a/resource/csdk/security/provisioning/src/secureresourceprovider.c +++ b/resource/csdk/security/provisioning/src/secureresourceprovider.c @@ -49,6 +49,7 @@ #include "utlist.h" #include "ocpayload.h" #include "srmutility.h" +#include "certhelpers.h" #ifdef __WITH_DTLS__ #include "crlresource.h" @@ -115,6 +116,15 @@ struct GetRolesData { size_t numOfResults; /**< Number of results in result array.**/ }; +typedef struct AssertRolesData AssertRolesData_t; +struct AssertRolesData { + void *ctx; /**< User-provided context **/ + const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/ + OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/ + OCProvisionResult_t *resArr; /**< Result array.**/ + size_t numOfResults; /**< Number of results in result array.**/ +}; + /** * Structure to carry PCONF provision API data to callback. */ @@ -322,7 +332,7 @@ static OCStackResult provisionCredentials(const OicSecCred_t *cred, OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); if (!secPayload) { - OIC_LOG(ERROR, TAG, "Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } secPayload->base.type = PAYLOAD_TYPE_SECURITY; @@ -460,7 +470,7 @@ static OCStackApplicationResult provisionCertCB(void *ctx, OCDoHandle UNUSED, return OC_STACK_DELETE_TRANSACTION; } -static OCStackApplicationResult provisionIdentityCertCB(void *ctx, OCDoHandle UNUSED, +static OCStackApplicationResult provisionCertificateCB(void *ctx, OCDoHandle UNUSED, OCClientResponse *clientResponse) { // Just call the callback provided to SRProvisionCredentials @@ -514,7 +524,7 @@ OCStackResult SRPProvisionTrustCertChain(void *ctx, OicSecCredType_t type, uint1 if(!secPayload) { DeleteCredList(trustCertChainCred); - OIC_LOG(ERROR, TAG, "Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } secPayload->base.type = PAYLOAD_TYPE_SECURITY; @@ -664,8 +674,11 @@ static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16 OIC_LOG_V(DEBUG, TAG, "IN %s", __func__); VERIFY_NOT_NULL_RETURN(TAG, cert, ERROR, OC_STACK_INVALID_PARAM); VERIFY_NOT_NULL_RETURN(TAG, cert->data, ERROR, OC_STACK_INVALID_PARAM); - VERIFY_NOT_NULL_RETURN(TAG, key, ERROR, OC_STACK_INVALID_PARAM); - VERIFY_NOT_NULL_RETURN(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM); + if (key != NULL) + { + /* Key is optional. */ + VERIFY_NOT_NULL_RETURN(TAG, key->data, ERROR, OC_STACK_INVALID_PARAM); + } VERIFY_NOT_NULL_RETURN(TAG, credId, ERROR, OC_STACK_INVALID_PARAM); VERIFY_NOT_NULL_RETURN(TAG, usage, ERROR, OC_STACK_INVALID_PARAM); @@ -679,7 +692,7 @@ static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16 res = GetDoxmDeviceID(&cred->subject); if (OC_STACK_OK != res) { - OIC_LOG(ERROR, TAG, "Cann't get the device id(GetDoxmDeviceID)"); + OIC_LOG(ERROR, TAG, "Can't get the device id(GetDoxmDeviceID)"); DeleteCredList(cred); return res; } @@ -697,12 +710,15 @@ static OCStackResult saveCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16 publicData->len = cert->len; publicData->encoding = cert->encoding; - OicSecKey_t *privateData = &cred->privateData; - privateData->data = (uint8_t *)OICCalloc(1, key->len); - VERIFY_NOT_NULL_RETURN(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY); - memcpy(privateData->data, key->data, key->len); - privateData->len = key->len; - privateData->encoding = key->encoding; + if (key != NULL) + { + OicSecKey_t *privateData = &cred->privateData; + privateData->data = (uint8_t *)OICCalloc(1, key->len); + VERIFY_NOT_NULL_RETURN(TAG, privateData->data, ERROR, OC_STACK_NO_MEMORY); + memcpy(privateData->data, key->data, key->len); + privateData->len = key->len; + privateData->encoding = key->encoding; + } res = AddCredential(cred); if(res != OC_STACK_OK) @@ -722,6 +738,155 @@ OCStackResult SRPSaveOwnCertChain(OicSecKey_t * cert, OicSecKey_t * key, uint16_ return saveCertChain(cert, key, credId, PRIMARY_CERT); } +OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId) +{ + return saveCertChain(cert, NULL, credId, ROLE_CERT); +} + +/** + * Callback handler of SRPAssertRoles. + * + * @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 SRPAssertRolesCB(void *ctx, OCDoHandle UNUSED, + OCClientResponse *clientResponse) +{ + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + OC_UNUSED(UNUSED); + VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION); + AssertRolesData_t *assertRolesData = (AssertRolesData_t*)ctx; + OCProvisionResultCB resultCallback = assertRolesData->resultCallback; + bool hasError = true; + + if (clientResponse && (OC_STACK_RESOURCE_CHANGED == clientResponse->result)) + { + hasError = false; + } + else + { + OIC_LOG_V(ERROR, TAG, "%s : NULL client response, or response indicating failure (%d)", __func__); + } + + ((OCProvisionResultCB)(resultCallback))(assertRolesData->ctx, assertRolesData->numOfResults, + assertRolesData->resArr, + hasError); + + OICFree(assertRolesData->resArr); + OICFree(assertRolesData); + + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + return OC_STACK_DELETE_TRANSACTION; +} + +OCStackResult SRPAssertRoles(void *ctx, const OCProvisionDev_t *device, OCProvisionResultCB resultCallback) +{ + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + + VERIFY_NOT_NULL_RETURN(TAG, device, ERROR, OC_STACK_INVALID_PARAM); + VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK); + + OC_UNUSED(device); + OC_UNUSED(ctx); + OC_UNUSED(resultCallback); + + /* 1. Retrieve all our stored role certificates */ + RoleCertChain_t *roles = NULL; + OCStackResult res = GetAllRoleCerts(&roles); + if (res != OC_STACK_OK) + { + OIC_LOG(ERROR, TAG, "Failed to retrieve role certs"); + return OC_STACK_ERROR; + } + if (roles == NULL) + { + OIC_LOG(ERROR, TAG, "Can't assert roles, no role certs installed"); + return OC_STACK_ERROR; + } + + /* 2. Encode them for transfer */ + OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); + if (!secPayload) + { + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); + FreeRoleCertChainList(roles); + return OC_STACK_NO_MEMORY; + } + secPayload->base.type = PAYLOAD_TYPE_SECURITY; + if(OC_STACK_OK != RolesToCBORPayload(roles, &secPayload->securityData, &secPayload->payloadSize)) + { + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "RolesToCBORPayload failed"); + FreeRoleCertChainList(roles); + return OC_STACK_NO_MEMORY; + } + OIC_LOG(DEBUG, TAG, "Created payload for asserting roles:"); + OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize); + FreeRoleCertChainList(roles); + + /* 3. Post roles to the roles resource on the server */ + char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0 }; + if (!PMGenerateQuery(true, + device->endpoint.addr, + device->securePort, + device->connType, + query, sizeof(query), OIC_RSRC_ROLES_URI)) + { + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query"); + return OC_STACK_ERROR; + } + OIC_LOG_V(DEBUG, TAG, "Query=%s", query); + + OCCallbackData cbData = { .context = NULL,.cb = NULL,.cd = NULL }; + cbData.cb = &SRPAssertRolesCB; + AssertRolesData_t *assertRolesData = (AssertRolesData_t *)OICCalloc(1, sizeof(AssertRolesData_t)); + if (assertRolesData == NULL) + { + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "Unable to allocate memory"); + return OC_STACK_NO_MEMORY; + } + assertRolesData->deviceInfo = device; + assertRolesData->resultCallback = resultCallback; + assertRolesData->numOfResults = 0; + assertRolesData->ctx = ctx; + + int noOfRiCalls = 1; + assertRolesData->resArr = (OCProvisionResult_t*)OICCalloc(noOfRiCalls, sizeof(OCProvisionResult_t)); + if (assertRolesData->resArr == NULL) + { + OICFree(assertRolesData); + OCPayloadDestroy((OCPayload *)secPayload); + OIC_LOG(ERROR, TAG, "Unable to allocate memory"); + return OC_STACK_NO_MEMORY; + } + cbData.context = (void *)assertRolesData; + cbData.cd = NULL; + OCMethod method = OC_REST_POST; + OCDoHandle handle = NULL; + + OIC_LOG(DEBUG, TAG, "Sending roles to server"); + OCStackResult ret = OCDoRequest(&handle, method, query, + &device->endpoint, (OCPayload*)secPayload, + device->connType, OC_HIGH_QOS, &cbData, NULL, 0); + if (ret != OC_STACK_OK) + { + OICFree(assertRolesData->resArr); + OICFree(assertRolesData); + OIC_LOG_V(ERROR, TAG, "%s OCDoRequest failed", __func__); + } + OCPayloadDestroy((OCPayload *)secPayload); + + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR); + + return ret; +} + #endif // __WITH_DTLS__ || __WITH_TLS__ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize, @@ -855,11 +1020,19 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k VERIFY_NOT_NULL_RETURN(TAG, cred, ERROR, OC_STACK_ERROR); cred->publicData.encoding = OIC_ENCODING_PEM; - cred->credUsage = OICStrdup(PRIMARY_CERT); - /* Create credential data (used by the response handler provisionIdentityCertCB and freed there) */ - CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t)); - if (NULL == credData) + if (OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL) == OC_STACK_OK) + { + cred->credUsage = OICStrdup(ROLE_CERT); + } + else + { + cred->credUsage = OICStrdup(PRIMARY_CERT); + } + + /* Create credential data (used by the response handler provisionCertificateCB and freed there) */ + CredentialData_t *credData = (CredentialData_t *)OICCalloc(1, sizeof(CredentialData_t)); + if ((NULL == credData) || (NULL == cred->credUsage)) { DeleteCredList(cred); OIC_LOG(ERROR, TAG, "Memory allocation problem"); @@ -874,8 +1047,8 @@ OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t k credData->resultCallback = resultCallback; credData->resArr = NULL; - /* Note: the callback of type OCClientResponseHandler, thin wrapper that calls resultCallback */ - OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionIdentityCertCB); + /* Note: the callback is of type OCClientResponseHandler, thin wrapper that calls resultCallback */ + OCStackResult res = provisionCredentials(cred, pDev1, credData, &provisionCertificateCB); if (res != OC_STACK_OK) { OICFree(credData); @@ -990,7 +1163,7 @@ OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceI OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); if(!secPayload) { - OIC_LOG(ERROR, TAG, "Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } secPayload->base.type = PAYLOAD_TYPE_SECURITY; @@ -1146,7 +1319,7 @@ OCStackResult SRPProvisionDirectPairing(void *ctx, const OCProvisionDev_t *selec OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload)); if(!secPayload) { - OIC_LOG(ERROR, TAG, "Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "Failed to allocate memory"); return OC_STACK_NO_MEMORY; } secPayload->base.type = PAYLOAD_TYPE_SECURITY; @@ -2074,7 +2247,7 @@ OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDi removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t)); if (!removeData) { - OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory"); res = OC_STACK_NO_MEMORY; goto error; } @@ -2091,7 +2264,7 @@ OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDi (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t)); if (!removeData->removeRes) { - OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to allocate memory"); res = OC_STACK_NO_MEMORY; goto error; } @@ -2216,7 +2389,7 @@ OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t)); if (!removeData) { - OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory"); res = OC_STACK_NO_MEMORY; goto error; } @@ -2233,7 +2406,7 @@ OCStackResult SRPRemoveDeviceWithoutDiscovery(void* ctx, const OCProvisionDev_t* (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t)); if (!removeData->removeRes) { - OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "SRPRemoveDeviceWithoutDiscovery : Failed to allocate memory"); res = OC_STACK_NO_MEMORY; goto error; } @@ -2362,7 +2535,7 @@ OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDisc removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t)); if (!removeData) { - OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to memory allocation"); + OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory"); res = OC_STACK_NO_MEMORY; goto error; } @@ -3006,7 +3179,7 @@ static void registerResultForGetRolesResourceCB(GetRolesData_t *getRolesData, /* Take ownership of the buffers from certificate and optData, rather than copy. */ currentEntry->chains[i].certificate = curr->certificate; currentEntry->chains[i].optData = curr->optData; - + curr->certificate.data = NULL; curr->certificate.len = 0; curr->optData.data = NULL; diff --git a/resource/csdk/security/src/aclresource.c b/resource/csdk/security/src/aclresource.c index 019e445c249d7927bfd335ebabd32f88bf391c77..c448bfba48ceb0458118e7fb3ca87c17624507f6 100644 --- a/resource/csdk/security/src/aclresource.c +++ b/resource/csdk/security/src/aclresource.c @@ -1877,7 +1877,18 @@ static bool IsSameACE(OicSecAce_t* ace1, OicSecAce_t* ace2) { if(ace1 && ace2) { - if(memcmp(ace1->subjectuuid.id, ace2->subjectuuid.id, sizeof(ace1->subjectuuid.id)) != 0) + if(ace1->subjectType != ace2->subjectType) + { + return false; + } + if(ace1->subjectType == OicSecAceUuidSubject && + memcmp(ace1->subjectuuid.id, ace2->subjectuuid.id, sizeof(ace1->subjectuuid.id)) != 0) + { + return false; + } + else if(ace1->subjectType == OicSecAceRoleSubject && + strcmp(ace1->subjectRole.id, ace2->subjectRole.id) != 0 && + strcmp(ace1->subjectRole.authority, ace2->subjectRole.authority) != 0) { return false; } @@ -1919,10 +1930,22 @@ static void printACE(const OicSecAce_t *ace) OIC_LOG_V(INFO, TAG, "ACE @ %p", ace); OIC_LOG_V(INFO, TAG, " permission = %#x", (uint32_t)ace->permission); - // Log the subjectuuid. - char uuidString[UUID_STRING_SIZE]; - bool convertedUUID = OCConvertUuidToString(ace->subjectuuid.id, uuidString); - OIC_LOG_V(INFO, TAG, " subjectuuid = %s", convertedUUID ? uuidString : "incorrect format"); + // Log the subject + if (ace->subjectType == OicSecAceUuidSubject) + { + char uuidString[UUID_STRING_SIZE]; + bool convertedUUID = OCConvertUuidToString(ace->subjectuuid.id, uuidString); + OIC_LOG_V(INFO, TAG, " subject UUID = %s", convertedUUID ? uuidString : "incorrect format"); + } + else if (ace->subjectType == OicSecAceRoleSubject) + { + OIC_LOG_V(DEBUG, TAG, " role id = %s", ace->subjectRole.id); + OIC_LOG_V(DEBUG, TAG, " authority = %s", ace->subjectRole.authority); + } + else + { + OIC_LOG(INFO, TAG, " subject = (subject of unknown type)"); + } // Log all resources this ACE applies to. OicSecRsrc_t *resource = NULL; @@ -2249,6 +2272,11 @@ static OCEntityHandlerResult HandleACLPostRequest(const OCEntityHandlerRequest * } } } + else + { + OIC_LOG(ERROR, TAG, "ACL post request with no payload."); + ehRet = OC_EH_ERROR; + } //Send response to request originator ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ? @@ -2725,7 +2753,7 @@ const OicSecAce_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAce_t ** // Find the next ACL corresponding to the 'subjectID' and return it. LL_FOREACH(begin, ace) { - if ((OicSecAceUuidSubject == ace->subjectType) && + if ((OicSecAceUuidSubject == ace->subjectType) && (0 == memcmp(&(ace->subjectuuid), subjectId, sizeof(OicUuid_t)))) { OIC_LOG(DEBUG, TAG, "GetACLResourceData: found matching ACE:"); diff --git a/resource/csdk/security/src/certhelpers.c b/resource/csdk/security/src/certhelpers.c index 12ab4bfe6fcb3656a4a2cd5d6646a0762520a57f..28011b70fb405795be8090c72d3ba00d8b3dab0c 100644 --- a/resource/csdk/security/src/certhelpers.c +++ b/resource/csdk/security/src/certhelpers.c @@ -321,8 +321,8 @@ OCStackResult OCInternalIsValidRoleCertificate(const uint8_t *buf, size_t bufLen valid = false; /* Check for at least one subjAltName with a role in it. */ - for (const mbedtls_x509_general_names *nameCur = &parsedCert.subject_alt_names; - NULL != nameCur; + for (const mbedtls_x509_general_names *nameCur = &parsedCert.subject_alt_names; + NULL != nameCur; nameCur = nameCur->next) { if (MBEDTLS_X509_GENERALNAME_DIRECTORYNAME == nameCur->general_name.name_type) @@ -444,7 +444,8 @@ OCStackResult OCInternalIsValidCertChain(const uint8_t *buf, size_t bufLen) static const mbedtls_x509_crt_profile s_certProfile = { MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256), /* MD algorithms */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), /* Allowed key type */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY) | /* Allowed key types */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA), MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1), /* EC curves */ 0 /* RSA minimum key length - not used because we only use EC key pairs */ }; @@ -489,7 +490,7 @@ OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificate, co goto exit; } - if (NULL != optData) + if ((NULL != optData) && (0 != optData->len)) { mbedRet = mbedtls_x509_crt_parse(&certChain, optData->data, optData->len); if (0 > mbedRet) @@ -541,20 +542,22 @@ OCStackResult OCInternalVerifyRoleCertificate(const OicSecKey_t *certificate, co dirName = dirName->next) { if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN) == dirName->oid.len) && - (0 == memcmp(MBEDTLS_OID_AT_CN, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN)))) + (0 == memcmp(MBEDTLS_OID_AT_CN, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN))) && + (rolesTmp[rolesTmpCount].id[0] == '\0')) { /* When checking validity above, we made sure the role ID and authority were not too * long to fit in an OicSecRole_t. Here we only assert, but don't check again in release code. - * id was also initialized as all zeroes, so string will automatically be null-terminated. + * id was also initialized as all zeroes, so the string will automatically be null-terminated. */ - assert(dirName->val.len < ROLEID_LENGTH); + assert(dirName->val.len < ROLEID_LENGTH); memcpy(rolesTmp[rolesTmpCount].id, dirName->val.p, dirName->val.len); advanceCount = true; } else if ((MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT) == dirName->oid.len) && - (0 == memcmp(MBEDTLS_OID_AT_ORG_UNIT, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT)))) + (0 == memcmp(MBEDTLS_OID_AT_ORG_UNIT, dirName->oid.p, MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_ORG_UNIT)))&& + (rolesTmp[rolesTmpCount].authority[0] == '\0')) { - assert(dirName->val.len < ROLEID_LENGTH); + assert(dirName->val.len < ROLEID_LENGTH); memcpy(rolesTmp[rolesTmpCount].authority, dirName->val.p, dirName->val.len); } diff --git a/resource/csdk/security/src/credresource.c b/resource/csdk/security/src/credresource.c index af2cdc72e34692d9a72adce694f59e8eaa0313da..3b665b999949ad1a82d0d5970fef690d91b9d5c6 100644 --- a/resource/csdk/security/src/credresource.c +++ b/resource/csdk/security/src/credresource.c @@ -324,7 +324,7 @@ size_t GetCredKeyDataSize(const OicSecCred_t* cred) #endif } } - OIC_LOG_V(DEBUG, TAG, "Cred Key Data Size : %zd\n", size); + OIC_LOG_V(DEBUG, TAG, "Cred Key Data Size : %u", (unsigned int) size); return size; } @@ -614,7 +614,7 @@ static void logCredMetadata() OIC_LOG_V(DEBUG, TAG, "privateData length: %d, encoding: %d", temp->privateData.len, temp->privateData.encoding); #if defined(__WITH_DTLS__) || defined(__WITH_TLS__) - OIC_LOG_V(DEBUG, TAG, "publicData length: %d, encoding: %d", temp->publicData.len, temp->publicData.encoding); + OIC_LOG_V(DEBUG, TAG, "publicData length: %d, encoding: %d", temp->publicData.len, temp->publicData.encoding); if (temp->credUsage) { OIC_LOG_V(DEBUG, TAG, "credUsage: %s", temp->credUsage); @@ -694,7 +694,7 @@ OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload } #endif //MULTIPLE_OWNER - if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType) + if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType) && cred->publicData.data) { mapSize++; @@ -753,7 +753,7 @@ OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload #if defined(__WITH_DTLS__) || defined(__WITH_TLS__) //PublicData -- Not Mandatory - if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType) + if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType) && cred->publicData.data) { cborEncoderResult = SerializeEncodingToCbor(&credMap, @@ -2853,7 +2853,7 @@ OCStackResult GetCredRownerId(OicUuid_t *rowneruuid) /* Caller must call OICFree on *der when finished. */ static int ConvertPemCertToDer(const char *pem, size_t pemLen, uint8_t** der, size_t* derLen) { - const char* pemHeader = "-----BEGIN CERTIFICATE-----"; /* no newlines allowed here */ + const char* pemHeader = "-----BEGIN CERTIFICATE-----"; /* no newlines allowed here */ const char* pemFooter = "-----END CERTIFICATE-----"; mbedtls_pem_context ctx; @@ -2892,7 +2892,7 @@ exit: /* Caller must call OICFree on *pem when finished. */ static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem) { - const char* pemHeader = "-----BEGIN CERTIFICATE-----\n"; + const char* pemHeader = "-----BEGIN CERTIFICATE-----\n"; const char* pemFooter = "-----END CERTIFICATE-----\n"; /* Get the length required for output */ @@ -2918,7 +2918,7 @@ static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem) } /* Try the conversion */ - ret = mbedtls_pem_write_buffer(pemHeader, + ret = mbedtls_pem_write_buffer(pemHeader, pemFooter, der, derLen, @@ -2943,7 +2943,7 @@ static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodin OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); return OC_STACK_INVALID_PARAM; } - + switch (desiredEncoding) { case OIC_ENCODING_PEM: @@ -3064,6 +3064,116 @@ OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage) return GetCaCert(crt, usage, OIC_ENCODING_PEM); } +static int cloneSecKey(OicSecKey_t * dst, OicSecKey_t * src) +{ + if ((src == NULL) || (dst == NULL)) + { + return -1; + } + + if (src->len > 0) + { + dst->data = OICCalloc(src->len, 1); + if (dst->data == NULL) + { + OIC_LOG_V(ERROR, TAG, "%s memory allocation failed", __func__); + return -1; + } + memcpy(dst->data, src->data, src->len); + } + else + { + dst->data = NULL; + } + + dst->len = src->len; + dst->encoding = src->encoding; + + return 0; +} + +static int cloneSecOpt(OicSecOpt_t * dst, OicSecOpt_t * src) +{ + if ((src == NULL) || (dst == NULL)) + { + return -1; + } + + if (src->len > 0) + { + dst->data = OICCalloc(src->len, 1); + if (dst == NULL) + { + OIC_LOG_V(ERROR, TAG, "%s memory allocation failed", __func__); + OICFree(dst); + return -1; + } + memcpy(dst->data, src->data, src->len); + } + else + { + dst->data = NULL; + } + + dst->len = src->len; + dst->encoding = src->encoding; + dst->revstat = src->revstat; + + return 0; +} + +/* Caller must call FreeRoleCertChainList on roleEntries when finished. */ +OCStackResult GetAllRoleCerts(RoleCertChain_t ** output) +{ + OIC_LOG_V(DEBUG, TAG, "In %s", __func__); + + *output = NULL; + + OicSecCred_t * temp = NULL; + LL_FOREACH(gCred, temp) + { + if ((SIGNED_ASYMMETRIC_KEY == temp->credType) && + (temp->credUsage != NULL) && + (0 == strcmp(temp->credUsage, ROLE_CERT))) + { + if (temp->publicData.data == NULL) + { + OIC_LOG_V(WARNING, TAG, "%s missing certificate data in role certificate", __func__); + continue; + } + + RoleCertChain_t * add = (RoleCertChain_t *) OICCalloc(1, sizeof(RoleCertChain_t)); + if (add == NULL) + { + OIC_LOG_V(ERROR, TAG, "%s Failed to allocate memory", __func__); + goto error; + } + LL_APPEND(*output, add); + add->credId = temp->credId; + if (cloneSecKey(&add->certificate, &temp->publicData) != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to copy certificate data", __func__); + goto error; + } + + if (cloneSecOpt(&add->optData, &temp->optionalData) != 0) + { + OIC_LOG_V(ERROR, TAG, "%s failed to copy optional data", __func__); + goto error; + } + } + } + + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + return OC_STACK_OK; + +error: + FreeRoleCertChainList(*output); + *output = NULL; + OIC_LOG_V(DEBUG, TAG, "Out %s", __func__); + return OC_STACK_ERROR; +} + void GetPemOwnCert(ByteArray_t * crt, const char * usage) { OIC_LOG_V(DEBUG, TAG, "In %s", __func__); @@ -3101,7 +3211,7 @@ void GetPemOwnCert(ByteArray_t * crt, const char * usage) mustAddNull = false; /* mbedTLS always NULL-terminates. */ pemLen = strlen((char *)pem) + 1; break; - + case OIC_ENCODING_PEM: case OIC_ENCODING_BASE64: pem = temp->publicData.data; @@ -3139,7 +3249,7 @@ void GetPemOwnCert(ByteArray_t * crt, const char * usage) /* If we're appending, subtract one from crt->len below so we overwrite the current terminating * NULL with the beginning of the new data. */ - if (0 < crt->len) + if (0 < crt->len) { assert(crt->data[crt->len - 1] == '\0'); memcpy(crt->data + crt->len - 1, pem, pemLen); @@ -3188,7 +3298,7 @@ void GetDerKey(ByteArray_t * key, const char * usage) key->len = 0; LL_FOREACH(gCred, temp) { - if ((SIGNED_ASYMMETRIC_KEY == temp->credType || ASYMMETRIC_KEY == temp->credType) && + if ((SIGNED_ASYMMETRIC_KEY == temp->credType || ASYMMETRIC_KEY == temp->credType) && temp->privateData.len > 0 && NULL != temp->credUsage && 0 == strcmp(temp->credUsage, usage)) @@ -3197,7 +3307,7 @@ void GetDerKey(ByteArray_t * key, const char * usage) if (temp->privateData.encoding == OIC_ENCODING_PEM) { /* Convert PEM to DER */ - const char* pemHeader = "-----BEGIN EC PRIVATE KEY-----"; /* no newlines allowed here */ + const char* pemHeader = "-----BEGIN EC PRIVATE KEY-----"; /* no newlines allowed here */ const char* pemFooter = "-----END EC PRIVATE KEY-----"; if (temp->privateData.data[temp->privateData.len - 1] != 0) diff --git a/resource/csdk/security/src/policyengine.c b/resource/csdk/security/src/policyengine.c index 8e959c30a7ca960d530ac5c56916060942fc70c9..8f44f1103c1bc8704bdeb19f3fc59b6c6e8dde2c 100644 --- a/resource/csdk/security/src/policyengine.c +++ b/resource/csdk/security/src/policyengine.c @@ -468,10 +468,11 @@ static void ProcessAccessRequest(SRMRequestContext_t *context) OCStackResult res = GetEndpointRoles(context->endPoint, &roles, &roleCount); if (OC_STACK_OK != res) { - OIC_LOG_V(ERROR, TAG, "Could not locate any roles for endpoint: %d", res); + OIC_LOG_V(ERROR, TAG, "Error getting asserted roles for endpoint: %d", res); } else { + OIC_LOG_V(DEBUG, TAG, "Found %u asserted roles for endpoint", (unsigned int) roleCount); do { currentAce = GetACLResourceDataByRoles(roles, roleCount, &aceSavePtr); diff --git a/resource/csdk/security/src/rolesresource.c b/resource/csdk/security/src/rolesresource.c index 97a872fda0b73af54de9343a7c98ffa407cb3629..32c461e08607c52906caf635e518610426ea86a5 100644 --- a/resource/csdk/security/src/rolesresource.c +++ b/resource/csdk/security/src/rolesresource.c @@ -67,9 +67,9 @@ static OCResourceHandle gRolesHandle = NULL; static RolesEntry_t *gRoles = NULL; static uint32_t gIdCounter = 1; -/** +/** * Default cbor payload size. This value is increased in case of CborErrorOutOfMemory. - * The value of payload size is increased until reaching max cbor size. + * The value of payload size is increased until reaching max cbor size. */ static const uint16_t CBOR_SIZE = 2048; @@ -93,7 +93,7 @@ static void InvalidateRoleCache(RolesEntry_t *entry) /* Caller must call OICFree on publicKey when finished. */ static OCStackResult GetPeerPublicKeyFromEndpoint(const CAEndpoint_t *endpoint, - uint8_t **publicKey, + uint8_t **publicKey, size_t *publicKeyLength) { CASecureEndpoint_t sep; @@ -168,7 +168,6 @@ static void FreeRolesEntry(RolesEntry_t *rolesEntry) } FreeRoleCertChainList(rolesEntry->chains); - OICFree(rolesEntry->chains); OICFree(rolesEntry->publicKey); OICFree(rolesEntry->cachedRoles); OICFree(rolesEntry); @@ -282,7 +281,7 @@ static OCStackResult AddRoleCertificate(const RoleCertChain_t *roleCert, const u else { /* We haven't seen this public key before and need a new entry. */ - targetEntry = (RolesEntry_t *)OICCalloc(1, sizeof(RolesEntry_t *)); + targetEntry = (RolesEntry_t *)OICCalloc(1, sizeof(RolesEntry_t)); if (NULL == targetEntry) { OIC_LOG(ERROR, TAG, "No memory for new targetEntry"); @@ -303,7 +302,7 @@ static OCStackResult AddRoleCertificate(const RoleCertChain_t *roleCert, const u LL_PREPEND(gRoles, targetEntry); } - // @todo: Detect duplicates and don't add them again + // @todo: (IOT-1949) Detect duplicates and don't add them again res = DuplicateRoleCertChain(roleCert, ©); if (OC_STACK_OK != res) { @@ -313,7 +312,6 @@ static OCStackResult AddRoleCertificate(const RoleCertChain_t *roleCert, const u // Assign our own credId. copy->credId = gIdCounter++; - LL_APPEND(targetEntry->chains, copy); res = OC_STACK_OK; @@ -325,12 +323,12 @@ exit: FreeRoleCertChain(copy); } - OIC_LOG_V(DEBUG, TAG, "AddRoleCertificate IN: %d", res); + OIC_LOG_V(DEBUG, TAG, "AddRoleCertificate Out: %d", res); return res; } -static OCStackResult RolesToCBORPayload(const RoleCertChain_t *roles, uint8_t **cborPayload, +OCStackResult RolesToCBORPayload(const RoleCertChain_t *roles, uint8_t **cborPayload, size_t *cborSize) { OCStackResult ret = OC_STACK_OK; @@ -400,7 +398,7 @@ static OCStackResult RolesToCBORPayload(const RoleCertChain_t *roles, uint8_t ** VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding subject tag"); cborEncoderResult = cbor_encode_text_string(&roleMap, EMPTY_UUID, sizeof(EMPTY_UUID) - 1); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding subject value"); - + // publicData - mandatory cborEncoderResult = SerializeEncodingToCbor(&roleMap, OIC_JSON_PUBLICDATA_NAME, &currChain->certificate); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed adding publicData"); @@ -489,7 +487,7 @@ exit: return ret; } -/* Caller must call DeleteRoleCredentials on roleEntries when finished. */ +/* Caller must call FreeRoleCertChainList on roleEntries when finished. */ OCStackResult CBORPayloadToRoles(const uint8_t *cborPayload, size_t size, RoleCertChain_t **roleEntries) { if (NULL == cborPayload || 0 == size || NULL == roleEntries) @@ -727,7 +725,7 @@ static OCEntityHandlerResult HandleGetRequest(OCEntityHandlerRequest *ehRequest) ehRet = (OC_STACK_OK == res) ? OC_EH_OK : OC_EH_ERROR; exit: - + ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR; OICFree(payload); @@ -755,7 +753,7 @@ static OCEntityHandlerResult HandlePostRequest(OCEntityHandlerRequest *ehRequest if (OC_STACK_OK != res) { OIC_LOG_V(ERROR, TAG, "Could not get peer's public key: %d", res); - ehRet = OC_EH_ERROR; + ehRet = OC_EH_ERROR; goto exit; } @@ -829,7 +827,7 @@ static OCEntityHandlerResult HandleDeleteRequest(OCEntityHandlerRequest *ehReque { return ehRet; } - + // Parsing REST query to get the credId ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter); while (GetNextQuery(&parseIter)) @@ -884,7 +882,7 @@ static OCEntityHandlerResult HandleDeleteRequest(OCEntityHandlerRequest *ehReque RoleCertChain_t *curr2 = NULL; LL_FOREACH_SAFE(entry->chains, curr1, curr2) { - // credId of zero means all creds; we never assign zero as a credId. + // credId of zero means delete all creds; we never assign zero as a credId. if ((0 == credId) || (curr1->credId == credId)) { LL_DELETE(entry->chains, curr1); @@ -972,7 +970,7 @@ OCStackResult DeInitRolesResource() gRolesHandle = NULL; FreeRolesList(gRoles); - + gRoles = NULL; return res; @@ -1133,7 +1131,7 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role return res; } - for (const RoleCertChain_t *chain = targetEntry->chains; NULL != chain; chain = chain->next) + for (RoleCertChain_t *chain = targetEntry->chains; NULL != chain; chain = chain->next) { OicSecRole_t *currCertRoles = NULL; size_t currCertRolesCount = 0; @@ -1148,7 +1146,9 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role if (OC_STACK_OK != res) { OIC_LOG_V(ERROR, TAG, "Failed to verify a role certificate: %d", res); - /* Don't exit; try all certificates presented. */ + /* Remove the invalid cert chain, but don't exit; try all certificates presented. */ + LL_DELETE(targetEntry->chains, chain); + FreeRoleCertChain(chain); } else { @@ -1166,14 +1166,14 @@ OCStackResult GetEndpointRoles(const CAEndpoint_t *endpoint, OicSecRole_t **role OICFree(publicKey); return OC_STACK_NO_MEMORY; } - memcpy(rolesToReturn + (rolesToReturnCount * sizeof(rolesToReturn[0])), - currCertRoles, + memcpy(rolesToReturn + (rolesToReturnCount * sizeof(rolesToReturn[0])), + currCertRoles, currCertRolesCount * sizeof(currCertRoles[0])); rolesToReturnCount += currCertRolesCount; OICFree(currCertRoles); } - /* + /* * Set the cacheValidUntil value to be the earliest notValidUntil date amongst * all the certificates. * diff --git a/resource/csdk/security/src/secureresourcemanager.c b/resource/csdk/security/src/secureresourcemanager.c index a4424a24963389f2a50cf896883b863f81c9b91e..d50d7167286e21e8447b16dd07f72f07d18f69a9 100644 --- a/resource/csdk/security/src/secureresourcemanager.c +++ b/resource/csdk/security/src/secureresourcemanager.c @@ -483,6 +483,7 @@ bool SRMIsSecurityResourceURI(const char* uri) OIC_RSRC_CRED_URI, OIC_RSRC_CSR_URI, OIC_RSRC_ACL_URI, + OIC_RSRC_ACL2_URI, OIC_RSRC_DOXM_URI, OIC_RSRC_PSTAT_URI, OIC_RSRC_PCONF_URI, @@ -551,6 +552,15 @@ OicSecSvrType_t GetSvrTypeFromUri(const char* uri) } } + svrLen = strlen(OIC_RSRC_ACL2_URI); + if (uriLen == svrLen) + { + if (0 == strncmp(uri, OIC_RSRC_ACL2_URI, svrLen)) + { + return OIC_R_ACL2_TYPE; + } + } + svrLen = strlen(OIC_RSRC_AMACL_URI); if (uriLen == svrLen) { diff --git a/resource/csdk/security/src/srmresourcestrings.c b/resource/csdk/security/src/srmresourcestrings.c index 8a0732101832716348aa66817ad69f298e515f0c..4b89eab81955a8c420b8e7ba5284e149664df816 100644 --- a/resource/csdk/security/src/srmresourcestrings.c +++ b/resource/csdk/security/src/srmresourcestrings.c @@ -175,6 +175,7 @@ const char * OIC_JSON_EMPTY_STRING = ""; // Certificates provided by Cloud const char * TRUST_CA = "oic.sec.cred.trustca"; const char * PRIMARY_CERT = "oic.sec.cred.cert"; +const char * ROLE_CERT = "oic.sec.cred.rolecert"; // Certificates provided by manufacturer const char * MF_TRUST_CA = "oic.sec.cred.mfgtrustca"; diff --git a/resource/csdk/stack/octbstack_product_secured.def b/resource/csdk/stack/octbstack_product_secured.def index 8bdfdea3c767d2e493fff956d457316e3b79dffa..a1badd44f959088c3f11a530443e2088cd1bb393 100644 --- a/resource/csdk/stack/octbstack_product_secured.def +++ b/resource/csdk/stack/octbstack_product_secured.def @@ -59,11 +59,16 @@ OCResetSVRDB OCSaveTrustCertChain OCSaveOwnCertChain OCSelectOwnershipTransferMethod +OCSaveOwnRoleCert OCSetOwnerTransferCallbackData OCSetOxmAllowStatus OCUnlinkDevices OCVerifyCSRSignature +; @todo: Remove or revise SRPAssertRoles once IOT-1952 is resolved. It should +; not be here in the release +SRPAssertRoles + SetClosePinDisplayCB SetDisplayPinWithContextCB UnsetDisplayPinWithContextCB