diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/auth/cryptocell/712/cryptocell_crypto.c | 306 | ||||
-rw-r--r-- | drivers/auth/cryptocell/712/cryptocell_plat_helpers.c | 113 | ||||
-rw-r--r-- | drivers/auth/cryptocell/713/cryptocell_crypto.c | 276 | ||||
-rw-r--r-- | drivers/auth/cryptocell/713/cryptocell_plat_helpers.c | 109 | ||||
-rw-r--r-- | drivers/auth/cryptocell/cryptocell_crypto.mk | 40 |
5 files changed, 844 insertions, 0 deletions
diff --git a/drivers/auth/cryptocell/712/cryptocell_crypto.c b/drivers/auth/cryptocell/712/cryptocell_crypto.c new file mode 100644 index 0000000..c7ee36f --- /dev/null +++ b/drivers/auth/cryptocell/712/cryptocell_crypto.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stddef.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/cryptocell/712/crypto_driver.h> +#include <drivers/arm/cryptocell/712/rsa.h> +#include <drivers/arm/cryptocell/712/sbrom_bsv_api.h> +#include <drivers/arm/cryptocell/712/secureboot_base_func.h> +#include <drivers/arm/cryptocell/712/secureboot_gen_defs.h> +#include <drivers/arm/cryptocell/712/util.h> +#include <drivers/auth/crypto_mod.h> +#include <drivers/auth/mbedtls/mbedtls_common.h> +#include <lib/utils.h> + +#include <mbedtls/oid.h> +#include <mbedtls/x509.h> + +#define LIB_NAME "CryptoCell 712 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvSbromInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvSbromInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvLcsGetAndInit((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvLcsGetAndInit() error %x\n", ret); + panic(); + } + + /* If the lifecyclestate is `SD`, then stop further execution */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) { + ERROR("CryptoCell LCS is security-disabled\n"); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + CCError_t error; + CCSbNParams_t pk; + CCSbSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + /* Temp buf to store the public key modulo (N) in LE format */ + uint32_t RevN[SB_RSA_MOD_SIZE_IN_WORDS]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The CCSbVerifySignature() API expects N and Np in BE format and + * the signature in LE format. Copy N from certificate. + */ + memcpy(pk.N, p, RSA_MOD_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* + * Calculate the Np (Barrett n' value). The RSA_CalcNp() API expects + * N in LE format. Hence reverse N into a temporary buffer `RevN`. + */ + UTIL_ReverseMemCopy((uint8_t *)RevN, (uint8_t *)pk.N, sizeof(RevN)); + + RSA_CalcNp((uintptr_t)PLAT_CRYPTOCELL_BASE, RevN, pk.Np); + + /* Np is in LE format. Reverse it to BE */ + UTIL_ReverseBuff((uint8_t *)pk.Np, sizeof(pk.Np)); + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The signature is BE format. Convert it to LE before calling + * CCSbVerifySignature(). + */ + UTIL_ReverseMemCopy((uint8_t *)signature.sig, p, RSA_MOD_SIZE_IN_BYTES); + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + /* Verify the signature */ + error = CCSbVerifySignature((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uint32_t *)data_ptr, &pk, &signature, + data_len, RSA_PSS); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + hash = p; + error = SBROM_CryptoHash((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uintptr_t)data_ptr, data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); + diff --git a/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c b/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c new file mode 100644 index 0000000..53d77db --- /dev/null +++ b/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <string.h> + +#include <platform_def.h> + +#include <plat/common/platform.h> +#include <tools_share/tbbr_oid.h> + +#include <common/debug.h> +#include <drivers/arm/cryptocell/712/sbrom_bsv_api.h> +#include <drivers/arm/cryptocell/712/nvm.h> +#include <drivers/arm/cryptocell/712/nvm_otp.h> + +/* + * Return the ROTPK hash + * + * dst: buffer into which the ROTPK hash will be copied into + * len: length of the provided buffer, which must be at least enough for a + * SHA256 hash + * flags: a pointer to integer that will be set to indicate the ROTPK status + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = NVM_GetLCS(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + /* If the lifecycle state is `SD`, return failure */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) + return 1; + + /* + * If the lifecycle state is `CM` or `DM`, ROTPK shouldn't be verified. + * Return success after setting ROTPK_NOT_DEPLOYED flag + */ + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || + (lcs == CC_BSV_DEVICE_MANUFACTURE_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + /* Copy the DER header */ + error = NVM_ReadHASHPubKey(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + (uint32_t *)dst, HASH_RESULT_SIZE_IN_WORDS); + if (error != CC_OK) + return 1; + + *flags = ROTPK_IS_HASH; + return 0; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/drivers/auth/cryptocell/713/cryptocell_crypto.c b/drivers/auth/cryptocell/713/cryptocell_crypto.c new file mode 100644 index 0000000..3ac16af --- /dev/null +++ b/drivers/auth/cryptocell/713/cryptocell_crypto.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <string.h> + +#include <platform_def.h> + +#include <drivers/arm/cryptocell/713/bsv_api.h> +#include <drivers/arm/cryptocell/713/bsv_crypto_asym_api.h> +#include <drivers/auth/crypto_mod.h> + +#include <mbedtls/oid.h> +#include <mbedtls/x509.h> + +#define LIB_NAME "CryptoCell 713 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + CCError_t error; + CCBsvNBuff_t NBuff; + CCBsvSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + CCHashResult_t digest; + CCBool_t is_verified; + /* This is a rather large array, we don't want it on stack */ + static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || + pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy N from certificate. + */ + memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy the signature (in BE format) + */ + memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, + data_ptr, data_len, digest); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the signature */ + error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff, + NULL, signature, digest, workspace, + BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified); + if ((error != CC_OK) || (is_verified != CC_TRUE)) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + hash = p; + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr, + data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c b/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c new file mode 100644 index 0000000..17e1280 --- /dev/null +++ b/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stddef.h> +#include <string.h> + +#include <plat/common/platform.h> +#include <tools_share/tbbr_oid.h> + +#include <lib/libc/endian.h> +#include <drivers/arm/cryptocell/713/bsv_api.h> +#include <drivers/arm/cryptocell/713/bsv_error.h> + +/* + * Return the ROTPK hash + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + int i; + uint32_t *key = (uint32_t *)dst; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = CC_BsvLcsGet(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || (lcs == CC_BSV_RMA_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + error = CC_BsvPubKeyHashGet(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + key, HASH_RESULT_SIZE_IN_WORDS); + + if (error == CC_BSV_HASH_NOT_PROGRAMMED_ERR) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + if (error == CC_OK) { + + /* Keys are stored in OTP in little-endian format */ + for (i = 0; i < HASH_RESULT_SIZE_IN_WORDS; i++) + key[i] = le32toh(key[i]); + + *flags = ROTPK_IS_HASH; + return 0; + } + + return 1; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/drivers/auth/cryptocell/cryptocell_crypto.mk b/drivers/auth/cryptocell/cryptocell_crypto.mk new file mode 100644 index 0000000..db39047 --- /dev/null +++ b/drivers/auth/cryptocell/cryptocell_crypto.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +# The algorithm is RSA when using Cryptocell crypto driver +TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA + +# Needs to be set to drive mbed TLS configuration correctly +$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID)) + +$(eval $(call add_define,KEY_SIZE)) + +# CCSBROM_LIB_PATH must be set to the Cryptocell SBROM library path +ifeq (${CCSBROM_LIB_PATH},) + $(error Error: CCSBROM_LIB_PATH not set) +endif + +CRYPTOCELL_VERSION ?= 712 +ifeq (${CRYPTOCELL_VERSION},712) + CCSBROM_LIB_FILENAME := cc_712sbromx509 +else ifeq (${CRYPTOCELL_VERSION},713) + CCSBROM_LIB_FILENAME := cc_713bsv +else + $(error Error: CRYPTOCELL_VERSION set to invalid version) +endif + +CRYPTOCELL_SRC_DIR := drivers/auth/cryptocell/${CRYPTOCELL_VERSION}/ + +CRYPTOCELL_SOURCES := ${CRYPTOCELL_SRC_DIR}/cryptocell_crypto.c \ + ${CRYPTOCELL_SRC_DIR}/cryptocell_plat_helpers.c + +TF_LDFLAGS += -L$(CCSBROM_LIB_PATH) +LDLIBS += -l$(CCSBROM_LIB_FILENAME) + +BL1_SOURCES += ${CRYPTOCELL_SOURCES} +BL2_SOURCES += ${CRYPTOCELL_SOURCES} |