From 29544a3f17d50316e39076db70413cef97703161 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Fri, 26 May 2023 17:15:14 +0200 Subject: [PATCH] Added support for SLIP-0021 node derivation. Signed-off-by: Pol Henarejos --- src/hsm/cmd_bip_slip.c | 124 +++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/src/hsm/cmd_bip_slip.c b/src/hsm/cmd_bip_slip.c index 46e7816..86c7384 100644 --- a/src/hsm/cmd_bip_slip.c +++ b/src/hsm/cmd_bip_slip.c @@ -58,17 +58,36 @@ int node_derive_bip_child(const mbedtls_ecp_keypair *parent, const uint8_t cpar[ return CCID_OK; } -int node_fingerprint(mbedtls_ecp_keypair *ctx, uint8_t *fingerprint) { +int sha256_ripemd160(const uint8_t *buffer, size_t buffer_len, uint8_t *output) { + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output); + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), output, 32, output); + return CCID_OK; +} + +int sha256_sha256(const uint8_t *buffer, size_t buffer_len, uint8_t *output) { + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output); + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), output, 32, output); + return CCID_OK; +} + +int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { size_t olen = 0; uint8_t buffer[33]; mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, buffer, sizeof(buffer)); - mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, sizeof(buffer), buffer); - mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), buffer, 32, buffer); + sha256_ripemd160(buffer, sizeof(buffer), buffer); memcpy(fingerprint, buffer, 4); return CCID_OK; } -int load_master_bip(uint32_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32]) { +int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { + uint8_t buffer[32]; + mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer)); + sha256_ripemd160(buffer, sizeof(buffer), buffer); + memcpy(fingerprint, buffer, 4); + return CCID_OK; +} + +int load_master_bip(uint32_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t key_type[1] ) { uint8_t mkey[65]; mbedtls_ecp_keypair_init(ctx); file_t *ef = search_dynamic_file(EF_MASTER_SEED | mid); @@ -80,45 +99,66 @@ int load_master_bip(uint32_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32]) { if (r != CCID_OK) { return CCID_EXEC_ERROR; } - if (mkey[0] == 0x1) { - mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256K1); - } - else if (mkey[0] == 0x2) { - mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); - } - else { - return CCID_WRONG_DATA; - } + if (mkey[0] == 0x1 || mkey[0] == 0x2) { + if (mkey[0] == 0x1) { + mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256K1); + } + else if (mkey[0] == 0x2) { + mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); + } + else { + return CCID_WRONG_DATA; + } - mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32); - memcpy(chain, mkey + 33, 32); - mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); + mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32); + memcpy(chain, mkey + 33, 32); + mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); + } + else if (mkey[0] == 0x3) { + mbedtls_mpi_read_binary(&ctx->d, mkey + 33, 32); + memcpy(chain, mkey + 1, 32); + } + key_type[0] = mkey[0]; return CCID_OK; } -int node_derive_bip_path(const uint8_t *path, size_t path_len, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t fingerprint[4], uint8_t *nodes, uint8_t last_node[4]) { +int node_derive_path(const uint8_t *path, size_t path_len, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t fingerprint[4], uint8_t *nodes, uint8_t last_node[4], uint8_t key_type[1]) { uint8_t *tag_data = NULL, *p = NULL; size_t tag_len = 0; uint16_t tag = 0x0; - uint8_t node = 0; + uint8_t node = 0, N[64] = {0}; int r = 0; memset(last_node, 0, 4); memset(fingerprint, 0, 4); for (; walk_tlv(path, path_len, &p, &tag, &tag_len, &tag_data); node++) { - if (tag != 0x02 || (node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) { - return CCID_WRONG_DATA; - } - if (node == 0) { - if ((r = load_master_bip(tag_data[0], ctx, chain)) != CCID_OK) { - return r; + if (tag == 0x02) { + if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) { + return CCID_WRONG_DATA; + } + if (node == 0) { + if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != CCID_OK) { + return r; + } + } + else if (node > 0) { + node_fingerprint_bip(ctx, fingerprint); + if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != CCID_OK) { + return r; + } + memcpy(last_node, tag_data, 4); } } - else if (node > 0) { - node_fingerprint(ctx, fingerprint); - if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != CCID_OK) { - return r; + else if (tag == 0x04) { + if (node == 0) { + return CCID_WRONG_DATA; + } + else if (node > 0) { + node_fingerprint_slip(ctx, fingerprint); + *(tag_data - 1) = 0; + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), chain, 32, tag_data - 1, tag_len + 1, N); + memcpy(chain, N, 32); + mbedtls_mpi_read_binary(&ctx->d, N + 32, 32); } - memcpy(last_node, tag_data, 4); } } if (nodes) { @@ -186,11 +226,10 @@ int cmd_bip_slip() { if (apdu.nc == 0) { return SW_WRONG_LENGTH(); } - uint8_t nodes = 0; mbedtls_ecp_keypair ctx; - uint8_t chain[32], fgpt[4], last_node[4]; + uint8_t chain[32] = {0}, fgpt[4] = {0}, last_node[4] = {0}, key_type = 0, nodes = 0; size_t olen = 0; - int r = node_derive_bip_path(apdu.data, apdu.nc, &ctx, chain, fgpt, &nodes, last_node); + int r = node_derive_path(apdu.data, apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type); if (r != CCID_OK) { mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); @@ -204,11 +243,22 @@ int cmd_bip_slip() { res_APDU_size += 4; memcpy(res_APDU + res_APDU_size, last_node, 4); res_APDU_size += 4; - memcpy(res_APDU + res_APDU_size, chain, 32); - res_APDU_size += 32; - mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pubkey, sizeof(pubkey)); - memcpy(res_APDU + res_APDU_size, pubkey, olen); - res_APDU_size += olen; + if (key_type == 0x1 || key_type == 0x2) { + memcpy(res_APDU + res_APDU_size, chain, 32); + res_APDU_size += 32; + mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pubkey, sizeof(pubkey)); + memcpy(res_APDU + res_APDU_size, pubkey, olen); + res_APDU_size += olen; + } + else if (key_type == 0x3) { + sha256_sha256(chain, 32, chain); + memcpy(res_APDU + res_APDU_size, chain, 32); + res_APDU_size += 32; + mbedtls_mpi_write_binary(&ctx.d, pubkey, 32); + sha256_sha256(pubkey, 32, pubkey); + memcpy(res_APDU + res_APDU_size, pubkey, 32); + res_APDU_size += 32; + } mbedtls_ecp_keypair_free(&ctx); } return SW_OK();