Compare commits

...

7 Commits

Author SHA1 Message Date
NIIBE Yutaka
98119dc991 Version 1.2.18.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-02 16:58:04 +09:00
NIIBE Yutaka
03cca1e451 Write ChangeLog entries and AUTHORS.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-02 16:53:56 +09:00
NIIBE Yutaka
3f65bf73e8 Add a check to make sure device is the one intended.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-01 16:23:39 +09:00
NIIBE Yutaka
07be37f45e Fix tests for Gnuk emulation (skip test with no KDF setup).
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-19 17:37:32 +09:00
Vincent Pelletier
dcef6e0ffa tests/card_test_personalize_card.py: Exercise ECDH, X25519 and ED25519.
ECDH curves exercised are OpenPGP recommended set: ANSIx9p{256,384,521}r1
and BRAINPOOLp{256,384,512}r1, plus X25519 and ED25519.
Signature is only tested (for now ?) with ED25519 as other signature schemes
are (usually) non-deterministic and require implementing the signature
verification algorithm rather than just testing for equality with a test
vector.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-03-19 16:09:03 +09:00
NIIBE Yutaka
d31687ebd6 Fix typo of configure.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-12 12:07:57 +09:00
NIIBE Yutaka
92443f8f07 Fix previous change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-12 03:00:44 +09:00
29 changed files with 741 additions and 12 deletions

12
AUTHORS
View File

@@ -89,6 +89,18 @@ Vincent Pelletier:
Modified:
test/features/202_setup_passphrase.feature
test/rsa_keys.py
tests/card_const.py
tests/card_reader.py
tests/rsa_keys.py
tool/gnuk_token.py
Wrote:
tests/card_test_ansix9p256r1.py
tests/card_test_ansix9p384r1.py
tests/card_test_ansix9p512r1.py
tests/card_test_brainpoolp256r1.py
tests/card_test_brainpoolp384r1.py
tests/card_test_brainpoolp512r1.py
tests/card_test_ed25519.py
tests/card_test_x25519.py
tests/func_pso_auth.py
tests/test_006_pso.py

View File

@@ -1,3 +1,44 @@
2021-04-02 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.18.
2021-04-01 NIIBE Yutaka <gniibe@fsij.org>
* tool/upgrade_by_passwd.py: Check configure target and
the config in the device are same target.
2021-03-19 NIIBE Yutaka <gniibe@fsij.org>
* tests/openpgp_card.py (is_emulated_gnuk): Add.
* tests/skip_if_emulation.py: New.
* tests/skip_if_gnuk.py: New.
* tests/test_001_personalize_card.py: Skip if emulation.
* tests/test_002_personalize_reset.py: Skip if emulation.
* tests/test_003_remove_keys.py: Skip if emulation.
* tests/test_004_reset_pw3.py: Skip if emulation.
* tests/test_005_personalize_admin_less.py: Skip if emulation.
* tests/test_006_pso.py: Skip if Gnuk.
* tests/test_009_keygen.py: Skip if emulation.
* tests/test_021_personalize_admin_less.py: Rewrite.
2021-03-12 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_pgp_gakp): Fix patch mistake.
2021-03-01 Vincent Pelletier <plr.vincent@gmail.com>
* tests/card_const.py: Add attributes for more algos.
* tests/card_test_ansix9p256r1.py: New.
* tests/card_test_ansix9p384r1.py: New.
* tests/card_test_ansix9p512r1.py: New.
* tests/card_test_brainpoolp256r1.py: New.
* tests/card_test_brainpoolp384r1.py: New.
* tests/card_test_brainpoolp512r1.py: New.
* tests/card_test_ed25519.py: New.
* tests/card_test_x25519.py: New.
* tests/func_pso_auth.py: New.
* tests/test_006_pso.py: New.
2021-02-25 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.17.

15
NEWS
View File

@@ -1,6 +1,21 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.18
Released 2021-04-02, by NIIBE Yutaka
** GNU/Linux emulation bug fix
This time, for GNU/Linux emulation, KDF Data Object is required before
keygen and key import, really.
** tool/upgrade_by_passwd.py
Now, it checks if the target of binary being written and the
configured target of running device are same. This check can be
skipped by -s option. Please note that FST-01 and FST-01SZ are
different target, as it's MHz is different.
* Major changes in Gnuk 1.2.17
Released 2021-02-25, by NIIBE Yutaka

10
README
View File

@@ -1,14 +1,14 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.17
2021-02-25
Version 1.2.18
2021-04-02
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.17, which has major
This is the release of Gnuk, version 1.2.18, which has major
incompatible changes to Gnuk 1.0.x. Specifically, it now supports
overriding key import, but importing keys (or generating keys) results
password reset. Also, you need to import private keys before changing
@@ -365,10 +365,10 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
On Debian we can install the packages of gcc-arm-none-eabi
and its friends. I'm using:
binutils-arm-none-eabi 2.35.1-7+14+b1
binutils-arm-none-eabi 2.35.2-2+14+b2
gcc-arm-none-eabi 15:8-2019-q3-1+b1
libnewlib-arm-none-eabi 3.3.0-1
gdb-multiarch 10.1-1.7
gdb-multiarch 10.1-2
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.

View File

@@ -1 +1 @@
release/1.2.17
release/1.2.18

2
src/configure vendored
View File

@@ -219,7 +219,7 @@ if test "$target" = "GNU_LINUX"; then
emulation="yes"
cross=""
mcu="none"
kdf_do_require=yes
kdf_do_required=yes
def_emulation="-DGNU_LINUX_EMULATION"
def_memory_size="-DMEMORY_SIZE=1024"
enable_hexoutput=""

View File

@@ -744,7 +744,6 @@ cmd_pgp_gakp (struct eventflag *ccid_comm)
#endif
else
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
}
}

View File

@@ -2,3 +2,11 @@ FACTORY_PASSPHRASE_PW1=b"123456"
FACTORY_PASSPHRASE_PW3=b"12345678"
KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00"
KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00"
KEY_ATTRIBUTES_ECDH_ANSIX9P256R1=b"\x12\x2a\x86\x48\xce\x3d\x03\x01\x07"
KEY_ATTRIBUTES_ECDH_ANSIX9P384R1=b"\x12\x2b\x81\x04\x00\x22"
KEY_ATTRIBUTES_ECDH_ANSIX9P521R1=b"\x12\x2b\x81\x04\x00\x23"
KEY_ATTRIBUTES_ECDH_BRAINPOOLP256R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x07"
KEY_ATTRIBUTES_ECDH_BRAINPOOLP384R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0b"
KEY_ATTRIBUTES_ECDH_BRAINPOOLP512R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0d"
KEY_ATTRIBUTES_X25519=b"\x12\x2b\x06\x01\x04\x01\x97\x55\x01\x05\x01"
KEY_ATTRIBUTES_ED25519=b"\x16\x2b\x06\x01\x04\x01\xda\x47\x0f\x01"

View File

@@ -0,0 +1,58 @@
"""
card_test_ansix9p256r1.py - test ansix9p256r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_AnsiX9P256R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc5903#section-8.1
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P256R1,
key_attribute_caption='ECDH ansix9p256r1',
private_key=(
b'\xC8\x8F\x01\xF5\x10\xD9\xAC\x3F\x70\xA2\x92\xDA\xA2\x31\x6D\xE5'
b'\x44\xE9\xAA\xB8\xAF\xE8\x40\x49\xC6\x2A\x9C\x57\x86\x2D\x14\x33'
),
expected_public_key=(
b'\x04'
b'\xDA\xD0\xB6\x53\x94\x22\x1C\xF9\xB0\x51\xE1\xFE\xCA\x57\x87\xD0'
b'\x98\xDF\xE6\x37\xFC\x90\xB9\xEF\x94\x5D\x0C\x37\x72\x58\x11\x80'
b'\x52\x71\xA0\x46\x1C\xDB\x82\x52\xD6\x1F\x1C\x45\x6F\xA3\xE5\x9A'
b'\xB1\xF4\x5B\x33\xAC\xCF\x5F\x58\x38\x9E\x05\x77\xB8\x99\x0B\xB3'
),
pso_input=(
b'\xa6\x46\x7f\x49\x43\x86\x41'
b'\x04'
b'\xD1\x2D\xFB\x52\x89\xC8\xD4\xF8\x12\x08\xB7\x02\x70\x39\x8C\x34'
b'\x22\x96\x97\x0A\x0B\xCC\xB7\x4C\x73\x6F\xC7\x55\x44\x94\xBF\x63'
b'\x56\xFB\xF3\xCA\x36\x6C\xC2\x3E\x81\x57\x85\x4C\x13\xC5\x8D\x6A'
b'\xAC\x23\xF0\x46\xAD\xA3\x0F\x83\x53\xE7\x4F\x33\x03\x98\x72\xAB'
),
expected_pso_output=(
b'\xD6\x84\x0F\x6B\x42\xF6\xED\xAF\xD1\x31\x16\xE0\xE1\x25\x65\x20'
b'\x2F\xEF\x8E\x9E\xCE\x7D\xCE\x03\x81\x24\x64\xD0\x4B\x94\x42\xDE'
),
)

View File

@@ -0,0 +1,64 @@
"""
card_test_ansix9p384r1.py - test ansix9p384r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_AnsiX9P384R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc5903#section-8.2
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P384R1,
key_attribute_caption='ECDH ansix9p384r1',
private_key=(
b'\x09\x9F\x3C\x70\x34\xD4\xA2\xC6\x99\x88\x4D\x73\xA3\x75\xA6\x7F'
b'\x76\x24\xEF\x7C\x6B\x3C\x0F\x16\x06\x47\xB6\x74\x14\xDC\xE6\x55'
b'\xE3\x5B\x53\x80\x41\xE6\x49\xEE\x3F\xAE\xF8\x96\x78\x3A\xB1\x94'
),
expected_public_key=(
b'\x04'
b'\x66\x78\x42\xD7\xD1\x80\xAC\x2C\xDE\x6F\x74\xF3\x75\x51\xF5\x57'
b'\x55\xC7\x64\x5C\x20\xEF\x73\xE3\x16\x34\xFE\x72\xB4\xC5\x5E\xE6'
b'\xDE\x3A\xC8\x08\xAC\xB4\xBD\xB4\xC8\x87\x32\xAE\xE9\x5F\x41\xAA'
b'\x94\x82\xED\x1F\xC0\xEE\xB9\xCA\xFC\x49\x84\x62\x5C\xCF\xC2\x3F'
b'\x65\x03\x21\x49\xE0\xE1\x44\xAD\xA0\x24\x18\x15\x35\xA0\xF3\x8E'
b'\xEB\x9F\xCF\xF3\xC2\xC9\x47\xDA\xE6\x9B\x4C\x63\x45\x73\xA8\x1C'
),
pso_input=(
b'\xa6\x66\x7f\x49\x63\x86\x61'
b'\x04'
b'\xE5\x58\xDB\xEF\x53\xEE\xCD\xE3\xD3\xFC\xCF\xC1\xAE\xA0\x8A\x89'
b'\xA9\x87\x47\x5D\x12\xFD\x95\x0D\x83\xCF\xA4\x17\x32\xBC\x50\x9D'
b'\x0D\x1A\xC4\x3A\x03\x36\xDE\xF9\x6F\xDA\x41\xD0\x77\x4A\x35\x71'
b'\xDC\xFB\xEC\x7A\xAC\xF3\x19\x64\x72\x16\x9E\x83\x84\x30\x36\x7F'
b'\x66\xEE\xBE\x3C\x6E\x70\xC4\x16\xDD\x5F\x0C\x68\x75\x9D\xD1\xFF'
b'\xF8\x3F\xA4\x01\x42\x20\x9D\xFF\x5E\xAA\xD9\x6D\xB9\xE6\x38\x6C'
),
expected_pso_output=(
b'\x11\x18\x73\x31\xC2\x79\x96\x2D\x93\xD6\x04\x24\x3F\xD5\x92\xCB'
b'\x9D\x0A\x92\x6F\x42\x2E\x47\x18\x75\x21\x28\x7E\x71\x56\xC5\xC4'
b'\xD6\x03\x13\x55\x69\xB9\xE9\xD0\x9C\xF5\xD4\xA2\x70\xF5\x97\x46'
),
)

View File

@@ -0,0 +1,76 @@
"""
card_test_ansix9p512r1.py - test ansix9p512r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_AnsiX9P512R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc5903#section-8.3
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P521R1,
key_attribute_caption='ECDH ansix9p521r1',
private_key=(
b'\x00\x37\xAD\xE9\x31\x9A\x89\xF4\xDA\xBD\xB3\xEF\x41\x1A\xAC\xCC'
b'\xA5\x12\x3C\x61\xAC\xAB\x57\xB5\x39\x3D\xCE\x47\x60\x81\x72\xA0'
b'\x95\xAA\x85\xA3\x0F\xE1\xC2\x95\x2C\x67\x71\xD9\x37\xBA\x97\x77'
b'\xF5\x95\x7B\x26\x39\xBA\xB0\x72\x46\x2F\x68\xC2\x7A\x57\x38\x2D'
b'\x4A\x52'
),
expected_public_key=(
b'\x04'
b'\x00\x15\x41\x7E\x84\xDB\xF2\x8C\x0A\xD3\xC2\x78\x71\x33\x49\xDC'
b'\x7D\xF1\x53\xC8\x97\xA1\x89\x1B\xD9\x8B\xAB\x43\x57\xC9\xEC\xBE'
b'\xE1\xE3\xBF\x42\xE0\x0B\x8E\x38\x0A\xEA\xE5\x7C\x2D\x10\x75\x64'
b'\x94\x18\x85\x94\x2A\xF5\xA7\xF4\x60\x17\x23\xC4\x19\x5D\x17\x6C'
b'\xED\x3E'
b'\x01\x7C\xAE\x20\xB6\x64\x1D\x2E\xEB\x69\x57\x86\xD8\xC9\x46\x14'
b'\x62\x39\xD0\x99\xE1\x8E\x1D\x5A\x51\x4C\x73\x9D\x7C\xB4\xA1\x0A'
b'\xD8\xA7\x88\x01\x5A\xC4\x05\xD7\x79\x9D\xC7\x5E\x7B\x7D\x5B\x6C'
b'\xF2\x26\x1A\x6A\x7F\x15\x07\x43\x8B\xF0\x1B\xEB\x6C\xA3\x92\x6F'
b'\x95\x82'
),
pso_input=(
b'\xa6\x81\x8c\x7f\x49\x81\x88\x86\x81\x85'
b'\x04'
b'\x00\xD0\xB3\x97\x5A\xC4\xB7\x99\xF5\xBE\xA1\x6D\x5E\x13\xE9\xAF'
b'\x97\x1D\x5E\x9B\x98\x4C\x9F\x39\x72\x8B\x5E\x57\x39\x73\x5A\x21'
b'\x9B\x97\xC3\x56\x43\x6A\xDC\x6E\x95\xBB\x03\x52\xF6\xBE\x64\xA6'
b'\xC2\x91\x2D\x4E\xF2\xD0\x43\x3C\xED\x2B\x61\x71\x64\x00\x12\xD9'
b'\x46\x0F'
b'\x01\x5C\x68\x22\x63\x83\x95\x6E\x3B\xD0\x66\xE7\x97\xB6\x23\xC2'
b'\x7C\xE0\xEA\xC2\xF5\x51\xA1\x0C\x2C\x72\x4D\x98\x52\x07\x7B\x87'
b'\x22\x0B\x65\x36\xC5\xC4\x08\xA1\xD2\xAE\xBB\x8E\x86\xD6\x78\xAE'
b'\x49\xCB\x57\x09\x1F\x47\x32\x29\x65\x79\xAB\x44\xFC\xD1\x7F\x0F'
b'\xC5\x6A'
),
expected_pso_output=(
b'\x01\x14\x4C\x7D\x79\xAE\x69\x56\xBC\x8E\xDB\x8E\x7C\x78\x7C\x45'
b'\x21\xCB\x08\x6F\xA6\x44\x07\xF9\x78\x94\xE5\xE6\xB2\xD7\x9B\x04'
b'\xD1\x42\x7E\x73\xCA\x4B\xAA\x24\x0A\x34\x78\x68\x59\x81\x0C\x06'
b'\xB3\xC7\x15\xA3\xA8\xCC\x31\x51\xF2\xBE\xE4\x17\x99\x6D\x19\xF3'
b'\xDD\xEA'
),
)

View File

@@ -0,0 +1,58 @@
"""
card_test_brainpoolp256r1.py - test brainpoolp256r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_BrainpoolP256R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc7027#appendix-A.1
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP256R1,
key_attribute_caption='ECDH brainpoolp256r1',
private_key=(
b'\x81\xDB\x1E\xE1\x00\x15\x0F\xF2\xEA\x33\x8D\x70\x82\x71\xBE\x38'
b'\x30\x0C\xB5\x42\x41\xD7\x99\x50\xF7\x7B\x06\x30\x39\x80\x4F\x1D'
),
expected_public_key=(
b'\x04'
b'\x44\x10\x6E\x91\x3F\x92\xBC\x02\xA1\x70\x5D\x99\x53\xA8\x41\x4D'
b'\xB9\x5E\x1A\xAA\x49\xE8\x1D\x9E\x85\xF9\x29\xA8\xE3\x10\x0B\xE5'
b'\x8A\xB4\x84\x6F\x11\xCA\xCC\xB7\x3C\xE4\x9C\xBD\xD1\x20\xF5\xA9'
b'\x00\xA6\x9F\xD3\x2C\x27\x22\x23\xF7\x89\xEF\x10\xEB\x08\x9B\xDC'
),
pso_input=(
b'\xa6\x46\x7f\x49\x43\x86\x41'
b'\x04'
b'\x8D\x2D\x68\x8C\x6C\xF9\x3E\x11\x60\xAD\x04\xCC\x44\x29\x11\x7D'
b'\xC2\xC4\x18\x25\xE1\xE9\xFC\xA0\xAD\xDD\x34\xE6\xF1\xB3\x9F\x7B'
b'\x99\x0C\x57\x52\x08\x12\xBE\x51\x26\x41\xE4\x70\x34\x83\x21\x06'
b'\xBC\x7D\x3E\x8D\xD0\xE4\xC7\xF1\x13\x6D\x70\x06\x54\x7C\xEC\x6A'
),
expected_pso_output=(
b'\x89\xAF\xC3\x9D\x41\xD3\xB3\x27\x81\x4B\x80\x94\x0B\x04\x25\x90'
b'\xF9\x65\x56\xEC\x91\xE6\xAE\x79\x39\xBC\xE3\x1F\x3A\x18\xBF\x2B'
),
)

View File

@@ -0,0 +1,64 @@
"""
card_test_brainpoolp384r1.py - test brainpoolp384r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_BrainpoolP384R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc7027#appendix-A.2
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP384R1,
key_attribute_caption='ECDH brainpoolp384r1',
private_key=(
b'\x1E\x20\xF5\xE0\x48\xA5\x88\x6F\x1F\x15\x7C\x74\xE9\x1B\xDE\x2B'
b'\x98\xC8\xB5\x2D\x58\xE5\x00\x3D\x57\x05\x3F\xC4\xB0\xBD\x65\xD6'
b'\xF1\x5E\xB5\xD1\xEE\x16\x10\xDF\x87\x07\x95\x14\x36\x27\xD0\x42'
),
expected_public_key=(
b'\x04'
b'\x68\xB6\x65\xDD\x91\xC1\x95\x80\x06\x50\xCD\xD3\x63\xC6\x25\xF4'
b'\xE7\x42\xE8\x13\x46\x67\xB7\x67\xB1\xB4\x76\x79\x35\x88\xF8\x85'
b'\xAB\x69\x8C\x85\x2D\x4A\x6E\x77\xA2\x52\xD6\x38\x0F\xCA\xF0\x68'
b'\x55\xBC\x91\xA3\x9C\x9E\xC0\x1D\xEE\x36\x01\x7B\x7D\x67\x3A\x93'
b'\x12\x36\xD2\xF1\xF5\xC8\x39\x42\xD0\x49\xE3\xFA\x20\x60\x74\x93'
b'\xE0\xD0\x38\xFF\x2F\xD3\x0C\x2A\xB6\x7D\x15\xC8\x5F\x7F\xAA\x59'
),
pso_input=(
b'\xa6\x66\x7f\x49\x63\x86\x61'
b'\x04'
b'\x4D\x44\x32\x6F\x26\x9A\x59\x7A\x5B\x58\xBB\xA5\x65\xDA\x55\x56'
b'\xED\x7F\xD9\xA8\xA9\xEB\x76\xC2\x5F\x46\xDB\x69\xD1\x9D\xC8\xCE'
b'\x6A\xD1\x8E\x40\x4B\x15\x73\x8B\x20\x86\xDF\x37\xE7\x1D\x1E\xB4'
b'\x62\xD6\x92\x13\x6D\xE5\x6C\xBE\x93\xBF\x5F\xA3\x18\x8E\xF5\x8B'
b'\xC8\xA3\xA0\xEC\x6C\x1E\x15\x1A\x21\x03\x8A\x42\xE9\x18\x53\x29'
b'\xB5\xB2\x75\x90\x3D\x19\x2F\x8D\x4E\x1F\x32\xFE\x9C\xC7\x8C\x48'
),
expected_pso_output=(
b'\x0B\xD9\xD3\xA7\xEA\x0B\x3D\x51\x9D\x09\xD8\xE4\x8D\x07\x85\xFB'
b'\x74\x4A\x6B\x35\x5E\x63\x04\xBC\x51\xC2\x29\xFB\xBC\xE2\x39\xBB'
b'\xAD\xF6\x40\x37\x15\xC3\x5D\x4F\xB2\xA5\x44\x4F\x57\x5D\x4F\x42'
),
)

View File

@@ -0,0 +1,70 @@
"""
card_test_brainpoolp512r1.py - test brainpoolp512r1 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_BrainpoolP512R1(object):
def test_ECDH_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc7027#appendix-A.3
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP512R1,
key_attribute_caption='ECDH brainpoolp512r1',
private_key=(
b'\x16\x30\x2F\xF0\xDB\xBB\x5A\x8D\x73\x3D\xAB\x71\x41\xC1\xB4\x5A'
b'\xCB\xC8\x71\x59\x39\x67\x7F\x6A\x56\x85\x0A\x38\xBD\x87\xBD\x59'
b'\xB0\x9E\x80\x27\x96\x09\xFF\x33\x3E\xB9\xD4\xC0\x61\x23\x1F\xB2'
b'\x6F\x92\xEE\xB0\x49\x82\xA5\xF1\xD1\x76\x4C\xAD\x57\x66\x54\x22'
),
expected_public_key=(
b'\x04'
b'\x0A\x42\x05\x17\xE4\x06\xAA\xC0\xAC\xDC\xE9\x0F\xCD\x71\x48\x77'
b'\x18\xD3\xB9\x53\xEF\xD7\xFB\xEC\x5F\x7F\x27\xE2\x8C\x61\x49\x99'
b'\x93\x97\xE9\x1E\x02\x9E\x06\x45\x7D\xB2\xD3\xE6\x40\x66\x8B\x39'
b'\x2C\x2A\x7E\x73\x7A\x7F\x0B\xF0\x44\x36\xD1\x16\x40\xFD\x09\xFD'
b'\x72\xE6\x88\x2E\x8D\xB2\x8A\xAD\x36\x23\x7C\xD2\x5D\x58\x0D\xB2'
b'\x37\x83\x96\x1C\x8D\xC5\x2D\xFA\x2E\xC1\x38\xAD\x47\x2A\x0F\xCE'
b'\xF3\x88\x7C\xF6\x2B\x62\x3B\x2A\x87\xDE\x5C\x58\x83\x01\xEA\x3E'
b'\x5F\xC2\x69\xB3\x73\xB6\x07\x24\xF5\xE8\x2A\x6A\xD1\x47\xFD\xE7'
),
pso_input=(
b'\xa6\x81\x88\x7f\x49\x81\x84\x86\x81\x81'
b'\x04'
b'\x9D\x45\xF6\x6D\xE5\xD6\x7E\x2E\x6D\xB6\xE9\x3A\x59\xCE\x0B\xB4'
b'\x81\x06\x09\x7F\xF7\x8A\x08\x1D\xE7\x81\xCD\xB3\x1F\xCE\x8C\xCB'
b'\xAA\xEA\x8D\xD4\x32\x0C\x41\x19\xF1\xE9\xCD\x43\x7A\x2E\xAB\x37'
b'\x31\xFA\x96\x68\xAB\x26\x8D\x87\x1D\xED\xA5\x5A\x54\x73\x19\x9F'
b'\x2F\xDC\x31\x30\x95\xBC\xDD\x5F\xB3\xA9\x16\x36\xF0\x7A\x95\x9C'
b'\x8E\x86\xB5\x63\x6A\x1E\x93\x0E\x83\x96\x04\x9C\xB4\x81\x96\x1D'
b'\x36\x5C\xC1\x14\x53\xA0\x6C\x71\x98\x35\x47\x5B\x12\xCB\x52\xFC'
b'\x3C\x38\x3B\xCE\x35\xE2\x7E\xF1\x94\x51\x2B\x71\x87\x62\x85\xFA'
),
expected_pso_output=(
b'\xA7\x92\x70\x98\x65\x5F\x1F\x99\x76\xFA\x50\xA9\xD5\x66\x86\x5D'
b'\xC5\x30\x33\x18\x46\x38\x1C\x87\x25\x6B\xAF\x32\x26\x24\x4B\x76'
b'\xD3\x64\x03\xC0\x24\xD7\xBB\xF0\xAA\x08\x03\xEA\xFF\x40\x5D\x3D'
b'\x24\xF1\x1A\x9B\x5C\x0B\xEF\x67\x9F\xE1\x45\x4B\x21\xC4\xCD\x1F'
),
)

View File

@@ -0,0 +1,51 @@
"""
card_test_ed25519.py - test ed25519 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import hashlib
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_ED25519(object):
def test_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(1, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc8032#section-7.3
assert_ec_pso(
card=card,
key_index=0,
key_attributes=KEY_ATTRIBUTES_ED25519,
key_attribute_caption='ed25519',
private_key=(
b'\x83\x3f\xe6\x24\x09\x23\x7b\x9d\x62\xec\x77\x58\x75\x20\x91\x1e'
b'\x9a\x75\x9c\xec\x1d\x19\x75\x5b\x7d\xa9\x01\xb9\x6d\xca\x3d\x42'
),
expected_public_key=(
b'\xec\x17\x2b\x93\xad\x5e\x56\x3b\xf4\x93\x2c\x70\xe1\x24\x50\x34'
b'\xc3\x54\x67\xef\x2e\xfd\x4d\x64\xeb\xf8\x19\x68\x34\x67\xe2\xbf'
),
pso_input=hashlib.sha512(b'\x61\x62\x63').digest(),
expected_pso_output=(
b'\x98\xa7\x02\x22\xf0\xb8\x12\x1a\xa9\xd3\x0f\x81\x3d\x68\x3f\x80'
b'\x9e\x46\x2b\x46\x9c\x7f\xf8\x76\x39\x49\x9b\xb9\x4e\x6d\xae\x41'
b'\x31\xf8\x50\x42\x46\x3c\x2a\x35\x5a\x20\x03\xd0\x62\xad\xf5\xaa'
b'\xa1\x0b\x8c\x61\xe6\x36\x06\x2a\xaa\xd1\x1c\x2a\x26\x08\x34\x06'
),
)

52
tests/card_test_x25519.py Normal file
View File

@@ -0,0 +1,52 @@
"""
card_test_x25519.py - test x25519 support
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from func_pso_auth import assert_ec_pso
from card_const import *
class Test_Card_X25519(object):
def test_reference_vectors(self, card):
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
# https://tools.ietf.org/html/rfc7748#section-6.1
assert_ec_pso(
card=card,
key_index=1,
key_attributes=KEY_ATTRIBUTES_X25519,
key_attribute_caption='x25519',
private_key=(
b'\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45'
b'\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a'
),
expected_public_key=(
b'\x85\x20\xf0\x09\x89\x30\xa7\x54\x74\x8b\x7d\xdc\xb4\x3e\xf7\x5a'
b'\x0d\xbf\x3a\x0d\x26\x38\x1a\xf4\xeb\xa4\xa9\x8e\xaa\x9b\x4e\x6a'
),
pso_input=(
b'\xa6\x25\x7f\x49\x22\x86\x20'
b'\xde\x9e\xdb\x7d\x7b\x7d\xc1\xb4\xd3\x5b\x61\xc2\xec\xe4\x35\x37'
b'\x3f\x83\x43\xc8\x5b\x78\x67\x4d\xad\xfc\x7e\x14\x6f\x88\x2b\x4f'
),
expected_pso_output=(
b'\x4a\x5d\x9d\x5b\xa4\xce\x2d\xe1\x72\x8e\x3b\xf4\x80\x35\x0f\x25'
b'\xe0\x7e\x21\xc9\x47\xd1\x9e\x33\x76\xf0\x9b\x3c\x1e\x16\x17\x42'
),
)

108
tests/func_pso_auth.py Normal file
View File

@@ -0,0 +1,108 @@
"""
func_pso_auth.py - functions for testing PSO commands
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import pytest
from card_const import KEY_ATTRIBUTES_RSA2K
def _encodeDERLength(length):
if length < 0x80:
return length.to_bytes(1, 'big')
if length < 0x100:
return b'\x81' + length.to_bytes(1, 'big')
return b'\x82' + length.to_bytes(2, 'big')
def get_ec_pso(
card,
key_index,
key_attributes,
key_attribute_caption,
private_key, expected_public_key,
pso_input,
):
"""
If card supports, change key attributes for given key slot, store
given private key, check that the card could derive the expected
public key from it, then call the appropriate PSO for this key slot
and return its result.
Sets key attributes to RSA2K before returning to caller.
Skips the test if initial key attribute change is rejected by the card.
"""
key_attribute_index, control_reference_template, pso_p1, pso_p2 = (
(0xc1, b'\xb6\x00', 0x9e, 0x9a), # Sign
(0xc2, b'\xb8\x00', 0x80, 0x86), # Decrypt
(0xc3, b'\xa4\x00', 0x9e, 0x9a), # Authenticate
)[key_index]
try:
card.cmd_put_data(0x00, key_attribute_index, key_attributes)
except ValueError:
pytest.skip('No %s support' % (key_attribute_caption, ))
try:
private_key_len = len(private_key)
r = card.cmd_put_data_odd(
0x3f,
0xff,
b'\x4d' + _encodeDERLength(private_key_len + 10) +
control_reference_template +
b'\x7f\x48\x02'
b'\x92' + _encodeDERLength(private_key_len) +
b'\x5f\x48' + _encodeDERLength(private_key_len) +
private_key,
)
assert r
r = card.cmd_get_public_key(key_index + 1)
expected_public_key_len = len(expected_public_key)
encoded_expected_public_key_len = _encodeDERLength(
expected_public_key_len,
)
expected_public_key_response = (
b'\x7f\x49' + _encodeDERLength(
expected_public_key_len +
len(encoded_expected_public_key_len) + 1,
) +
b'\x86' + encoded_expected_public_key_len +
expected_public_key
)
assert r == expected_public_key_response
return card.cmd_pso(pso_p1, pso_p2, pso_input)
finally:
card.cmd_put_data(0x00, key_attribute_index, KEY_ATTRIBUTES_RSA2K)
def assert_ec_pso(
card,
key_index,
key_attributes,
key_attribute_caption,
private_key, expected_public_key,
pso_input, expected_pso_output,
):
"""
Calls get_ec_pso and checks if produced output matches the expected value.
"""
r = get_ec_pso(
card=card,
key_index=key_index,
key_attributes=key_attributes,
key_attribute_caption=key_attribute_caption,
private_key=private_key,
expected_public_key=expected_public_key,
pso_input=pso_input,
)
assert r == expected_pso_output

View File

@@ -60,6 +60,7 @@ class OpenPGP_Card(object):
self.__kdf_salt_reset = None
self.__kdf_salt_admin = None
self.is_gnuk = (reader.get_string(2) == "Gnuk Token")
self.is_emulated_gnuk = (reader.get_string(3)[-8:] == "EMULATED")
def configure_with_kdf(self):
kdf_data = self.cmd_get_data(0x00, 0xf9)

View File

@@ -0,0 +1,6 @@
import pytest
@pytest.fixture(scope="module",autouse=True)
def check_emulation(card):
if card.is_emulated_gnuk:
pytest.skip("Emulation requires KDF setup", allow_module_level=True)

6
tests/skip_if_gnuk.py Normal file
View File

@@ -0,0 +1,6 @@
import pytest
@pytest.fixture(scope="module",autouse=True)
def check_gnuk(card):
if card.is_gnuk:
pytest.skip("Gnuk has no support for those features", allow_module_level=True)

View File

@@ -1 +1,2 @@
from skip_if_emulation import *
from card_test_personalize_card import *

View File

@@ -1 +1,2 @@
from skip_if_emulation import *
from card_test_personalize_reset import *

View File

@@ -1 +1,2 @@
from skip_if_emulation import *
from card_test_remove_keys import *

View File

@@ -1 +1,2 @@
from skip_if_emulation import *
from card_test_reset_pw3 import *

View File

@@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_emulation import *
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less import *

9
tests/test_006_pso.py Normal file
View File

@@ -0,0 +1,9 @@
from skip_if_gnuk import *
from card_test_ed25519 import *
from card_test_x25519 import *
from card_test_ansix9p256r1 import *
from card_test_ansix9p384r1 import *
from card_test_ansix9p512r1 import *
from card_test_brainpoolp256r1 import *
from card_test_brainpoolp384r1 import *
from card_test_brainpoolp512r1 import *

View File

@@ -20,5 +20,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_emulation import *
from card_test_keygen import *
from card_test_remove_keys import *

View File

@@ -1 +1,5 @@
from test_005_personalize_admin_less import *
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less import *
from card_test_personalize_reset import *
from card_test_remove_keys import *
from card_test_reset_pw3 import *

View File

@@ -128,7 +128,8 @@ if __name__ == '__main__':
keyno = 0
passwd = None
wait_e = DEFAULT_WAIT_FOR_REENUMERATION
while len(sys.argv) > 3:
skip_check = False
while len(sys.argv) > 1:
option = sys.argv[1]
sys.argv.pop(1)
if option == '-f': # F for Factory setting
@@ -139,15 +140,35 @@ if __name__ == '__main__':
elif option == '-k': # K for Key number
keyno = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-s': # S for skip the check of target
skip_check = True
else:
raise ValueError("unknown option", option)
if not passwd:
passwd = getpass("Admin password: ")
if len(sys.argv) > 1:
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
else:
filename_regnual = "../regnual/regnual.bin"
filename_upgrade = "../src/build/gnuk.bin"
if not filename_regnual.endswith('bin') or not filename_upgrade.endswith('bin'):
print("Both input files must be in binary format (*.bin)!")
exit(1)
if not skip_check:
# More checks
gnuk = get_gnuk_device()
u_target = gnuk.get_string(5).split(b':')[0].decode('UTF-8')
del gnuk
f = open("../src/usb-strings.c.inc","r")
config_str = f.read()
f.close()
conf_options=config_str[config_str.find('/* configure options: "')+23:]
target=conf_options[:conf_options.find(':')]
if target != u_target:
print("Target", target, "!= device info from USB " , u_target)
exit(1)
#
f = open(filename_regnual,"rb")
data_regnual = f.read()
f.close()