1 /*
2 * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include "unity.h"
9
10 #include "soc/soc_caps.h"
11
12 #if SOC_DIG_SIGN_SUPPORTED
13 #if CONFIG_IDF_TARGET_ESP32S2
14 #include "esp32s2/rom/efuse.h"
15 #include "esp32s2/rom/digital_signature.h"
16 #include "esp32s2/rom/aes.h"
17 #include "esp32s2/rom/sha.h"
18 #elif CONFIG_IDF_TARGET_ESP32C3
19 #include "esp32c3/rom/efuse.h"
20 #include "esp32c3/rom/digital_signature.h"
21 #include "esp32c3/rom/hmac.h"
22 #elif CONFIG_IDF_TARGET_ESP32S3
23 #include "esp32s3/rom/efuse.h"
24 #include "esp32s3/rom/digital_signature.h"
25 #include "esp32s3/rom/aes.h"
26 #include "esp32s3/rom/sha.h"
27 #endif
28
29 #include "esp_ds.h"
30
31 #define NUM_RESULTS 10
32
33 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
34 #define DS_MAX_BITS (4096)
35 #elif CONFIG_IDF_TARGET_ESP32C3
36 #define DS_MAX_BITS (ETS_DS_MAX_BITS)
37 #endif
38
39 typedef struct {
40 uint8_t iv[ETS_DS_IV_LEN];
41 ets_ds_p_data_t p_data;
42 uint8_t expected_c[ETS_DS_C_LEN];
43 uint8_t hmac_key_idx;
44 uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS / 32];
45 } encrypt_testcase_t;
46
47 // Generated header digital_signature_test_cases_<bits>.h (by gen_digital_signature_tests.py) defines
48 // NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[]
49 // Some adaptations were made: removed the 512 bit case and changed RSA lengths to the enums from esp_ds.h
50 #if DS_MAX_BITS == 4096
51 #define RSA_LEN (ESP_DS_RSA_4096)
52 #include "digital_signature_test_cases_4096.h"
53 #elif DS_MAX_BITS == 3072
54 #define RSA_LEN (ESP_DS_RSA_3072)
55 #include "digital_signature_test_cases_3072.h"
56 #endif
57
58 _Static_assert(NUM_RESULTS == NUM_MESSAGES, "expected_results size should be the same as NUM_MESSAGES in generated header");
59
60 TEST_CASE("Digital Signature Parameter Encryption data NULL", "[hw_crypto] [ds]")
61 {
62 const char iv [32];
63 esp_ds_p_data_t p_data;
64 const char key [32];
65
66 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(NULL, iv, &p_data, key));
67 }
68
69 TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]")
70 {
71 esp_ds_data_t data;
72 esp_ds_p_data_t p_data;
73 const char key [32];
74
75 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, NULL, &p_data, key));
76 }
77
78 TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds]")
79 {
80 esp_ds_data_t data;
81 const char iv [32];
82 const char key [32];
83
84 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, NULL, key));
85 }
86
87 TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]")
88 {
89 esp_ds_data_t data;
90 const char iv [32];
91 esp_ds_p_data_t p_data;
92
93 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, &p_data, NULL));
94 }
95
96 TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]")
97 {
98 for (int i = 0; i < NUM_CASES; i++) {
99 printf("Encrypting test case %d...\n", i);
100 const encrypt_testcase_t *t = &test_cases[i];
101 esp_ds_data_t result = { };
102 esp_ds_p_data_t p_data;
103
104 memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS / 8);
105 memcpy(p_data.M, t->p_data.M, DS_MAX_BITS / 8);
106 memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS / 8);
107 p_data.M_prime = t->p_data.M_prime;
108 p_data.length = t->p_data.length;
109
110 esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data,
111 test_hmac_keys[t->hmac_key_idx]);
112 printf("Encrypting test case %d done\n", i);
113 TEST_ASSERT_EQUAL(ESP_OK, r);
114 TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length);
115 TEST_ASSERT_EQUAL_HEX8_ARRAY(t->iv, result.iv, ETS_DS_IV_LEN);
116 TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_c, result.c, ETS_DS_C_LEN);
117 }
118 }
119
120 TEST_CASE("Digital Signature start Invalid message", "[hw_crypto] [ds]")
121 {
122 esp_ds_data_t ds_data = { };
123 ds_data.rsa_length = RSA_LEN;
124 esp_ds_context_t *ctx;
125
126 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(NULL, &ds_data, HMAC_KEY1, &ctx));
127 }
128
129 TEST_CASE("Digital Signature start Invalid data", "[hw_crypto] [ds]")
130 {
131 const char *message = "test";
132 esp_ds_context_t *ctx;
133
134 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, NULL, HMAC_KEY1, &ctx));
135 }
136
137 TEST_CASE("Digital Signature start Invalid context", "[hw_crypto] [ds]")
138 {
139 esp_ds_data_t ds_data = {};
140 ds_data.rsa_length = RSA_LEN;
141 const char *message = "test";
142
143 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
144 }
145
146 TEST_CASE("Digital Signature RSA length 0", "[hw_crypto] [ds]")
147 {
148 esp_ds_data_t ds_data = {};
149 ds_data.rsa_length = 0;
150 const char *message = "test";
151
152 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
153 }
154
155 TEST_CASE("Digital Signature RSA length too long", "[hw_crypto] [ds]")
156 {
157 esp_ds_data_t ds_data = {};
158 ds_data.rsa_length = 128;
159 const char *message = "test";
160
161 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
162 }
163
164 TEST_CASE("Digital Signature start HMAC key out of range", "[hw_crypto] [ds]")
165 {
166 esp_ds_data_t ds_data = {};
167 ds_data.rsa_length = RSA_LEN;
168 esp_ds_context_t *ctx;
169 const char *message = "test";
170
171 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY5 + 1, &ctx));
172 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY0 - 1, &ctx));
173 }
174
175 TEST_CASE("Digital Signature finish Invalid signature ptr", "[hw_crypto] [ds]")
176 {
177 esp_ds_context_t *ctx = NULL;
178
179 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(NULL, ctx));
180 }
181
182 TEST_CASE("Digital Signature finish Invalid context", "[hw_crypto] [ds]")
183 {
184 uint8_t signature_data [128 * 4];
185
186 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(signature_data, NULL));
187 }
188
189 TEST_CASE("Digital Signature Blocking Invalid message", "[hw_crypto] [ds]")
190 {
191 esp_ds_data_t ds_data = { };
192 ds_data.rsa_length = RSA_LEN;
193 uint8_t signature_data [128 * 4];
194
195 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(NULL, &ds_data, HMAC_KEY1, signature_data));
196 }
197
198 TEST_CASE("Digital Signature Blocking Invalid data", "[hw_crypto] [ds]")
199 {
200 const char *message = "test";
201 uint8_t signature_data [128 * 4];
202
203 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, NULL, HMAC_KEY1, signature_data));
204 }
205
206 TEST_CASE("Digital Signature Blocking Invalid signature ptr", "[hw_crypto] [ds]")
207 {
208 esp_ds_data_t ds_data = {};
209 ds_data.rsa_length = RSA_LEN;
210 const char *message = "test";
211
212 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, NULL));
213 }
214
215 TEST_CASE("Digital Signature Blocking RSA length 0", "[hw_crypto] [ds]")
216 {
217 esp_ds_data_t ds_data = {};
218 ds_data.rsa_length = 0;
219 const char *message = "test";
220 uint8_t signature_data [128 * 4];
221
222 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
223 }
224
225 TEST_CASE("Digital Signature Blocking RSA length too long", "[hw_crypto] [ds]")
226 {
227 esp_ds_data_t ds_data = {};
228 ds_data.rsa_length = 128;
229 const char *message = "test";
230 uint8_t signature_data [128 * 4];
231
232 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
233 }
234
235 TEST_CASE("Digital Signature Blocking HMAC key out of range", "[hw_crypto] [ds]")
236 {
237 esp_ds_data_t ds_data = {};
238 ds_data.rsa_length = 127;
239 const char *message = "test";
240 uint8_t signature_data [128 * 4];
241
242 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY5 + 1, signature_data));
243 TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY0 - 1, signature_data));
244 }
245
246 #if CONFIG_IDF_ENV_FPGA
247
burn_hmac_keys(void)248 static void burn_hmac_keys(void)
249 {
250 printf("Burning %d HMAC keys to efuse...\n", NUM_HMAC_KEYS);
251 for (int i = 0; i < NUM_HMAC_KEYS; i++) {
252 // TODO: vary the purpose across the keys
253 ets_efuse_purpose_t purpose = ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE;
254
255 // starting from block 1, block 0 occupied with HMAC upstream test key
256 int __attribute__((unused)) ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i,
257 purpose,
258 test_hmac_keys[i], 32);
259
260 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
261 if (ets_status == ESP_OK) {
262 printf("written DS test key to block [%d]!\n", ETS_EFUSE_BLOCK_KEY1 + i);
263 } else {
264 printf("writing DS test key to block [%d] failed, maybe written already\n", ETS_EFUSE_BLOCK_KEY1 + i);
265 }
266 #endif
267 }
268 #if CONFIG_IDF_TARGET_ESP32C3
269 /* verify the keys are what we expect (possibly they're already burned, doesn't matter but they have to match) */
270 uint8_t block_compare[32];
271 for (int i = 0; i < NUM_HMAC_KEYS; i++) {
272 printf("Checking key %d...\n", i);
273 memcpy(block_compare, (void *)ets_efuse_get_read_register_address(ETS_EFUSE_BLOCK_KEY1 + i), 32);
274 TEST_ASSERT_EQUAL_HEX8_ARRAY(test_hmac_keys[i], block_compare, 32);
275 }
276 #endif
277 }
278
279 // This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
280 // HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
281 TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
282 {
283 esp_ds_data_t ds_data = {};
284 ds_data.rsa_length = RSA_LEN;
285 esp_ds_context_t *ctx;
286 const char *message = "test";
287
288 // HMAC fails in that case because it checks for the correct purpose
289 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
290 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx));
291 #elif CONFIG_IDF_TARGET_ESP32C3
292 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx));
293 #endif
294 }
295
296 // This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
297 // HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
298 TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
299 {
300 esp_ds_data_t ds_data = {};
301 ds_data.rsa_length = RSA_LEN;
302 const char *message = "test";
303 uint8_t signature_data [128 * 4];
304
305 // HMAC fails in that case because it checks for the correct purpose
306 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
307 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data));
308 #elif CONFIG_IDF_TARGET_ESP32C3
309 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data));
310 #endif
311 }
312
313 TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]")
314 {
315 burn_hmac_keys();
316
317 for (int i = 0; i < NUM_CASES; i++) {
318 printf("Running test case %d...\n", i);
319 const encrypt_testcase_t *t = &test_cases[i];
320
321 // copy encrypt parameter test case into ds_data structure
322 esp_ds_data_t ds_data = { };
323 memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
324 memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
325 ds_data.rsa_length = t->p_data.length;
326
327 for (int j = 0; j < NUM_MESSAGES; j++) {
328 uint8_t signature[DS_MAX_BITS / 8] = { 0 };
329 printf(" ... message %d\n", j);
330
331 esp_ds_context_t *esp_ds_ctx;
332
333 esp_err_t ds_r = esp_ds_start_sign(test_messages[j],
334 &ds_data,
335 t->hmac_key_idx + 1,
336 &esp_ds_ctx);
337 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
338
339 ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
340 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
341
342 TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[j], signature, sizeof(signature));
343 }
344 #if CONFIG_IDF_TARGET_ESP32C3
345 ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
346 #endif
347 }
348 }
349
350 TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]")
351 {
352 burn_hmac_keys();
353
354 for (int i = 0; i < NUM_CASES; i++) {
355 printf("Running test case %d...\n", i);
356 const encrypt_testcase_t *t = &test_cases[i];
357
358 // copy encrypt parameter test case into ds_data structure
359 esp_ds_data_t ds_data = { };
360 memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
361 memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
362 ds_data.rsa_length = t->p_data.length;
363
364 uint8_t signature[DS_MAX_BITS / 8] = { 0 };
365 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
366 esp_ds_context_t *esp_ds_ctx;
367
368 esp_err_t ds_r = esp_ds_start_sign(test_messages[0],
369 &ds_data,
370 t->hmac_key_idx + 1,
371 &esp_ds_ctx);
372 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
373
374 ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
375 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
376 #elif CONFIG_IDF_TARGET_ESP32C3
377 esp_err_t ds_r = esp_ds_sign(test_messages[0],
378 &ds_data,
379 t->hmac_key_idx + 1,
380 signature);
381 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
382 #endif
383
384 TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[0], signature, sizeof(signature));
385 }
386 }
387
388 TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
389 {
390 burn_hmac_keys();
391
392 // Set up a valid test case
393 const encrypt_testcase_t *t = &test_cases[0];
394 esp_ds_data_t ds_data = { };
395 memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
396 memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
397 ds_data.rsa_length = t->p_data.length;
398
399 uint8_t signature[DS_MAX_BITS / 8] = { 0 };
400 const uint8_t zero[DS_MAX_BITS / 8] = { 0 };
401
402 // Corrupt the IV one bit at a time, rerun and expect failure
403 for (int bit = 0; bit < 128; bit++) {
404 printf("Corrupting IV bit %d...\n", bit);
405 ds_data.iv[bit / 8] ^= 1 << (bit % 8);
406 esp_ds_context_t *esp_ds_ctx;
407
408 esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
409 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
410 ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
411 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
412 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
413 #elif CONFIG_IDF_TARGET_ESP32C3
414 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
415 #endif
416 TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
417
418 ds_data.iv[bit / 8] ^= 1 << (bit % 8);
419 }
420
421 // Corrupt encrypted key data one bit at a time, rerun and expect failure
422 printf("Corrupting C...\n");
423 for (int bit = 0; bit < ETS_DS_C_LEN * 8; bit++) {
424 printf("Corrupting C bit %d...\n", bit);
425 ds_data.c[bit / 8] ^= 1 << (bit % 8);
426 esp_ds_context_t *esp_ds_ctx;
427
428 esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
429 TEST_ASSERT_EQUAL(ESP_OK, ds_r);
430 ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
431 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
432 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
433 #elif CONFIG_IDF_TARGET_ESP32C3
434 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
435 #endif
436 TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
437
438 ds_data.c[bit / 8] ^= 1 << (bit % 8);
439 }
440 }
441
442 #endif // CONFIG_IDF_ENV_FPGA
443 #endif // SOC_DIG_SIGN_SUPPORTED
444