mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-16 11:38:12 +00:00
feat(core/prodtest): parse algorithm identifier
[no changelog]
This commit is contained in:
parent
a684d6f1ed
commit
be7236076f
@ -21,10 +21,12 @@
|
||||
const uint8_t OID_AUTHORITY_KEY_IDENTIFIER[] = {0x06, 0x03, 0x55, 0x1d, 0x23};
|
||||
|
||||
// clang-format off
|
||||
static const uint8_t ECDSA_WITH_SHA256[] = {
|
||||
0x30, 0x0a, // a sequence of 10 bytes
|
||||
static const uint8_t ECDSA_P256_WITH_SHA256[] = {
|
||||
0x30, 0x13, // a sequence of 19 bytes
|
||||
0x06, 0x07, // an OID of 7 bytes
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, // corresponds to ecPublicKey in X.509
|
||||
0x06, 0x08, // an OID of 8 bytes
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, // corresponds to prime256v1 in X.509
|
||||
};
|
||||
|
||||
static const uint8_t OID_COMMON_NAME[] = {
|
||||
@ -45,6 +47,19 @@ static const uint8_t SUBJECT_COMMON_NAME[] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
typedef enum { ALG_ID_ECDSA_P256_WITH_SHA256 } alg_id_t;
|
||||
|
||||
static bool get_algorithm(DER_ITEM* alg, alg_id_t* alg_id) {
|
||||
if (alg->buf.size == sizeof(ECDSA_P256_WITH_SHA256) &&
|
||||
memcmp(alg->buf.data, ECDSA_P256_WITH_SHA256,
|
||||
sizeof(ECDSA_P256_WITH_SHA256)) == 0) {
|
||||
*alg_id = ALG_ID_ECDSA_P256_WITH_SHA256;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool get_cert_extensions(DER_ITEM* tbs_cert, DER_ITEM* extensions) {
|
||||
// Find the certificate extensions in the tbsCertificate.
|
||||
DER_ITEM cert_item = {0};
|
||||
@ -171,27 +186,31 @@ static bool get_common_name(DER_ITEM* name, const uint8_t** common_name,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool verify_signature(const uint8_t* pub_key, size_t pub_key_size,
|
||||
const uint8_t* sig, size_t sig_size,
|
||||
const uint8_t* msg, size_t msg_size) {
|
||||
// ECDSA (NIST P-256) with SHA-256
|
||||
if (pub_key_size != 65) {
|
||||
return false;
|
||||
static bool verify_signature(alg_id_t alg_id, const uint8_t* pub_key,
|
||||
size_t pub_key_size, const uint8_t* sig,
|
||||
size_t sig_size, const uint8_t* msg,
|
||||
size_t msg_size) {
|
||||
if (alg_id == ALG_ID_ECDSA_P256_WITH_SHA256) {
|
||||
if (pub_key_size != 65) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
sha256_Raw(msg, msg_size, digest);
|
||||
|
||||
uint8_t decoded_sig[64] = {0};
|
||||
if (ecdsa_sig_from_der(sig, sig_size, decoded_sig) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ecdsa_verify_digest(&nist256p1, pub_key, decoded_sig, digest) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
sha256_Raw(msg, msg_size, digest);
|
||||
|
||||
uint8_t decoded_sig[64] = {0};
|
||||
if (ecdsa_sig_from_der(sig, sig_size, decoded_sig) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ecdsa_verify_digest(&nist256p1, pub_key, decoded_sig, digest) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
|
||||
@ -215,6 +234,8 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
|
||||
const uint8_t* pub_key = NULL;
|
||||
size_t pub_key_size = 0;
|
||||
|
||||
alg_id_t alg_id = 0;
|
||||
|
||||
BUFFER_READER chain_reader = {0};
|
||||
buffer_reader_init(&chain_reader, chain, chain_size);
|
||||
int cert_count = 0;
|
||||
@ -281,16 +302,24 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the algorithm
|
||||
DER_ITEM alg = {0};
|
||||
if (!der_read_item(&pub_key_info.buf, &alg) ||
|
||||
!get_algorithm(&alg, &alg_id)) {
|
||||
cli_error(cli, CLI_ERROR,
|
||||
"check_device_cert_chain, reading algorithm, cert %d.",
|
||||
cert_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the public key.
|
||||
DER_ITEM pub_key_val = {0};
|
||||
uint8_t unused_bits = 0;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (!der_read_item(&pub_key_info.buf, &pub_key_val)) {
|
||||
cli_error(cli, CLI_ERROR,
|
||||
"check_device_cert_chain, der_read_item 6, cert %d.",
|
||||
cert_count);
|
||||
return false;
|
||||
}
|
||||
if (!der_read_item(&pub_key_info.buf, &pub_key_val)) {
|
||||
cli_error(cli, CLI_ERROR,
|
||||
"check_device_cert_chain, der_read_item 6, cert %d.",
|
||||
cert_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!buffer_get(&pub_key_val.buf, &unused_bits) ||
|
||||
@ -303,7 +332,7 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
|
||||
pub_key_size = buffer_remaining(&pub_key_val.buf);
|
||||
|
||||
// Verify the previous signature.
|
||||
if (!verify_signature(pub_key, pub_key_size, sig, sig_size, message,
|
||||
if (!verify_signature(alg_id, pub_key, pub_key_size, sig, sig_size, message,
|
||||
message_size)) {
|
||||
cli_error(cli, CLI_ERROR,
|
||||
"check_device_cert_chain, verify_signature, cert %d.",
|
||||
@ -322,15 +351,11 @@ bool check_cert_chain(cli_t* cli, const uint8_t* chain, size_t chain_size,
|
||||
message = tbs_cert.buf.data;
|
||||
message_size = tbs_cert.buf.size;
|
||||
|
||||
// Read the signatureAlgorithm and ensure it matches ECDSA_WITH_SHA256.
|
||||
// skip the signatureAlgorithm
|
||||
DER_ITEM sig_alg = {0};
|
||||
if (!der_read_item(&cert.buf, &sig_alg) ||
|
||||
sig_alg.buf.size != sizeof(ECDSA_WITH_SHA256) ||
|
||||
memcmp(ECDSA_WITH_SHA256, sig_alg.buf.data,
|
||||
sizeof(ECDSA_WITH_SHA256)) != 0) {
|
||||
if (!der_read_item(&cert.buf, &sig_alg)) {
|
||||
cli_error(cli, CLI_ERROR,
|
||||
"check_device_cert_chain, checking signatureAlgorithm, cert "
|
||||
"%d.",
|
||||
"check_device_cert_chain, der_read_item 7, cert %d.", "%d.",
|
||||
cert_count);
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user