Commit 4541e501 authored by Greg Zaverucha's avatar Greg Zaverucha Committed by Nathan Heldt-Sheller

[IOT-1785] Finish role certs feature

Add end-to-end testing of role certificate scenario:
- provision role certs
- test role-based ACLs provisioning and enforcement
- test assertion of role certificates

Fix bugs and add new functions as necessary. Added the ROLE_CERT
usage to distinguish role certs (which can't be used for TLS)
from identity certs. Previously they were both saved as PRIMARY_CERT.
Some small changes to save and retrieve role certificates locally. Add
functionality to assert roles (POST the certs to /oic/sec/roles).

Change-Id: I9080e0ca6b0809608621eb8b23dd4bbbfbbb176c
Signed-off-by: default avatarGreg Zaverucha <gregz@microsoft.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18219Reviewed-by: default avatarAlex Kelley <alexke@microsoft.com>
Reviewed-by: default avatarDave Thaler <dthaler@microsoft.com>
Reviewed-by: default avatarKevin Kane <kkane@microsoft.com>
Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Nathan Heldt-Sheller's avatarNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
parent 9ca54cba
......@@ -24,6 +24,7 @@
#include "cainterface.h"
#include "securevirtualresourcetypes.h"
#include "octypes.h"
#include "rolesresource.h"
#include <cbor.h>
#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
*
......
......@@ -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.
*
......
......@@ -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;
......
......@@ -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
......
......@@ -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
};
......
......@@ -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.
......
......@@ -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'
......
......@@ -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.
*
......
......@@ -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)
{