1b9eebfadSRuchika Gupta /* 2b9eebfadSRuchika Gupta * Copyright 2014 Freescale Semiconductor, Inc. 3b9eebfadSRuchika Gupta * 4b9eebfadSRuchika Gupta * SPDX-License-Identifier: GPL-2.0+ 5b9eebfadSRuchika Gupta * 6b9eebfadSRuchika Gupta */ 7b9eebfadSRuchika Gupta 8b9eebfadSRuchika Gupta #include <common.h> 9b9eebfadSRuchika Gupta #include <malloc.h> 10b9eebfadSRuchika Gupta #include "jobdesc.h" 11b9eebfadSRuchika Gupta #include "desc.h" 12b9eebfadSRuchika Gupta #include "jr.h" 13*94e3c8c4Sgaurav rana #include "fsl_hash.h" 14*94e3c8c4Sgaurav rana #include <hw_sha.h> 15*94e3c8c4Sgaurav rana #include <asm-generic/errno.h> 16b9eebfadSRuchika Gupta 17b9eebfadSRuchika Gupta #define CRYPTO_MAX_ALG_NAME 80 18b9eebfadSRuchika Gupta #define SHA1_DIGEST_SIZE 20 19b9eebfadSRuchika Gupta #define SHA256_DIGEST_SIZE 32 20b9eebfadSRuchika Gupta 21b9eebfadSRuchika Gupta struct caam_hash_template { 22b9eebfadSRuchika Gupta char name[CRYPTO_MAX_ALG_NAME]; 23b9eebfadSRuchika Gupta unsigned int digestsize; 24b9eebfadSRuchika Gupta u32 alg_type; 25b9eebfadSRuchika Gupta }; 26b9eebfadSRuchika Gupta 27b9eebfadSRuchika Gupta enum caam_hash_algos { 28b9eebfadSRuchika Gupta SHA1 = 0, 29b9eebfadSRuchika Gupta SHA256 30b9eebfadSRuchika Gupta }; 31b9eebfadSRuchika Gupta 32b9eebfadSRuchika Gupta static struct caam_hash_template driver_hash[] = { 33b9eebfadSRuchika Gupta { 34b9eebfadSRuchika Gupta .name = "sha1", 35b9eebfadSRuchika Gupta .digestsize = SHA1_DIGEST_SIZE, 36b9eebfadSRuchika Gupta .alg_type = OP_ALG_ALGSEL_SHA1, 37b9eebfadSRuchika Gupta }, 38b9eebfadSRuchika Gupta { 39b9eebfadSRuchika Gupta .name = "sha256", 40b9eebfadSRuchika Gupta .digestsize = SHA256_DIGEST_SIZE, 41b9eebfadSRuchika Gupta .alg_type = OP_ALG_ALGSEL_SHA256, 42b9eebfadSRuchika Gupta }, 43b9eebfadSRuchika Gupta }; 44b9eebfadSRuchika Gupta 45*94e3c8c4Sgaurav rana static enum caam_hash_algos get_hash_type(struct hash_algo *algo) 46*94e3c8c4Sgaurav rana { 47*94e3c8c4Sgaurav rana if (!strcmp(algo->name, driver_hash[SHA1].name)) 48*94e3c8c4Sgaurav rana return SHA1; 49*94e3c8c4Sgaurav rana else 50*94e3c8c4Sgaurav rana return SHA256; 51*94e3c8c4Sgaurav rana } 52*94e3c8c4Sgaurav rana 53*94e3c8c4Sgaurav rana /* Create the context for progressive hashing using h/w acceleration. 54*94e3c8c4Sgaurav rana * 55*94e3c8c4Sgaurav rana * @ctxp: Pointer to the pointer of the context for hashing 56*94e3c8c4Sgaurav rana * @caam_algo: Enum for SHA1 or SHA256 57*94e3c8c4Sgaurav rana * @return 0 if ok, -ENOMEM on error 58*94e3c8c4Sgaurav rana */ 59*94e3c8c4Sgaurav rana static int caam_hash_init(void **ctxp, enum caam_hash_algos caam_algo) 60*94e3c8c4Sgaurav rana { 61*94e3c8c4Sgaurav rana *ctxp = calloc(1, sizeof(struct sha_ctx)); 62*94e3c8c4Sgaurav rana if (*ctxp == NULL) { 63*94e3c8c4Sgaurav rana debug("Cannot allocate memory for context\n"); 64*94e3c8c4Sgaurav rana return -ENOMEM; 65*94e3c8c4Sgaurav rana } 66*94e3c8c4Sgaurav rana return 0; 67*94e3c8c4Sgaurav rana } 68*94e3c8c4Sgaurav rana 69*94e3c8c4Sgaurav rana /* 70*94e3c8c4Sgaurav rana * Update sg table for progressive hashing using h/w acceleration 71*94e3c8c4Sgaurav rana * 72*94e3c8c4Sgaurav rana * The context is freed by this function if an error occurs. 73*94e3c8c4Sgaurav rana * We support at most 32 Scatter/Gather Entries. 74*94e3c8c4Sgaurav rana * 75*94e3c8c4Sgaurav rana * @hash_ctx: Pointer to the context for hashing 76*94e3c8c4Sgaurav rana * @buf: Pointer to the buffer being hashed 77*94e3c8c4Sgaurav rana * @size: Size of the buffer being hashed 78*94e3c8c4Sgaurav rana * @is_last: 1 if this is the last update; 0 otherwise 79*94e3c8c4Sgaurav rana * @caam_algo: Enum for SHA1 or SHA256 80*94e3c8c4Sgaurav rana * @return 0 if ok, -EINVAL on error 81*94e3c8c4Sgaurav rana */ 82*94e3c8c4Sgaurav rana static int caam_hash_update(void *hash_ctx, const void *buf, 83*94e3c8c4Sgaurav rana unsigned int size, int is_last, 84*94e3c8c4Sgaurav rana enum caam_hash_algos caam_algo) 85*94e3c8c4Sgaurav rana { 86*94e3c8c4Sgaurav rana uint32_t final = 0; 87*94e3c8c4Sgaurav rana dma_addr_t addr = virt_to_phys((void *)buf); 88*94e3c8c4Sgaurav rana struct sha_ctx *ctx = hash_ctx; 89*94e3c8c4Sgaurav rana 90*94e3c8c4Sgaurav rana if (ctx->sg_num >= MAX_SG_32) { 91*94e3c8c4Sgaurav rana free(ctx); 92*94e3c8c4Sgaurav rana return -EINVAL; 93*94e3c8c4Sgaurav rana } 94*94e3c8c4Sgaurav rana 95*94e3c8c4Sgaurav rana #ifdef CONFIG_PHYS_64BIT 96*94e3c8c4Sgaurav rana ctx->sg_tbl[ctx->sg_num].addr_hi = addr >> 32; 97*94e3c8c4Sgaurav rana #else 98*94e3c8c4Sgaurav rana ctx->sg_tbl[ctx->sg_num].addr_hi = 0x0; 99*94e3c8c4Sgaurav rana #endif 100*94e3c8c4Sgaurav rana ctx->sg_tbl[ctx->sg_num].addr_lo = addr; 101*94e3c8c4Sgaurav rana 102*94e3c8c4Sgaurav rana sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, 103*94e3c8c4Sgaurav rana (size & SG_ENTRY_LENGTH_MASK)); 104*94e3c8c4Sgaurav rana 105*94e3c8c4Sgaurav rana ctx->sg_num++; 106*94e3c8c4Sgaurav rana 107*94e3c8c4Sgaurav rana if (is_last) { 108*94e3c8c4Sgaurav rana final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | 109*94e3c8c4Sgaurav rana SG_ENTRY_FINAL_BIT; 110*94e3c8c4Sgaurav rana sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); 111*94e3c8c4Sgaurav rana } 112*94e3c8c4Sgaurav rana 113*94e3c8c4Sgaurav rana return 0; 114*94e3c8c4Sgaurav rana } 115*94e3c8c4Sgaurav rana 116*94e3c8c4Sgaurav rana /* 117*94e3c8c4Sgaurav rana * Perform progressive hashing on the given buffer and copy hash at 118*94e3c8c4Sgaurav rana * destination buffer 119*94e3c8c4Sgaurav rana * 120*94e3c8c4Sgaurav rana * The context is freed after completion of hash operation. 121*94e3c8c4Sgaurav rana * 122*94e3c8c4Sgaurav rana * @hash_ctx: Pointer to the context for hashing 123*94e3c8c4Sgaurav rana * @dest_buf: Pointer to the destination buffer where hash is to be copied 124*94e3c8c4Sgaurav rana * @size: Size of the buffer being hashed 125*94e3c8c4Sgaurav rana * @caam_algo: Enum for SHA1 or SHA256 126*94e3c8c4Sgaurav rana * @return 0 if ok, -EINVAL on error 127*94e3c8c4Sgaurav rana */ 128*94e3c8c4Sgaurav rana static int caam_hash_finish(void *hash_ctx, void *dest_buf, 129*94e3c8c4Sgaurav rana int size, enum caam_hash_algos caam_algo) 130*94e3c8c4Sgaurav rana { 131*94e3c8c4Sgaurav rana uint32_t len = 0; 132*94e3c8c4Sgaurav rana struct sha_ctx *ctx = hash_ctx; 133*94e3c8c4Sgaurav rana int i = 0, ret = 0; 134*94e3c8c4Sgaurav rana 135*94e3c8c4Sgaurav rana if (size < driver_hash[caam_algo].digestsize) { 136*94e3c8c4Sgaurav rana free(ctx); 137*94e3c8c4Sgaurav rana return -EINVAL; 138*94e3c8c4Sgaurav rana } 139*94e3c8c4Sgaurav rana 140*94e3c8c4Sgaurav rana for (i = 0; i < ctx->sg_num; i++) 141*94e3c8c4Sgaurav rana len += (sec_in32(&ctx->sg_tbl[i].len_flag) & 142*94e3c8c4Sgaurav rana SG_ENTRY_LENGTH_MASK); 143*94e3c8c4Sgaurav rana 144*94e3c8c4Sgaurav rana inline_cnstr_jobdesc_hash(ctx->sha_desc, (uint8_t *)ctx->sg_tbl, len, 145*94e3c8c4Sgaurav rana ctx->hash, 146*94e3c8c4Sgaurav rana driver_hash[caam_algo].alg_type, 147*94e3c8c4Sgaurav rana driver_hash[caam_algo].digestsize, 148*94e3c8c4Sgaurav rana 1); 149*94e3c8c4Sgaurav rana 150*94e3c8c4Sgaurav rana ret = run_descriptor_jr(ctx->sha_desc); 151*94e3c8c4Sgaurav rana 152*94e3c8c4Sgaurav rana if (ret) 153*94e3c8c4Sgaurav rana debug("Error %x\n", ret); 154*94e3c8c4Sgaurav rana else 155*94e3c8c4Sgaurav rana memcpy(dest_buf, ctx->hash, sizeof(ctx->hash)); 156*94e3c8c4Sgaurav rana 157*94e3c8c4Sgaurav rana free(ctx); 158*94e3c8c4Sgaurav rana return ret; 159*94e3c8c4Sgaurav rana } 160*94e3c8c4Sgaurav rana 161b9eebfadSRuchika Gupta int caam_hash(const unsigned char *pbuf, unsigned int buf_len, 162b9eebfadSRuchika Gupta unsigned char *pout, enum caam_hash_algos algo) 163b9eebfadSRuchika Gupta { 164b9eebfadSRuchika Gupta int ret = 0; 165b9eebfadSRuchika Gupta uint32_t *desc; 166b9eebfadSRuchika Gupta 167b9eebfadSRuchika Gupta desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE); 168b9eebfadSRuchika Gupta if (!desc) { 169b9eebfadSRuchika Gupta debug("Not enough memory for descriptor allocation\n"); 170*94e3c8c4Sgaurav rana return -ENOMEM; 171b9eebfadSRuchika Gupta } 172b9eebfadSRuchika Gupta 173b9eebfadSRuchika Gupta inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, 174b9eebfadSRuchika Gupta driver_hash[algo].alg_type, 175b9eebfadSRuchika Gupta driver_hash[algo].digestsize, 176b9eebfadSRuchika Gupta 0); 177b9eebfadSRuchika Gupta 178b9eebfadSRuchika Gupta ret = run_descriptor_jr(desc); 179b9eebfadSRuchika Gupta 180b9eebfadSRuchika Gupta free(desc); 181b9eebfadSRuchika Gupta return ret; 182b9eebfadSRuchika Gupta } 183b9eebfadSRuchika Gupta 184b9eebfadSRuchika Gupta void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, 185b9eebfadSRuchika Gupta unsigned char *pout, unsigned int chunk_size) 186b9eebfadSRuchika Gupta { 187b9eebfadSRuchika Gupta if (caam_hash(pbuf, buf_len, pout, SHA256)) 188b9eebfadSRuchika Gupta printf("CAAM was not setup properly or it is faulty\n"); 189b9eebfadSRuchika Gupta } 190b9eebfadSRuchika Gupta 191b9eebfadSRuchika Gupta void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, 192b9eebfadSRuchika Gupta unsigned char *pout, unsigned int chunk_size) 193b9eebfadSRuchika Gupta { 194b9eebfadSRuchika Gupta if (caam_hash(pbuf, buf_len, pout, SHA1)) 195b9eebfadSRuchika Gupta printf("CAAM was not setup properly or it is faulty\n"); 196b9eebfadSRuchika Gupta } 197*94e3c8c4Sgaurav rana 198*94e3c8c4Sgaurav rana int hw_sha_init(struct hash_algo *algo, void **ctxp) 199*94e3c8c4Sgaurav rana { 200*94e3c8c4Sgaurav rana return caam_hash_init(ctxp, get_hash_type(algo)); 201*94e3c8c4Sgaurav rana } 202*94e3c8c4Sgaurav rana 203*94e3c8c4Sgaurav rana int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, 204*94e3c8c4Sgaurav rana unsigned int size, int is_last) 205*94e3c8c4Sgaurav rana { 206*94e3c8c4Sgaurav rana return caam_hash_update(ctx, buf, size, is_last, get_hash_type(algo)); 207*94e3c8c4Sgaurav rana } 208*94e3c8c4Sgaurav rana 209*94e3c8c4Sgaurav rana int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, 210*94e3c8c4Sgaurav rana int size) 211*94e3c8c4Sgaurav rana { 212*94e3c8c4Sgaurav rana return caam_hash_finish(ctx, dest_buf, size, get_hash_type(algo)); 213*94e3c8c4Sgaurav rana } 214