1*01b2a7fcSCarlo Caione /* 2*01b2a7fcSCarlo Caione * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt> 3*01b2a7fcSCarlo Caione * 4*01b2a7fcSCarlo Caione * SPDX-License-Identifier: BSD-3-Clause 5*01b2a7fcSCarlo Caione */ 6*01b2a7fcSCarlo Caione 7*01b2a7fcSCarlo Caione #include <arch_helpers.h> 8*01b2a7fcSCarlo Caione #include <assert.h> 9*01b2a7fcSCarlo Caione #include <crypto/sha_dma.h> 10*01b2a7fcSCarlo Caione #include <lib/mmio.h> 11*01b2a7fcSCarlo Caione 12*01b2a7fcSCarlo Caione #define AML_SHA_DMA_BASE 0xc883e000 13*01b2a7fcSCarlo Caione 14*01b2a7fcSCarlo Caione #define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08) 15*01b2a7fcSCarlo Caione #define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18) 16*01b2a7fcSCarlo Caione 17*01b2a7fcSCarlo Caione #define ASD_MODE_SHA224 0x7 18*01b2a7fcSCarlo Caione #define ASD_MODE_SHA256 0x6 19*01b2a7fcSCarlo Caione 20*01b2a7fcSCarlo Caione /* SHA DMA descriptor */ 21*01b2a7fcSCarlo Caione struct asd_desc { 22*01b2a7fcSCarlo Caione uint32_t cfg; 23*01b2a7fcSCarlo Caione uint32_t src; 24*01b2a7fcSCarlo Caione uint32_t dst; 25*01b2a7fcSCarlo Caione }; 26*01b2a7fcSCarlo Caione #define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk)) 27*01b2a7fcSCarlo Caione #define ASD_DESC_SET(x, v, msk, off) \ 28*01b2a7fcSCarlo Caione ((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off))) 29*01b2a7fcSCarlo Caione 30*01b2a7fcSCarlo Caione #define ASD_DESC_LEN_OFF 0 31*01b2a7fcSCarlo Caione #define ASD_DESC_LEN_MASK 0x1ffff 32*01b2a7fcSCarlo Caione #define ASD_DESC_LEN(d) \ 33*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) 34*01b2a7fcSCarlo Caione #define ASD_DESC_LEN_SET(d, v) \ 35*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) 36*01b2a7fcSCarlo Caione 37*01b2a7fcSCarlo Caione #define ASD_DESC_IRQ_OFF 17 38*01b2a7fcSCarlo Caione #define ASD_DESC_IRQ_MASK 0x1 39*01b2a7fcSCarlo Caione #define ASD_DESC_IRQ(d) \ 40*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) 41*01b2a7fcSCarlo Caione #define ASD_DESC_IRQ_SET(d, v) \ 42*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) 43*01b2a7fcSCarlo Caione 44*01b2a7fcSCarlo Caione #define ASD_DESC_EOD_OFF 18 45*01b2a7fcSCarlo Caione #define ASD_DESC_EOD_MASK 0x1 46*01b2a7fcSCarlo Caione #define ASD_DESC_EOD(d) \ 47*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) 48*01b2a7fcSCarlo Caione #define ASD_DESC_EOD_SET(d, v) \ 49*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) 50*01b2a7fcSCarlo Caione 51*01b2a7fcSCarlo Caione #define ASD_DESC_LOOP_OFF 19 52*01b2a7fcSCarlo Caione #define ASD_DESC_LOOP_MASK 0x1 53*01b2a7fcSCarlo Caione #define ASD_DESC_LOOP(d) \ 54*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) 55*01b2a7fcSCarlo Caione #define ASD_DESC_LOOP_SET(d, v) \ 56*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) 57*01b2a7fcSCarlo Caione 58*01b2a7fcSCarlo Caione #define ASD_DESC_MODE_OFF 20 59*01b2a7fcSCarlo Caione #define ASD_DESC_MODE_MASK 0xf 60*01b2a7fcSCarlo Caione #define ASD_DESC_MODE(d) \ 61*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) 62*01b2a7fcSCarlo Caione #define ASD_DESC_MODE_SET(d, v) \ 63*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) 64*01b2a7fcSCarlo Caione 65*01b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_OFF 24 66*01b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_MASK 0x1 67*01b2a7fcSCarlo Caione #define ASD_DESC_BEGIN(d) \ 68*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) 69*01b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_SET(d, v) \ 70*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) 71*01b2a7fcSCarlo Caione 72*01b2a7fcSCarlo Caione #define ASD_DESC_END_OFF 25 73*01b2a7fcSCarlo Caione #define ASD_DESC_END_MASK 0x1 74*01b2a7fcSCarlo Caione #define ASD_DESC_END(d) \ 75*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) 76*01b2a7fcSCarlo Caione #define ASD_DESC_END_SET(d, v) \ 77*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) 78*01b2a7fcSCarlo Caione 79*01b2a7fcSCarlo Caione #define ASD_DESC_OP_OFF 26 80*01b2a7fcSCarlo Caione #define ASD_DESC_OP_MASK 0x2 81*01b2a7fcSCarlo Caione #define ASD_DESC_OP(d) \ 82*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) 83*01b2a7fcSCarlo Caione #define ASD_DESC_OP_SET(d, v) \ 84*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) 85*01b2a7fcSCarlo Caione 86*01b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_OFF 28 87*01b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_MASK 0x1 88*01b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY(d) \ 89*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) 90*01b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_SET(d, v) \ 91*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) 92*01b2a7fcSCarlo Caione 93*01b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_OFF 29 94*01b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_MASK 0x1 95*01b2a7fcSCarlo Caione #define ASD_DESC_BLOCK(d) \ 96*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) 97*01b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_SET(d, v) \ 98*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) 99*01b2a7fcSCarlo Caione 100*01b2a7fcSCarlo Caione #define ASD_DESC_ERR_OFF 30 101*01b2a7fcSCarlo Caione #define ASD_DESC_ERR_MASK 0x1 102*01b2a7fcSCarlo Caione #define ASD_DESC_ERR(d) \ 103*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) 104*01b2a7fcSCarlo Caione #define ASD_DESC_ERR_SET(d, v) \ 105*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) 106*01b2a7fcSCarlo Caione 107*01b2a7fcSCarlo Caione #define ASD_DESC_OWNER_OFF 31u 108*01b2a7fcSCarlo Caione #define ASD_DESC_OWNER_MASK 0x1u 109*01b2a7fcSCarlo Caione #define ASD_DESC_OWNER(d) \ 110*01b2a7fcSCarlo Caione (ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) 111*01b2a7fcSCarlo Caione #define ASD_DESC_OWNER_SET(d, v) \ 112*01b2a7fcSCarlo Caione (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) 113*01b2a7fcSCarlo Caione 114*01b2a7fcSCarlo Caione static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len, 115*01b2a7fcSCarlo Caione int finalize) 116*01b2a7fcSCarlo Caione { 117*01b2a7fcSCarlo Caione /* Make it cache line size aligned ? */ 118*01b2a7fcSCarlo Caione struct asd_desc desc = { 119*01b2a7fcSCarlo Caione .src = (uint32_t)(uintptr_t)data, 120*01b2a7fcSCarlo Caione .dst = (uint32_t)(uintptr_t)ctx->digest, 121*01b2a7fcSCarlo Caione }; 122*01b2a7fcSCarlo Caione 123*01b2a7fcSCarlo Caione /* Check data address is 32bit compatible */ 124*01b2a7fcSCarlo Caione assert((uintptr_t)data == (uintptr_t)desc.src); 125*01b2a7fcSCarlo Caione assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst); 126*01b2a7fcSCarlo Caione assert((uintptr_t)&desc == (uintptr_t)&desc); 127*01b2a7fcSCarlo Caione 128*01b2a7fcSCarlo Caione ASD_DESC_LEN_SET(&desc, len); 129*01b2a7fcSCarlo Caione ASD_DESC_OWNER_SET(&desc, 1u); 130*01b2a7fcSCarlo Caione ASD_DESC_ENCONLY_SET(&desc, 1); 131*01b2a7fcSCarlo Caione ASD_DESC_EOD_SET(&desc, 1); 132*01b2a7fcSCarlo Caione if (ctx->started == 0) { 133*01b2a7fcSCarlo Caione ASD_DESC_BEGIN_SET(&desc, 1); 134*01b2a7fcSCarlo Caione ctx->started = 1; 135*01b2a7fcSCarlo Caione } 136*01b2a7fcSCarlo Caione if (finalize) { 137*01b2a7fcSCarlo Caione ASD_DESC_END_SET(&desc, 1); 138*01b2a7fcSCarlo Caione ctx->started = 0; 139*01b2a7fcSCarlo Caione } 140*01b2a7fcSCarlo Caione if (ctx->mode == ASM_SHA224) 141*01b2a7fcSCarlo Caione ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224); 142*01b2a7fcSCarlo Caione else 143*01b2a7fcSCarlo Caione ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256); 144*01b2a7fcSCarlo Caione 145*01b2a7fcSCarlo Caione flush_dcache_range((uintptr_t)&desc, sizeof(desc)); 146*01b2a7fcSCarlo Caione flush_dcache_range((uintptr_t)data, len); 147*01b2a7fcSCarlo Caione 148*01b2a7fcSCarlo Caione mmio_write_32(AML_SHA_DMA_STATUS, 0xf); 149*01b2a7fcSCarlo Caione mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2); 150*01b2a7fcSCarlo Caione while (mmio_read_32(AML_SHA_DMA_STATUS) == 0) 151*01b2a7fcSCarlo Caione continue; 152*01b2a7fcSCarlo Caione flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ); 153*01b2a7fcSCarlo Caione } 154*01b2a7fcSCarlo Caione 155*01b2a7fcSCarlo Caione void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len) 156*01b2a7fcSCarlo Caione { 157*01b2a7fcSCarlo Caione size_t nr; 158*01b2a7fcSCarlo Caione 159*01b2a7fcSCarlo Caione if (ctx->blocksz) { 160*01b2a7fcSCarlo Caione nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz); 161*01b2a7fcSCarlo Caione memcpy(ctx->block + ctx->blocksz, data, nr); 162*01b2a7fcSCarlo Caione ctx->blocksz += nr; 163*01b2a7fcSCarlo Caione len -= nr; 164*01b2a7fcSCarlo Caione data += nr; 165*01b2a7fcSCarlo Caione } 166*01b2a7fcSCarlo Caione 167*01b2a7fcSCarlo Caione if (ctx->blocksz == SHA256_BLOCKSZ) { 168*01b2a7fcSCarlo Caione asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0); 169*01b2a7fcSCarlo Caione ctx->blocksz = 0; 170*01b2a7fcSCarlo Caione } 171*01b2a7fcSCarlo Caione 172*01b2a7fcSCarlo Caione asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0); 173*01b2a7fcSCarlo Caione data += len & ~(SHA256_BLOCKSZ - 1); 174*01b2a7fcSCarlo Caione 175*01b2a7fcSCarlo Caione if (len & (SHA256_BLOCKSZ - 1)) { 176*01b2a7fcSCarlo Caione nr = len & (SHA256_BLOCKSZ - 1); 177*01b2a7fcSCarlo Caione memcpy(ctx->block + ctx->blocksz, data, nr); 178*01b2a7fcSCarlo Caione ctx->blocksz += nr; 179*01b2a7fcSCarlo Caione } 180*01b2a7fcSCarlo Caione } 181*01b2a7fcSCarlo Caione 182*01b2a7fcSCarlo Caione void asd_sha_finalize(struct asd_ctx *ctx) 183*01b2a7fcSCarlo Caione { 184*01b2a7fcSCarlo Caione asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1); 185*01b2a7fcSCarlo Caione } 186