/* * Copyright 2021 NXP * * SPDX-License-Identifier: BSD-3-Clause * */ #include #include #include #include #include #include #include #include "caam.h" #include #include #include "hash.h" #include "jobdesc.h" #include "sec_hw_specific.h" /* Since no Allocator is available . Taking a global static ctx. * This would mean that only one active ctx can be there at a time. */ static struct hash_ctx glbl_ctx; static void hash_done(uint32_t *desc, uint32_t status, void *arg, void *job_ring) { INFO("Hash Desc SUCCESS with status %x\n", status); } /*************************************************************************** * Function : hash_init * Arguments : ctx - SHA context * Return : init, * Description : This function initializes the context for SHA calculation ***************************************************************************/ int hash_init(enum hash_algo algo, void **ctx) { if (glbl_ctx.active == false) { memset(&glbl_ctx, 0, sizeof(struct hash_ctx)); glbl_ctx.active = true; glbl_ctx.algo = algo; *ctx = &glbl_ctx; return 0; } else { return -1; } } /*************************************************************************** * Function : hash_update * Arguments : ctx - SHA context * buffer - Data * length - Length * Return : -1 on error * 0 on SUCCESS * Description : This function creates SG entry of the data provided ***************************************************************************/ int hash_update(enum hash_algo algo, void *context, void *data_ptr, unsigned int data_len) { struct hash_ctx *ctx = context; /* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */ if (ctx->sg_num >= MAX_SG) { ERROR("Reached limit for calling %s\n", __func__); ctx->active = false; return -EINVAL; } if (ctx->algo != algo) { ERROR("ctx for algo not correct\n"); ctx->active = false; return -EINVAL; } #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) flush_dcache_range((uintptr_t)data_ptr, data_len); dmbsy(); #endif #ifdef CONFIG_PHYS_64BIT sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t) ((uintptr_t) data_ptr >> 32)); #else sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); #endif sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr); sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, (data_len & SG_ENTRY_LENGTH_MASK)); ctx->sg_num++; ctx->len += data_len; return 0; } /*************************************************************************** * Function : hash_final * Arguments : ctx - SHA context * Return : SUCCESS or FAILURE * Description : This function sets the final bit and enqueues the descriptor ***************************************************************************/ int hash_final(enum hash_algo algo, void *context, void *hash_ptr, unsigned int hash_len) { int ret = 0; struct hash_ctx *ctx = context; uint32_t final = 0U; struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); jobdesc.arg = NULL; jobdesc.callback = hash_done; if (ctx->algo != algo) { ERROR("ctx for algo not correct\n"); ctx->active = false; return -EINVAL; } final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | SG_ENTRY_FINAL_BIT; sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); dsb(); /* create the hw_rng descriptor */ cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl, ctx->len, hash_ptr); #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) flush_dcache_range((uintptr_t)ctx->sg_tbl, (sizeof(struct sg_entry) * MAX_SG)); inv_dcache_range((uintptr_t)hash_ptr, hash_len); dmbsy(); #endif /* Finally, generate the requested random data bytes */ ret = run_descriptor_jr(&jobdesc); if (ret != 0) { ERROR("Error in running descriptor\n"); ret = -1; } ctx->active = false; return ret; }