From 9e724be03606888c795370b1a0b3fd2b69696248 Mon Sep 17 00:00:00 2001 From: z4yx Date: Tue, 21 May 2024 19:51:34 +0800 Subject: [PATCH 1/4] test PIV cipher extension with Yubico piv tool --- applets/piv/piv.c | 8 ++++---- test-real/test-piv.sh | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/applets/piv/piv.c b/applets/piv/piv.c index 92908071..da1f2c1f 100644 --- a/applets/piv/piv.c +++ b/applets/piv/piv.c @@ -41,10 +41,10 @@ #define ALG_RSA_2048 0x07 #define ALG_ECC_256 0x11 #define ALG_ECC_384 0x14 -#define ALG_ED25519_DEFAULT 0x22 // defined in https://github.com/go-piv/piv-go/pull/69 +#define ALG_ED25519_DEFAULT 0xE0 #define ALG_RSA_3072_DEFAULT 0x05 // defined in NIST SP 800-78-5 (Initial Public Draft) -#define ALG_RSA_4096_DEFAULT 0x51 -#define ALG_X25519_DEFAULT 0x52 +#define ALG_RSA_4096_DEFAULT 0x16 +#define ALG_X25519_DEFAULT 0xE1 #define ALG_SECP256K1_DEFAULT 0x53 #define ALG_SM2_DEFAULT 0x54 @@ -1099,7 +1099,7 @@ static int piv_get_version(const CAPDU *capdu, RAPDU *rapdu) { if (P1 != 0x00 || P2 != 0x00) EXCEPT(SW_WRONG_P1P2); if (LC != 0) EXCEPT(SW_WRONG_LENGTH); RDATA[0] = 0x05; - RDATA[1] = 0x04; + RDATA[1] = 0x07; RDATA[2] = 0x00; LL = 3; return 0; diff --git a/test-real/test-piv.sh b/test-real/test-piv.sh index cac821f7..71db6619 100755 --- a/test-real/test-piv.sh +++ b/test-real/test-piv.sh @@ -86,8 +86,8 @@ test_ChangePin() { assertEquals 'set-mgm-key' 0 $? } -test_RSA2048() { - for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" RSA2048; done +rsa_tests() { + for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" $1; done YPT -a status PIVSignDec 9e # PIN not required for key 9e for s in 9a 9c 9d; do PIVSignDec $s 1; done @@ -101,6 +101,18 @@ test_RSA2048() { assertEquals 'openssl dgst verify' 0 $? } +test_RSA2048() { + rsa_tests RSA2048 +} + +test_RSA3072() { + rsa_tests RSA3072 +} + +test_RSA4096() { + rsa_tests RSA4096 +} + test_ECC256() { for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ECCP256; done YPT -a status @@ -119,6 +131,16 @@ test_ECC384() { assertContains 'CERT' "$out" 'CN = CertAtSlot9c' } +test_25519() { + for s in 9a 9c 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ED25519; done + for s in 9d; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" X25519; done + YPT -a status + for s in 9a 9c 9e; do PIVSignDec $s 1 s; done # 9a/9c/9e only do the EDDSA + # PIVSignDec 9d 1 d # 9d only do the EDDH + # out=$(pkcs15-tool --reader "$RDID" --read-certificate 01 | openssl x509 -text) + # assertContains 'CERT' "$out" 'CN = CertAtSlot9a' +} + test_PinBlock() { out=$(YPT -a verify-pin -P 222222 2>&1) assertContains 'verify-pin' "$out" '2 tries left before pin is blocked.' From 0339e3ec7328defc85656bbad2701eace865d721 Mon Sep 17 00:00:00 2001 From: z4yx Date: Tue, 25 Jun 2024 21:57:53 +0800 Subject: [PATCH 2/4] test algorithm extension --- test-real/test-piv.sh | 45 +++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/test-real/test-piv.sh b/test-real/test-piv.sh index 71db6619..3ecad0c6 100755 --- a/test-real/test-piv.sh +++ b/test-real/test-piv.sh @@ -15,6 +15,7 @@ PIVGenKeyCert() { algo="$3" YPT -a generate -A $algo -s $key >$TEST_TMP_DIR/pubkey-$key.pem # generate key at $key assertEquals 'yubico-piv-tool generate' 0 $? + if [[ $algo == "X25519" ]]; then return; fi YPT -P 654321 -a verify-pin -a selfsign-certificate -s $key -S "$subject" < $TEST_TMP_DIR/pubkey-$key.pem >$TEST_TMP_DIR/cert-$key.pem assertEquals 'yubico-piv-tool selfsign-certificate' 0 $? YPT -a import-certificate -s $key < $TEST_TMP_DIR/cert-$key.pem @@ -36,13 +37,15 @@ PIVSignDec() { key=$1 pinArgs= op=$3 + inp_file=$TEST_TMP_DIR/cert-$key.pem + if [[ $key == X25519 ]]; then inp_file=$TEST_TMP_DIR/pubkey-$key.pem; fi if [[ -n "$2" ]]; then pinArgs="-P 654321 -a verify-pin"; fi if [[ -z "$op" || s = "$op" ]]; then - YPT $pinArgs -a test-signature -s $key < $TEST_TMP_DIR/cert-$key.pem; + YPT $pinArgs -a test-signature -s $key < $inp_file; assertEquals 'yubico-piv-tool test-signature' 0 $? fi if [[ -z "$op" || d = "$op" ]]; then - YPT $pinArgs -a test-decipher -s $key < $TEST_TMP_DIR/cert-$key.pem; + YPT $pinArgs -a test-decipher -s $key < $inp_file; assertEquals 'yubico-piv-tool test-decipher' 0 $? fi } @@ -113,32 +116,32 @@ test_RSA4096() { rsa_tests RSA4096 } -test_ECC256() { - for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ECCP256; done +ec_tests() { + for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" $1; done YPT -a status - for s in 9a 9c 9e; do PIVSignDec $s 1 s; done # 9a/9c/9e only do the ECDSA - PIVSignDec 9d 1 d # 9d only do the ECDH - out=$(pkcs15-tool --reader "$RDID" --read-certificate 01 | openssl x509 -text) - assertContains 'CERT' "$out" 'CN = CertAtSlot9a' + for s in 9a 9c 9d 9e; do + if [[ $1 != "X25519" ]]; then PIVSignDec $s 1 s; fi + if [[ $1 != "ED25519" ]]; then PIVSignDec $s 1 d; fi + done + if [[ $1 != *25519 ]]; then + out=$(pkcs15-tool --reader "$RDID" --read-certificate 01 | openssl x509 -text) + assertContains 'CERT' "$out" 'CN = CertAtSlot9a' + out=$(pkcs15-tool --reader "$RDID" --read-certificate 02 | openssl x509 -text) + assertContains 'CERT' "$out" 'CN = CertAtSlot9c' + fi +} + +test_ECC256() { + ec_tests ECCP256 } test_ECC384() { - for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ECCP384; done - YPT -a status - for s in 9a 9c 9e; do PIVSignDec $s 1 s; done # 9a/9c/9e only do the ECDSA - PIVSignDec 9d 1 d # 9d only do the ECDH - out=$(pkcs15-tool --reader "$RDID" --read-certificate 02 | openssl x509 -text) - assertContains 'CERT' "$out" 'CN = CertAtSlot9c' + ec_tests ECCP384 } test_25519() { - for s in 9a 9c 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ED25519; done - for s in 9d; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" X25519; done - YPT -a status - for s in 9a 9c 9e; do PIVSignDec $s 1 s; done # 9a/9c/9e only do the EDDSA - # PIVSignDec 9d 1 d # 9d only do the EDDH - # out=$(pkcs15-tool --reader "$RDID" --read-certificate 01 | openssl x509 -text) - # assertContains 'CERT' "$out" 'CN = CertAtSlot9a' + ec_tests ED25519 + ec_tests X25519 } test_PinBlock() { From 69495fc60762ec6c03defabe1c9639ea7d440dfa Mon Sep 17 00:00:00 2001 From: z4yx Date: Fri, 28 Jun 2024 13:08:17 +0800 Subject: [PATCH 3/4] fix tests with piv-go --- .github/workflows/tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a95d08f3..13063c04 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -384,12 +384,16 @@ jobs: set -o xtrace go test -v test-via-pcsc/piv_test.go RDID="Canokey [OpenPGP PIV OATH] 00 00" + export PIV_EXT_AUTH_KEY=$PWD/test-via-pcsc/PIV_EXT_AUTH_KEY.txt yubico-piv-tool -r "$RDID" -a status -a set-ccc -a set-chuid -a status opensc-tool -r "$RDID" -s '00 F8 00 00' | grep 'SW1=0x90, SW2=0x00' # PIV_INS_GET_SERIAL, Yubico opensc-tool -r "$RDID" -s '00 FD 00 00' | grep 'SW1=0x90, SW2=0x00' # PIV_INS_GET_VERSION, Yubico pkcs15-tool --reader "$RDID" -D + # change the algorithm identifier of ED25519 + piv-tool --admin M:9B:03 -s '00 EE 02 00 07 01 22 05 51 52 53 54' | grep 'SW1=0x90, SW2=0x00' # PIV_INS_ALGORITHM_EXTENSION, Yubico cd piv-go; go test -v ./piv --wipe-yubikey; cd - + piv-tool --admin M:9B:03 -s '00 EE 02 00 07 01 E0 05 16 E1 53 54' | grep 'SW1=0x90, SW2=0x00' # PIV_INS_ALGORITHM_EXTENSION, Yubico yubico-piv-tool -r "$RDID" -a verify-pin -P 123456 yubico-piv-tool -r "$RDID" -a change-pin -P 123456 -N 654321 @@ -399,7 +403,6 @@ jobs: yubico-piv-tool -r "$RDID" -a verify-pin -P 654321 yubico-piv-tool -r "$RDID" -a set-mgm-key -n F1F2F3F4F5F6F7F8F1F2F3F4F5F6F7F8F1F2F3F4F5F6F7F8 yubico-piv-tool -r "$RDID" -a set-mgm-key --key=F1F2F3F4F5F6F7F8F1F2F3F4F5F6F7F8F1F2F3F4F5F6F7F8 -n 010203040506070801020304050607080102030405060708 - export PIV_EXT_AUTH_KEY=$PWD/test-via-pcsc/PIV_EXT_AUTH_KEY.txt # opensc 0.22.0~0.23.0 has a bug on External Auth. See opensc commit: a0aef25c7f2ce0ec2c7e1014f959f0fe86ff0479 piv-tool --reader "$RDID" --admin A:9B:03 # External Auth piv-tool --reader "$RDID" --admin M:9B:03 # Mutual Auth From 82d16abc5b321f656639180845d11aeca2859e71 Mon Sep 17 00:00:00 2001 From: Yuxiang Zhang Date: Sat, 29 Jun 2024 13:27:11 +0800 Subject: [PATCH 4/4] skip reseting algorithm extensions ID --- applets/piv/piv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applets/piv/piv.c b/applets/piv/piv.c index da1f2c1f..469f950e 100644 --- a/applets/piv/piv.c +++ b/applets/piv/piv.c @@ -253,7 +253,8 @@ int piv_install(const uint8_t reset) { if (write_attr(pin.path, TAG_PIN_KEY_DEFAULT, &tmp, sizeof(tmp)) < 0) return -1; if (pin_create(&puk, DEFAULT_PUK, 8, 3) < 0) return -1; if (write_attr(puk.path, TAG_PIN_KEY_DEFAULT, &tmp, sizeof(tmp)) < 0) return -1; - + + if (get_file_size(ALGORITHM_EXT_CONFIG_PATH) == sizeof(alg_ext_cfg)) return 0; // Algorithm extensions alg_ext_cfg.enabled = 1; alg_ext_cfg.ed25519 = ALG_ED25519_DEFAULT;