mirror of
https://github.com/polhenarejos/pico-hsm.git
synced 2026-01-17 01:18:06 +00:00
Merge branch 'development' into development-eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
commit
ba562da00e
44 changed files with 821 additions and 160 deletions
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: polhenarejos
|
||||
custom: ["https://www.paypal.me/polhenarejos"]
|
||||
37
.github/workflows/test.yml
vendored
37
.github/workflows/test.yml
vendored
|
|
@ -23,9 +23,7 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository and submodules
|
||||
uses: actions/checkout@v3
|
||||
|
|
@ -33,5 +31,36 @@ jobs:
|
|||
submodules: recursive
|
||||
- name: Build in container
|
||||
run: ./tests/build-in-docker.sh
|
||||
- name: Start emulation and test
|
||||
run: ./tests/run-test-in-docker.sh
|
||||
- name: Export image
|
||||
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
6
.gitmodules
vendored
|
|
@ -1,3 +1,3 @@
|
|||
[submodule "pico-hsm-sdk"]
|
||||
path = pico-hsm-sdk
|
||||
url = ../pico-hsm-sdk
|
||||
[submodule "pico-keys-sdk"]
|
||||
path = pico-keys-sdk
|
||||
url = https://github.com/polhenarejos/pico-keys-sdk
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ else()
|
|||
pico_sdk_init()
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED __FOR_CI)
|
||||
set(__FOR_CI 0)
|
||||
endif()
|
||||
if (__FOR_CI)
|
||||
add_definitions(-D__FOR_CI)
|
||||
endif()
|
||||
|
||||
add_executable(pico_hsm)
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
|
|
@ -70,7 +77,7 @@ set(SOURCES ${SOURCES}
|
|||
|
||||
)
|
||||
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}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/hsm
|
||||
|
|
@ -102,5 +109,5 @@ endif (APPLE)
|
|||
else()
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
VERSION_MAJOR="3"
|
||||
VERSION_MINOR="2"
|
||||
VERSION_MINOR="6"
|
||||
|
||||
rm -rf release/*
|
||||
cd build_release
|
||||
|
|
@ -17,6 +17,7 @@ for board in adafruit_feather_rp2040 \
|
|||
eetree_gamekit_rp2040 \
|
||||
garatronic_pybstick26_rp2040 \
|
||||
melopero_shake_rp2040 \
|
||||
nullbits_bit_c_pro \
|
||||
pico \
|
||||
pico_w \
|
||||
pimoroni_badger2040 \
|
||||
|
|
@ -31,6 +32,7 @@ for board in adafruit_feather_rp2040 \
|
|||
pimoroni_servo2040 \
|
||||
pimoroni_tiny2040 \
|
||||
pimoroni_tiny2040_2mb \
|
||||
pololu_3pi_2040_robot \
|
||||
seeed_xiao_rp2040 \
|
||||
solderparty_rp2040_stamp \
|
||||
solderparty_rp2040_stamp_carrier \
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ PIN=648219
|
|||
## Initialization
|
||||
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 accepts from 6 to 16 characters.
|
||||
|
|
@ -51,7 +51,7 @@ $ pkcs11-tool --login --pin 648219 --change-pin --new-pin 123456
|
|||
|
||||
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
|
||||
|
|
|
|||
1
pico-keys-sdk
Submodule
1
pico-keys-sdk
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit f0687c1ef392c2bcb293ea554f1dd8b784484922
|
||||
|
|
@ -412,20 +412,21 @@ int cmd_cipher_sym() {
|
|||
res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32);
|
||||
}
|
||||
else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
|
||||
size_t olen = 0;
|
||||
mbedtls_asn1_buf params =
|
||||
{ .p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) };
|
||||
int r = mbedtls_pkcs5_pbes2(¶ms,
|
||||
{.p = aad, .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,
|
||||
enc_len,
|
||||
res_APDU);
|
||||
res_APDU, 4096, &olen);
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
if (r != 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
res_APDU_size = enc_len;
|
||||
res_APDU_size = olen;
|
||||
}
|
||||
else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ int cmd_derive_asym() {
|
|||
mbedtls_ecp_keypair_free(&ctx);
|
||||
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) {
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
|
|
|
|||
|
|
@ -187,13 +187,13 @@ int cmd_initialize() {
|
|||
mbedtls_ecdsa_free(&ecdsa);
|
||||
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) {
|
||||
mbedtls_ecdsa_free(&ecdsa);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
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);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ int cmd_initialize() {
|
|||
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);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,14 @@
|
|||
|
||||
uint8_t get_key_domain(file_t *fkey) {
|
||||
size_t tag_len = 0;
|
||||
if (!file_has_data(fkey)) {
|
||||
return 0xff;
|
||||
}
|
||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len);
|
||||
if (meta_tag) {
|
||||
return *meta_tag;
|
||||
}
|
||||
return 0xff;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
int cmd_key_domain() {
|
||||
|
|
@ -65,10 +68,16 @@ int cmd_key_domain() {
|
|||
}
|
||||
import_dkek_share(p2, apdu.data);
|
||||
if (++current_dkeks >= dkeks) {
|
||||
if (save_dkek_key(p2, NULL) != CCID_OK) {
|
||||
/* On fail, it will return to previous dkek state. */
|
||||
import_dkek_share(p2, apdu.data);
|
||||
return SW_FILE_NOT_FOUND();
|
||||
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. */
|
||||
import_dkek_share(p2, apdu.data);
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t t[MAX_KEY_DOMAINS * 2];
|
||||
|
|
@ -94,8 +103,9 @@ int cmd_key_domain() {
|
|||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (p1 == 0x3) { //if key domain is not empty, command is denied
|
||||
for (int i = 0; i < dynamic_files; i++) {
|
||||
if (get_key_domain(&dynamic_file[i]) == p2) {
|
||||
for (int i = 1; i < 256; i++) {
|
||||
file_t *fkey = search_dynamic_file(KEY_PREFIX << 8 | i);
|
||||
if (get_key_domain(fkey) == p2) {
|
||||
return SW_FILE_EXISTS();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,16 +44,16 @@ int cmd_key_gen() {
|
|||
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
||||
int aes_type = 0x0;
|
||||
if (key_size == 16) {
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
aes_type = PICO_KEYS_KEY_AES_128;
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
aes_type = PICO_KEYS_KEY_AES_192;
|
||||
}
|
||||
else if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
aes_type = PICO_KEYS_KEY_AES_256;
|
||||
}
|
||||
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);
|
||||
if (r != CCID_OK) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ int cmd_key_unwrap() {
|
|||
if (key_type == 0x0) {
|
||||
return SW_DATA_INVALID();
|
||||
}
|
||||
if (key_type & HSM_KEY_RSA) {
|
||||
if (key_type & PICO_KEYS_KEY_RSA) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
do {
|
||||
|
|
@ -45,8 +45,8 @@ int cmd_key_unwrap() {
|
|||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = store_keys(&ctx, HSM_KEY_RSA, key_id);
|
||||
if ((res_APDU_size = asn1_cvc_aut(&ctx, HSM_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
r = store_keys(&ctx, PICO_KEYS_KEY_RSA, key_id);
|
||||
if ((res_APDU_size = asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
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));
|
||||
}
|
||||
else if (key_type & HSM_KEY_EC) {
|
||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
||||
mbedtls_ecp_keypair ctx;
|
||||
mbedtls_ecp_keypair_init(&ctx);
|
||||
do {
|
||||
|
|
@ -67,7 +67,7 @@ int cmd_key_unwrap() {
|
|||
mbedtls_ecp_keypair_free(&ctx);
|
||||
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) {
|
||||
mbedtls_ecp_keypair_free(&ctx);
|
||||
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));
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES) {
|
||||
else if (key_type & PICO_KEYS_KEY_AES) {
|
||||
uint8_t aes_key[64];
|
||||
int key_size = 0, aes_type = 0;
|
||||
do {
|
||||
|
|
@ -95,16 +95,16 @@ int cmd_key_unwrap() {
|
|||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (key_size == 64) {
|
||||
aes_type = HSM_KEY_AES_512;
|
||||
aes_type = PICO_KEYS_KEY_AES_512;
|
||||
}
|
||||
else if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
aes_type = PICO_KEYS_KEY_AES_256;
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
aes_type = PICO_KEYS_KEY_AES_192;
|
||||
}
|
||||
else if (key_size == 16) {
|
||||
aes_type = HSM_KEY_AES_128;
|
||||
aes_type = PICO_KEYS_KEY_AES_128;
|
||||
}
|
||||
else {
|
||||
return SW_EXEC_ERROR();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ int cmd_key_wrap() {
|
|||
}
|
||||
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);
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||
|
|
@ -81,7 +81,7 @@ int cmd_key_wrap() {
|
|||
}
|
||||
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);
|
||||
}
|
||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||
|
|
@ -90,22 +90,22 @@ int cmd_key_wrap() {
|
|||
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);
|
||||
if (mkek_decrypt(kdata, key_size) != 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
if (key_size == 64) {
|
||||
aes_type = HSM_KEY_AES_512;
|
||||
aes_type = PICO_KEYS_KEY_AES_512;
|
||||
}
|
||||
else if (key_size == 32) {
|
||||
aes_type = HSM_KEY_AES_256;
|
||||
aes_type = PICO_KEYS_KEY_AES_256;
|
||||
}
|
||||
else if (key_size == 24) {
|
||||
aes_type = HSM_KEY_AES_192;
|
||||
aes_type = PICO_KEYS_KEY_AES_192;
|
||||
}
|
||||
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);
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
|
|
|
|||
|
|
@ -69,10 +69,10 @@ int cmd_keypair_gen() {
|
|||
return SW_EXEC_ERROR();
|
||||
}
|
||||
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();
|
||||
}
|
||||
ret = store_keys(&rsa, HSM_KEY_RSA, key_id);
|
||||
ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id);
|
||||
if (ret != CCID_OK) {
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return SW_EXEC_ERROR();
|
||||
|
|
@ -146,7 +146,7 @@ int cmd_keypair_gen() {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
free(ext);
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ int cmd_keypair_gen() {
|
|||
if (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);
|
||||
if (ret != CCID_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ int cmd_read_binary() {
|
|||
return SW_WARNING_EOF();
|
||||
}
|
||||
|
||||
uint16_t maxle = data_len - offset;
|
||||
if (apdu.ne > maxle) {
|
||||
apdu.ne = maxle;
|
||||
}
|
||||
//uint16_t maxle = data_len - offset;
|
||||
//if (apdu.ne > maxle) {
|
||||
// apdu.ne = maxle;
|
||||
//}
|
||||
memcpy(res_APDU, file_get_data(ef) + offset, data_len - offset);
|
||||
res_APDU_size = data_len - offset;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,16 +36,15 @@ int cmd_reset_retry() {
|
|||
if (P1(apdu) == 0x0 || P1(apdu) == 0x2) {
|
||||
int newpin_len = 0;
|
||||
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();
|
||||
}
|
||||
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) {
|
||||
return r;
|
||||
}
|
||||
newpin_len = apdu.nc - 8;
|
||||
has_session_sopin = true;
|
||||
hash_multi(apdu.data, 8, session_sopin);
|
||||
newpin_len = apdu.nc - so_pin_len;
|
||||
}
|
||||
else if (P1(apdu) == 0x2) {
|
||||
if (!has_session_sopin) {
|
||||
|
|
@ -83,15 +82,14 @@ int cmd_reset_retry() {
|
|||
return SW_COMMAND_NOT_ALLOWED();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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) {
|
||||
return r;
|
||||
}
|
||||
has_session_sopin = true;
|
||||
hash_multi(apdu.data, 8, session_sopin);
|
||||
}
|
||||
else if (P1(apdu) == 0x3) {
|
||||
if (!has_session_sopin) {
|
||||
|
|
|
|||
|
|
@ -166,10 +166,10 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa,
|
|||
size_t ext_len,
|
||||
bool full) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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
|
||||
*p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar;
|
||||
//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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
//chr
|
||||
|
|
@ -266,10 +266,10 @@ size_t asn1_cvc_cert(void *rsa_ecdsa,
|
|||
size_t ext_len,
|
||||
bool full) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
memcpy(p, "\x5F\x37", 2); p += 2;
|
||||
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) {
|
||||
memset(p, 0, key_size);
|
||||
}
|
||||
p += key_size;
|
||||
}
|
||||
else if (key_type & HSM_KEY_EC) {
|
||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
||||
mbedtls_mpi r, s;
|
||||
int ret = 0;
|
||||
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;
|
||||
const uint8_t *seq = NULL;
|
||||
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_len = 3;
|
||||
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_len = 2;
|
||||
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_len = 3;
|
||||
first_tag = 0xA8;
|
||||
|
|
@ -469,10 +469,10 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
|||
size_t seq2_size =
|
||||
asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len));
|
||||
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)));
|
||||
}
|
||||
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)));
|
||||
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;
|
||||
|
||||
//Seq 3
|
||||
if (key_type & HSM_KEY_AES) {
|
||||
if (key_type & PICO_KEYS_KEY_AES) {
|
||||
*p++ = 0xA0;
|
||||
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x2, 2)), p);
|
||||
*p++ = 0x30;
|
||||
|
|
@ -518,7 +518,7 @@ size_t asn1_build_prkd_generic(const uint8_t *label,
|
|||
//Seq 4
|
||||
*p++ = 0xA1;
|
||||
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);
|
||||
}
|
||||
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++ = 0x4;
|
||||
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 += format_tlv_len(2, p);
|
||||
*p++ = (keysize >> 8) & 0xff;
|
||||
|
|
@ -549,7 +549,7 @@ size_t asn1_build_prkd_ecc(const uint8_t *label,
|
|||
keyid,
|
||||
keyid_len,
|
||||
keysize,
|
||||
HSM_KEY_EC,
|
||||
PICO_KEYS_KEY_EC,
|
||||
buf,
|
||||
buf_len);
|
||||
}
|
||||
|
|
@ -566,7 +566,7 @@ size_t asn1_build_prkd_rsa(const uint8_t *label,
|
|||
keyid,
|
||||
keyid_len,
|
||||
keysize,
|
||||
HSM_KEY_RSA,
|
||||
PICO_KEYS_KEY_RSA,
|
||||
buf,
|
||||
buf_len);
|
||||
}
|
||||
|
|
@ -583,7 +583,7 @@ size_t asn1_build_prkd_aes(const uint8_t *label,
|
|||
keyid,
|
||||
keyid_len,
|
||||
keysize,
|
||||
HSM_KEY_AES,
|
||||
PICO_KEYS_KEY_AES,
|
||||
buf,
|
||||
buf_len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extern bool has_session_pin, has_session_sopin;
|
|||
extern uint8_t session_pin[32], session_sopin[32];
|
||||
uint8_t mkek_mask[MKEK_KEY_SIZE];
|
||||
bool has_mkek_mask = false;
|
||||
uint8_t pending_save_dkek = 0xff;
|
||||
|
||||
#define POLY 0xedb88320
|
||||
|
||||
|
|
@ -286,7 +287,7 @@ int dkek_encode_key(uint8_t id,
|
|||
size_t *out_len,
|
||||
const uint8_t *allowed,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -316,17 +317,17 @@ int dkek_encode_key(uint8_t id,
|
|||
return r;
|
||||
}
|
||||
|
||||
if (key_type & HSM_KEY_AES) {
|
||||
if (key_type & HSM_KEY_AES_128) {
|
||||
if (key_type & PICO_KEYS_KEY_AES) {
|
||||
if (key_type & PICO_KEYS_KEY_AES_128) {
|
||||
kb_len = 16;
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES_192) {
|
||||
else if (key_type & PICO_KEYS_KEY_AES_192) {
|
||||
kb_len = 24;
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES_256) {
|
||||
else if (key_type & PICO_KEYS_KEY_AES_256) {
|
||||
kb_len = 32;
|
||||
}
|
||||
else if (key_type & HSM_KEY_AES_512) {
|
||||
else if (key_type & PICO_KEYS_KEY_AES_512) {
|
||||
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_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
|
||||
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_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
|
||||
return CCID_WRONG_LENGTH;
|
||||
}
|
||||
|
|
@ -417,13 +418,13 @@ int dkek_encode_key(uint8_t id,
|
|||
memcpy(out + *out_len, kcv, 8);
|
||||
*out_len += 8;
|
||||
|
||||
if (key_type & HSM_KEY_AES) {
|
||||
if (key_type & PICO_KEYS_KEY_AES) {
|
||||
out[*out_len] = 15;
|
||||
}
|
||||
else if (key_type & HSM_KEY_RSA) {
|
||||
else if (key_type & PICO_KEYS_KEY_RSA) {
|
||||
out[*out_len] = 5;
|
||||
}
|
||||
else if (key_type & HSM_KEY_EC) {
|
||||
else if (key_type & PICO_KEYS_KEY_EC) {
|
||||
out[*out_len] = 12;
|
||||
}
|
||||
*out_len += 1;
|
||||
|
|
@ -457,7 +458,7 @@ int dkek_encode_key(uint8_t id,
|
|||
if (kb_len < kb_len_pad) {
|
||||
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) {
|
||||
return r;
|
||||
}
|
||||
|
|
@ -481,13 +482,13 @@ int dkek_encode_key(uint8_t id,
|
|||
|
||||
int dkek_type_key(const uint8_t *in) {
|
||||
if (in[8] == 5 || in[8] == 6) {
|
||||
return HSM_KEY_RSA;
|
||||
return PICO_KEYS_KEY_RSA;
|
||||
}
|
||||
else if (in[8] == 12) {
|
||||
return HSM_KEY_EC;
|
||||
return PICO_KEYS_KEY_EC;
|
||||
}
|
||||
else if (in[8] == 15) {
|
||||
return HSM_KEY_AES;
|
||||
return PICO_KEYS_KEY_AES;
|
||||
}
|
||||
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)
|
||||
memset(kb, 0, sizeof(kb));
|
||||
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) {
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,4 +74,6 @@ extern mse_t mse;
|
|||
|
||||
extern int mse_decrypt_ct(uint8_t *, size_t);
|
||||
|
||||
extern uint8_t pending_save_dkek;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "eac.h"
|
||||
#include "cvc.h"
|
||||
#include "asn1.h"
|
||||
#include "hsm.h"
|
||||
#include "pico_keys.h"
|
||||
#include "usb.h"
|
||||
#include "random.h"
|
||||
|
||||
|
|
@ -80,20 +80,16 @@ extern int cmd_bip_slip();
|
|||
|
||||
extern const uint8_t *ccid_atr;
|
||||
|
||||
app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) {
|
||||
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->unload = sc_hsm_unload;
|
||||
init_sc_hsm();
|
||||
return a;
|
||||
}
|
||||
return NULL;
|
||||
int sc_hsm_select_aid(app_t *a) {
|
||||
a->process_apdu = sc_hsm_process_apdu;
|
||||
a->unload = sc_hsm_unload;
|
||||
init_sc_hsm();
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
void __attribute__((constructor)) sc_hsm_ctor() {
|
||||
ccid_atr = atr_sc_hsm;
|
||||
register_app(sc_hsm_select_aid);
|
||||
register_app(sc_hsm_select_aid, sc_hsm_aid);
|
||||
}
|
||||
|
||||
void scan_files() {
|
||||
|
|
@ -289,7 +285,11 @@ bool wait_button_pressed() {
|
|||
}
|
||||
|
||||
int parse_token_info(const file_t *f, int mode) {
|
||||
#ifdef __FOR_CI
|
||||
char *label = "SmartCard-HSM";
|
||||
#else
|
||||
char *label = "Pico-HSM";
|
||||
#endif
|
||||
char *manu = "Pol Henarejos";
|
||||
if (mode == 1) {
|
||||
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);
|
||||
has_session_sopin = true;
|
||||
}
|
||||
if (pending_save_dkek != 0xff) {
|
||||
save_dkek_key(pending_save_dkek, NULL);
|
||||
pending_save_dkek = 0xff;
|
||||
}
|
||||
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 r, key_size = 0;
|
||||
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;
|
||||
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->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;
|
||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
||||
kdata[0] = ecdsa->grp.id & 0xff;
|
||||
mbedtls_ecp_write_key(ecdsa, kdata + 1, key_size);
|
||||
key_size++;
|
||||
}
|
||||
else if (type & HSM_KEY_AES) {
|
||||
if (type == HSM_KEY_AES_128) {
|
||||
else if (type & PICO_KEYS_KEY_AES) {
|
||||
if (type == PICO_KEYS_KEY_AES_128) {
|
||||
key_size = 16;
|
||||
}
|
||||
else if (type == HSM_KEY_AES_192) {
|
||||
else if (type == PICO_KEYS_KEY_AES_192) {
|
||||
key_size = 24;
|
||||
}
|
||||
else if (type == HSM_KEY_AES_256) {
|
||||
else if (type == PICO_KEYS_KEY_AES_256) {
|
||||
key_size = 32;
|
||||
}
|
||||
else if (type == HSM_KEY_AES_512) {
|
||||
else if (type == PICO_KEYS_KEY_AES_512) {
|
||||
key_size = 64;
|
||||
}
|
||||
memcpy(kdata, key_ctx, key_size);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#endif
|
||||
#include "file.h"
|
||||
#include "apdu.h"
|
||||
#include "hsm.h"
|
||||
#include "pico_keys.h"
|
||||
|
||||
extern const uint8_t sc_hsm_aid[];
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef __VERSION_H_
|
||||
#define __VERSION_H_
|
||||
|
||||
#define HSM_VERSION 0x0304
|
||||
#define HSM_VERSION 0x0306
|
||||
|
||||
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
|
||||
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
#!/bin/bash -eu
|
||||
|
||||
source tests/docker_env.sh
|
||||
build_image
|
||||
#run_in_docker rm -rf CMakeFiles
|
||||
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}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ ARG DEBIAN_FRONTEND=noninteractive
|
|||
|
||||
RUN apt update && apt upgrade -y
|
||||
RUN apt install -y apt-utils
|
||||
RUN apt autoremove -y
|
||||
RUN rm -rf /var/cache/apt/archives/*
|
||||
RUN apt install -y libccid \
|
||||
libpcsclite-dev \
|
||||
git \
|
||||
|
|
@ -15,16 +17,33 @@ RUN apt install -y libccid \
|
|||
gcc \
|
||||
make \
|
||||
build-essential \
|
||||
opensc \
|
||||
python3 \
|
||||
python3-pip \
|
||||
swig \
|
||||
libssl-dev \
|
||||
cmake \
|
||||
vsmartcard-vpcd \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN pip3 install pytest pycvc cryptography pyscard
|
||||
RUN git clone https://github.com/polhenarejos/vsmartcard.git
|
||||
WORKDIR /vsmartcard/virtualsmartcard
|
||||
RUN autoreconf --verbose --install
|
||||
RUN ./configure --sysconfdir=/etc
|
||||
RUN make && make install
|
||||
RUN pip3 install pytest pycvc cryptography pyscard base58
|
||||
WORKDIR /
|
||||
RUN git clone https://github.com/OpenSC/OpenSC
|
||||
WORKDIR /OpenSC
|
||||
RUN git checkout tags/0.23.0
|
||||
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 /
|
||||
|
|
|
|||
18
tests/docker_env.sh
Normal file → Executable file
18
tests/docker_env.sh
Normal file → Executable file
|
|
@ -72,14 +72,16 @@ else
|
|||
NUM_PROC="$(nproc)"
|
||||
fi
|
||||
|
||||
# Build the Docker image
|
||||
echo "Getting docker image up to date (this may take a few minutes)..."
|
||||
${DOCKER} image build \
|
||||
-t ${DOCKER_IMAGE_TAG} \
|
||||
--cache-from=${DOCKER_IMAGE_TAG} \
|
||||
--network host \
|
||||
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
|
||||
tests/docker/${MBEDTLS_DOCKER_GUEST}
|
||||
build_image() {
|
||||
# Build the Docker image
|
||||
echo "Getting docker image up to date (this may take a few minutes)..."
|
||||
${DOCKER} image build \
|
||||
-t ${DOCKER_IMAGE_TAG} \
|
||||
--cache-from=${DOCKER_IMAGE_TAG} \
|
||||
--network host \
|
||||
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
|
||||
tests/docker/${MBEDTLS_DOCKER_GUEST}
|
||||
}
|
||||
|
||||
run_in_docker()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
#!/bin/bash -eu
|
||||
|
||||
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
38
tests/scripts/aes.sh
Executable 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
62
tests/scripts/asym_cipher.sh
Executable 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
60
tests/scripts/backup.sh
Executable 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
52
tests/scripts/func.sh
Executable 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
49
tests/scripts/initialize.sh
Executable 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
13
tests/scripts/keygen.sh
Executable 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
58
tests/scripts/pkcs11.sh
Executable 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
17
tests/scripts/pkcs11_test.sh
Executable 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
24
tests/scripts/sc_hsm_test.sh
Executable 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
126
tests/scripts/sign_and_verify.sh
Executable 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
28
tests/scripts/store_binary.sh
Executable 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
|
||||
8
tests/start-up-and-test-pkcs11.sh
Executable file
8
tests/start-up-and-test-pkcs11.sh
Executable 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
27
tests/startup.sh
Normal file
27
tests/startup.sh
Normal 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
|
||||
|
|
@ -39,7 +39,7 @@ except ModuleNotFoundError:
|
|||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, utils
|
||||
from picohsm import PicoHSM, PinType, DOPrefixes, KeyType, EncryptionMode, utils, APDUResponse, SWCodes
|
||||
except ModuleNotFoundError:
|
||||
print('ERROR: picohsm module not found! Install picohsm package.\nTry with `pip install pypicohsm`')
|
||||
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.add_argument('--pin', help='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.add_argument('-k', '--key', help='The private key index', metavar='KEY_ID')
|
||||
|
|
@ -176,23 +177,30 @@ def pki(_, args):
|
|||
print('Error: no PKI is passed. Use --default to retrieve default PKI.')
|
||||
|
||||
def initialize(picohsm, args):
|
||||
print('********************************')
|
||||
print('* PLEASE READ IT CAREFULLY *')
|
||||
print('********************************')
|
||||
print('')
|
||||
print('This tool will erase and reset your device. It will delete all '
|
||||
'private and secret keys.')
|
||||
print('Are you sure?')
|
||||
_ = input('[Press enter to confirm]')
|
||||
if (not args.silent):
|
||||
print('********************************')
|
||||
print('* PLEASE READ IT CAREFULLY *')
|
||||
print('********************************')
|
||||
print('')
|
||||
print('This tool will erase and reset your device. It will delete all '
|
||||
'private and secret keys.')
|
||||
print('Are you sure?')
|
||||
_ = input('[Press enter to confirm]')
|
||||
|
||||
if (args.pin):
|
||||
picohsm.login(args.pin)
|
||||
pin = args
|
||||
try:
|
||||
picohsm.login(args.pin)
|
||||
except APDUResponse:
|
||||
pass
|
||||
pin = args.pin
|
||||
else:
|
||||
pin = '648219'
|
||||
|
||||
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
|
||||
else:
|
||||
so_pin = '57621880'
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ def get_secure_key():
|
|||
try:
|
||||
backend = get_backend(False)
|
||||
key = backend.get_password(DOMAIN, USERNAME)[0]
|
||||
except keyring.errors.KeyringError:
|
||||
if (key is None):
|
||||
raise TypeError
|
||||
except (keyring.errors.KeyringError, TypeError):
|
||||
try:
|
||||
key = generate_secure_key(False)[0] # It should be True, but secure enclave causes python segfault
|
||||
except keyring.errors.PasswordSetError:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ def get_secure_key():
|
|||
key = None
|
||||
try:
|
||||
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()
|
||||
return get_d(key.encode())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue