From 1174648777cda9f23edcf532f34e9d38055e9b8f Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 14 Oct 2021 12:41:16 +0200 Subject: [PATCH] refactor(crypto): extract Cardano derivations to separate file Changes the API: all Cardano derivations will now produce a 96-byte secret in the format of private_key + private_key_ext + chain_code. This can then be trivially converted to a HDNode. --- crypto/Makefile | 1 + crypto/bip32.c | 182 ++------------------- crypto/bip32.h | 8 - crypto/cardano.c | 252 ++++++++++++++++++++++++++++++ crypto/cardano.h | 54 +++++++ crypto/tests/test_check.c | 1 + crypto/tests/test_check_cardano.h | 124 +++++++++------ 7 files changed, 404 insertions(+), 218 deletions(-) create mode 100644 crypto/cardano.c create mode 100644 crypto/cardano.h diff --git a/crypto/Makefile b/crypto/Makefile index 8b76b168f..d266fac4b 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -100,6 +100,7 @@ SRCS += schnorr.c SRCS += zkp_context.c SRCS += zkp_ecdsa.c SRCS += zkp_bip340.c +SRCS += cardano.c OBJS = $(SRCS:.c=.o) OBJS += secp256k1-zkp.o diff --git a/crypto/bip32.c b/crypto/bip32.c index 4e6c4a72c..b3b3702e8 100644 --- a/crypto/bip32.c +++ b/crypto/bip32.c @@ -30,6 +30,7 @@ #include "base58.h" #include "bignum.h" #include "bip32.h" +#include "cardano.h" #include "curves.h" #include "ecdsa.h" #include "ed25519-donna/ed25519-sha3.h" @@ -45,13 +46,8 @@ #if USE_NEM #include "nem.h" #endif -#if USE_CARDANO -#include "pbkdf2.h" -#endif #include "memzero.h" -#define CARDANO_MAX_NODE_DEPTH 1048576 - const curve_info ed25519_info = { .bip32_name = "ed25519 seed", .params = NULL, @@ -61,15 +57,6 @@ const curve_info ed25519_info = { .hasher_script = HASHER_SHA2, }; -const curve_info ed25519_cardano_info = { - .bip32_name = "ed25519 cardano seed", - .params = NULL, - .hasher_base58 = HASHER_SHA2D, - .hasher_sign = HASHER_SHA2D, - .hasher_pubkey = HASHER_SHA2_RIPEMD, - .hasher_script = HASHER_SHA2, -}; - const curve_info ed25519_sha3_info = { .bip32_name = "ed25519-sha3 seed", .params = NULL, @@ -203,11 +190,17 @@ uint32_t hdnode_fingerprint(HDNode *node) { return fingerprint; } -int hdnode_private_ckd(HDNode *inout, uint32_t i) { +int hdnode_private_ckd_bip32(HDNode *inout, uint32_t i) { static CONFIDENTIAL uint8_t data[1 + 32 + 4]; static CONFIDENTIAL uint8_t I[32 + 32]; static CONFIDENTIAL bignum256 a, b; +#if USE_CARDANO + if (inout->curve == &ed25519_cardano_info) { + return 0; + } +#endif + if (i & 0x80000000) { // private derivation data[0] = 0; memcpy(data + 1, inout->private_key, 32); @@ -271,160 +264,17 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i) { return 1; } +int hdnode_private_ckd(HDNode *inout, uint32_t i) { #if USE_CARDANO -static void scalar_multiply8(const uint8_t *src, int bytes, uint8_t *dst) { - uint8_t prev_acc = 0; - for (int i = 0; i < bytes; i++) { - dst[i] = (src[i] << 3) + (prev_acc & 0x7); - prev_acc = src[i] >> 5; - } - dst[bytes] = src[bytes - 1] >> 5; -} - -static void scalar_add_256bits(const uint8_t *src1, const uint8_t *src2, - uint8_t *dst) { - uint16_t r = 0; - for (int i = 0; i < 32; i++) { - r = r + (uint16_t)src1[i] + (uint16_t)src2[i]; - dst[i] = r & 0xff; - r >>= 8; - } -} - -int hdnode_private_ckd_cardano(HDNode *inout, uint32_t index) { - if (inout->depth >= CARDANO_MAX_NODE_DEPTH) { - return 0; - } - - // checks for hardened/non-hardened derivation, keysize 32 means we are - // dealing with public key and thus non-h, keysize 64 is for private key - int keysize = 32; - if (index & 0x80000000) { - keysize = 64; - } - - static CONFIDENTIAL uint8_t data[1 + 64 + 4]; - static CONFIDENTIAL uint8_t z[32 + 32]; - static CONFIDENTIAL uint8_t priv_key[64]; - static CONFIDENTIAL uint8_t res_key[64]; - - write_le(data + keysize + 1, index); - - memcpy(priv_key, inout->private_key, 32); - memcpy(priv_key + 32, inout->private_key_extension, 32); - - if (keysize == 64) { // private derivation - data[0] = 0; - memcpy(data + 1, inout->private_key, 32); - memcpy(data + 1 + 32, inout->private_key_extension, 32); - } else { // public derivation - if (hdnode_fill_public_key(inout) != 0) { - return 0; - } - data[0] = 2; - memcpy(data + 1, inout->public_key + 1, 32); - } - - static CONFIDENTIAL HMAC_SHA512_CTX ctx; - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, 1 + keysize + 4); - hmac_sha512_Final(&ctx, z); - - static CONFIDENTIAL uint8_t zl8[32]; - memzero(zl8, 32); - - /* get 8 * Zl */ - scalar_multiply8(z, 28, zl8); - /* Kl = 8*Zl + parent(K)l */ - scalar_add_256bits(zl8, priv_key, res_key); - - /* Kr = Zr + parent(K)r */ - scalar_add_256bits(z + 32, priv_key + 32, res_key + 32); - - memcpy(inout->private_key, res_key, 32); - memcpy(inout->private_key_extension, res_key + 32, 32); - - if (keysize == 64) { - data[0] = 1; - } else { - data[0] = 3; - } - hmac_sha512_Init(&ctx, inout->chain_code, 32); - hmac_sha512_Update(&ctx, data, 1 + keysize + 4); - hmac_sha512_Final(&ctx, z); - - memcpy(inout->chain_code, z + 32, 32); - inout->depth++; - inout->child_num = index; - memzero(inout->public_key, sizeof(inout->public_key)); - - // making sure to wipe our memory - memzero(z, sizeof(z)); - memzero(data, sizeof(data)); - memzero(priv_key, sizeof(priv_key)); - memzero(res_key, sizeof(res_key)); - return 1; -} - -static int hdnode_from_secret_cardano(const uint8_t *k, - const uint8_t *chain_code, HDNode *out) { - memzero(out, sizeof(HDNode)); - out->depth = 0; - out->child_num = 0; - out->curve = &ed25519_cardano_info; - memcpy(out->private_key, k, 32); - memcpy(out->private_key_extension, k + 32, 32); - memcpy(out->chain_code, chain_code, 32); - - out->private_key[0] &= 0xf8; - out->private_key[31] &= 0x1f; - out->private_key[31] |= 0x40; - - out->public_key[0] = 0; - if (hdnode_fill_public_key(out) != 0) { - return 0; + if (inout->curve == &ed25519_cardano_info) { + return hdnode_private_ckd_cardano(inout, i); + } else +#endif + { + return hdnode_private_ckd_bip32(inout, i); } - - return 1; } -// Derives the root Cardano HDNode from a master secret, aka seed, as defined in -// SLIP-0023. -int hdnode_from_seed_cardano(const uint8_t *seed, int seed_len, HDNode *out) { - static CONFIDENTIAL uint8_t I[SHA512_DIGEST_LENGTH]; - static CONFIDENTIAL uint8_t k[SHA512_DIGEST_LENGTH]; - static CONFIDENTIAL HMAC_SHA512_CTX ctx; - - hmac_sha512_Init(&ctx, (const uint8_t *)ED25519_CARDANO_NAME, - strlen(ED25519_CARDANO_NAME)); - hmac_sha512_Update(&ctx, seed, seed_len); - hmac_sha512_Final(&ctx, I); - - sha512_Raw(I, 32, k); - - int ret = hdnode_from_secret_cardano(k, I + 32, out); - - memzero(I, sizeof(I)); - memzero(k, sizeof(k)); - memzero(&ctx, sizeof(ctx)); - return ret; -} - -// Derives the root Cardano HDNode from a passphrase and the entropy encoded in -// a BIP-0039 mnemonic using the Icarus derivation scheme, aka V2 derivation -// scheme. -int hdnode_from_entropy_cardano_icarus(const uint8_t *pass, int pass_len, - const uint8_t *entropy, int entropy_len, - HDNode *out) { - static CONFIDENTIAL uint8_t secret[96]; - pbkdf2_hmac_sha512(pass, pass_len, entropy, entropy_len, 4096, secret, 96); - - int ret = hdnode_from_secret_cardano(secret, secret + 64, out); - memzero(secret, sizeof(secret)); - return ret; -} -#endif - int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code) { @@ -952,9 +802,11 @@ const curve_info *get_curve_by_name(const char *curve_name) { if (strcmp(curve_name, ED25519_NAME) == 0) { return &ed25519_info; } +#if USE_CARDANO if (strcmp(curve_name, ED25519_CARDANO_NAME) == 0) { return &ed25519_cardano_info; } +#endif if (strcmp(curve_name, ED25519_SHA3_NAME) == 0) { return &ed25519_sha3_info; } diff --git a/crypto/bip32.h b/crypto/bip32.h index 5c5fb87cf..09862b34f 100644 --- a/crypto/bip32.h +++ b/crypto/bip32.h @@ -75,14 +75,6 @@ int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, int hdnode_private_ckd(HDNode *inout, uint32_t i); -#if USE_CARDANO -int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); -int hdnode_from_seed_cardano(const uint8_t *seed, int seed_len, HDNode *out); -int hdnode_from_entropy_cardano_icarus(const uint8_t *pass, int pass_len, - const uint8_t *seed, int seed_len, - HDNode *out); -#endif - int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code); diff --git a/crypto/cardano.c b/crypto/cardano.c new file mode 100644 index 000000000..4cf817351 --- /dev/null +++ b/crypto/cardano.c @@ -0,0 +1,252 @@ +/** + * Copyright (c) 2013-2021 SatoshiLabs + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "bignum.h" +#include "bip32.h" +#include "cardano.h" +#include "curves.h" +#include "hasher.h" +#include "hmac.h" +#include "memzero.h" +#include "options.h" +#include "pbkdf2.h" +#include "sha2.h" + +#if USE_CARDANO + +#define CARDANO_MAX_NODE_DEPTH 1048576 + +const curve_info ed25519_cardano_info = { + .bip32_name = "ed25519 cardano seed", + .params = NULL, + .hasher_base58 = HASHER_SHA2D, + .hasher_sign = HASHER_SHA2D, + .hasher_pubkey = HASHER_SHA2_RIPEMD, + .hasher_script = HASHER_SHA2, +}; + +static void scalar_multiply8(const uint8_t *src, int bytes, uint8_t *dst) { + uint8_t prev_acc = 0; + for (int i = 0; i < bytes; i++) { + dst[i] = (src[i] << 3) + (prev_acc & 0x7); + prev_acc = src[i] >> 5; + } + dst[bytes] = src[bytes - 1] >> 5; +} + +static void scalar_add_256bits(const uint8_t *src1, const uint8_t *src2, + uint8_t *dst) { + uint16_t r = 0; + for (int i = 0; i < 32; i++) { + r = r + (uint16_t)src1[i] + (uint16_t)src2[i]; + dst[i] = r & 0xff; + r >>= 8; + } +} + +static void cardano_ed25519_tweak_bits(uint8_t private_key[32]) { + private_key[0] &= 0xf8; + private_key[31] &= 0x1f; + private_key[31] |= 0x40; +} + +int hdnode_private_ckd_cardano(HDNode *inout, uint32_t index) { + if (inout->curve != &ed25519_cardano_info) { + return 0; + } + + if (inout->depth >= CARDANO_MAX_NODE_DEPTH) { + return 0; + } + + // checks for hardened/non-hardened derivation, keysize 32 means we are + // dealing with public key and thus non-h, keysize 64 is for private key + int keysize = 32; + if (index & 0x80000000) { + keysize = 64; + } + + static CONFIDENTIAL uint8_t data[1 + 64 + 4]; + static CONFIDENTIAL uint8_t z[32 + 32]; + static CONFIDENTIAL uint8_t priv_key[64]; + static CONFIDENTIAL uint8_t res_key[64]; + + write_le(data + keysize + 1, index); + + memcpy(priv_key, inout->private_key, 32); + memcpy(priv_key + 32, inout->private_key_extension, 32); + + if (keysize == 64) { // private derivation + data[0] = 0; + memcpy(data + 1, inout->private_key, 32); + memcpy(data + 1 + 32, inout->private_key_extension, 32); + } else { // public derivation + if (hdnode_fill_public_key(inout) != 0) { + return 0; + } + data[0] = 2; + memcpy(data + 1, inout->public_key + 1, 32); + } + + static CONFIDENTIAL HMAC_SHA512_CTX ctx; + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, 1 + keysize + 4); + hmac_sha512_Final(&ctx, z); + + static CONFIDENTIAL uint8_t zl8[32]; + memzero(zl8, 32); + + /* get 8 * Zl */ + scalar_multiply8(z, 28, zl8); + /* Kl = 8*Zl + parent(K)l */ + scalar_add_256bits(zl8, priv_key, res_key); + + /* Kr = Zr + parent(K)r */ + scalar_add_256bits(z + 32, priv_key + 32, res_key + 32); + + memcpy(inout->private_key, res_key, 32); + memcpy(inout->private_key_extension, res_key + 32, 32); + + if (keysize == 64) { + data[0] = 1; + } else { + data[0] = 3; + } + hmac_sha512_Init(&ctx, inout->chain_code, 32); + hmac_sha512_Update(&ctx, data, 1 + keysize + 4); + hmac_sha512_Final(&ctx, z); + + memcpy(inout->chain_code, z + 32, 32); + inout->depth++; + inout->child_num = index; + memzero(inout->public_key, sizeof(inout->public_key)); + + // making sure to wipe our memory + memzero(z, sizeof(z)); + memzero(data, sizeof(data)); + memzero(priv_key, sizeof(priv_key)); + memzero(res_key, sizeof(res_key)); + return 1; +} + +int hdnode_from_secret_cardano(const uint8_t secret[CARDANO_SECRET_LENGTH], + HDNode *out) { + memzero(out, sizeof(HDNode)); + out->depth = 0; + out->child_num = 0; + out->curve = &ed25519_cardano_info; + memcpy(out->private_key, secret, 32); + memcpy(out->private_key_extension, secret + 32, 32); + memcpy(out->chain_code, secret + 64, 32); + + cardano_ed25519_tweak_bits(out->private_key); + + out->public_key[0] = 0; + if (hdnode_fill_public_key(out) != 0) { + return 0; + } + + return 1; +} + +// Derives the root Cardano secret from a master secret, aka seed, as defined in +// SLIP-0023. +int secret_from_seed_cardano_slip23(const uint8_t *seed, int seed_len, + uint8_t secret_out[CARDANO_SECRET_LENGTH]) { + static CONFIDENTIAL uint8_t I[SHA512_DIGEST_LENGTH]; + static CONFIDENTIAL HMAC_SHA512_CTX ctx; + + hmac_sha512_Init(&ctx, (const uint8_t *)ED25519_CARDANO_NAME, + strlen(ED25519_CARDANO_NAME)); + hmac_sha512_Update(&ctx, seed, seed_len); + hmac_sha512_Final(&ctx, I); + + sha512_Raw(I, 32, secret_out); + + memcpy(secret_out + SHA512_DIGEST_LENGTH, I + 32, 32); + cardano_ed25519_tweak_bits(secret_out); + + memzero(I, sizeof(I)); + memzero(&ctx, sizeof(ctx)); + return 1; +} + +#define CARDANO_ICARUS_STEPS 32 +#define CARDANO_ICARUS_ROUNDS_PER_STEP \ + (CARDANO_ICARUS_PBKDF2_ROUNDS / CARDANO_ICARUS_STEPS) + +// Derives the root Cardano HDNode from a passphrase and the entropy encoded in +// a BIP-0039 mnemonic using the Icarus derivation scheme, aka V2 derivation +// scheme. +int secret_from_entropy_cardano_icarus( + const uint8_t *pass, int pass_len, const uint8_t *entropy, int entropy_len, + uint8_t secret_out[CARDANO_SECRET_LENGTH], + void (*progress_callback)(uint32_t, uint32_t)) { + static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx; + static CONFIDENTIAL uint8_t digest[SHA512_DIGEST_LENGTH]; + uint32_t progress = 0; + + // PASS 1: first 64 bytes + pbkdf2_hmac_sha512_Init(&pctx, pass, pass_len, entropy, entropy_len, 1); + if (progress_callback) { + progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2); + } + for (int i = 0; i < CARDANO_ICARUS_STEPS; i++) { + pbkdf2_hmac_sha512_Update(&pctx, CARDANO_ICARUS_ROUNDS_PER_STEP); + if (progress_callback) { + progress += CARDANO_ICARUS_ROUNDS_PER_STEP; + progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2); + } + } + pbkdf2_hmac_sha512_Final(&pctx, digest); + + memcpy(secret_out, digest, SHA512_DIGEST_LENGTH); + + // PASS 2: remaining 32 bytes + pbkdf2_hmac_sha512_Init(&pctx, pass, pass_len, entropy, entropy_len, 2); + if (progress_callback) { + progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2); + } + for (int i = 0; i < CARDANO_ICARUS_STEPS; i++) { + pbkdf2_hmac_sha512_Update(&pctx, CARDANO_ICARUS_ROUNDS_PER_STEP); + if (progress_callback) { + progress += CARDANO_ICARUS_ROUNDS_PER_STEP; + progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2); + } + } + pbkdf2_hmac_sha512_Final(&pctx, digest); + + memcpy(secret_out + SHA512_DIGEST_LENGTH, digest, + CARDANO_SECRET_LENGTH - SHA512_DIGEST_LENGTH); + + cardano_ed25519_tweak_bits(secret_out); + + memzero(&pctx, sizeof(pctx)); + memzero(digest, sizeof(digest)); + return 1; +} + +#endif // USE_CARDANO diff --git a/crypto/cardano.h b/crypto/cardano.h new file mode 100644 index 000000000..b5a8b0b39 --- /dev/null +++ b/crypto/cardano.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2013-2021 SatoshiLabs + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __CARDANO_H__ +#define __CARDANO_H__ + +#include +#include +#include "bip32.h" +#include "options.h" + +#if USE_CARDANO + +#define CARDANO_SECRET_LENGTH 96 +#define CARDANO_ICARUS_PBKDF2_ROUNDS 4096 + +extern const curve_info ed25519_cardano_info; + +int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i); + +int secret_from_entropy_cardano_icarus( + const uint8_t *pass, int pass_len, const uint8_t *entropy, int entropy_len, + uint8_t secret_out[CARDANO_SECRET_LENGTH], + void (*progress_callback)(uint32_t current, uint32_t total)); +int secret_from_seed_cardano_ledger(const uint8_t *seed, int seed_len, + uint8_t secret_out[CARDANO_SECRET_LENGTH]); +int secret_from_seed_cardano_slip23(const uint8_t *seed, int seed_len, + uint8_t secret_out[CARDANO_SECRET_LENGTH]); + +int hdnode_from_secret_cardano(const uint8_t secret[CARDANO_SECRET_LENGTH], + HDNode *out); + +#endif // USE_CARDANO + +#endif // __CARDANO_H__ diff --git a/crypto/tests/test_check.c b/crypto/tests/test_check.c index 01e87b4c3..c24fb6329 100644 --- a/crypto/tests/test_check.c +++ b/crypto/tests/test_check.c @@ -48,6 +48,7 @@ #include "blake256.h" #include "blake2b.h" #include "blake2s.h" +#include "cardano.h" #include "chacha_drbg.h" #include "curves.h" #include "ecdsa.h" diff --git a/crypto/tests/test_check_cardano.h b/crypto/tests/test_check_cardano.h index f3e02caae..f5ab7c02d 100644 --- a/crypto/tests/test_check_cardano.h +++ b/crypto/tests/test_check_cardano.h @@ -113,14 +113,24 @@ START_TEST(test_bip32_cardano_hdnode_vector_1) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); + ck_assert_mem_eq( + cardano_secret, + fromhex( + "08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46" + "daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc" + "affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"), + 96); ck_assert_mem_eq( node.chain_code, fromhex( @@ -149,15 +159,18 @@ START_TEST(test_bip32_cardano_hdnode_vector_2) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000000); ck_assert_mem_eq( node.chain_code, @@ -187,15 +200,18 @@ START_TEST(test_bip32_cardano_hdnode_vector_3) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000001); ck_assert_mem_eq( node.chain_code, @@ -225,16 +241,19 @@ START_TEST(test_bip32_cardano_hdnode_vector_4) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); ck_assert_mem_eq( node.chain_code, @@ -264,17 +283,20 @@ START_TEST(test_bip32_cardano_hdnode_vector_5) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000002); ck_assert_mem_eq( node.chain_code, @@ -304,18 +326,21 @@ START_TEST(test_bip32_cardano_hdnode_vector_6) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000002); ck_assert_mem_eq( node.chain_code, @@ -345,19 +370,22 @@ START_TEST(test_bip32_cardano_hdnode_vector_7) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "ring crime symptom enough erupt lady behave ramp apart settle citizen " "junk", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 132); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0xBB9ACA00); + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0xBB9ACA00); ck_assert_mem_eq( node.chain_code, @@ -387,19 +415,22 @@ START_TEST(test_bip32_cardano_hdnode_vector_8) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "found differ bulb shadow wrist blue bind vessel deposit tip pelican " "action surprise weapon check fiction muscle this", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 198); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0xBB9ACA00); + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0xBB9ACA00); ck_assert_mem_eq( node.chain_code, @@ -429,20 +460,23 @@ START_TEST(test_bip32_cardano_hdnode_vector_9) { HDNode node; uint8_t mnemonic_bits[66]; + uint8_t cardano_secret[CARDANO_SECRET_LENGTH]; int mnemonic_bits_len = mnemonic_to_bits( "balance exotic ranch knife glory slow tape favorite yard gym awake " "ill exist useless parent aim pig stay effort into square gasp credit " "butter", mnemonic_bits); ck_assert_int_eq(mnemonic_bits_len, 264); - hdnode_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, - mnemonic_bits_len / 8, &node); - - hdnode_private_ckd_cardano(&node, 0x80000000); - hdnode_private_ckd_cardano(&node, 0x80000001); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0x80000002); - hdnode_private_ckd_cardano(&node, 0xBB9ACA00); + secret_from_entropy_cardano_icarus((const uint8_t *)"", 0, mnemonic_bits, + mnemonic_bits_len / 8, cardano_secret, + NULL); + hdnode_from_secret_cardano(cardano_secret, &node); + + hdnode_private_ckd(&node, 0x80000000); + hdnode_private_ckd(&node, 0x80000001); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0x80000002); + hdnode_private_ckd(&node, 0xBB9ACA00); ck_assert_mem_eq( node.chain_code,