diff options
Diffstat (limited to 'drivers/nxp/crypto/caam/src/auth/rsa.c')
-rw-r--r-- | drivers/nxp/crypto/caam/src/auth/rsa.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/drivers/nxp/crypto/caam/src/auth/rsa.c b/drivers/nxp/crypto/caam/src/auth/rsa.c new file mode 100644 index 0000000..0c44462 --- /dev/null +++ b/drivers/nxp/crypto/caam/src/auth/rsa.c @@ -0,0 +1,179 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <arch_helpers.h> +#include "caam.h" +#include <common/debug.h> +#include <drivers/auth/crypto_mod.h> + +#include "jobdesc.h" +#include "rsa.h" +#include "sec_hw_specific.h" + +/* This array contains DER value for SHA-256 */ +static const uint8_t hash_identifier[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20 +}; + +static void rsa_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("RSA Desc SUCCESS with status %x\n", status); +} + +static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to, + uint8_t *rsa_pub_key, uint32_t klen) +{ + int ret = 0; + struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); + + jobdesc.arg = NULL; + jobdesc.callback = rsa_done; + + memset(&ctx, 0, sizeof(struct rsa_context)); + + ctx.pkin.a = sign; + ctx.pkin.a_siz = klen; + ctx.pkin.n = rsa_pub_key; + ctx.pkin.n_siz = klen; + ctx.pkin.e = rsa_pub_key + klen; + ctx.pkin.e_siz = klen; + + cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)sign, klen); + flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen); + flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin)); + inv_dcache_range((uintptr_t)to, klen); + + dmbsy(); + dsbsy(); + isb(); +#endif + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(&jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)to, klen); + dmbsy(); + dsbsy(); + isb(); +#endif + return ret; +} + +/* + * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the + * pointers for padding, DER value and hash. And finally, constructs EM' + * which includes hash of complete CSF header and ESBC image. If SG flag + * is on, hash of SG table and entries is also included. + */ +static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len, + uint8_t *encoded_hash_second, + unsigned int key_len) +{ + /* + * RSA PKCSv1.5 encoding format for encoded message is below + * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash + * PS is Padding String + * DER is DER value for SHA-256 + * Hash is SHA-256 hash + * ********************************************************* + * representative points to first byte of EM initially and is + * filled with 0x0 + * representative is incremented by 1 and second byte is filled + * with 0x1 + * padding points to third byte of EM + * digest points to full length of EM - 32 bytes + * hash_id (DER value) points to 19 bytes before pDigest + * separator is one byte which separates padding and DER + */ + + unsigned int len; + uint8_t *representative; + uint8_t *padding, *digest; + uint8_t *hash_id, *separator; + int i; + int ret = 0; + + if (hash_len != SHA256_BYTES) { + return -1; + } + + /* Key length = Modulus length */ + len = (key_len / 2U) - 1U; + representative = encoded_hash_second; + representative[0] = 0U; + representative[1] = 1U; /* block type 1 */ + + padding = &representative[2]; + digest = &representative[1] + len - 32; + hash_id = digest - sizeof(hash_identifier); + separator = hash_id - 1; + + /* fill padding area pointed by padding with 0xff */ + memset(padding, 0xff, separator - padding); + + /* fill byte pointed by separator */ + *separator = 0U; + + /* fill SHA-256 DER value pointed by HashId */ + memcpy(hash_id, hash_identifier, sizeof(hash_identifier)); + + /* fill hash pointed by Digest */ + for (i = 0; i < SHA256_BYTES; i++) { + digest[i] = hash[i]; + } + + return ret; +} + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len) +{ + uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES]; + uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); + int ret = 0; + + ret = construct_img_encoded_hash_second(hash_ptr, hash_len, + img_encoded_hash_second, + pk_len); + if (ret != 0) { + ERROR("Encoded Hash Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2); + if (ret != 0) { + ERROR("RSA signature Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len); + if (ret != 0) { + ERROR("Comparison Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + return CRYPTO_SUCCESS; +} |