Added support for SLIP-0021 node derivation.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2023-05-26 17:15:14 +02:00
parent 5135404083
commit 29544a3f17

View File

@@ -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();