@@ -143,10 +143,7 @@ int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
|
||||
mbedtls_md_update(&md_ctx, input, input_len);
|
||||
|
||||
//TODO: be careful with architecture little vs. big
|
||||
counter_buf[0] = (uint8_t) ((counter >> 24) & 0xff);
|
||||
counter_buf[1] = (uint8_t) ((counter >> 16) & 0xff);
|
||||
counter_buf[2] = (uint8_t) ((counter >> 8) & 0xff);
|
||||
counter_buf[3] = (uint8_t) ((counter >> 0) & 0xff);
|
||||
put_uint32_t_be(counter, counter_buf);
|
||||
|
||||
mbedtls_md_update(&md_ctx, counter_buf, 4);
|
||||
|
||||
@@ -413,13 +410,7 @@ int cmd_cipher_sym() {
|
||||
size_t olen = 0;
|
||||
mbedtls_asn1_buf params =
|
||||
{.p = aad.data, .len = aad.len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)};
|
||||
int r = mbedtls_pkcs5_pbes2_ext(¶ms,
|
||||
algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT,
|
||||
kdata,
|
||||
key_size,
|
||||
enc.data,
|
||||
enc.len,
|
||||
res_APDU, 4096, &olen);
|
||||
int r = mbedtls_pkcs5_pbes2_ext(¶ms, algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT, kdata, key_size, enc.data, enc.len, res_APDU, MAX_APDU_DATA, &olen);
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
if (r != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
|
||||
@@ -30,7 +30,7 @@ int cmd_delete_file() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint16_t fid = (apdu.data[0] << 8) | apdu.data[1];
|
||||
uint16_t fid = get_uint16_t_be(apdu.data);
|
||||
if (!(ef = search_file(fid))) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "mbedtls/ecdh.h"
|
||||
#ifdef PICO_PLATFORM
|
||||
#include "pico/aon_timer.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -35,17 +36,20 @@
|
||||
#define CMD_DATETIME 0xA
|
||||
#define CMD_DYNOPS 0x6
|
||||
#define CMD_SECURE_LOCK 0x3A
|
||||
#define CMD_REBOOT 0xFB
|
||||
#define SECURE_LOCK_KEY_AGREEMENT 0x1
|
||||
#define SECURE_LOCK_ENABLE 0x2
|
||||
#define SECURE_LOCK_MASK 0x3
|
||||
#define SECURE_LOCK_DISABLE 0x4
|
||||
#define CMD_PHY 0x1B
|
||||
#define CMD_OTP 0x4C
|
||||
#define CMD_MEMORY 0x5
|
||||
|
||||
int cmd_extras() {
|
||||
int cmd = P1(apdu);
|
||||
#ifndef ENABLE_EMULATION
|
||||
// Only allow change PHY without PIN
|
||||
if (!isUserAuthenticated && P1(apdu) != 0x1B) {
|
||||
if (!isUserAuthenticated && cmd != CMD_PHY && cmd != CMD_MEMORY) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
#endif
|
||||
@@ -53,7 +57,7 @@ int cmd_extras() {
|
||||
if (wait_button_pressed() == true) {
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
}
|
||||
if (P1(apdu) == CMD_DATETIME) { //datetime operations
|
||||
if (cmd == CMD_DATETIME) { //datetime operations
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -66,8 +70,7 @@ int cmd_extras() {
|
||||
gettimeofday(&tv, NULL);
|
||||
#endif
|
||||
struct tm *tm = localtime(&tv.tv_sec);
|
||||
res_APDU[res_APDU_size++] = (tm->tm_year + 1900) >> 8;
|
||||
res_APDU[res_APDU_size++] = (tm->tm_year + 1900) & 0xff;
|
||||
res_APDU_size += put_uint16_t_be(tm->tm_year + 1900, res_APDU);
|
||||
res_APDU[res_APDU_size++] = tm->tm_mon;
|
||||
res_APDU[res_APDU_size++] = tm->tm_mday;
|
||||
res_APDU[res_APDU_size++] = tm->tm_wday;
|
||||
@@ -80,7 +83,7 @@ int cmd_extras() {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
struct tm tm;
|
||||
tm.tm_year = ((apdu.data[0] << 8) | (apdu.data[1])) - 1900;
|
||||
tm.tm_year = get_uint16_t_be(apdu.data) - 1900;
|
||||
tm.tm_mon = apdu.data[2];
|
||||
tm.tm_mday = apdu.data[3];
|
||||
tm.tm_wday = apdu.data[4];
|
||||
@@ -97,7 +100,7 @@ int cmd_extras() {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (P1(apdu) == CMD_DYNOPS) { //dynamic options
|
||||
else if (cmd == CMD_DYNOPS) { //dynamic options
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -106,8 +109,7 @@ int cmd_extras() {
|
||||
}
|
||||
uint16_t opts = get_device_options();
|
||||
if (apdu.nc == 0) {
|
||||
res_APDU[res_APDU_size++] = opts >> 8;
|
||||
res_APDU[res_APDU_size++] = opts & 0xff;
|
||||
res_APDU_size += put_uint16_t_be(opts, res_APDU);
|
||||
}
|
||||
else {
|
||||
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
|
||||
@@ -116,7 +118,7 @@ int cmd_extras() {
|
||||
low_flash_available();
|
||||
}
|
||||
}
|
||||
else if (P1(apdu) == CMD_SECURE_LOCK) { // secure lock
|
||||
else if (cmd == CMD_SECURE_LOCK) { // secure lock
|
||||
if (apdu.nc == 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@@ -148,7 +150,7 @@ int cmd_extras() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
ret = mbedtls_ecp_point_write_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, res_APDU, 4096);
|
||||
ret = mbedtls_ecp_point_write_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, res_APDU, MAX_APDU_DATA);
|
||||
mbedtls_ecdh_free(&hkey);
|
||||
if (ret != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
@@ -160,13 +162,12 @@ int cmd_extras() {
|
||||
if (mse.init == false) {
|
||||
return SW_COMMAND_NOT_ALLOWED();
|
||||
}
|
||||
|
||||
uint16_t opts = get_device_options();
|
||||
int ret = mse_decrypt_ct(apdu.data, apdu.nc);
|
||||
if (ret != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (P2(apdu) == SECURE_LOCK_ENABLE || P2(apdu) == SECURE_LOCK_DISABLE) { // Enable
|
||||
uint16_t opts = get_device_options();
|
||||
uint8_t newopts[] = { opts >> 8, (opts & 0xff) };
|
||||
if ((P2(apdu) == SECURE_LOCK_ENABLE && !(opts & HSM_OPT_SECURE_LOCK)) ||
|
||||
(P2(apdu) == SECURE_LOCK_DISABLE && (opts & HSM_OPT_SECURE_LOCK))) {
|
||||
@@ -194,14 +195,14 @@ int cmd_extras() {
|
||||
file_put_data(tf, newopts, sizeof(newopts));
|
||||
low_flash_available();
|
||||
}
|
||||
else if (P2(apdu) == SECURE_LOCK_MASK) {
|
||||
memcpy(mkek_mask, apdu.data, apdu.nc);
|
||||
else if (P2(apdu) == SECURE_LOCK_MASK && (opts & HSM_OPT_SECURE_LOCK)) {
|
||||
memcpy(mkek_mask, apdu.data, MKEK_KEY_SIZE);
|
||||
has_mkek_mask = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef ENABLE_EMULATION
|
||||
else if (P1(apdu) == CMD_PHY) { // Set PHY
|
||||
else if (cmd == CMD_PHY) { // Set PHY
|
||||
if (apdu.nc == 0) {
|
||||
if (file_has_data(ef_phy)) {
|
||||
res_APDU_size = file_get_size(ef_phy);
|
||||
@@ -213,8 +214,8 @@ int cmd_extras() {
|
||||
if (apdu.nc != 4) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
phy_data.vid = (apdu.data[0] << 8) | apdu.data[1];
|
||||
phy_data.pid = (apdu.data[2] << 8) | apdu.data[3];
|
||||
phy_data.vid = get_uint16_t_be(apdu.data);
|
||||
phy_data.pid = get_uint16_t_be(apdu.data + 2);
|
||||
phy_data.vidpid_present = true;
|
||||
}
|
||||
else if (P2(apdu) == PHY_LED_GPIO) {
|
||||
@@ -229,7 +230,7 @@ int cmd_extras() {
|
||||
if (apdu.nc != 2) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
phy_data.opts = (apdu.data[0] << 8) | apdu.data[1];
|
||||
phy_data.opts = get_uint16_t_be(apdu.data);
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -246,11 +247,11 @@ int cmd_extras() {
|
||||
}
|
||||
#endif
|
||||
#if PICO_RP2350
|
||||
else if (P1(apdu) == CMD_OTP) {
|
||||
else if (cmd == CMD_OTP) {
|
||||
if (apdu.nc < 2) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint16_t row = (apdu.data[0] << 8) | apdu.data[1];
|
||||
uint16_t row = get_uint16_t_be(apdu.data);
|
||||
bool israw = P2(apdu) == 0x1;
|
||||
if (apdu.nc == 2) {
|
||||
if (row > 0xbf && row < 0xf48) {
|
||||
@@ -288,6 +289,23 @@ int cmd_extras() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PICO_PLATFORM
|
||||
else if (cmd == CMD_REBOOT) {
|
||||
if (apdu.nc != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
watchdog_reboot(0, 0, 100);
|
||||
}
|
||||
#endif
|
||||
else if (cmd == CMD_MEMORY) {
|
||||
res_APDU_size = 0;
|
||||
uint32_t free = flash_free_space(), total = flash_total_space(), used = flash_used_space(), nfiles = flash_num_files(), size = flash_size();
|
||||
res_APDU_size += put_uint32_t_be(free, res_APDU + res_APDU_size);
|
||||
res_APDU_size += put_uint32_t_be(used, res_APDU + res_APDU_size);
|
||||
res_APDU_size += put_uint32_t_be(total, res_APDU + res_APDU_size);
|
||||
res_APDU_size += put_uint32_t_be(nfiles, res_APDU + res_APDU_size);
|
||||
res_APDU_size += put_uint32_t_be(size, res_APDU + res_APDU_size);
|
||||
}
|
||||
else {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
|
||||
@@ -43,10 +43,14 @@ extern void reset_puk_store();
|
||||
int cmd_initialize() {
|
||||
if (apdu.nc > 0) {
|
||||
uint8_t mkek[MKEK_SIZE];
|
||||
uint16_t opts = get_device_options();
|
||||
if (opts & HSM_OPT_SECURE_LOCK && !has_mkek_mask) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
|
||||
initialize_flash(true);
|
||||
scan_all();
|
||||
has_session_pin = has_session_sopin = false;
|
||||
has_session_pin = has_session_sopin = has_mkek_mask = false;
|
||||
uint16_t tag = 0x0;
|
||||
uint8_t *tag_data = NULL, *p = NULL, *kds = NULL, *dkeks = NULL;
|
||||
uint16_t tag_len = 0;
|
||||
@@ -206,7 +210,7 @@ int cmd_initialize() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint16_t ee_len = 0, term_len = 0;
|
||||
if ((ee_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
if ((ee_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@@ -218,7 +222,7 @@ int cmd_initialize() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
if ((term_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU + ee_len, 4096 - ee_len, NULL, 0, true)) == 0) {
|
||||
if ((term_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU + ee_len, MAX_APDU_DATA - ee_len, NULL, 0, true)) == 0) {
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@@ -231,7 +235,7 @@ int cmd_initialize() {
|
||||
|
||||
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";
|
||||
uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, 4096);
|
||||
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);
|
||||
ret = file_put_data(fpk, res_APDU, prkd_len);
|
||||
}
|
||||
@@ -243,10 +247,7 @@ int cmd_initialize() {
|
||||
}
|
||||
else { //free memory bytes request
|
||||
int heap_left = heapLeft();
|
||||
res_APDU[0] = ((heap_left >> 24) & 0xff);
|
||||
res_APDU[1] = ((heap_left >> 16) & 0xff);
|
||||
res_APDU[2] = ((heap_left >> 8) & 0xff);
|
||||
res_APDU[3] = ((heap_left >> 0) & 0xff);
|
||||
res_APDU_size += put_uint32_t_be(heap_left, res_APDU);
|
||||
res_APDU[4] = 0;
|
||||
res_APDU[5] = HSM_VERSION_MAJOR;
|
||||
res_APDU[6] = HSM_VERSION_MINOR;
|
||||
|
||||
@@ -57,7 +57,7 @@ int cmd_key_unwrap() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&ctx, PICO_KEYS_KEY_RSA, key_id);
|
||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
@@ -77,7 +77,7 @@ int cmd_key_unwrap() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&ctx, PICO_KEYS_KEY_EC, key_id);
|
||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
@@ -58,8 +58,7 @@ int cmd_keypair_gen() {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if ((res_APDU_size =
|
||||
(uint16_t)asn1_cvc_aut(&rsa, PICO_KEYS_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&rsa, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id);
|
||||
@@ -131,8 +130,7 @@ int cmd_keypair_gen() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((res_APDU_size =
|
||||
(uint16_t)asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, ext.data, ext.len)) == 0) {
|
||||
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 (ext.data) {
|
||||
free(ext.data);
|
||||
}
|
||||
|
||||
@@ -22,12 +22,10 @@ int cmd_list_keys() {
|
||||
/* First we send DEV private key */
|
||||
/* Both below conditions should be always TRUE */
|
||||
if (search_file(EF_PRKD_DEV)) {
|
||||
res_APDU[res_APDU_size++] = EF_PRKD_DEV >> 8;
|
||||
res_APDU[res_APDU_size++] = EF_PRKD_DEV & 0xff;
|
||||
res_APDU_size += put_uint16_t_be(EF_PRKD_DEV, res_APDU + res_APDU_size);
|
||||
}
|
||||
if (search_file(EF_KEY_DEV)) {
|
||||
res_APDU[res_APDU_size++] = EF_KEY_DEV >> 8;
|
||||
res_APDU[res_APDU_size++] = EF_KEY_DEV & 0xff;
|
||||
res_APDU_size += put_uint16_t_be(EF_KEY_DEV, res_APDU + res_APDU_size);
|
||||
}
|
||||
//first CC
|
||||
for (int i = 0; i < dynamic_files; i++) {
|
||||
|
||||
@@ -30,7 +30,7 @@ int cmd_read_binary() {
|
||||
offset = p2;
|
||||
}
|
||||
else {
|
||||
offset = make_uint16_t(p1, p2) & 0x7fff;
|
||||
offset = make_uint16_t_be(p1, p2) & 0x7fff;
|
||||
ef = currentEF;
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ int cmd_read_binary() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint16_t file_id = make_uint16_t(p1, p2); // & 0x7fff;
|
||||
uint16_t file_id = make_uint16_t_be(p1, p2); // & 0x7fff;
|
||||
if (file_id == 0x0) {
|
||||
ef = currentEF;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ int cmd_select() {
|
||||
//}
|
||||
|
||||
if (apdu.nc == 2) {
|
||||
fid = get_uint16_t(apdu.data, 0);
|
||||
fid = get_uint16_t_be(apdu.data);
|
||||
}
|
||||
|
||||
//if ((fid & 0xff00) == (KEY_PREFIX << 8))
|
||||
@@ -119,8 +119,7 @@ int cmd_select() {
|
||||
res_APDU[res_APDU_size++] = 0x85;
|
||||
res_APDU[res_APDU_size++] = 5;
|
||||
uint16_t opts = get_device_options();
|
||||
res_APDU[res_APDU_size++] = opts >> 8;
|
||||
res_APDU[res_APDU_size++] = opts & 0xff;
|
||||
res_APDU_size += put_uint16_t_be(opts, res_APDU + res_APDU_size);
|
||||
res_APDU[res_APDU_size++] = 0xFF;
|
||||
res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;
|
||||
|
||||
@@ -431,8 +431,7 @@ uint16_t asn1_build_cert_description(const uint8_t *label,
|
||||
p += format_tlv_len(asn1_len_tag(0x4, sizeof(uint16_t)), p);
|
||||
*p++ = 0x4;
|
||||
p += format_tlv_len(sizeof(uint16_t), p);
|
||||
*p++ = fid >> 8;
|
||||
*p++ = fid & 0xff;
|
||||
put_uint16_t_be(fid, p); p += sizeof(uint16_t);
|
||||
return (uint16_t)(p - buf);
|
||||
}
|
||||
|
||||
@@ -508,8 +507,7 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
p += format_tlv_len(asn1_len_tag(0x2, 2), p);
|
||||
*p++ = 0x2;
|
||||
p += format_tlv_len(2, p);
|
||||
*p++ = (keysize >> 8) & 0xff;
|
||||
*p++ = keysize & 0xff;
|
||||
p += put_uint16_t_be(keysize, p);
|
||||
}
|
||||
|
||||
//Seq 4
|
||||
@@ -528,8 +526,7 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
|
||||
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) {
|
||||
*p++ = 0x2;
|
||||
p += format_tlv_len(2, p);
|
||||
*p++ = (keysize >> 8) & 0xff;
|
||||
*p++ = keysize & 0xff;
|
||||
p += put_uint16_t_be(keysize, p);
|
||||
}
|
||||
return (uint16_t)(p - buf);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ file_t file_entries[] = {
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //retries PIN (SOPIN)
|
||||
/* 15 */ { .fid = EF_DEVOPS, .parent = 5, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Device options
|
||||
/* 16 */ { .fid = EF_PRKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
|
||||
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.PrKDFs
|
||||
|
||||
@@ -50,6 +50,14 @@ uint32_t crc32c(const uint8_t *buf, size_t len) {
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
void mkek_masked(uint8_t *mkek, const uint8_t *mask) {
|
||||
if (mask) {
|
||||
for (int i = 0; i < MKEK_KEY_SIZE; i++) {
|
||||
MKEK_KEY(mkek)[i] ^= mask[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int load_mkek(uint8_t *mkek) {
|
||||
if (has_session_pin == false && has_session_sopin == false) {
|
||||
return PICOKEY_NO_LOGIN;
|
||||
@@ -73,6 +81,10 @@ int load_mkek(uint8_t *mkek) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
|
||||
if (has_mkek_mask) {
|
||||
mkek_masked(mkek, mkek_mask);
|
||||
}
|
||||
|
||||
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
||||
if (ret != 0) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
@@ -80,11 +92,8 @@ int load_mkek(uint8_t *mkek) {
|
||||
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *) MKEK_CHECKSUM(mkek)) {
|
||||
return PICOKEY_WRONG_DKEK;
|
||||
}
|
||||
if (has_mkek_mask || otp_key_1) {
|
||||
const uint8_t *mask = otp_key_1 ? otp_key_1 : mkek_mask;
|
||||
for (int i = 0; i < MKEK_KEY_SIZE; i++) {
|
||||
MKEK_KEY(mkek)[i] ^= mask[i];
|
||||
}
|
||||
if (otp_key_1) {
|
||||
mkek_masked(mkek, otp_key_1);
|
||||
}
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
@@ -125,6 +134,9 @@ int store_mkek(const uint8_t *mkek) {
|
||||
else {
|
||||
memcpy(tmp_mkek, mkek, MKEK_SIZE);
|
||||
}
|
||||
if (otp_key_1) {
|
||||
mkek_masked(tmp_mkek, otp_key_1);
|
||||
}
|
||||
*(uint32_t *) MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE);
|
||||
if (has_session_pin) {
|
||||
uint8_t tmp_mkek_pin[MKEK_SIZE];
|
||||
@@ -319,7 +331,7 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
||||
return PICOKEY_WRONG_LENGTH;
|
||||
}
|
||||
|
||||
put_uint16_t(kb_len, kb + 8);
|
||||
put_uint16_t_be(kb_len, kb + 8);
|
||||
memcpy(kb + 10, key_ctx, kb_len);
|
||||
kb_len += 2;
|
||||
|
||||
@@ -332,15 +344,15 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
||||
}
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||
kb_len = 0;
|
||||
put_uint16_t((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_be((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len);
|
||||
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&rsa->D), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->D);
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&rsa->N), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->N);
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&rsa->E), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->E);
|
||||
|
||||
@@ -353,32 +365,32 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
||||
}
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
||||
kb_len = 0;
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P) * 8, kb + 8 + kb_len); kb_len += 2;
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->grp.A), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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);
|
||||
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);
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->grp.B), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.B);
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.P);
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->grp.N), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N);
|
||||
|
||||
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);
|
||||
put_uint16_t((uint16_t)olen, kb + 8 + kb_len);
|
||||
kb_len += 2 + (uint16_t)olen;
|
||||
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len);
|
||||
kb_len += (uint16_t)olen;
|
||||
|
||||
put_uint16_t((uint16_t)mbedtls_mpi_size(&ecdsa->d), kb + 8 + kb_len); kb_len += 2;
|
||||
kb_len += put_uint16_t_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));
|
||||
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);
|
||||
put_uint16_t((uint16_t)olen, kb + 8 + kb_len);
|
||||
kb_len += 2 + (uint16_t)olen;
|
||||
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len);
|
||||
kb_len += (uint16_t)olen;
|
||||
|
||||
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
|
||||
algo_len = 12;
|
||||
@@ -409,7 +421,7 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
|
||||
}
|
||||
|
||||
if (allowed && allowed_len > 0) {
|
||||
put_uint16_t(allowed_len, out + *out_len); *out_len += 2;
|
||||
*out_len += put_uint16_t_be(allowed_len, out + *out_len);
|
||||
memcpy(out + *out_len, allowed, allowed_len);
|
||||
*out_len += allowed_len;
|
||||
}
|
||||
@@ -517,21 +529,21 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
uint16_t ofs = 9;
|
||||
|
||||
//OID
|
||||
uint16_t len = get_uint16_t(in, ofs);
|
||||
uint16_t len = get_uint16_t_be(in + ofs);
|
||||
ofs += len + 2;
|
||||
|
||||
//Allowed algorithms
|
||||
len = get_uint16_t(in, ofs);
|
||||
len = get_uint16_t_be(in + ofs);
|
||||
*allowed = (uint8_t *) (in + ofs + 2);
|
||||
*allowed_len = len;
|
||||
ofs += len + 2;
|
||||
|
||||
//Access conditions
|
||||
len = get_uint16_t(in, ofs);
|
||||
len = get_uint16_t_be(in + ofs);
|
||||
ofs += len + 2;
|
||||
|
||||
//Key OID
|
||||
len = get_uint16_t(in, ofs);
|
||||
len = get_uint16_t_be(in + ofs);
|
||||
ofs += len + 2;
|
||||
|
||||
if ((in_len - 16 - ofs) % 16 != 0) {
|
||||
@@ -545,7 +557,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
return r;
|
||||
}
|
||||
|
||||
int key_size = get_uint16_t(kb, 8);
|
||||
int key_size = get_uint16_t_be(kb + 8);
|
||||
if (key_size_out) {
|
||||
*key_size_out = key_size;
|
||||
}
|
||||
@@ -554,14 +566,14 @@ 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_init(rsa);
|
||||
if (key_type == 5) {
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return PICOKEY_WRONG_DATA;
|
||||
}
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
@@ -570,12 +582,12 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
}
|
||||
else if (key_type == 6) {
|
||||
//DP-1
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
//DQ-1
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
@@ -583,19 +595,19 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
}
|
||||
|
||||
//PQ
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
return PICOKEY_WRONG_DATA;
|
||||
}
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
}
|
||||
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len;
|
||||
if (r != 0) {
|
||||
mbedtls_rsa_free(rsa);
|
||||
@@ -633,13 +645,13 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
mbedtls_ecdsa_init(ecdsa);
|
||||
|
||||
//A
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
//B
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
//P
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len);
|
||||
if (ec_id == MBEDTLS_ECP_DP_NONE) {
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
@@ -648,10 +660,10 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
ofs += len;
|
||||
|
||||
//N
|
||||
len = get_uint16_t(kb, ofs); ofs += len + 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += len + 2;
|
||||
|
||||
//G
|
||||
len = get_uint16_t(kb, ofs);
|
||||
len = get_uint16_t_be(kb + ofs);
|
||||
if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) {
|
||||
ec_id = MBEDTLS_ECP_DP_ED25519;
|
||||
}
|
||||
@@ -661,7 +673,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
ofs += len + 2;
|
||||
|
||||
//d
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len);
|
||||
if (r != 0) {
|
||||
mbedtls_ecdsa_free(ecdsa);
|
||||
@@ -670,7 +682,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
|
||||
ofs += len;
|
||||
|
||||
//Q
|
||||
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||
len = get_uint16_t_be(kb + ofs); ofs += 2;
|
||||
r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len);
|
||||
if (r != 0) {
|
||||
if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS) {
|
||||
|
||||
@@ -269,7 +269,7 @@ int sc_hsm_unload() {
|
||||
uint16_t get_device_options() {
|
||||
file_t *ef = search_file(EF_DEVOPS);
|
||||
if (file_has_data(ef)) {
|
||||
return (file_read_uint8(ef) << 8) | file_read_uint8_offset(ef, 1);
|
||||
return get_uint16_t_be(file_get_data(ef));
|
||||
}
|
||||
return 0x0;
|
||||
}
|
||||
@@ -462,7 +462,7 @@ uint32_t get_key_counter(file_t *fkey) {
|
||||
uint16_t tag_len = 0;
|
||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
|
||||
if (meta_tag) {
|
||||
return (meta_tag[0] << 24) | (meta_tag[1] << 16) | (meta_tag[2] << 8) | meta_tag[3];
|
||||
return get_uint32_t_be(meta_tag);
|
||||
}
|
||||
return 0xffffffff;
|
||||
}
|
||||
@@ -498,14 +498,9 @@ uint32_t decrement_key_counter(file_t *fkey) {
|
||||
asn1_ctx_init(meta_data, meta_size, &ctxi);
|
||||
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
||||
if (tag == 0x90) { // ofset tag
|
||||
uint32_t val =
|
||||
(tag_data[0] << 24) | (tag_data[1] << 16) | (tag_data[2] << 8) | tag_data[3];
|
||||
uint32_t val = get_uint32_t_be(tag_data);
|
||||
val--;
|
||||
tag_data[0] = (val >> 24) & 0xff;
|
||||
tag_data[1] = (val >> 16) & 0xff;
|
||||
tag_data[2] = (val >> 8) & 0xff;
|
||||
tag_data[3] = val & 0xff;
|
||||
|
||||
put_uint32_t_be(val, tag_data);
|
||||
int r = meta_add(fkey->fid, cmeta, (uint16_t)meta_size);
|
||||
free(cmeta);
|
||||
if (r != 0) {
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#include "file.h"
|
||||
#include "apdu.h"
|
||||
#include "pico_keys.h"
|
||||
#include "usb.h"
|
||||
|
||||
#define MAX_APDU_DATA (USB_BUFFER_SIZE - 20)
|
||||
|
||||
extern const uint8_t sc_hsm_aid[];
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifndef __VERSION_H_
|
||||
#define __VERSION_H_
|
||||
|
||||
#define HSM_VERSION 0x0500
|
||||
#define HSM_VERSION 0x0502
|
||||
|
||||
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
||||
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
||||
|
||||
Reference in New Issue
Block a user