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