From a2bdbaf8ed75960e00eafb3344cbb30fec932a69 Mon Sep 17 00:00:00 2001 From: Xavier Chapron Date: Fri, 28 Jul 2023 17:44:22 +0200 Subject: [PATCH] lib_standard_app/crypto_helpers.c: Add API for 64bytes private key --- lib_standard_app/crypto_helpers.c | 361 ++++++++++++++++++++++++------ lib_standard_app/crypto_helpers.h | 352 +++++++++++++++++++++++++++++ 2 files changed, 650 insertions(+), 63 deletions(-) diff --git a/lib_standard_app/crypto_helpers.c b/lib_standard_app/crypto_helpers.c index 4a6428bf5..f7f66f357 100644 --- a/lib_standard_app/crypto_helpers.c +++ b/lib_standard_app/crypto_helpers.c @@ -21,29 +21,20 @@ #include "cx.h" #include "os.h" -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( +static WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_internal( unsigned int derivation_mode, - cx_curve_t curve, const uint32_t *path, size_t path_len, - cx_ecfp_256_private_key_t *privkey, + struct cx_ecfp_private_key_s *privkey, uint8_t *chain_code, unsigned char *seed, size_t seed_len) { cx_err_t error = CX_OK; - uint8_t raw_privkey[64]; // Allocate 64 bytes to respect Syscall API but only 32 will be used - size_t length; - - // Check curve key length - CX_CHECK(cx_ecdomain_parameters_length(curve, &length)); - if (length != 32) { - error = CX_EC_INVALID_CURVE; - goto end; - } + uint8_t raw_privkey[64]; // Derive private key according to BIP32 path CX_CHECK(os_derive_bip32_with_seed_no_throw(derivation_mode, - curve, + privkey->curve, path, path_len, raw_privkey, @@ -52,7 +43,10 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( seed_len)); // Init privkey from raw - CX_CHECK(cx_ecfp_init_private_key_no_throw(curve, raw_privkey, length, privkey)); + CX_CHECK(cx_ecfp_init_private_key_no_throw(privkey->curve, + raw_privkey, + privkey->d_len, + (cx_ecfp_256_private_key_t *) privkey)); end: explicit_bzero(raw_privkey, sizeof(raw_privkey)); @@ -60,38 +54,74 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( if (error != CX_OK) { // Make sure the caller doesn't use uninitialized data in case // the return code is not checked. - explicit_bzero(privkey, sizeof(cx_ecfp_256_private_key_t)); + // Do not clear using the structure size as this is not the real one. + explicit_bzero(privkey->d, privkey->d_len); } return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256( unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, - uint8_t raw_pubkey[static 65], + cx_ecfp_256_private_key_t *privkey, uint8_t *chain_code, - cx_md_t hashID, unsigned char *seed, size_t seed_len) { + privkey->curve = curve; + privkey->d_len = sizeof(privkey->d); + + return bip32_derive_with_seed_init_privkey_internal(derivation_mode, + path, + path_len, + (struct cx_ecfp_private_key_s *) privkey, + chain_code, + seed, + seed_len); +} + +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_extended_private_key_t *privkey, + uint8_t *chain_code, + unsigned char *seed, + size_t seed_len) { + privkey->curve = curve; + privkey->d_len = sizeof(privkey->d); + + return bip32_derive_with_seed_init_privkey_internal(derivation_mode, + path, + path_len, + (struct cx_ecfp_private_key_s *) privkey, + chain_code, + seed, + seed_len); +} + +/* This function purpose is to get the pubkey for a corresponding + * private_key type (normal or extended) + * + * It takes as a param a cx_ecfp_private_key_s which should be initialized + * and will be cleaned before the function returns. + */ +static cx_err_t bip32_derive_with_seed_get_pubkey_256_internal( + struct cx_ecfp_private_key_s *privkey, + uint8_t raw_pubkey[static 65], + cx_md_t hashID) { cx_err_t error = CX_OK; - cx_ecfp_256_private_key_t privkey; cx_ecfp_256_public_key_t pubkey; - // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - chain_code, - seed, - seed_len)); - // Generate associated pubkey - CX_CHECK(cx_ecfp_generate_pair2_no_throw(curve, &pubkey, &privkey, true, hashID)); + CX_CHECK(cx_ecfp_generate_pair2_no_throw(privkey->curve, + &pubkey, + (cx_ecfp_private_key_t *) privkey, + true, + hashID)); // Check pubkey length then copy it to raw_pubkey if (pubkey.W_len != 65) { @@ -101,7 +131,8 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( memmove(raw_pubkey, pubkey.W, pubkey.W_len); end: - explicit_bzero(&privkey, sizeof(privkey)); + // Do not clear using the structure size as this is not the real one. + explicit_bzero(privkey->d, privkey->d_len); if (error != CX_OK) { // Make sure the caller doesn't use uninitialized data in case @@ -111,38 +142,97 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID, + unsigned char *seed, + size_t seed_len) { + cx_err_t error = CX_OK; + cx_ecfp_256_private_key_t privkey; + + error = bip32_derive_with_seed_init_privkey_256(derivation_mode, + curve, + path, + path_len, + &privkey, + chain_code, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_get_pubkey_256_internal((struct cx_ecfp_private_key_s *) &privkey, + raw_pubkey, + hashID); +} + +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256_extended( unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID, + unsigned char *seed, + size_t seed_len) { + cx_err_t error = CX_OK; + cx_ecfp_256_extended_private_key_t privkey; + + error = bip32_derive_with_seed_init_privkey_256_extended(derivation_mode, + curve, + path, + path_len, + &privkey, + chain_code, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_get_pubkey_256_internal((struct cx_ecfp_private_key_s *) &privkey, + raw_pubkey, + hashID); +} + + +/* This function purpose is to get the signature for a corresponding + * private_key type (normal or extended) + * + * It takes as a param a cx_ecfp_private_key_s which should be initialized + * and will be cleaned before the function returns. + */ +static cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256_internal( + struct cx_ecfp_private_key_s *privkey, uint32_t sign_mode, cx_md_t hashID, const uint8_t *hash, size_t hash_len, uint8_t *sig, size_t *sig_len, - uint32_t *info, - unsigned char *seed, - size_t seed_len) { + uint32_t *info) { cx_err_t error = CX_OK; - cx_ecfp_256_private_key_t privkey; size_t buf_len = *sig_len; - // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - NULL, - seed, - seed_len)); - - CX_CHECK(cx_ecdsa_sign_no_throw(&privkey, sign_mode, hashID, hash, hash_len, sig, sig_len, info)); + CX_CHECK(cx_ecdsa_sign_no_throw((const cx_ecfp_private_key_t *) privkey, + sign_mode, + hashID, + hash, + hash_len, + sig, + sig_len, + info)); end: - explicit_bzero(&privkey, sizeof(privkey)); + // Do not clear using the structure size as this is not the real one. + explicit_bzero(privkey->d, privkey->d_len); if (error != CX_OK) { // Make sure the caller doesn't use uninitialized data in case @@ -152,20 +242,99 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( return error; } -WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256( unsigned int derivation_mode, cx_curve_t curve, const uint32_t *path, size_t path_len, + uint32_t sign_mode, cx_md_t hashID, const uint8_t *hash, size_t hash_len, uint8_t *sig, size_t *sig_len, + uint32_t *info, unsigned char *seed, size_t seed_len) { cx_err_t error = CX_OK; cx_ecfp_256_private_key_t privkey; + + error = bip32_derive_with_seed_init_privkey_256(derivation_mode, + curve, + path, + path_len, + &privkey, + NULL, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_ecdsa_sign_hash_256_internal((struct cx_ecfp_private_key_s *) &privkey, + sign_mode, + hashID, + hash, + hash_len, + sig, + sig_len, + info); +} + +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info, + unsigned char *seed, + size_t seed_len) { + cx_err_t error = CX_OK; + cx_ecfp_256_extended_private_key_t privkey; + + // Derive private key according to BIP32 path + error = bip32_derive_with_seed_init_privkey_256_extended(derivation_mode, + curve, + path, + path_len, + &privkey, + NULL, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_ecdsa_sign_hash_256_internal((struct cx_ecfp_private_key_s *) &privkey, + sign_mode, + hashID, + hash, + hash_len, + sig, + sig_len, + info); +} + +/* This function purpose is to get the signature for a corresponding + * private_key type (normal or extended) + * + * It takes as a param a cx_ecfp_private_key_s which should be initialized + * and will be cleaned before the function returns. + */ +static cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256_internal( + struct cx_ecfp_private_key_s *privkey, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len) { + cx_err_t error = CX_OK; size_t size; size_t buf_len = *sig_len; @@ -174,23 +343,19 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( goto end; } - // Derive private key according to BIP32 path - CX_CHECK(bip32_derive_with_seed_init_privkey_256(derivation_mode, - curve, - path, - path_len, - &privkey, - NULL, - seed, - seed_len)); - - CX_CHECK(cx_eddsa_sign_no_throw(&privkey, hashID, hash, hash_len, sig, *sig_len)); - - CX_CHECK(cx_ecdomain_parameters_length(curve, &size)); + CX_CHECK(cx_eddsa_sign_no_throw((const cx_ecfp_private_key_t *) privkey, + hashID, + hash, + hash_len, + sig, + *sig_len)); + + CX_CHECK(cx_ecdomain_parameters_length(privkey->curve, &size)); *sig_len = size * 2; end: - explicit_bzero(&privkey, sizeof(privkey)); + // Do not clear using the structure size as this is not the real one. + explicit_bzero(privkey->d, privkey->d_len); if (error != CX_OK) { // Make sure the caller doesn't use uninitialized data in case @@ -199,3 +364,73 @@ WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( } return error; } + +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + unsigned char *seed, + size_t seed_len) { + cx_err_t error = CX_OK; + cx_ecfp_256_private_key_t privkey; + + error = bip32_derive_with_seed_init_privkey_256(derivation_mode, + curve, + path, + path_len, + &privkey, + NULL, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_eddsa_sign_hash_256_internal((struct cx_ecfp_private_key_s *) &privkey, + hashID, + hash, + hash_len, + sig, + sig_len); +} + +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + unsigned char *seed, + size_t seed_len) { + cx_err_t error = CX_OK; + cx_ecfp_256_extended_private_key_t privkey; + + error = bip32_derive_with_seed_init_privkey_256_extended(derivation_mode, + curve, + path, + path_len, + &privkey, + NULL, + seed, + seed_len); + if (error) { + return error; + } + + return bip32_derive_with_seed_eddsa_sign_hash_256_internal((struct cx_ecfp_private_key_s *) &privkey, + hashID, + hash, + hash_len, + sig, + sig_len); +} diff --git a/lib_standard_app/crypto_helpers.h b/lib_standard_app/crypto_helpers.h index 7b2a4e5d2..a561c5b1b 100644 --- a/lib_standard_app/crypto_helpers.h +++ b/lib_standard_app/crypto_helpers.h @@ -73,6 +73,76 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_init_privkey_256( 0); } +/** + * @brief Gets the private key from the device seed using the specified bip32 path and seed key. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[out] privkey Generated private key. + * + * @param[out] chain_code Buffer where to store the chain code. Can be NULL. + * + * @param[in] seed Seed key to use for derivation. + * + * @param[in] seed_len Seed key length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_init_privkey_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_extended_private_key_t *privkey, + uint8_t *chain_code, + unsigned char *seed, + size_t seed_len); + +/** + * @brief Gets the private key from the device seed using the specified bip32 path. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[out] privkey Generated private key. + * + * @param[out] chain_code Buffer where to store the chain code. Can be NULL. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_init_privkey_256_extended( + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_ecfp_256_extended_private_key_t *privkey, + uint8_t *chain_code) { + return bip32_derive_with_seed_init_privkey_256_extended(HDW_NORMAL, + curve, + path, + path_len, + privkey, + chain_code, + NULL, + 0); +} + /** * @brief Gets the public key from the device seed using the specified bip32 path and seed key. * @@ -148,6 +218,83 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256( 0); } +/** + * @brief Gets the public key from the device seed using the specified bip32 path and seed key. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[out] raw_pubkey Buffer where to store the public key. + * + * @param[out] chain_code Buffer where to store the chain code. Can be NULL. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] seed Seed key to use for derivation. + * + * @param[in] seed_len Seed key length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_get_pubkey_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID, + unsigned char *seed, + size_t seed_len); + +/** + * @brief Gets the public key from the device seed using the specified bip32 path. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[out] raw_pubkey Buffer where to store the public key. + * + * @param[out] chain_code Buffer where to store the chain code. Can be NULL. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_get_pubkey_256_extended( + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint8_t raw_pubkey[static 65], + uint8_t *chain_code, + cx_md_t hashID) { + return bip32_derive_with_seed_get_pubkey_256_extended(HDW_NORMAL, + curve, + path, + path_len, + raw_pubkey, + chain_code, + hashID, + NULL, + 0); +} + /** * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path and seed key. * @@ -255,6 +402,115 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256( 0); } +/** + * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path and seed key. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig Buffer where to store the signature. + * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * + * @param[in] sig_len Length of the signature buffer, updated with signature length. + * + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing **[k].G**. + * + * @param[in] seed Seed key to use for derivation. + * + * @param[in] seed_len Seed key length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_ecdsa_sign_hash_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info, + unsigned char *seed, + size_t seed_len); + +/** + * @brief Sign a hash with ecdsa using the device seed derived from the specified bip32 path. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig Buffer where to store the signature. + * The signature is encoded in TLV: **30 || L || 02 || Lr || r || 02 || Ls || s** + * + * @param[in] sig_len Length of the signature buffer, updated with signature length. + * + * @param[out] info Set with CX_ECCINFO_PARITY_ODD if the y-coordinate is odd when computing **[k].G**. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_ecdsa_sign_hash_256_extended( + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + uint32_t sign_mode, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + uint32_t *info) { + return bip32_derive_with_seed_ecdsa_sign_hash_256_extended(HDW_NORMAL, + curve, + path, + path_len, + sign_mode, + hashID, + hash, + hash_len, + sig, + sig_len, + info, + NULL, + 0); +} + /** * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path and seed key. * @@ -347,3 +603,99 @@ WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_eddsa_sign_hash_256( NULL, 0); } + + +/** + * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path and seed key. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] derivation_mode Derivation mode, one of HDW_NORMAL / HDW_ED25519_SLIP10 / HDW_SLIP21. + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig Buffer where to store the signature. + * + * @param[in] sig_len Length of the signature buffer, updated with signature length. + * + * @param[in] seed Seed key to use for derivation. + * + * @param[in] seed_len Seed key length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT cx_err_t bip32_derive_with_seed_eddsa_sign_hash_256_extended( + unsigned int derivation_mode, + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len, + unsigned char *seed, + size_t seed_len); + +/** + * @brief Sign a hash with eddsa using the device seed derived from the specified bip32 path. + * Used for extended private key (64bytes / 512 bits). + * + * @param[in] curve Curve identifier. + * + * @param[in] path Bip32 path to use for derivation. + * + * @param[in] path_len Bip32 path length. + * + * @param[in] hashID Message digest algorithm identifier. + * + * @param[in] hash Digest of the message to be signed. + * The length of *hash* must be shorter than the group order size. + * Otherwise it is truncated. + * + * @param[in] hash_len Length of the digest in octets. + * + * @param[out] sig Buffer where to store the signature. + * + * @param[in] sig_len Length of the signature buffer, updated with signature length. + * + * @return Error code: + * - CX_OK on success + * - CX_EC_INVALID_CURVE + * - CX_INTERNAL_ERROR + */ +WARN_UNUSED_RESULT static inline cx_err_t bip32_derive_eddsa_sign_hash_256_extended( + cx_curve_t curve, + const uint32_t *path, + size_t path_len, + cx_md_t hashID, + const uint8_t *hash, + size_t hash_len, + uint8_t *sig, + size_t *sig_len) { + return bip32_derive_with_seed_eddsa_sign_hash_256_extended(HDW_NORMAL, + curve, + path, + path_len, + hashID, + hash, + hash_len, + sig, + sig_len, + NULL, + 0); +}