Added support for SLIP-0021 node derivation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user