Skip to content

Commit 5217521

Browse files
committed
feat(core/prodtest): introduce prodtest error codes
1 parent 108189e commit 5217521

32 files changed

Lines changed: 2866 additions & 345 deletions

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ hsm_keys:
199199
hsm_keys_check:
200200
./core/tools/generate_hsm_keys.py --check
201201

202-
gen: templates mocks icons protobuf vendorheader solana_templates bootloader_hashes lsgen tropic_model_config hsm_keys ## regenerate auto-generated files from sources
202+
prodtest_error_codes: ## generate prodtest error codes JSON
203+
python3 core/tools/prodtest_error_codes.py
203204

204-
gen_check: templates_check mocks_check icons_check protobuf_check vendorheader_check solana_templates_check bootloader_hashes_check lsgen_check tropic_model_config_check hsm_keys_check ## check validity of auto-generated files
205+
prodtest_error_codes_check: ## check prodtest error codes JSON is up to date
206+
python3 core/tools/prodtest_error_codes.py --check
207+
208+
gen: templates mocks icons protobuf vendorheader solana_templates bootloader_hashes lsgen tropic_model_config hsm_keys prodtest_error_codes ## regenerate auto-generated files from sources
209+
210+
gen_check: templates_check mocks_check icons_check protobuf_check vendorheader_check solana_templates_check bootloader_hashes_check lsgen_check tropic_model_config_check hsm_keys_check prodtest_error_codes_check ## check validity of auto-generated files
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduce prodtest error codes.

core/embed/projects/prodtest/cmd/common.c

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
224224
const uint8_t** authority_key_digest) {
225225
DER_ITEM extensions = {0};
226226
if (!get_cert_extensions(tbs_cert, &extensions)) {
227-
cli_error(cli, CLI_ERROR,
227+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_EXTENSIONS,
228228
"get_authority_key_digest, extensions not found.");
229229
return false;
230230
}
@@ -234,7 +234,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
234234
if (!get_extension_value(OID_AUTHORITY_KEY_IDENTIFIER,
235235
sizeof(OID_AUTHORITY_KEY_IDENTIFIER), &extensions,
236236
&extension_value)) {
237-
cli_error(cli, CLI_ERROR,
237+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_NOT_FOUND,
238238
"get_authority_key_digest, authority key identifier extension "
239239
"not found.");
240240
return false;
@@ -244,7 +244,7 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
244244
DER_ITEM auth_key_id = {0};
245245
if (!der_read_item_expected(&extension_value.buf, DER_SEQUENCE,
246246
&auth_key_id)) {
247-
cli_error(cli, CLI_ERROR,
247+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_EXTNVALUE,
248248
"get_authority_key_digest, failed to open authority key "
249249
"identifier extnValue.");
250250
return false;
@@ -254,15 +254,15 @@ static bool get_authority_key_digest(cli_t* cli, DER_ITEM* tbs_cert,
254254
DER_ITEM key_id = {0};
255255
if (!der_read_item_expected(&auth_key_id.buf, DER_X509_KEY_IDENTIFIER,
256256
&key_id)) {
257-
cli_error(cli, CLI_ERROR,
257+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_FIELD,
258258
"get_authority_key_digest, failed to find keyIdentifier field.");
259259
return false;
260260
}
261261

262262
// Return the pointer to the keyIdentifier data.
263263
if (buffer_remaining(&key_id.buf) != SHA1_DIGEST_LENGTH ||
264264
!buffer_ptr(&key_id.buf, authority_key_digest)) {
265-
cli_error(cli, CLI_ERROR,
265+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_AUTH_KEY_LEN,
266266
"get_authority_key_digest, invalid length of keyIdentifier.");
267267
return false;
268268
}
@@ -442,7 +442,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
442442
cert_count += 1;
443443
DER_ITEM cert = {0};
444444
if (!der_read_item_expected(&chain_reader, DER_SEQUENCE, &cert)) {
445-
cli_error(cli, CLI_ERROR,
445+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_CERT,
446446
"check_device_cert_chain, der_read_item 1, cert %d.",
447447
cert_count);
448448
return false;
@@ -451,7 +451,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
451451
// Read the tbsCertificate.
452452
DER_ITEM tbs_cert = {0};
453453
if (!der_read_item_expected(&cert.buf, DER_SEQUENCE, &tbs_cert)) {
454-
cli_error(cli, CLI_ERROR,
454+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS,
455455
"check_device_cert_chain, der_read_item 2, cert %d.",
456456
cert_count);
457457
return false;
@@ -461,7 +461,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
461461
DER_ITEM der_item = {0};
462462
for (int i = 0; i < 5; ++i) {
463463
if (!der_read_item(&tbs_cert.buf, &der_item)) {
464-
cli_error(cli, CLI_ERROR,
464+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_TBS_PRELUDE,
465465
"check_device_cert_chain, der_read_item 3, cert %d.",
466466
cert_count);
467467
return false;
@@ -471,7 +471,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
471471
// Read the subject.
472472
DER_ITEM subject = {0};
473473
if (!der_read_item_expected(&tbs_cert.buf, DER_SEQUENCE, &subject)) {
474-
cli_error(cli, CLI_ERROR,
474+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SUBJECT,
475475
"check_device_cert_chain, der_read_item 4, cert %d.",
476476
cert_count);
477477
return false;
@@ -487,7 +487,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
487487
common_name_size != sizeof(SUBJECT_COMMON_NAME) ||
488488
memcmp(common_name, SUBJECT_COMMON_NAME,
489489
sizeof(SUBJECT_COMMON_NAME)) != 0) {
490-
cli_error(cli, CLI_ERROR,
490+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_COMMON_NAME,
491491
"check_device_cert_chain, invalid common name.");
492492
return false;
493493
}
@@ -499,7 +499,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
499499
if (!unit_properties_get_sn(device_sn, sizeof(device_sn),
500500
&device_sn_size) ||
501501
device_sn_size == 0) {
502-
cli_error(cli, CLI_ERROR,
502+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_DEVICE_SN,
503503
"check_device_cert_chain, device_sn not set.");
504504
}
505505

@@ -508,13 +508,13 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
508508
if (!get_name_attribute(&subject, OID_SERIAL_NUMBER,
509509
sizeof(OID_SERIAL_NUMBER), &subject_sn,
510510
&subject_sn_size)) {
511-
cli_error(cli, CLI_ERROR,
511+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SERIAL_NUM,
512512
"check_device_cert_chain, serialNumber not set.");
513513
}
514514

515515
if (subject_sn_size != device_sn_size ||
516516
memcmp(subject_sn, device_sn, device_sn_size) != 0) {
517-
cli_error(cli, CLI_ERROR,
517+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SN_MISMATCH,
518518
"check_device_cert_chain, serial number mismatch.");
519519
return false;
520520
}
@@ -524,7 +524,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
524524
// Read the Subject Public Key Info.
525525
DER_ITEM pub_key_info = {0};
526526
if (!der_read_item_expected(&tbs_cert.buf, DER_SEQUENCE, &pub_key_info)) {
527-
cli_error(cli, CLI_ERROR,
527+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SPKI,
528528
"check_device_cert_chain, der_read_item 5, cert %d.",
529529
cert_count);
530530
return false;
@@ -534,7 +534,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
534534
DER_ITEM alg = {0};
535535
if (!der_read_item_expected(&pub_key_info.buf, DER_SEQUENCE, &alg) ||
536536
!get_algorithm(&alg, &alg_id)) {
537-
cli_error(cli, CLI_ERROR,
537+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ALGORITHM,
538538
"check_device_cert_chain, reading algorithm, cert %d.",
539539
cert_count);
540540
return false;
@@ -545,15 +545,15 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
545545
uint8_t unused_bits = 0;
546546
if (!der_read_item_expected(&pub_key_info.buf, DER_BIT_STRING,
547547
&pub_key_val)) {
548-
cli_error(cli, CLI_ERROR,
548+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_PUBKEY_BITS,
549549
"check_device_cert_chain, der_read_item 6, cert %d.",
550550
cert_count);
551551
return false;
552552
}
553553

554554
if (!buffer_get(&pub_key_val.buf, &unused_bits) ||
555555
!buffer_ptr(&pub_key_val.buf, &pub_key)) {
556-
cli_error(cli, CLI_ERROR,
556+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_PUBKEY,
557557
"check_device_cert_chain, reading public key, cert %d.",
558558
cert_count);
559559
return false;
@@ -563,7 +563,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
563563
// Verify the previous signature.
564564
if (!verify_signature(alg_id, pub_key, pub_key_size, sig, sig_size, message,
565565
message_size)) {
566-
cli_error(cli, CLI_ERROR,
566+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_VERIFY_SIG,
567567
"check_device_cert_chain, verify_signature, cert %d.",
568568
cert_count);
569569
return false;
@@ -583,7 +583,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
583583
// skip the signatureAlgorithm
584584
DER_ITEM sig_alg = {0};
585585
if (!der_read_item_expected(&cert.buf, DER_SEQUENCE, &sig_alg)) {
586-
cli_error(cli, CLI_ERROR,
586+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_READ_SIG_ALG,
587587
"check_device_cert_chain, der_read_item 7, cert %d.", "%d.",
588588
cert_count);
589589
return false;
@@ -594,7 +594,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
594594
if (!der_read_item_expected(&cert.buf, DER_BIT_STRING, &sig_val) ||
595595
!buffer_get(&sig_val.buf, &unused_bits) || unused_bits != 0 ||
596596
!buffer_ptr(&sig_val.buf, &sig)) {
597-
cli_error(cli, CLI_ERROR,
597+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_SIG_VALUE,
598598
"check_device_cert_chain, reading signatureValue, cert %d.",
599599
cert_count);
600600
return false;
@@ -612,7 +612,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
612612

613613
uint8_t decoded_sig[64] = {0};
614614
if (ecdsa_sig_from_der(sig, sig_size, decoded_sig) != 0) {
615-
cli_error(cli, CLI_ERROR,
615+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_DER,
616616
"check_device_cert_chain, ecdsa_sig_from_der root.");
617617
return false;
618618
}
@@ -632,7 +632,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
632632
}
633633
}
634634
if (!matches) {
635-
cli_error(cli, CLI_ERROR,
635+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ECDSA_ROOT,
636636
"check_device_cert_chain, ecdsa_verify_digest root.");
637637
return false;
638638
}
@@ -643,7 +643,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
643643
const char msg[] =
644644
"check_device_cert_chain, failed to get root public key.";
645645
#if PRODUCTION
646-
cli_error(cli, CLI_ERROR, msg);
646+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_KEY, msg);
647647
return false;
648648
#else
649649
// In non-production mode we succeed and write the certificate even if the
@@ -656,7 +656,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
656656
// Verify the last signature.
657657
if (!verify_signature(alg_id, pub_key, pub_key_size, sig, sig_size, message,
658658
message_size)) {
659-
cli_error(cli, CLI_ERROR,
659+
cli_error(cli, PRODTEST_ERR_COMMON_CERT_CHAIN_ROOT_SIG,
660660
"check_device_cert_chain, verify_signature, cert %d.",
661661
cert_count);
662662
return false;
@@ -708,7 +708,8 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
708708
}
709709

710710
if (!binary_update_in_progress) {
711-
cli_error(cli, CLI_ERROR, "Update not started. Use 'begin' first.");
711+
cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_NOT_STARTED,
712+
"Update not started. Use 'begin' first.");
712713
goto cleanup;
713714
}
714715

@@ -732,13 +733,14 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
732733
}
733734

734735
if (binary_len == 0) {
735-
cli_error(cli, CLI_ERROR, "No data received");
736+
cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_NO_DATA, "No data received");
736737
goto cleanup;
737738
}
738739

739740
if (!finalize(binary_buffer, binary_len)) {
740741
binary_len = 0;
741-
cli_error(cli, CLI_ERROR, "Error while finalizing the update");
742+
cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_FINALIZE,
743+
"Error while finalizing the update");
742744
goto cleanup;
743745
}
744746

@@ -750,7 +752,8 @@ void binary_update(cli_t* cli, bool (*finalize)(uint8_t* data, size_t len)) {
750752
binary_update_in_progress = false;
751753

752754
} else {
753-
cli_error(cli, CLI_ERROR, "Unknown phase '%s' (begin|chunk|end)", phase);
755+
cli_error(cli, PRODTEST_ERR_COMMON_UPDATE_UNKNOWN_PHASE,
756+
"Unknown phase '%s' (begin|chunk|end)", phase);
754757
goto cleanup;
755758
}
756759

core/embed/projects/prodtest/cmd/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#include <rtl/cli.h>
2323

24+
#include "prodtest_error_codes.h"
25+
2426
#define CHALLENGE_SIZE 16
2527

2628
bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,

core/embed/projects/prodtest/cmd/prodtest_backup_ram.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,17 @@
2626
#include <sec/backup_ram.h>
2727
#include <sys/systick.h>
2828

29+
#include "prodtest_error_codes.h"
30+
2931
static void prodtest_backup_ram_list(cli_t* cli) {
3032
if (cli_arg_count(cli) > 0) {
3133
cli_error_arg_count(cli);
3234
return;
3335
}
3436

3537
if (!backup_ram_init()) {
36-
cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
38+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_LIST_INIT,
39+
"Failed to initialize backup RAM");
3740
return;
3841
}
3942

@@ -45,7 +48,8 @@ static void prodtest_backup_ram_list(cli_t* cli) {
4548
if (backup_ram_read(key, NULL, 0, &data_size)) {
4649
cli_trace(cli, "Key #%d: %d bytes", key, data_size);
4750
} else {
48-
cli_error(cli, CLI_ERROR, "Failed to read key #%d info", key);
51+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_INFO_READ,
52+
"Failed to read key #%d info", key);
4953
return;
5054
}
5155
key++;
@@ -68,7 +72,8 @@ static void prodtest_backup_ram_erase(cli_t* cli) {
6872
}
6973

7074
if (!backup_ram_init()) {
71-
cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
75+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_ERASE_INIT,
76+
"Failed to initialize backup RAM");
7277
return;
7378
}
7479

@@ -90,19 +95,22 @@ static void prodtest_backup_ram_read(cli_t* cli) {
9095
}
9196

9297
if (!backup_ram_init()) {
93-
cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
98+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_READ_INIT,
99+
"Failed to initialize backup RAM");
94100
return;
95101
}
96102

97103
if (!backup_ram_read(key, NULL, 0, NULL)) {
98-
cli_error(cli, CLI_ERROR, "Key #%d not found", key);
104+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_NOT_FOUND, "Key #%d not found",
105+
key);
99106
return;
100107
}
101108

102109
uint8_t data[BACKUP_RAM_MAX_KEY_DATA_SIZE];
103110
size_t data_size = 0;
104111
if (!backup_ram_read(key, data, sizeof(data), &data_size)) {
105-
cli_error(cli, CLI_ERROR, "Failed to read the key #%d", key);
112+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_READ,
113+
"Failed to read the key #%d", key);
106114
return;
107115
}
108116

@@ -114,7 +122,7 @@ static void prodtest_backup_ram_read(cli_t* cli) {
114122
char block_hex[16 * 2 + 1];
115123
if (!cstr_encode_hex(block_hex, sizeof(block_hex), &data[offset],
116124
block_size)) {
117-
cli_error(cli, CLI_ERROR_FATAL, "Buffer too small.");
125+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_HEX_ENCODE, "Buffer too small.");
118126
return;
119127
}
120128
cli_trace(cli, "%04x: %s", offset, block_hex);
@@ -149,21 +157,24 @@ static void prodtest_backup_ram_write(cli_t* cli) {
149157
if (cli_has_arg(cli, "hex-data")) {
150158
if (!cli_arg_hex(cli, "hex-data", data, sizeof(data), &len)) {
151159
if (len == sizeof(data)) {
152-
cli_error(cli, CLI_ERROR, "Data too long.");
160+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_DATA_TOO_LONG, "Data too long.");
153161
} else {
154-
cli_error(cli, CLI_ERROR, "Hexadecimal decoding error.");
162+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_HEX_DECODE,
163+
"Hexadecimal decoding error.");
155164
}
156165
return;
157166
}
158167
}
159168

160169
if (!backup_ram_init()) {
161-
cli_error(cli, CLI_ERROR, "Failed to initialize backup RAM");
170+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_WRITE_INIT,
171+
"Failed to initialize backup RAM");
162172
return;
163173
}
164174

165175
if (!backup_ram_write(key, type, data, len)) {
166-
cli_error(cli, CLI_ERROR, "Failed to write key #%d", key);
176+
cli_error(cli, PRODTEST_ERR_BACKUP_RAM_KEY_WRITE, "Failed to write key #%d",
177+
key);
167178
return;
168179
}
169180

0 commit comments

Comments
 (0)