Compare commits
24 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49f2544918 | ||
|
|
d156fc6261 | ||
|
|
81d6945081 | ||
|
|
c3e9db14e8 | ||
|
|
9180c35420 | ||
|
|
cc0d59cfe6 | ||
|
|
9c1368fdd0 | ||
|
|
2dd5a76002 | ||
|
|
f68ff0bddc | ||
|
|
add3299306 | ||
|
|
e28ec2c4c4 | ||
|
|
1ba05a0f0f | ||
|
|
2d50795d0a | ||
|
|
fd493562c3 | ||
|
|
16c6af215a | ||
|
|
177ef67edf | ||
|
|
126283b1ac | ||
|
|
076d727061 | ||
|
|
41fa424450 | ||
|
|
940332c47f | ||
|
|
aedf8267ec | ||
|
|
e9d9de3ae2 | ||
|
|
fc109fd8af | ||
|
|
3d06051a32 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ regnual/regnual.elf
|
||||
doc/_build
|
||||
tests/.cache
|
||||
tests/__pycache__
|
||||
tests/.pytest_cache
|
||||
|
||||
58
ChangeLog
58
ChangeLog
@@ -1,3 +1,61 @@
|
||||
2020-01-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.15.
|
||||
|
||||
2020-01-11 Bertrand Jacquin <bertrand@jacquin.bzh>
|
||||
|
||||
* tool/add_openpgp_authkey_from_gpgssh.py: Switch to Python3.
|
||||
* tool/calc_precompute_table_ecc.py: Likewise.
|
||||
* tool/dfuse.py: Likewise.
|
||||
* tool/dump_mem.py: Likewise.
|
||||
* tool/get_raw_public_key.py: Likewise.
|
||||
* tool/pageant_proxy_to_gpg.py: Likewise.
|
||||
|
||||
2019-12-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Update to 1.18.
|
||||
|
||||
2019-06-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/bn.c (bn256_random): More portable.
|
||||
|
||||
2019-04-03 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests: Factor out tests into classes.
|
||||
|
||||
2019-03-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.14.
|
||||
|
||||
* chopstx: Update to 1.14.
|
||||
|
||||
* tool/gnuk_token.py: Add 1209:2440.
|
||||
|
||||
2019-02-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_thread): Clean up the ack button state
|
||||
at reset (by SET_INTERFACE).
|
||||
|
||||
* tool/gnuk_token.py (gnuk_token.__init__): Add back
|
||||
setAltInterface to issue SET_INTERFACE control transfer.
|
||||
|
||||
2019-02-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/gnuk_get_random.py: New.
|
||||
|
||||
* src/openpgp.c (cmd_external_authenticate): move
|
||||
ACKBTN_SUPPORT to...
|
||||
(cmd_get_challenge): ... here.
|
||||
|
||||
* src/gnuk.h (EV_*): Change the values.
|
||||
|
||||
* src/usb-ccid.c (GPG_ACK_TIMEOUT): New.
|
||||
(ccid_thread): Implement timout for the user interaction.
|
||||
|
||||
2019-02-21 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* GNUK_USB_DEVICE_ID: Add 1209:2440.
|
||||
|
||||
2018-12-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.13.
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
0000:0000 0200 Gnuk Emulation Free Software Initiative of Japan
|
||||
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
|
||||
20a0:4211 0200 Nitrokey Start Nitrokey
|
||||
1209:2440 0200 Gnuk Token GnuPG e.V.
|
||||
##########<TAB> ##<TAB> ##########<TAB> #################
|
||||
|
||||
27
NEWS
27
NEWS
@@ -1,6 +1,33 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.15
|
||||
|
||||
Released 2020-01-24, by NIIBE Yutaka
|
||||
|
||||
** Switch to Python3
|
||||
Scripts under tool/ are switched to Python3.
|
||||
Thanks to Bertrand Jacquin.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.18.
|
||||
|
||||
** Tests also support OpenPGPcard
|
||||
Now, a test suite under "tests" may be used to OpenPGPcard.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.14
|
||||
|
||||
Released 2019-03-05, by NIIBE Yutaka
|
||||
|
||||
** Timeout for ACK button support
|
||||
When a user doesn't acknowledge (> 15 seconds), the operation
|
||||
timeouts, and authentication state is cleared.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.14.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.13
|
||||
|
||||
Released 2018-12-26, by NIIBE Yutaka
|
||||
|
||||
33
README
33
README
@@ -1,14 +1,14 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.2.13
|
||||
2018-12-26
|
||||
Version 1.2.15
|
||||
2020-01-24
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
This is the release of Gnuk, version 1.2.13, which has major
|
||||
This is the release of Gnuk, version 1.2.15, 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
|
||||
@@ -75,7 +75,7 @@ A1: Gnuk version 1.0 only supports RSA-2048.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so for RSA-2048.
|
||||
It takes more than 8 secondd for RSA-4096.
|
||||
It takes more than 8 seconds for RSA-4096.
|
||||
|
||||
Q3: What's your recommendation for target board?
|
||||
A3: Orthodox choice is Olimex STM32-H103.
|
||||
@@ -85,7 +85,7 @@ A3: Orthodox choice is Olimex STM32-H103.
|
||||
choice for experiment.
|
||||
|
||||
Q4: What's version of GnuPG are you using?
|
||||
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.18.
|
||||
A4: In Debian GNU/Linux system, I use GnuPG modern 2.2.12.
|
||||
|
||||
Q5: What's version of pcscd and libccid are you using?
|
||||
A5: I don't use them, pcscd and libccid are optional, you can use Gnuk
|
||||
@@ -211,8 +211,7 @@ script prepending 'bash' before './configure'.
|
||||
|
||||
Some tools are written in Python. If your Python is not installed as
|
||||
/usr/bin/python, please prepend 'python' for your command invocation.
|
||||
Python 2.7 and PyUSB 0.4.3 is assumed. I also use Python 3.5 and
|
||||
PyUSB 1.0.0.
|
||||
I use Python 3.7 and PyUSB 1.0.0.
|
||||
|
||||
|
||||
Source code
|
||||
@@ -249,7 +248,7 @@ External source code
|
||||
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* chopstx/ -- Chopstx 1.13
|
||||
* chopstx/ -- Chopstx 1.18
|
||||
|
||||
We use Chopstx as the kernel for Gnuk.
|
||||
|
||||
@@ -371,10 +370,10 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
On Debian we can install the packages of gcc-arm-none-eabi,
|
||||
gdb-arm-none-eabi and its friends. I'm using:
|
||||
|
||||
binutils-arm-none-eabi 2.31.1-2+10
|
||||
gcc-arm-none-eabi 15:7-2018-q2-4
|
||||
gdb-arm-none-eabi 7.12-6+9+b2
|
||||
libnewlib-arm-none-eabi 3.0.0.20180802-2
|
||||
binutils-arm-none-eabi 2.31.1-12+11
|
||||
gcc-arm-none-eabi 15:7-2018-q2-6
|
||||
gdb-multiarch 8.2.1-1
|
||||
libnewlib-arm-none-eabi 3.1.0.20181231-1
|
||||
|
||||
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
|
||||
GNU Toolchain for 'arm-none-eabi' target.
|
||||
@@ -432,10 +431,12 @@ OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
|
||||
-c "program build/gnuk.elf verify reset exit"
|
||||
|
||||
|
||||
|
||||
STBee
|
||||
-----
|
||||
|
||||
Note that this is only for your experiment; Your private key materials
|
||||
on the board can be accessed by DfuSe.
|
||||
|
||||
Reset the board with "USER" switch pushed. Type following to write
|
||||
to flash:
|
||||
|
||||
@@ -474,7 +475,7 @@ protect, killing DfuSe and accessing by JTAG debugger is recommended.
|
||||
This is completely optional.
|
||||
|
||||
For this procedure, you need python and pyscard (python-pyscard
|
||||
package in Debian) or PyUSB 0.4.3 (python-usb package in Debian).
|
||||
package in Debian) or PyUSB (python-usb package in Debian).
|
||||
|
||||
(1) [pyscard] Stop scdaemon
|
||||
[PyUSB] Stop the pcsc daemon.
|
||||
@@ -486,7 +487,7 @@ Exception" by "Sharing violation".
|
||||
|
||||
In case of PyUSB tool, you need to stop pcscd.
|
||||
|
||||
# /etc/init.d/pcscd stop
|
||||
# systemctl stop pcscd
|
||||
|
||||
|
||||
(2) [Optional] Write fixed serial number
|
||||
@@ -599,7 +600,7 @@ You can get it by:
|
||||
$ git clone https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
|
||||
|
||||
It's also available at: www.gniibe.org
|
||||
You can browse at: https://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
|
||||
You can browse at: https://git.gniibe.org/cgit/gnuk/gnuk.git/
|
||||
|
||||
I put Chopstx as a submodule of Git. Please do this:
|
||||
|
||||
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: b6c90e3df4...cc49f4ef23
23
src/bn.c
23
src/bn.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* bn.c -- 256-bit (and 512-bit) bignum calculation
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2013, 2014, 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -412,17 +413,15 @@ bn256_cmp (const bn256 *A, const bn256 *B)
|
||||
void
|
||||
bn256_random (bn256 *X)
|
||||
{
|
||||
const uint8_t *rand = random_bytes_get ();
|
||||
int i, j;
|
||||
const uint8_t *rand;
|
||||
|
||||
X->word[7] = ((uint32_t *)rand)[7];
|
||||
X->word[6] = ((uint32_t *)rand)[6];
|
||||
X->word[5] = ((uint32_t *)rand)[5];
|
||||
X->word[4] = ((uint32_t *)rand)[4];
|
||||
X->word[3] = ((uint32_t *)rand)[3];
|
||||
X->word[2] = ((uint32_t *)rand)[2];
|
||||
X->word[1] = ((uint32_t *)rand)[1];
|
||||
X->word[0] = ((uint32_t *)rand)[0];
|
||||
|
||||
random_bytes_free (rand);
|
||||
for (i = 0; i < 256/256; i++)
|
||||
{
|
||||
rand = random_bytes_get ();
|
||||
for (j = 0; j < BN256_WORDS; j++)
|
||||
X->word[i*BN256_WORDS+j] = ((uint32_t *)rand)[j];
|
||||
random_bytes_free (rand);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
16
src/gnuk.h
16
src/gnuk.h
@@ -24,18 +24,18 @@ extern struct apdu apdu;
|
||||
void ccid_card_change_signal (int how);
|
||||
|
||||
/* CCID thread */
|
||||
#define EV_RX_DATA_READY 1 /* USB Rx data available */
|
||||
#define EV_EXEC_FINISHED 2 /* OpenPGPcard Execution finished */
|
||||
#define EV_CARD_CHANGE 1
|
||||
#define EV_TX_FINISHED 2 /* CCID Tx finished */
|
||||
#define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */
|
||||
#define EV_TX_FINISHED 8 /* CCID Tx finished */
|
||||
#define EV_CARD_CHANGE 16
|
||||
#define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */
|
||||
#define EV_RX_DATA_READY 16 /* USB Rx data available */
|
||||
|
||||
/* OpenPGPcard thread */
|
||||
#define EV_PINPAD_INPUT_DONE 1
|
||||
#define EV_EXIT 2
|
||||
#define EV_MODIFY_CMD_AVAILABLE 1
|
||||
#define EV_VERIFY_CMD_AVAILABLE 2
|
||||
#define EV_CMD_AVAILABLE 4
|
||||
#define EV_VERIFY_CMD_AVAILABLE 8
|
||||
#define EV_MODIFY_CMD_AVAILABLE 16
|
||||
#define EV_EXIT 8
|
||||
#define EV_PINPAD_INPUT_DONE 16
|
||||
|
||||
/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */
|
||||
#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -1388,13 +1389,6 @@ cmd_external_authenticate (struct eventflag *ccid_comm)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
r = rsa_verify (pubkey, FIRMWARE_UPDATE_KEY_CONTENT_LEN,
|
||||
challenge, signature);
|
||||
random_bytes_free (challenge);
|
||||
@@ -1432,6 +1426,13 @@ cmd_get_challenge (struct eventflag *ccid_comm)
|
||||
if (challenge)
|
||||
random_bytes_free (challenge);
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
challenge = random_bytes_get ();
|
||||
memcpy (res_APDU, challenge, len);
|
||||
res_APDU_size = len;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* usb-ccid.c -- USB CCID protocol handling
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
|
||||
* 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -190,6 +191,7 @@ struct ccid {
|
||||
uint32_t state : 4;
|
||||
uint32_t err : 1;
|
||||
uint32_t tx_busy : 1;
|
||||
uint32_t timeout_cnt: 3;
|
||||
|
||||
uint8_t *p;
|
||||
size_t len;
|
||||
@@ -1577,7 +1579,7 @@ ccid_notify_slot_change (struct ccid *c)
|
||||
#define USB_CCID_TIMEOUT (1950*1000)
|
||||
|
||||
#define GPG_THREAD_TERMINATED 0xffff
|
||||
|
||||
#define GPG_ACK_TIMEOUT 0x6600
|
||||
|
||||
extern uint32_t bDeviceState;
|
||||
extern void usb_device_reset (struct usb_dev *dev);
|
||||
@@ -1728,6 +1730,7 @@ ccid_thread (void *arg)
|
||||
struct usb_dev dev;
|
||||
struct ccid *c = &ccid;
|
||||
uint32_t *timeout_p;
|
||||
int ackbtn_active = 0;
|
||||
|
||||
(void)arg;
|
||||
|
||||
@@ -1749,6 +1752,13 @@ ccid_thread (void *arg)
|
||||
struct ep_out *epo = &endpoint_out;
|
||||
struct apdu *a = &apdu;
|
||||
|
||||
if (ackbtn_active)
|
||||
{
|
||||
ackbtn_active = 0;
|
||||
ackbtn_disable ();
|
||||
led_blink (LED_WAIT_FOR_BUTTON);
|
||||
}
|
||||
|
||||
epi_init (epi, ENDP1, c);
|
||||
epo_init (epo, ENDP1, c);
|
||||
apdu_init (a);
|
||||
@@ -1774,7 +1784,8 @@ ccid_thread (void *arg)
|
||||
eventflag_set_mask (&c->ccid_comm, c->tx_busy ? EV_TX_FINISHED : ~0);
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
chopstx_poll (timeout_p, CCID_POLL_NUM - c->tx_busy, ccid_poll);
|
||||
chopstx_poll (timeout_p, CCID_POLL_NUM - (c->tx_busy || !ackbtn_active),
|
||||
ccid_poll);
|
||||
#else
|
||||
chopstx_poll (timeout_p, CCID_POLL_NUM, ccid_poll);
|
||||
#endif
|
||||
@@ -1802,9 +1813,10 @@ ccid_thread (void *arg)
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (!c->tx_busy && ack_intr.ready)
|
||||
{
|
||||
ackbtn_active = 0;
|
||||
ackbtn_disable ();
|
||||
chopstx_intr_done (&ack_intr);
|
||||
led_blink (LED_WAIT_FOR_BUTTON);
|
||||
chopstx_intr_done (&ack_intr);
|
||||
if (c->ccid_state == CCID_STATE_ACK_REQUIRED_1)
|
||||
goto exec_done;
|
||||
|
||||
@@ -1813,7 +1825,11 @@ ccid_thread (void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
if (timeout == 0)
|
||||
{
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
c->timeout_cnt++;
|
||||
}
|
||||
m = eventflag_get (&c->ccid_comm);
|
||||
|
||||
if (m == EV_CARD_CHANGE)
|
||||
@@ -1836,7 +1852,11 @@ ccid_thread (void *arg)
|
||||
ccid_notify_slot_change (c);
|
||||
}
|
||||
else if (m == EV_RX_DATA_READY)
|
||||
c->ccid_state = ccid_handle_data (c);
|
||||
{
|
||||
c->ccid_state = ccid_handle_data (c);
|
||||
timeout = 0;
|
||||
c->timeout_cnt = 0;
|
||||
}
|
||||
else if (m == EV_EXEC_FINISHED)
|
||||
if (c->ccid_state == CCID_STATE_EXECUTE)
|
||||
{
|
||||
@@ -1885,6 +1905,7 @@ ccid_thread (void *arg)
|
||||
if (c->ccid_state == CCID_STATE_EXECUTE)
|
||||
{
|
||||
ackbtn_enable ();
|
||||
ackbtn_active = 1;
|
||||
led_blink (LED_WAIT_FOR_BUTTON);
|
||||
c->ccid_state = CCID_STATE_ACK_REQUIRED_0;
|
||||
ccid_send_data_block_time_extension (c);
|
||||
@@ -1907,7 +1928,20 @@ ccid_thread (void *arg)
|
||||
ccid_prepare_receive (c);
|
||||
}
|
||||
else /* Timeout */
|
||||
c->ccid_state = ccid_handle_timeout (c);
|
||||
{
|
||||
if (c->timeout_cnt == 7
|
||||
&& c->ccid_state == CCID_STATE_ACK_REQUIRED_1)
|
||||
{
|
||||
ackbtn_active = 0;
|
||||
ackbtn_disable ();
|
||||
led_blink (LED_WAIT_FOR_BUTTON);
|
||||
c->a->sw = GPG_ACK_TIMEOUT;
|
||||
c->a->res_apdu_data_len = 0;
|
||||
goto exec_done;
|
||||
}
|
||||
else
|
||||
c->ccid_state = ccid_handle_timeout (c);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->application)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
card_reader.py - a library for smartcard reader
|
||||
|
||||
Copyright (C) 2016, 2017 Free Software Initiative of Japan
|
||||
Copyright (C) 2016, 2017, 2019 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -25,6 +25,7 @@ from struct import pack
|
||||
from usb.util import find_descriptor, claim_interface, get_string, \
|
||||
endpoint_type, endpoint_direction, \
|
||||
ENDPOINT_TYPE_BULK, ENDPOINT_OUT, ENDPOINT_IN
|
||||
from binascii import hexlify
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
@@ -168,7 +169,7 @@ class CardReader(object):
|
||||
return status
|
||||
|
||||
def ccid_power_on(self):
|
||||
msg = ccid_compose(0x62, self.__seq, rsv=1) # Vcc=5V
|
||||
msg = ccid_compose(0x62, self.__seq, rsv=2) # Vcc=3.3V
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data = self.ccid_get_result()
|
||||
@@ -237,16 +238,21 @@ class CardReader(object):
|
||||
|
||||
def send_tpdu(self, info=None, more=0, response_time_ext=0,
|
||||
edc_error=0, no_error=0):
|
||||
rsv = 0
|
||||
if info:
|
||||
data = compose_i_block(self.ns, info, more)
|
||||
elif response_time_ext:
|
||||
# compose S-block
|
||||
data = b"\x00\xE3\x00\xE3"
|
||||
# compose S-block response
|
||||
pcb = 0xe3
|
||||
bwi_byte = bytes([response_time_ext])
|
||||
edc = compute_edc(pcb, bwi_byte)
|
||||
data = bytes([0, pcb, 1]) + bwi_byte + bytes([edc])
|
||||
rsv = response_time_ext
|
||||
elif edc_error:
|
||||
data = compose_r_block(self.nr, edc_error=1)
|
||||
elif no_error:
|
||||
data = compose_r_block(self.nr)
|
||||
msg = ccid_compose(0x6f, self.__seq, data=data)
|
||||
msg = ccid_compose(0x6f, self.__seq, rsv=rsv, data=data)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
|
||||
@@ -277,7 +283,7 @@ class CardReader(object):
|
||||
res = b""
|
||||
while True:
|
||||
if is_s_block_time_ext(blk):
|
||||
self.send_tpdu(response_time_ext=1)
|
||||
self.send_tpdu(response_time_ext=blk[3])
|
||||
elif is_i_block_last(blk):
|
||||
self.nr = self.nr ^ 1
|
||||
if is_edc_error(blk):
|
||||
|
||||
36
tests/card_test_kdf_full.py
Normal file
36
tests/card_test_kdf_full.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
card_test_kdf_full.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_KDF_full(object):
|
||||
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_full(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_FULL)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
35
tests/card_test_kdf_single.py
Normal file
35
tests/card_test_kdf_single.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
card_test_kdf_single.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_KDF_Single(object):
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_single(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_SINGLE)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
84
tests/card_test_keygen.py
Normal file
84
tests/card_test_keygen.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
card_test_keygen.py - test key generation
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 binascii import hexlify
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_Keygen(object):
|
||||
def test_keygen_1(self, card):
|
||||
pk = card.cmd_genkey(1)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xce, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_2(self, card):
|
||||
pk = card.cmd_genkey(2)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xcf, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_3(self, card):
|
||||
pk = card.cmd_genkey(3)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xd0, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_verify_pw1(self, card):
|
||||
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_signature_sigkey(self, card):
|
||||
msg = b"Sign me please"
|
||||
pk = card.cmd_get_public_key(1)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_pso(0x9e, 0x9a, digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_decryption(self, card):
|
||||
msg = b"encrypt me please"
|
||||
pk = card.cmd_get_public_key(2)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
ciphertext = rsa_keys.encrypt_with_pubkey(pk_info, msg)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == msg
|
||||
|
||||
def test_signature_authkey(self, card):
|
||||
msg = b"Sign me please to authenticate"
|
||||
pk = card.cmd_get_public_key(3)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_internal_authenticate(digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
312
tests/card_test_personalize_admin_less.py
Normal file
312
tests/card_test_personalize_admin_less.py
Normal file
@@ -0,0 +1,312 @@
|
||||
"""
|
||||
card_test_personalize_admin_less.py - test admin-less mode
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_Personalize_Adminless(object):
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_rsa_import_key_1(self, card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(self, card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(self, card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(self, card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(self, card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(self, card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(self, card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(self, card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(self, card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(self, card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(self, card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(self, card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(self, card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
# Changing PW1 to admin-less mode
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
# Now, it's admin-less mode, auth-status admin cleared
|
||||
|
||||
def test_verify_pw3_fail_1(self, card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = False
|
||||
assert not v
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(self, card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(self, card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_admin_less_1(self, card):
|
||||
v = card.verify(3, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(self, card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(self, card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
# Changing PW1, auth status for admin cleared
|
||||
def test_login_put_fail(self, card):
|
||||
try:
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(self, card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_fail_2(self, card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = e.args[0]
|
||||
assert v == "6982"
|
||||
|
||||
def test_sign_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
# Since forcesig setting, failed
|
||||
def test_sign_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
try:
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_ds_counter_1(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x01'
|
||||
|
||||
def test_sign_auth_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
|
||||
def test_verify_pw3_admin_less_2(self, card):
|
||||
v = card.verify(3, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(self, card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(self, card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(self, card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
# Setting PW3, changed to admin-full mode
|
||||
|
||||
def test_setup_pw3_1(self, card):
|
||||
r = card.change_passwd(3, PW1_TEST2, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(self, card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(self, card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(self, card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(self, card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(self, card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(self, card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
277
tests/card_test_personalize_card.py
Normal file
277
tests/card_test_personalize_card.py
Normal file
@@ -0,0 +1,277 @@
|
||||
"""
|
||||
card_test_personalize_card.py - test personalizing card
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_Personalize_Card(object):
|
||||
def test_setup_pw3_0(self, card):
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(self, card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(self, card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(self, card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_rsa_import_key_1(self, card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(self, card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(self, card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(self, card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(self, card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(self, card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(self, card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(self, card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(self, card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(self, card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(self, card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(self, card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(self, card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(self, card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(self, card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(self, card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(self, card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(self, card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_1(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST0, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(self, card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(self, card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(self, card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(self, card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(self, card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(self, card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_sign_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_ds_counter_1(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x02'
|
||||
|
||||
def test_sign_auth_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
82
tests/card_test_personalize_reset.py
Normal file
82
tests/card_test_personalize_reset.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
card_test_personalize_reset.py - test resetting personalization of card
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Personalize_Reset(object):
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
try:
|
||||
# Gnuk
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"")
|
||||
except ValueError:
|
||||
# OpenPGP card which doesn't allow b""
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"9")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x00")
|
||||
assert r
|
||||
|
||||
def test_setup_pw3_0(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST0, FACTORY_PASSPHRASE_PW3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST4, FACTORY_PASSPHRASE_PW1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_delete_reset_code(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xd3, b"")
|
||||
assert r
|
||||
45
tests/card_test_remove_keys.py
Normal file
45
tests/card_test_remove_keys.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
card_test_remove_keys.py - test removing keys on card
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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/>.
|
||||
"""
|
||||
|
||||
# Remove a key material on card by changing algorithm attributes of the key
|
||||
|
||||
from card_const import *
|
||||
|
||||
class Test_Remove_Keys(object):
|
||||
|
||||
def test_rsa_keyattr_change_1(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_keyattr_change_2(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_keyattr_change_3(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
46
tests/card_test_reset_pw3.py
Normal file
46
tests/card_test_reset_pw3.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
card_test_reset_pw3.py - test resetting pw3
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 card_const import *
|
||||
import pytest
|
||||
|
||||
class Test_Reset_PW3(object):
|
||||
# Gnuk specific feature of clear PW3
|
||||
def test_setup_pw3_null(self, card):
|
||||
if card.is_gnuk:
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, None)
|
||||
assert r
|
||||
else:
|
||||
pytest.skip("Gnuk only feature of clearing PW3")
|
||||
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
# Check PW1 again to see the possiblity of admin-less mode
|
||||
def test_verify_pw1(self, card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
@@ -16,3 +16,4 @@ def card():
|
||||
card.cmd_select_openpgp()
|
||||
yield card
|
||||
del card
|
||||
reader.ccid_power_off()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
openpgp_card.py - a library for OpenPGP card
|
||||
|
||||
Copyright (C) 2011, 2012, 2013, 2015, 2016, 2018
|
||||
Copyright (C) 2011, 2012, 2013, 2015, 2016, 2018, 2019
|
||||
Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
@@ -59,6 +59,7 @@ class OpenPGP_Card(object):
|
||||
self.__kdf_salt_user = None
|
||||
self.__kdf_salt_reset = None
|
||||
self.__kdf_salt_admin = None
|
||||
self.is_gnuk = (reader.get_string(2) == "Gnuk Token")
|
||||
|
||||
def configure_with_kdf(self):
|
||||
kdf_data = self.cmd_get_data(0x00, 0xf9)
|
||||
@@ -338,16 +339,20 @@ class OpenPGP_Card(object):
|
||||
data = b'\xb8\x00'
|
||||
else:
|
||||
data = b'\xa4\x00'
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data)
|
||||
if self.__reader.is_tpdu_reader():
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data, le=512)
|
||||
else:
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data)
|
||||
sw = self.__reader.send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
if len(sw) < 2:
|
||||
raise ValueError(sw)
|
||||
if sw[0] == 0x90 and sw[1] == 0x00:
|
||||
return b""
|
||||
elif sw[0] != 0x61:
|
||||
if sw[-2] == 0x61:
|
||||
pk = self.cmd_get_response(sw[1])
|
||||
elif sw[-2] == 0x90 and sw[-1] == 0x00:
|
||||
pk = sw
|
||||
else:
|
||||
raise ValueError("%02x%02x" % (sw[0], sw[1]))
|
||||
pk = self.cmd_get_response(sw[1])
|
||||
return (pk[9:9+256], pk[9+256+2:9+256+2+3])
|
||||
return (pk[9:9+256], pk[9+256+2:-2])
|
||||
|
||||
def cmd_get_public_key(self, keyno):
|
||||
if keyno == 1:
|
||||
@@ -358,10 +363,9 @@ class OpenPGP_Card(object):
|
||||
data = b'\xa4\x00'
|
||||
if self.__reader.is_tpdu_reader():
|
||||
cmd_data = iso7816_compose(0x47, 0x81, 0, data, le=512)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
else:
|
||||
cmd_data = iso7816_compose(0x47, 0x81, 0, data)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
if len(r) < 2:
|
||||
raise ValueError(r)
|
||||
sw = r[-2:]
|
||||
|
||||
6
tests/skip_gnuk_only_tests.py
Normal file
6
tests/skip_gnuk_only_tests.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="module",autouse=True)
|
||||
def check_gnuk(card):
|
||||
if not card.is_gnuk:
|
||||
pytest.skip("Gnuk only feature", allow_module_level=True)
|
||||
@@ -50,12 +50,16 @@ def test_sex(card):
|
||||
def test_name_lang_sex(card):
|
||||
name = b""
|
||||
lang = b""
|
||||
lang_de = b"de"
|
||||
sex = b"9"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
expected_de = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang_de)) + lang_de \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == b'' or name_lang_sex == expected
|
||||
assert name_lang_sex == b'' or name_lang_sex == expected or name_lang_sex == expected_de
|
||||
|
||||
def test_app_data(card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
@@ -140,7 +144,8 @@ def test_historical_bytes(card):
|
||||
h = get_data_object(card, 0x5f52)
|
||||
assert h == b'\x001\xc5s\xc0\x01@\x05\x90\x00' or \
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x00\x90\x00' or \
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x05\x90\x00'
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x05\x90\x00' or \
|
||||
h == b'\x00\x31\xf5\x73\xc0\x01\x60\x05\x90\x00'
|
||||
|
||||
def test_extended_capabilities(card):
|
||||
a = get_data_object(card, 0xc0)
|
||||
|
||||
@@ -1,276 +1 @@
|
||||
"""
|
||||
test_personalize_card.py - test personalizing card
|
||||
|
||||
Copyright (C) 2016, 2018 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
def test_setup_pw3_0(card):
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_login_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_rsa_import_key_1(card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
def test_setup_pw1_0(card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_1(card):
|
||||
r = card.change_passwd(3, PW3_TEST0, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_sign_0(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_1(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_ds_counter_1(card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x02'
|
||||
|
||||
def test_sign_auth_0(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
from card_test_personalize_card import *
|
||||
|
||||
@@ -1,81 +1 @@
|
||||
"""
|
||||
test_personalize_reset.py - test resetting personalization of card
|
||||
|
||||
Copyright (C) 2016, 2018 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
def test_login_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"")
|
||||
assert r
|
||||
|
||||
def test_name_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"")
|
||||
assert r
|
||||
|
||||
def test_lang_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"")
|
||||
assert r
|
||||
|
||||
def test_sex_put(card):
|
||||
try:
|
||||
# Gnuk
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"")
|
||||
except ValueError:
|
||||
# OpenPGP card which doesn't allow b""
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"9")
|
||||
assert r
|
||||
|
||||
def test_url_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x00")
|
||||
assert r
|
||||
|
||||
def test_setup_pw3_0(card):
|
||||
r = card.change_passwd(3, PW3_TEST0, FACTORY_PASSPHRASE_PW3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_0(card):
|
||||
r = card.change_passwd(1, PW1_TEST4, FACTORY_PASSPHRASE_PW1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_delete_reset_code(card):
|
||||
r = card.cmd_put_data(0x00, 0xd3, b"")
|
||||
assert r
|
||||
from card_test_personalize_reset import *
|
||||
|
||||
@@ -1,43 +1 @@
|
||||
"""
|
||||
test_remove_keys.py - test removing keys on card
|
||||
|
||||
Copyright (C) 2016, 2018 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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/>.
|
||||
"""
|
||||
|
||||
# Remove a key material on card by changing algorithm attributes of the key
|
||||
|
||||
from card_const import *
|
||||
|
||||
def test_rsa_keyattr_change_1(card):
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_keyattr_change_2(card):
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_keyattr_change_3(card):
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
from card_test_remove_keys import *
|
||||
|
||||
@@ -1,41 +1 @@
|
||||
"""
|
||||
test_004_reset_pw3.py - test resetting pw3
|
||||
|
||||
Copyright (C) 2018 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
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 card_const import *
|
||||
|
||||
# Gnuk specific feature of clear PW3
|
||||
def test_setup_pw3_null(card):
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, None)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3(card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
# Check PW1 again to see the possiblity of admin-less mode
|
||||
def test_verify_pw1(card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2(card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
from card_test_reset_pw3 import *
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_005_personalize_admin_less.py - test admin-less mode
|
||||
|
||||
Copyright (C) 2016, 2018 g10 Code GmbH
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -20,291 +20,9 @@ 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 struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
from skip_gnuk_only_tests import *
|
||||
|
||||
def test_verify_pw3_0(card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_rsa_import_key_1(card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
# Changing PW1 to admin-less mode
|
||||
|
||||
def test_setup_pw1_0(card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
# Now, it's admin-less mode, auth-status admin cleared
|
||||
|
||||
def test_verify_pw3_fail_1(card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = False
|
||||
assert not v
|
||||
|
||||
def test_verify_pw1_0(card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_admin_less_1(card):
|
||||
v = card.verify(3, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
# Changing PW1, auth status for admin cleared
|
||||
def test_login_put_fail(card):
|
||||
try:
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_verify_pw1_2(card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_fail_2(card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = e.args[0]
|
||||
assert v == "6982"
|
||||
|
||||
def test_sign_0(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
# Since forcesig setting, failed
|
||||
def test_sign_1(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
try:
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_ds_counter_1(card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x01'
|
||||
|
||||
def test_sign_auth_0(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
|
||||
def test_verify_pw3_admin_less_2(card):
|
||||
v = card.verify(3, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_login_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
# Setting PW3, changed to admin-full mode
|
||||
|
||||
def test_setup_pw3_1(card):
|
||||
r = card.change_passwd(3, PW1_TEST2, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
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 *
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
test_002_personalize_reset.py
|
||||
@@ -1 +0,0 @@
|
||||
test_003_remove_keys.py
|
||||
@@ -1 +0,0 @@
|
||||
test_004_reset_pw3.py
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_005_keygen.py - test key generation
|
||||
|
||||
Copyright (C) 2018 g10 Code GmbH
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -20,64 +20,5 @@ 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 binascii import hexlify
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
|
||||
def test_keygen_1(card):
|
||||
pk = card.cmd_genkey(1)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xce, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_2(card):
|
||||
pk = card.cmd_genkey(2)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xcf, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_3(card):
|
||||
pk = card.cmd_genkey(3)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xd0, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_verify_pw1(card):
|
||||
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_signature_sigkey(card):
|
||||
msg = b"Sign me please"
|
||||
pk = card.cmd_get_public_key(1)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_pso(0x9e, 0x9a, digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(card):
|
||||
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_decryption(card):
|
||||
msg = b"encrypt me please"
|
||||
pk = card.cmd_get_public_key(2)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
|
||||
ciphertext = rsa_keys.encrypt_with_pubkey(pk_info, msg)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == msg
|
||||
|
||||
def test_signature_authkey(card):
|
||||
msg = b"Sign me please to authenticate"
|
||||
pk = card.cmd_get_public_key(3)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_internal_authenticate(digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
from card_test_keygen import *
|
||||
from card_test_remove_keys import *
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
test_003_remove_keys.py
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_007_kdf_full.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018 g10 Code GmbH
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -20,15 +20,10 @@ 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 card_const import *
|
||||
from constants_for_test import *
|
||||
from skip_gnuk_only_tests import *
|
||||
|
||||
def test_verify_pw3(card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_full(card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_FULL)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
from card_test_kdf_full import *
|
||||
from card_test_personalize_card import *
|
||||
from card_test_personalize_reset import *
|
||||
from card_test_remove_keys import *
|
||||
from card_test_reset_pw3 import *
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
test_001_personalize_card.py
|
||||
@@ -1 +0,0 @@
|
||||
test_002_personalize_reset.py
|
||||
@@ -1 +0,0 @@
|
||||
test_003_remove_keys.py
|
||||
@@ -1 +0,0 @@
|
||||
test_004_reset_pw3.py
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_012_kdf_single.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018 g10 Code GmbH
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -20,15 +20,10 @@ 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 card_const import *
|
||||
from constants_for_test import *
|
||||
from skip_gnuk_only_tests import *
|
||||
|
||||
def test_verify_pw3(card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_single(card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_SINGLE)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
from card_test_kdf_single import *
|
||||
from card_test_personalize_card import *
|
||||
from card_test_personalize_reset import *
|
||||
from card_test_remove_keys import *
|
||||
from card_test_reset_pw3 import *
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
test_001_personalize_card.py
|
||||
@@ -1 +0,0 @@
|
||||
test_002_personalize_reset.py
|
||||
@@ -1 +0,0 @@
|
||||
test_003_remove_keys.py
|
||||
@@ -1 +0,0 @@
|
||||
test_004_reset_pw3.py
|
||||
@@ -1 +0,0 @@
|
||||
test_005_personalize_admin_less.py
|
||||
1
tests/test_021_personalize_admin_less.py
Normal file
1
tests/test_021_personalize_admin_less.py
Normal file
@@ -0,0 +1 @@
|
||||
from test_005_personalize_admin_less import *
|
||||
@@ -1 +0,0 @@
|
||||
test_002_personalize_reset.py
|
||||
@@ -1 +0,0 @@
|
||||
test_003_remove_keys.py
|
||||
@@ -1 +0,0 @@
|
||||
test_004_reset_pw3.py
|
||||
@@ -20,6 +20,8 @@ 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_gnuk_only_tests import *
|
||||
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
|
||||
@@ -109,15 +109,15 @@ def build_rsakey_from_ssh_key_under_gpg_agent(g, timestamp=None):
|
||||
# The information is in SEXP format, extract N and E
|
||||
s = sexp(pubkey_info_str)
|
||||
if s[0] != 'public-key':
|
||||
print s
|
||||
print(s)
|
||||
exit(1)
|
||||
rsa = s[1]
|
||||
if rsa[0] != 'rsa':
|
||||
print rsa
|
||||
print(rsa)
|
||||
exit(1)
|
||||
n_x = rsa[1]
|
||||
if n_x[0] != 'n':
|
||||
print n_x
|
||||
print(n_x)
|
||||
exit(1)
|
||||
n_byte_str = n_x[1]
|
||||
while n_byte_str[0] == '\x00':
|
||||
@@ -125,7 +125,7 @@ def build_rsakey_from_ssh_key_under_gpg_agent(g, timestamp=None):
|
||||
n = n_byte_str
|
||||
e_x = rsa[2]
|
||||
if e_x[0] != 'e':
|
||||
print e_x
|
||||
print(e_x)
|
||||
exit(1)
|
||||
e = e_x[1]
|
||||
if not timestamp:
|
||||
|
||||
@@ -8,21 +8,21 @@ def print_nG(n):
|
||||
nGy_str = "%064x" % nG.y()
|
||||
print256(nGx_str)
|
||||
print256(nGy_str)
|
||||
print
|
||||
print()
|
||||
|
||||
def print256(s):
|
||||
print("0x%s, 0x%s, 0x%s, 0x%s," % (s[56:64], s[48:56], s[40:48], s[32:40]))
|
||||
print("0x%s, 0x%s, 0x%s, 0x%s" % (s[24:32], s[16:24], s[8:16], s[0:8]))
|
||||
print
|
||||
print()
|
||||
|
||||
|
||||
for i in range(1,16):
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000L + (i & 4) * 0x40000000000000000000000000000000L + (i & 8) * 0x200000000000000000000000000000000000000000000000L
|
||||
print "%064x" % n
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000 + (i & 4) * 0x40000000000000000000000000000000 + (i & 8) * 0x200000000000000000000000000000000000000000000000
|
||||
print("%064x" % n)
|
||||
print_nG(n)
|
||||
|
||||
for i in range(1,16):
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000L + (i & 4) * 0x40000000000000000000000000000000L + (i & 8) * 0x200000000000000000000000000000000000000000000000L
|
||||
n = n * 0x100000000L
|
||||
print "%064x" % n
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000 + (i & 4) * 0x40000000000000000000000000000000 + (i & 8) * 0x200000000000000000000000000000000000000000000000
|
||||
n = n * 0x100000000
|
||||
print("%064x" % n)
|
||||
print_nG(n)
|
||||
|
||||
@@ -104,9 +104,9 @@ class DFU_STM32(object):
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != DFU_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
raise ValueError("Wrong interface class")
|
||||
if interface.interfaceSubClass != DFU_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
raise ValueError("Wrong interface sub class")
|
||||
self.__protocol = interface.interfaceProtocol
|
||||
self.__devhandle = device.open()
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
@@ -170,7 +170,7 @@ class DFU_STM32(object):
|
||||
while s[4] == STATE_DFU_DOWNLOAD_BUSY:
|
||||
time.sleep(0.1)
|
||||
s = self.ll_get_status()
|
||||
raise ValueError, "Read memory failed (%d)" % s[0]
|
||||
raise ValueError("Read memory failed (%d)" % s[0])
|
||||
|
||||
def dfuse_set_address_pointer(self, address):
|
||||
bytes = get_four_bytes (address)
|
||||
@@ -181,7 +181,7 @@ class DFU_STM32(object):
|
||||
time.sleep(0.1)
|
||||
s = self.ll_get_status()
|
||||
if s[4] != STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise ValueError, "Set Address Pointer failed"
|
||||
raise ValueError("Set Address Pointer failed")
|
||||
|
||||
def dfuse_erase(self, address):
|
||||
bytes = get_four_bytes (address)
|
||||
@@ -191,7 +191,7 @@ class DFU_STM32(object):
|
||||
time.sleep(0.1)
|
||||
s = self.ll_get_status()
|
||||
if s[4] != STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise ValueError, "Erase failed"
|
||||
raise ValueError("Erase failed")
|
||||
|
||||
def dfuse_write_memory(self, block):
|
||||
blocknum = self.__blocknum
|
||||
@@ -202,7 +202,7 @@ class DFU_STM32(object):
|
||||
time.sleep(0.1)
|
||||
s = self.ll_get_status()
|
||||
if s[4] != STATE_DFU_DOWNLOAD_IDLE:
|
||||
raise ValueError, "Write memory failed"
|
||||
raise ValueError("Write memory failed")
|
||||
|
||||
def download(self, ih):
|
||||
# First, erase pages
|
||||
@@ -280,7 +280,7 @@ class DFU_STM32(object):
|
||||
elif s[4] == STATE_DFU_MANIFEST_WAIT_RESET:
|
||||
self.__devhandle.reset()
|
||||
elif s[4] != STATE_DFU_IDLE:
|
||||
raise ValueError, "write failed (%d)." % s[4]
|
||||
raise ValueError("write failed (%d)." % s[4])
|
||||
else:
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
@@ -315,7 +315,7 @@ class DFU_STM32(object):
|
||||
j = 0
|
||||
for c in data[0:(addr + 1024 - start_addr)]:
|
||||
if (ord(c)&0xff) != block[j + start_addr - addr]:
|
||||
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
|
||||
raise ValueError("verify failed at %08x" % (addr + i*1024+j))
|
||||
j += 1
|
||||
data = data[(addr + 1024 - start_addr):]
|
||||
addr += 1024
|
||||
@@ -330,7 +330,7 @@ class DFU_STM32(object):
|
||||
j = 0
|
||||
for c in data[i*1024:(i+1)*1024]:
|
||||
if (ord(c)&0xff) != block[j]:
|
||||
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
|
||||
raise ValueError("verify failed at %08x" % (addr + i*1024+j))
|
||||
j += 1
|
||||
if i & 0x03 == 0x03:
|
||||
sys.stdout.write("#")
|
||||
@@ -367,25 +367,25 @@ def get_device():
|
||||
(alt.interfaceProtocol == DFU_STM32PROTOCOL_0 or \
|
||||
alt.interfaceProtocol == DFU_STM32PROTOCOL_2):
|
||||
return dev, config, alt
|
||||
raise ValueError, "Device not found"
|
||||
raise ValueError("Device not found")
|
||||
|
||||
def main(filename):
|
||||
dev, config, intf = get_device()
|
||||
print "Device:", dev.filename
|
||||
print "Configuration", config.value
|
||||
print "Interface", intf.interfaceNumber
|
||||
print("Device:", dev.filename)
|
||||
print("Configuration", config.value)
|
||||
print("Interface", intf.interfaceNumber)
|
||||
dfu = DFU_STM32(dev, config, intf)
|
||||
print dfu.ll_get_string(intf.iInterface)
|
||||
print(dfu.ll_get_string(intf.iInterface))
|
||||
s = dfu.ll_get_status()
|
||||
if s[4] == STATE_DFU_ERROR:
|
||||
dfu.ll_clear_status()
|
||||
s = dfu.ll_get_status()
|
||||
print s
|
||||
print(s)
|
||||
if s[4] == STATE_DFU_IDLE:
|
||||
exit
|
||||
transfer_size = 1024
|
||||
if s[0] != DFU_STATUS_OK:
|
||||
print s
|
||||
print(s)
|
||||
exit
|
||||
ih = intel_hex(filename)
|
||||
dfu.download(ih)
|
||||
|
||||
@@ -27,22 +27,22 @@ from dfuse import *
|
||||
|
||||
dev, config, intf = get_device()
|
||||
dfu = DFU_STM32(dev, config, intf)
|
||||
print dfu.ll_get_string(intf.iInterface)
|
||||
print(dfu.ll_get_string(intf.iInterface))
|
||||
s = dfu.ll_get_status()
|
||||
dfu.ll_clear_status()
|
||||
s = dfu.ll_get_status()
|
||||
print s
|
||||
print(s)
|
||||
dfu.dfuse_set_address_pointer(int(sys.argv[1], 16))
|
||||
s = dfu.ll_get_status()
|
||||
dfu.ll_clear_status()
|
||||
s = dfu.ll_get_status()
|
||||
dfu.ll_clear_status()
|
||||
s = dfu.ll_get_status()
|
||||
print s
|
||||
print(s)
|
||||
block = dfu.dfuse_read_memory()
|
||||
count = 0
|
||||
for d in block:
|
||||
print "%02x" % d,
|
||||
print("%02x" % d)
|
||||
if count & 0x0f == 0x0f:
|
||||
print
|
||||
count += 1
|
||||
|
||||
@@ -20,7 +20,7 @@ def get_gpg_public_key(keygrip):
|
||||
pos_last = key.index(")(1:e3:")
|
||||
key = key[pos:pos_last]
|
||||
if len(key) != 256:
|
||||
raise ValueError, binascii.hexlify(key)
|
||||
raise ValueError(binascii.hexlify(key))
|
||||
return key
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
21
tool/gnuk_get_random.py
Executable file
21
tool/gnuk_get_random.py
Executable file
@@ -0,0 +1,21 @@
|
||||
#! /usr/bin/python3
|
||||
|
||||
from gnuk_token import get_gnuk_device, gnuk_token
|
||||
from binascii import hexlify
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
count = 0
|
||||
gnuk = get_gnuk_device()
|
||||
gnuk.cmd_select_openpgp()
|
||||
looping = (len(sys.argv) > 1)
|
||||
while True:
|
||||
try:
|
||||
challenge = gnuk.cmd_get_challenge().tostring()
|
||||
except Exception as e:
|
||||
print(count)
|
||||
raise e
|
||||
print(hexlify(challenge))
|
||||
count = count + 1
|
||||
if not looping:
|
||||
break
|
||||
@@ -30,6 +30,7 @@ from array import array
|
||||
USB_PRODUCT_LIST=[
|
||||
{ 'vendor' : 0x234b, 'product' : 0x0000 }, # FSIJ Gnuk Token
|
||||
{ 'vendor' : 0x20a0, 'product' : 0x4211 }, # Nitrokey Start
|
||||
{ 'vendor' : 0x1209, 'product' : 0x2440 }, # GnuPG e.V.
|
||||
]
|
||||
|
||||
# USB class, subclass, protocol
|
||||
@@ -74,6 +75,7 @@ class gnuk_token(object):
|
||||
raise ValueError("Wrong interface sub class")
|
||||
self.__devhandle = device.open()
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
|
||||
@@ -28,7 +28,7 @@ from sexp import sexp
|
||||
# Assume it's only OPENPGP.3 key and it's 2048-bit
|
||||
|
||||
def debug(string):
|
||||
print "DEBUG: %s" % string
|
||||
print("DEBUG: %s" % string)
|
||||
sys.stdout.flush()
|
||||
|
||||
def get_keygrip_list(keyinfo_result):
|
||||
|
||||
@@ -82,7 +82,7 @@ class Card(object):
|
||||
elif code == FEATURE_MODIFY_PIN_DIRECT:
|
||||
self.modify_ioctl = ioctl
|
||||
if self.verify_ioctl == -1:
|
||||
raise ValueError, "Not supported"
|
||||
raise ValueError("Not supported")
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
|
||||
@@ -90,7 +90,7 @@ class Card(object):
|
||||
if sw1 == 0x61: # More data
|
||||
response, sw1, sw2 = self.connection.transmit([0x00, 0xc0, 0, 0, sw2])
|
||||
elif not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_select_openpgp %02x %02x" % (sw1, sw2))
|
||||
raise ValueError("cmd_select_openpgp %02x %02x" % (sw1, sw2))
|
||||
|
||||
def possibly_add_dummy_byte(self):
|
||||
if self.another_byte:
|
||||
@@ -135,11 +135,11 @@ class Card(object):
|
||||
sw1 = data[0]
|
||||
sw2 = data[1]
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_verify_pinpad %02x %02x" % (sw1, sw2))
|
||||
raise ValueError("cmd_verify_pinpad %02x %02x" % (sw1, sw2))
|
||||
|
||||
def send_modify_pinpad(self, apdu, single_step, command):
|
||||
if self.modify_ioctl == -1:
|
||||
raise ValueError, "Not supported"
|
||||
raise ValueError("Not supported")
|
||||
pin_modify = [ 0x00, # bTimerOut
|
||||
0x00, # bTimerOut2
|
||||
0x82, # bmFormatString: Byte, pos=0, left, ASCII.
|
||||
@@ -171,7 +171,7 @@ class Card(object):
|
||||
sw1 = data[0]
|
||||
sw2 = data[1]
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("%s %02x %02x" % (command, sw1, sw2))
|
||||
raise ValueError("%s %02x %02x" % (command, sw1, sw2))
|
||||
|
||||
def cmd_reset_retry_counter(self, who, data):
|
||||
if who == BY_ADMIN:
|
||||
@@ -180,7 +180,7 @@ class Card(object):
|
||||
apdu = [0x00, 0x2c, 0x00, 0x81, len(data) ] + data # BY_USER with resetcode
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_reset_retry_counter %02x %02x" % (sw1, sw2))
|
||||
raise ValueError("cmd_reset_retry_counter %02x %02x" % (sw1, sw2))
|
||||
|
||||
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
|
||||
def cmd_reset_retry_counter_pinpad(self, who):
|
||||
@@ -195,7 +195,7 @@ class Card(object):
|
||||
apdu = [0x00, 0xda, 0x00, 0xd3, len(data) ] + data # BY_ADMIN
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_put_resetcode %02x %02x" % (sw1, sw2))
|
||||
raise ValueError("cmd_put_resetcode %02x %02x" % (sw1, sw2))
|
||||
|
||||
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
|
||||
def cmd_put_resetcode_pinpad(self):
|
||||
@@ -225,8 +225,8 @@ def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed):
|
||||
card.connection.connect()
|
||||
|
||||
ident = card.connection.getReader()
|
||||
print "Reader/Token:", ident
|
||||
print "ATR:", toHexString( card.connection.getATR() )
|
||||
print("Reader/Token:", ident)
|
||||
print("ATR:", toHexString( card.connection.getATR() ))
|
||||
|
||||
if ident == COVADIS_VEGA_ALPHA:
|
||||
card.cmd_vega_alpha_disable_empty_verify()
|
||||
@@ -236,29 +236,29 @@ def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed):
|
||||
card.cmd_select_openpgp()
|
||||
if method == "verify":
|
||||
if who == BY_USER:
|
||||
print "Please input User's PIN"
|
||||
print("Please input User's PIN")
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(who)
|
||||
elif method == "change":
|
||||
if change_by_two_steps:
|
||||
if who == BY_USER:
|
||||
print "Please input User's PIN"
|
||||
print("Please input User's PIN")
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(who)
|
||||
if who == BY_USER:
|
||||
print "Please input New User's PIN twice"
|
||||
print("Please input New User's PIN twice")
|
||||
else:
|
||||
print "Please input New Admin's PIN twice"
|
||||
print("Please input New Admin's PIN twice")
|
||||
card.cmd_change_reference_data_pinpad(who, True)
|
||||
else:
|
||||
if who == BY_USER:
|
||||
print "Please input User's PIN"
|
||||
print "and New User's PIN twice"
|
||||
print("Please input User's PIN")
|
||||
print("and New User's PIN twice")
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print "and New Admin's PIN twice"
|
||||
print("Please input Admin's PIN")
|
||||
print("and New Admin's PIN twice")
|
||||
card.cmd_change_reference_data_pinpad(who, False)
|
||||
elif method == "unblock":
|
||||
if change_by_two_steps:
|
||||
@@ -268,66 +268,66 @@ def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed):
|
||||
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
|
||||
card.cmd_reset_retry_counter(who,resetcode+newpin)
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
|
||||
card.cmd_reset_retry_counter(who,newpin)
|
||||
else:
|
||||
if who == BY_USER:
|
||||
print "Please input reset code"
|
||||
print "and New User's PIN twice"
|
||||
print("Please input reset code")
|
||||
print("and New User's PIN twice")
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
print "Please input New User's PIN twice"
|
||||
print("Please input New User's PIN twice")
|
||||
card.cmd_reset_retry_counter_pinpad(who)
|
||||
elif method == "put":
|
||||
if change_by_two_steps:
|
||||
# It means using keyboard for new PIN
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
resetcode=s2l(getpass("Please input New Reset Code from keyboard: "))
|
||||
card.cmd_put_resetcode(resetcode)
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print("Please input Admin's PIN")
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
print "Please input New Reset Code twice"
|
||||
print("Please input New Reset Code twice")
|
||||
card.cmd_put_resetcode_pinpad()
|
||||
else:
|
||||
raise ValueError, method
|
||||
raise ValueError(method)
|
||||
card.connection.disconnect()
|
||||
|
||||
print "OK."
|
||||
print("OK.")
|
||||
return 0
|
||||
|
||||
def print_usage():
|
||||
print "pinpad-test: testing pinentry of PC/SC card reader"
|
||||
print " help:"
|
||||
print "\t--help:\t\tthis message"
|
||||
print " method:\t\t\t\t\t\t\t[verify]"
|
||||
print "\t--verify:\tverify PIN"
|
||||
print "\t--change:\tchange PIN (old PIN, new PIN twice)"
|
||||
print "\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)"
|
||||
print "\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)"
|
||||
print "\t--unblock2:\tunblock PIN (admin PIN:pinpad, new PIN:kbd)"
|
||||
print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)"
|
||||
print "\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)"
|
||||
print " options:"
|
||||
print "\t--fixed N:\tUse fixed length input"
|
||||
print "\t--admin:\tby administrator\t\t\t[False]"
|
||||
print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]"
|
||||
print "\t--pinmin:\tspecify minimum length of PIN\t\t[6]"
|
||||
print "\t--pinmax:\tspecify maximum length of PIN\t\t[15]"
|
||||
print "EXAMPLES:"
|
||||
print " $ pinpad-test # verify user's PIN "
|
||||
print " $ pinpad-test --admin # verify admin's PIN "
|
||||
print " $ pinpad-test --change # change user's PIN "
|
||||
print " $ pinpad-test --change --admin # change admin's PIN "
|
||||
print " $ pinpad-test --change2 # change user's PIN by two steps"
|
||||
print " $ pinpad-test --change2 --admin # change admin's PIN by two steps"
|
||||
print " $ pinpad-test --unblock # change user's PIN by reset code"
|
||||
print " $ pinpad-test --unblock --admin # change user's PIN by admin's PIN"
|
||||
print " $ pinpad-test --put # setup resetcode "
|
||||
print("pinpad-test: testing pinentry of PC/SC card reader")
|
||||
print(" help:")
|
||||
print("\t--help:\t\tthis message")
|
||||
print(" method:\t\t\t\t\t\t\t[verify]")
|
||||
print("\t--verify:\tverify PIN")
|
||||
print("\t--change:\tchange PIN (old PIN, new PIN twice)")
|
||||
print("\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)")
|
||||
print("\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)")
|
||||
print("\t--unblock2:\tunblock PIN (admin PIN:pinpad, new PIN:kbd)")
|
||||
print("\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)")
|
||||
print("\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)")
|
||||
print(" options:")
|
||||
print("\t--fixed N:\tUse fixed length input")
|
||||
print("\t--admin:\tby administrator\t\t\t[False]")
|
||||
print("\t--add:\t\tadd a dummy byte at the end of APDU\t[False]")
|
||||
print("\t--pinmin:\tspecify minimum length of PIN\t\t[6]")
|
||||
print("\t--pinmax:\tspecify maximum length of PIN\t\t[15]")
|
||||
print("EXAMPLES:")
|
||||
print(" $ pinpad-test # verify user's PIN ")
|
||||
print(" $ pinpad-test --admin # verify admin's PIN ")
|
||||
print(" $ pinpad-test --change # change user's PIN ")
|
||||
print(" $ pinpad-test --change --admin # change admin's PIN ")
|
||||
print(" $ pinpad-test --change2 # change user's PIN by two steps")
|
||||
print(" $ pinpad-test --change2 --admin # change admin's PIN by two steps")
|
||||
print(" $ pinpad-test --unblock # change user's PIN by reset code")
|
||||
print(" $ pinpad-test --unblock --admin # change user's PIN by admin's PIN")
|
||||
print(" $ pinpad-test --put # setup resetcode ")
|
||||
|
||||
if __name__ == '__main__':
|
||||
who = BY_USER
|
||||
@@ -374,7 +374,7 @@ if __name__ == '__main__':
|
||||
print_usage()
|
||||
exit(0)
|
||||
else:
|
||||
raise ValueError, option
|
||||
raise ValueError(option)
|
||||
main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed)
|
||||
|
||||
# Failure
|
||||
|
||||
Reference in New Issue
Block a user