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