Compare commits

...

24 Commits

Author SHA1 Message Date
NIIBE Yutaka
4af98308e0 Version 1.2.17.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-25 15:46:02 +09:00
NIIBE Yutaka
baec3a1c1e Fix the previous commit. 2021-02-25 14:26:31 +09:00
NIIBE Yutaka
4f1325794d Require KDF Data Object for GNU/Linux emulation.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-22 10:52:44 +09:00
NIIBE Yutaka
0acf6485ae Prepare next release.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-19 16:37:08 +09:00
NIIBE Yutaka
4d15700580 Python3 update things.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-19 13:12:48 +09:00
NIIBE Yutaka
8822fcae77 Update AUTHORS.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-19 12:07:15 +09:00
NIIBE Yutaka
20a2f99691 Update Chopstx.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-19 12:07:02 +09:00
NIIBE Yutaka
acfccb729d Add changelog entries.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-18 16:00:13 +09:00
Vincent Pelletier
5283506755 tests/card_reader.py: Ignore CCID devices which report card absence.
Helps running tests on computers which have a "real" card reader in
addition to the ICC to be tested.
2021-02-18 14:42:47 +09:00
Vincent Pelletier
c688df7c2c {tests/card_reader.py,tool/gnuk_token.py}: Extend timeout.
Some devices are slow at generating RSA4096 after a key settings change,
and may take time to notice a later change to a shorter key size.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-02-18 14:28:32 +09:00
Vincent Pelletier
594896ac57 test/feature/202_setup_passphease.feature: Fix expected PW1 value.
Since 040_passphrase_change.feature, PW1 has this value and not the reset
default.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-02-18 14:28:27 +09:00
Vincent Pelletier
dfe046e08d tool/gnuk_token.py: Detect CCID bulk endpoints addresses.
Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-02-18 14:28:23 +09:00
Vincent Pelletier
c66b01e74b test{,s}/rka_keys.py: Add missing char escape specifiers.
Removes a 2-bytes trailer to the private key template, fitting in the
2-bytes length (which itself lacked an hexadecimal escape specifier, but
without effect on the result).
Fixes the length of the DigestInfo outermost list, from 25 to the intended
49.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-02-18 14:28:17 +09:00
NIIBE Yutaka
21a46306ae Make GNU/Linux emulation work again, with initialization support.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-02-18 14:04:21 +09:00
NIIBE Yutaka
e5158572ee Version 1.2.16.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-10 11:55:16 +09:00
NIIBE Yutaka
2142d0aa35 Don't use memmove, but use memcpy with dummy memory area.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-09 08:55:09 +09:00
NIIBE Yutaka
dd47cf4312 Avoid compiler optimization removing memmove.
Thanks to Szczepan Zalega.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-08 09:22:40 +09:00
NIIBE Yutaka
ffbb754fc0 Use an array for _updatekey_store.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-07 09:45:28 +09:00
NIIBE Yutaka
d85750d791 Fix use of memcpy to memmove.
memcpy doesn't allow memory areas overlap.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-07 09:44:28 +09:00
NIIBE Yutaka
d20e9e9b1e Add 0x00FA data object (Algorithm Information).
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-04 13:28:28 +09:00
NIIBE Yutaka
bf30144144 Remove Ed25519 signing condition against EDDSA_HASH_LEN_MAX.
See GnuPG bug report: https://dev.gnupg.org/T5041

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-09-03 10:42:20 +09:00
NIIBE Yutaka
934daf3585 For admin-less mode, make sure the passphrase is long enough.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-08-28 09:53:16 +09:00
NIIBE Yutaka
22420ed1f4 Fix cmd_verify with AC_OTHER_AUTHORIZED for signing key only case.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-08-26 11:24:15 +09:00
NIIBE Yutaka
e97e3b1810 tests: Fix a test for OpenPGP card version 3.3.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-08-26 09:38:41 +09:00
28 changed files with 438 additions and 212 deletions

18
AUTHORS
View File

@@ -11,6 +11,16 @@ Anthony Romano:
src/main.c
src/mod.c
Bertrand Jacquin
Modified:
tool/add_openpgp_authkey_from_gpgssh.py
tool/calc_precompute_table_ecc.py
tool/dfuse.py
tool/dump_mem.py
tool/get_raw_public_key.py
tool/pageant_proxy_to_gpg.py
tool/pinpadtest.py
Jeremy Drake:
Modified:
regnual/regnual.c
@@ -74,3 +84,11 @@ Peter Lebbing:
src/Makefile
Wrote:
src/stdaln-sys.ld.in
Vincent Pelletier:
Modified:
test/features/202_setup_passphrase.feature
test/rsa_keys.py
tests/card_reader.py
tests/rsa_keys.py
tool/gnuk_token.py

109
ChangeLog
View File

@@ -1,3 +1,112 @@
2021-02-25 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.17.
2021-02-22 NIIBE Yutaka <gniibe@fsij.org>
* src/config.h.in (@KDF_DO_REQUIRED_DEFINE@): New.
* src/configure (KDF_DO_REQUIRED_DEFINE): New for GNU/Linux.
* src/openpgp-do.c (gpg_do_kdf_check): When LEN==0, check if
KDO data object is available.
[KDF_DO_REQUIRED] (proc_key_import): Refuse the key import when
KDF data object is not available.
* src/openpgp.c [KDF_DO_REQUIRED] (cmd_pgp_gakp): Refuse key
generation when KDF data object is not available.
2021-02-19 NIIBE Yutaka <gniibe@fsij.org>
* tool/gnuk-emulation-setup: Remove.
* tool/upgrade_by_passwd.py (main): Use tobytes.
* tool/gnuk_get_random.py: Likewise.
* tool/gnuk_remove_keys_libusb.py (main): Likewise.
Switch to Python3.
* tool/gnuk_put_binary_libusb.py (main): Use tobytes.
Switch to Python3.
* tool/gnuk_upgrade.py (main): Use tobytes.
Switch to Python3.
* chopstx: Update to 1.19.
2021-02-18 Vincent Pelletier <plr.vincent@gmail.com>
* test/features/202_setup_passphrase.feature: Fix.
* test/rsa_keys.py: Fix escape.
* tests/card_reader.py: Extend the timeout.
Handle no card.
* tests/rsa_keys.py: Fix escape.
* tool/gnuk_token.py: Avoid hard-coding the endpoints.
Longer timeout.
2021-02-18 NIIBE Yutaka <gniibe@fsij.org>
* src/configure [GNU_LINUX_EMULATION] (def_mhz): Define.
(output_vendor_product_serial_strings): Output ARCH.
* GNUK_USB_DEVICE_ID: Use "Gnuk Token" for emulation, too.
* src/main.c [GNU_LINUX_EMULATION] (main): Add initialization of
the .gnuk-flash-image file.
(gnuk_sbrk): Rename from sbrk.
2020-09-10 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.16.
2020-09-09 NIIBE Yutaka <gniibe@fsij.org>
* src/modp256k1.c (modp256k1_add, modp256k1_sub): Use memcpy with
dummy memory area.
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
(modp256r1_reduce): Likewise.
2020-09-08 NIIBE Yutaka <gniibe@fsij.org>
* src/modp256k1.c (modp256k1_add, modp256k1_reduce): Avoid
optimization to remove call of memmove.
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
(modp256r1_reduce): Likewise.
2020-09-07 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (gpg_get_firmware_update_key): Use an array.
* src/modp256k1.c (modp256k1_add, modp256k1_sub): Use memmove.
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
(modp256r1_reduce): Likewise.
2020-09-04 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (GPG_DO_ALG_INFO): New.
(do_fp_all, do_cafp_all, do_kgtime_all, do_openpgpcard_aid)
(do_ds_count): Return nothing.
(copy_do): Change the API for DO_PROC_READ.
(do_alg_info): New for GPG_DO_ALG_INFO.
(gpg_do_table): Add an entry for GPG_DO_ALG_INFO.
2020-09-03 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_internal_authenticate): Remove checking
against EDDSA_HASH_LEN_MAX.
(cmd_pso): Likewise.
2020-08-28 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_reset_user_password): Add passphrase length
check.
2020-08-26 NIIBE Yutaka <gniibe@fsij.org>
* src/ac.c (verify_user_0): Fix for a use case of having
signing key only.
(verify_admin_00): Clean up.
* tests/test_000_empty_card.py (test_name_lang_sex): Support
OpenPGP card version 3.3.
2020-01-24 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.15.

View File

@@ -1,5 +1,5 @@
# VID:PID bcdDev Product_STRING Vendor_STRING
0000:0000 0200 Gnuk Emulation Free Software Initiative of Japan
0000:0000 0200 Gnuk Token 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.

40
NEWS
View File

@@ -1,6 +1,46 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.17
Released 2021-02-25, by NIIBE Yutaka
** GNU/Linux: KDF Data Object is required before keygen and key import
For GNU/Linux emulation, KDF Data Object is required before keygen and
key import.
** GNU/Linux emulation
Since 1.2.10, it was not build-able because of MHZ definition. It is
build-able again, and its USB product string is now "Gnuk Token". It
has ACK button support using terminal. It now has start-up message,
and its driver show useful information to setup USBIP. When no file
for the .gnuk-flash-image file, it is automatically created.
** Removal of tool/gnuk-emulation-setup
Because it is automatically created, the tool is not needed any more.
** Upgrade of Chopstx
We use Chopstx 1.19.
* Major changes in Gnuk 1.2.16
Released 2020-09-10, by NIIBE Yutaka
** New Data Object (Algorithm Information) of OpenPGP card v3.4
The tag is 0x00FA. This is useful for user interaction to show which
algorithms are supported by the device.
** Ed25519 signing allowing longer message
For OpenPGP, it does hashing on host side before requesting signing to
the device. Thus, the length of message to be signed is limited and
determined by the hash algorithm. That's good feature of OpenPGP. On
the other hand, there is a use case, like OpenSSH certificate signing,
where the length of message is a kind of arbitrary. Even though Gnuk
(or OpenPGP card protocol itself) has limitation, we removed the
length check against EDDSA_HASH_LEN_MAX at cmd_pso.
* Major changes in Gnuk 1.2.15
Released 2020-01-24, by NIIBE Yutaka

67
README
View File

@@ -1,24 +1,23 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.15
2020-01-24
Version 1.2.17
2021-02-25
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.15, which has major
This is the release of Gnuk, version 1.2.17, 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
your password. Please update your documentation for Gnuk Token, so
that the instruction of importing keys won't cause any confusion.
It has supports of EdDSA, ECDSA (with NIST P256 and secp256k1), and
ECDH (with X25519, NIST P256 and secp256k1), but this ECC feature is
somehow experimental, and it requires modern GnuPG 2.2 with libgcrypt
1.7.0 or later.
It has supports of Ed25519 and X25519 (ECDH on Curve25519). It also
has experimental support of ECDSA (on NIST P256 and secp256k1) and
ECDH (on NIST P256 and secp256k1).
It also supports RSA-4096, but users should know that it takes more
than 8 seconds to sign/decrypt. Key generation of RSA-4096 just fails,
@@ -29,7 +28,8 @@ experimental. To use the feature, you need to use newer GnuPG (2.2.6
or later). You need to prepare the KDF-DO on your token by the
card-edit/kdf-setup command.
With FST-01SZ, experimental ack button support is available for test.
With FST-01SZ and GNU/Linux emulation, experimental ack button support
is available for test.
What's Gnuk?
@@ -54,7 +54,7 @@ FAQ
===
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, YubiKey, etc.) ?
card 2.0/3.3/3.4, YubiKey, etc.) ?
https://www.g10code.de/p-card.html
https://www.yubico.com/
A0: Good points of Gnuk are:
@@ -79,13 +79,12 @@ A2: It takes a second and a half or so for RSA-2048.
Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103.
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
kind of the best choice, hopefully.
If you have a skill of electronics, STM32 Nucleo F103 is the best
choice for experiment.
FST-01SZ (Flying Stone Tiny 01 SZ) is available for sale, and it
is a kind of the best choice, hopefully. If you have a skill of
electronics, STM32 Nucleo F103 is the best choice for experiment.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use GnuPG modern 2.2.12.
A4: In Debian GNU/Linux system, I use GnuPG modern 2.2.23.
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
@@ -146,14 +145,20 @@ Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
Qd: Do you know a good SWD debugger to connect FST-01 or something?
Ad: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program. STM32 Nucleo F103 comes with the valiant of
ST-Link/V2. However, the firmware of ST-Link/V2 is proprietary.
Now, I develop BBG-SWD, SWD debugger by BeagleBone Green.
ST-Link/V2. Note that the firmware of ST-Link/V2 is proprietary.
So, in case of transparency matters, ST-Link/V2 would not be your
choice.
I care transparency for our process of manufacturing FST-01SZ (and
better control by Free Software, in general), thus, I develop
BBG-SWD, SWD debugger by BeagleBone Green.
I use ST-Link/V2 for daily development. For serious task like
flashing product, I use BBG-SWD.
Tested features
===============
Gnuk is tested by test suite. Please see the test directory.
Gnuk is tested by test suite. Please see the "tests" directory.
* Personalization of the card
* Changing Login name, URL, Name, Sex, Language, etc.
@@ -190,16 +195,6 @@ DfuSe is for experiment only, because it is impossible for DfuSe to
disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger.
For experimental PIN-pad support, I connect a consumer IR receive
module to FST-01, and use controller for TV. PIN verification is
supported by this configuration. Yes, it is not secure at all, since
it is very easy to monitor IR output of the controllers. It is just
an experiment. Note that hardware needed for this experiment is only
a consumer IR receive module which is as cheap as 50 JPY.
Note that you need pinpad support for GnuPG to use PIN-pad enabled
Gnuk. The pinpad support for GnuPG is only available in version 2.
Build system and Host system
============================
@@ -210,8 +205,8 @@ If your bash is not installed as /bin/bash, you need to run configure
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.
I use Python 3.7 and PyUSB 1.0.0.
/usr/bin/python, please prepend 'python' or 'python3' for your command
invocation. I use Python 3.8 and PyUSB 1.0.2.
Source code
@@ -248,7 +243,7 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 1.18
* chopstx/ -- Chopstx 1.19
We use Chopstx as the kernel for Gnuk.
@@ -367,13 +362,13 @@ How to compile
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:
On Debian we can install the packages of gcc-arm-none-eabi
and its friends. I'm using:
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
binutils-arm-none-eabi 2.35.1-7+14+b1
gcc-arm-none-eabi 15:8-2019-q3-1+b1
libnewlib-arm-none-eabi 3.3.0-1
gdb-multiarch 10.1-1.7
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.

1
THANKS
View File

@@ -41,5 +41,6 @@ Shane Coughlan scoughlan@openinventionnetwork.com
Stanislas Bach sbach@0g.re
Szczepan Zalega szczepan@nitrokey.com
Vasily Evseenko
Vincent Pelletier plr.vincent@gmail.com
Werner Koch wk@gnupg.org
Yuji Imai ug@xcast.jp

View File

@@ -1 +1 @@
release/1.2.15
release/1.2.17

Submodule chopstx updated: cc49f4ef23...71cc5a8f32

View File

@@ -63,7 +63,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks_pw1, int save_ks)
{
int pw_len;
int r1, r2;
int r;
uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
@@ -99,21 +99,31 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
if (access == AC_PSO_CDS_AUTHORIZED)
{
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
r2 = 0;
}
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
else
{
int r1, r2;
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring);
r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring);
if (r1 < 0 || r2 < 0)
r = -1;
else if (r1 == 0)
{
if (r2 == 0)
/* No encryption/authentication keys, then, check signing key. */
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
else
r = r2;
}
else if (r2 == 0)
r = r1;
else
r = 1;
}
if (r1 < 0 || r2 < 0
|| (r1 == 0 && r2 == 0 && ks_pw1 != NULL
&& ((ks_pw1[0] & PW_LEN_KEYSTRING_BIT) == 0
|| memcmp (KS_GET_KEYSTRING (ks_pw1),
keystring, KEYSTRING_MD_SIZE) != 0)))
if (r < 0)
{
failure:
gpg_pw_increment_err_counter (PW_ERR_PW1);
@@ -163,7 +173,7 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks, int save_ks)
{
int pw_len;
int r1, r2;
int r;
uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *salt;
int salt_len;
@@ -179,12 +189,11 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
if (save_ks)
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
r2 = 0;
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
if (r1 < 0 || r2 < 0)
if (r < 0)
return -1;
else if (r1 == 0 && r2 == 0)
else if (r == 0)
if ((ks[0] & PW_LEN_KEYSTRING_BIT) == 0
|| memcmp (KS_GET_KEYSTRING (ks), keystring, KEYSTRING_MD_SIZE) != 0)
return -1;

View File

@@ -12,3 +12,4 @@
@LIFE_CYCLE_MANAGEMENT_DEFINE@
@ACKBTN_DEFINE@
@SERIALNO_STR_LEN_DEFINE@
@KDF_DO_REQUIRED_DEFINE@

19
src/configure vendored
View File

@@ -6,7 +6,7 @@ nl=$'\n'
#
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2021
# Free Software Initiative of Japan
#
# This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -46,6 +46,7 @@ hid_card_change=no
factory_reset=no
ackbtn_support=yes
flash_override=""
kdf_do_required=no
# For emulation
prefix=/usr/local
exec_prefix='${prefix}'
@@ -210,26 +211,28 @@ FST_01SZ)
;;
esac
def_mhz="-DMHZ=$MHZ"
if test "$target" = "GNU_LINUX"; then
ldscript=""
chip="gnu-linux"
arch="gnu-linux"
emulation="yes"
cross=""
mcu="none"
kdf_do_require=yes
def_emulation="-DGNU_LINUX_EMULATION"
def_memory_size="-DMEMORY_SIZE=1024"
def_mhz=""
enable_hexoutput=""
libs="-lpthread"
else
ldscript="gnuk.ld"
chip="stm32f103"
arch="cortex-m"
emulation=""
cross="arm-none-eabi-"
mcu="cortex-m3"
def_emulation=""
def_memory_size="-DMEMORY_SIZE=$MEMORY_SIZE"
def_mhz="-DMHZ=$MHZ"
enable_hexoutput=yes
libs=""
fi
@@ -337,6 +340,14 @@ else
echo "Acknowledge button is not supported"
fi
# KDF Data Object is always required for GNU/Linux emulation
if test "$kdf_do_required" = "yes"; then
KDF_DO_REQUIRED_DEFINE="#define KDF_DO_REQUIRED 1"
echo "KDF DO is required before key import/generation"
else
KDF_DO_REQUIRED_DEFINE="#undef KDF_DO_REQUIRED"
fi
### !!! Replace following string of "FSIJ" to yours !!! ####
SERIALNO="FSIJ-$(sed -e 's%^[^/]*/%%' <../VERSION)-"
@@ -470,6 +481,7 @@ fi
(echo "CHIP=$chip";
echo "ARCH=$arch";
echo "EMULATION=$emulation";
echo "CROSS=$cross";
echo "MCU=$mcu";
@@ -519,5 +531,6 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
-e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
-e "s/@ACKBTN_DEFINE@/$ACKBTN_DEFINE/" \
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
-e "s/@KDF_DO_REQUIRED_DEFINE@/$KDF_DO_REQUIRED_DEFINE/" \
< config.h.in > config.h
exit 0

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018, 2021
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -36,6 +36,11 @@
#include "usb-cdc.h"
#include "random.h"
#ifdef GNU_LINUX_EMULATION
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define main emulated_main
@@ -372,6 +377,34 @@ main (int argc, const char *argv[])
else
flash_image_path = argv[1];
if (access (flash_image_path, F_OK) < 0)
{
int fd;
char buf[8192];
memset (buf, 0xff, sizeof buf);
memset (buf+4*1024, 0, 2);
fd = open (flash_image_path, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
if (fd < 0)
{
perror ("creating flash file");
exit (1);
}
if (write (fd, buf, sizeof buf) != sizeof buf)
{
perror ("initializing flash file");
close (fd);
exit (1);
}
close (fd);
}
puts ("Gnuk (emulation with USBIP), a GnuPG USB Token implementation");
puts ("Copyright (C) 2021 Free Software Initiative of Japan");
puts ("This is free software under GPLv3+.");
flash_addr = flash_init (flash_image_path);
flash_addr_key_storage_start = (uint8_t *)flash_addr;
flash_addr_data_storage_start = (uint8_t *)flash_addr + 4096;
@@ -563,11 +596,11 @@ gnuk_malloc_init (void)
}
static void *
sbrk (size_t size)
gnuk_sbrk (intptr_t size)
{
void *p = (void *)heap_p;
if ((size_t)(HEAP_END - heap_p) < size)
if ((HEAP_END - heap_p) < size)
return NULL;
heap_p += size;
@@ -603,7 +636,7 @@ gnuk_malloc (size_t size)
{
if (m == NULL)
{
m = (struct mem_head *)sbrk (size);
m = (struct mem_head *)gnuk_sbrk (size);
if (m)
m->size = size;
break;

View File

@@ -1,7 +1,7 @@
/*
* modp256k1.c -- modulo arithmetic for p256k1
*
* Copyright (C) 2014, 2016 Free Software Initiative of Japan
* Copyright (C) 2014, 2016, 2020 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -71,14 +71,12 @@ modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t cond;
bn256 tmp[1];
bn256 dummy[1];
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256K1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
memcpy (X, tmp, sizeof (bn256));
memcpy (cond?dummy:X, tmp, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
}
/**
@@ -89,13 +87,12 @@ modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t borrow;
bn256 tmp[1];
bn256 dummy[1];
borrow = bn256_sub (X, A, B);
bn256_add (tmp, X, P256K1);
if (borrow)
memcpy (X, tmp, sizeof (bn256));
else
memcpy (tmp, tmp, sizeof (bn256));
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
}
/**

View File

@@ -1,7 +1,7 @@
/*
* modp256r1.c -- modulo arithmetic for p256r1
*
* Copyright (C) 2011, 2013, 2014, 2016
* Copyright (C) 2011, 2013, 2014, 2016, 2020
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -66,14 +66,12 @@ modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t cond;
bn256 tmp[1];
bn256 dummy[1];
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256R1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
memcpy (X, tmp, sizeof (bn256));
memcpy (cond?dummy:X, tmp, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
}
/**
@@ -84,13 +82,12 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t borrow;
bn256 tmp[1];
bn256 dummy[1];
borrow = bn256_sub (X, A, B);
bn256_add (tmp, X, P256R1);
if (borrow)
memcpy (X, tmp, sizeof (bn256));
else
memcpy (tmp, tmp, sizeof (bn256));
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
}
/**
@@ -100,6 +97,7 @@ void
modp256r1_reduce (bn256 *X, const bn512 *A)
{
bn256 tmp[1], tmp0[1];
bn256 dummy[1];
uint32_t borrow;
#define S1 X
@@ -121,10 +119,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S1->word[1] = A->word[1];
S1->word[0] = A->word[0];
borrow = bn256_sub (tmp0, S1, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S1, tmp0, sizeof (bn256));
memcpy (borrow?dummy:S1, tmp0, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
/* X = S1 */
S2->word[7] = A->word[15];
@@ -165,10 +161,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S5->word[1] = A->word[10];
S5->word[0] = A->word[9];
borrow = bn256_sub (tmp0, S5, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S5, tmp0, sizeof (bn256));
memcpy (borrow?dummy:S5, tmp0, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
/* X += S5 */
modp256r1_add (X, X, S5);
@@ -179,10 +173,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S6->word[1] = A->word[12];
S6->word[0] = A->word[11];
borrow = bn256_sub (tmp0, S6, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S6, tmp0, sizeof (bn256));
memcpy (borrow?dummy:S6, tmp0, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
/* X -= S6 */
modp256r1_sub (X, X, S6);
@@ -194,10 +186,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S7->word[1] = A->word[13];
S7->word[0] = A->word[12];
borrow = bn256_sub (tmp0, S7, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S7, tmp0, sizeof (bn256));
memcpy (borrow?dummy:S7, tmp0, sizeof (bn256));
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
/* X -= S7 */
modp256r1_sub (X, X, S7);

View File

@@ -1,7 +1,8 @@
/*
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2020
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -466,6 +467,7 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
#define GPG_DO_UIF_DEC 0x00d7
#define GPG_DO_UIF_AUT 0x00d8
#define GPG_DO_KDF 0x00f9
#define GPG_DO_ALG_INFO 0x00fa
#define GPG_DO_KEY_IMPORT 0x3fff
#define GPG_DO_LANGUAGE 0x5f2d
#define GPG_DO_SEX 0x5f35
@@ -532,7 +534,7 @@ copy_tag (uint16_t tag)
#define SIZE_FP 20
#define SIZE_KGTIME 4
static int
static void
do_fp_all (uint16_t tag, int with_tag)
{
const uint8_t *data;
@@ -563,10 +565,9 @@ do_fp_all (uint16_t tag, int with_tag)
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
return 1;
}
static int
static void
do_cafp_all (uint16_t tag, int with_tag)
{
const uint8_t *data;
@@ -597,10 +598,9 @@ do_cafp_all (uint16_t tag, int with_tag)
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
return 1;
}
static int
static void
do_kgtime_all (uint16_t tag, int with_tag)
{
const uint8_t *data;
@@ -631,7 +631,6 @@ do_kgtime_all (uint16_t tag, int with_tag)
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
return 1;
}
const uint8_t openpgpcard_aid[] = {
@@ -643,7 +642,7 @@ const uint8_t openpgpcard_aid[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
};
static int
static void
do_openpgpcard_aid (uint16_t tag, int with_tag)
{
const volatile uint8_t *p = openpgpcard_aid;
@@ -679,11 +678,9 @@ do_openpgpcard_aid (uint16_t tag, int with_tag)
*res_p++ = 0;
*res_p++ = 0;
return 1;
}
static int
static void
do_ds_count (uint16_t tag, int with_tag)
{
if (with_tag)
@@ -695,7 +692,37 @@ do_ds_count (uint16_t tag, int with_tag)
*res_p++ = (digital_signature_counter >> 16) & 0xff;
*res_p++ = (digital_signature_counter >> 8) & 0xff;
*res_p++ = digital_signature_counter & 0xff;
return 1;
}
static void
do_alg_info (uint16_t tag, int with_tag)
{
uint8_t *len_p = NULL;
int i;
if (with_tag)
{
copy_tag (tag);
len_p = res_p;
*res_p++ = 0; /* Filled later, assuming length is <= 127 */
}
for (i = 0; i < 3; i++)
{
uint16_t tag_algo = GPG_DO_ALG_SIG + i;
copy_do_1 (tag_algo, algorithm_attr_rsa2k, 1);
copy_do_1 (tag_algo, algorithm_attr_rsa4k, 1);
copy_do_1 (tag_algo, algorithm_attr_p256r1, 1);
copy_do_1 (tag_algo, algorithm_attr_p256k1, 1);
if (i == 0 || i == 2)
copy_do_1 (tag_algo, algorithm_attr_ed25519, 1);
if (i == 1)
copy_do_1 (tag_algo, algorithm_attr_cv25519, 1);
};
if (len_p)
*len_p = res_p - len_p - 1; /* Actually, it's 127-byte long. */
}
static int
@@ -959,11 +986,25 @@ rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
}
}
/*
* Check LEN is valid for HOW_MANY of passphrase string.
*
* HOW_MANY = 1: LEN is valid for a single passphrase string.
* HOW_MANY = 2: LEN is valid for two single passphrase strings.
* This is used to change passphrase.
* The second passphrase may be nothing.
*
* LEN = 0: Check if KDF-DO is available.
*/
int
gpg_do_kdf_check (int len, int how_many)
{
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
if (len == 0)
return kdf_do != NULL;
if (kdf_do)
{
const uint8_t *kdf_spec = kdf_do+1;
@@ -1571,6 +1612,13 @@ proc_key_import (const uint8_t *data, int len)
const uint8_t *p = data;
uint8_t pubkey[512];
#ifdef KDF_DO_REQUIRED
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
if (kdf_do == NULL)
return 0; /* Error. */
#endif
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
else
@@ -1735,6 +1783,7 @@ gpg_do_table[] = {
/* Pseudo DO READ: calculated, not changeable by user */
{ GPG_DO_DS_COUNT, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_ds_count },
{ GPG_DO_AID, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_openpgpcard_aid },
{ GPG_DO_ALG_INFO, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_alg_info },
/* Pseudo DO READ/WRITE: calculated */
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_pw_status },
@@ -2084,9 +2133,10 @@ copy_do (const struct do_table_entry *do_p, int with_tag)
}
case DO_PROC_READ:
{
int (*do_func)(uint16_t, int) = (int (*)(uint16_t, int))do_p->obj;
void (*do_func)(uint16_t, int) = (void (*)(uint16_t, int))do_p->obj;
return do_func (do_p->tag, with_tag);
do_func (do_p->tag, with_tag);
return 1;
}
case DO_PROC_READWRITE:
{

View File

@@ -561,6 +561,7 @@ cmd_reset_user_password (struct eventflag *ccid_comm)
uint8_t new_ks0[KEYSTRING_SIZE];
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
uint8_t *new_salt = KS_GET_SALT (new_ks0);
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
const uint8_t *salt;
int salt_len;
@@ -575,7 +576,6 @@ cmd_reset_user_password (struct eventflag *ccid_comm)
{
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
uint8_t old_ks[KEYSTRING_MD_SIZE];
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (gpg_do_kdf_check (len, 2) == 0)
{
@@ -665,6 +665,16 @@ cmd_reset_user_password (struct eventflag *ccid_comm)
newpw_len = len;
newpw = pw;
/* Check length of new password */
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|| newpw_len < USER_PASSWD_MINLEN)
{
DEBUG_INFO ("new password length is too short.");
GPG_CONDITION_NOT_SATISFIED ();
return;
}
random_get_salt (new_salt);
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
@@ -728,6 +738,12 @@ cmd_pgp_gakp (struct eventflag *ccid_comm)
{
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
GPG_SECURITY_FAILURE ();
#ifdef KDF_DO_REQUIRED
else if (!gpg_do_kdf_check (0, 0))
GPG_CONDITION_NOT_SATISFIED ();
#endif
else
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
}
}
@@ -736,10 +752,10 @@ cmd_pgp_gakp (struct eventflag *ccid_comm)
const uint8_t *
gpg_get_firmware_update_key (uint8_t keyno)
{
extern uint8_t _updatekey_store;
extern uint8_t _updatekey_store[1024];
const uint8_t *p;
p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
p = _updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
return p;
}
#endif
@@ -995,13 +1011,6 @@ cmd_pso (struct eventflag *ccid_comm)
{
uint32_t output[64/4]; /* Require 4-byte alignment. */
if (len > EDDSA_HASH_LEN_MAX)
{
DEBUG_INFO ("wrong hash length.");
GPG_CONDITION_NOT_SATISFIED ();
return;
}
cs = chopstx_setcancelstate (0);
result_len = EDDSA_SIGNATURE_LENGTH;
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
@@ -1208,13 +1217,6 @@ cmd_internal_authenticate (struct eventflag *ccid_comm)
{
uint32_t output[64/4]; /* Require 4-byte alignment. */
if (len > EDDSA_HASH_LEN_MAX)
{
DEBUG_INFO ("wrong hash length.");
GPG_CONDITION_NOT_SATISFIED ();
return;
}
cs = chopstx_setcancelstate (0);
result_len = EDDSA_SIGNATURE_LENGTH;
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,

View File

@@ -4,7 +4,7 @@ Feature: setup pass phrase
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW1 (admin-full mode)
Given cmd_change_reference_data with 1 and "123456user pass phrase"
Given cmd_change_reference_data with 1 and "another user pass phraseuser pass phrase"
Then it should get success
Scenario: verify PW1 (1)

View File

@@ -70,11 +70,11 @@ def build_privkey_template_for_remove(openpgp_keyno):
keyspec = b'\xb8'
else:
keyspec = b'\xa4'
return b'\x4d\02' + keyspec + b'\0x00'
return b'\x4d\x02' + keyspec + b'\x00'
def compute_digestinfo(msg):
digest = sha256(msg).digest()
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
prefix = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
return prefix + digest
# egcd and modinv are from wikibooks

View File

@@ -126,9 +126,12 @@ class CardReader(object):
# intf.extra_descriptors[41]
self.__dev = dev
self.__timeout = 10000
self.__timeout = 100000
self.__seq = 0
if self.ccid_get_status() & 0x03 not in (0, 1):
raise ValueError("Card absent")
def get_string(self, num):
return get_string(self.__dev, num)

View File

@@ -70,11 +70,11 @@ def build_privkey_template_for_remove(openpgp_keyno):
keyspec = b'\xb8'
else:
keyspec = b'\xa4'
return b'\x4d\02' + keyspec + b'\0x00'
return b'\x4d\x02' + keyspec + b'\x00'
def compute_digestinfo(msg):
digest = sha256(msg).digest()
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
prefix = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
return prefix + digest
# egcd and modinv are from wikibooks

View File

@@ -52,14 +52,19 @@ def test_name_lang_sex(card):
lang = b""
lang_de = b"de"
sex = b"9"
sex_alt = b"0"
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
expected_de_alt = b'\x5b' + pack('B', len(name)) + name \
+ b'\x5f\x2d' + pack('B', len(lang_de)) + lang_de \
+ b'\x5f\x35' + pack('B', len(sex_alt)) + sex_alt
name_lang_sex = get_data_object(card, 0x65)
assert name_lang_sex == b'' or name_lang_sex == expected or name_lang_sex == expected_de
assert name_lang_sex == b'' or name_lang_sex == expected \
or name_lang_sex == expected_de or name_lang_sex == expected_de_alt
def test_app_data(card):
app_data = get_data_object(card, 0x6e)

View File

@@ -1,48 +0,0 @@
#! /bin/sh
#
# gnuk-emulation-setup - Generate flash image for Gnuk
#
# Copyright (C) 2017 Free Software Initiative of Japan
# 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/>.
if test "$1" = "--help"; then
echo "Usage:"
echo " $0 [output-file]"
echo " Generate Gnuk flash image"
echo " $0 --help"
echo " Show this message"
exit 0
fi
OUTPUT_FILE=${1:-$HOME/.gnuk-flash-image}
# Generate 8192-byte flash data into OUTPUT_FILE
exec > $OUTPUT_FILE
for i in $(seq 512); do
/bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff'
done
/bin/echo -n -e '\x00\x00\xff\xff\xff\xff\xff\xff'
for i in $(seq 511); do
/bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff'
done
chmod og-rw $OUTPUT_FILE

View File

@@ -11,7 +11,7 @@ if __name__ == '__main__':
looping = (len(sys.argv) > 1)
while True:
try:
challenge = gnuk.cmd_get_challenge().tostring()
challenge = gnuk.cmd_get_challenge().tobytes()
except Exception as e:
print(count)
raise e

View File

@@ -1,10 +1,10 @@
#! /usr/bin/python
#! /usr/bin/python3
"""
gnuk_put_binary.py - a tool to put binary to Gnuk Token
This tool is for importing certificate, writing serial number, etc.
Copyright (C) 2011, 2012 Free Software Initiative of Japan
Copyright (C) 2011, 2012, 2021 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -56,7 +56,7 @@ def main(fileid, is_update, data, passwd):
if fileid == 0:
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
print(' '.join([ "%02x" % d for d in data_in_device ]))
compare(data + b'\x00\x00', data_in_device[8:].tostring())
compare(data + b'\x00\x00', data_in_device[8:].tobytes())
elif fileid >= 1 and fileid <= 4:
data_in_device = gnuk.cmd_read_binary(fileid)
compare(data, data_in_device)

View File

@@ -1,9 +1,9 @@
#! /usr/bin/python
#! /usr/bin/python3
"""
gnuk_remove_keys_libusb.py - a tool to remove keys in Gnuk Token
Copyright (C) 2012, 2018 Free Software Initiative of Japan
Copyright (C) 2012, 2018, 2021 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -51,7 +51,7 @@ def main(passwd):
gnuk.icc_power_on()
gnuk.cmd_select_openpgp()
# Compute passwd data
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring()
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tobytes()
if kdf_data == b"":
passwd_data = passwd.encode('UTF-8')
else:

View File

@@ -88,11 +88,17 @@ class gnuk_token(object):
alt.interfaceSubClass == HID_SUBCLASS_NO_BOOT and \
alt.interfaceProtocol == HID_PROTOCOL_0:
self.__hid_intf = alt.interfaceNumber
elif alt.interfaceClass == CCID_CLASS and \
alt.interfaceSubClass == CCID_SUBCLASS and \
alt.interfaceProtocol == CCID_PROTOCOL_0:
for endpoint in alt.endpoints:
if endpoint.type == usb.ENDPOINT_TYPE_BULK:
if endpoint.address & usb.ENDPOINT_DIR_MASK == usb.ENDPOINT_IN:
self.__bulkin = endpoint.address
else:
self.__bulkout = endpoint.address
self.__bulkout = 1
self.__bulkin = 0x81
self.__timeout = 10000
self.__timeout = 100000
self.__seq = 0
def get_string(self, num):

View File

@@ -1,9 +1,9 @@
#! /usr/bin/python
#! /usr/bin/python3
"""
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
Copyright (C) 2012, 2015 Free Software Initiative of Japan
Copyright (C) 2012, 2015, 2021 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -70,7 +70,7 @@ def gpg_sign(keygrip, hash):
raise ValueError(binascii.hexlify(signed))
return signed
def main(keyno,keygrip, data_regnual, data_upgrade):
def main(keyno, keygrip, data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), b'\x00')
@@ -91,7 +91,7 @@ def main(keyno,keygrip, data_regnual, data_upgrade):
elif icc.icc_get_status() == 1:
icc.icc_power_on()
icc.cmd_select_openpgp()
challenge = icc.cmd_get_challenge().tostring()
challenge = icc.cmd_get_challenge().tobytes()
signed = gpg_sign(keygrip, binascii.hexlify(challenge))
icc.cmd_external_authenticate(keyno, signed)
icc.stop_gnuk()
@@ -107,17 +107,19 @@ def main(keyno,keygrip, data_regnual, data_upgrade):
del icc
icc = None
#
print("Wait 3 seconds...")
time.sleep(3)
# Then, send upgrade program...
reg = None
for dev in gnuk_devices_by_vidpid():
try:
reg = regnual(dev)
print("Device: %d" % dev.filename)
break
except:
pass
print("Waiting for device to appear:")
while reg == None:
print(" Wait {} second{}...".format(wait_e, 's' if wait_e > 1 else ''))
time.sleep(wait_e)
for dev in gnuk_devices_by_vidpid():
try:
reg = regnual(dev)
print("Device: %s" % dev.filename)
break
except:
pass
# Then, send upgrade program...
mem_info = reg.mem_info()
print("%08x:%08x" % mem_info)
print("Downloading the program")

View File

@@ -1,10 +1,10 @@
#! /usr/bin/python
#! /usr/bin/python3
"""
upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token
which is just shipped from factory
Copyright (C) 2012, 2013, 2015, 2018
Copyright (C) 2012, 2013, 2015, 2018, 2021
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -52,7 +52,7 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
gnuk.cmd_select_openpgp()
# Compute passwd data
try:
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring()
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tobytes()
except:
kdf_data = b""
if kdf_data == b"":
@@ -70,7 +70,7 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
gnuk.cmd_select_openpgp()
challenge = gnuk.cmd_get_challenge().tostring()
challenge = gnuk.cmd_get_challenge().tobytes()
digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge
signed = rsa.compute_signature(rsa_key, digestinfo)
signed_bytes = rsa.integer_to_bytes_256(signed)