From bfe9c1c948f43dca1f77ac78b1ddadfe64f27bea Mon Sep 17 00:00:00 2001 From: Tarak Ben Youssef Date: Thu, 6 Jun 2024 19:52:43 +0800 Subject: [PATCH 1/3] replace crypto magic constants --- src/crypto.c | 3 --- src/crypto.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 07ea046b..d550282f 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -88,9 +88,6 @@ typedef struct { uint8_t r[32]; uint8_t s[32]; uint8_t v; - - // DER signature max size should be 73 - // https://bitcoin.stackexchange.com/questions/77191/what-is-the-maximum-size-of-a-der-encoded-ecdsa-signature#77192 uint8_t der_signature[73]; } __attribute__((packed)) signature_t; diff --git a/src/crypto.h b/src/crypto.h index 722652ee..ad722857 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -32,7 +32,18 @@ typedef enum { CURVE_UNKNOWN, CURVE_SECP256K1, CURVE_SECP256R1 } curve_e; #if defined(TARGET_NANOS) || defined(TARGET_NANOX) || defined(TARGET_NANOS2) #else +/* output sizes of the supported hash algorithms */ #define CX_SHA256_SIZE 32 +#define CX_SHA3_256_SIZE 32 + +/* constants related to the supported elliptic curves */ +/* the currently supported curves have the same group order byte size and prime field byte size */ +#define CURVE_ORDER_SIZE 32 +#define CURVE_FIELD_SIZE 32 +#define PUB_KEY_SIZE ((2*CURVE_FIELD_SIZE)+1) +// DER signature max size should be 73 +// https://bitcoin.stackexchange.com/questions/77191/what-is-the-maximum-size-of-a-der-encoded-ecdsa-signature#77192 +#define DER_SIG_MAX_SIZE (2*(CURVE_ORDER_SIZE+3)+3) #endif void sha256(const uint8_t *message, uint16_t messageLen, uint8_t message_digest[CX_SHA256_SIZE]); From 26dd5445b2a57ce88375047299acadf0a0614e86 Mon Sep 17 00:00:00 2001 From: Tarak Ben Youssef Date: Thu, 6 Jun 2024 19:57:07 +0800 Subject: [PATCH 2/3] replace magic constants --- src/crypto.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index d550282f..885b2d41 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -69,7 +69,7 @@ zxerr_t crypto_extractPublicKey(const hd_path_t path, return zxerr_invalid_crypto_settings; } - if (pubKeyLen < 65) { + if (pubKeyLen < PUB_KEY_SIZE) { zemu_log_stack("extractPublicKey: zxerr_buffer_too_small"); return zxerr_buffer_too_small; } @@ -85,10 +85,10 @@ zxerr_t crypto_extractPublicKey(const hd_path_t path, } typedef struct { - uint8_t r[32]; - uint8_t s[32]; + uint8_t r[CURVE_ORDER_SIZE]; + uint8_t s[CURVE_ORDER_SIZE]; uint8_t v; - uint8_t der_signature[73]; + uint8_t der_signature[DER_SIG_MAX_SIZE]; } __attribute__((packed)) signature_t; void sha256(const uint8_t *message, uint16_t messageLen, uint8_t message_digest[CX_SHA256_SIZE]) { @@ -129,18 +129,18 @@ zxerr_t digest_message(const uint8_t *message, return zxerr_ok; } case HASH_SHA3_256: { - if (digestMax < 32) { + if (digestMax < CX_SHA3_256_SIZE) { return zxerr_buffer_too_small; } zemu_log_stack("sha3_256"); cx_sha3_t sha3; - cx_err = cx_sha3_init_no_throw(&sha3, 256); + cx_err = cx_sha3_init_no_throw(&sha3, CX_SHA3_256_SIZE * 8); if (cx_err != CX_OK) return zxerr_invalid_crypto_settings; cx_err = cx_hash_no_throw((cx_hash_t *) &sha3, 0, domainTag, DOMAIN_TAG_LENGTH, NULL, 0); if (cx_err != CX_OK) return zxerr_invalid_crypto_settings; cx_err = - cx_hash_no_throw((cx_hash_t *) &sha3, CX_LAST, message, messageLen, digest, 32); + cx_hash_no_throw((cx_hash_t *) &sha3, CX_LAST, message, messageLen, digest, CX_SHA3_256_SIZE); if (cx_err != CX_OK) return zxerr_invalid_crypto_settings; *digest_size = cx_hash_get_size((cx_hash_t *) &sha3); return zxerr_ok; @@ -171,7 +171,7 @@ zxerr_t crypto_sign(const hd_path_t path, const digest_type_e cx_hash_kind = get_hash_type(options); - uint8_t messageDigest[32]; + uint8_t messageDigest[CURVE_ORDER_SIZE]; uint16_t messageDigestSize = 0; CHECK_ZXERR(digest_message(message, @@ -182,7 +182,7 @@ zxerr_t crypto_sign(const hd_path_t path, sizeof(messageDigest), &messageDigestSize)); - if (messageDigestSize != CX_SHA256_SIZE) { + if (messageDigestSize != CURVE_ORDER_SIZE) { zemu_log_stack("crypto_sign: zxerr_out_of_bounds"); return zxerr_out_of_bounds; } From 1e5abf83528fe276dc6ce035389577c768d48eb6 Mon Sep 17 00:00:00 2001 From: Tarak Ben Youssef Date: Sat, 8 Jun 2024 15:08:12 +0800 Subject: [PATCH 3/3] update digest size checks before signing --- src/crypto.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/crypto.c b/src/crypto.c index 885b2d41..1c4b2f97 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -182,11 +182,26 @@ zxerr_t crypto_sign(const hd_path_t path, sizeof(messageDigest), &messageDigestSize)); - if (messageDigestSize != CURVE_ORDER_SIZE) { + + // check the message worked properly + if (cx_hash_kind == HASH_SHA2_256 && messageDigestSize != CX_SHA256_SIZE) { + zemu_log_stack("crypto_sign: zxerr_out_of_bounds"); + return zxerr_out_of_bounds; + } + + if (cx_hash_kind == HASH_SHA3_256 && messageDigestSize != CX_SHA3_256_SIZE) { zemu_log_stack("crypto_sign: zxerr_out_of_bounds"); return zxerr_out_of_bounds; } + // check that the hashing choice doesn't reduce the curve security. + // it's enough to check that the digest size is larger or equal to the group order + // but we check the equality to make sure the algos are fully compatible. + if (messageDigestSize != CURVE_ORDER_SIZE) { + zemu_log_stack("crypto_sign: zxerr_invalid_crypto_settings"); + return zxerr_invalid_crypto_settings; + } + size_t signatureLength; uint32_t info = 0;