Merge branch 'development' into development-eddsa

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2023-11-06 23:11:08 +01:00
44 changed files with 821 additions and 160 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
# These are supported funding model platforms
github: polhenarejos
custom: ["https://www.paypal.me/polhenarejos"]

View File

@@ -23,9 +23,7 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository and submodules - name: Checkout repository and submodules
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -33,5 +31,36 @@ jobs:
submodules: recursive submodules: recursive
- name: Build in container - name: Build in container
run: ./tests/build-in-docker.sh run: ./tests/build-in-docker.sh
- name: Start emulation and test - name: Export image
run: ./tests/run-test-in-docker.sh run: |
mkdir -p artifacts
docker save pico-hsm-test:bullseye -o artifacts/docker-image.tar
- name: Temporarily save image
uses: actions/upload-artifact@v3
with:
name: docker-artifact
path: artifacts
retention-days: 1
test:
runs-on: ubuntu-latest
needs: build
strategy:
matrix:
suite: ["pkcs11", "pytest", "sc-hsm-pkcs11"]
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v3
with:
submodules: recursive
- name: Retrieve saved image
uses: actions/download-artifact@v3
with:
name: docker-artifact
path: artifacts
- name: Load image
run: |
cd artifacts
docker load -q -i docker-image.tar
- name: Test ${{ matrix.suite }}
run: ./tests/run-test-in-docker.sh ${{ matrix.suite }}

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "pico-hsm-sdk"] [submodule "pico-keys-sdk"]
path = pico-hsm-sdk path = pico-keys-sdk
url = ../pico-hsm-sdk url = https://github.com/polhenarejos/pico-keys-sdk

View File

@@ -32,6 +32,13 @@ else()
pico_sdk_init() pico_sdk_init()
endif() endif()
if (NOT DEFINED __FOR_CI)
set(__FOR_CI 0)
endif()
if (__FOR_CI)
add_definitions(-D__FOR_CI)
endif()
add_executable(pico_hsm) add_executable(pico_hsm)
set(SOURCES ${SOURCES} set(SOURCES ${SOURCES}
@@ -70,7 +77,7 @@ set(SOURCES ${SOURCES}
) )
set(USB_ITF_CCID 1) set(USB_ITF_CCID 1)
include(pico-hsm-sdk/pico_hsm_sdk_import.cmake) include(pico-keys-sdk/pico_keys_sdk_import.cmake)
set(INCLUDES ${INCLUDES} set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/hsm ${CMAKE_CURRENT_LIST_DIR}/src/hsm
@@ -102,5 +109,5 @@ endif (APPLE)
else() else()
pico_add_extra_outputs(pico_hsm) pico_add_extra_outputs(pico_hsm)
target_link_libraries(pico_hsm PRIVATE pico_hsm_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board) target_link_libraries(pico_hsm PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board)
endif() endif()

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
VERSION_MAJOR="3" VERSION_MAJOR="3"
VERSION_MINOR="2" VERSION_MINOR="6"
rm -rf release/* rm -rf release/*
cd build_release cd build_release
@@ -17,6 +17,7 @@ for board in adafruit_feather_rp2040 \
eetree_gamekit_rp2040 \ eetree_gamekit_rp2040 \
garatronic_pybstick26_rp2040 \ garatronic_pybstick26_rp2040 \
melopero_shake_rp2040 \ melopero_shake_rp2040 \
nullbits_bit_c_pro \
pico \ pico \
pico_w \ pico_w \
pimoroni_badger2040 \ pimoroni_badger2040 \
@@ -31,6 +32,7 @@ for board in adafruit_feather_rp2040 \
pimoroni_servo2040 \ pimoroni_servo2040 \
pimoroni_tiny2040 \ pimoroni_tiny2040 \
pimoroni_tiny2040_2mb \ pimoroni_tiny2040_2mb \
pololu_3pi_2040_robot \
seeed_xiao_rp2040 \ seeed_xiao_rp2040 \
solderparty_rp2040_stamp \ solderparty_rp2040_stamp \
solderparty_rp2040_stamp_carrier \ solderparty_rp2040_stamp_carrier \

View File

@@ -30,7 +30,7 @@ PIN=648219
## Initialization ## Initialization
The first step is to initialize the HSM. To do so, use the `pico-hsm-tool.py` in `tools` folder: The first step is to initialize the HSM. To do so, use the `pico-hsm-tool.py` in `tools` folder:
``` ```
$ python3 pico-hsm-tool.py initialize --so-pin 3537363231383830 --pin 648219 $ python3 tools/pico-hsm-tool.py --pin 648219 initialize --so-pin 57621880
``` ```
The PIN number is used to manage all private keys in the device. It supports three attemps. After the third PIN failure, it gets blocked. The PIN number is used to manage all private keys in the device. It supports three attemps. After the third PIN failure, it gets blocked.
The PIN accepts from 6 to 16 characters. The PIN accepts from 6 to 16 characters.
@@ -51,7 +51,7 @@ $ pkcs11-tool --login --pin 648219 --change-pin --new-pin 123456
To unblock the PIN: To unblock the PIN:
``` ```
$ pkcs11-tool --login --login-type so --so-pin=3537363231383830 --init-pin --new-pin=648219 $ pkcs11-tool --login --login-type so --so-pin 3537363231383830 --init-pin --new-pin 648219
``` ```
## Keypair generation ## Keypair generation

1
pico-keys-sdk Submodule

Submodule pico-keys-sdk added at f0687c1ef3

View File

@@ -412,20 +412,21 @@ int cmd_cipher_sym() {
res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32); res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32);
} }
else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) { else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
size_t olen = 0;
mbedtls_asn1_buf params = mbedtls_asn1_buf params =
{.p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)}; {.p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)};
int r = mbedtls_pkcs5_pbes2(&params, int r = mbedtls_pkcs5_pbes2_ext(&params,
algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT, algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT,
kdata, kdata,
key_size, key_size,
enc, enc,
enc_len, enc_len,
res_APDU); res_APDU, 4096, &olen);
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();
} }
res_APDU_size = enc_len; res_APDU_size = olen;
} }
else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) { else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;

View File

@@ -88,7 +88,7 @@ int cmd_derive_asym() {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, HSM_KEY_EC, dest_id); r = store_keys(&ctx, PICO_KEYS_KEY_EC, dest_id);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();

View File

@@ -187,13 +187,13 @@ int cmd_initialize() {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = store_keys(&ecdsa, HSM_KEY_EC, key_id); ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id);
if (ret != CCID_OK) { if (ret != CCID_OK) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
size_t cvc_len = 0; size_t cvc_len = 0;
if ((cvc_len = asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) { if ((cvc_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -205,7 +205,7 @@ int cmd_initialize() {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if ((cvc_len = asn1_cvc_cert(&ecdsa, HSM_KEY_EC, res_APDU, 4096, NULL, 0, true)) == 0) { if ((cvc_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0, true)) == 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }

View File

@@ -23,11 +23,14 @@
uint8_t get_key_domain(file_t *fkey) { uint8_t get_key_domain(file_t *fkey) {
size_t tag_len = 0; size_t tag_len = 0;
if (!file_has_data(fkey)) {
return 0xff;
}
const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len); const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len);
if (meta_tag) { if (meta_tag) {
return *meta_tag; return *meta_tag;
} }
return 0xff; return 0x0;
} }
int cmd_key_domain() { int cmd_key_domain() {
@@ -65,12 +68,18 @@ int cmd_key_domain() {
} }
import_dkek_share(p2, apdu.data); import_dkek_share(p2, apdu.data);
if (++current_dkeks >= dkeks) { if (++current_dkeks >= dkeks) {
if (save_dkek_key(p2, NULL) != CCID_OK) { int r = save_dkek_key(p2, NULL);
if (r != CCID_OK) {
if (r == CCID_NO_LOGIN) {
pending_save_dkek = p2;
}
else {
/* On fail, it will return to previous dkek state. */ /* On fail, it will return to previous dkek state. */
import_dkek_share(p2, apdu.data); import_dkek_share(p2, apdu.data);
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
}
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;
@@ -94,8 +103,9 @@ int cmd_key_domain() {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
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 (int i = 0; i < dynamic_files; i++) { for (int i = 1; i < 256; i++) {
if (get_key_domain(&dynamic_file[i]) == p2) { file_t *fkey = search_dynamic_file(KEY_PREFIX << 8 | i);
if (get_key_domain(fkey) == p2) {
return SW_FILE_EXISTS(); return SW_FILE_EXISTS();
} }
} }

View File

@@ -44,16 +44,16 @@ int cmd_key_gen() {
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 = HSM_KEY_AES_128; aes_type = PICO_KEYS_KEY_AES_128;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = HSM_KEY_AES_192; aes_type = PICO_KEYS_KEY_AES_192;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = PICO_KEYS_KEY_AES_256;
} }
else if (key_size == 64) { else if (key_size == 64) {
aes_type = HSM_KEY_AES_512; aes_type = PICO_KEYS_KEY_AES_512;
} }
r = store_keys(aes_key, aes_type, key_id); r = store_keys(aes_key, aes_type, key_id);
if (r != CCID_OK) { if (r != CCID_OK) {

View File

@@ -35,7 +35,7 @@ int cmd_key_unwrap() {
if (key_type == 0x0) { if (key_type == 0x0) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
if (key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_KEY_RSA) {
mbedtls_rsa_context ctx; mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx); mbedtls_rsa_init(&ctx);
do { do {
@@ -45,8 +45,8 @@ int cmd_key_unwrap() {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, HSM_KEY_RSA, key_id); r = store_keys(&ctx, PICO_KEYS_KEY_RSA, key_id);
if ((res_APDU_size = asn1_cvc_aut(&ctx, HSM_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) { if ((res_APDU_size = asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -57,7 +57,7 @@ int cmd_key_unwrap() {
} }
prkd_len = asn1_build_prkd_ecc(NULL, 0, NULL, 0, key_size * 8, prkd_buf, sizeof(prkd_buf)); prkd_len = asn1_build_prkd_ecc(NULL, 0, NULL, 0, key_size * 8, prkd_buf, sizeof(prkd_buf));
} }
else if (key_type & HSM_KEY_EC) { else if (key_type & PICO_KEYS_KEY_EC) {
mbedtls_ecp_keypair ctx; mbedtls_ecp_keypair ctx;
mbedtls_ecp_keypair_init(&ctx); mbedtls_ecp_keypair_init(&ctx);
do { do {
@@ -67,7 +67,7 @@ int cmd_key_unwrap() {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, HSM_KEY_EC, key_id); r = store_keys(&ctx, PICO_KEYS_KEY_EC, key_id);
if ((res_APDU_size = asn1_cvc_aut(&ctx, HSM_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) { if ((res_APDU_size = asn1_cvc_aut(&ctx, HSM_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -79,7 +79,7 @@ int cmd_key_unwrap() {
} }
prkd_len = asn1_build_prkd_ecc(NULL, 0, NULL, 0, key_size, prkd_buf, sizeof(prkd_buf)); prkd_len = asn1_build_prkd_ecc(NULL, 0, NULL, 0, key_size, prkd_buf, sizeof(prkd_buf));
} }
else if (key_type & HSM_KEY_AES) { else if (key_type & PICO_KEYS_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 {
@@ -95,16 +95,16 @@ int cmd_key_unwrap() {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 64) { if (key_size == 64) {
aes_type = HSM_KEY_AES_512; aes_type = PICO_KEYS_KEY_AES_512;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = PICO_KEYS_KEY_AES_256;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = HSM_KEY_AES_192; aes_type = PICO_KEYS_KEY_AES_192;
} }
else if (key_size == 16) { else if (key_size == 16) {
aes_type = HSM_KEY_AES_128; aes_type = PICO_KEYS_KEY_AES_128;
} }
else { else {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();

View File

@@ -67,7 +67,7 @@ int cmd_key_wrap() {
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, &ctx, PICO_KEYS_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) {
@@ -81,7 +81,7 @@ int cmd_key_wrap() {
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, &ctx, PICO_KEYS_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) {
@@ -90,22 +90,22 @@ int cmd_key_wrap() {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
int key_size = file_get_size(ef), aes_type = HSM_KEY_AES; int key_size = file_get_size(ef), aes_type = PICO_KEYS_KEY_AES;
memcpy(kdata, file_get_data(ef), key_size); memcpy(kdata, file_get_data(ef), key_size);
if (mkek_decrypt(kdata, key_size) != 0) { if (mkek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 64) { if (key_size == 64) {
aes_type = HSM_KEY_AES_512; aes_type = PICO_KEYS_KEY_AES_512;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = PICO_KEYS_KEY_AES_256;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = HSM_KEY_AES_192; aes_type = PICO_KEYS_KEY_AES_192;
} }
else if (key_size == 16) { else if (key_size == 16) {
aes_type = HSM_KEY_AES_128; aes_type = PICO_KEYS_KEY_AES_128;
} }
r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));

View File

@@ -69,10 +69,10 @@ int cmd_keypair_gen() {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if ((res_APDU_size = if ((res_APDU_size =
asn1_cvc_aut(&rsa, HSM_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) { asn1_cvc_aut(&rsa, PICO_KEYS_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = store_keys(&rsa, HSM_KEY_RSA, key_id); ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id);
if (ret != CCID_OK) { if (ret != CCID_OK) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -146,7 +146,7 @@ int cmd_keypair_gen() {
} }
} }
if ((res_APDU_size = if ((res_APDU_size =
asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, ext, ext_len)) == 0) { asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, ext, ext_len)) == 0) {
if (ext) { if (ext) {
free(ext); free(ext);
} }
@@ -156,7 +156,7 @@ int cmd_keypair_gen() {
if (ext) { if (ext) {
free(ext); free(ext);
} }
ret = store_keys(&ecdsa, HSM_KEY_EC, key_id); ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
if (ret != CCID_OK) { if (ret != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();

View File

@@ -88,10 +88,10 @@ int cmd_read_binary() {
return SW_WARNING_EOF(); return SW_WARNING_EOF();
} }
uint16_t maxle = data_len - offset; //uint16_t maxle = data_len - offset;
if (apdu.ne > maxle) { //if (apdu.ne > maxle) {
apdu.ne = maxle; // apdu.ne = maxle;
} //}
memcpy(res_APDU, file_get_data(ef) + offset, data_len - offset); memcpy(res_APDU, file_get_data(ef) + offset, data_len - offset);
res_APDU_size = data_len - offset; res_APDU_size = data_len - offset;
} }

View File

@@ -36,16 +36,15 @@ int cmd_reset_retry() {
if (P1(apdu) == 0x0 || P1(apdu) == 0x2) { if (P1(apdu) == 0x0 || P1(apdu) == 0x2) {
int newpin_len = 0; int newpin_len = 0;
if (P1(apdu) == 0x0) { if (P1(apdu) == 0x0) {
if (apdu.nc <= 8) { uint8_t so_pin_len = file_read_uint8(file_get_data(file_sopin));
if (apdu.nc <= so_pin_len + 1) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
uint16_t r = check_pin(file_sopin, apdu.data, 8); uint16_t r = check_pin(file_sopin, apdu.data, so_pin_len);
if (r != 0x9000) { if (r != 0x9000) {
return r; return r;
} }
newpin_len = apdu.nc - 8; newpin_len = apdu.nc - so_pin_len;
has_session_sopin = true;
hash_multi(apdu.data, 8, session_sopin);
} }
else if (P1(apdu) == 0x2) { else if (P1(apdu) == 0x2) {
if (!has_session_sopin) { if (!has_session_sopin) {
@@ -83,15 +82,14 @@ int cmd_reset_retry() {
return SW_COMMAND_NOT_ALLOWED(); return SW_COMMAND_NOT_ALLOWED();
} }
if (P1(apdu) == 0x1) { if (P1(apdu) == 0x1) {
if (apdu.nc != 8) { uint8_t so_pin_len = file_read_uint8(file_get_data(file_sopin));
if (apdu.nc != so_pin_len) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
uint16_t r = check_pin(file_sopin, apdu.data, 8); uint16_t r = check_pin(file_sopin, apdu.data, so_pin_len);
if (r != 0x9000) { if (r != 0x9000) {
return r; return r;
} }
has_session_sopin = true;
hash_multi(apdu.data, 8, session_sopin);
} }
else if (P1(apdu) == 0x3) { else if (P1(apdu) == 0x3) {
if (!has_session_sopin) { if (!has_session_sopin) {

View File

@@ -166,10 +166,10 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
size_t ext_len, size_t ext_len,
bool full) { bool full) {
size_t pubkey_size = 0; size_t pubkey_size = 0;
if (key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_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 & HSM_KEY_EC) { else if (key_type & PICO_KEYS_KEY_EC) {
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
} }
size_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0; size_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0;
@@ -222,10 +222,10 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
//car //car
*p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar; *p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar;
//pubkey //pubkey
if (key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_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 & HSM_KEY_EC) { else if (key_type & PICO_KEYS_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
@@ -266,10 +266,10 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
size_t ext_len, size_t ext_len,
bool full) { bool full) {
size_t key_size = 0; size_t key_size = 0;
if (key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_KEY_RSA) {
key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N); key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
} }
else if (key_type & HSM_KEY_EC) { else if (key_type & PICO_KEYS_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);
} }
size_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); size_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);
@@ -289,13 +289,13 @@ size_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 & HSM_KEY_RSA) { if (key_type & PICO_KEYS_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_gen, 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 & HSM_KEY_EC) { else if (key_type & PICO_KEYS_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;
@@ -450,17 +450,17 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
size_t seq_len = 0; size_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 & HSM_KEY_EC) { if (key_type & PICO_KEYS_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 & HSM_KEY_RSA) { else if (key_type & PICO_KEYS_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 & HSM_KEY_AES) { else if (key_type & PICO_KEYS_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;
@@ -469,10 +469,10 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
size_t seq2_size = size_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));
size_t seq3_size = 0, seq4_size = 0; size_t seq3_size = 0, seq4_size = 0;
if (key_type & HSM_KEY_EC || key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_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 & HSM_KEY_AES) { else if (key_type & PICO_KEYS_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))));
} }
@@ -504,7 +504,7 @@ size_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 & HSM_KEY_AES) { if (key_type & PICO_KEYS_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;
@@ -518,7 +518,7 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
//Seq 4 //Seq 4
*p++ = 0xA1; *p++ = 0xA1;
size_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0)); size_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0));
if (key_type & HSM_KEY_EC || key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_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);
@@ -528,7 +528,7 @@ size_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 & HSM_KEY_EC || key_type & HSM_KEY_RSA) { if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) {
*p++ = 0x2; *p++ = 0x2;
p += format_tlv_len(2, p); p += format_tlv_len(2, p);
*p++ = (keysize >> 8) & 0xff; *p++ = (keysize >> 8) & 0xff;
@@ -549,7 +549,7 @@ size_t asn1_build_prkd_ecc(const uint8_t *label,
keyid, keyid,
keyid_len, keyid_len,
keysize, keysize,
HSM_KEY_EC, PICO_KEYS_KEY_EC,
buf, buf,
buf_len); buf_len);
} }
@@ -566,7 +566,7 @@ size_t asn1_build_prkd_rsa(const uint8_t *label,
keyid, keyid,
keyid_len, keyid_len,
keysize, keysize,
HSM_KEY_RSA, PICO_KEYS_KEY_RSA,
buf, buf,
buf_len); buf_len);
} }
@@ -583,7 +583,7 @@ size_t asn1_build_prkd_aes(const uint8_t *label,
keyid, keyid,
keyid_len, keyid_len,
keysize, keysize,
HSM_KEY_AES, PICO_KEYS_KEY_AES,
buf, buf,
buf_len); buf_len);
} }

View File

@@ -36,6 +36,7 @@ extern bool has_session_pin, has_session_sopin;
extern uint8_t session_pin[32], session_sopin[32]; extern uint8_t session_pin[32], session_sopin[32];
uint8_t mkek_mask[MKEK_KEY_SIZE]; uint8_t mkek_mask[MKEK_KEY_SIZE];
bool has_mkek_mask = false; bool has_mkek_mask = false;
uint8_t pending_save_dkek = 0xff;
#define POLY 0xedb88320 #define POLY 0xedb88320
@@ -286,7 +287,7 @@ int dkek_encode_key(uint8_t id,
size_t *out_len, size_t *out_len,
const uint8_t *allowed, const uint8_t *allowed,
size_t allowed_len) { size_t allowed_len) {
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES)) { if (!(key_type & PICO_KEYS_KEY_RSA) && !(key_type & PICO_KEYS_KEY_EC) && !(key_type & PICO_KEYS_KEY_AES)) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
} }
@@ -316,17 +317,17 @@ int dkek_encode_key(uint8_t id,
return r; return r;
} }
if (key_type & HSM_KEY_AES) { if (key_type & PICO_KEYS_KEY_AES) {
if (key_type & HSM_KEY_AES_128) { if (key_type & PICO_KEYS_KEY_AES_128) {
kb_len = 16; kb_len = 16;
} }
else if (key_type & HSM_KEY_AES_192) { else if (key_type & PICO_KEYS_KEY_AES_192) {
kb_len = 24; kb_len = 24;
} }
else if (key_type & HSM_KEY_AES_256) { else if (key_type & PICO_KEYS_KEY_AES_256) {
kb_len = 32; kb_len = 32;
} }
else if (key_type & HSM_KEY_AES_512) { else if (key_type & PICO_KEYS_KEY_AES_512) {
kb_len = 64; kb_len = 64;
} }
@@ -344,7 +345,7 @@ int dkek_encode_key(uint8_t id,
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 & HSM_KEY_RSA) { else if (key_type & PICO_KEYS_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 CCID_WRONG_LENGTH; return CCID_WRONG_LENGTH;
} }
@@ -365,7 +366,7 @@ int dkek_encode_key(uint8_t id,
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 & HSM_KEY_EC) { else if (key_type & PICO_KEYS_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 CCID_WRONG_LENGTH; return CCID_WRONG_LENGTH;
} }
@@ -417,13 +418,13 @@ int dkek_encode_key(uint8_t id,
memcpy(out + *out_len, kcv, 8); memcpy(out + *out_len, kcv, 8);
*out_len += 8; *out_len += 8;
if (key_type & HSM_KEY_AES) { if (key_type & PICO_KEYS_KEY_AES) {
out[*out_len] = 15; out[*out_len] = 15;
} }
else if (key_type & HSM_KEY_RSA) { else if (key_type & PICO_KEYS_KEY_RSA) {
out[*out_len] = 5; out[*out_len] = 5;
} }
else if (key_type & HSM_KEY_EC) { else if (key_type & PICO_KEYS_KEY_EC) {
out[*out_len] = 12; out[*out_len] = 12;
} }
*out_len += 1; *out_len += 1;
@@ -457,7 +458,7 @@ int dkek_encode_key(uint8_t id,
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, HSM_AES_MODE_CBC, kb, kb_len_pad); r = aes_encrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, kb_len_pad);
if (r != CCID_OK) { if (r != CCID_OK) {
return r; return r;
} }
@@ -481,13 +482,13 @@ int dkek_encode_key(uint8_t id,
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 HSM_KEY_RSA; return PICO_KEYS_KEY_RSA;
} }
else if (in[8] == 12) { else if (in[8] == 12) {
return HSM_KEY_EC; return PICO_KEYS_KEY_EC;
} }
else if (in[8] == 15) { else if (in[8] == 15) {
return HSM_KEY_AES; return PICO_KEYS_KEY_AES;
} }
return 0x0; return 0x0;
} }
@@ -584,7 +585,7 @@ int dkek_decode_key(uint8_t id,
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, HSM_AES_MODE_CBC, kb, in_len - 16 - ofs); r = aes_decrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, in_len - 16 - ofs);
if (r != CCID_OK) { if (r != CCID_OK) {
return r; return r;
} }

View File

@@ -74,4 +74,6 @@ extern mse_t mse;
extern int mse_decrypt_ct(uint8_t *, size_t); extern int mse_decrypt_ct(uint8_t *, size_t);
extern uint8_t pending_save_dkek;
#endif #endif

View File

@@ -24,7 +24,7 @@
#include "eac.h" #include "eac.h"
#include "cvc.h" #include "cvc.h"
#include "asn1.h" #include "asn1.h"
#include "hsm.h" #include "pico_keys.h"
#include "usb.h" #include "usb.h"
#include "random.h" #include "random.h"
@@ -80,20 +80,16 @@ extern int cmd_bip_slip();
extern const uint8_t *ccid_atr; extern const uint8_t *ccid_atr;
app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) { int sc_hsm_select_aid(app_t *a) {
if (!memcmp(aid, sc_hsm_aid + 1, MIN(aid_len, sc_hsm_aid[0]))) {
a->aid = sc_hsm_aid;
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 a; return CCID_OK;
}
return NULL;
} }
void __attribute__((constructor)) sc_hsm_ctor() { void __attribute__((constructor)) sc_hsm_ctor() {
ccid_atr = atr_sc_hsm; ccid_atr = atr_sc_hsm;
register_app(sc_hsm_select_aid); register_app(sc_hsm_select_aid, sc_hsm_aid);
} }
void scan_files() { void scan_files() {
@@ -289,7 +285,11 @@ bool wait_button_pressed() {
} }
int parse_token_info(const file_t *f, int mode) { int parse_token_info(const file_t *f, int mode) {
#ifdef __FOR_CI
char *label = "SmartCard-HSM";
#else
char *label = "Pico-HSM"; char *label = "Pico-HSM";
#endif
char *manu = "Pol Henarejos"; char *manu = "Pol Henarejos";
if (mode == 1) { if (mode == 1) {
uint8_t *p = res_APDU; uint8_t *p = res_APDU;
@@ -407,6 +407,10 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
hash_multi(data, len, session_sopin); hash_multi(data, len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
if (pending_save_dkek != 0xff) {
save_dkek_key(pending_save_dkek, NULL);
pending_save_dkek = 0xff;
}
return SW_OK(); return SW_OK();
} }
@@ -492,30 +496,30 @@ uint32_t decrement_key_counter(file_t *fkey) {
int store_keys(void *key_ctx, int type, uint8_t key_id) { int store_keys(void *key_ctx, int type, uint8_t key_id) {
int r, key_size = 0; int r, key_size = 0;
uint8_t kdata[4096 / 8]; // worst case uint8_t kdata[4096 / 8]; // worst case
if (type & HSM_KEY_RSA) { if (type & PICO_KEYS_KEY_RSA) {
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
key_size = mbedtls_mpi_size(&rsa->P) + mbedtls_mpi_size(&rsa->Q); key_size = mbedtls_mpi_size(&rsa->P) + 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 & HSM_KEY_EC) { else if (type & PICO_KEYS_KEY_EC) {
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
key_size = mbedtls_mpi_size(&ecdsa->d); key_size = mbedtls_mpi_size(&ecdsa->d);
kdata[0] = ecdsa->grp.id & 0xff; kdata[0] = ecdsa->grp.id & 0xff;
mbedtls_ecp_write_key(ecdsa, kdata + 1, key_size); mbedtls_ecp_write_key(ecdsa, kdata + 1, key_size);
key_size++; key_size++;
} }
else if (type & HSM_KEY_AES) { else if (type & PICO_KEYS_KEY_AES) {
if (type == HSM_KEY_AES_128) { if (type == PICO_KEYS_KEY_AES_128) {
key_size = 16; key_size = 16;
} }
else if (type == HSM_KEY_AES_192) { else if (type == PICO_KEYS_KEY_AES_192) {
key_size = 24; key_size = 24;
} }
else if (type == HSM_KEY_AES_256) { else if (type == PICO_KEYS_KEY_AES_256) {
key_size = 32; key_size = 32;
} }
else if (type == HSM_KEY_AES_512) { else if (type == PICO_KEYS_KEY_AES_512) {
key_size = 64; key_size = 64;
} }
memcpy(kdata, key_ctx, key_size); memcpy(kdata, key_ctx, key_size);

View File

@@ -27,7 +27,7 @@
#endif #endif
#include "file.h" #include "file.h"
#include "apdu.h" #include "apdu.h"
#include "hsm.h" #include "pico_keys.h"
extern const uint8_t sc_hsm_aid[]; extern const uint8_t sc_hsm_aid[];

View File

@@ -18,7 +18,7 @@
#ifndef __VERSION_H_ #ifndef __VERSION_H_
#define __VERSION_H_ #define __VERSION_H_
#define HSM_VERSION 0x0304 #define HSM_VERSION 0x0306
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff) #define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff)

View File

@@ -1,7 +1,14 @@
#!/bin/bash -eu #!/bin/bash -eu
source tests/docker_env.sh source tests/docker_env.sh
build_image
#run_in_docker rm -rf CMakeFiles #run_in_docker rm -rf CMakeFiles
run_in_docker mkdir -p build_in_docker run_in_docker mkdir -p build_in_docker
run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 .. run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -D__FOR_CI=1 ..
run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC} run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC}
docker create --name temp_container pico-hsm-test:bullseye
docker cp $PWD/build_in_docker/pico_hsm temp_container:/pico_hsm
docker commit temp_container pico-hsm-test:bullseye
docker stop temp_container
docker rm temp_container
docker image prune -f

View File

@@ -4,6 +4,8 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y RUN apt update && apt upgrade -y
RUN apt install -y apt-utils RUN apt install -y apt-utils
RUN apt autoremove -y
RUN rm -rf /var/cache/apt/archives/*
RUN apt install -y libccid \ RUN apt install -y libccid \
libpcsclite-dev \ libpcsclite-dev \
git \ git \
@@ -15,16 +17,33 @@ RUN apt install -y libccid \
gcc \ gcc \
make \ make \
build-essential \ build-essential \
opensc \
python3 \ python3 \
python3-pip \ python3-pip \
swig \ swig \
libssl-dev \
cmake \ cmake \
vsmartcard-vpcd \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN pip3 install pytest pycvc cryptography pyscard RUN pip3 install pytest pycvc cryptography pyscard base58
RUN git clone https://github.com/polhenarejos/vsmartcard.git WORKDIR /
WORKDIR /vsmartcard/virtualsmartcard RUN git clone https://github.com/OpenSC/OpenSC
RUN autoreconf --verbose --install WORKDIR /OpenSC
RUN ./configure --sysconfdir=/etc RUN git checkout tags/0.23.0
RUN make && make install RUN ./bootstrap
RUN ./configure --enable-openssl
RUN make -j `nproc`
RUN make install
RUN make clean
RUN ldconfig
WORKDIR /
RUN git clone https://github.com/polhenarejos/pypicohsm.git
RUN pip3 install -e pypicohsm
RUN git clone https://github.com/CardContact/sc-hsm-embedded
WORKDIR /sc-hsm-embedded
RUN autoreconf -fi
RUN ./configure
RUN make -j `nproc`
RUN make install
RUN cp ./src/tests/sc-hsm-pkcs11-test /usr/local/bin/sc-hsm-pkcs11-test
RUN make clean
WORKDIR / WORKDIR /

2
tests/docker_env.sh Normal file → Executable file
View File

@@ -72,6 +72,7 @@ else
NUM_PROC="$(nproc)" NUM_PROC="$(nproc)"
fi fi
build_image() {
# Build the Docker image # Build the Docker image
echo "Getting docker image up to date (this may take a few minutes)..." echo "Getting docker image up to date (this may take a few minutes)..."
${DOCKER} image build \ ${DOCKER} image build \
@@ -80,6 +81,7 @@ ${DOCKER} image build \
--network host \ --network host \
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \ --build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
tests/docker/${MBEDTLS_DOCKER_GUEST} tests/docker/${MBEDTLS_DOCKER_GUEST}
}
run_in_docker() run_in_docker()
{ {

View File

@@ -1,5 +1,11 @@
#!/bin/bash -eu #!/bin/bash -eu
source tests/docker_env.sh source tests/docker_env.sh
run_in_docker ./tests/start-up-and-test.sh
if [[ $1 == "pkcs11" ]]; then
run_in_docker ./tests/start-up-and-test-pkcs11.sh
elif [[ $1 == "sc-hsm-pkcs11" ]]; then
run_in_docker ./tests/scripts/sc_hsm_test.sh
else
run_in_docker ./tests/start-up-and-test.sh
fi

38
tests/scripts/aes.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
TEST_DATA="This is a text."
echo "${TEST_DATA}" > test
sc_tool() {
pkcs11-tool --module /usr/local/lib/libsc-hsm-pkcs11.so -l --pin 648219 $@
}
aeses=("16" "24" "32")
for aes in ${aeses[*]}; do
echo " Test AES (AES:${aes})"
echo -n " Keygen... "
sc_tool --keygen --key-type "AES:${aes}" --id 1 --label "AES:${aes}" > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(sc_tool --list-object --type secrkey 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "AES length ${aes}" <<< $e && echo -n "." || exit $?
grep -q "AES:${aes}" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Encryption..."
sc_tool --encrypt --id 1 --input-file test --mechanism aes-cbc > crypted.aes 2>/dev/null
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Decryption..."
e=$(sc_tool --decrypt --id 1 --input-file crypted.aes --mechanism aes-cbc 2>/dev/null)
test $? -eq 0 && echo -n "." || exit $?
grep -q "${TEST_DATA}" <<< $e && echo -e ".\t${OK}" || exit $?
sc_tool --delete --type secrkey --id 1 > /dev/null 2>&1
done
rm -rf test crypted.aes

62
tests/scripts/asym_cipher.sh Executable file
View File

@@ -0,0 +1,62 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
rsa_encrypt_decrypt() {
openssl pkeyutl -encrypt -pubin -inkey 1.pub $2 -in $1 -out data.crypt
test $? -eq 0 && echo -n "." || exit $?
TDATA=$(tr -d '\0' < <(pkcs11-tool --id 1 --pin 648219 --decrypt $3 -i data.crypt 2>/dev/null))
test $? -eq 0 && echo -n "." || exit $?
if [[ ${TEST_STRING} != "$TDATA" ]]; then
exit 1
fi
test $? -eq 0 && echo -n "." || exit $?
}
TEST_STRING="This is a test string. Be safe, be secure."
echo ${TEST_STRING} > data
echo -n " Keygen RSA 2048..."
keygen_and_export rsa:2048
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test RSA-PKCS ciphering..."
rsa_encrypt_decrypt data "-pkeyopt rsa_padding_mode:pkcs1" "--mechanism RSA-PKCS"
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test RSA-X-509 ciphering..."
cp data data_pad
tlen=${#TEST_STRING}
dd if=/dev/zero bs=1 count=$((256-$tlen-1)) >> data_pad 2> /dev/null
test $? -eq 0 && echo -n "." || exit $?
rsa_encrypt_decrypt data_pad "-pkeyopt rsa_padding_mode:none" "--mechanism RSA-X-509"
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test RSA-PKCS-OAEP ciphering..."
rsa_encrypt_decrypt data "-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256" "--mechanism RSA-PKCS-OAEP"
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
rm -rf data* 1.*
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
algs=("secp192r1" "secp256r1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "secp192k1" "secp256k1")
for alg in ${algs[*]}; do
echo -n " Test EC derive with ${alg}..."
keygen_and_export ec:${alg}
test $? -eq 0 && echo -n "." || exit $?
openssl ecparam -genkey -name ${alg} > bob.pem 2>/dev/null
test $? -eq 0 && echo -n "." || exit $?
openssl ec -in bob.pem -pubout -outform DER > bob.der 2>/dev/null
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --pin 648219 --id 1 --derive -i bob.der -o mine-bob.der > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
openssl pkeyutl -derive -out bob-mine.der -inkey bob.pem -peerkey 1.pub 2>/dev/null
test $? -eq 0 && echo -n "." || exit $?
cmp bob-mine.der mine-bob.der
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
rm -rf data* 1.*
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
done

60
tests/scripts/backup.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
sc_backup() {
for i in $(seq 1 $1); do
sc-hsm-tool --create-dkek-share dkek.${i}.pbe --password testpw > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
done
sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares $1 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool -l --pin 648219 -I > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
for i in $(seq 1 $1); do
e=$(sc-hsm-tool --import-dkek-share dkek.${i}.pbe --password testpw 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "DKEK share imported" <<< $e && echo -n "." || exit $?
grep -q "DKEK shares[[:blank:]]*: $1" <<< $e && echo -n "." || exit $?
if [[ $i -lt $1 ]]; then
grep -q "DKEK import pending, $(( $1 - $i ))" <<< $e && echo -n "." || exit $?
fi
done
# Store DKEK, since it is not logged in
pkcs11-tool -l --pin 648219 -I > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
}
echo -n " Test single DKEK..."
sc_backup 1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test multiple DKEK..."
sc_backup 3
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
rm -rf dkek.*.pbe
echo " Test backup and restore"
algs=("rsa:1024" "rsa:2048" "ec:secp192r1" "ec:secp256r1" "ec:secp384r1" "ec:secp521r1" "ec:brainpoolP256r1" "ec:brainpoolP384r1" "ec:brainpoolP512r1" "ec:secp192k1" "ec:secp256k1")
for alg in ${algs[*]}; do
echo -n " Keygen ${alg}..."
gen_and_check ${alg}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Wrap key..."
sc-hsm-tool --wrap-key wrap-key.bin --key-reference 1 --pin 648219 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs15-tool -D 2>&1)
grep -q "Key ref[[:blank:]]*: 10" <<< $e && exit $? || echo -e ".\t${OK}"
echo -n " Unwrap key..."
sc-hsm-tool --unwrap-key wrap-key.bin --key-reference 10 --pin 648219 --force > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs15-tool -D 2>&1)
grep -q "Key ref[[:blank:]]*: 10" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Cleaning..."
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
done

52
tests/scripts/func.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/bin/bash
OK="\033[32mok\033[0m"
FAIL="\033[31mfail\033[0m"
gen_and_check() {
e=$(pkcs11-tool -l --pin 648219 --keypairgen --key-type $1 --id 1 --label "TestLabel" 2>&1)
test $? -eq 0 && echo -n "." || exit $?
glabel=""
case $1 in
*"192"*)
glabel="EC_POINT 192 bits"
;;
*"256"*)
glabel="EC_POINT 256 bits"
;;
*"384"*)
glabel="EC_POINT 384 bits"
;;
*"512"*)
glabel="EC_POINT 512 bits"
;;
*"521"*)
glabel="EC_POINT 528 bits"
;;
*"rsa"*)
IFS=: read -r v1 bits <<< "$1"
glabel="RSA ${bits} bits"
;;
esac
grep -q "${glabel}" <<< $e && echo -n "." || exit $?
}
gen_and_delete() {
gen_and_check $1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
}
reset() {
python3 tools/pico-hsm-tool.py --pin 648219 initialize --so-pin 57621880 --silent > /dev/null 2>&1
test $? -eq 0 || exit $?
}
keygen_and_export() {
gen_and_check $1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --read-object --pin 648219 --id 1 --type pubkey > 1.der 2>/dev/null
test $? -eq 0 && echo -n "." || exit $?
IFS=: read -r mk bts <<< "$1"
openssl ${mk} -inform DER -outform PEM -in 1.der -pubin > 1.pub 2>/dev/null
test $? -eq 0 && echo -n "." || exit $?
}

49
tests/scripts/initialize.sh Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
# Change SO-PIN
echo -n " Test SO-PIN change..."
pkcs11-tool --login --login-type so --so-pin 3537363231383830 --change-pin --new-pin 0123456789012345 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --login --login-type so --so-pin 0123456789012345 --change-pin --new-pin 3537363231383830 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
# Change PIN
echo -n " Test PIN change..."
pkcs11-tool --login --pin 648219 --change-pin --new-pin 123456 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
# Reset PIN
echo -n " Test PIN reset..."
pkcs11-tool --login --login-type so --so-pin 3537363231383830 --init-pin --new-pin 648219 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
# Change PIN
pkcs11-tool --login --pin 648219 --change-pin --new-pin 123456 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --login --pin 123456 --change-pin --new-pin 648219 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
# Wrong PIN (1st and 2nd PIN_INCORRECT, 3rd PIN_LOCKED)
echo -n " Test wrong PIN attempts..."
e=$(pkcs11-tool --login --pin 123456 -I 2>&1)
test $? -eq 1 && echo -n "." || exit $?
grep -q CKR_PIN_INCORRECT <<< $e && echo -n "." || exit $?
e=$(pkcs11-tool --login --pin 123456 -I 2>&1)
test $? -eq 1 && echo -n "." || exit $?
grep -q CKR_PIN_INCORRECT <<< $e && echo -n "." || exit $?
e=$(pkcs11-tool --login --pin 123456 -I 2>&1)
test $? -eq 1 && echo -n "." || exit $?
grep -q CKR_PIN_LOCKED <<< $e && echo -e "\t${OK}" || exit $?
# Reset PIN
echo -n " Test restore PIN..."
pkcs11-tool --login --login-type so --so-pin 3537363231383830 --init-pin --new-pin 648219 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --login --pin 648219 -I > /dev/null 2>&1
test $? -eq 0 && echo -e "\t${OK}" || exit $?

13
tests/scripts/keygen.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
algs=("rsa:1024" "rsa:2048" "ec:secp192r1" "ec:secp256r1" "ec:secp384r1" "ec:secp521r1" "ec:brainpoolP256r1" "ec:brainpoolP384r1" "ec:brainpoolP512r1" "ec:secp192k1" "ec:secp256k1")
for alg in ${algs[*]}; do
IFS=: read -r a s <<< "${alg}"
au=$(awk '{print toupper($0)}' <<<${a})
echo -n " Test ${au} ${s}..."
gen_and_delete ${alg} && echo -e ".\t${OK}" || exit $?
done

58
tests/scripts/pkcs11.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
source ./tests/scripts/func.sh
echo "==== Test initialization ===="
./tests/scripts/initialize.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test keygen ===="
./tests/scripts/keygen.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test sign and verify ===="
./tests/scripts/sign_and_verify.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test asymmetric ciphering ===="
./tests/scripts/asym_cipher.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test binary storage ===="
./tests/scripts/store_binary.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test AES ===="
./tests/scripts/aes.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test PKCS11-tool ===="
./tests/scripts/pkcs11_test.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test backup and restore ===="
./tests/scripts/backup.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}

17
tests/scripts/pkcs11_test.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
echo -n " Test PKCS11 tool..."
gen_and_check rsa:2048
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --test -l --pin 648219 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "No errors" <<< $e && echo -n "." || exit $?
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
#e=$(pkcs11-tool --test-ec -l --pin 648219 --id 1 --key-type ec:secp256r1 2>&1)
#test $? -eq 0 && echo -n "." || exit $?
#grep -q "==> OK" <<< $e && echo -e ".\t${OK}" || exit $?

24
tests/scripts/sc_hsm_test.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
source ./tests/startup.sh
echo "==== Test SC HSM ===="
echo -n " Running sc-hsm-pkcs11-test..."
pkcs11-tool -l --pin 648219 --keypairgen --key-type ec:secp256r1 --id 1 --label "TestLabel" > /dev/null 2>&1
test $? -eq 0 && echo -n "." || {
echo -e "\t${FAIL}"
exit 1
}
e=$(/usr/local/bin/sc-hsm-pkcs11-test --module /usr/local/lib/libsc-hsm-pkcs11.so --pin 648219 --invasive 2>&1)
test $? -eq 0 && echo -n "." || {
echo -e "\t${FAIL}"
exit 1
}
grep -q "338 tests performed" <<< $e && echo -n "." || {
echo -e "\t${FAIL}"
exit 1
}
grep -q "0 tests failed" <<< $e && echo -e ".\t${OK}" || {
echo -e "\t${FAIL}"
exit 1
}

126
tests/scripts/sign_and_verify.sh Executable file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
TEST_DATA="This is a test string. Be safe, be secure."
echo ${TEST_DATA} > data
create_dgst() {
openssl dgst -$1 -binary -out data.$1 data > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
}
dgsts=("sha1" "sha224" "sha256" "sha384" "sha512")
for dgst in ${dgsts[*]}; do
echo -n " Create digest ${dgst}..."
create_dgst ${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
done
# $1 sign mechanism
# $2 sign input file
# $3 sign parameters
# $4 vrfy input file
# $5 vrfy parameters
sign_and_verify() {
pkcs11-tool --id 1 --sign --pin 648219 --mechanism $1 -i $2 -o data.sig $3 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(openssl pkeyutl -verify -pubin -inkey 1.pub -in $4 -sigfile data.sig $5 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Signature Verified Successfully" <<< $e && echo -n "." || exit $?
}
sign_and_verify_rsa_pkcs() {
dgstl=$(awk '{print tolower($0)}' <<<$1)
dgstu=$(awk '{print toupper($0)}' <<<$1)
sign_and_verify "${dgstu}-RSA-PKCS" data "" data.${dgstl} "-pkeyopt digest:${dgstl}"
test $? -eq 0 && echo -n "." || exit $?
}
sign_and_verify_rsa_pss() {
dgstl=$(awk '{print tolower($0)}' <<<$1)
dgstu=$(awk '{print toupper($0)}' <<<$1)
sign_and_verify "RSA-PKCS-PSS" data.${dgstl} "--mgf MGF1-${dgstu} --hash-algorithm ${dgstu}" data.${dgstl} "-pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:${dgstl}"
test $? -eq 0 && echo -n "." || exit $?
}
sign_and_verify_rsa_pss_dgst() {
dgstl=$(awk '{print tolower($0)}' <<<$1)
dgstu=$(awk '{print toupper($0)}' <<<$1)
sign_and_verify "${dgstu}-RSA-PKCS-PSS" data "" data.${dgstl} "-pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:${dgstl}"
test $? -eq 0 && echo -n "." || exit $?
}
keygen_sign_and_verify_ec() {
echo " Test ECDSA with $1"
echo -n " Keygen $1..."
keygen_and_export $1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
for dgst in ${dgsts[*]}; do
dgstu=$(awk '{print toupper($0)}' <<<${dgst})
echo -n " Test ECDSA with ${dgst} and $1..."
sign_and_verify ECDSA "data.${dgst}" "--signature-format openssl" data.${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test ECDSA-${dgstu} with $1..."
sign_and_verify "ECDSA-${dgstu}" data "--signature-format openssl" data.${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
done
echo -n " Delete $1..."
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
}
algs=("ec:secp192r1" "ec:secp256r1" "ec:secp384r1" "ec:secp521r1" "ec:brainpoolP256r1" "ec:brainpoolP384r1" "ec:brainpoolP512r1" "ec:secp192k1" "ec:secp256k1")
for alg in ${algs[*]}; do
keygen_sign_and_verify_ec ${alg} || exit $?
done
echo " Test RSA PKCS"
echo -n " Keygen rsa:2048..."
keygen_and_export "rsa:2048"
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " Test RSA-PKCS..."
pkcs11-tool --id 1 --sign --pin 648219 --mechanism RSA-PKCS -i data -o data.sig > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(openssl pkeyutl -verify -pubin -inkey 1.pub -in data -sigfile data.sig 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Signature Verified Successfully" <<< $e && echo -e ".\t${OK}" || exit $?
for dgst in ${dgsts[*]}; do
dgstu=$(awk '{print toupper($0)}' <<<${dgst})
echo -n " Test RSA-PKCS-${dgstu}..."
sign_and_verify_rsa_pkcs ${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
done
echo -n " Test RSA-X-509..."
cp data data_pad
test $? -eq 0 && echo -n "." || exit $?
tlen=${#TEST_DATA}
dd if=/dev/zero bs=1 count=$((256-$tlen)) >> data_pad > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
pkcs11-tool --id 1 --sign --pin 648219 --mechanism RSA-X-509 -i data_pad -o data.sig > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
TDATA=$(tr -d '\0' < <(openssl rsautl -verify -inkey 1.pub -in data.sig -pubin -raw))
if [[ ${TEST_DATA} != "$TDATA" ]]; then
exit 1
fi
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
for dgst in ${dgsts[*]}; do
dgstu=$(awk '{print toupper($0)}' <<<${dgst})
if [[ "${dgst}" != "sha1" ]]; then
echo -n " Test RSA-PKCS-PSS with ${dgst}..."
sign_and_verify_rsa_pss ${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
fi
echo -n " Test ${dgstu}-RSA-PKCS-PSS..."
sign_and_verify_rsa_pss_dgst ${dgst}
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
done
rm -rf data* 1.*
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1

28
tests/scripts/store_binary.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
TEST_DATA="Pico HSM is awesome!"
echo ${TEST_DATA} > test
echo -n " Test public binary storage..."
pkcs11-tool --pin 648219 --write-object test --type data --id 1 --label 'test1' > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --read-object --type data --label 'test1' 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "${TEST_DATA}" <<< $e && echo -e ".\t${OK}" || exit $?
pkcs11-tool --pin 648219 --delete-object --type data --label 'test1' > /dev/null 2>&1
echo -n " Test private binary storage..."
pkcs11-tool --pin 648219 --write-object test --type data --id 1 --label 'test1' --private > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --read-object --type data --label 'test1' --pin 648219 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "${TEST_DATA}" <<< $e && echo -n "." || exit $?
e=$(pkcs11-tool --read-object --type data --label 'test1' 2>&1)
test $? -eq 1 && echo -n "." || exit $?
grep -q "error: object not found" <<< $e && echo -e ".\t${OK}" || exit $?
pkcs11-tool --pin 648219 --delete-object --type data --label 'test1' > /dev/null 2>&1

View File

@@ -0,0 +1,8 @@
#!/bin/bash
source ./tests/startup.sh
chmod a+x tests/scripts/*.sh
echo "======== PKCS11 Test suite ========"
./tests/scripts/pkcs11.sh

View File

@@ -1,11 +1,5 @@
#!/bin/bash -eu #!/bin/bash
source ./tests/startup.sh
rm -rf pypicohsm
git clone https://github.com/polhenarejos/pypicohsm.git
pip3 install -e pypicohsm
/usr/sbin/pcscd &
sleep 2
rm -f memory.flash
tar -xf tests/memory.tar.gz
./build_in_docker/pico_hsm > /dev/null &
pytest tests -W ignore::DeprecationWarning pytest tests -W ignore::DeprecationWarning

27
tests/startup.sh Normal file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
OK="\t\033[32mok\033[0m"
FAIL="\t\033[31mfail\033[0m"
fail() {
echo -e "${FAIL}"
exit 1
}
echo -n "Start PCSC..."
/usr/sbin/pcscd &
test $? -eq 0 && echo -e "${OK}" || {
echo -e "${FAIL}"
exit 1
}
sleep 2
rm -f memory.flash
tar -xf tests/memory.tar.gz
echo -n "Start Pico HSM..."
/pico_hsm > /dev/null 2>&1 &
test $? -eq 0 && echo -n "." || fail
sleep 2
ATR="3b:fe:18:00:00:81:31:fe:45:80:31:81:54:48:53:4d:31:73:80:21:40:81:07:fa"
e=$(opensc-tool -an 2>&1)
grep -q "${ATR}" <<< $e && echo -n "." || fail
test $? -eq 0 && echo -e "${OK}" || fail

View File

@@ -39,7 +39,7 @@ except ModuleNotFoundError:
sys.exit(-1) sys.exit(-1)
try: try:
from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, utils from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, utils, APDUResponse, SWCodes
except ModuleNotFoundError: except ModuleNotFoundError:
print('ERROR: picohsm module not found! Install picohsm package.\nTry with `pip install pypicohsm`') print('ERROR: picohsm module not found! Install picohsm package.\nTry with `pip install pypicohsm`')
sys.exit(-1) sys.exit(-1)
@@ -66,6 +66,7 @@ def parse_args():
parser_init = subparser.add_parser('initialize', help='Performs the first initialization of the Pico HSM.') parser_init = subparser.add_parser('initialize', help='Performs the first initialization of the Pico HSM.')
parser.add_argument('--pin', help='PIN number') parser.add_argument('--pin', help='PIN number')
parser_init.add_argument('--so-pin', help='SO-PIN number') parser_init.add_argument('--so-pin', help='SO-PIN number')
parser_init.add_argument('--silent', help='Confirms initialization silently.', action='store_true')
parser_attestate = subparser.add_parser('attestate', help='Generates an attestation report for a private key and verifies the private key was generated in the devices or outside.') parser_attestate = subparser.add_parser('attestate', help='Generates an attestation report for a private key and verifies the private key was generated in the devices or outside.')
parser_attestate.add_argument('-k', '--key', help='The private key index', metavar='KEY_ID') parser_attestate.add_argument('-k', '--key', help='The private key index', metavar='KEY_ID')
@@ -176,6 +177,7 @@ def pki(_, args):
print('Error: no PKI is passed. Use --default to retrieve default PKI.') print('Error: no PKI is passed. Use --default to retrieve default PKI.')
def initialize(picohsm, args): def initialize(picohsm, args):
if (not args.silent):
print('********************************') print('********************************')
print('* PLEASE READ IT CAREFULLY *') print('* PLEASE READ IT CAREFULLY *')
print('********************************') print('********************************')
@@ -186,13 +188,19 @@ def initialize(picohsm, args):
_ = input('[Press enter to confirm]') _ = input('[Press enter to confirm]')
if (args.pin): if (args.pin):
try:
picohsm.login(args.pin) picohsm.login(args.pin)
pin = args except APDUResponse:
pass
pin = args.pin
else: else:
pin = '648219' pin = '648219'
if (args.so_pin): if (args.so_pin):
picohsm.login(args.pin, who=PinType.SO_PIN) try:
picohsm.login(args.so_pin, who=PinType.SO_PIN)
except APDUResponse:
pass
so_pin = args.so_pin so_pin = args.so_pin
else: else:
so_pin = '57621880' so_pin = '57621880'

View File

@@ -51,7 +51,9 @@ def get_secure_key():
try: try:
backend = get_backend(False) backend = get_backend(False)
key = backend.get_password(DOMAIN, USERNAME)[0] key = backend.get_password(DOMAIN, USERNAME)[0]
except keyring.errors.KeyringError: if (key is None):
raise TypeError
except (keyring.errors.KeyringError, TypeError):
try: try:
key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault
except keyring.errors.PasswordSetError: except keyring.errors.PasswordSetError:

View File

@@ -39,6 +39,8 @@ def get_secure_key():
key = None key = None
try: try:
key = keyring.get_password(DOMAIN, USERNAME) key = keyring.get_password(DOMAIN, USERNAME)
except keyring.errors.KeyringError: if (key is None):
raise TypeError
except (keyring.errors.KeyringError, TypeError):
key = generate_secure_key() key = generate_secure_key()
return get_d(key.encode()) return get_d(key.encode())