1 /* 2 * Copyright 2021 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #include <errno.h> 9 #include <stdbool.h> 10 #include <stdint.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 15 #include <arch_helpers.h> 16 #include "caam.h" 17 #include <common/debug.h> 18 #include <drivers/auth/crypto_mod.h> 19 20 #include "hash.h" 21 #include "jobdesc.h" 22 #include "sec_hw_specific.h" 23 24 /* Since no Allocator is available . Taking a global static ctx. 25 * This would mean that only one active ctx can be there at a time. 26 */ 27 28 static struct hash_ctx glbl_ctx; 29 30 static void hash_done(uint32_t *desc, uint32_t status, void *arg, 31 void *job_ring) 32 { 33 INFO("Hash Desc SUCCESS with status %x\n", status); 34 } 35 36 /*************************************************************************** 37 * Function : hash_init 38 * Arguments : ctx - SHA context 39 * Return : init, 40 * Description : This function initializes the context for SHA calculation 41 ***************************************************************************/ 42 int hash_init(enum hash_algo algo, void **ctx) 43 { 44 if (glbl_ctx.active == false) { 45 memset(&glbl_ctx, 0, sizeof(struct hash_ctx)); 46 glbl_ctx.active = true; 47 glbl_ctx.algo = algo; 48 *ctx = &glbl_ctx; 49 return 0; 50 } else { 51 return -1; 52 } 53 } 54 55 /*************************************************************************** 56 * Function : hash_update 57 * Arguments : ctx - SHA context 58 * buffer - Data 59 * length - Length 60 * Return : -1 on error 61 * 0 on SUCCESS 62 * Description : This function creates SG entry of the data provided 63 ***************************************************************************/ 64 int hash_update(enum hash_algo algo, void *context, void *data_ptr, 65 unsigned int data_len) 66 { 67 struct hash_ctx *ctx = context; 68 /* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */ 69 if (ctx->sg_num >= MAX_SG) { 70 ERROR("Reached limit for calling %s\n", __func__); 71 ctx->active = false; 72 return -EINVAL; 73 74 } 75 76 if (ctx->algo != algo) { 77 ERROR("ctx for algo not correct\n"); 78 ctx->active = false; 79 return -EINVAL; 80 } 81 82 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) 83 flush_dcache_range((uintptr_t)data_ptr, data_len); 84 dmbsy(); 85 #endif 86 87 #ifdef CONFIG_PHYS_64BIT 88 sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 89 (uint32_t) ((uintptr_t) data_ptr >> 32)); 90 #else 91 sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); 92 #endif 93 sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr); 94 95 sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, 96 (data_len & SG_ENTRY_LENGTH_MASK)); 97 98 ctx->sg_num++; 99 100 ctx->len += data_len; 101 102 return 0; 103 } 104 105 /*************************************************************************** 106 * Function : hash_final 107 * Arguments : ctx - SHA context 108 * Return : SUCCESS or FAILURE 109 * Description : This function sets the final bit and enqueues the descriptor 110 ***************************************************************************/ 111 int hash_final(enum hash_algo algo, void *context, void *hash_ptr, 112 unsigned int hash_len) 113 { 114 int ret = 0; 115 struct hash_ctx *ctx = context; 116 uint32_t final = 0U; 117 118 struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); 119 120 jobdesc.arg = NULL; 121 jobdesc.callback = hash_done; 122 123 if (ctx->algo != algo) { 124 ERROR("ctx for algo not correct\n"); 125 ctx->active = false; 126 return -EINVAL; 127 } 128 129 final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | 130 SG_ENTRY_FINAL_BIT; 131 sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); 132 133 dsb(); 134 135 /* create the hw_rng descriptor */ 136 cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl, 137 ctx->len, hash_ptr); 138 139 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) 140 flush_dcache_range((uintptr_t)ctx->sg_tbl, 141 (sizeof(struct sg_entry) * MAX_SG)); 142 inv_dcache_range((uintptr_t)hash_ptr, hash_len); 143 144 dmbsy(); 145 #endif 146 147 /* Finally, generate the requested random data bytes */ 148 ret = run_descriptor_jr(&jobdesc); 149 if (ret != 0) { 150 ERROR("Error in running descriptor\n"); 151 ret = -1; 152 } 153 ctx->active = false; 154 return ret; 155 } 156