blob: 25f8cd028d42209548847a5cda8d8ad64cf8bc2e [file] [log] [blame]
Jeetesh Burman50cd1062018-07-19 13:07:23 +05301/*
2 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <drivers/delay_timer.h>
9#include <errno.h>
10#include <string.h>
11
12#include <bpmp_ipc.h>
13#include <pmc.h>
14#include <security_engine.h>
Jeetesh Burman50cd1062018-07-19 13:07:23 +053015#include <tegra_private.h>
16
17#include "se_private.h"
18
19/*******************************************************************************
20 * Constants and Macros
21 ******************************************************************************/
22#define SE0_MAX_BUSY_TIMEOUT_MS U(100) /* 100ms */
23#define BYTES_IN_WORD U(4)
24#define SHA256_MAX_HASH_RESULT U(7)
25#define SHA256_DST_SIZE U(32)
26#define SHA_FIRST_OP U(1)
27#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF)
28#define SHA256_MSG_LENGTH_ONETIME U(0xffff)
29
30/*
31 * Check that SE operation has completed after kickoff
32 * This function is invoked after an SE operation has been started,
33 * and it checks the following conditions:
34 * 1. SE0_INT_STATUS = SE0_OP_DONE
35 * 2. SE0_STATUS = IDLE
36 * 3. SE0_ERR_STATUS is clean.
37 */
38static int32_t tegra_se_operation_complete(void)
39{
40 uint32_t val = 0U;
41
42 /* Read SE0 interrupt register to ensure H/W operation complete */
43 val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
44 if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
45 ERROR("%s: Engine busy state too many times! val = 0x%x\n",
46 __func__, val);
47 return -ETIMEDOUT;
48 }
49
50 /* Read SE0 status idle to ensure H/W operation complete */
51 val = tegra_se_read_32(SE0_SHA_STATUS_0);
52 if (val != SE0_SHA_STATUS_IDLE) {
53 ERROR("%s: Idle state timeout! val = 0x%x\n", __func__,
54 val);
55 return -ETIMEDOUT;
56 }
57
58 /* Ensure that no errors are thrown during operation */
59 val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
60 if (val != SE0_ERR_STATUS_CLEAR) {
61 ERROR("%s: Error during SE operation! val = 0x%x",
62 __func__, val);
63 return -ENOTSUP;
64 }
65
66 return 0;
67}
68
69/*
70 * Security engine primitive normal operations
71 */
72static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
73 uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
74{
75 int32_t ret = 0;
76 uint32_t val = 0U;
77 uint32_t src_in_lo;
78 uint32_t src_in_msb;
79 uint32_t src_in_hi;
80
81 if ((src_addr == 0UL) || (nbytes == 0U))
82 return -EINVAL;
83
84 src_in_lo = (uint32_t)src_addr;
85 src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU);
86 src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
87 (nbytes & 0xffffffU));
88
89 /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
90 tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
91 tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
92
93 val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
94 if (val > 0U) {
95 tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U);
96 }
97
98 /* Enable SHA interrupt for SE0 Operation */
99 tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
100
101 /* flush to DRAM for SE to use the updated contents */
102 flush_dcache_range(src_addr, src_len_inbytes);
103
104 /* Start SHA256 operation */
105 if (last_buf == 1U) {
106 tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
107 SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
108 } else {
109 tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
110 }
111
112 /* Wait for SE-operation to finish */
113 udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U);
114
115 /* Check SE0 operation status */
116 ret = tegra_se_operation_complete();
117 if (ret != 0) {
118 ERROR("SE operation complete Failed! 0x%x", ret);
119 return ret;
120 }
121
122 return 0;
123}
124
125static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
126 uint32_t src_len_inbyte)
127{
128 uint32_t val, last_buf, i;
129 int32_t ret = 0;
130 uint32_t operations;
131 uint64_t src_len_inbits;
132 uint32_t len_bits_msb;
133 uint32_t len_bits_lsb;
134 uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
135
136 if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
137 ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
138 return -EINVAL;
139 }
140
141 if (src_addr == 0UL) {
142 return -EINVAL;
143 }
144
145 /* number of bytes per operation */
146 max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME;
147
148 src_len_inbits = src_len_inbyte * 8U;
149 len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
150 len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF);
151
152 /* program SE0_CONFIG for SHA256 operation */
153 val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
154 SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG;
155 tegra_se_write_32(SE0_SHA_CONFIG, val);
156
157 /* set SE0_SHA_MSG_LENGTH registers */
158 tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
159 tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
160 tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
161
162 /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
163 tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
164 tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
165 tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
166 tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
167 tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
168
169 number_of_operations = src_len_inbyte / max_bytes;
170 remaining_bytes = src_len_inbyte % max_bytes;
171 if (remaining_bytes > 0U) {
172 number_of_operations += 1U;
173 }
174
175 /*
176 * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256
177 * hash generation by setting
178 * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
179 * and start SHA256-normal operation.
180 * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
181 * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
182 * intermediate SHA256 digest result from
183 * HASH_RESULT register to continue SHA256
184 * generation and start SHA256-normal operation.
185 * 3. Operations == number_of_operations: continue with step 2 and set
186 * max_bytes to bytes_left to process final
187 * hash-result generation and
188 * start SHA256-normal operation.
189 */
190 bytes_left = src_len_inbyte;
191 for (operations = 1U; operations <= number_of_operations;
192 operations++) {
193 if (operations == SHA_FIRST_OP) {
194 val = SE0_SHA_CONFIG_HW_INIT_HASH;
195 } else {
196 /* Load intermediate SHA digest result to
197 * SHA:HASH_RESULT(0..7) to continue the SHA
198 * calculation and tell the SHA engine to use it.
199 */
200 for (i = 0U; (i / BYTES_IN_WORD) <=
201 SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
202 val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
203 i);
204 tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
205 val);
206 }
207 val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
208 if (len_bits_lsb <= (max_bytes * 8U)) {
209 len_bits_lsb = (remaining_bytes * 8U);
210 } else {
211 len_bits_lsb -= (max_bytes * 8U);
212 }
213 tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
214 }
215 tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
216
217 max_bytes = (SHA256_HASH_SIZE_BYTES *
218 SHA256_MSG_LENGTH_ONETIME);
219 if (bytes_left < max_bytes) {
220 max_bytes = bytes_left;
221 last_buf = 1U;
222 } else {
223 bytes_left = bytes_left - max_bytes;
224 last_buf = 0U;
225 }
226 /* start operation */
227 ret = tegra_se_start_normal_operation(src_addr, max_bytes,
228 last_buf, src_len_inbyte);
229 if (ret != 0) {
230 ERROR("Error during SE operation! 0x%x", ret);
231 return -EINVAL;
232 }
233 }
234
235 return ret;
236}
237
238/*
239 * Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register.
240 */
241int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte)
242{
243 int32_t ret = 0;
244 uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security;
245
246 /*
247 * Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
248 * registers.
249 */
250 security = tegra_se_read_32(SE0_SECURITY);
251 tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
252
253 ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte);
254 if (ret != 0L) {
255 ERROR("%s: SHA256 generation failed\n", __func__);
256 return ret;
257 }
258
259 /*
260 * Reset SE_SECURE to previous value.
261 */
262 tegra_se_write_32(SE0_SECURITY, security);
263
264 /* read SHA256_HASH_RESULT and save to PMC Scratch registers */
265 scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
266 while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) {
267
268 val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
269 mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val);
270
271 hash_offset += BYTES_IN_WORD;
272 scratch_offset += BYTES_IN_WORD;
273 }
274
275 return ret;
276}
277