Skip to content

Commit

Permalink
Merge pull request #89 from canokeys/feature/piv-extension
Browse files Browse the repository at this point in the history
Feature/piv extension
  • Loading branch information
dangfan authored Jun 30, 2024
2 parents 7f31674 + 82d16ab commit 6162ed5
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 22 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
11 changes: 6 additions & 5 deletions applets/piv/piv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1099,7 +1100,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;
Expand Down
57 changes: 41 additions & 16 deletions test-real/test-piv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -86,8 +89,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
Expand All @@ -101,22 +104,44 @@ test_RSA2048() {
assertEquals 'openssl dgst verify' 0 $?
}

test_ECC256() {
for s in 9a 9c 9d 9e; do PIVGenKeyCert $s "/CN=CertAtSlot$s/" ECCP256; done
test_RSA2048() {
rsa_tests RSA2048
}

test_RSA3072() {
rsa_tests RSA3072
}

test_RSA4096() {
rsa_tests RSA4096
}

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() {
ec_tests ED25519
ec_tests X25519
}

test_PinBlock() {
Expand Down

0 comments on commit 6162ed5

Please sign in to comment.