blob: 1665df1a86153c4cbcad8feaf5203d5d61988ed3 [file] [log] [blame]
/*
* 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 "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 decriptor
***************************************************************************/
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;
}