mirror of
https://github.com/polhenarejos/pico-hsm
synced 2026-06-07 18:43:42 +02:00
Upgrade PicoKeys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -45,9 +45,9 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
set(USB_ITF_CCID 1)
|
set(USB_ITF_CCID 1)
|
||||||
set(USB_ITF_WCID 1)
|
set(USB_ITF_WCID 1)
|
||||||
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
include(pico-keys-sdk/picokeys_sdk_import.cmake)
|
||||||
if(NOT ESP_PLATFORM)
|
if(NOT ESP_PLATFORM)
|
||||||
set(SOURCES ${PICO_KEYS_SOURCES})
|
set(SOURCES ${PICOKEYS_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c
|
${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c
|
||||||
@@ -100,7 +100,7 @@ if(NOT ESP_PLATFORM)
|
|||||||
)
|
)
|
||||||
target_compile_options(pico_hsm PRIVATE ${COMMON_COMPILE_OPTIONS})
|
target_compile_options(pico_hsm PRIVATE ${COMMON_COMPILE_OPTIONS})
|
||||||
|
|
||||||
pico_keys_apply_strict_flags(
|
picokeys_apply_strict_flags(
|
||||||
SOURCES ${SOURCES}
|
SOURCES ${SOURCES}
|
||||||
FILTER_REGEX "/src/hsm/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
|
FILTER_REGEX "/src/hsm/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
|
||||||
)
|
)
|
||||||
@@ -136,7 +136,7 @@ if(NOT ESP_PLATFORM)
|
|||||||
-Wl,--gc-sections
|
-Wl,--gc-sections
|
||||||
)
|
)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
set(PICO_HSM_EMU_LIBS pico_keys_sdk pthread m)
|
set(PICO_HSM_EMU_LIBS picokeys_sdk pthread m)
|
||||||
if(NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION)
|
if(NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION)
|
||||||
list(APPEND PICO_HSM_EMU_LIBS mbedtls)
|
list(APPEND PICO_HSM_EMU_LIBS mbedtls)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
Submodule pico-keys-sdk updated: 44ee025416...ee13b6904a
@@ -27,78 +27,58 @@ const uint8_t *sym_seed = (const uint8_t *) "Symmetric key seed";
|
|||||||
mbedtls_ecp_keypair hd_context = { 0 };
|
mbedtls_ecp_keypair hd_context = { 0 };
|
||||||
uint8_t hd_keytype = 0;
|
uint8_t hd_keytype = 0;
|
||||||
|
|
||||||
static int node_derive_bip_child(const mbedtls_ecp_keypair *parent,
|
static int node_derive_bip_child(const mbedtls_ecp_keypair *parent, const uint8_t cpar[32], const uint8_t *i, mbedtls_ecp_keypair *child, uint8_t cchild[32]) {
|
||||||
const uint8_t cpar[32],
|
|
||||||
const uint8_t *i,
|
|
||||||
mbedtls_ecp_keypair *child,
|
|
||||||
uint8_t cchild[32]) {
|
|
||||||
uint8_t data[1 + 32 + 4], I[64], *iL = I, *iR = I + 32;
|
uint8_t data[1 + 32 + 4], I[64], *iL = I, *iR = I + 32;
|
||||||
mbedtls_mpi il, kchild;
|
mbedtls_mpi il, kchild;
|
||||||
mbedtls_mpi_init(&il);
|
mbedtls_mpi_init(&il);
|
||||||
mbedtls_mpi_init(&kchild);
|
mbedtls_mpi_init(&kchild);
|
||||||
if (i[0] >= 0x80) {
|
if (i[0] >= 0x80) {
|
||||||
if (mbedtls_mpi_cmp_int(&parent->d, 0) == 0) {
|
if (mbedtls_mpi_cmp_int(&parent->d, 0) == 0) {
|
||||||
return PICOKEY_ERR_NULL_PARAM;
|
return PICOKEYS_ERR_NULL_PARAM;
|
||||||
}
|
}
|
||||||
data[0] = 0x00;
|
data[0] = 0x00;
|
||||||
mbedtls_mpi_write_binary(&parent->d, data + 1, 32);
|
mbedtls_mpi_write_binary(&parent->d, data + 1, 32);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
mbedtls_ecp_point_write_binary(&parent->grp,
|
mbedtls_ecp_point_write_binary(&parent->grp, &parent->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, data, 33);
|
||||||
&parent->Q,
|
|
||||||
MBEDTLS_ECP_PF_COMPRESSED,
|
|
||||||
&olen,
|
|
||||||
data,
|
|
||||||
33);
|
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
memcpy(data + 33, i, 4);
|
memcpy(data + 33, i, 4);
|
||||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
|
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), cpar, 32, data, sizeof(data), I);
|
||||||
cpar,
|
|
||||||
32,
|
|
||||||
data,
|
|
||||||
sizeof(data),
|
|
||||||
I);
|
|
||||||
mbedtls_mpi_read_binary(&il, iL, 32);
|
mbedtls_mpi_read_binary(&il, iL, 32);
|
||||||
mbedtls_mpi_add_mpi(&kchild, &il, &parent->d);
|
mbedtls_mpi_add_mpi(&kchild, &il, &parent->d);
|
||||||
mbedtls_mpi_mod_mpi(&kchild, &kchild, &parent->grp.N);
|
mbedtls_mpi_mod_mpi(&kchild, &kchild, &parent->grp.N);
|
||||||
data[0] = 0x01;
|
data[0] = 0x01;
|
||||||
memcpy(data + 1, iR, 32);
|
memcpy(data + 1, iR, 32);
|
||||||
} while (mbedtls_mpi_cmp_mpi(&il,
|
} while (mbedtls_mpi_cmp_mpi(&il, &parent->grp.N) != -1 || mbedtls_mpi_cmp_int(&kchild, 0) == 0);
|
||||||
&parent->grp.N) != -1 || mbedtls_mpi_cmp_int(&kchild, 0) == 0);
|
|
||||||
mbedtls_mpi_copy(&child->d, &kchild);
|
mbedtls_mpi_copy(&child->d, &kchild);
|
||||||
mbedtls_ecp_mul(&child->grp, &child->Q, &child->d, &child->grp.G, random_gen, NULL);
|
mbedtls_ecp_mul(&child->grp, &child->Q, &child->d, &child->grp.G, random_fill_iterator, NULL);
|
||||||
memcpy(cchild, iR, 32);
|
memcpy(cchild, iR, 32);
|
||||||
mbedtls_mpi_free(&il);
|
mbedtls_mpi_free(&il);
|
||||||
mbedtls_mpi_free(&kchild);
|
mbedtls_mpi_free(&kchild);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sha256_ripemd160(const uint8_t *buffer, size_t buffer_len, uint8_t *output) {
|
static 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_SHA256), buffer, buffer_len, output);
|
||||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), output, 32, output);
|
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), output, 32, output);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sha256_sha256(const uint8_t *buffer, size_t buffer_len, uint8_t *output) {
|
static 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), buffer, buffer_len, output);
|
||||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), output, 32, output);
|
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), output, 32, output);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
|
static int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
uint8_t buffer[33];
|
uint8_t buffer[33];
|
||||||
mbedtls_ecp_point_write_binary(&ctx->grp,
|
mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, buffer, sizeof(buffer));
|
||||||
&ctx->Q,
|
|
||||||
MBEDTLS_ECP_PF_COMPRESSED,
|
|
||||||
&olen,
|
|
||||||
buffer,
|
|
||||||
sizeof(buffer));
|
|
||||||
sha256_ripemd160(buffer, sizeof(buffer), buffer);
|
sha256_ripemd160(buffer, sizeof(buffer), buffer);
|
||||||
memcpy(fingerprint, buffer, 4);
|
memcpy(fingerprint, buffer, 4);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
|
static int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
|
||||||
@@ -106,22 +86,21 @@ static int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4
|
|||||||
mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer));
|
mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer));
|
||||||
sha256_ripemd160(buffer, sizeof(buffer), buffer);
|
sha256_ripemd160(buffer, sizeof(buffer), buffer);
|
||||||
memcpy(fingerprint, buffer, 4);
|
memcpy(fingerprint, buffer, 4);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32],
|
static int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t key_type[1]) {
|
||||||
uint8_t key_type[1]) {
|
|
||||||
uint8_t mkey[65];
|
uint8_t mkey[65];
|
||||||
mbedtls_ecp_keypair_init(ctx);
|
mbedtls_ecp_keypair_init(ctx);
|
||||||
file_t *ef = search_file(EF_MASTER_SEED | mid);
|
file_t *ef = file_search(EF_MASTER_SEED | mid);
|
||||||
if (!file_has_data(ef)) {
|
if (!file_has_data(ef)) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
memcpy(mkey, file_get_data(ef), sizeof(mkey));
|
memcpy(mkey, file_get_data(ef), sizeof(mkey));
|
||||||
int r = mkek_decrypt(mkey + 1,
|
int r = mkek_decrypt(mkey + 1,
|
||||||
sizeof(mkey) - 1);
|
sizeof(mkey) - 1);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
if (mkey[0] == 0x1 || mkey[0] == 0x2) {
|
if (mkey[0] == 0x1 || mkey[0] == 0x2) {
|
||||||
if (mkey[0] == 0x1) {
|
if (mkey[0] == 0x1) {
|
||||||
@@ -131,29 +110,22 @@ static int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain
|
|||||||
mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1);
|
mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32);
|
mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32);
|
||||||
memcpy(chain, mkey + 33, 32);
|
memcpy(chain, mkey + 33, 32);
|
||||||
mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL);
|
mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
else if (mkey[0] == 0x3) {
|
else if (mkey[0] == 0x3) {
|
||||||
mbedtls_mpi_read_binary(&ctx->d, mkey + 33, 32);
|
mbedtls_mpi_read_binary(&ctx->d, mkey + 33, 32);
|
||||||
memcpy(chain, mkey + 1, 32);
|
memcpy(chain, mkey + 1, 32);
|
||||||
}
|
}
|
||||||
key_type[0] = mkey[0];
|
key_type[0] = mkey[0];
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int node_derive_path(const uint8_t *path,
|
static int node_derive_path(const uint8_t *path, uint16_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]) {
|
||||||
uint16_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;
|
uint8_t *tag_data = NULL, *p = NULL;
|
||||||
uint16_t tag_len = 0, tag = 0x0;
|
uint16_t tag_len = 0, tag = 0x0;
|
||||||
uint8_t node = 0, N[64] = { 0 };
|
uint8_t node = 0, N[64] = { 0 };
|
||||||
@@ -166,16 +138,16 @@ static int node_derive_path(const uint8_t *path,
|
|||||||
for (; walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data); node++) {
|
for (; walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data); node++) {
|
||||||
if (tag == 0x02) {
|
if (tag == 0x02) {
|
||||||
if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) {
|
if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (node == 0) {
|
if (node == 0) {
|
||||||
if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != PICOKEY_OK) {
|
if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (node > 0) {
|
else if (node > 0) {
|
||||||
node_fingerprint_bip(ctx, fingerprint);
|
node_fingerprint_bip(ctx, fingerprint);
|
||||||
if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != PICOKEY_OK) {
|
if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
memcpy(last_node, tag_data, 4);
|
memcpy(last_node, tag_data, 4);
|
||||||
@@ -183,17 +155,12 @@ static int node_derive_path(const uint8_t *path,
|
|||||||
}
|
}
|
||||||
else if (tag == 0x04) {
|
else if (tag == 0x04) {
|
||||||
if (node == 0) {
|
if (node == 0) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
else if (node > 0) {
|
else if (node > 0) {
|
||||||
node_fingerprint_slip(ctx, fingerprint);
|
node_fingerprint_slip(ctx, fingerprint);
|
||||||
*(tag_data - 1) = 0;
|
*(tag_data - 1) = 0;
|
||||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
|
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), chain, 32, tag_data - 1, tag_len + 1, N);
|
||||||
chain,
|
|
||||||
32,
|
|
||||||
tag_data - 1,
|
|
||||||
tag_len + 1,
|
|
||||||
N);
|
|
||||||
memcpy(chain, N, 32);
|
memcpy(chain, N, 32);
|
||||||
mbedtls_mpi_read_binary(&ctx->d, N + 32, 32);
|
mbedtls_mpi_read_binary(&ctx->d, N + 32, 32);
|
||||||
}
|
}
|
||||||
@@ -202,7 +169,7 @@ static int node_derive_path(const uint8_t *path,
|
|||||||
if (nodes) {
|
if (nodes) {
|
||||||
*nodes = node;
|
*nodes = node;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmd_bip_slip(void) {
|
int cmd_bip_slip(void) {
|
||||||
@@ -230,7 +197,7 @@ int cmd_bip_slip(void) {
|
|||||||
}
|
}
|
||||||
if (apdu.nc == 0) {
|
if (apdu.nc == 0) {
|
||||||
seed_len = 64;
|
seed_len = 64;
|
||||||
random_gen(NULL, seed, seed_len);
|
random_fill_buffer(seed, seed_len);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
seed_len = MIN((uint8_t)apdu.nc, 64);
|
seed_len = MIN((uint8_t)apdu.nc, 64);
|
||||||
@@ -238,8 +205,7 @@ int cmd_bip_slip(void) {
|
|||||||
}
|
}
|
||||||
if (p1 == 0x1 || p1 == 0x2) {
|
if (p1 == 0x1 || p1 == 0x2) {
|
||||||
do {
|
do {
|
||||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed,
|
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, strlen((char *) key_seed), seed, seed_len, seed);
|
||||||
strlen((char *) key_seed), seed, seed_len, seed);
|
|
||||||
mbedtls_mpi_read_binary(&il, seed, 32);
|
mbedtls_mpi_read_binary(&il, seed, 32);
|
||||||
seed_len = 64;
|
seed_len = 64;
|
||||||
} while (mbedtls_mpi_cmp_int(&il, 0) == 0 || mbedtls_mpi_cmp_mpi(&il, &grp.N) != -1);
|
} while (mbedtls_mpi_cmp_int(&il, 0) == 0 || mbedtls_mpi_cmp_mpi(&il, &grp.N) != -1);
|
||||||
@@ -247,20 +213,19 @@ int cmd_bip_slip(void) {
|
|||||||
mbedtls_mpi_free(&il);
|
mbedtls_mpi_free(&il);
|
||||||
}
|
}
|
||||||
else if (p1 == 0x3) {
|
else if (p1 == 0x3) {
|
||||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed,
|
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, strlen((char *) key_seed), seed, seed_len, seed);
|
||||||
strlen((char *) key_seed), seed, seed_len, seed);
|
|
||||||
}
|
}
|
||||||
mkey[0] = p1;
|
mkey[0] = p1;
|
||||||
file_t *ef = file_new(EF_MASTER_SEED | p2);
|
file_t *ef = file_new(EF_MASTER_SEED | p2);
|
||||||
int r = mkek_encrypt(mkey + 1, sizeof(mkey) - 1);
|
int r = mkek_encrypt(mkey + 1, sizeof(mkey) - 1);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = file_put_data(ef, mkey, sizeof(mkey));
|
r = file_put_data(ef, mkey, sizeof(mkey));
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
else if (p1 == 0xA) {
|
else if (p1 == 0xA) {
|
||||||
if (apdu.nc == 0) {
|
if (apdu.nc == 0) {
|
||||||
@@ -271,7 +236,7 @@ int cmd_bip_slip(void) {
|
|||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
int r =
|
int r =
|
||||||
node_derive_path(apdu.data, (uint16_t)apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type);
|
node_derive_path(apdu.data, (uint16_t)apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -287,12 +252,7 @@ int cmd_bip_slip(void) {
|
|||||||
if (key_type == 0x1 || key_type == 0x2) {
|
if (key_type == 0x1 || key_type == 0x2) {
|
||||||
memcpy(res_APDU + res_APDU_size, chain, 32);
|
memcpy(res_APDU + res_APDU_size, chain, 32);
|
||||||
res_APDU_size += 32;
|
res_APDU_size += 32;
|
||||||
mbedtls_ecp_point_write_binary(&ctx.grp,
|
mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pubkey, sizeof(pubkey));
|
||||||
&ctx.Q,
|
|
||||||
MBEDTLS_ECP_PF_COMPRESSED,
|
|
||||||
&olen,
|
|
||||||
pubkey,
|
|
||||||
sizeof(pubkey));
|
|
||||||
memcpy(res_APDU + res_APDU_size, pubkey, olen);
|
memcpy(res_APDU + res_APDU_size, pubkey, olen);
|
||||||
res_APDU_size += (uint16_t)olen;
|
res_APDU_size += (uint16_t)olen;
|
||||||
}
|
}
|
||||||
@@ -309,15 +269,8 @@ int cmd_bip_slip(void) {
|
|||||||
}
|
}
|
||||||
else if (p1 == 0x10) {
|
else if (p1 == 0x10) {
|
||||||
uint8_t chain[32] = { 0 }, fgpt[4] = { 0 }, last_node[4] = { 0 }, nodes = 0;
|
uint8_t chain[32] = { 0 }, fgpt[4] = { 0 }, last_node[4] = { 0 }, nodes = 0;
|
||||||
int r = node_derive_path(apdu.data,
|
int r = node_derive_path(apdu.data, (uint16_t)apdu.nc, &hd_context, chain, fgpt, &nodes, last_node, &hd_keytype);
|
||||||
(uint16_t)apdu.nc,
|
if (r != PICOKEYS_OK) {
|
||||||
&hd_context,
|
|
||||||
chain,
|
|
||||||
fgpt,
|
|
||||||
&nodes,
|
|
||||||
last_node,
|
|
||||||
&hd_keytype);
|
|
||||||
if (r != PICOKEY_OK) {
|
|
||||||
mbedtls_ecp_keypair_free(&hd_context);
|
mbedtls_ecp_keypair_free(&hd_context);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "crypto_utils.h"
|
#include "crypto_utils.h"
|
||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
#include "kek.h"
|
#include "kek.h"
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
int cmd_change_pin(void) {
|
int cmd_change_pin(void) {
|
||||||
if (P1(apdu) == 0x0) {
|
if (P1(apdu) == 0x0) {
|
||||||
@@ -42,7 +43,7 @@ int cmd_change_pin(void) {
|
|||||||
}
|
}
|
||||||
uint8_t mkek[MKEK_SIZE];
|
uint8_t mkek[MKEK_SIZE];
|
||||||
r = load_mkek(mkek); //loads the MKEK with old pin
|
r = load_mkek(mkek); //loads the MKEK with old pin
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
//encrypt MKEK with new pin
|
//encrypt MKEK with new pin
|
||||||
@@ -57,7 +58,7 @@ int cmd_change_pin(void) {
|
|||||||
}
|
}
|
||||||
r = store_mkek(mkek);
|
r = store_mkek(mkek);
|
||||||
release_mkek(mkek);
|
release_mkek(mkek);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
uint8_t dhash[34];
|
uint8_t dhash[34];
|
||||||
@@ -65,7 +66,7 @@ int cmd_change_pin(void) {
|
|||||||
dhash[1] = 1; // Format
|
dhash[1] = 1; // Format
|
||||||
pin_derive_verifier(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), dhash + 2);
|
pin_derive_verifier(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), dhash + 2);
|
||||||
file_put_data(file_pin, dhash, sizeof(dhash));
|
file_put_data(file_pin, dhash, sizeof(dhash));
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ static int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
|
|||||||
mbedtls_md_update(&md_ctx, input, input_len);
|
mbedtls_md_update(&md_ctx, input, input_len);
|
||||||
|
|
||||||
//TODO: be careful with architecture little vs. big
|
//TODO: be careful with architecture little vs. big
|
||||||
put_uint32_t_be(counter, counter_buf);
|
put_uint32_be(counter, counter_buf);
|
||||||
|
|
||||||
mbedtls_md_update(&md_ctx, counter_buf, 4);
|
mbedtls_md_update(&md_ctx, counter_buf, 4);
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ int cmd_cipher_sym(void) {
|
|||||||
if (wait_button_pressed() == true) { // timeout
|
if (wait_button_pressed() == true) { // timeout
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
file_t *ef = search_file((KEY_PREFIX << 8) | key_id);
|
file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
|
||||||
if (hd_keytype == 0) {
|
if (hd_keytype == 0) {
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
@@ -204,12 +204,7 @@ int cmd_cipher_sym(void) {
|
|||||||
mbedtls_aes_free(&aes);
|
mbedtls_aes_free(&aes);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = mbedtls_aes_crypt_cbc(&aes,
|
r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU);
|
||||||
MBEDTLS_AES_ENCRYPT,
|
|
||||||
apdu.nc,
|
|
||||||
tmp_iv,
|
|
||||||
apdu.data,
|
|
||||||
res_APDU);
|
|
||||||
mbedtls_aes_free(&aes);
|
mbedtls_aes_free(&aes);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -221,12 +216,7 @@ int cmd_cipher_sym(void) {
|
|||||||
mbedtls_aes_free(&aes);
|
mbedtls_aes_free(&aes);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = mbedtls_aes_crypt_cbc(&aes,
|
r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU);
|
||||||
MBEDTLS_AES_DECRYPT,
|
|
||||||
apdu.nc,
|
|
||||||
tmp_iv,
|
|
||||||
apdu.data,
|
|
||||||
res_APDU);
|
|
||||||
mbedtls_aes_free(&aes);
|
mbedtls_aes_free(&aes);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -257,15 +247,7 @@ int cmd_cipher_sym(void) {
|
|||||||
res_APDU_size = 16;
|
res_APDU_size = 16;
|
||||||
}
|
}
|
||||||
else if (algo == ALGO_AES_DERIVE) {
|
else if (algo == ALGO_AES_DERIVE) {
|
||||||
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
|
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0,kdata, key_size, apdu.data, apdu.nc, res_APDU, apdu.nc);
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
kdata,
|
|
||||||
key_size,
|
|
||||||
apdu.data,
|
|
||||||
apdu.nc,
|
|
||||||
res_APDU,
|
|
||||||
apdu.nc);
|
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -294,24 +276,10 @@ int cmd_cipher_sym(void) {
|
|||||||
mbedtls_chachapoly_init(&ctx);
|
mbedtls_chachapoly_init(&ctx);
|
||||||
mbedtls_chachapoly_setkey(&ctx, kdata);
|
mbedtls_chachapoly_setkey(&ctx, kdata);
|
||||||
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
|
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
|
||||||
r = mbedtls_chachapoly_encrypt_and_tag(&ctx,
|
r = mbedtls_chachapoly_encrypt_and_tag(&ctx, enc.len, asn1_len(&iv) > 0 ? iv.data : tmp_iv, aad.data, aad.len, enc.data, res_APDU, res_APDU + enc.len);
|
||||||
enc.len,
|
|
||||||
asn1_len(&iv) > 0 ? iv.data : tmp_iv,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
enc.data,
|
|
||||||
res_APDU,
|
|
||||||
res_APDU + enc.len);
|
|
||||||
}
|
}
|
||||||
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||||
r = mbedtls_chachapoly_auth_decrypt(&ctx,
|
r = mbedtls_chachapoly_auth_decrypt(&ctx,enc.len - 16, asn1_len(&iv) > 0 ? iv.data : tmp_iv, aad.data, aad.len, enc.data + enc.len - 16, enc.data, res_APDU);
|
||||||
enc.len - 16,
|
|
||||||
asn1_len(&iv) > 0 ? iv.data : tmp_iv,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
enc.data + enc.len - 16,
|
|
||||||
enc.data,
|
|
||||||
res_APDU);
|
|
||||||
}
|
}
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_chachapoly_free(&ctx);
|
mbedtls_chachapoly_free(&ctx);
|
||||||
@@ -369,16 +337,7 @@ int cmd_cipher_sym(void) {
|
|||||||
else if (memcmp(oid.data, OID_HKDF_SHA512, oid.len) == 0) {
|
else if (memcmp(oid.data, OID_HKDF_SHA512, oid.len) == 0) {
|
||||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||||
}
|
}
|
||||||
int r = mbedtls_hkdf(md_info,
|
int r = mbedtls_hkdf(md_info, iv.data, iv.len, kdata, key_size, enc.data, enc.len, res_APDU, apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info));
|
||||||
iv.data,
|
|
||||||
iv.len,
|
|
||||||
kdata,
|
|
||||||
key_size,
|
|
||||||
enc.data,
|
|
||||||
enc.len,
|
|
||||||
res_APDU,
|
|
||||||
apdu.ne > 0 &&
|
|
||||||
apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info));
|
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -399,15 +358,7 @@ int cmd_cipher_sym(void) {
|
|||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type,
|
r = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, kdata, key_size, salt.p, salt.len, iterations, keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32), res_APDU);
|
||||||
kdata,
|
|
||||||
key_size,
|
|
||||||
salt.p,
|
|
||||||
salt.len,
|
|
||||||
iterations,
|
|
||||||
keylen ? keylen : (apdu.ne > 0 &&
|
|
||||||
apdu.ne < 65536 ? apdu.ne : 32),
|
|
||||||
res_APDU);
|
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -442,13 +393,7 @@ int cmd_cipher_sym(void) {
|
|||||||
else if (memcmp(enc.data, OID_HMAC_SHA512, enc.len) == 0) {
|
else if (memcmp(enc.data, OID_HMAC_SHA512, enc.len) == 0) {
|
||||||
md_type = MBEDTLS_MD_SHA512;
|
md_type = MBEDTLS_MD_SHA512;
|
||||||
}
|
}
|
||||||
int r = mbedtls_ansi_x963_kdf(md_type,
|
int r = mbedtls_ansi_x963_kdf(md_type, key_size, kdata, aad.len, aad.data, apdu.ne > 0 && apdu.ne < 65536 ? (uint16_t)apdu.ne : 32, res_APDU);
|
||||||
key_size,
|
|
||||||
kdata,
|
|
||||||
aad.len,
|
|
||||||
aad.data,
|
|
||||||
apdu.ne > 0 && apdu.ne < 65536 ? (uint16_t)apdu.ne : 32,
|
|
||||||
res_APDU);
|
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
@@ -550,16 +495,7 @@ int cmd_cipher_sym(void) {
|
|||||||
res_APDU_size = enc.len + 16;
|
res_APDU_size = enc.len + 16;
|
||||||
}
|
}
|
||||||
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||||
r = mbedtls_gcm_auth_decrypt(&gctx,
|
r = mbedtls_gcm_auth_decrypt(&gctx, enc.len - 16, iv.data, iv.len, aad.data, aad.len, enc.data + enc.len - 16, 16, enc.data, res_APDU);
|
||||||
enc.len - 16,
|
|
||||||
iv.data,
|
|
||||||
iv.len,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
enc.data + enc.len - 16,
|
|
||||||
16,
|
|
||||||
enc.data,
|
|
||||||
res_APDU);
|
|
||||||
res_APDU_size = enc.len - 16;
|
res_APDU_size = enc.len - 16;
|
||||||
}
|
}
|
||||||
mbedtls_gcm_free(&gctx);
|
mbedtls_gcm_free(&gctx);
|
||||||
@@ -592,29 +528,11 @@ int cmd_cipher_sym(void) {
|
|||||||
}
|
}
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
|
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
|
||||||
r = mbedtls_ccm_encrypt_and_tag(&gctx,
|
r = mbedtls_ccm_encrypt_and_tag(&gctx, enc.len, iv.data, iv.len, aad.data,aad.len, enc.data, res_APDU, res_APDU + enc.len, 16);
|
||||||
enc.len,
|
|
||||||
iv.data,
|
|
||||||
iv.len,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
enc.data,
|
|
||||||
res_APDU,
|
|
||||||
res_APDU + enc.len,
|
|
||||||
16);
|
|
||||||
res_APDU_size = enc.len + 16;
|
res_APDU_size = enc.len + 16;
|
||||||
}
|
}
|
||||||
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
|
||||||
r = mbedtls_ccm_auth_decrypt(&gctx,
|
r = mbedtls_ccm_auth_decrypt(&gctx, enc.len - 16, iv.data, iv.len, aad.data, aad.len, enc.data, res_APDU, enc.data + enc.len - 16, 16);
|
||||||
enc.len - 16,
|
|
||||||
iv.data,
|
|
||||||
iv.len,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
enc.data,
|
|
||||||
res_APDU,
|
|
||||||
enc.data + enc.len - 16,
|
|
||||||
16);
|
|
||||||
res_APDU_size = enc.len - 16;
|
res_APDU_size = enc.len - 16;
|
||||||
}
|
}
|
||||||
mbedtls_ccm_free(&gctx);
|
mbedtls_ccm_free(&gctx);
|
||||||
@@ -668,12 +586,7 @@ int cmd_cipher_sym(void) {
|
|||||||
}
|
}
|
||||||
key_size = 32;
|
key_size = 32;
|
||||||
mbedtls_mpi_write_binary(&hd_context.d, kdata, key_size);
|
mbedtls_mpi_write_binary(&hd_context.d, kdata, key_size);
|
||||||
r = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
|
r = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), kdata, key_size,aad.data, aad.len, secret);
|
||||||
kdata,
|
|
||||||
key_size,
|
|
||||||
aad.data,
|
|
||||||
aad.len,
|
|
||||||
secret);
|
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ int cmd_decrypt_asym(void) {
|
|||||||
if (!isUserAuthenticated) {
|
if (!isUserAuthenticated) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
file_t *ef = search_file((KEY_PREFIX << 8) | key_id);
|
file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -48,9 +48,9 @@ int cmd_decrypt_asym(void) {
|
|||||||
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||||
}
|
}
|
||||||
int r = load_private_key_rsa(&ctx, ef);
|
int r = load_private_key_rsa(&ctx, ef);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -61,13 +61,13 @@ int cmd_decrypt_asym(void) {
|
|||||||
}
|
}
|
||||||
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
|
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
|
||||||
size_t olen = apdu.nc;
|
size_t olen = apdu.nc;
|
||||||
r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_gen, NULL, &olen, apdu.data, res_APDU, 512);
|
r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_fill_iterator, NULL, &olen, apdu.data, res_APDU, 512);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
res_APDU_size = (uint16_t)olen;
|
res_APDU_size = (uint16_t)olen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
|
r = mbedtls_rsa_private(&ctx, random_fill_iterator, NULL, apdu.data, res_APDU);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
res_APDU_size = key_size;
|
res_APDU_size = key_size;
|
||||||
}
|
}
|
||||||
@@ -134,9 +134,7 @@ int cmd_decrypt_asym(void) {
|
|||||||
// The SmartCard-HSM returns the point result of the DH operation
|
// The SmartCard-HSM returns the point result of the DH operation
|
||||||
// with a leading '04'
|
// with a leading '04'
|
||||||
res_APDU[0] = 0x04;
|
res_APDU[0] = 0x04;
|
||||||
r =
|
r = mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU + 1, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
|
||||||
mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU + 1, MBEDTLS_ECP_MAX_BYTES, random_gen,
|
|
||||||
NULL);
|
|
||||||
mbedtls_ecdh_free(&ctx);
|
mbedtls_ecdh_free(&ctx);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -158,10 +156,7 @@ int cmd_decrypt_asym(void) {
|
|||||||
while (walk_tlv(&ctxi, &p, &tag, &ctxo.len, &ctxo.data)) {
|
while (walk_tlv(&ctxi, &p, &tag, &ctxo.len, &ctxo.data)) {
|
||||||
if (tag == 0x73) {
|
if (tag == 0x73) {
|
||||||
asn1_ctx_t oid = {0};
|
asn1_ctx_t oid = {0};
|
||||||
if (asn1_find_tag(&ctxo, 0x6, &oid) == true &&
|
if (asn1_find_tag(&ctxo, 0x6, &oid) == true && oid.len == strlen(OID_ID_KEY_DOMAIN_UID) && memcmp(oid.data, OID_ID_KEY_DOMAIN_UID, strlen(OID_ID_KEY_DOMAIN_UID)) == 0) {
|
||||||
oid.len == strlen(OID_ID_KEY_DOMAIN_UID) &&
|
|
||||||
memcmp(oid.data, OID_ID_KEY_DOMAIN_UID,
|
|
||||||
strlen(OID_ID_KEY_DOMAIN_UID)) == 0) {
|
|
||||||
if (asn1_find_tag(&ctxo, 0x80, &kdom_uid) == false) {
|
if (asn1_find_tag(&ctxo, 0x80, &kdom_uid) == false) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
@@ -173,12 +168,11 @@ int cmd_decrypt_asym(void) {
|
|||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
for (uint8_t n = 0; n < MAX_KEY_DOMAINS; n++) {
|
for (uint8_t n = 0; n < MAX_KEY_DOMAINS; n++) {
|
||||||
file_t *tf = search_file(EF_XKEK + n);
|
file_t *tf = file_search(EF_XKEK + n);
|
||||||
if (tf) {
|
if (tf) {
|
||||||
if (file_get_size(tf) == kdom_uid.len &&
|
if (file_get_size(tf) == kdom_uid.len && memcmp(file_get_data(tf), kdom_uid.data, kdom_uid.len) == 0) {
|
||||||
memcmp(file_get_data(tf), kdom_uid.data, kdom_uid.len) == 0) {
|
|
||||||
file_new(EF_DKEK + n);
|
file_new(EF_DKEK + n);
|
||||||
if (store_dkek_key(n, res_APDU + 1) != PICOKEY_OK) {
|
if (store_dkek_key(n, res_APDU + 1) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
mbedtls_platform_zeroize(res_APDU, 32);
|
mbedtls_platform_zeroize(res_APDU, 32);
|
||||||
|
|||||||
@@ -25,20 +25,20 @@ int cmd_delete_file(void) {
|
|||||||
|
|
||||||
if (apdu.nc == 0) {
|
if (apdu.nc == 0) {
|
||||||
ef = currentEF;
|
ef = currentEF;
|
||||||
if (!(ef = search_file(ef->fid))) {
|
if (!(ef = file_search(ef->fid))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint16_t fid = get_uint16_t_be(apdu.data);
|
uint16_t fid = get_uint16_be(apdu.data);
|
||||||
if (!(ef = search_file(fid))) {
|
if (!(ef = file_search(fid))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) {
|
if (!file_authenticate_action(ef, ACL_OP_DELETE_SELF)) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
if (delete_file(ef) != PICOKEY_OK) {
|
if (file_delete(ef) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ int cmd_derive_asym(void) {
|
|||||||
if (!isUserAuthenticated) {
|
if (!isUserAuthenticated) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
if (!(fkey = search_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
|
if (!(fkey = file_search((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) {
|
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) {
|
||||||
@@ -57,9 +57,9 @@ int cmd_derive_asym(void) {
|
|||||||
|
|
||||||
int r;
|
int r;
|
||||||
r = load_private_key_ec(&ctx, fkey);
|
r = load_private_key_ec(&ctx, fkey);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -87,8 +87,8 @@ int cmd_derive_asym(void) {
|
|||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&ctx, PICO_KEYS_KEY_EC, dest_id);
|
r = store_keys(&ctx, PICOKEYS_KEY_EC, dest_id);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ int cmd_external_authenticate(void) {
|
|||||||
if (apdu.nc == 0) {
|
if (apdu.nc == 0) {
|
||||||
return SW_WRONG_LENGTH();
|
return SW_WRONG_LENGTH();
|
||||||
}
|
}
|
||||||
file_t *ef_puk = search_file(EF_PUKAUT);
|
file_t *ef_puk = file_search(EF_PUKAUT);
|
||||||
if (!file_has_data(ef_puk)) {
|
if (!file_has_data(ef_puk)) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -44,13 +44,7 @@ int cmd_external_authenticate(void) {
|
|||||||
memcpy(input, dev_name, dev_name_len);
|
memcpy(input, dev_name, dev_name_len);
|
||||||
memcpy(input + dev_name_len, challenge, challenge_len);
|
memcpy(input + dev_name_len, challenge, challenge_len);
|
||||||
hash256(input, dev_name_len + challenge_len, hash);
|
hash256(input, dev_name_len + challenge_len, hash);
|
||||||
int r =
|
int r = puk_verify(apdu.data, (uint16_t)apdu.nc, hash, 32, file_get_data(ef_puk_aut), file_get_size(ef_puk_aut));
|
||||||
puk_verify(apdu.data,
|
|
||||||
(uint16_t)apdu.nc,
|
|
||||||
hash,
|
|
||||||
32,
|
|
||||||
file_get_data(ef_puk_aut),
|
|
||||||
file_get_size(ef_puk_aut));
|
|
||||||
free(input);
|
free(input);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_CONDITIONS_NOT_SATISFIED();
|
return SW_CONDITIONS_NOT_SATISFIED();
|
||||||
|
|||||||
@@ -59,13 +59,13 @@ int cmd_extras(void) {
|
|||||||
}
|
}
|
||||||
uint16_t opts = get_device_options();
|
uint16_t opts = get_device_options();
|
||||||
if (apdu.nc == 0) {
|
if (apdu.nc == 0) {
|
||||||
res_APDU_size += put_uint16_t_be(opts, res_APDU);
|
res_APDU_size += put_uint16_be(opts, res_APDU);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
|
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
|
||||||
file_t *tf = search_file(EF_DEVOPS);
|
file_t *tf = file_search(EF_DEVOPS);
|
||||||
file_put_data(tf, newopts, sizeof(newopts));
|
file_put_data(tf, newopts, sizeof(newopts));
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == CMD_SECURE_LOCK) { // secure lock
|
else if (cmd == CMD_SECURE_LOCK) { // secure lock
|
||||||
@@ -76,7 +76,7 @@ int cmd_extras(void) {
|
|||||||
mbedtls_ecdh_context hkey;
|
mbedtls_ecdh_context hkey;
|
||||||
mbedtls_ecdh_init(&hkey);
|
mbedtls_ecdh_init(&hkey);
|
||||||
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
|
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
|
||||||
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_gen, NULL);
|
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_fill_iterator, NULL);
|
||||||
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
|
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
|
||||||
ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Qp, apdu.data, apdu.nc);
|
ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Qp, apdu.data, apdu.nc);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -87,7 +87,7 @@ int cmd_extras(void) {
|
|||||||
|
|
||||||
uint8_t buf[MBEDTLS_ECP_MAX_BYTES];
|
uint8_t buf[MBEDTLS_ECP_MAX_BYTES];
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL);
|
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdh_free(&hkey);
|
mbedtls_ecdh_free(&hkey);
|
||||||
mbedtls_platform_zeroize(buf, sizeof(buf));
|
mbedtls_platform_zeroize(buf, sizeof(buf));
|
||||||
@@ -123,7 +123,7 @@ int cmd_extras(void) {
|
|||||||
(P2(apdu) == SECURE_LOCK_DISABLE && (opts & HSM_OPT_SECURE_LOCK))) {
|
(P2(apdu) == SECURE_LOCK_DISABLE && (opts & HSM_OPT_SECURE_LOCK))) {
|
||||||
uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO };
|
uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO };
|
||||||
for (size_t t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) {
|
for (size_t t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) {
|
||||||
file_t *tf = search_file(tfids[t]);
|
file_t *tf = file_search(tfids[t]);
|
||||||
if (tf) {
|
if (tf) {
|
||||||
uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf));
|
uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf));
|
||||||
memcpy(tmp, file_get_data(tf), file_get_size(tf));
|
memcpy(tmp, file_get_data(tf), file_get_size(tf));
|
||||||
@@ -141,9 +141,9 @@ int cmd_extras(void) {
|
|||||||
else if (P2(apdu) == SECURE_LOCK_DISABLE) {
|
else if (P2(apdu) == SECURE_LOCK_DISABLE) {
|
||||||
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
|
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
|
||||||
}
|
}
|
||||||
file_t *tf = search_file(EF_DEVOPS);
|
file_t *tf = file_search(EF_DEVOPS);
|
||||||
file_put_data(tf, newopts, sizeof(newopts));
|
file_put_data(tf, newopts, sizeof(newopts));
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
else if (P2(apdu) == SECURE_LOCK_MASK && (opts & HSM_OPT_SECURE_LOCK)) {
|
else if (P2(apdu) == SECURE_LOCK_MASK && (opts & HSM_OPT_SECURE_LOCK)) {
|
||||||
memcpy(mkek_mask, apdu.data, MKEK_KEY_SIZE);
|
memcpy(mkek_mask, apdu.data, MKEK_KEY_SIZE);
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ int cmd_general_authenticate(void) {
|
|||||||
pubkey_len = tag_len + 1;
|
pubkey_len = tag_len + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_t *fkey = search_file(EF_KEY_DEV);
|
file_t *fkey = file_search(EF_KEY_DEV);
|
||||||
if (!fkey) {
|
if (!fkey) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
mbedtls_ecp_keypair ectx;
|
mbedtls_ecp_keypair ectx;
|
||||||
mbedtls_ecp_keypair_init(&ectx);
|
mbedtls_ecp_keypair_init(&ectx);
|
||||||
r = load_private_key_ecdh(&ectx, fkey);
|
r = load_private_key_ecdh(&ectx, fkey);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ectx);
|
mbedtls_ecp_keypair_free(&ectx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -77,12 +77,7 @@ int cmd_general_authenticate(void) {
|
|||||||
}
|
}
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
uint8_t derived[MBEDTLS_ECP_MAX_BYTES];
|
uint8_t derived[MBEDTLS_ECP_MAX_BYTES];
|
||||||
r = mbedtls_ecdh_calc_secret(&ctx,
|
r = mbedtls_ecdh_calc_secret(&ctx, &olen, derived, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
|
||||||
&olen,
|
|
||||||
derived,
|
|
||||||
MBEDTLS_ECP_MAX_BYTES,
|
|
||||||
random_gen,
|
|
||||||
NULL);
|
|
||||||
mbedtls_ecdh_free(&ctx);
|
mbedtls_ecdh_free(&ctx);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -110,7 +105,7 @@ int cmd_general_authenticate(void) {
|
|||||||
r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size);
|
r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size);
|
||||||
|
|
||||||
free(t);
|
free(t);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
res_APDU_size += 8;
|
res_APDU_size += 8;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ int cmd_initialize(void) {
|
|||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
|
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
|
||||||
initialize_flash(true);
|
file_initialize_flash(true);
|
||||||
scan_all();
|
scan_all();
|
||||||
has_session_pin = has_session_sopin = has_mkek_mask = false;
|
has_session_pin = has_session_sopin = has_mkek_mask = false;
|
||||||
uint16_t tag = 0x0;
|
uint16_t tag = 0x0;
|
||||||
@@ -55,7 +55,7 @@ int cmd_initialize(void) {
|
|||||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||||
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag == 0x80) { //options
|
if (tag == 0x80) { //options
|
||||||
file_t *tf = search_file(EF_DEVOPS);
|
file_t *tf = file_search(EF_DEVOPS);
|
||||||
file_put_data(tf, tag_data, tag_len);
|
file_put_data(tf, tag_data, tag_len);
|
||||||
}
|
}
|
||||||
else if (tag == 0x81) { //user pin
|
else if (tag == 0x81) { //user pin
|
||||||
@@ -81,7 +81,7 @@ int cmd_initialize(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tag == 0x91) { //retries user pin
|
else if (tag == 0x91) { //retries user pin
|
||||||
file_t *tf = search_file(EF_PIN1_MAX_RETRIES);
|
file_t *tf = file_search(EF_PIN1_MAX_RETRIES);
|
||||||
if (tf && tf->data) {
|
if (tf && tf->data) {
|
||||||
file_put_data(tf, tag_data, tag_len);
|
file_put_data(tf, tag_data, tag_len);
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ int cmd_initialize(void) {
|
|||||||
file_put_data(tf, NULL, 0);
|
file_put_data(tf, NULL, 0);
|
||||||
}
|
}
|
||||||
else if (tag == 0x93) {
|
else if (tag == 0x93) {
|
||||||
file_t *ef_puk = search_file(EF_PUKAUT);
|
file_t *ef_puk = file_search(EF_PUKAUT);
|
||||||
if (!ef_puk) {
|
if (!ef_puk) {
|
||||||
release_mkek(mkek);
|
release_mkek(mkek);
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
@@ -131,15 +131,15 @@ int cmd_initialize(void) {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_t *tf_kd = search_file(EF_KEY_DOMAIN);
|
file_t *tf_kd = file_search(EF_KEY_DOMAIN);
|
||||||
if (!tf_kd) {
|
if (!tf_kd) {
|
||||||
release_mkek(mkek);
|
release_mkek(mkek);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (ret_mkek != PICOKEY_OK) {
|
if (ret_mkek != PICOKEYS_OK) {
|
||||||
ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same
|
ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same
|
||||||
}
|
}
|
||||||
if (store_mkek(ret_mkek == PICOKEY_OK ? mkek : NULL) != PICOKEY_OK) {
|
if (store_mkek(ret_mkek == PICOKEYS_OK ? mkek : NULL) != PICOKEYS_OK) {
|
||||||
release_mkek(mkek);
|
release_mkek(mkek);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -147,43 +147,43 @@ int cmd_initialize(void) {
|
|||||||
if (dkeks) {
|
if (dkeks) {
|
||||||
if (*dkeks > 0) {
|
if (*dkeks > 0) {
|
||||||
uint16_t d = *dkeks;
|
uint16_t d = *dkeks;
|
||||||
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int r = save_dkek_key(0, random_bytes_get(32));
|
int r = save_dkek_key(0, random_bytes_get(32));
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
uint16_t d = 0x0101;
|
uint16_t d = 0x0101;
|
||||||
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint16_t d = 0x0000;
|
uint16_t d = 0x0000;
|
||||||
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (kds) {
|
if (kds) {
|
||||||
uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS);
|
uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS);
|
||||||
memset(t, 0xff, 2 * k);
|
memset(t, 0xff, 2 * k);
|
||||||
if (file_put_data(tf_kd, t, 2 * k) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, t, 2 * k) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* When initialized, it has all credentials */
|
/* When initialized, it has all credentials */
|
||||||
isUserAuthenticated = true;
|
isUserAuthenticated = true;
|
||||||
/* Create terminal private key */
|
/* Create terminal private key */
|
||||||
file_t *fdkey = search_file(EF_KEY_DEV);
|
file_t *fdkey = file_search(EF_KEY_DEV);
|
||||||
if (!fdkey) {
|
if (!fdkey) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (ret_mkek != PICOKEY_OK || !file_has_data(fdkey)) {
|
if (ret_mkek != PICOKEYS_OK || !file_has_data(fdkey)) {
|
||||||
mbedtls_ecdsa_context ecdsa;
|
mbedtls_ecdsa_context ecdsa;
|
||||||
mbedtls_ecdsa_init(&ecdsa);
|
mbedtls_ecdsa_init(&ecdsa);
|
||||||
mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_SECP256R1;
|
mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_SECP256R1;
|
||||||
@@ -194,59 +194,63 @@ int cmd_initialize(void) {
|
|||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
ret = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL);
|
ret = mbedtls_ecp_keypair_calc_public(&ecdsa, random_fill_iterator, NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
|
return SW_EXEC_ERROR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, NULL);
|
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id);
|
ret = store_keys(&ecdsa, PICOKEYS_KEY_EC, key_id);
|
||||||
if (ret != PICOKEY_OK) {
|
if (ret != PICOKEYS_OK) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
uint16_t ee_len = 0, term_len = 0;
|
uint16_t ee_len = 0, term_len = 0;
|
||||||
if ((ee_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
if ((ee_len = asn1_cvc_aut(&ecdsa, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
file_t *fpk = search_file(EF_EE_DEV);
|
file_t *fpk = file_search(EF_EE_DEV);
|
||||||
ret = file_put_data(fpk, res_APDU, ee_len);
|
ret = file_put_data(fpk, res_APDU, ee_len);
|
||||||
if (ret != 0) {
|
if (ret != PICOKEYS_OK) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((term_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU + ee_len, MAX_APDU_DATA - ee_len, NULL, 0, true)) == 0) {
|
if ((term_len = asn1_cvc_cert(&ecdsa, PICOKEYS_KEY_EC, res_APDU + ee_len, MAX_APDU_DATA - ee_len, NULL, 0, true)) == 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
fpk = search_file(EF_TERMCA);
|
fpk = file_search(EF_TERMCA);
|
||||||
ret = file_put_data(fpk, res_APDU, ee_len + term_len);
|
ret = file_put_data(fpk, res_APDU, ee_len + term_len);
|
||||||
if (ret != 0) {
|
if (ret != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *keyid = (const uint8_t *) "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",
|
const uint8_t *keyid = (const uint8_t *) "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",
|
||||||
*label = (const uint8_t *) "ESPICOHSMTR";
|
*label = (const uint8_t *) "ESPICOHSMTR";
|
||||||
uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, MAX_APDU_DATA);
|
uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, MAX_APDU_DATA);
|
||||||
fpk = search_file(EF_PRKD_DEV);
|
fpk = file_search(EF_PRKD_DEV);
|
||||||
ret = file_put_data(fpk, res_APDU, prkd_len);
|
ret = file_put_data(fpk, res_APDU, prkd_len);
|
||||||
}
|
}
|
||||||
if (ret != 0) {
|
if (ret != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
reset_puk_store();
|
reset_puk_store();
|
||||||
}
|
}
|
||||||
else { //free memory bytes request
|
else { //free memory bytes request
|
||||||
int heap_left = heapLeft();
|
int heap_left = heapLeft();
|
||||||
res_APDU_size += put_uint32_t_be(heap_left, res_APDU);
|
res_APDU_size += put_uint32_be(heap_left, res_APDU);
|
||||||
res_APDU[4] = 0;
|
res_APDU[4] = 0;
|
||||||
res_APDU[5] = HSM_VERSION_MAJOR;
|
res_APDU[5] = HSM_VERSION_MAJOR;
|
||||||
res_APDU[6] = HSM_VERSION_MINOR;
|
res_APDU[6] = HSM_VERSION_MINOR;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ int cmd_key_domain(void) {
|
|||||||
if (p2 >= MAX_KEY_DOMAINS) {
|
if (p2 >= MAX_KEY_DOMAINS) {
|
||||||
return SW_WRONG_P1P2();
|
return SW_WRONG_P1P2();
|
||||||
}
|
}
|
||||||
file_t *tf_kd = search_file(EF_KEY_DOMAIN);
|
file_t *tf_kd = file_search(EF_KEY_DOMAIN);
|
||||||
if (!tf_kd) {
|
if (!tf_kd) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -72,8 +72,8 @@ int cmd_key_domain(void) {
|
|||||||
import_dkek_share(p2, apdu.data);
|
import_dkek_share(p2, apdu.data);
|
||||||
if (++current_dkeks >= dkeks) {
|
if (++current_dkeks >= dkeks) {
|
||||||
int r = save_dkek_key(p2, NULL);
|
int r = save_dkek_key(p2, NULL);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
if (r == PICOKEY_NO_LOGIN) {
|
if (r == PICOKEYS_NO_LOGIN) {
|
||||||
pending_save_dkek = p2;
|
pending_save_dkek = p2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -86,13 +86,13 @@ int cmd_key_domain(void) {
|
|||||||
uint8_t t[MAX_KEY_DOMAINS * 2];
|
uint8_t t[MAX_KEY_DOMAINS * 2];
|
||||||
memcpy(t, kdata, tf_kd_size);
|
memcpy(t, kdata, tf_kd_size);
|
||||||
t[2 * p2 + 1] = current_dkeks;
|
t[2 * p2 + 1] = current_dkeks;
|
||||||
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
file_t *tf = search_file(EF_XKEK + p2);
|
file_t *tf = file_search(EF_XKEK + p2);
|
||||||
if (current_dkeks == 0xff && !file_has_data(tf)) { //XKEK have always 0xff
|
if (current_dkeks == 0xff && !file_has_data(tf)) { //XKEK have always 0xff
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ int cmd_key_domain(void) {
|
|||||||
}
|
}
|
||||||
if (p1 == 0x3) { //if key domain is not empty, command is denied
|
if (p1 == 0x3) { //if key domain is not empty, command is denied
|
||||||
for (uint16_t i = 1; i < 256; i++) {
|
for (uint16_t i = 1; i < 256; i++) {
|
||||||
file_t *fkey = search_file(KEY_PREFIX << 8 | (uint8_t)i);
|
file_t *fkey = file_search(KEY_PREFIX << 8 | (uint8_t)i);
|
||||||
if (get_key_domain(fkey) == p2) {
|
if (get_key_domain(fkey) == p2) {
|
||||||
return SW_FILE_EXISTS();
|
return SW_FILE_EXISTS();
|
||||||
}
|
}
|
||||||
@@ -129,21 +129,21 @@ int cmd_key_domain(void) {
|
|||||||
else if (p1 == 0x4) {
|
else if (p1 == 0x4) {
|
||||||
t[2 * p2 + 1] = current_dkeks = 0;
|
t[2 * p2 + 1] = current_dkeks = 0;
|
||||||
}
|
}
|
||||||
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) {
|
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
file_t *tf = NULL;
|
file_t *tf = NULL;
|
||||||
if ((tf = search_file(EF_DKEK + p2))) {
|
if ((tf = file_search(EF_DKEK + p2))) {
|
||||||
if (delete_file(tf) != PICOKEY_OK) {
|
if (file_delete(tf) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p1 == 0x3 && (tf = search_file(EF_XKEK + p2))) {
|
if (p1 == 0x3 && (tf = file_search(EF_XKEK + p2))) {
|
||||||
if (delete_file(tf) != PICOKEY_OK) {
|
if (file_delete(tf) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
if (p1 == 0x3) {
|
if (p1 == 0x3) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ int cmd_key_domain(void) {
|
|||||||
else if (p1 == 0x2) { //XKEK Key Domain creation
|
else if (p1 == 0x2) { //XKEK Key Domain creation
|
||||||
if (apdu.nc > 0) {
|
if (apdu.nc > 0) {
|
||||||
uint16_t pub_len = 0;
|
uint16_t pub_len = 0;
|
||||||
file_t *fterm = search_file(EF_TERMCA);
|
file_t *fterm = file_search(EF_TERMCA);
|
||||||
if (!fterm) {
|
if (!fterm) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ int cmd_key_domain(void) {
|
|||||||
t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
|
t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
|
||||||
if (t86) {
|
if (t86) {
|
||||||
file_put_data(tf, t86 + 1, (uint16_t)t86_len - 1);
|
file_put_data(tf, t86 + 1, (uint16_t)t86_len - 1);
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ int cmd_key_domain(void) {
|
|||||||
res_APDU[1] = dkeks > current_dkeks ? dkeks - current_dkeks : 0;
|
res_APDU[1] = dkeks > current_dkeks ? dkeks - current_dkeks : 0;
|
||||||
dkek_kcv(p2, res_APDU + 2);
|
dkek_kcv(p2, res_APDU + 2);
|
||||||
res_APDU_size = 2 + 8;
|
res_APDU_size = 2 + 8;
|
||||||
file_t *tf = search_file(EF_XKEK + p2);
|
file_t *tf = file_search(EF_XKEK + p2);
|
||||||
if (file_has_data(tf)) {
|
if (file_has_data(tf)) {
|
||||||
memcpy(res_APDU + 10, file_get_data(tf), file_get_size(tf));
|
memcpy(res_APDU + 10, file_get_data(tf), file_get_size(tf));
|
||||||
res_APDU_size += file_get_size(tf);
|
res_APDU_size += file_get_size(tf);
|
||||||
|
|||||||
@@ -44,24 +44,24 @@ int cmd_key_gen(void) {
|
|||||||
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
||||||
int aes_type = 0x0;
|
int aes_type = 0x0;
|
||||||
if (key_size == 16) {
|
if (key_size == 16) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_128;
|
aes_type = PICOKEYS_KEY_AES_128;
|
||||||
}
|
}
|
||||||
else if (key_size == 24) {
|
else if (key_size == 24) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_192;
|
aes_type = PICOKEYS_KEY_AES_192;
|
||||||
}
|
}
|
||||||
else if (key_size == 32) {
|
else if (key_size == 32) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_256;
|
aes_type = PICOKEYS_KEY_AES_256;
|
||||||
}
|
}
|
||||||
else if (key_size == 64) {
|
else if (key_size == 64) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_512;
|
aes_type = PICOKEYS_KEY_AES_512;
|
||||||
}
|
}
|
||||||
r = store_keys(aes_key, aes_type, key_id);
|
r = store_keys(aes_key, aes_type, key_id);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
if (find_and_store_meta_key(key_id) != PICOKEY_OK) {
|
if (find_and_store_meta_key(key_id) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ int cmd_key_unwrap(void) {
|
|||||||
uint8_t *data = apdu.data;
|
uint8_t *data = apdu.data;
|
||||||
uint16_t data_len = apdu.nc;
|
uint16_t data_len = apdu.nc;
|
||||||
if (data_len == 0) { // New style
|
if (data_len == 0) { // New style
|
||||||
file_t *tef = search_file(0x2F10);
|
file_t *tef = file_search(0x2F10);
|
||||||
if (!file_has_data(tef)) {
|
if (!file_has_data(tef)) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -46,78 +46,72 @@ int cmd_key_unwrap(void) {
|
|||||||
if (key_type == 0x0) {
|
if (key_type == 0x0) {
|
||||||
return SW_DATA_INVALID();
|
return SW_DATA_INVALID();
|
||||||
}
|
}
|
||||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
do {
|
do {
|
||||||
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
|
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
|
||||||
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
} while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&ctx, PICO_KEYS_KEY_RSA, key_id);
|
r = store_keys(&ctx, PICOKEYS_KEY_RSA, key_id);
|
||||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICOKEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
mbedtls_ecp_keypair ctx;
|
mbedtls_ecp_keypair ctx;
|
||||||
mbedtls_ecp_keypair_init(&ctx);
|
mbedtls_ecp_keypair_init(&ctx);
|
||||||
do {
|
do {
|
||||||
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
|
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
|
||||||
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
} while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&ctx, PICO_KEYS_KEY_EC, key_id);
|
r = store_keys(&ctx, PICOKEYS_KEY_EC, key_id);
|
||||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES) {
|
else if (key_type & PICOKEYS_KEY_AES) {
|
||||||
uint8_t aes_key[64];
|
uint8_t aes_key[64];
|
||||||
int key_size = 0, aes_type = 0;
|
int key_size = 0, aes_type = 0;
|
||||||
do {
|
do {
|
||||||
r = dkek_decode_key((uint8_t)++kdom,
|
r = dkek_decode_key((uint8_t)++kdom, aes_key, data, data_len, &key_size, &allowed, &allowed_len);
|
||||||
aes_key,
|
} while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
data,
|
if (r != PICOKEYS_OK) {
|
||||||
data_len,
|
|
||||||
&key_size,
|
|
||||||
&allowed,
|
|
||||||
&allowed_len);
|
|
||||||
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
|
||||||
if (r != PICOKEY_OK) {
|
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (key_size == 64) {
|
if (key_size == 64) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_512;
|
aes_type = PICOKEYS_KEY_AES_512;
|
||||||
}
|
}
|
||||||
else if (key_size == 32) {
|
else if (key_size == 32) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_256;
|
aes_type = PICOKEYS_KEY_AES_256;
|
||||||
}
|
}
|
||||||
else if (key_size == 24) {
|
else if (key_size == 24) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_192;
|
aes_type = PICOKEYS_KEY_AES_192;
|
||||||
}
|
}
|
||||||
else if (key_size == 16) {
|
else if (key_size == 16) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_128;
|
aes_type = PICOKEYS_KEY_AES_128;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(aes_key, aes_type, key_id);
|
r = store_keys(aes_key, aes_type, key_id);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +130,7 @@ int cmd_key_unwrap(void) {
|
|||||||
}
|
}
|
||||||
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
|
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
|
||||||
free(meta);
|
free(meta);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,6 +142,6 @@ int cmd_key_unwrap(void) {
|
|||||||
}
|
}
|
||||||
res_APDU_size = 0;
|
res_APDU_size = 0;
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ int cmd_key_wrap(void) {
|
|||||||
if (!isUserAuthenticated) {
|
if (!isUserAuthenticated) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
file_t *ef = search_file((KEY_PREFIX << 8) | key_id);
|
file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ int cmd_key_wrap(void) {
|
|||||||
if (kdom == 0xff) {
|
if (kdom == 0xff) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
file_t *tf_kd = search_file(EF_KEY_DOMAIN);
|
file_t *tf_kd = file_search(EF_KEY_DOMAIN);
|
||||||
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2 * kdom] : 0,
|
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2 * kdom] : 0,
|
||||||
current_dkeks = kdata ? kdata[2 * kdom + 1] : 0;
|
current_dkeks = kdata ? kdata[2 * kdom + 1] : 0;
|
||||||
if (dkeks != current_dkeks || dkeks == 0 || dkeks == 0xff) {
|
if (dkeks != current_dkeks || dkeks == 0 || dkeks == 0xff) {
|
||||||
@@ -47,7 +47,7 @@ int cmd_key_wrap(void) {
|
|||||||
if (key_has_purpose(ef, ALGO_WRAP) == false) {
|
if (key_has_purpose(ef, ALGO_WRAP) == false) {
|
||||||
return SW_CONDITIONS_NOT_SATISFIED();
|
return SW_CONDITIONS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
file_t *prkd = search_file((PRKD_PREFIX << 8) | key_id);
|
file_t *prkd = file_search((PRKD_PREFIX << 8) | key_id);
|
||||||
if (!prkd) {
|
if (!prkd) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
@@ -58,28 +58,28 @@ int cmd_key_wrap(void) {
|
|||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
r = load_private_key_rsa(&ctx, ef);
|
r = load_private_key_rsa(&ctx, ef);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = dkek_encode_key(kdom, &ctx, PICO_KEYS_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
|
r = dkek_encode_key(kdom, &ctx, PICOKEYS_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||||
mbedtls_ecp_keypair ctx;
|
mbedtls_ecp_keypair ctx;
|
||||||
mbedtls_ecp_keypair_init(&ctx);
|
mbedtls_ecp_keypair_init(&ctx);
|
||||||
r = load_private_key_ec(&ctx, ef);
|
r = load_private_key_ec(&ctx, ef);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = dkek_encode_key(kdom, &ctx, PICO_KEYS_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
|
r = dkek_encode_key(kdom, &ctx, PICOKEYS_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||||
@@ -88,27 +88,27 @@ int cmd_key_wrap(void) {
|
|||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t key_size = file_get_size(ef), aes_type = PICO_KEYS_KEY_AES;
|
uint16_t key_size = file_get_size(ef), aes_type = PICOKEYS_KEY_AES;
|
||||||
memcpy(kdata_aes, file_get_data(ef), key_size);
|
memcpy(kdata_aes, file_get_data(ef), key_size);
|
||||||
if (mkek_decrypt(kdata_aes, key_size) != 0) {
|
if (mkek_decrypt(kdata_aes, key_size) != 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (key_size == 64) {
|
if (key_size == 64) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_512;
|
aes_type = PICOKEYS_KEY_AES_512;
|
||||||
}
|
}
|
||||||
else if (key_size == 32) {
|
else if (key_size == 32) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_256;
|
aes_type = PICOKEYS_KEY_AES_256;
|
||||||
}
|
}
|
||||||
else if (key_size == 24) {
|
else if (key_size == 24) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_192;
|
aes_type = PICOKEYS_KEY_AES_192;
|
||||||
}
|
}
|
||||||
else if (key_size == 16) {
|
else if (key_size == 16) {
|
||||||
aes_type = PICO_KEYS_KEY_AES_128;
|
aes_type = PICOKEYS_KEY_AES_128;
|
||||||
}
|
}
|
||||||
r = dkek_encode_key(kdom, kdata_aes, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
|
r = dkek_encode_key(kdom, kdata_aes, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
|
||||||
mbedtls_platform_zeroize(kdata_aes, sizeof(kdata_aes));
|
mbedtls_platform_zeroize(kdata_aes, sizeof(kdata_aes));
|
||||||
}
|
}
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
res_APDU_size = wrap_len;
|
res_APDU_size = wrap_len;
|
||||||
|
|||||||
@@ -49,17 +49,16 @@ int cmd_keypair_gen(void) {
|
|||||||
}
|
}
|
||||||
mbedtls_rsa_context rsa;
|
mbedtls_rsa_context rsa;
|
||||||
mbedtls_rsa_init(&rsa);
|
mbedtls_rsa_init(&rsa);
|
||||||
uint8_t index = 0;
|
ret = mbedtls_rsa_gen_key(&rsa, random_fill_iterator, NULL, key_size, exponent);
|
||||||
ret = mbedtls_rsa_gen_key(&rsa, random_gen, &index, key_size, exponent);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&rsa, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&rsa, PICOKEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id);
|
ret = store_keys(&rsa, PICOKEYS_KEY_RSA, key_id);
|
||||||
if (ret != PICOKEY_OK) {
|
if (ret != PICOKEYS_OK) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -90,8 +89,7 @@ int cmd_keypair_gen(void) {
|
|||||||
}
|
}
|
||||||
mbedtls_ecdsa_context ecdsa;
|
mbedtls_ecdsa_context ecdsa;
|
||||||
mbedtls_ecdsa_init(&ecdsa);
|
mbedtls_ecdsa_init(&ecdsa);
|
||||||
uint8_t index = 0;
|
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_fill_iterator, NULL);
|
||||||
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, &index);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -107,12 +105,11 @@ int cmd_keypair_gen(void) {
|
|||||||
if (a92.data[0] > MAX_KEY_DOMAINS) {
|
if (a92.data[0] > MAX_KEY_DOMAINS) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
file_t *tf_xkek = search_file(EF_XKEK + a92.data[0]);
|
file_t *tf_xkek = file_search(EF_XKEK + a92.data[0]);
|
||||||
if (!tf_xkek) {
|
if (!tf_xkek) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
ext.len = 2 + 2 + (uint16_t)strlen(OID_ID_KEY_DOMAIN_UID) + 2 + file_get_size(
|
ext.len = 2 + 2 + (uint16_t)strlen(OID_ID_KEY_DOMAIN_UID) + 2 + file_get_size(tf_xkek);
|
||||||
tf_xkek);
|
|
||||||
ext.data = (uint8_t *) calloc(1, ext.len);
|
ext.data = (uint8_t *) calloc(1, ext.len);
|
||||||
uint8_t *pe = ext.data;
|
uint8_t *pe = ext.data;
|
||||||
*pe++ = 0x73;
|
*pe++ = 0x73;
|
||||||
@@ -127,7 +124,7 @@ int cmd_keypair_gen(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, ext.data, ext.len)) == 0) {
|
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ecdsa, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, ext.data, ext.len)) == 0) {
|
||||||
if (ext.data) {
|
if (ext.data) {
|
||||||
free(ext.data);
|
free(ext.data);
|
||||||
}
|
}
|
||||||
@@ -137,9 +134,9 @@ int cmd_keypair_gen(void) {
|
|||||||
if (ext.data) {
|
if (ext.data) {
|
||||||
free(ext.data);
|
free(ext.data);
|
||||||
}
|
}
|
||||||
ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id);
|
ret = store_keys(&ecdsa, PICOKEYS_KEY_EC, key_id);
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
if (ret != PICOKEY_OK) {
|
if (ret != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +146,7 @@ int cmd_keypair_gen(void) {
|
|||||||
else {
|
else {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
if (find_and_store_meta_key(key_id) != PICOKEY_OK) {
|
if (find_and_store_meta_key(key_id) != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
|
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
|
||||||
@@ -160,6 +157,6 @@ int cmd_keypair_gen(void) {
|
|||||||
if (apdu.ne == 0) {
|
if (apdu.ne == 0) {
|
||||||
apdu.ne = res_APDU_size;
|
apdu.ne = res_APDU_size;
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,17 @@
|
|||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
|
extern uint16_t dynamic_files;
|
||||||
|
extern file_t dynamic_file[];
|
||||||
|
|
||||||
int cmd_list_keys(void) {
|
int cmd_list_keys(void) {
|
||||||
/* First we send DEV private key */
|
/* First we send DEV private key */
|
||||||
/* Both below conditions should be always TRUE */
|
/* Both below conditions should be always TRUE */
|
||||||
if (search_file(EF_PRKD_DEV)) {
|
if (file_search(EF_PRKD_DEV)) {
|
||||||
res_APDU_size += put_uint16_t_be(EF_PRKD_DEV, res_APDU + res_APDU_size);
|
res_APDU_size += put_uint16_be(EF_PRKD_DEV, res_APDU + res_APDU_size);
|
||||||
}
|
}
|
||||||
if (search_file(EF_KEY_DEV)) {
|
if (file_search(EF_KEY_DEV)) {
|
||||||
res_APDU_size += put_uint16_t_be(EF_KEY_DEV, res_APDU + res_APDU_size);
|
res_APDU_size += put_uint16_be(EF_KEY_DEV, res_APDU + res_APDU_size);
|
||||||
}
|
}
|
||||||
//first CC
|
//first CC
|
||||||
for (int i = 0; i < dynamic_files; i++) {
|
for (int i = 0; i < dynamic_files; i++) {
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ int cmd_mse(void) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (p2 == 0xB6) {
|
if (p2 == 0xB6) {
|
||||||
if (puk_store_select_chr(tag_data) == PICOKEY_OK) {
|
if (puk_store_select_chr(tag_data) == PICOKEYS_OK) {
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p2 == 0xA4) { /* Aut */
|
else if (p2 == 0xA4) { /* Aut */
|
||||||
for (uint8_t i = 0; i < MAX_PUK; i++) {
|
for (uint8_t i = 0; i < MAX_PUK; i++) {
|
||||||
file_t *ef = search_file(EF_PUK + i);
|
file_t *ef = file_search(EF_PUK + i);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,23 +39,22 @@ int cmd_pso(void) {
|
|||||||
apdu.nc += tlv_len;
|
apdu.nc += tlv_len;
|
||||||
}
|
}
|
||||||
int r = cvc_verify(apdu.data, (uint16_t)apdu.nc, current_puk->cvcert, current_puk->cvcert_len);
|
int r = cvc_verify(apdu.data, (uint16_t)apdu.nc, current_puk->cvcert, current_puk->cvcert_len);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
if (r == PICOKEY_WRONG_DATA) {
|
if (r == PICOKEYS_WRONG_DATA) {
|
||||||
return SW_DATA_INVALID();
|
return SW_DATA_INVALID();
|
||||||
}
|
}
|
||||||
else if (r == PICOKEY_WRONG_SIGNATURE) {
|
else if (r == PICOKEYS_WRONG_SIGNATURE) {
|
||||||
return SW_CONDITIONS_NOT_SATISFIED();
|
return SW_CONDITIONS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < 0xfe; i++) {
|
for (uint8_t i = 0; i < 0xfe; i++) {
|
||||||
uint16_t fid = (CA_CERTIFICATE_PREFIX << 8) | i;
|
uint16_t fid = (CA_CERTIFICATE_PREFIX << 8) | i;
|
||||||
file_t *ca_ef = search_file(fid);
|
file_t *ca_ef = file_search(fid);
|
||||||
if (!ca_ef) {
|
if (!ca_ef) {
|
||||||
ca_ef = file_new(fid);
|
ca_ef = file_new(fid);
|
||||||
file_put_data(ca_ef, apdu.data, (uint16_t)apdu.nc);
|
file_put_data(ca_ef, apdu.data, (uint16_t)apdu.nc);
|
||||||
if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef),
|
if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef), false) != PICOKEYS_OK) {
|
||||||
false) != PICOKEY_OK) {
|
|
||||||
return SW_FILE_FULL();
|
return SW_FILE_FULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,30 +124,18 @@ int cmd_pso(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_t *cd_ef = file_new((CD_PREFIX << 8) | i);
|
file_t *cd_ef = file_new((CD_PREFIX << 8) | i);
|
||||||
uint16_t cd_len = (uint16_t)asn1_build_cert_description(chr,
|
uint16_t cd_len = (uint16_t)asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, NULL, 0);
|
||||||
chr_len,
|
|
||||||
puk_bin,
|
|
||||||
puk_bin_len,
|
|
||||||
fid,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
if (cd_len == 0) {
|
if (cd_len == 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
uint8_t *buf = (uint8_t *) calloc(cd_len, sizeof(uint8_t));
|
uint8_t *buf = (uint8_t *) calloc(cd_len, sizeof(uint8_t));
|
||||||
r = (int)asn1_build_cert_description(chr,
|
r = (int)asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, buf, cd_len);
|
||||||
chr_len,
|
|
||||||
puk_bin,
|
|
||||||
puk_bin_len,
|
|
||||||
fid,
|
|
||||||
buf,
|
|
||||||
cd_len);
|
|
||||||
file_put_data(cd_ef, buf, cd_len);
|
file_put_data(cd_ef, buf, cd_len);
|
||||||
free(buf);
|
free(buf);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
int cmd_puk_auth(void) {
|
int cmd_puk_auth(void) {
|
||||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||||
file_t *ef_puk = search_file(EF_PUKAUT);
|
file_t *ef_puk = file_search(EF_PUKAUT);
|
||||||
if (!file_has_data(ef_puk)) {
|
if (!file_has_data(ef_puk)) {
|
||||||
if (apdu.nc > 0) {
|
if (apdu.nc > 0) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
@@ -37,7 +37,7 @@ int cmd_puk_auth(void) {
|
|||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < puk_data[0]; i++) {
|
for (uint8_t i = 0; i < puk_data[0]; i++) {
|
||||||
ef = search_file(EF_PUK + i);
|
ef = file_search(EF_PUK + i);
|
||||||
if (!ef) { /* Never should not happen */
|
if (!ef) { /* Never should not happen */
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
@@ -56,13 +56,13 @@ int cmd_puk_auth(void) {
|
|||||||
if (p2 >= puk_data[0]) {
|
if (p2 >= puk_data[0]) {
|
||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
}
|
}
|
||||||
ef = search_file(EF_PUK + p2);
|
ef = file_search(EF_PUK + p2);
|
||||||
if (!ef) { /* Never should not happen */
|
if (!ef) { /* Never should not happen */
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_put_data(ef, apdu.data, (uint16_t)apdu.nc);
|
file_put_data(ef, apdu.data, (uint16_t)apdu.nc);
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
@@ -72,7 +72,7 @@ int cmd_puk_auth(void) {
|
|||||||
if (p2 >= puk_data[0]) {
|
if (p2 >= puk_data[0]) {
|
||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
}
|
}
|
||||||
file_t *ef = search_file(EF_PUK + p2);
|
file_t *ef = file_search(EF_PUK + p2);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,28 +26,28 @@ int cmd_read_binary(void) {
|
|||||||
|
|
||||||
if ((ins & 0x1) == 0) {
|
if ((ins & 0x1) == 0) {
|
||||||
if ((p1 & 0x80) != 0) {
|
if ((p1 & 0x80) != 0) {
|
||||||
if (!(ef = search_file(p1 & 0x1f))) {
|
if (!(ef = file_search(p1 & 0x1f))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
offset = p2;
|
offset = p2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
offset = make_uint16_t_be(p1, p2) & 0x7fff;
|
offset = make_uint16_be(p1, p2) & 0x7fff;
|
||||||
ef = currentEF;
|
ef = currentEF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
|
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
|
||||||
if (!(ef = search_file(p2 & 0x1f))) {
|
if (!(ef = file_search(p2 & 0x1f))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint16_t file_id = make_uint16_t_be(p1, p2); // & 0x7fff;
|
uint16_t file_id = make_uint16_be(p1, p2); // & 0x7fff;
|
||||||
if (file_id == 0x0) {
|
if (file_id == 0x0) {
|
||||||
ef = currentEF;
|
ef = currentEF;
|
||||||
}
|
}
|
||||||
else if (!(ef = search_file(file_id))) {
|
else if (!(ef = file_search(file_id))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ int cmd_read_binary(void) {
|
|||||||
memset(ef->acl, 0x90, sizeof(ef->acl)); //force PIN for protected data objects
|
memset(ef->acl, 0x90, sizeof(ef->acl)); //force PIN for protected data objects
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ef->fid >> 8) == KEY_PREFIX || !authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
if ((ef->fid >> 8) == KEY_PREFIX || !file_authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
if (ef->data) {
|
if (ef->data) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "crypto_utils.h"
|
#include "crypto_utils.h"
|
||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
#include "kek.h"
|
#include "kek.h"
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
int cmd_reset_retry(void) {
|
int cmd_reset_retry(void) {
|
||||||
if (P2(apdu) != 0x81) {
|
if (P2(apdu) != 0x81) {
|
||||||
@@ -55,19 +56,19 @@ int cmd_reset_retry(void) {
|
|||||||
}
|
}
|
||||||
newpin_len = (uint8_t)apdu.nc;
|
newpin_len = (uint8_t)apdu.nc;
|
||||||
}
|
}
|
||||||
if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) {
|
if (pin_reset_retries(file_pin1, true) != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
uint8_t mkek[MKEK_SIZE];
|
uint8_t mkek[MKEK_SIZE];
|
||||||
int r = load_mkek(mkek); //loads the MKEK with SO pin
|
int r = load_mkek(mkek); //loads the MKEK with SO pin
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
pin_derive_session(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin);
|
pin_derive_session(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin);
|
||||||
has_session_pin = true;
|
has_session_pin = true;
|
||||||
r = store_mkek(mkek);
|
r = store_mkek(mkek);
|
||||||
release_mkek(mkek);
|
release_mkek(mkek);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
uint8_t dhash[34];
|
uint8_t dhash[34];
|
||||||
@@ -75,7 +76,7 @@ int cmd_reset_retry(void) {
|
|||||||
dhash[1] = 1; // Format
|
dhash[1] = 1; // Format
|
||||||
pin_derive_verifier(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 2);
|
pin_derive_verifier(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 2);
|
||||||
file_put_data(file_pin1, dhash, sizeof(dhash));
|
file_put_data(file_pin1, dhash, sizeof(dhash));
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
|
else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
|
||||||
@@ -100,7 +101,7 @@ int cmd_reset_retry(void) {
|
|||||||
return SW_WRONG_LENGTH();
|
return SW_WRONG_LENGTH();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) {
|
if (pin_reset_retries(file_pin1, true) != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
|
|||||||
@@ -16,8 +16,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
|
#include "files.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
extern const file_t *file_openpgp;
|
||||||
|
extern const file_t *file_sc_hsm;
|
||||||
|
|
||||||
void select_file(file_t *pe) {
|
void select_file(file_t *pe) {
|
||||||
if (!pe) {
|
if (!pe) {
|
||||||
currentDF = (file_t *) MF;
|
currentDF = (file_t *) MF;
|
||||||
@@ -48,7 +52,7 @@ int cmd_select(void) {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
if (apdu.nc == 2) {
|
if (apdu.nc == 2) {
|
||||||
fid = get_uint16_t_be(apdu.data);
|
fid = get_uint16_be(apdu.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if ((fid & 0xff00) == (KEY_PREFIX << 8))
|
//if ((fid & 0xff00) == (KEY_PREFIX << 8))
|
||||||
@@ -63,7 +67,7 @@ int cmd_select(void) {
|
|||||||
pfx == DCOD_PREFIX ||
|
pfx == DCOD_PREFIX ||
|
||||||
pfx == DATA_PREFIX ||
|
pfx == DATA_PREFIX ||
|
||||||
pfx == PROT_DATA_PREFIX) {*/
|
pfx == PROT_DATA_PREFIX) {*/
|
||||||
if (fid != 0x0 && !(pe = search_file(fid))) {
|
if (fid != 0x0 && !(pe = file_search(fid))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
/*}*/
|
/*}*/
|
||||||
@@ -74,18 +78,18 @@ int cmd_select(void) {
|
|||||||
//ac_fini();
|
//ac_fini();
|
||||||
}
|
}
|
||||||
else if (apdu.nc == 2) {
|
else if (apdu.nc == 2) {
|
||||||
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
|
if (!(pe = file_search_by_fid(fid, NULL, SPECIFY_ANY))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p1 == 0x01) { //Select child DF - DF identifier
|
else if (p1 == 0x01) { //Select child DF - DF identifier
|
||||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
|
if (!(pe = file_search_by_fid(fid, currentDF, SPECIFY_DF))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
|
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
|
||||||
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
|
if (!(pe = file_search_by_fid(fid, currentDF, SPECIFY_EF))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +99,7 @@ int cmd_select(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
|
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
|
||||||
if (!(pe = search_by_name(apdu.data, (uint16_t)apdu.nc))) {
|
if (!(pe = file_search_by_name(apdu.data, (uint16_t)apdu.nc))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
if (card_terminated) {
|
if (card_terminated) {
|
||||||
@@ -103,23 +107,23 @@ int cmd_select(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
|
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
|
||||||
if (!(pe = search_by_path(apdu.data, (uint8_t)apdu.nc, MF))) {
|
if (!(pe = file_search_by_path(apdu.data, (uint8_t)apdu.nc, MF))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
|
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
|
||||||
if (!(pe = search_by_path(apdu.data, (uint8_t)apdu.nc, currentDF))) {
|
if (!(pe = file_search_by_path(apdu.data, (uint8_t)apdu.nc, currentDF))) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
|
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
|
||||||
process_fci(pe, 0);
|
file_process_fci(pe, 0);
|
||||||
if (pe == file_sc_hsm) {
|
if (pe == file_sc_hsm) {
|
||||||
res_APDU[res_APDU_size++] = 0x85;
|
res_APDU[res_APDU_size++] = 0x85;
|
||||||
res_APDU[res_APDU_size++] = 5;
|
res_APDU[res_APDU_size++] = 5;
|
||||||
uint16_t opts = get_device_options();
|
uint16_t opts = get_device_options();
|
||||||
res_APDU_size += put_uint16_t_be(opts, res_APDU + res_APDU_size);
|
res_APDU_size += put_uint16_be(opts, res_APDU + res_APDU_size);
|
||||||
res_APDU[res_APDU_size++] = 0xFF;
|
res_APDU[res_APDU_size++] = 0xFF;
|
||||||
res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR;
|
res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR;
|
||||||
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;
|
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;
|
||||||
|
|||||||
@@ -85,17 +85,17 @@ static int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
|
|||||||
*algorithm = digest_info_prefix[i].algorithm;
|
*algorithm = digest_info_prefix[i].algorithm;
|
||||||
}
|
}
|
||||||
if (out_dat == NULL) {
|
if (out_dat == NULL) {
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
if (*out_len < hash_len) {
|
if (*out_len < hash_len) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
memmove(out_dat, in_dat + hdr_len, hash_len);
|
memmove(out_dat, in_dat + hdr_len, hash_len);
|
||||||
*out_len = hash_len;
|
*out_len = hash_len;
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
//-----
|
//-----
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ int cmd_signature(void) {
|
|||||||
if (!isUserAuthenticated) {
|
if (!isUserAuthenticated) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
if (!(fkey = search_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
|
if (!(fkey = file_search((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
if (get_key_counter(fkey) == 0) {
|
if (get_key_counter(fkey) == 0) {
|
||||||
@@ -145,9 +145,9 @@ int cmd_signature(void) {
|
|||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
|
|
||||||
int r = load_private_key_rsa(&ctx, fkey);
|
int r = load_private_key_rsa(&ctx, fkey);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -156,7 +156,7 @@ int cmd_signature(void) {
|
|||||||
if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached
|
if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached
|
||||||
uint16_t nc = (uint16_t)apdu.nc;
|
uint16_t nc = (uint16_t)apdu.nc;
|
||||||
if (pkcs1_strip_digest_info_prefix(&md, apdu.data, (uint16_t)apdu.nc, apdu.data,
|
if (pkcs1_strip_digest_info_prefix(&md, apdu.data, (uint16_t)apdu.nc, apdu.data,
|
||||||
&nc) != PICOKEY_OK) { //gets the MD algo id and strips it off
|
&nc) != PICOKEYS_OK) { //gets the MD algo id and strips it off
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
apdu.nc = nc;
|
apdu.nc = nc;
|
||||||
@@ -214,11 +214,11 @@ int cmd_signature(void) {
|
|||||||
if (apdu.nc < key_size) { //needs padding
|
if (apdu.nc < key_size) { //needs padding
|
||||||
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
|
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
|
||||||
}
|
}
|
||||||
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
|
r = mbedtls_rsa_private(&ctx, random_fill_iterator, NULL, apdu.data, res_APDU);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t));
|
uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t));
|
||||||
r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash.len, hash.data, signature);
|
r = mbedtls_rsa_pkcs1_sign(&ctx, random_fill_iterator, NULL, md, hash.len, hash.data, signature);
|
||||||
memcpy(res_APDU, signature, key_size);
|
memcpy(res_APDU, signature, key_size);
|
||||||
free(signature);
|
free(signature);
|
||||||
}
|
}
|
||||||
@@ -267,9 +267,9 @@ int cmd_signature(void) {
|
|||||||
md = MBEDTLS_MD_SHA512;
|
md = MBEDTLS_MD_SHA512;
|
||||||
}
|
}
|
||||||
int r = load_private_key_ec(&ctx, fkey);
|
int r = load_private_key_ec(&ctx, fkey);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
if (r == PICOKEY_VERIFICATION_FAILED) {
|
if (r == PICOKEYS_VERIFICATION_FAILED) {
|
||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -278,13 +278,12 @@ int cmd_signature(void) {
|
|||||||
uint8_t buf[MBEDTLS_ECDSA_MAX_LEN];
|
uint8_t buf[MBEDTLS_ECDSA_MAX_LEN];
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
#ifdef MBEDTLS_EDDSA_C
|
||||||
if (ctx.grp.id == MBEDTLS_ECP_DP_ED25519 || ctx.grp.id == MBEDTLS_ECP_DP_ED448) {
|
if (ctx.grp.id == MBEDTLS_ECP_DP_ED25519 || ctx.grp.id == MBEDTLS_ECP_DP_ED448) {
|
||||||
r = mbedtls_eddsa_write_signature(&ctx, apdu.data, apdu.nc, buf, sizeof(buf), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
r = mbedtls_eddsa_write_signature(&ctx, apdu.data, apdu.nc, buf, sizeof(buf), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
r = mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN,
|
r = mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_fill_iterator, NULL);
|
||||||
&olen, random_gen, NULL);
|
|
||||||
}
|
}
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
@@ -306,9 +305,7 @@ int cmd_signature(void) {
|
|||||||
return SW_INCORRECT_PARAMS();
|
return SW_INCORRECT_PARAMS();
|
||||||
}
|
}
|
||||||
md = MBEDTLS_MD_SHA256;
|
md = MBEDTLS_MD_SHA256;
|
||||||
if (mbedtls_ecdsa_write_signature(&hd_context, md, apdu.data, apdu.nc, buf,
|
if (mbedtls_ecdsa_write_signature(&hd_context, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_fill_iterator, NULL) != 0) {
|
||||||
MBEDTLS_ECDSA_MAX_LEN,
|
|
||||||
&olen, random_gen, NULL) != 0) {
|
|
||||||
mbedtls_ecp_keypair_free(&hd_context);
|
mbedtls_ecp_keypair_free(&hd_context);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ int cmd_update_ef(void) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ef && !authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
if (ef && !file_authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +70,13 @@ int cmd_update_ef(void) {
|
|||||||
if (fid == 0x0 && !ef) {
|
if (fid == 0x0 && !ef) {
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
else if (fid != 0x0 && !(ef = search_file(fid))) { //if does not exist, create it
|
else if (fid != 0x0 && !(ef = file_search(fid))) { //if does not exist, create it
|
||||||
//return SW_FILE_NOT_FOUND();
|
//return SW_FILE_NOT_FOUND();
|
||||||
ef = file_new(fid);
|
ef = file_new(fid);
|
||||||
}
|
}
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
int r = file_put_data(ef, data, data_len);
|
int r = file_put_data(ef, data, data_len);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,11 +93,11 @@ int cmd_update_ef(void) {
|
|||||||
memcpy(data_merge + offset, data, data_len);
|
memcpy(data_merge + offset, data, data_len);
|
||||||
int r = file_put_data(ef, data_merge, offset + data_len);
|
int r = file_put_data(ef, data_merge, offset + data_len);
|
||||||
free(data_merge);
|
free(data_merge);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
int cmd_verify(void) {
|
int cmd_verify(void) {
|
||||||
uint8_t p1 = P1(apdu);
|
uint8_t p1 = P1(apdu);
|
||||||
|
|||||||
216
src/hsm/cvc.c
216
src/hsm/cvc.c
@@ -164,18 +164,12 @@ static uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecp_keypair *ecdsa, uint8_t *b
|
|||||||
return tot_len;
|
return tot_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
static uint16_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len, bool full) {
|
||||||
uint8_t key_type,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len,
|
|
||||||
const uint8_t *ext,
|
|
||||||
uint16_t ext_len,
|
|
||||||
bool full) {
|
|
||||||
uint16_t pubkey_size = 0;
|
uint16_t pubkey_size = 0;
|
||||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0);
|
pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0);
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
|
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
|
||||||
}
|
}
|
||||||
uint16_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0;
|
uint16_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0;
|
||||||
@@ -225,10 +219,10 @@ static uint16_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
|||||||
//car
|
//car
|
||||||
*p++ = 0x42; p += format_tlv_len(car.len, p); memcpy(p, car.data, car.len); p += car.len;
|
*p++ = 0x42; p += format_tlv_len(car.len, p); memcpy(p, car.data, car.len); p += car.len;
|
||||||
//pubkey
|
//pubkey
|
||||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size);
|
p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size);
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size);
|
p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size);
|
||||||
}
|
}
|
||||||
//chr
|
//chr
|
||||||
@@ -261,18 +255,12 @@ static uint16_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
|||||||
return tot_len;
|
return tot_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_cvc_cert(void *rsa_ecdsa,
|
uint16_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len, bool full) {
|
||||||
uint8_t key_type,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len,
|
|
||||||
const uint8_t *ext,
|
|
||||||
uint16_t ext_len,
|
|
||||||
bool full) {
|
|
||||||
uint16_t key_size = 0;
|
uint16_t key_size = 0;
|
||||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
key_size = (uint16_t)mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
|
key_size = (uint16_t)mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)->grp.id)->bit_size + 7) / 8);
|
key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)->grp.id)->bit_size + 7) / 8);
|
||||||
}
|
}
|
||||||
uint16_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, full), sig_size = asn1_len_tag(0x5f37, key_size);
|
uint16_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, full), sig_size = asn1_len_tag(0x5f37, key_size);
|
||||||
@@ -292,13 +280,13 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
|
|||||||
hash256(body, body_size, hsh);
|
hash256(body, body_size, hsh);
|
||||||
memcpy(p, "\x5F\x37", 2); p += 2;
|
memcpy(p, "\x5F\x37", 2); p += 2;
|
||||||
p += format_tlv_len(key_size, p);
|
p += format_tlv_len(key_size, p);
|
||||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) {
|
if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_fill_iterator, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) {
|
||||||
memset(p, 0, key_size);
|
memset(p, 0, key_size);
|
||||||
}
|
}
|
||||||
p += key_size;
|
p += key_size;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
mbedtls_mpi r, s;
|
mbedtls_mpi r, s;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) rsa_ecdsa;
|
mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) rsa_ecdsa;
|
||||||
@@ -306,12 +294,12 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
|
|||||||
mbedtls_mpi_init(&s);
|
mbedtls_mpi_init(&s);
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
#ifdef MBEDTLS_EDDSA_C
|
||||||
if (ecdsa->grp.id == MBEDTLS_ECP_DP_ED25519 || ecdsa->grp.id == MBEDTLS_ECP_DP_ED448) {
|
if (ecdsa->grp.id == MBEDTLS_ECP_DP_ED25519 || ecdsa->grp.id == MBEDTLS_ECP_DP_ED448) {
|
||||||
ret = mbedtls_eddsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, body, body_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
ret = mbedtls_eddsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, body, body_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL);
|
ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2;
|
mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2;
|
||||||
@@ -327,23 +315,18 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
|
|||||||
return (uint16_t)(p - buf);
|
return (uint16_t)(p - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_cvc_aut(void *rsa_ecdsa,
|
uint16_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len) {
|
||||||
uint8_t key_type,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len,
|
|
||||||
const uint8_t *ext,
|
|
||||||
uint16_t ext_len) {
|
|
||||||
uint16_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, false);
|
uint16_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, false);
|
||||||
uint16_t outcar_len = dev_name_len;
|
uint16_t outcar_len = dev_name_len;
|
||||||
const uint8_t *outcar = dev_name;
|
const uint8_t *outcar = dev_name;
|
||||||
uint16_t outcar_size = asn1_len_tag(0x42, outcar_len);
|
uint16_t outcar_size = asn1_len_tag(0x42, outcar_len);
|
||||||
file_t *fkey = search_file(EF_KEY_DEV);
|
file_t *fkey = file_search(EF_KEY_DEV);
|
||||||
if (!fkey) {
|
if (!fkey) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mbedtls_ecp_keypair ectx;
|
mbedtls_ecp_keypair ectx;
|
||||||
mbedtls_ecp_keypair_init(&ectx);
|
mbedtls_ecp_keypair_init(&ectx);
|
||||||
if (load_private_key_ec(&ectx, fkey) != PICOKEY_OK) {
|
if (load_private_key_ec(&ectx, fkey) != PICOKEYS_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ectx);
|
mbedtls_ecp_keypair_free(&ectx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -371,14 +354,14 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa,
|
|||||||
mbedtls_mpi_init(&s);
|
mbedtls_mpi_init(&s);
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
#ifdef MBEDTLS_EDDSA_C
|
||||||
if (ectx.grp.id == MBEDTLS_ECP_DP_ED25519 || ectx.grp.id == MBEDTLS_ECP_DP_ED448) {
|
if (ectx.grp.id == MBEDTLS_ECP_DP_ED25519 || ectx.grp.id == MBEDTLS_ECP_DP_ED448) {
|
||||||
ret = mbedtls_eddsa_sign(&ectx.grp, &r, &s, &ectx.d, body, cvcert_size + outcar_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
|
ret = mbedtls_eddsa_sign(&ectx.grp, &r, &s, &ectx.d, body, cvcert_size + outcar_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t hsh[32];
|
uint8_t hsh[32];
|
||||||
hash256(body, cvcert_size + outcar_size, hsh);
|
hash256(body, cvcert_size + outcar_size, hsh);
|
||||||
ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_gen, NULL);
|
ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_fill_iterator, NULL);
|
||||||
}
|
}
|
||||||
mbedtls_ecp_keypair_free(&ectx);
|
mbedtls_ecp_keypair_free(&ectx);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -393,20 +376,11 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa,
|
|||||||
return (uint16_t)(p - buf);
|
return (uint16_t)(p - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_build_cert_description(const uint8_t *label,
|
uint16_t asn1_build_cert_description(const uint8_t *label, uint16_t label_len, const uint8_t *puk, uint16_t puk_len, uint16_t fid, uint8_t *buf, uint16_t buf_len) {
|
||||||
uint16_t label_len,
|
|
||||||
const uint8_t *puk,
|
|
||||||
uint16_t puk_len,
|
|
||||||
uint16_t fid,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len) {
|
|
||||||
uint16_t opt_len = 2;
|
uint16_t opt_len = 2;
|
||||||
uint16_t seq1_size =
|
uint16_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len));
|
||||||
asn1_len_tag(0x30, asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len));
|
|
||||||
uint16_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */
|
uint16_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */
|
||||||
uint16_t seq3_size =
|
uint16_t seq3_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
|
||||||
asn1_len_tag(0xA1,
|
|
||||||
asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
|
|
||||||
uint16_t tot_len = asn1_len_tag(0x30, seq1_size + seq2_size + seq3_size);
|
uint16_t tot_len = asn1_len_tag(0x30, seq1_size + seq2_size + seq3_size);
|
||||||
if (buf_len == 0 || buf == NULL) {
|
if (buf_len == 0 || buf == NULL) {
|
||||||
return tot_len;
|
return tot_len;
|
||||||
@@ -444,32 +418,25 @@ uint16_t asn1_build_cert_description(const uint8_t *label,
|
|||||||
p += format_tlv_len(asn1_len_tag(0x4, sizeof(uint16_t)), p);
|
p += format_tlv_len(asn1_len_tag(0x4, sizeof(uint16_t)), p);
|
||||||
*p++ = 0x4;
|
*p++ = 0x4;
|
||||||
p += format_tlv_len(sizeof(uint16_t), p);
|
p += format_tlv_len(sizeof(uint16_t), p);
|
||||||
put_uint16_t_be(fid, p); p += sizeof(uint16_t);
|
put_uint16_be(fid, p); p += sizeof(uint16_t);
|
||||||
return (uint16_t)(p - buf);
|
return (uint16_t)(p - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
uint16_t asn1_build_prkd_generic(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, int key_type, uint8_t *buf, uint16_t buf_len) {
|
||||||
uint16_t label_len,
|
|
||||||
const uint8_t *keyid,
|
|
||||||
uint16_t keyid_len,
|
|
||||||
uint16_t keysize,
|
|
||||||
int key_type,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len) {
|
|
||||||
uint16_t seq_len = 0;
|
uint16_t seq_len = 0;
|
||||||
const uint8_t *seq = NULL;
|
const uint8_t *seq = NULL;
|
||||||
uint8_t first_tag = 0x0;
|
uint8_t first_tag = 0x0;
|
||||||
if (key_type & PICO_KEYS_KEY_EC) {
|
if (key_type & PICOKEYS_KEY_EC) {
|
||||||
seq = (const uint8_t *)"\x07\x20\x80";
|
seq = (const uint8_t *)"\x07\x20\x80";
|
||||||
seq_len = 3;
|
seq_len = 3;
|
||||||
first_tag = 0xA0;
|
first_tag = 0xA0;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_RSA) {
|
else if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
seq = (const uint8_t *)"\x02\x74";
|
seq = (const uint8_t *)"\x02\x74";
|
||||||
seq_len = 2;
|
seq_len = 2;
|
||||||
first_tag = 0x30;
|
first_tag = 0x30;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES) {
|
else if (key_type & PICOKEYS_KEY_AES) {
|
||||||
seq = (const uint8_t *)"\x07\xC0\x10";
|
seq = (const uint8_t *)"\x07\xC0\x10";
|
||||||
seq_len = 3;
|
seq_len = 3;
|
||||||
first_tag = 0xA8;
|
first_tag = 0xA8;
|
||||||
@@ -478,10 +445,10 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
|||||||
uint16_t seq2_size =
|
uint16_t seq2_size =
|
||||||
asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len));
|
asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len));
|
||||||
uint16_t seq3_size = 0, seq4_size = 0;
|
uint16_t seq3_size = 0, seq4_size = 0;
|
||||||
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
|
||||||
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2)));
|
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2)));
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES) {
|
else if (key_type & PICOKEYS_KEY_AES) {
|
||||||
seq3_size = asn1_len_tag(0xA0, asn1_len_tag(0x30, asn1_len_tag(0x2, 2)));
|
seq3_size = asn1_len_tag(0xA0, asn1_len_tag(0x30, asn1_len_tag(0x2, 2)));
|
||||||
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))));
|
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))));
|
||||||
}
|
}
|
||||||
@@ -513,20 +480,20 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
|||||||
memcpy(p, seq, seq_len); p += seq_len;
|
memcpy(p, seq, seq_len); p += seq_len;
|
||||||
|
|
||||||
//Seq 3
|
//Seq 3
|
||||||
if (key_type & PICO_KEYS_KEY_AES) {
|
if (key_type & PICOKEYS_KEY_AES) {
|
||||||
*p++ = 0xA0;
|
*p++ = 0xA0;
|
||||||
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x2, 2)), p);
|
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x2, 2)), p);
|
||||||
*p++ = 0x30;
|
*p++ = 0x30;
|
||||||
p += format_tlv_len(asn1_len_tag(0x2, 2), p);
|
p += format_tlv_len(asn1_len_tag(0x2, 2), p);
|
||||||
*p++ = 0x2;
|
*p++ = 0x2;
|
||||||
p += format_tlv_len(2, p);
|
p += format_tlv_len(2, p);
|
||||||
p += put_uint16_t_be(keysize, p);
|
p += put_uint16_be(keysize, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Seq 4
|
//Seq 4
|
||||||
*p++ = 0xA1;
|
*p++ = 0xA1;
|
||||||
uint16_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0));
|
uint16_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0));
|
||||||
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
|
||||||
inseq4_len += asn1_len_tag(0x2, 2);
|
inseq4_len += asn1_len_tag(0x2, 2);
|
||||||
}
|
}
|
||||||
p += format_tlv_len(asn1_len_tag(0x30, inseq4_len), p);
|
p += format_tlv_len(asn1_len_tag(0x30, inseq4_len), p);
|
||||||
@@ -536,63 +503,24 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
|||||||
p += format_tlv_len(asn1_len_tag(0x4, 0), p);
|
p += format_tlv_len(asn1_len_tag(0x4, 0), p);
|
||||||
*p++ = 0x4;
|
*p++ = 0x4;
|
||||||
p += format_tlv_len(0, p);
|
p += format_tlv_len(0, p);
|
||||||
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) {
|
if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
|
||||||
*p++ = 0x2;
|
*p++ = 0x2;
|
||||||
p += format_tlv_len(2, p);
|
p += format_tlv_len(2, p);
|
||||||
p += put_uint16_t_be(keysize, p);
|
p += put_uint16_be(keysize, p);
|
||||||
}
|
}
|
||||||
return (uint16_t)(p - buf);
|
return (uint16_t)(p - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_build_prkd_ecc(const uint8_t *label,
|
uint16_t asn1_build_prkd_ecc(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
|
||||||
uint16_t label_len,
|
return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_EC, buf, buf_len);
|
||||||
const uint8_t *keyid,
|
|
||||||
uint16_t keyid_len,
|
|
||||||
uint16_t keysize,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len) {
|
|
||||||
return asn1_build_prkd_generic(label,
|
|
||||||
label_len,
|
|
||||||
keyid,
|
|
||||||
keyid_len,
|
|
||||||
keysize,
|
|
||||||
PICO_KEYS_KEY_EC,
|
|
||||||
buf,
|
|
||||||
buf_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_build_prkd_rsa(const uint8_t *label,
|
uint16_t asn1_build_prkd_rsa(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
|
||||||
uint16_t label_len,
|
return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_RSA, buf, buf_len);
|
||||||
const uint8_t *keyid,
|
|
||||||
uint16_t keyid_len,
|
|
||||||
uint16_t keysize,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len) {
|
|
||||||
return asn1_build_prkd_generic(label,
|
|
||||||
label_len,
|
|
||||||
keyid,
|
|
||||||
keyid_len,
|
|
||||||
keysize,
|
|
||||||
PICO_KEYS_KEY_RSA,
|
|
||||||
buf,
|
|
||||||
buf_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t asn1_build_prkd_aes(const uint8_t *label,
|
uint16_t asn1_build_prkd_aes(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
|
||||||
uint16_t label_len,
|
return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_AES, buf, buf_len);
|
||||||
const uint8_t *keyid,
|
|
||||||
uint16_t keyid_len,
|
|
||||||
uint16_t keysize,
|
|
||||||
uint8_t *buf,
|
|
||||||
uint16_t buf_len) {
|
|
||||||
return asn1_build_prkd_generic(label,
|
|
||||||
label_len,
|
|
||||||
keyid,
|
|
||||||
keyid_len,
|
|
||||||
keysize,
|
|
||||||
PICO_KEYS_KEY_AES,
|
|
||||||
buf,
|
|
||||||
buf_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *cvc_get_field(const uint8_t *data, uint16_t len, uint16_t *olen, uint16_t tag) {
|
const uint8_t *cvc_get_field(const uint8_t *data, uint16_t len, uint16_t *olen, uint16_t tag) {
|
||||||
@@ -703,30 +631,22 @@ mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, uint16_t ca_len) {
|
|||||||
return ec_get_curve_from_prime(t81, t81_len);
|
return ec_get_curve_from_prime(t81, t81_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int puk_verify(const uint8_t *sig,
|
int puk_verify(const uint8_t *sig, uint16_t sig_len, const uint8_t *hash, uint16_t hash_len, const uint8_t *ca, uint16_t ca_len) {
|
||||||
uint16_t sig_len,
|
|
||||||
const uint8_t *hash,
|
|
||||||
uint16_t hash_len,
|
|
||||||
const uint8_t *ca,
|
|
||||||
uint16_t ca_len) {
|
|
||||||
uint16_t puk_len = 0;
|
uint16_t puk_len = 0;
|
||||||
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
||||||
if (!puk) {
|
if (!puk) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
uint16_t oid_len = 0;
|
uint16_t oid_len = 0;
|
||||||
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
|
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
|
||||||
if (!oid) {
|
if (!oid) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
|
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
|
||||||
uint16_t t81_len = 0, t82_len = 0;
|
uint16_t t81_len = 0, t82_len = 0;
|
||||||
const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk,
|
const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk, puk_len, &t81_len, 0x82);
|
||||||
puk_len,
|
|
||||||
&t81_len,
|
|
||||||
0x82);
|
|
||||||
if (!t81 || !t82) {
|
if (!t81 || !t82) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
mbedtls_rsa_context rsa;
|
mbedtls_rsa_context rsa;
|
||||||
mbedtls_rsa_init(&rsa);
|
mbedtls_rsa_init(&rsa);
|
||||||
@@ -754,32 +674,32 @@ int puk_verify(const uint8_t *sig,
|
|||||||
}
|
}
|
||||||
if (md == MBEDTLS_MD_NONE) {
|
if (md == MBEDTLS_MD_NONE) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
int r = mbedtls_mpi_read_binary(&rsa.N, t81, t81_len);
|
int r = mbedtls_mpi_read_binary(&rsa.N, t81, t81_len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = mbedtls_mpi_read_binary(&rsa.E, t82, t82_len);
|
r = mbedtls_mpi_read_binary(&rsa.E, t82, t82_len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = mbedtls_rsa_complete(&rsa);
|
r = mbedtls_rsa_complete(&rsa);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = mbedtls_rsa_check_pubkey(&rsa);
|
r = mbedtls_rsa_check_pubkey(&rsa);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = mbedtls_rsa_pkcs1_verify(&rsa, md, (unsigned int)hash_len, hash, sig);
|
r = mbedtls_rsa_pkcs1_verify(&rsa, md, (unsigned int)hash_len, hash, sig);
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return PICOKEY_WRONG_SIGNATURE;
|
return PICOKEYS_WRONG_SIGNATURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
|
||||||
@@ -800,34 +720,34 @@ int puk_verify(const uint8_t *sig,
|
|||||||
md = MBEDTLS_MD_SHA512;
|
md = MBEDTLS_MD_SHA512;
|
||||||
}
|
}
|
||||||
if (md == MBEDTLS_MD_NONE) {
|
if (md == MBEDTLS_MD_NONE) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t t86_len = 0;
|
uint16_t t86_len = 0;
|
||||||
const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86);
|
const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86);
|
||||||
if (!t86) {
|
if (!t86) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len);
|
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len);
|
||||||
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
mbedtls_ecdsa_context ecdsa;
|
mbedtls_ecdsa_context ecdsa;
|
||||||
mbedtls_ecdsa_init(&ecdsa);
|
mbedtls_ecdsa_init(&ecdsa);
|
||||||
int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id);
|
int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, t86, t86_len);
|
ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, t86, t86_len);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
ret = mbedtls_ecp_check_pubkey(&ecdsa.grp, &ecdsa.Q);
|
ret = mbedtls_ecp_check_pubkey(&ecdsa.grp, &ecdsa.Q);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
mbedtls_mpi r, s;
|
mbedtls_mpi r, s;
|
||||||
mbedtls_mpi_init(&r);
|
mbedtls_mpi_init(&r);
|
||||||
@@ -837,44 +757,44 @@ int puk_verify(const uint8_t *sig,
|
|||||||
mbedtls_mpi_free(&r);
|
mbedtls_mpi_free(&r);
|
||||||
mbedtls_mpi_free(&s);
|
mbedtls_mpi_free(&s);
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2);
|
ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_mpi_free(&r);
|
mbedtls_mpi_free(&r);
|
||||||
mbedtls_mpi_free(&s);
|
mbedtls_mpi_free(&s);
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
ret = mbedtls_ecdsa_verify(&ecdsa.grp, hash, hash_len, &ecdsa.Q, &r, &s);
|
ret = mbedtls_ecdsa_verify(&ecdsa.grp, hash, hash_len, &ecdsa.Q, &r, &s);
|
||||||
mbedtls_mpi_free(&r);
|
mbedtls_mpi_free(&r);
|
||||||
mbedtls_mpi_free(&s);
|
mbedtls_mpi_free(&s);
|
||||||
mbedtls_ecdsa_free(&ecdsa);
|
mbedtls_ecdsa_free(&ecdsa);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return PICOKEY_WRONG_SIGNATURE;
|
return PICOKEYS_WRONG_SIGNATURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16_t ca_len) {
|
int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16_t ca_len) {
|
||||||
uint16_t puk_len = 0;
|
uint16_t puk_len = 0;
|
||||||
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
|
||||||
if (!puk) {
|
if (!puk) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
uint16_t oid_len = 0, cv_body_len = 0, sig_len = 0;
|
uint16_t oid_len = 0, cv_body_len = 0, sig_len = 0;
|
||||||
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
|
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
|
||||||
const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len);
|
const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len);
|
||||||
const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len);
|
const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len);
|
||||||
if (!sig) {
|
if (!sig) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (!cv_body) {
|
if (!cv_body) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (!oid) {
|
if (!oid) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||||
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
|
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
|
||||||
@@ -915,18 +835,18 @@ int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (md == MBEDTLS_MD_NONE) {
|
if (md == MBEDTLS_MD_NONE) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
|
||||||
uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info);
|
uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info);
|
||||||
uint8_t tlv_body = 2 + format_tlv_len(cv_body_len, NULL);
|
uint8_t tlv_body = 2 + format_tlv_len(cv_body_len, NULL);
|
||||||
int r = mbedtls_md(md_info, cv_body - tlv_body, cv_body_len + tlv_body, hash);
|
int r = mbedtls_md(md_info, cv_body - tlv_body, cv_body_len + tlv_body, hash);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len);
|
r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return PICOKEY_WRONG_SIGNATURE;
|
return PICOKEYS_WRONG_SIGNATURE;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,4 +51,9 @@
|
|||||||
#define EF_TOKENINFO 0x2F03
|
#define EF_TOKENINFO 0x2F03
|
||||||
#define EF_STATICTOKEN 0xCB00
|
#define EF_STATICTOKEN 0xCB00
|
||||||
|
|
||||||
|
extern file_t *file_pin1;
|
||||||
|
extern file_t *file_retries_pin1;
|
||||||
|
extern file_t *file_sopin;
|
||||||
|
extern file_t *file_retries_sopin;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
264
src/hsm/kek.c
264
src/hsm/kek.c
@@ -45,26 +45,26 @@ static void mkek_masked(uint8_t *mkek, const uint8_t *mask) {
|
|||||||
|
|
||||||
int load_mkek(uint8_t *mkek) {
|
int load_mkek(uint8_t *mkek) {
|
||||||
if (has_session_pin == false && has_session_sopin == false) {
|
if (has_session_pin == false && has_session_sopin == false) {
|
||||||
return PICOKEY_NO_LOGIN;
|
return PICOKEYS_NO_LOGIN;
|
||||||
}
|
}
|
||||||
file_t *ef = NULL;
|
file_t *ef = NULL;
|
||||||
const uint8_t *pin = NULL;
|
const uint8_t *pin = NULL;
|
||||||
if (pin == NULL && has_session_pin == true) {
|
if (pin == NULL && has_session_pin == true) {
|
||||||
file_t *tf = search_file(EF_MKEK);
|
file_t *tf = file_search(EF_MKEK);
|
||||||
if (file_has_data(tf)) {
|
if (file_has_data(tf)) {
|
||||||
ef = tf;
|
ef = tf;
|
||||||
pin = session_pin;
|
pin = session_pin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pin == NULL && has_session_sopin == true) {
|
if (pin == NULL && has_session_sopin == true) {
|
||||||
file_t *tf = search_file(EF_MKEK_SO);
|
file_t *tf = file_search(EF_MKEK_SO);
|
||||||
if (file_has_data(tf)) {
|
if (file_has_data(tf)) {
|
||||||
ef = tf;
|
ef = tf;
|
||||||
pin = session_sopin;
|
pin = session_sopin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pin == NULL) { //Should never happen
|
if (pin == NULL) { //Should never happen
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t fid_size = file_get_size(ef);
|
uint16_t fid_size = file_get_size(ef);
|
||||||
@@ -75,12 +75,12 @@ int load_mkek(uint8_t *mkek) {
|
|||||||
}
|
}
|
||||||
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
uint32_t mkek_checksum = 0;
|
uint32_t mkek_checksum = 0;
|
||||||
memcpy(&mkek_checksum, MKEK_CHECKSUM(mkek), sizeof(mkek_checksum));
|
memcpy(&mkek_checksum, MKEK_CHECKSUM(mkek), sizeof(mkek_checksum));
|
||||||
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != mkek_checksum) {
|
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != mkek_checksum) {
|
||||||
return PICOKEY_WRONG_DKEK;
|
return PICOKEYS_WRONG_DKEK;
|
||||||
}
|
}
|
||||||
if (otp_key_1) {
|
if (otp_key_1) {
|
||||||
mkek_masked(mkek, otp_key_1);
|
mkek_masked(mkek, otp_key_1);
|
||||||
@@ -93,18 +93,18 @@ int load_mkek(uint8_t *mkek) {
|
|||||||
memcpy(tmp_key, file_get_data(ef), sizeof(tmp_key));
|
memcpy(tmp_key, file_get_data(ef), sizeof(tmp_key));
|
||||||
int ret = decrypt_with_aad(pin, tmp_key + 1, MKEK_FILE_SIZE - 1, 2, mkek);
|
int ret = decrypt_with_aad(pin, tmp_key + 1, MKEK_FILE_SIZE - 1, 2, mkek);
|
||||||
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
||||||
if (ret != PICOKEY_OK) {
|
if (ret != PICOKEYS_OK) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
mse_t mse = { .init = false };
|
mse_t mse = { .init = false };
|
||||||
@@ -119,9 +119,9 @@ int mse_decrypt_ct(uint8_t *data, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int load_dkek(uint8_t id, uint8_t *dkek) {
|
static int load_dkek(uint8_t id, uint8_t *dkek) {
|
||||||
file_t *tf = search_file(EF_DKEK + id);
|
file_t *tf = file_search(EF_DKEK + id);
|
||||||
if (!file_has_data(tf)) {
|
if (!file_has_data(tf)) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
|
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
|
||||||
return mkek_decrypt(dkek, DKEK_KEY_SIZE);
|
return mkek_decrypt(dkek, DKEK_KEY_SIZE);
|
||||||
@@ -133,7 +133,7 @@ void release_mkek(uint8_t *mkek) {
|
|||||||
|
|
||||||
int store_mkek(const uint8_t *mkek) {
|
int store_mkek(const uint8_t *mkek) {
|
||||||
if (has_session_pin == false && has_session_sopin == false) {
|
if (has_session_pin == false && has_session_sopin == false) {
|
||||||
return PICOKEY_NO_LOGIN;
|
return PICOKEYS_NO_LOGIN;
|
||||||
}
|
}
|
||||||
uint8_t tmp_mkek[MKEK_FILE_SIZE];
|
uint8_t tmp_mkek[MKEK_FILE_SIZE];
|
||||||
tmp_mkek[0] = 0x03; // Format indicator
|
tmp_mkek[0] = 0x03; // Format indicator
|
||||||
@@ -141,47 +141,47 @@ int store_mkek(const uint8_t *mkek) {
|
|||||||
mkek = random_bytes_get(MKEK_SIZE);
|
mkek = random_bytes_get(MKEK_SIZE);
|
||||||
}
|
}
|
||||||
if (has_session_pin) {
|
if (has_session_pin) {
|
||||||
file_t *ef = search_file(EF_MKEK);
|
file_t *ef = file_search(EF_MKEK);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
encrypt_with_aad(session_pin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
|
encrypt_with_aad(session_pin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
|
||||||
file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
|
file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
|
||||||
}
|
}
|
||||||
if (has_session_sopin) {
|
if (has_session_sopin) {
|
||||||
file_t *ef = search_file(EF_MKEK_SO);
|
file_t *ef = file_search(EF_MKEK_SO);
|
||||||
if (!ef) {
|
if (!ef) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
encrypt_with_aad(session_sopin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
|
encrypt_with_aad(session_sopin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
|
||||||
file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
|
file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
mbedtls_platform_zeroize(tmp_mkek, sizeof(tmp_mkek));
|
mbedtls_platform_zeroize(tmp_mkek, sizeof(tmp_mkek));
|
||||||
|
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int store_dkek_key(uint8_t id, uint8_t *dkek) {
|
int store_dkek_key(uint8_t id, uint8_t *dkek) {
|
||||||
file_t *tf = search_file(EF_DKEK + id);
|
file_t *tf = file_search(EF_DKEK + id);
|
||||||
if (!tf) {
|
if (!tf) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
int r = mkek_encrypt(dkek, DKEK_KEY_SIZE);
|
int r = mkek_encrypt(dkek, DKEK_KEY_SIZE);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
file_put_data(tf, dkek, DKEK_KEY_SIZE);
|
file_put_data(tf, dkek, DKEK_KEY_SIZE);
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int save_dkek_key(uint8_t id, const uint8_t *key) {
|
int save_dkek_key(uint8_t id, const uint8_t *key) {
|
||||||
uint8_t dkek[DKEK_KEY_SIZE];
|
uint8_t dkek[DKEK_KEY_SIZE];
|
||||||
if (!key) {
|
if (!key) {
|
||||||
file_t *tf = search_file(EF_DKEK + id);
|
file_t *tf = file_search(EF_DKEK + id);
|
||||||
if (!tf) {
|
if (!tf) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
|
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
|
||||||
}
|
}
|
||||||
@@ -193,9 +193,9 @@ int save_dkek_key(uint8_t id, const uint8_t *key) {
|
|||||||
|
|
||||||
int import_dkek_share(uint8_t id, const uint8_t *share) {
|
int import_dkek_share(uint8_t id, const uint8_t *share) {
|
||||||
uint8_t tmp_dkek[DKEK_KEY_SIZE];
|
uint8_t tmp_dkek[DKEK_KEY_SIZE];
|
||||||
file_t *tf = search_file(EF_DKEK + id);
|
file_t *tf = file_search(EF_DKEK + id);
|
||||||
if (!tf) {
|
if (!tf) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
memset(tmp_dkek, 0, sizeof(tmp_dkek));
|
||||||
if (file_get_size(tf) == DKEK_KEY_SIZE) {
|
if (file_get_size(tf) == DKEK_KEY_SIZE) {
|
||||||
@@ -205,8 +205,8 @@ int import_dkek_share(uint8_t id, const uint8_t *share) {
|
|||||||
tmp_dkek[i] ^= share[i];
|
tmp_dkek[i] ^= share[i];
|
||||||
}
|
}
|
||||||
file_put_data(tf, tmp_dkek, DKEK_KEY_SIZE);
|
file_put_data(tf, tmp_dkek, DKEK_KEY_SIZE);
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
|
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
|
||||||
@@ -214,45 +214,45 @@ int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
|
|||||||
memset(kcv, 0, 8);
|
memset(kcv, 0, 8);
|
||||||
memset(hsh, 0, sizeof(hsh));
|
memset(hsh, 0, sizeof(hsh));
|
||||||
int r = load_dkek(id, dkek);
|
int r = load_dkek(id, dkek);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
hash256(dkek, DKEK_KEY_SIZE, hsh);
|
hash256(dkek, DKEK_KEY_SIZE, hsh);
|
||||||
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
||||||
memcpy(kcv, hsh, 8);
|
memcpy(kcv, hsh, 8);
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes
|
static int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes
|
||||||
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
||||||
memset(kenc, 0, 32);
|
memset(kenc, 0, 32);
|
||||||
int r = load_dkek(id, dkek);
|
int r = load_dkek(id, dkek);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
|
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
|
||||||
hash256(dkek, sizeof(dkek), kenc);
|
hash256(dkek, sizeof(dkek), kenc);
|
||||||
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes
|
static int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes
|
||||||
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
uint8_t dkek[DKEK_KEY_SIZE + 4];
|
||||||
memset(kmac, 0, 32);
|
memset(kmac, 0, 32);
|
||||||
int r = load_dkek(id, dkek);
|
int r = load_dkek(id, dkek);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
|
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
|
||||||
hash256(dkek, DKEK_KEY_SIZE + 4, kmac);
|
hash256(dkek, DKEK_KEY_SIZE + 4, kmac);
|
||||||
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
mbedtls_platform_zeroize(dkek, sizeof(dkek));
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mkek_encrypt(uint8_t *data, uint16_t len) {
|
int mkek_encrypt(uint8_t *data, uint16_t len) {
|
||||||
int r;
|
int r;
|
||||||
uint8_t mkek[MKEK_SIZE];
|
uint8_t mkek[MKEK_SIZE];
|
||||||
if ((r = load_mkek(mkek)) != PICOKEY_OK) {
|
if ((r = load_mkek(mkek)) != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
|
r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
|
||||||
@@ -263,7 +263,7 @@ int mkek_encrypt(uint8_t *data, uint16_t len) {
|
|||||||
int mkek_decrypt(uint8_t *data, uint16_t len) {
|
int mkek_decrypt(uint8_t *data, uint16_t len) {
|
||||||
int r;
|
int r;
|
||||||
uint8_t mkek[MKEK_SIZE];
|
uint8_t mkek[MKEK_SIZE];
|
||||||
if ((r = load_mkek(mkek)) != PICOKEY_OK) {
|
if ((r = load_mkek(mkek)) != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
|
r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
|
||||||
@@ -272,8 +272,8 @@ int mkek_decrypt(uint8_t *data, uint16_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint16_t *out_len, const uint8_t *allowed, uint16_t allowed_len) {
|
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint16_t *out_len, const uint8_t *allowed, uint16_t allowed_len) {
|
||||||
if (!(key_type & PICO_KEYS_KEY_RSA) && !(key_type & PICO_KEYS_KEY_EC) && !(key_type & PICO_KEYS_KEY_AES)) {
|
if (!(key_type & PICOKEYS_KEY_RSA) && !(key_type & PICOKEYS_KEY_EC) && !(key_type & PICOKEYS_KEY_AES)) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||||
@@ -285,104 +285,104 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
|||||||
uint8_t kenc[32];
|
uint8_t kenc[32];
|
||||||
memset(kenc, 0, sizeof(kenc));
|
memset(kenc, 0, sizeof(kenc));
|
||||||
r = dkek_kenc(id, kenc);
|
r = dkek_kenc(id, kenc);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kcv[8];
|
uint8_t kcv[8];
|
||||||
memset(kcv, 0, sizeof(kcv));
|
memset(kcv, 0, sizeof(kcv));
|
||||||
r = dkek_kcv(id, kcv);
|
r = dkek_kcv(id, kcv);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kmac[32];
|
uint8_t kmac[32];
|
||||||
memset(kmac, 0, sizeof(kmac));
|
memset(kmac, 0, sizeof(kmac));
|
||||||
r = dkek_kmac(id, kmac);
|
r = dkek_kmac(id, kmac);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_type & PICO_KEYS_KEY_AES) {
|
if (key_type & PICOKEYS_KEY_AES) {
|
||||||
if (key_type & PICO_KEYS_KEY_AES_128) {
|
if (key_type & PICOKEYS_KEY_AES_128) {
|
||||||
kb_len = 16;
|
kb_len = 16;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES_192) {
|
else if (key_type & PICOKEYS_KEY_AES_192) {
|
||||||
kb_len = 24;
|
kb_len = 24;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES_256) {
|
else if (key_type & PICOKEYS_KEY_AES_256) {
|
||||||
kb_len = 32;
|
kb_len = 32;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_AES_512) {
|
else if (key_type & PICOKEYS_KEY_AES_512) {
|
||||||
kb_len = 64;
|
kb_len = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kb_len != 16 && kb_len != 24 && kb_len != 32 && kb_len != 64) {
|
if (kb_len != 16 && kb_len != 24 && kb_len != 32 && kb_len != 64) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (*out_len < 8 + 1 + 10 + 6 + (2 + 64 + 14) + 16) { // 14 bytes padding
|
if (*out_len < 8 + 1 + 10 + 6 + (2 + 64 + 14) + 16) { // 14 bytes padding
|
||||||
return PICOKEY_WRONG_LENGTH;
|
return PICOKEYS_WRONG_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
put_uint16_t_be(kb_len, kb + 8);
|
put_uint16_be(kb_len, kb + 8);
|
||||||
memcpy(kb + 10, key_ctx, kb_len);
|
memcpy(kb + 10, key_ctx, kb_len);
|
||||||
kb_len += 2;
|
kb_len += 2;
|
||||||
|
|
||||||
algo = (uint8_t *) "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
|
algo = (uint8_t *) "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
|
||||||
algo_len = 10;
|
algo_len = 10;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_RSA) {
|
else if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) { //13 bytes pading
|
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) { //13 bytes pading
|
||||||
return PICOKEY_WRONG_LENGTH;
|
return PICOKEYS_WRONG_LENGTH;
|
||||||
}
|
}
|
||||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||||
kb_len = 0;
|
kb_len = 0;
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len);
|
||||||
|
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->D), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->D), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&rsa->D, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->D));
|
mbedtls_mpi_write_binary(&rsa->D, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->D));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->D);
|
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->D);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->N), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->N), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&rsa->N, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->N));
|
mbedtls_mpi_write_binary(&rsa->N, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->N));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->N);
|
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->N);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->E), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->E), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&rsa->E, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->E));
|
mbedtls_mpi_write_binary(&rsa->E, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->E));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->E);
|
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->E);
|
||||||
|
|
||||||
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
|
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
|
||||||
algo_len = 12;
|
algo_len = 12;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 8 + 9 * 66 + 2 + 4) + 16) { //4 bytes pading
|
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 8 + 9 * 66 + 2 + 4) + 16) { //4 bytes pading
|
||||||
return PICOKEY_WRONG_LENGTH;
|
return PICOKEYS_WRONG_LENGTH;
|
||||||
}
|
}
|
||||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
||||||
kb_len = 0;
|
kb_len = 0;
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P) * 8, kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P) * 8, kb + 8 + kb_len);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.A), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.A), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&ecdsa->grp.A, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.A));
|
mbedtls_mpi_write_binary(&ecdsa->grp.A, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.A));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.A);
|
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.A);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.B), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.B), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&ecdsa->grp.B, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.B));
|
mbedtls_mpi_write_binary(&ecdsa->grp.B, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.B));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.B);
|
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.B);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&ecdsa->grp.P, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.P));
|
mbedtls_mpi_write_binary(&ecdsa->grp.P, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.P));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.P);
|
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.P);
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.N), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.N), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&ecdsa->grp.N, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.N));
|
mbedtls_mpi_write_binary(&ecdsa->grp.N, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.N));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N);
|
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N);
|
||||||
|
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
|
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
|
||||||
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)olen, kb + 8 + kb_len);
|
||||||
kb_len += (uint16_t)olen;
|
kb_len += (uint16_t)olen;
|
||||||
|
|
||||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->d), kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->d), kb + 8 + kb_len);
|
||||||
mbedtls_mpi_write_binary(&ecdsa->d, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->d));
|
mbedtls_mpi_write_binary(&ecdsa->d, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->d));
|
||||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->d);
|
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->d);
|
||||||
|
|
||||||
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
|
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
|
||||||
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len);
|
kb_len += put_uint16_be((uint16_t)olen, kb + 8 + kb_len);
|
||||||
kb_len += (uint16_t)olen;
|
kb_len += (uint16_t)olen;
|
||||||
|
|
||||||
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
||||||
@@ -394,13 +394,13 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
|||||||
memcpy(out + *out_len, kcv, 8);
|
memcpy(out + *out_len, kcv, 8);
|
||||||
*out_len += 8;
|
*out_len += 8;
|
||||||
|
|
||||||
if (key_type & PICO_KEYS_KEY_AES) {
|
if (key_type & PICOKEYS_KEY_AES) {
|
||||||
out[*out_len] = 15;
|
out[*out_len] = 15;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_RSA) {
|
else if (key_type & PICOKEYS_KEY_RSA) {
|
||||||
out[*out_len] = 5;
|
out[*out_len] = 5;
|
||||||
}
|
}
|
||||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
else if (key_type & PICOKEYS_KEY_EC) {
|
||||||
out[*out_len] = 12;
|
out[*out_len] = 12;
|
||||||
}
|
}
|
||||||
*out_len += 1;
|
*out_len += 1;
|
||||||
@@ -414,7 +414,7 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (allowed && allowed_len > 0) {
|
if (allowed && allowed_len > 0) {
|
||||||
*out_len += put_uint16_t_be(allowed_len, out + *out_len);
|
*out_len += put_uint16_be(allowed_len, out + *out_len);
|
||||||
memcpy(out + *out_len, allowed, allowed_len);
|
memcpy(out + *out_len, allowed, allowed_len);
|
||||||
*out_len += allowed_len;
|
*out_len += allowed_len;
|
||||||
}
|
}
|
||||||
@@ -434,8 +434,8 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
|||||||
if (kb_len < kb_len_pad) {
|
if (kb_len < kb_len_pad) {
|
||||||
kb[kb_len] = 0x80;
|
kb[kb_len] = 0x80;
|
||||||
}
|
}
|
||||||
r = aes_encrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, kb_len_pad);
|
r = aes_encrypt(kenc, NULL, 256, PICOKEYS_AES_MODE_CBC, kb, kb_len_pad);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,18 +448,18 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
|||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dkek_type_key(const uint8_t *in) {
|
int dkek_type_key(const uint8_t *in) {
|
||||||
if (in[8] == 5 || in[8] == 6) {
|
if (in[8] == 5 || in[8] == 6) {
|
||||||
return PICO_KEYS_KEY_RSA;
|
return PICOKEYS_KEY_RSA;
|
||||||
}
|
}
|
||||||
else if (in[8] == 12) {
|
else if (in[8] == 12) {
|
||||||
return PICO_KEYS_KEY_EC;
|
return PICOKEYS_KEY_EC;
|
||||||
}
|
}
|
||||||
else if (in[8] == 15) {
|
else if (in[8] == 15) {
|
||||||
return PICO_KEYS_KEY_AES;
|
return PICOKEYS_KEY_AES;
|
||||||
}
|
}
|
||||||
return 0x0;
|
return 0x0;
|
||||||
}
|
}
|
||||||
@@ -469,88 +469,88 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
memset(kcv, 0, sizeof(kcv));
|
memset(kcv, 0, sizeof(kcv));
|
||||||
r = dkek_kcv(id, kcv);
|
r = dkek_kcv(id, kcv);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kmac[32];
|
uint8_t kmac[32];
|
||||||
memset(kmac, 0, sizeof(kmac));
|
memset(kmac, 0, sizeof(kmac));
|
||||||
r = dkek_kmac(id, kmac);
|
r = dkek_kmac(id, kmac);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t kenc[32];
|
uint8_t kenc[32];
|
||||||
memset(kenc, 0, sizeof(kenc));
|
memset(kenc, 0, sizeof(kenc));
|
||||||
r = dkek_kenc(id, kenc);
|
r = dkek_kenc(id, kenc);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(kcv, in, 8) != 0) {
|
if (memcmp(kcv, in, 8) != 0) {
|
||||||
return PICOKEY_WRONG_DKEK;
|
return PICOKEYS_WRONG_DKEK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t signature[16];
|
uint8_t signature[16];
|
||||||
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len - 16, signature);
|
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len - 16, signature);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return PICOKEY_WRONG_SIGNATURE;
|
return PICOKEYS_WRONG_SIGNATURE;
|
||||||
}
|
}
|
||||||
if (memcmp(signature, in + in_len - 16, 16) != 0) {
|
if (memcmp(signature, in + in_len - 16, 16) != 0) {
|
||||||
return PICOKEY_WRONG_SIGNATURE;
|
return PICOKEYS_WRONG_SIGNATURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int key_type = in[8];
|
int key_type = in[8];
|
||||||
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) {
|
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((key_type == 5 || key_type == 6) &&
|
if ((key_type == 5 || key_type == 6) &&
|
||||||
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) {
|
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_type == 12 &&
|
if (key_type == 12 &&
|
||||||
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
|
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
|
if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ofs = 9;
|
uint16_t ofs = 9;
|
||||||
|
|
||||||
//OID
|
//OID
|
||||||
uint16_t len = get_uint16_t_be(in + ofs);
|
uint16_t len = get_uint16_be(in + ofs);
|
||||||
ofs += len + 2;
|
ofs += len + 2;
|
||||||
|
|
||||||
//Allowed algorithms
|
//Allowed algorithms
|
||||||
len = get_uint16_t_be(in + ofs);
|
len = get_uint16_be(in + ofs);
|
||||||
*allowed = (uint8_t *) (in + ofs + 2);
|
*allowed = (uint8_t *) (in + ofs + 2);
|
||||||
*allowed_len = len;
|
*allowed_len = len;
|
||||||
ofs += len + 2;
|
ofs += len + 2;
|
||||||
|
|
||||||
//Access conditions
|
//Access conditions
|
||||||
len = get_uint16_t_be(in + ofs);
|
len = get_uint16_be(in + ofs);
|
||||||
ofs += len + 2;
|
ofs += len + 2;
|
||||||
|
|
||||||
//Key OID
|
//Key OID
|
||||||
len = get_uint16_t_be(in + ofs);
|
len = get_uint16_be(in + ofs);
|
||||||
ofs += len + 2;
|
ofs += len + 2;
|
||||||
|
|
||||||
if ((in_len - 16 - ofs) % 16 != 0) {
|
if ((in_len - 16 - ofs) % 16 != 0) {
|
||||||
return PICOKEY_WRONG_PADDING;
|
return PICOKEYS_WRONG_PADDING;
|
||||||
}
|
}
|
||||||
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
|
||||||
memset(kb, 0, sizeof(kb));
|
memset(kb, 0, sizeof(kb));
|
||||||
memcpy(kb, in + ofs, in_len - 16 - ofs);
|
memcpy(kb, in + ofs, in_len - 16 - ofs);
|
||||||
r = aes_decrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, in_len - 16 - ofs);
|
r = aes_decrypt(kenc, NULL, 256, PICOKEYS_AES_MODE_CBC, kb, in_len - 16 - ofs);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int key_size = get_uint16_t_be(kb + 8);
|
int key_size = get_uint16_be(kb + 8);
|
||||||
if (key_size_out) {
|
if (key_size_out) {
|
||||||
*key_size_out = key_size;
|
*key_size_out = key_size;
|
||||||
}
|
}
|
||||||
@@ -559,78 +559,78 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
|||||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||||
mbedtls_rsa_init(rsa);
|
mbedtls_rsa_init(rsa);
|
||||||
if (key_type == 5) {
|
if (key_type == 5) {
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len;
|
r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len;
|
r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type == 6) {
|
else if (key_type == 6) {
|
||||||
//DP-1
|
//DP-1
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
//DQ-1
|
//DQ-1
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len;
|
r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
//PQ
|
//PQ
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len;
|
r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
//N
|
//N
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len;
|
r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len;
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key_type == 5) {
|
if (key_type == 5) {
|
||||||
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
|
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type == 6) {
|
else if (key_type == 6) {
|
||||||
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
|
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mbedtls_rsa_complete(rsa);
|
r = mbedtls_rsa_complete(rsa);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
r = mbedtls_rsa_check_privkey(rsa);
|
r = mbedtls_rsa_check_privkey(rsa);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_rsa_free(rsa);
|
mbedtls_rsa_free(rsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type == 12) {
|
else if (key_type == 12) {
|
||||||
@@ -638,25 +638,25 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
|||||||
mbedtls_ecdsa_init(ecdsa);
|
mbedtls_ecdsa_init(ecdsa);
|
||||||
|
|
||||||
//A
|
//A
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
//B
|
//B
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
//P
|
//P
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len);
|
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len);
|
||||||
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||||
mbedtls_ecdsa_free(ecdsa);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
ofs += len;
|
ofs += len;
|
||||||
|
|
||||||
//N
|
//N
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
len = get_uint16_be(kb + ofs); ofs += len + 2;
|
||||||
|
|
||||||
//G
|
//G
|
||||||
len = get_uint16_t_be(kb + ofs);
|
len = get_uint16_be(kb + ofs);
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
#ifdef MBEDTLS_EDDSA_C
|
||||||
if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) {
|
if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) {
|
||||||
ec_id = MBEDTLS_ECP_DP_ED25519;
|
ec_id = MBEDTLS_ECP_DP_ED25519;
|
||||||
@@ -668,40 +668,32 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
|||||||
ofs += len + 2;
|
ofs += len + 2;
|
||||||
|
|
||||||
//d
|
//d
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len);
|
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecdsa_free(ecdsa);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
ofs += len;
|
ofs += len;
|
||||||
|
|
||||||
//Q
|
//Q
|
||||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
len = get_uint16_be(kb + ofs); ofs += 2;
|
||||||
r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len);
|
r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
r = mbedtls_ecp_keypair_calc_public(ecdsa, random_fill_iterator, NULL);
|
||||||
if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS) {
|
|
||||||
r = mbedtls_ecp_point_edwards(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, random_gen, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
r = mbedtls_ecp_mul(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, &ecdsa->grp.G, random_gen, NULL);
|
|
||||||
}
|
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecdsa_free(ecdsa);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r = mbedtls_ecp_check_pub_priv(ecdsa, ecdsa, random_gen, NULL);
|
r = mbedtls_ecp_check_pub_priv(ecdsa, ecdsa, random_fill_iterator, NULL);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecdsa_free(ecdsa);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (key_type == 15) {
|
else if (key_type == 15) {
|
||||||
memcpy(key_ctx, kb + ofs, key_size);
|
memcpy(key_ctx, kb + ofs, key_size);
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
171
src/hsm/sc_hsm.c
171
src/hsm/sc_hsm.c
@@ -15,6 +15,8 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "picokeys.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "sc_hsm.h"
|
#include "sc_hsm.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@@ -23,7 +25,6 @@
|
|||||||
#include "eac.h"
|
#include "eac.h"
|
||||||
#include "cvc.h"
|
#include "cvc.h"
|
||||||
#include "asn1.h"
|
#include "asn1.h"
|
||||||
#include "pico_keys.h"
|
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@@ -60,17 +61,21 @@ static int sc_hsm_select_aid(app_t *a, uint8_t force) {
|
|||||||
a->process_apdu = sc_hsm_process_apdu;
|
a->process_apdu = sc_hsm_process_apdu;
|
||||||
a->unload = sc_hsm_unload;
|
a->unload = sc_hsm_unload;
|
||||||
init_sc_hsm();
|
init_sc_hsm();
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_atr(void) {
|
||||||
|
ccid_atr = atr_sc_hsm;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZER( sc_hsm_ctor ) {
|
INITIALIZER( sc_hsm_ctor ) {
|
||||||
printf("INITIALIZER\n");
|
printf("INITIALIZER\n");
|
||||||
ccid_atr = atr_sc_hsm;
|
|
||||||
register_app(sc_hsm_select_aid, sc_hsm_aid);
|
register_app(sc_hsm_select_aid, sc_hsm_aid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_files(void) {
|
static void scan_files(void) {
|
||||||
file_pin1 = search_file(EF_PIN1);
|
file_pin1 = file_search(EF_PIN1);
|
||||||
if (file_pin1) {
|
if (file_pin1) {
|
||||||
if (!file_pin1->data) {
|
if (!file_pin1->data) {
|
||||||
printf("PIN1 is empty. Initializing with default password\n");
|
printf("PIN1 is empty. Initializing with default password\n");
|
||||||
@@ -81,7 +86,7 @@ static void scan_files(void) {
|
|||||||
else {
|
else {
|
||||||
printf("FATAL ERROR: PIN1 not found in memory!\n");
|
printf("FATAL ERROR: PIN1 not found in memory!\n");
|
||||||
}
|
}
|
||||||
file_sopin = search_file(EF_SOPIN);
|
file_sopin = file_search(EF_SOPIN);
|
||||||
if (file_sopin) {
|
if (file_sopin) {
|
||||||
if (!file_sopin->data) {
|
if (!file_sopin->data) {
|
||||||
printf("SOPIN is empty. Initializing with default password\n");
|
printf("SOPIN is empty. Initializing with default password\n");
|
||||||
@@ -92,7 +97,7 @@ static void scan_files(void) {
|
|||||||
else {
|
else {
|
||||||
printf("FATAL ERROR: SOPIN not found in memory!\n");
|
printf("FATAL ERROR: SOPIN not found in memory!\n");
|
||||||
}
|
}
|
||||||
file_retries_pin1 = search_file(EF_PIN1_RETRIES);
|
file_retries_pin1 = file_search(EF_PIN1_RETRIES);
|
||||||
if (file_retries_pin1) {
|
if (file_retries_pin1) {
|
||||||
if (!file_retries_pin1->data) {
|
if (!file_retries_pin1->data) {
|
||||||
printf("Retries PIN1 is empty. Initializing with default retriesr\n");
|
printf("Retries PIN1 is empty. Initializing with default retriesr\n");
|
||||||
@@ -103,7 +108,7 @@ static void scan_files(void) {
|
|||||||
else {
|
else {
|
||||||
printf("FATAL ERROR: Retries PIN1 not found in memory!\n");
|
printf("FATAL ERROR: Retries PIN1 not found in memory!\n");
|
||||||
}
|
}
|
||||||
file_retries_sopin = search_file(EF_SOPIN_RETRIES);
|
file_retries_sopin = file_search(EF_SOPIN_RETRIES);
|
||||||
if (file_retries_sopin) {
|
if (file_retries_sopin) {
|
||||||
if (!file_retries_sopin->data) {
|
if (!file_retries_sopin->data) {
|
||||||
printf("Retries SOPIN is empty. Initializing with default retries\n");
|
printf("Retries SOPIN is empty. Initializing with default retries\n");
|
||||||
@@ -116,7 +121,7 @@ static void scan_files(void) {
|
|||||||
}
|
}
|
||||||
file_t *tf = NULL;
|
file_t *tf = NULL;
|
||||||
|
|
||||||
tf = search_file(EF_PIN1_MAX_RETRIES);
|
tf = file_search(EF_PIN1_MAX_RETRIES);
|
||||||
if (tf) {
|
if (tf) {
|
||||||
if (!tf->data) {
|
if (!tf->data) {
|
||||||
printf("Max retries PIN1 is empty. Initializing with default max retriesr\n");
|
printf("Max retries PIN1 is empty. Initializing with default max retriesr\n");
|
||||||
@@ -127,7 +132,7 @@ static void scan_files(void) {
|
|||||||
else {
|
else {
|
||||||
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\n");
|
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\n");
|
||||||
}
|
}
|
||||||
tf = search_file(EF_SOPIN_MAX_RETRIES);
|
tf = file_search(EF_SOPIN_MAX_RETRIES);
|
||||||
if (tf) {
|
if (tf) {
|
||||||
if (!tf->data) {
|
if (!tf->data) {
|
||||||
printf("Max Retries SOPIN is empty. Initializing with default max retries\n");
|
printf("Max Retries SOPIN is empty. Initializing with default max retries\n");
|
||||||
@@ -138,11 +143,11 @@ static void scan_files(void) {
|
|||||||
else {
|
else {
|
||||||
printf("FATAL ERROR: Retries SOPIN not found in memory!\n");
|
printf("FATAL ERROR: Retries SOPIN not found in memory!\n");
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scan_all(void) {
|
void scan_all(void) {
|
||||||
scan_flash();
|
file_scan_flash();
|
||||||
scan_files();
|
scan_files();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,10 +158,10 @@ uint8_t puk_status[MAX_PUK];
|
|||||||
|
|
||||||
int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) {
|
int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) {
|
||||||
if (data == NULL || data_len == 0) {
|
if (data == NULL || data_len == 0) {
|
||||||
return PICOKEY_ERR_NULL_PARAM;
|
return PICOKEYS_ERR_NULL_PARAM;
|
||||||
}
|
}
|
||||||
if (puk_store_entries == MAX_PUK_STORE_ENTRIES) {
|
if (puk_store_entries == MAX_PUK_STORE_ENTRIES) {
|
||||||
return PICOKEY_ERR_MEMORY_FATAL;
|
return PICOKEYS_ERR_MEMORY_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
puk_store[puk_store_entries].copied = copy;
|
puk_store[puk_store_entries].copied = copy;
|
||||||
@@ -180,17 +185,17 @@ int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) {
|
|||||||
&puk_store[puk_store_entries].puk_len);
|
&puk_store[puk_store_entries].puk_len);
|
||||||
|
|
||||||
puk_store_entries++;
|
puk_store_entries++;
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int puk_store_select_chr(const uint8_t *chr) {
|
int puk_store_select_chr(const uint8_t *chr) {
|
||||||
for (int i = 0; i < puk_store_entries; i++) {
|
for (int i = 0; i < puk_store_entries; i++) {
|
||||||
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
|
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
|
||||||
current_puk = &puk_store[i];
|
current_puk = &puk_store[i];
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_puk_store(void) {
|
void reset_puk_store(void) {
|
||||||
@@ -203,7 +208,7 @@ void reset_puk_store(void) {
|
|||||||
}
|
}
|
||||||
memset(puk_store, 0, sizeof(puk_store));
|
memset(puk_store, 0, sizeof(puk_store));
|
||||||
puk_store_entries = 0;
|
puk_store_entries = 0;
|
||||||
file_t *fterm = search_file(EF_TERMCA);
|
file_t *fterm = file_search(EF_TERMCA);
|
||||||
if (fterm) {
|
if (fterm) {
|
||||||
uint8_t *p = NULL, *fterm_data = file_get_data(fterm), *pq = fterm_data;
|
uint8_t *p = NULL, *fterm_data = file_get_data(fterm), *pq = fterm_data;
|
||||||
uint16_t fterm_data_len = file_get_size(fterm);
|
uint16_t fterm_data_len = file_get_size(fterm);
|
||||||
@@ -215,7 +220,7 @@ void reset_puk_store(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 0xfe; i++) {
|
for (int i = 0; i < 0xfe; i++) {
|
||||||
file_t *ef = search_file((CA_CERTIFICATE_PREFIX << 8) | (uint8_t)i);
|
file_t *ef = file_search((CA_CERTIFICATE_PREFIX << 8) | (uint8_t)i);
|
||||||
if (ef && file_get_size(ef) > 0) {
|
if (ef && file_get_size(ef) > 0) {
|
||||||
add_cert_puk_store(file_get_data(ef), file_get_size(ef), false);
|
add_cert_puk_store(file_get_data(ef), file_get_size(ef), false);
|
||||||
}
|
}
|
||||||
@@ -235,13 +240,13 @@ void init_sc_hsm(void) {
|
|||||||
int sc_hsm_unload(void) {
|
int sc_hsm_unload(void) {
|
||||||
has_session_pin = has_session_sopin = false;
|
has_session_pin = has_session_sopin = false;
|
||||||
isUserAuthenticated = false;
|
isUserAuthenticated = false;
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t get_device_options(void) {
|
uint16_t get_device_options(void) {
|
||||||
file_t *ef = search_file(EF_DEVOPS);
|
file_t *ef = file_search(EF_DEVOPS);
|
||||||
if (file_has_data(ef)) {
|
if (file_has_data(ef)) {
|
||||||
return get_uint16_t_be(file_get_data(ef));
|
return get_uint16_be(file_get_data(ef));
|
||||||
}
|
}
|
||||||
return 0x0;
|
return 0x0;
|
||||||
}
|
}
|
||||||
@@ -308,49 +313,49 @@ int parse_ef_dir(const file_t *f, int mode) {
|
|||||||
|
|
||||||
int pin_reset_retries(const file_t *pin, bool force) {
|
int pin_reset_retries(const file_t *pin, bool force) {
|
||||||
if (!pin) {
|
if (!pin) {
|
||||||
return PICOKEY_ERR_NULL_PARAM;
|
return PICOKEYS_ERR_NULL_PARAM;
|
||||||
}
|
}
|
||||||
const file_t *max = search_file(pin->fid + 1);
|
const file_t *max = file_search(pin->fid + 1);
|
||||||
const file_t *act = search_file(pin->fid + 2);
|
const file_t *act = file_search(pin->fid + 2);
|
||||||
if (!max || !act) {
|
if (!max || !act) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t retries = file_read_uint8(act);
|
uint8_t retries = file_read_uint8(act);
|
||||||
if (retries == 0 && force == false) { // blocked
|
if (retries == 0 && force == false) { // blocked
|
||||||
return PICOKEY_ERR_BLOCKED;
|
return PICOKEYS_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
retries = file_read_uint8(max);
|
retries = file_read_uint8(max);
|
||||||
int r = file_put_data((file_t *) act, &retries, sizeof(retries));
|
int r = file_put_data((file_t *) act, &retries, sizeof(retries));
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pin_wrong_retry(const file_t *pin) {
|
int pin_wrong_retry(const file_t *pin) {
|
||||||
if (!pin) {
|
if (!pin) {
|
||||||
return PICOKEY_ERR_NULL_PARAM;
|
return PICOKEYS_ERR_NULL_PARAM;
|
||||||
}
|
}
|
||||||
const file_t *act = search_file(pin->fid + 2);
|
const file_t *act = file_search(pin->fid + 2);
|
||||||
if (!act) {
|
if (!act) {
|
||||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
return PICOKEYS_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t retries = file_read_uint8(act);
|
uint8_t retries = file_read_uint8(act);
|
||||||
if (retries > 0) {
|
if (retries > 0) {
|
||||||
retries -= 1;
|
retries -= 1;
|
||||||
int r = file_put_data((file_t *) act, &retries, sizeof(retries));
|
int r = file_put_data((file_t *) act, &retries, sizeof(retries));
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
if (retries == 0) {
|
if (retries == 0) {
|
||||||
return PICOKEY_ERR_BLOCKED;
|
return PICOKEYS_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
return retries;
|
return retries;
|
||||||
}
|
}
|
||||||
return PICOKEY_ERR_BLOCKED;
|
return PICOKEYS_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pka_enabled(void) {
|
bool pka_enabled(void) {
|
||||||
file_t *ef_puk = search_file(EF_PUKAUT);
|
file_t *ef_puk = file_search(EF_PUKAUT);
|
||||||
return file_has_data(ef_puk) && file_read_uint8(ef_puk) > 0;
|
return file_has_data(ef_puk) && file_read_uint8(ef_puk) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,20 +380,20 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) {
|
|||||||
}
|
}
|
||||||
if (memcmp(file_get_data(pin) + off, dhash, sizeof(dhash)) != 0) {
|
if (memcmp(file_get_data(pin) + off, dhash, sizeof(dhash)) != 0) {
|
||||||
int retries;
|
int retries;
|
||||||
if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) {
|
if ((retries = pin_wrong_retry(pin)) < PICOKEYS_OK) {
|
||||||
return SW_PIN_BLOCKED();
|
return SW_PIN_BLOCKED();
|
||||||
}
|
}
|
||||||
return set_res_sw(0x63, 0xc0 | (uint8_t)retries);
|
return set_res_sw(0x63, 0xc0 | (uint8_t)retries);
|
||||||
}
|
}
|
||||||
int r = pin_reset_retries(pin, false);
|
int r = pin_reset_retries(pin, false);
|
||||||
if (r == PICOKEY_ERR_BLOCKED) {
|
if (r == PICOKEYS_ERR_BLOCKED) {
|
||||||
return SW_PIN_BLOCKED();
|
return SW_PIN_BLOCKED();
|
||||||
}
|
}
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
if (off == 1) { // Upgrade PIN format
|
if (off == 1) { // Upgrade PIN format
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
if (pin == file_pin1) {
|
if (pin == file_pin1) {
|
||||||
@@ -401,7 +406,7 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) {
|
|||||||
}
|
}
|
||||||
uint8_t mkek[MKEK_SIZE_OLD]; // Old MKEK size, as it is encrypted with old PIN format
|
uint8_t mkek[MKEK_SIZE_OLD]; // Old MKEK size, as it is encrypted with old PIN format
|
||||||
r = load_mkek(mkek); //loads the MKEK with old format
|
r = load_mkek(mkek); //loads the MKEK with old format
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
if (pin == file_pin1) {
|
if (pin == file_pin1) {
|
||||||
@@ -412,7 +417,7 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) {
|
|||||||
}
|
}
|
||||||
r = store_mkek(mkek); //stores the MKEK with new format
|
r = store_mkek(mkek); //stores the MKEK with new format
|
||||||
mbedtls_platform_zeroize(mkek, sizeof(mkek));
|
mbedtls_platform_zeroize(mkek, sizeof(mkek));
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,10 +426,10 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) {
|
|||||||
pin_data[1] = 1; // new format indicator
|
pin_data[1] = 1; // new format indicator
|
||||||
pin_derive_verifier(data, len, pin_data + 2);
|
pin_derive_verifier(data, len, pin_data + 2);
|
||||||
r = file_put_data((file_t *) pin, pin_data, sizeof(pin_data));
|
r = file_put_data((file_t *) pin, pin_data, sizeof(pin_data));
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
}
|
}
|
||||||
if (pka_enabled() == false) {
|
if (pka_enabled() == false) {
|
||||||
isUserAuthenticated = true;
|
isUserAuthenticated = true;
|
||||||
@@ -468,7 +473,7 @@ uint32_t get_key_counter(file_t *fkey) {
|
|||||||
uint16_t tag_len = 0;
|
uint16_t tag_len = 0;
|
||||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
|
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
|
||||||
if (meta_tag) {
|
if (meta_tag) {
|
||||||
return get_uint32_t_be(meta_tag);
|
return get_uint32_be(meta_tag);
|
||||||
}
|
}
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
}
|
}
|
||||||
@@ -504,15 +509,15 @@ uint32_t decrement_key_counter(file_t *fkey) {
|
|||||||
asn1_ctx_init(meta_data, meta_size, &ctxi);
|
asn1_ctx_init(meta_data, meta_size, &ctxi);
|
||||||
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
||||||
if (tag == 0x90) { // ofset tag
|
if (tag == 0x90) { // ofset tag
|
||||||
uint32_t val = get_uint32_t_be(tag_data);
|
uint32_t val = get_uint32_be(tag_data);
|
||||||
val--;
|
val--;
|
||||||
put_uint32_t_be(val, tag_data);
|
put_uint32_be(val, tag_data);
|
||||||
int r = meta_add(fkey->fid, cmeta, (uint16_t)meta_size);
|
int r = meta_add(fkey->fid, cmeta, (uint16_t)meta_size);
|
||||||
free(cmeta);
|
free(cmeta);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -526,52 +531,52 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) {
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
uint16_t key_size = 0;
|
uint16_t key_size = 0;
|
||||||
uint8_t kdata[4096 / 8]; // worst case
|
uint8_t kdata[4096 / 8]; // worst case
|
||||||
if (type & PICO_KEYS_KEY_RSA) {
|
if (type & PICOKEYS_KEY_RSA) {
|
||||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||||
key_size = (uint16_t)mbedtls_mpi_size(&rsa->P) + (uint16_t)mbedtls_mpi_size(&rsa->Q);
|
key_size = (uint16_t)mbedtls_mpi_size(&rsa->P) + (uint16_t)mbedtls_mpi_size(&rsa->Q);
|
||||||
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2);
|
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2);
|
||||||
mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2);
|
mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2);
|
||||||
}
|
}
|
||||||
else if (type & PICO_KEYS_KEY_EC) {
|
else if (type & PICOKEYS_KEY_EC) {
|
||||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
kdata[0] = ecdsa->grp.id & 0xff;
|
kdata[0] = ecdsa->grp.id & 0xff;
|
||||||
mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1);
|
mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1);
|
||||||
key_size = olen + 1;
|
key_size = olen + 1;
|
||||||
}
|
}
|
||||||
else if (type & PICO_KEYS_KEY_AES) {
|
else if (type & PICOKEYS_KEY_AES) {
|
||||||
if (type == PICO_KEYS_KEY_AES_128) {
|
if (type == PICOKEYS_KEY_AES_128) {
|
||||||
key_size = 16;
|
key_size = 16;
|
||||||
}
|
}
|
||||||
else if (type == PICO_KEYS_KEY_AES_192) {
|
else if (type == PICOKEYS_KEY_AES_192) {
|
||||||
key_size = 24;
|
key_size = 24;
|
||||||
}
|
}
|
||||||
else if (type == PICO_KEYS_KEY_AES_256) {
|
else if (type == PICOKEYS_KEY_AES_256) {
|
||||||
key_size = 32;
|
key_size = 32;
|
||||||
}
|
}
|
||||||
else if (type == PICO_KEYS_KEY_AES_512) {
|
else if (type == PICOKEYS_KEY_AES_512) {
|
||||||
key_size = 64;
|
key_size = 64;
|
||||||
}
|
}
|
||||||
memcpy(kdata, key_ctx, key_size);
|
memcpy(kdata, key_ctx, key_size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||||
if (!fpk) {
|
if (!fpk) {
|
||||||
return PICOKEY_ERR_MEMORY_FATAL;
|
return PICOKEYS_ERR_MEMORY_FATAL;
|
||||||
}
|
}
|
||||||
r = mkek_encrypt(kdata, key_size);
|
r = mkek_encrypt(kdata, key_size);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r = file_put_data(fpk, kdata, (uint16_t)key_size);
|
r = file_put_data(fpk, kdata, (uint16_t)key_size);
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
char key_id_str[4] = {0};
|
char key_id_str[4] = {0};
|
||||||
sprintf(key_id_str, "%u", key_id);
|
sprintf(key_id_str, "%u", key_id);
|
||||||
if (type & PICO_KEYS_KEY_EC) {
|
if (type & PICOKEYS_KEY_EC) {
|
||||||
key_size--;
|
key_size--;
|
||||||
}
|
}
|
||||||
uint16_t prkd_len = asn1_build_prkd_generic(NULL, 0, (uint8_t *)key_id_str, (uint16_t)strlen(key_id_str), key_size * 8, type, kdata, sizeof(kdata));
|
uint16_t prkd_len = asn1_build_prkd_generic(NULL, 0, (uint8_t *)key_id_str, (uint16_t)strlen(key_id_str), key_size * 8, type, kdata, sizeof(kdata));
|
||||||
@@ -582,8 +587,8 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) {
|
|||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
low_flash_available();
|
flash_commit();
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_and_store_meta_key(uint8_t key_id) {
|
int find_and_store_meta_key(uint8_t key_id) {
|
||||||
@@ -617,89 +622,81 @@ int find_and_store_meta_key(uint8_t key_id) {
|
|||||||
int r = meta_add((KEY_PREFIX << 8) | key_id, meta, (uint16_t)meta_size);
|
int r = meta_add((KEY_PREFIX << 8) | key_id, meta, (uint16_t)meta_size);
|
||||||
free(meta);
|
free(meta);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
||||||
if (wait_button_pressed() == true) { // timeout
|
if (wait_button_pressed() == true) { // timeout
|
||||||
return PICOKEY_VERIFICATION_FAILED;
|
return PICOKEYS_VERIFICATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t key_size = file_get_size(fkey);
|
uint16_t key_size = file_get_size(fkey);
|
||||||
uint8_t kdata[4096 / 8];
|
uint8_t kdata[4096 / 8];
|
||||||
memcpy(kdata, file_get_data(fkey), key_size);
|
memcpy(kdata, file_get_data(fkey), key_size);
|
||||||
if (mkek_decrypt(kdata, key_size) != 0) {
|
if (mkek_decrypt(kdata, key_size) != 0) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) {
|
if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) {
|
if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) {
|
if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (mbedtls_rsa_complete(ctx) != 0) {
|
if (mbedtls_rsa_complete(ctx) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
if (mbedtls_rsa_check_privkey(ctx) != 0) {
|
if (mbedtls_rsa_check_privkey(ctx) != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_rsa_free(ctx);
|
mbedtls_rsa_free(ctx);
|
||||||
return PICOKEY_WRONG_DATA;
|
return PICOKEYS_WRONG_DATA;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
||||||
if (wait_button_pressed() == true) { // timeout
|
if (wait_button_pressed() == true) { // timeout
|
||||||
return PICOKEY_VERIFICATION_FAILED;
|
return PICOKEYS_VERIFICATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t key_size = file_get_size(fkey);
|
uint16_t key_size = file_get_size(fkey);
|
||||||
uint8_t kdata[67]; // Worst case, 521 bit + 1byte
|
uint8_t kdata[67]; // Worst case, 521 bit + 1byte
|
||||||
memcpy(kdata, file_get_data(fkey), key_size);
|
memcpy(kdata, file_get_data(fkey), key_size);
|
||||||
if (mkek_decrypt(kdata, key_size) != 0) {
|
if (mkek_decrypt(kdata, key_size) != 0) {
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
mbedtls_ecp_group_id gid = kdata[0];
|
mbedtls_ecp_group_id gid = kdata[0];
|
||||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1);
|
int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
mbedtls_ecp_keypair_free(ctx);
|
mbedtls_ecp_keypair_free(ctx);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
#ifdef MBEDTLS_EDDSA_C
|
r = mbedtls_ecp_keypair_calc_public(ctx, random_fill_iterator, NULL);
|
||||||
if (gid == MBEDTLS_ECP_DP_ED25519 || gid == MBEDTLS_ECP_DP_ED448) {
|
|
||||||
r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL);
|
|
||||||
}
|
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecp_keypair_free(ctx);
|
mbedtls_ecp_keypair_free(ctx);
|
||||||
return PICOKEY_EXEC_ERROR;
|
return PICOKEYS_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
return PICOKEY_OK;
|
return PICOKEYS_OK;
|
||||||
}
|
}
|
||||||
int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
||||||
return load_private_key_ec(ctx, fkey);
|
return load_private_key_ec(ctx, fkey);
|
||||||
@@ -767,7 +764,7 @@ static const cmd_t cmds[] = {
|
|||||||
int sc_hsm_process_apdu(void) {
|
int sc_hsm_process_apdu(void) {
|
||||||
uint32_t ne = apdu.ne;
|
uint32_t ne = apdu.ne;
|
||||||
int r = sm_unwrap();
|
int r = sm_unwrap();
|
||||||
if (r != PICOKEY_OK) {
|
if (r != PICOKEYS_OK) {
|
||||||
return SW_DATA_INVALID();
|
return SW_DATA_INVALID();
|
||||||
}
|
}
|
||||||
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "pico_keys.h"
|
#include "picokeys.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
#define MAX_APDU_DATA (USB_BUFFER_SIZE - 20)
|
#define MAX_APDU_DATA (USB_BUFFER_SIZE - 20)
|
||||||
|
|||||||
Reference in New Issue
Block a user