Compare commits

...

230 Commits

Author SHA1 Message Date
2519f799fd Default acknowledgement button to yes 2022-07-30 13:29:09 +02:00
32f563a28d Add chopstx update for ST-Dongle 2022-07-30 13:15:50 +02:00
7b471948b4 How to reflash st-link 2022-07-30 12:55:04 +02:00
d2363c8ad8 Add DTS token 2022-07-30 12:40:24 +02:00
9306ad5043 Update how to flash firmware 2022-07-19 10:49:50 +02:00
54d031bc27 Remove docker as I will not be maintaning it 2022-07-19 10:42:06 +02:00
6909e0359c Add VID/PID 2022-07-19 10:39:40 +02:00
5acd8a23d9 Change serial 2022-07-19 10:39:11 +02:00
d5a539986e Correct OpenPGP version 2022-07-19 10:29:44 +02:00
8a19a2cb66 Update openocd documentation 2022-07-18 23:38:33 +02:00
5e4a264ac0 Update readme 2022-07-17 23:02:30 +02:00
a9079e8b5c Update readme 2022-07-17 22:41:25 +02:00
057920600f Update readme 2022-07-17 12:39:26 +02:00
7d1b5e4b71 Update readme 2022-07-17 12:28:58 +02:00
fe66b67317 Update readme 2022-07-17 12:25:42 +02:00
14f0acd749 Update readme 2022-07-17 12:20:41 +02:00
9ccbd5804a Update readme 2022-07-17 12:14:38 +02:00
b4b82e1557 Update readme 2022-07-17 11:52:09 +02:00
357a4b3510 Update readme 2022-07-17 11:44:42 +02:00
1fdb74eb10 Update readme 2022-07-17 10:57:37 +02:00
977a09f69f Update readme 2022-07-17 10:49:35 +02:00
cd271fbeb5 Update readme 2022-07-17 01:31:11 +02:00
7e17548610 Update readme 2022-07-17 01:28:57 +02:00
fd7a7c7dfa Update build section in README 2022-07-17 01:00:38 +02:00
8de235b26f Don't set default VID:PID 2022-07-17 00:57:08 +02:00
53cbb62738 Update readme 2022-07-17 00:47:47 +02:00
511f6de8b1 Change default configuration 2022-07-17 00:00:54 +02:00
0132723c7a Move license info into root of project 2022-07-16 23:59:01 +02:00
a37f7aca5c Update readme 2022-07-16 23:52:00 +02:00
531be827dd Remove unnecessary svg 2022-07-16 23:44:27 +02:00
d6c040400a Update readme 2022-07-16 23:28:47 +02:00
b8ada80163 Remove redundant files 2022-07-16 21:46:55 +02:00
1d63372017 Remove old ChangeLog 2022-07-16 21:24:23 +02:00
8dfbf63452 Fix compile bug when acknowledgement button is disabled 2022-07-16 20:56:25 +02:00
b9f6c3be7a Update submodule url 2022-07-16 20:05:23 +02:00
NIIBE Yutaka
9d3c08bd2b Version 1.2.20.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-22 11:19:41 +09:00
NIIBE Yutaka
a909502388 Update Chopstx to 1.21.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-22 11:17:22 +09:00
NIIBE Yutaka
286b620648 Fix for address calculation and access to object on memory.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-22 10:36:13 +09:00
Bertrand Jacquin
cce65c6d34 regnual: remove duplicate type declaration. 2022-03-29 15:11:24 +09:00
NIIBE Yutaka
57fdadf283 Version 1.2.19.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-12 11:42:44 +09:00
NIIBE Yutaka
870de72ee2 configure: Allow override of kdf_do variable.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-10-11 11:51:55 +09:00
NIIBE Yutaka
fa667b04f7 configure: Add KDF configuration.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-07-01 13:43:42 +09:00
Bertrand Jacquin
2a72f3df08 regnual: add missing header
regnual.c:32:1: note: ‘memset’ is declared in header ‘<string.h>’
2021-06-15 10:56:57 +09:00
NIIBE Yutaka
db2527459f Fix scripts.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-06-10 14:31:45 +09:00
NIIBE Yutaka
1ca3bbdaae Fix for key attributes (long standing bug).
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-30 13:55:52 +09:00
NIIBE Yutaka
98119dc991 Version 1.2.18.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-02 16:58:04 +09:00
NIIBE Yutaka
03cca1e451 Write ChangeLog entries and AUTHORS.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-02 16:53:56 +09:00
NIIBE Yutaka
3f65bf73e8 Add a check to make sure device is the one intended.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-04-01 16:23:39 +09:00
NIIBE Yutaka
07be37f45e Fix tests for Gnuk emulation (skip test with no KDF setup).
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-19 17:37:32 +09:00
Vincent Pelletier
dcef6e0ffa tests/card_test_personalize_card.py: Exercise ECDH, X25519 and ED25519.
ECDH curves exercised are OpenPGP recommended set: ANSIx9p{256,384,521}r1
and BRAINPOOLp{256,384,512}r1, plus X25519 and ED25519.
Signature is only tested (for now ?) with ED25519 as other signature schemes
are (usually) non-deterministic and require implementing the signature
verification algorithm rather than just testing for equality with a test
vector.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
2021-03-19 16:09:03 +09:00
NIIBE Yutaka
d31687ebd6 Fix typo of configure.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-12 12:07:57 +09:00
NIIBE Yutaka
92443f8f07 Fix previous change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-03-12 03:00:44 +09:00
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
NIIBE Yutaka
49f2544918 Version 1.2.15.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-01-24 12:48:49 +09:00
NIIBE Yutaka
d156fc6261 Add ChangeLog. 2020-01-23 15:09:45 +09:00
Bertrand Jacquin
81d6945081 tool: switch to python3
python2 is no longer maintained upstream
2020-01-14 14:07:55 +09:00
NIIBE Yutaka
c3e9db14e8 Update Chopstx to 1.18.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-12-30 11:03:49 +09:00
NIIBE Yutaka
9180c35420 Fix bn.c. 2019-06-18 11:10:33 +09:00
NIIBE Yutaka
cc0d59cfe6 tests: Power off the reader at the end of test suite. 2019-04-09 10:55:38 +09:00
NIIBE Yutaka
9c1368fdd0 tests: Fix time extension S block responce to TPDU reader. 2019-04-04 15:44:58 +09:00
NIIBE Yutaka
2dd5a76002 tests: Fix timer extension handling. 2019-04-03 17:03:35 +09:00
NIIBE Yutaka
f68ff0bddc tests: Support keygen by OpenPGP card. 2019-04-03 17:02:37 +09:00
NIIBE Yutaka
add3299306 tests: KDF feature is Gnuk only. 2019-04-03 17:01:11 +09:00
NIIBE Yutaka
e28ec2c4c4 tests: Skip Gnuk only tests. 2019-04-03 14:51:32 +09:00
NIIBE Yutaka
1ba05a0f0f tests: factor out tests into classes. 2019-04-03 13:49:55 +09:00
NIIBE Yutaka
2d50795d0a tests: Skip Gnuk only test. 2019-04-03 09:45:06 +09:00
NIIBE Yutaka
fd493562c3 Add OpenPGP card v3.3 card factory reset setup. 2019-04-02 17:29:56 +09:00
NIIBE Yutaka
16c6af215a tests: Use 3.3V for the card. 2019-04-02 13:19:56 +09:00
NIIBE Yutaka
177ef67edf Version 1.2.14. 2019-03-04 11:36:18 +09:00
NIIBE Yutaka
126283b1ac Add count for tool/gnuk_get_random.py. 2019-02-24 15:12:12 +09:00
NIIBE Yutaka
076d727061 Fix timeout initialization at receiving command. 2019-02-24 13:59:59 +09:00
NIIBE Yutaka
41fa424450 Fix for ack button. 2019-02-24 13:04:28 +09:00
NIIBE Yutaka
940332c47f Change for firmware upgrade and ack-button. 2019-02-22 19:53:52 +09:00
NIIBE Yutaka
aedf8267ec Change the constant values for eventflag.
I misunderstood semantics of __builtin_ffs function which prefers
less significant 1-bit.
2019-02-22 14:26:46 +09:00
NIIBE Yutaka
e9d9de3ae2 Implement timeout for the user interaction. 2019-02-22 09:21:11 +09:00
NIIBE Yutaka
fc109fd8af Add GnuPG e.V.'s VID:PID. 2019-02-21 11:39:37 +09:00
NIIBE Yutaka
3d06051a32 Comment in the commit log fix.
In the commit of e760d5b780, I wrote
wrong comment.  The nvic_system_reset function lets MCU go through by
the vectors at 0x08000000.  Thanks to Peter Lebbing to confirm this
fact.
2018-12-31 19:07:33 +09:00
NIIBE Yutaka
b7368e41e9 Version 1.2.13. 2018-12-26 14:14:11 +09:00
NIIBE Yutaka
e760d5b780 Add ChangeLog entry for Peter's changes.
Note that the call of nvic_system_reset from device_initialize_once
uses the old RESET vector.
2018-12-26 14:10:20 +09:00
Peter Lebbing
b57c33c204 Fix make {,dist}clean 2018-12-22 14:42:34 +01:00
Peter Lebbing
ca3312eb25 DFU fix: Copy initial MSP, reset after protect 2018-12-22 14:08:54 +01:00
NIIBE Yutaka
6a1f50abda Add ChangeLog entries for Peter's changes. 2018-12-21 10:30:16 +09:00
Peter Lebbing
66f39c57cd DFU support: overwrite DFU with SYS and protect flash 2018-12-21 10:10:57 +09:00
Peter Lebbing
4b5f93624e Build standalone SYS 2018-12-21 09:57:04 +09:00
Peter Lebbing
0ef687ea4c Add ORIGIN_REAL, emit more configure variables
ORIGIN{,_REAL} is made available to C and USE_DFU is made available to
make.
2018-12-21 09:53:12 +09:00
Peter Lebbing
786b4adc42 Use different ORIGIN for DFU on Maple Mini 2018-12-21 09:49:43 +09:00
NIIBE Yutaka
385261c9a0 Update Chopstx to 1.13. 2018-12-20 14:02:30 +09:00
NIIBE Yutaka
65689199e7 Fix order of EV_* for CCID thread.
Since openpgp thread has lower priority than CCID thread, there is no
case where two consecutive messages EV_EXEC_ACK_REQUIRED and
EV_EXEC_FINISHED are handled simultaneously (openpgp thread needs to
work some time to send EV_EXEC_FINISHED, after sending
EV_EXEC_ACK_REQUIRED).  But just in case, when there are two messages
at once, EV_EXEC_ACK_REQUIRED should been handled before
EV_EXEC_FINISHED.
2018-12-07 08:35:27 +09:00
NIIBE Yutaka
8d15086d06 Really fix the last race condition.
Fixes the commit of fc36773.
2018-12-06 12:09:42 +09:00
NIIBE Yutaka
c17fd5401b Support Ack button for firmware update. 2018-12-05 15:36:16 +09:00
NIIBE Yutaka
56cd4ae7b5 Fix for UIF DO. 2018-12-04 17:22:04 +09:00
NIIBE Yutaka
fc36773c6a Fix hopefully the last race condition for tx_busy handling. 2018-12-01 23:28:19 +09:00
NIIBE Yutaka
7249775c17 Version 1.2.12. 2018-11-25 14:37:09 +09:00
NIIBE Yutaka
980cff0a2f Fix another race condition around ack button and usb communication. 2018-11-21 14:56:56 +09:00
NIIBE Yutaka
8f44f5d3c6 Unique 96-bit looks different on GD32F103.
Depending on MHZ, we change how we get the 96-bits.
2018-11-17 19:01:59 +09:00
NIIBE Yutaka
37a84ed218 Version 1.2.11. 2018-11-12 14:44:18 +09:00
NIIBE Yutaka
6c72147248 Always enable ACKBTN support. 2018-11-12 14:25:22 +09:00
NIIBE Yutaka
3d37003d8c Fix tool/kdf_calc.py. 2018-11-09 20:52:15 +09:00
NIIBE Yutaka
becf8fabc5 Fix synchronous sending. 2018-11-09 20:50:35 +09:00
NIIBE Yutaka
17492287f3 Fix cmd_pso and cmd_internal_authenticate. 2018-11-09 18:57:51 +09:00
NIIBE Yutaka
c800dee95e Sending from Gnuk Token is now synchronous. 2018-11-09 16:38:14 +09:00
NIIBE Yutaka
2c390dc763 Minor fixes for usb-ccid.c. 2018-11-09 15:23:33 +09:00
NIIBE Yutaka
5aee75fd4b Remove unused CCID_STATE_RECEIVE and CCID_STATE_SEND state.
It was used before when Gnuk uses extended APDU exchange (7 years ago).
2018-11-09 12:57:41 +09:00
NIIBE Yutaka
69e8c0f334 It also works with Python3. 2018-10-22 14:26:21 +09:00
NIIBE Yutaka
317cc2036d Fix UIF interaction. 2018-10-12 11:54:41 +09:00
NIIBE Yutaka
312d15c3fa Tweak stack size. 2018-10-02 19:10:56 +09:00
NIIBE Yutaka
d356f1b1e0 doc: Fix by Fabio Utzig for scdaemon. 2018-10-02 13:31:03 +09:00
NIIBE Yutaka
9cb6591491 Update Chopstx to 1.11. 2018-10-02 13:30:51 +09:00
NIIBE Yutaka
ebec8ee156 UI change for LED blink. 2018-10-01 14:36:56 +09:00
NIIBE Yutaka
f810fb83d3 Allow parallel execution waiting ACK. 2018-10-01 14:06:31 +09:00
NIIBE Yutaka
12079974fd Fix UIF DO handling. 2018-09-27 22:29:49 +09:00
NIIBE Yutaka
ca79f5421f Fix rw_uif. 2018-09-27 16:38:07 +09:00
NIIBE Yutaka
c438367d67 Add UIF Data Object support for Acknowledge Button. 2018-09-27 15:02:43 +09:00
NIIBE Yutaka
4c6511231c Blink LED rapidly when asking ACK from user. 2018-09-27 13:16:51 +09:00
NIIBE Yutaka
ba750d153d Fix for ack button driver and configuration. 2018-09-27 11:29:46 +09:00
NIIBE Yutaka
72647f01d0 Remove ack-button.c to use the driver in Chopstx. 2018-09-27 10:46:18 +09:00
NIIBE Yutaka
c6e32a36fb Experimental Ack-button feature added (not yet finished). 2018-09-27 07:30:17 +09:00
NIIBE Yutaka
c3a0eb1439 Doc fix for udev rules (use ATTR instead of ATTRS). 2018-09-26 13:57:42 +09:00
NIIBE Yutaka
030a9c576d Update for new Chopstx API. 2018-09-26 13:24:19 +09:00
NIIBE Yutaka
8a5e0eb783 Fix README about -no-vidpid file name. 2018-08-23 14:30:07 +09:00
NIIBE Yutaka
bce53546e7 Fix for GCC 7. 2018-08-20 16:09:13 +09:00
NIIBE Yutaka
b2b19e1ad4 Add ChangeLog entry. 2018-07-13 16:28:29 +09:00
Szczepan Zalega
58fa773bb7 Fix typo
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2018-07-13 16:24:06 +09:00
Szczepan Zalega
ea88c3da66 Catch exception, when no KDF data is found
While updating from GNUK 1.2.6, upgrade_by_passwd.py script shows
exception about not found referenced data:
  File "./upgrade_by_passwd.py", line 55, in main
    kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring()
  File "/home/sz/work/nitrokey-start-firmware/tool/gnuk_token.py", line 320, in cmd_get_data
    raise ValueError("%02x%02x" % (sw[0], sw[1]))
ValueError: 6a88

While it is checked, whether the KDF DO is empty, there is no
exception catch for not found object. This patch adds it.
Tested update paths 1.2.6 -> 1.2.10, 1.2.6 -> 1.2.6, 1.2.10 -> 1.2.10, 1.2.10 -> 1.2.6.

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2018-07-13 16:23:58 +09:00
NIIBE Yutaka
b905b4802f Version 1.2.10. 2018-05-10 13:54:21 +09:00
NIIBE Yutaka
40f2c6c49e Version 1.2.10. 2018-05-10 13:53:09 +09:00
NIIBE Yutaka
61a7f9602b gnuk.elf is the target with VID:PID. New target gnuk-no-vidpid.elf. 2018-05-10 12:09:19 +09:00
NIIBE Yutaka
5465fda927 Update Chopstx to 1.9. 2018-05-10 12:04:37 +09:00
NIIBE Yutaka
f7c46a6c55 More usb_device_reset fix. 2018-04-26 21:23:44 +09:00
NIIBE Yutaka
4550458806 Fix USB initialization.
After USB RESET, all endpoints registers are being reset.  So,
there is no need to let each endpoint stall (it's disabled).
Actually, it's wrong to call usb_lld_stall_rx or usb_lld_stall_tx
before usb_lld_setup_endpoint, because other fields of endpoint
register are not specified after RESET.
2018-04-26 21:22:36 +09:00
NIIBE Yutaka
93a2bac94b Support GD32F103. 2018-04-26 17:33:48 +09:00
NIIBE Yutaka
24adc09406 Version 1.2.9. 2018-04-05 14:00:50 +09:00
NIIBE Yutaka
bf9fc628b3 More tests for admin-less mode. 2018-04-05 13:06:13 +09:00
NIIBE Yutaka
d76534dd3a Fix admin-less mode -> admin-full mode change. 2018-04-05 12:13:45 +09:00
NIIBE Yutaka
d9c5dcf206 Update ChangeLog. 2018-04-04 19:33:56 +09:00
NIIBE Yutaka
26448d58ee Update copyright year. 2018-04-04 19:29:35 +09:00
NIIBE Yutaka
9cfeb817bd More check for length of PW1. 2018-04-04 19:28:42 +09:00
NIIBE Yutaka
b6534dceba Fix removal of resetting code. 2018-04-04 18:59:28 +09:00
NIIBE Yutaka
b47bd693ba More tests (3). 2018-04-04 17:42:14 +09:00
NIIBE Yutaka
1a7d3a698f More tests (2). 2018-04-04 16:34:51 +09:00
NIIBE Yutaka
f7b03f7fb5 More tests. 2018-04-04 16:34:07 +09:00
NIIBE Yutaka
44971541fe More test suite improvement. Add experimental KDF DO tests. 2018-04-04 15:44:34 +09:00
NIIBE Yutaka
53ed5e0a42 Test suite improvement. 2018-04-04 15:10:52 +09:00
NIIBE Yutaka
63eccda0a1 Add a test case to reset PW3. 2018-04-04 10:51:32 +09:00
NIIBE Yutaka
f430c90715 Rename tests. 2018-04-04 08:48:40 +09:00
NIIBE Yutaka
1f18ec1d63 Clear all keystrings when KDF DO is written. 2018-04-03 20:24:28 +09:00
NIIBE Yutaka
ec7423f493 Fix tool/. 2018-04-03 17:17:51 +09:00
NIIBE Yutaka
e50dda28d1 Support authentication with KDF Data Object. 2018-04-03 17:17:39 +09:00
NIIBE Yutaka
8ad176921f Fix kdf_calc.py. 2018-04-03 17:17:28 +09:00
NIIBE Yutaka
d71b116be8 Add kdf_calc.py. 2018-04-03 17:17:20 +09:00
NIIBE Yutaka
d9d3f35ac3 Fix previous commit. 2018-03-30 17:46:52 +09:00
NIIBE Yutaka
7cc8d8930e Support single-salt KDF for admin-less mode. 2018-03-30 15:57:34 +09:00
NIIBE Yutaka
6446a5bd89 KDF format validation should be done before removing data object. 2018-03-22 16:03:56 +09:00
NIIBE Yutaka
8b0cb8be65 factory-reset should erase all upgrade public keys. 2018-03-13 14:05:18 +09:00
NIIBE Yutaka
c73bb0548e Fix KDF DO handling. 2018-02-13 07:26:29 +09:00
NIIBE Yutaka
40b1d453dc Fix .gitignore. 2018-01-23 13:47:46 +09:00
NIIBE Yutaka
3b965fafc0 Fix README. 2018-01-23 13:26:41 +09:00
NIIBE Yutaka
35edbdc731 Version 1.2.8. 2018-01-23 10:13:13 +09:00
NIIBE Yutaka
d4c776e308 Fix the procedure to put VID:PID. Apply the procedure to regnual. 2018-01-23 10:11:35 +09:00
NIIBE Yutaka
6c0c510347 Update documentation. 2018-01-23 09:31:03 +09:00
NIIBE Yutaka
704d8a5cf1 Check passphrase length when changing. 2018-01-22 11:55:10 +09:00
NIIBE Yutaka
55781cb7bb Remove keystring with BY_ADMIN when it's becomming admin-less mode. 2018-01-22 11:02:02 +09:00
NIIBE Yutaka
de24655920 VIDPID substitution at the last stage of build. 2018-01-19 22:36:01 +09:00
NIIBE Yutaka
7bfe0f5427 Add binary-edit.sh. 2018-01-19 22:22:29 +09:00
NIIBE Yutaka
ec058537ed Update Chopstx to 1.8. 2018-01-19 22:15:21 +09:00
NIIBE Yutaka
abeb1015ec Update neug.c. 2018-01-18 19:42:40 +09:00
NIIBE Yutaka
c5f20dc355 Update Chopstx and follow the changes. 2018-01-18 15:14:34 +09:00
NIIBE Yutaka
4ff0b3c5f8 tests: Fix for card readers. 2018-01-09 09:39:42 +09:00
NIIBE Yutaka
4e517778d0 Update Chopstx to 1.7. 2017-12-19 10:24:28 +09:00
NIIBE Yutaka
c81544fffd Fix long-standing bug of admin-less mode. GnuPG should be fixed. 2017-11-26 21:20:46 +09:00
NIIBE Yutaka
ad42010272 Version 1.2.7. 2017-11-26 19:38:26 +09:00
NIIBE Yutaka
8ce91267be Fix regnual. 2017-11-26 19:28:03 +09:00
NIIBE Yutaka
b5c2ace2ae NEWS update. 2017-11-25 15:02:51 +09:00
NIIBE Yutaka
4cbc661fb7 Update Chopstx to 1.6. 2017-11-24 20:53:40 +09:00
NIIBE Yutaka
543f28574e Use of eventflag poll change. 2017-11-17 20:10:13 +09:00
NIIBE Yutaka
fe94e1885b LED status loop change.
Using chopstx_poll, it requires more memory on stack.
2017-11-17 17:20:52 +09:00
NIIBE Yutaka
ce82b347f9 Make sure to turn off LED soon. 2017-11-17 16:25:26 +09:00
NIIBE Yutaka
d54712c04c Less power consumption on suspend. 2017-11-17 15:49:56 +09:00
NIIBE Yutaka
9c63c874d0 Fix ReGNUal. 2017-11-17 15:47:59 +09:00
NIIBE Yutaka
bb9b31166f Fix NeuG for CRC module clock setting. 2017-11-17 15:47:22 +09:00
NIIBE Yutaka
e417846408 More change for USB suspend. 2017-11-17 12:29:32 +09:00
NIIBE Yutaka
21a481060c Make sure to turn off LED on suspend. 2017-11-16 13:08:00 +09:00
NIIBE Yutaka
d4c9d6653b Use const pointer for chopstx_poll. 2017-11-16 09:17:33 +09:00
NIIBE Yutaka
f00306627b Fix pin-cir.c for use of EXTI. 2017-11-16 08:40:49 +09:00
NIIBE Yutaka
f4b36b7503 Lower power consumption on suspend. 2017-11-15 10:59:55 +09:00
NIIBE Yutaka
e85527d302 USB suspend/resume change. 2017-11-14 12:59:18 +09:00
NIIBE Yutaka
bd58997dc9 Possibly support other hash in future, for KDF. 2017-11-08 10:28:55 +09:00
NIIBE Yutaka
9d5834d47b Avoid passphrase-error-lock by old GnuPG. 2017-11-07 13:48:08 +09:00
NIIBE Yutaka
36ecf67694 Update tool information in README. 2017-11-06 15:29:02 +09:00
NIIBE Yutaka
c9b1e511ba Fix test and tests. 2017-11-06 10:51:11 +09:00
NIIBE Yutaka
01b5aa5984 Enable KDF-DO available bit. 2017-11-02 13:53:06 +09:00
NIIBE Yutaka
b735c02ec2 Implement use of KDF data object. 2017-11-02 10:59:17 +09:00
NIIBE Yutaka
2ecb104ae4 Implement rw_kdf. 2017-11-02 09:28:43 +09:00
NIIBE Yutaka
6b4f3c9934 Start adding KDF-DO of OpenPGPcard v3. 2017-11-01 16:52:58 +09:00
NIIBE Yutaka
660aaeb04b Bug fix for keygeneration. 2017-10-31 17:10:03 +09:00
NIIBE Yutaka
1022534c02 Fix gpg_do_keygen. 2017-10-30 15:01:17 +09:00
Daniel Kahn Gillmor
46cc64cf03 fix documentation typo 2017-10-25 16:54:41 +09:00
NIIBE Yutaka
effc65381a Don't change PPS for other readers. 2017-10-24 20:39:51 +09:00
Aurelien Jarno
6cbf5a4822 linker script: fix keystore_pool size
Gnuk supports RSA keys up to 4096 bits. This require 1024 bytes of
storage (p and q are 256 bytes, n is 512 bytes). The linker script
should therefore reserve 1024 bytes per key instead of 512.

In practice it's not an issue at all as all supported MCU have a page
size bigger than 1024 bytes and Gnuk use one page per key.
2017-10-19 14:31:12 +09:00
NIIBE Yutaka
8ff3865890 Update ChangeLog, README, AUTHORS, and THANKS. 2017-10-17 15:26:46 +09:00
Aurelien Jarno
43009f39e8 polarssl: use a bigger sliding window when possible 2017-10-17 15:01:17 +09:00
Aurelien Jarno
56fb5002bf malloc: rename MEMORY_ into HEAP_
That way MEMORY_SIZE can be exported in a later patch.
2017-10-17 15:01:13 +09:00
Aurelien Jarno
3bb5097031 polarssl: add ARM DSP optimized mpi_montsqr 2017-10-17 15:01:09 +09:00
Aurelien Jarno
8319f4a14b polarssl: replace BIGNUM_C_IMPLEMENTATION check
Replace the BIGNUM_C_IMPLEMENTATION check by a check on POLARSSL_HAVE_ASM
and __arm__. This way it's possible to use this code on non arm, but
also to run the GNU/Linux emulation on an arm machine, which is useful
for debugging and profiling.
2017-10-17 15:01:06 +09:00
Aurelien Jarno
f7cf0a3461 polarssl: add ARM DSP optimized MULADDC code
The Cortex M4, M7 MCUs and the Cortex A CPUs support the ARM DSP
instructions, and especially the umaal instruction which greatly
speed up MULADDC code.
2017-10-17 15:01:03 +09:00
Aurelien Jarno
5ac52d3f2f polarssl: rename MULADDC_HUIT into MULADDC_HUIT_DEAD
As the comment above said, it's dead code. Renaming it make sure it's
not used by mistake, for example when testing/debugging code.
2017-10-17 15:01:00 +09:00
Aurelien Jarno
209d459d09 polarssl: fix build without POLARSSL_HAVE_ASM
This fixes building polarssl for architectures without assembly code or
when POLARSSL_HAVE_ASM is not defined.

This has been done in upstream commit a755ca1bbe, but somehow the
generic version has been missed in gnuk's version.
2017-10-17 15:00:55 +09:00
114 changed files with 4203 additions and 7098 deletions

4
.gitignore vendored
View File

@@ -1,16 +1,20 @@
*.lst
*.o
*.pyc
regnual/regnual-no-vidpid.elf
src/.dep
src/config.mk
src/config.h
src/gnuk.ld
src/stdaln-sys.ld
src/board.h
src/build/*
src/*.inc
src/put-vid-pid-ver.sh
regnual/regnual.bin
regnual/regnual.hex
regnual/regnual.elf
doc/_build
tests/.cache
tests/__pycache__
tests/.pytest_cache

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "chopstx"]
path = chopstx
url = ../../chopstx/chopstx.git
url = ../chopstx.git

60
AUTHORS
View File

@@ -1,60 +0,0 @@
Anthony Romano:
Modified:
src/call-rsa.c
src/main.c
src/mod.c
Jeremy Drake:
Modified:
regnual/regnual.c
Kaz Kojima:
Added STM32 Primer2 support.
NIIBE Yutaka:
Founder of the project.
Wrote tools for STLink/V2:
tool/stlinkv2.py
Wrote tools for DfuSe:
tool/dfuse.py
tool/dump_mem.py
tool/intel_hex.py
Wrote a tool for Gnuk:
tool/gnuk_put_binary.py
tool/gnuk_put_binary_libusb.py
tool/gnuk_remove_keys.py
tool/gnuk_upgrade.py
Wrote a tool for USB Hub:
tool/hub_ctrl.py
Wrote a tool for testing card reader with pinpad:
tool/pinpadtest.py
Wrote reGNUal implementation:
regnual/regnual.c
regnual/sys.c
Wrote Gnuk implementation:
gnuk.svg
src/configure
src/ac.c
src/call-rsa.c
src/debug.c
src/flash.c
src/gnuk.h
src/main.c
src/neug.c
src/openpgp-do.c
src/openpgp.c
src/openpgp.h
src/pin-cir.c
src/pin-dial.c
src/pin-dnd.c
src/random.c
src/sys.c
src/usb-icc.c
src/usb-msc.c
src/usb-msc.h
src/usb_ctrl.c
src/usb_desc.c
src/usb_lld.c
src/usb_lld.h
*
and others.

2197
ChangeLog

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
# 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.
1337:0010 0200 Gnuk Token Deon Spengler
##########<TAB> ##<TAB> ##########<TAB> #################

258
NEWS
View File

@@ -1,5 +1,256 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.20
Released 2022-04-22, by NIIBE Yutaka
** Minor fixes for newer compiler
For build with newer compiler, Gnuk and regnual are fixed for address
calculation and access to object on memory, as well as declarations of
function and type in standard C library.
** Upgrade of Chopstx
We use Chopstx 1.21. This includes fix to silence compiler warnings.
* Major changes in Gnuk 1.2.19
Released 2021-10-12, by NIIBE Yutaka
** KDF Data Object configuration
KDF Data Object should be highly recommended for all configurations.
Nevertheless, for backward compatibillity, in Gnuk 1.2, it is optional
by default; It is up to user to configure KDF Data Object before
importing private keys. In this situation, it is not good to
introduce new build-time option like --enable-always-require-kdf-do,
because it might wrongly encourage use of Gnuk with no KDF Data Object
setting, by confusion. If needed, please run configure:
kdf_do=required ./configure --enable-factory-reset --target...
or
kdf_do=optional ./configure --enable-factory-reset --target...
Please note that such a use of variable by shell command line is not
well supported by the configure script (for other variables), but
override of kdf_do is needed in some situations.
** Upgrade of Chopstx
We use Chopstx 1.20. This enables use with PC/SC for GNU/Linux
emulation.
* Major changes in Gnuk 1.2.18
Released 2021-04-02, by NIIBE Yutaka
** GNU/Linux emulation bug fix
This time, for GNU/Linux emulation, KDF Data Object is required before
keygen and key import, really.
** tool/upgrade_by_passwd.py
Now, it checks if the target of binary being written and the
configured target of running device are same. This check can be
skipped by -s option. Please note that FST-01 and FST-01SZ are
different target, as it's MHz is different.
* Major changes in Gnuk 1.2.17
Released 2021-02-25, by NIIBE Yutaka
** 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
** 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
** DFU support and its firmware upgrade fix
DFU support was not well maintained, and firmware upgrade was not
possible for boards with DFU. Now, at least for Maple Mini, it is
tested. Note that using Gnuk with DFU on a board is only for an
experiment, because DFU can access the content of flash ROM. DFU
should be killed by upgrading to normal Gnuk, so that you can have
your private keys.
** Fix for UIF Data Object
When flash ROM is full and coping to new page, UIF DO was not properly
copied. This bug resulted losing the flag for user interaction. Now,
it's properly copied, keeping the setting of the feature.
** Upgrade of Chopstx
We use Chopstx 1.13.
* Major changes in Gnuk 1.2.12
Released 2018-11-25, by NIIBE Yutaka
** FST-01SZ fixes
Fixes for Ack button support and serial number.
* Major changes in Gnuk 1.2.11
Released 2018-11-12, by NIIBE Yutaka
** Experimental ACK button support with FST-01SZ
While OpenPGP card specification verison 3 has description for the
"user interaction" button and data objects, there were no
implementation. To evaluate the feature, experimental support is
added.
** Upgrade of Chopstx
We use Chopstx 1.12, which comes with ACK button driver and supports
FST-01SZ.
* Major changes in Gnuk 1.2.10
Released 2018-05-10, by NIIBE Yutaka
** No inclusion of VID:PID in gnuk-no-vidpid.elf
Now, we have new file named gnuk-no-vidpid.elf with no VID:PID. The
file gnuk.elf has the VID:PID, like version 1.2.7 or older.
** Upgrade of Chopstx
We use Chopstx 1.9, which supports GD32F103.
* Major changes in Gnuk 1.2.9
Released 2018-04-05, by NIIBE Yutaka
** A test suite fix: Clear PW3
Until 1.2.8, after running the test suite under "tests", PW3 keystring
remained, which affects use of admin-less mode. New test case is
added to clear PW3.
** tool/upgrade_by_passwd.py supports KDF-DO auth
With KDF-DO, firmware upgrade didn't work. Now, it's supported.
** Add "single-salt" support for KDF-DO
With KDF-DO, "admin-less" mode didn't work well. With new feature of
"single-salt" support, we can use "admin-less" mode with KDF-DO.
** factory-reset deletes all upgrade public keys
By card-edit/factory-reset by GnuPG, it deletes all upgrade public
keys, now.
* Major changes in Gnuk 1.2.8
Released 2018-01-23, by NIIBE Yutaka
** No inclusion of VID:PID in gnuk.elf
Distribution of binary image with VID:PID would violate vendor ID
agreement to USB Forum. Now, we have new file named gnuk-vidpid.elf
for flashing. The file gnuk.elf can be used to generate
gnuk-vidpid.elf and we can check if it is reproducible or not.
** Passphrase length check
Now, Gnuk checks length of passphrase if it's too short when
changing passphrase.
** Remove unused DEK with BY_ADMIN
For admin-less mode, DEK by OPENPGP_CARD_INITIAL_PW3 remained on flash
ROM. This could be considered a backdoor, if some other person had or
kept access to the flash ROM, cheating a user. Now, the DEK is
cleared by zero when the token is set to admin-less mode.
** Upgrade of Chopstx
We use Chopstx 1.8.
* Major changes in Gnuk 1.2.7
Released 2017-11-26, by NIIBE Yutaka
** reGNUal
reGNUal enables CRC module by itself.
** Flash update change
CRC module is disabled when Gnuk stops. It's reGNUal which needs to
enable CRC module.
** Support of USB suspend
USB suspend and wakeup event are now handled.
** KDF-DO support and KDF by host
KDF-DO is now available. Host can use this feature.
** Upgrade of Chopstx
We use Chopstx 1.6.
* Major changes in Gnuk 1.2.6
Released 2017-10-11, by NIIBE Yutaka
@@ -782,6 +1033,7 @@ Gnuk Token could run with GPG4WIN on MS Windows. GPG4WIN runs with
** This is initial release. Only it supports digital signing.
Local Variables:
mode: outline
End:
# Local Variables:
# mode: outline
# End:

629
README
View File

@@ -1,629 +0,0 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.6
2017-10-11
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.6, 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 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,
because the device doesn't have enough memory.
With this release, you can test how Gnuk Token works on GNU/Linux,
without real hardware, by USBIP emulation (--target=GNU_LINUX).
Please note that this emulation is intended only for testing. When
Gnuk does crypto computation on host, it is vulnerable by side channel
attacks.
What's Gnuk?
============
Gnuk is an implementation of USB cryptographic token for GNU Privacy
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
STM32F103 processor.
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
been nervous of storing secret key(s) on usual secondary storage.
There is a solution with OpenPGP card, but it is not the choice for
me, as card reader is not common device. With Gnuk, this issue will
be solved by a USB token.
Please look at the graphics of "gnuk.svg" for the software name. My
son used to be with his NUK(R), always, everywhere. Now, I am with a
USB Cryptographic Token by "Gnuk", always, everywhere.
FAQ
===
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, YubiKey, etc.) ?
https://www.g10code.de/p-card.html
https://www.yubico.com/
A0: Good points of Gnuk are:
* If you have skill of electronics and like DIY, you can build
Gnuk Token cheaper (see Q8-A8).
* You can study Gnuk to modify and to enhance. For example, you
can implement your own authentication method with some sensor
such as an acceleration sensor.
* It is "of Free Software"; Gnuk is distributed under GPLv3+,
"by Free Software"; Gnuk development requires only Free Software
(GNU Toolchain, Python, etc.),
"for Free Software"; Gnuk supports GnuPG.
Q1: What kind of key algorithm is supported?
A1: Gnuk version 1.0 only supports RSA-2048.
Gnuk version 1.2.x supports 255-bit EdDSA, as well as RSA-4096.
(Note that it takes long time to sign with RSA-4096.)
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.
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.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.18 in
unstable.
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
Token without them.
I tested pcscd 1.5.5-4 and libccid 1.3.11-2 which were in Debian
squeeze.
Q6: What kinds of hardware is required for development?
A6: You need a target board plus a JTAG/SWD debugger. If you just
want to test Gnuk for target boards with DfuSe, JTAG debugger is
not the requirement. Note that for real use, you need JTAG/SWD
debugger to enable flash ROM protection.
Q7: How much does it cost?
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
Q8: How much does it cost for DIY version?
A8: STM32 Nucleo F103 costs about $10 USD.
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
A9: Older GnuPG's SCDaemon has problems for handling insertion/removal of
card/reader. When your newly inserted token is not found by
GnuPG, try killing scdaemon and let it to be invoked again. I do:
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
and confirm scdaemon doesn't exist, then,
$ gpg-connect-agent learn /bye
Qa: With GNOME 2, I can't use Gnuk Token for SSH. How can we use it for SSH?
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
gpg-agant for the role of ssh-agent. For gnome-keyring please do:
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
Qb: With GNOME 3.0, I can't use Gnuk Token at all. Why?
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
$ gnome-session-properties
and at the tab of "Startup Programs", disable check buttons for
"GPG Password Agent" and "SSH Key Agent".
Qc: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
disable the invocation of gnome-keyring-daemon. In Debian
wheezy, it's in the files /etc/xdg/autostart/gnome-keyring-ssh.desktop
and /etc/xdg/autostart/gnome-keyring-gpg.desktop.
We have a line something like:
OnlyShowIn=GNOME;Unity;MATE;
Please edit this line to:
OnlyShowIn=
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.
Tested features
===============
Gnuk is tested by test suite. Please see the test directory.
* Personalization of the card
* Changing Login name, URL, Name, Sex, Language, etc.
* Password handling (PW1, RC, PW3)
* Key import for three types:
* key for digital signing
* key for decryption
* key for authentication
* PSO: Digital Signature
* PSO: Decipher
* INTERNAL AUTHENTICATE
* Changing value of password status bytes (0x00C4): forcesig
* Verify with pin pad
* Modify with pin pad
* Card holder certificate (read)
* Removal of keys
* Key generation on device side for RSA-2048
* Overriding key import
Original features of Gnuk, tested manually lightly:
* OpenPGP card serial number setup
* Card holder certificate (write by UPDATE BINARY)
* Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal
It is known not-working well:
* It is known that the specific combination of libccid 1.4.1
(or newer) with libusb 1.0.8 (or older) had a minor problem.
It is rare but it is possible for USB communication to be
failed, because of a bug in libusb implementation. Use
libusbx 1.0.9 or newer, or don't use PC/SC, but use internal
CCID driver of GnuPG.
Targets
=======
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01).
With DfuSe support, STBee is also our targets. But this target with
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
============================
Makefile is written for GNU make. You need Bash 4.x for configure.
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.
Python 2.7 and PyUSB 0.4.3 is assumed.
Souce code
==========
Gnuk source code is under src/ directory.
Note that SHA-2 hash function implementation, src/sha256.c, is based
on the original implementation by Dr. Brian Gladman. See:
http://brg.a2hosted.com//oldsite/cryptography_technology/sha/index.php
(was at:
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php)
License
=======
It is distributed under GNU General Public Licence version 3 or later
(GPLv3+). Please see src/COPYING.
Please note that it is distributed with external source code too.
Please read relevant licenses for external source code as well.
The author(s) of Gnuk expect users of Gnuk will be able to access the
source code of Gnuk, so that users can study the code and can modify
if needed. This doesn't mean person who has a Gnuk Token should be
able to access everything on the Token, regardless of its protections.
Private keys, and other information should be protected properly.
External source code
====================
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 1.5
We use Chopstx as the kernel for Gnuk.
Chopstx is distributed under GPLv3+ (with a special exception).
* polarssl/ -- based on PolarSSL 1.2.10 (now mbedTLS)
Souce code taken from: http://polarssl.org/
We use PolarSSL for RSA computation, and AES encryption/decryption.
PolarSSL is distributed under GPLv2+. We use PolarSSL under GPLv3
as our options.
The file include/polarssl/bn_mul.h is heavily modified for ARM
Cortex-M3.
The function rsa_private in polarssl/library/rsa.c is modified so
that it doesn't check T against N. The function rsa_pkcs1_sign is
modified to avoid warnings in case of !POLARSSL_PKCS1_V21.
The functions rsa_pkcs1_verify and rsa_rsassa_pkcs1_v15_verify in
include/polarssl/rsa.h and polarssl/library/rsa.c are modified
(fixed) for last argument SIG, as the memory at SIG aren't modified
by those routines.
The constant POLARSSL_MPI_MAX_SIZE in include/polarssl/bignum.h is
modified for 2048-bit keys only Gnuk.
The function mpi_mul_hlp in library/bignum.c is modified for more
optimization for ARM Cortex-M3. Functions mpi_montred, mpi_sub_hlp,
mpi_sub_abs, mpi_mul_mpi, mpi_montmul, and mpi_exp_mod are modified
to avoid side channel attacks. Note that we don't use RSA-blinding
technique for Gnuk. Function mpi_gen_prime and mpi_is_prime are
modified to use Fouque-Tibouchi method. Function mpi_exp_mod is
modified to use new function mpi_montsqr for speed up.
The file library/aes.c is modified so that some constants can
go to .sys section.
The file include/polarssl/config.h are modified not to define
POLARSSL_HAVE_LONGLONG to avoid linking libgcc, to define
POLARSSL_AES_ROM_TABLES to have AES tables, not to define
POLARSSL_CIPHER_MODE_CTR, POLARSSL_FS_IO, POLARSSL_PKCS1_V21,
POLARSSL_SELF_TEST, and POLARSSL_PADLOCK_C, and only define
POLARSSL_GENPRIME when defined KEYGEN_SUPPORT.
USB vendor ID and product ID (USB device ID)
============================================
When you have a vendor ID and assign a product ID for Gnuk, edit the
file GNUK_USB_DEVICE_ID and add an entry for yours. In this case,
please contact Niibe, so that it is listed to the file in the official
release of the source code.
When you are modifing Gnuk and installing the binary to device, you
should replace the vendor string and serial number to yours (in the
file GNUK_USB_DEVICE_ID and SERIALNO of the script of src/configure),
so that users can see it's not by original vendor, and it is modified
version.
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices
with Gnuk under one of following conditions:
* For everyone for experimental purpose:
- You must not distribute a binary with FSIJ's USB device ID, but
must use the binary by yourself only for your experiment. Note
that "Distributing binary" includes distributing a device which
holds the binary.
* For general individuals:
- You must use your Gnuk device with a card serial number which is
*not* by FSIJ. Easy one would be a card serial number generated
by chip unique ID.
* For individuals with explicit permission from FSIJ.
- You should have an assigned card serial number by FSIJ,
please use that number for your device.
(There a file 'GNUK_SERIAL_NUMBER' in the official release.)
FSIJ could give companies or business entities "second source
manufacturer" license to use USB device ID of FSIJ for devices with
unmodified version of Gnuk, provided they support Free Software and
respect users' freedom for computing. Please ask FSIJ for the
license.
Otherwise, companies which want to distribute Gnuk devices, please use
your own USB vendor ID and product ID. Please replace vendor string
and possibly product string to yours, when you modify Gnuk.
Host Requirements
=================
For GNU/Linux, PC/SC service is an option, you can use GnuPG's
internal CCID driver instead. If you chose using PC/SC service,
libccid version >= 1.3.11 is recommended for GNU/Linux.
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:
binutils-arm-none-eabi 2.28-4+9+b3
gcc-arm-none-eabi 15:5.4.1+svn241155-1
gdb-arm-none-eabi 7.12-6+9+b2
libnewlib-arm-none-eabi 2.4.0.20160527-2
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
Change directory to `src':
$ cd gnuk-VERSION/src
Then, run `configure':
$ ./configure --vidpid=<VID:PID>
Here, you need to specify USB vendor ID and product ID. For FSIJ's,
it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and
product ID' above.
Then, type:
$ make
Then, we will have "gnuk.elf" under src/build directory.
How to install
==============
Olimex STM32-H103 board
-----------------------
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD
and write "gnuk.elf" to Flash ROM:
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg \
-f board/olimex_stm32_h103.cfg \
-c "program build/gnuk.elf verify reset exit"
Command invocation is assumed in src/ directory.
Flying Stone Tiny 01
--------------------
If you are using Flying Stone Tiny 01, you need a SWD writer.
OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "program build/gnuk.elf verify reset exit"
STBee
-----
Reset the board with "USER" switch pushed. Type following to write
to flash:
# cd ../tool
# ./dfuse.py ../src/build/gnuk.hex
Then, reset the board.
How to protect flash ROM
========================
To protect, invoke OpenOCD like (for FST-01):
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x lock 0" -c reset -c exit
After power-off / power-on sequence, the contents of flash ROM cannot
be accessible from JTAG debugger.
Unprotecting is:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x unlock 0" -c reset -c exit
Upon unprotection, flash is erased.
Note that it would be still possible for some implementation of DfuSe
to access the contents, even if it's protected. If you really want to
protect, killing DfuSe and accessing by JTAG debugger is recommended.
(Optional) Configure serial number and X.509 certificate
========================================================
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).
(1) [pyscard] Stop scdaemon
[PyUSB] Stop the pcsc daemon.
If scdaemon is running, please kill it, or you will get "Smartcard
Exception" by "Sharing violation".
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
In case of PyUSB tool, you need to stop pcscd.
# /etc/init.d/pcscd stop
(2) [Optional] Write fixed serial number
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary_usb.py -s ../GNUK_SERIAL_NUMBER
Writing serial number
...
(3) [Optional] Write card holder certificate
If you have card holder certificate binary file, you can do:
$ ../tool/gnuk_put_binary_usb.py ../../<YOUR-CERTIFICATE>.bin
../../<YOUR-CERTIFICATE>.bin: <LENGTH-OF-YOUR-CERTIFICATE>
Updating card holder certificate
...
How to run
==========
Debug enabled
-------------
If you compiled with --enable-debug option, Gnuk has two interfaces
(one is CCID/ICCD device and another is virtual COM port). Open
virtual COM port by:
$ cu -l /dev/ttyACM0
and you will see debug output of Gnuk.
Testing Gnuk
------------
Type following command to see Gnuk runs:
$ gpg --card-status
Besides, there is a functionality test under test/ directory. See
test/README.
Personalize the Token, import keys, and change the password
-----------------------------------------------------------
You can personalize the token, putting your information like: Name,
Login name, Sex, Languages, URL. To do so, GnuPG command is:
$ gpg --card-edit
Note that the factory setting of user password is "123456" and admin
password is "12345678" as the specification.
It is recommended to create your keys on your computer, and import
them to Gnuk Token. After you create your keys (they must be 2048-bit
RSA), you can import them.
Gnuk supports key generation, but this feature is young and should be
considered experimental.
For detail, please see documentation under doc/. You can see the HTML
version at: https://www.fsij.org/doc-gnuk/
How to debug
============
We can use GDB.
$ arm-none-eabi-gdb gnuk.elf
Inside GDB, we can connect OpenOCD by:
(gdb) target remote localhost:3333
or
(gdb) target extended-remote localhost:3333
You can see the output of PCSCD:
# /etc/init.d/pcscd stop
# LIBCCID_ifdLogLevel=7 /usr/sbin/pcscd --debug --foreground
You can observe the traffic of USB using "usbmon". See the file:
linux/Documentation/usb/usbmon.txt
Firmware update
===============
See doc/note/firmware-update.
Git Repositories
================
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
You can get it by:
$ git clone git://anonscm.debian.org/gnuk/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
I put Chopstx as a submodule of Git. Please do this:
$ git submodule update --init
Information on the Web
======================
For more information, please visit: https://www.fsij.org/gnuk/
Please see the FST-01 support pages:
https://www.gniibe.org/category/fst-01.html
Please consider to join Gnuk-users mailing list:
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
The mailing list will be moved to lists.debian.org.
Your Contributions
==================
FSIJ welcomes your contributions. Please assign your copyright
to FSIJ (if possible), as I do.
Foot note
==========
* NUK(R) is a registered trademark owend by MAPA GmbH, Germany.
--

138
README.md Normal file
View File

@@ -0,0 +1,138 @@
***Note:*** *This fork of Gnuk fixes some compiling bugs and focuses on using the "ST-Link V2" clone hardware.*
Here is the link to the original project: <http://git.gniibe.org/cgit/gnuk/gnuk.git/>
What's Gnuk?
============
Gnuk is an implementation of a USB cryptographic security token that supports the OpenPGP card protocol version 2. It runs on a STM32F103 processor (and its compatible). In short it allows one to convert a cheap $2 "ST-Link V2" clone device into a hardware security token.
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).
Gnuk supports the Key Derived Function (KDF) functionality. To use this feature one will need to use GnuPG 2.2.6 or later.
How to build the Gnuk firmware
==============================
You will need the GNU toolchain for arm-none-eabi and newlib.
To clone the source code and compile, use the following commands.
```
git clone --recursive https://git.spengler.co.za/deon/gnuk.git gnuk
cd gnuk/src
./configure --vidpid=1337:0010
make
```
Then, you will have "gnuk.bin" under src/build directory.
***Please read section 'USB vendor ID and product ID' below.***
How to flash the Gnuk firmware
==============================
In order to flash the firmware ensure that you have openocd installed.
Execute openocd and connect with telnet
```
openocd -f ../misc/stm32f103.cfg
telnet localhost 4444
```
Use the following commands to unlock, flash the firmware and lock the device again.
```
reset halt
stm32f1x unlock 0
reset halt
flash write_bank 0 ./build/gnuk.bin 0
stm32f1x lock 0
reset halt
```
How to reflash the ST-LINK
==========================
To reflash the ST-LINK, connect the device to a programmer as before while keeping pins 7 and 8 shorted. While the LED is blinking, run openocd. Once its running (i.e. it doesnt show any errors), you can unshort the pins.
Then use the following to unlock and reflash.
```
reset halt
stm32f1x unlock 0
reset halt
stm32f1x mass_erase 0
flash write_bank 0 ./build/gnuk.bin 0
stm32f1x lock 0
reset halt
```
***Note: That reprograming will wipe the flash memory and you will lose all key's that was on the device.***
Testing Gnuk
============
Type following command to see if GnuPG detects the Gnuk token.
```
gpg --card-status
```
***See tests/README for functionality tests.***
Personalize the Token, import keys, and change the password
===========================================================
You can personalize your token by putting in your information like: Name, Login and Language.
The KDF setting needs to be enabled before any keys are imported into the Gnuk token. Once a key has been imported the KDF setting can't be changed until the token has been reset.
***Note:*** That the factory user password is "123456" and admin password is "12345678". It is recommended to create your keys on your computer, and import them into the token. Gnuk supports key generation, but this feature is young and should be considered experimental.
To configure your Gnuk token use the following command.
```
gpg --card-edit
```
For further details, please see documentation under doc.
Firmware update
===============
See doc/note/firmware-update.
How to debug
============
Ensure that you have arm-none-eabi-gdb installed and then you must configure and compile the Gnuk firmware with --enable-debug option. After flashing Gnuk debug firmware one will see two interfaces, one is CCID/ICCD device and the another is a virtual COM port.
Open the virtual COM with the following command:
```
picocom /dev/ttyACM0
```
and you will see debug output of Gnuk firmware.
You can now use GDB with the following command.
```
arm-none-eabi-gdb src/build/gnuk.elf
```
Inside GDB, we can connect OpenOCD by:
```
(gdb) target remote localhost:3333
```
You can see the output of PCSCD with the following command:
```
/usr/bin/pcscd --debug --foreground
```
You can also observe the traffic of the USB interface using "usbmon".
USB vendor ID and product ID (USB device ID)
============================================
When you have a vendor ID and assign a product ID for Gnuk, edit the file GNUK_USB_DEVICE_ID and add an entry for yours. In this case, please contact Niibe, so that it is listed to the file in the official release of the source code.
When you are modifing Gnuk and installing the binary to device, you should replace the vendor string and serial number to yours (in the file GNUK_USB_DEVICE_ID and SERIALNO of the script of src/configure), so that users can see it's not by original vendor, and it is modified version.
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices with Gnuk under one of following conditions:
* For everyone for experimental purpose:
- You must not distribute a binary with FSIJ's USB device ID, but must use the binary by yourself only for your experiment. Note that "Distributing binary" includes distributing a device which holds the binary.
* For general individuals:
- You must use your Gnuk device with a card serial number which is *not* by FSIJ. Easy one would be a card serial number generated by chip unique ID.
* For individuals with explicit permission from FSIJ.
- You should have an assigned card serial number by FSIJ, please use that number for your device.
(There a file 'GNUK_SERIAL_NUMBER' in the official release.)
FSIJ could give companies or business entities "second source manufacturer" license to use USB device ID of FSIJ for devices with unmodified version of Gnuk, provided they support Free Software and respect users' freedom for computing. Please ask FSIJ for the license.
Otherwise, companies which want to distribute Gnuk devices, please use your own USB vendor ID and product ID. Please replace vendor string and possibly product string to yours, when you modify Gnuk.

42
THANKS
View File

@@ -1,42 +0,0 @@
-*- coding: utf-8 -*-
We would like to express our gratitudes to Werner Koch for GnuPG, and
Giovanni Di Sirio for ChibiOS/RT.
Gnuk was originally written by NIIBE Yutaka. People contributed by
encouraging the development, testing the implementation, suggesting
improvements, or fixing bugs. Here is a list of those people.
Achim Pietig achim@pietig.com
Aidan Thornton
Anibal Monsalve Salazar anibal@debian.org
Andre Zepezauer andre.zepezauer@student.uni-halle.de
Anthony Romano anthony.romano@coreos.com
Bertrand Jacquin bertrand@jacquin.bzh
Clint Adams clint@softwarefreedom.org
Daniel Kahn Gillmor dkg@fifthhorseman.net
Elliott Mitchell
Hironobu SUZUKI hironobu@h2np.net
Jan Suhr jan@suhr.info
Jeremy Drake jeremydrake+gnuk@eacceleration.com
Jonathan McDowell noodles@earth.li
Kaz Kojima kkojima@rr.iij4u.or.jp
Kenji Rikitake
Ludovic Rousseau ludovic.rousseau@free.fr
Luis Felipe R. Murillo luisfelipe@ucla.edu
Mateusz Zalega mateusz@nitrokey.com
MATSUU Takuto matsuu@gentoo.org
Micah Anderson micah@debian.org
NAGAMI Takeshi nagami-takeshi@aist.go.jp
Nguyễn Hồng Quân quannguyen@mbm.vn
Nico Rikken nico@nicorikken.eu
NOKUBI Takatsugu knok@daionet.gr.jp
Paul Fertser
Paul Bakker polarssl_maintainer@polarssl.org
Santiago Ruano Rincón santiago@debian.org
Shane Coughlan scoughlan@openinventionnetwork.com
Stanislas Bach sbach@0g.re
Szczepan Zalega szczepan@nitrokey.com
Vasily Evseenko
Werner Koch wk@gnupg.org
Yuji Imai ug@xcast.jp

View File

@@ -1 +1 @@
release/1.2.6
release/1.2.20

Submodule chopstx updated: 96d2a81331...a8e9074faf

View File

@@ -40,11 +40,11 @@ We are using "-O3 -Os" for compiler option.
Building Gnuk
-------------
Change directory to ``src``:
Change directory to ``src``: ::
$ cd gnuk-VERSION/src
Then, run ``configure``:
Then, run ``configure``: ::
$ ./configure --vidpid=<VID:PID>
@@ -52,8 +52,14 @@ Here, you need to specify USB vendor ID and product ID. For FSIJ's,
it's: --vidpid=234b:0000 . Please read the section 'USB vendor ID and
product ID' in README.
Type:
Type: ::
$ make
Then, we will have "gnuk.elf" under src/build directory.
If you are not the authorized vendor, please never distribute this
file of "gnuk.elf", which includes VID:PID in the image. If you would
like to distribute the image (for example, to check if it's
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
VID:PID.

View File

@@ -16,7 +16,7 @@ In addition to settings of Gnuk, I create a file
# For updating firmware, permission settings are needed.
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd"

View File

@@ -54,7 +54,7 @@ setting). It should have lines something like: ::
# Gnuk Token by FSIJ
SUBSYSTEMS=="usb", ACTION=="add", \
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
I have those lines in /etc/udev/rules.d/69-gnuk.rules.
@@ -73,16 +73,21 @@ and make: ::
$ make
Please take care of configure options. The default target in 1.0.x
series is Olimex STM32 H103 (not FST-01). The default target in 1.1.8
series is Olimex STM32 H103 (not FST-01). The default target in 1.2.x
is FST-01.
Then you get build/gnuk.elf.
Then you get build/gnuk.elf and build/gnuk.bin.
If you are not the authorized vendor, please never distribute this
file of "gnuk.elf", which includes VID:PID in the image. If you would
like to distribute the image (for example, to check if it's
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
VID:PID.
Invoking configure with FSIJ's USB ID (234b:0000) means that you are
using FSIJ's USB ID (for reGNUal in this case). Please note that FSIJ
only allows use of its USB ID for specific situations. Please read
README of Gnuk about that.
Invoking configure with FSIJ's USB ID (234b:0000) and generating
gnuk.elf means that you are using FSIJ's USB ID (for reGNUal in this
case). Please note that FSIJ only allows use of its USB ID for
specific situations. Please read README of Gnuk about that.
Bulding reGNUal
@@ -117,13 +122,13 @@ your environment for Gnuk Token.
How to run the script: ::
$ cd tool
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.bin
$ ./upgrade_by_passwd.py
Then, the script on your host PC invoke the steps described above, and
you will get new version of Gnuk installed.
You can also specify -p option to enter your password (other than
factory setting).
You can also specify -f option to skip entering your password (it
assumes the factory setting).
If you already have configured another upgrade key installed, you can
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0

View File

@@ -30,9 +30,9 @@ command.
Or, you can use ``gpgconf`` command. Type::
$ gpgconf --reload scdameon
$ gpgconf --reload scdaemon
will do the samething.
will do the same thing.
Let GPG-AGENT/SCDAEMON learn

View File

@@ -37,7 +37,7 @@ When we only install "gnupg2" package for 2.0 (with no "gnupg" package),
there will be no udev rules (there is a bug report #543217 for this issue).
In this case, we need something like this in /etc/udev/rules.d/60-gnuk.rules::
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
Usually, udev daemon automatically handles for the changes of configuration

View File

@@ -1,7 +0,0 @@
FROM gnuk:latest
LABEL Description="Image for checking gnuK"
RUN apt install -y shellcheck
RUN apt install -y clang libfindbin-libs-perl
RUN apt clean

View File

@@ -1,4 +0,0 @@
FROM gnuk:latest
LABEL Description="Image for building gnuK with debugging"
RUN apt install -y gdb-arm-none-eabi && apt clean

View File

@@ -1,6 +0,0 @@
FROM debian:latest
LABEL Description="Image for building gnuK"
RUN apt update -y && apt install -y make gcc-arm-none-eabi && apt clean
CMD ["/bin/sh", "-c", "cd /gnuk/src && make clean && ./configure $GNUK_CONFIG && make"]

View File

@@ -1,36 +0,0 @@
ifndef GNUK_CONFIG
$(warning configuration flags not set in GNUK_CONFIG)
endif
all: ../chopstx docker-build-release
docker run --user=`id -u` --env GNUK_CONFIG --rm -v `pwd`/..:/gnuk/ -t gnuk:latest
clean: docker-build-release
docker run --user=`id -u` --env GNUK_CONFIG --rm -v `pwd`/..:/gnuk/ -w /gnuk/src -t gnuk:latest make clean
gdb: docker-build-debug
docker run --net host --rm -i -v `pwd`/..:/gnuk/ -t gnuk:latest-debug arm-none-eabi-gdb /gnuk/src/build/gnuk.elf
shellcheck: docker-build-check
docker run --rm -v `pwd`/..:/gnuk/ -t gnuk:latest-check shellcheck /gnuk/src/configure
CHECKERS=security optin nullability core deadcode alpha.core alpha.security
scan-build: clean docker-build-check
docker run --user=`id -u` --rm -v `pwd`/..:/gnuk/ -w /gnuk/src -t gnuk:latest-check scan-build -o scan-build \
-analyze-headers -stats $(addprefix -enable-checker ,$(CHECKERS)) -k \
--use-cc=arm-none-eabi-gcc \
make
../chopstx:
git submodule update --init
docker-build-release:
docker build -t gnuk:latest -f `pwd`/Dockerfile.release ..
docker-build-debug: docker-build-release
docker build -t gnuk:latest-debug -f `pwd`/Dockerfile.debug ..
docker-build-check: docker-build-release
docker build -t gnuk:latest-check -f `pwd`/Dockerfile.check ..
.PHONY: all clean gdb shellcheck scan-build \
docker-build-release docker-build-debug docker-build-check

View File

@@ -1,553 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
id="svg3961"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="gnuk-sticers.svg">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3967" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="1031.615"
x2="240.89818"
y1="1031.615"
x1="85.996228"
id="linearGradient4296"
xlink:href="#linearGradient4290"
inkscape:collect="always" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3903" />
<filter
id="filter3875"
inkscape:collect="always">
<feBlend
id="feBlend3877"
in2="BackgroundImage"
mode="screen"
inkscape:collect="always" />
</filter>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective3830" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10-5" />
<linearGradient
id="linearGradient0">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3620" />
<stop
id="stop3632"
offset="0.07"
style="stop-color:#c8c8e0;stop-opacity:1;" />
<stop
id="stop3630"
offset="0.17"
style="stop-color:#9696c8;stop-opacity:1;" />
<stop
id="stop3628"
offset="0.33"
style="stop-color:#6464b4;stop-opacity:1;" />
<stop
style="stop-color:#3232a0;stop-opacity:1;"
offset="0.5"
id="stop3634" />
<stop
id="stop3636"
offset="0.66"
style="stop-color:#282898;stop-opacity:1;" />
<stop
id="stop3626"
offset="0.85"
style="stop-color:#1e1e90;stop-opacity:1;" />
<stop
style="stop-color:#000088;stop-opacity:1;"
offset="1"
id="stop3622" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient0"
id="radialGradient0"
cx="450"
cy="750"
fx="450"
fy="750"
r="201.5"
gradientTransform="matrix(1,0,0,0.75369458,-1.760006,108.15135)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient1">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop0" />
<stop
id="stop1"
offset="0.0625"
style="stop-color:#f8fcff;stop-opacity:1;" />
<stop
id="stop2"
offset="0.17166339"
style="stop-color:#f0f8ff;stop-opacity:1;" />
<stop
id="stop3"
offset="0.30279359"
style="stop-color:#ecf4ff;stop-opacity:1;" />
<stop
style="stop-color:#e8f0ff;stop-opacity:1;"
offset="0.5"
id="stop4" />
<stop
id="stop5"
offset="0.65893352"
style="stop-color:#e0ecff;stop-opacity:1;" />
<stop
id="stop6"
offset="0.83552629"
style="stop-color:#d8e8ff;stop-opacity:1;" />
<stop
style="stop-color:#d0e0ff;stop-opacity:1;"
offset="1"
id="stop7" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="radialGradient1"
cx="0"
cy="440"
fx="0"
fy="440"
r="80"
gradientUnits="userSpaceOnUse" />
<filter
inkscape:collect="always"
id="filter0"
x="-0.1423529"
width="1.2847058"
y="-0.13404847"
height="1.2680969">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.0538481"
id="feGaussianBlur0" />
</filter>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective2884" />
<inkscape:perspective
id="perspective10"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 526.18109 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
id="linearGradient4290"
inkscape:collect="always">
<stop
id="stop4292"
offset="0"
style="stop-color:#000734;stop-opacity:1;" />
<stop
id="stop4294"
offset="1"
style="stop-color:#000734;stop-opacity:0;" />
</linearGradient>
</defs>
<sodipodi:namedview
inkscape:document-units="mm"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-75.714286"
inkscape:cy="520"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1122"
inkscape:window-height="692"
inkscape:window-x="150"
inkscape:window-y="51"
inkscape:window-maximized="0" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
style="display:inline"
transform="translate(0.5,-946.62598)"
id="layer1-63"
inkscape:label="Layer1"
inkscape:tile-cx="124.59931"
inkscape:tile-cy="53.118107"
inkscape:tile-w="248.19862"
inkscape:tile-h="105.23622"
inkscape:tile-x0="0.5"
inkscape:tile-y0="0.49999656">
<rect
y="947.12598"
x="0"
height="105.23622"
width="248.19862"
id="rect0"
style="fill:#d9fffe;fill-opacity:1;stroke:none" />
<line id="line0"
x1="0" y1="947.12598" x2="20" y2="947.12598"
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
<line id="line1"
x1="248.19862" y1="947.12598" x2="248.19862" y2="957.12598"
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
<line id="line2"
x1="248.19862" y1="1052.3622" x2="228.19862" y2="1052.3622"
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
<line id="line3"
x1="0" y1="1052.3622" x2="0" y2="1042.3622"
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
<image
xlink:href="FSIJ-s.png"
width="41.757679"
height="28.346457"
id="image2886"
x="202.27382"
y="951.12598" />
<text
sodipodi:linespacing="100%"
id="text2890"
y="1014.9048"
x="94.433884"
style="font-size:52.27830124px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#032b7f;fill-opacity:1;stroke:none;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch Bold"
xml:space="preserve"><tspan
y="1014.9048"
x="94.433884"
id="tspan2892"
sodipodi:role="line">GNUK</tspan></text>
<g
inkscape:label="Layer 1"
id="layer1-6"
transform="matrix(-0.1014557,0,0,0.1014557,90.73972,926.6016)">
<path
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:2.29999995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,0 c 0,0 0,0 -76,0 0,0 -8,-9 -12,-12 -18,-15 -48,-48 -36,-84 4,-14 12,-36 12,-36 -10,6 -50,26 -66,54 -8,16 -18,30 -18,54 0,24 25,100 48,108 0,0 0,0 150,0 0,0 0,0 150,0 23,-8 48,-84 48,-108 0,-24 -10,-38 -18,-54 -16,-28 -46,-48 -66,-54 0,0 8,22 12,36 12,36 -18,69 -36,84 C 88,-9 80,0 80,0 z"
transform="matrix(-1.76,0,0,1.76,410,560)"
id="path0" />
<path
inkscape:connector-curvature="0"
style="fill:#000040;fill-opacity:1;stroke:none"
d="m 411.01194,560.94628 c 0,0 0,0 133.76,0 0,0 14.08,-15.84 21.12,-21.12 31.68,-26.4 84.48,-84.48 63.36,-147.84 -7.04,-24.64 -21.12,-63.36 -21.12,-63.36 17.6,10.56 38,45.76 66.16,95.04 14.08,28.16 19.18,52.8 19.18,95.04 0,42.24 -44,176 -84.48,190.08 0,0 62.5,0 -201.5,0 0,0 62.5,0 -201.5,0 -40.48,-14.08 -84.48,-147.84 -84.48,-190.08 0,-42.24 5.1,-66.88 19.18,-95.04 28.16,-49.28 30.96,-84.48 66.16,-95.04 0,0 -14.08,38.72 -21.12,63.36 -21.12,63.36 31.68,121.44 63.36,147.84 7.04,5.28 21.12,21.12 21.12,21.12 z"
id="path0-9"
sodipodi:nodetypes="ccccccscccscccccc" />
<path
style="fill:#c0c0fd;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 409.21999,592 c 0,0 90,0 90,-33 0,-20 -4,-28 -12,-40 -5,-8 -8,-18 -8,-28 -1,-13 -1,-20 8,-36 6,-9 8,-23 5,-33 -5,-14 -19,-23 -33,-25 -16,-5 -35,-4 -50,-5 -15,1 -34,0 -50,5 -14,2 -28,9 -33,25 -3,10 1,24 5,33 9,16 9,23 8,36 0,10 -3,20 -8,28 -8,12 -12,20 -12,40 0,33 90,33 90,33 z"
id="path1" />
<path
style="fill:url(#radialGradient1);fill-opacity:1;fill-rule:evenodd;stroke:#d0e0ff;stroke-width:10px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0,592 c 0,0 -90,0 -90,-33 0,-20 4,-28 12,-40 5,-8 8,-18 8,-28 1,-13 1,-20 -8,-36 -6,-9 -8,-23 -5,-33 5,-14 19,-23 33,-25 16,-5 35,-4 50,-5 15,1 34,0 50,5 14,2 28,9 33,25 3,10 -1,24 -5,33 -9,16 -9,23 -8,36 0,10 3,20 8,28 8,12 12,20 12,40 0,33 -90,33 -90,33 z"
id="path1-1"
transform="matrix(-0.75,0,0,0.8,410,100)" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
d="m 344.11439,411.54794 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
id="path1-2"
sodipodi:nodetypes="ccccsc" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
d="m 474.68123,406.16125 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
id="path1-3"
sodipodi:nodetypes="ccccsc"
transform="matrix(-1,0,0,1,949.00681,5.38669)" />
<path
style="fill:#afcfff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 236.90125,452.90625 C 135.34805,496.35376 97.060607,634.496 151.37,761.4375 c 50.02335,116.92341 158.1859,159.40625 257.75,159.40625 99.5641,0 207.72665,-42.48284 257.75,-159.40625 C 721.17939,634.496 682.89195,496.35376 581.33875,452.90625 526.07714,429.26367 466.8919,524.375 409.12,524.375 c -57.7719,0 -116.77668,-94.67646 -172.21875,-71.46875 z"
id="path2"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path3"
d="m 538.23999,720 a 130,150 0 0 1 -260,0 130,150 0 1 1 260,0 z"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4.47213602px;stroke-opacity:1"
d="m 538.30032,722.21875 c 56.32313,26.16396 100.82185,68.68738 119.76563,119.4375 33.50451,82.59901 -5.55269,179.72665 -93.67188,230.71875 -89.66782,55.4574 -224.43374,55.4574 -314.10156,0 -88.11919,-50.9921 -127.13733,-148.11974 -93.63281,-230.71875 18.61816,-50.41349 63.06491,-92.92973 119.25781,-119.1875 11.1304,10.32118 18.58377,23.0939 22.34375,36.6875 -5.94376,3.59375 -11.63988,7.47175 -16.99219,11.625 -73.95399,55.19241 -81.85302,155.28934 -18.59375,218.125 47.75721,51.30795 139.68,72.55545 213.4375,46.68755 87.41094,-28.2229 135.47694,-110.93384 113.94531,-183.2813 -9.09953,-36.85675 -36.47131,-70.33241 -73.67187,-92.96875 2.51871,-9.1715 6.69761,-18.00492 12.57812,-26 2.55237,-3.99852 5.70954,-7.71801 9.33594,-11.125 z"
id="path4"
inkscape:connector-curvature="0" />
</g>
<text
sodipodi:linespacing="85.000002%"
id="text3817"
y="1038.1145"
x="98.368591"
style="font-size:18px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:85.00000238%;writing-mode:lr-tb;text-anchor:start;fill:#120054;fill-opacity:1;stroke:none;display:inline;font-family:Gentium Basic;-inkscape-font-specification:Gentium Basic Bold Italic"
xml:space="preserve"><tspan
y="1038.1145"
x="98.368591"
style="fill:#120054;fill-opacity:1"
id="tspan4288"
sodipodi:role="line">GnuPG USB Token</tspan></text>
</g>
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
id="use4758" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,105.23622)"
id="use4760" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,210.47244)"
id="use4762" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,315.70866)"
id="use4764" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,420.94489)"
id="use4766" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,526.18111)"
id="use4768" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,631.41733)"
id="use4770" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,736.65355)"
id="use4772" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,841.88977)"
id="use4774" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(0,947.12599)"
id="use4776" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,0)"
id="use4778" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,105.23622)"
id="use4780" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,210.47244)"
id="use4782" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,315.70866)"
id="use4784" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,420.94489)"
id="use4786" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,526.18111)"
id="use4788" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,631.41733)"
id="use4790" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,736.65355)"
id="use4792" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,841.88977)"
id="use4794" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(248.19862,947.12599)"
id="use4796" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,0)"
id="use4798" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,105.23622)"
id="use4800" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,210.47244)"
id="use4802" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,315.70866)"
id="use4804" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,420.94489)"
id="use4806" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,526.18111)"
id="use4808" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,631.41733)"
id="use4810" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,736.65355)"
id="use4812" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,841.88977)"
id="use4814" />
<use
x="0"
y="0"
inkscape:tiled-clone-of="#layer1-63"
xlink:href="#layer1-63"
transform="translate(496.39725,947.12599)"
id="use4816" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

BIN
gnuk.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

4
misc/stm32f103.cfg Normal file
View File

@@ -0,0 +1,4 @@
telnet_port 4444
source [find interface/stlink.cfg]
source [find target/stm32f1x.cfg]
set WORKAREASIZE 0x10000

View File

@@ -495,6 +495,67 @@
#endif /* TriCore */
#if defined(__arm__)
#if defined(__ARM_FEATURE_DSP)
/* The ARM DSP instructions are available on Cortex M4, M7 and
Cortex A CPUs */
#define MULADDC_1024_CORE \
"ldmia %[s]!, { r7, r8, r9, r10 } \n\t" \
"ldmia %[d], { r3, r4, r5, r6 } \n\t" \
"umaal r3, %2, %[b], r7 \n\t" \
"umaal r4, %2, %[b], r8 \n\t" \
"umaal r5, %2, %[b], r9 \n\t" \
"umaal r6, %2, %[b], r10 \n\t" \
"stmia %[d]!, {r3, r4, r5, r6} \n\t"
#define MULADDC_1024_LOOP \
asm( "tst %[i], #0xfe0 \n\t" \
"beq 0f \n" \
"1: sub %[i], %[i], #32 \n\t" \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
"tst %[i], #0xfe0 \n\t" \
"bne 1b \n" \
"0:" \
: [s] "=r" (s), [d] "=r" (d), [c] "=r" (c), [i] "=r" (i) \
: [b] "r" (b), "[s]" (s), "[d]" (d), "[c]" (c), "[i]" (i) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
#define MULADDC_INIT \
asm(
#define MULADDC_CORE \
"ldr r0, [%0], #4 \n\t" \
"ldr r1, [%1] \n\t" \
"umaal r1, %2, %3, r0 \n\t" \
"str r1, [%1], #4 \n\t"
#define MULADDC_HUIT \
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
"ldmia %1, {r4, r5, r6, r7} \n\t" \
"umaal r4, %2, %3, r0 \n\t" \
"umaal r5, %2, %3, r1 \n\t" \
"umaal r6, %2, %3, r2 \n\t" \
"umaal r7, %2, %3, r3 \n\t" \
"stmia %1!, {r4, r5, r6, r7} \n\t" \
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
"ldmia %1, {r4, r5, r6, r7} \n\t" \
"umaal r4, %2, %3, r0 \n\t" \
"umaal r5, %2, %3, r1 \n\t" \
"umaal r6, %2, %3, r2 \n\t" \
"umaal r7, %2, %3, r3 \n\t" \
"stmia %1!, {r4, r5, r6, r7} \n\t"
#define MULADDC_STOP \
: "=r" (s), "=r" (d), "=r" (c) \
: "r" (b), "0" (s), "1" (d), "2" (c) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "memory");
#else /* __ARM_FEATURE_DSP */
#define MULADDC_1024_CORE \
"ldmia %[s]!, { r8, r9, r10 } \n\t" \
"ldmia %[d], { r5, r6, r7 } \n\t" \
@@ -556,7 +617,7 @@
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
/* Just for reference (dead code) */
#define MULADDC_HUIT \
#define MULADDC_HUIT_DEAD \
"ldmia %0!, { r4, r5 } \n\t" \
"ldmia %1, { r8, r9 } \n\t" \
"umull r6, r7, %3, r4 \n\t" \
@@ -620,6 +681,7 @@
: "r" (b), "0" (s), "1" (d), "2" (c) \
: "r4", "r5", "r6", "r7", "memory", "cc" );
#endif /* __ARM_FEATURE_DSP */
#endif /* ARMv3 */
#if defined(__alpha__)
@@ -811,8 +873,8 @@
#else
#define MULADDC_INIT \
{ \
t_int s0, s1, b0, b1; \
t_int r0, r1, rx, ry; \
t_uint s0, s1, b0, b1; \
t_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );

View File

@@ -1524,12 +1524,7 @@ static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
*/
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
{
#ifdef BIGNUM_C_IMPLEMENTATION
t_uint a_input[n];
memcpy (a_input, &d[n], sizeof (a_input));
mpi_montmul (n, np, mm, d, a_input);
#else
#if defined(POLARSSL_HAVE_ASM) && defined(__arm__)
size_t i;
register t_uint c = 0;
@@ -1542,6 +1537,51 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
x_i = *xj;
*xj++ = c;
#if defined(__ARM_FEATURE_DSP)
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
"mov %[c], #0\n\t"
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
"mov r4, %[c]\n\t"
"umlal r5, r4, %[x_i], %[x_i]\n\t"
"str r5, [%[wij]], #4\n\t"
"cmp %[xj], %[x_max1]\n\t"
"bhi 0f\n\t"
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
"beq 1f\n"
"2:\n\t"
"ldmia %[xj]!, { r7, r8 }\n\t"
"ldmia %[wij], { r5, r6 }\n\t"
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
"umaal r5, r4, %[x_i], r7\n\t"
"umlal r5, %[c], %[x_i], r7\n\t"
"umaal r4, %[c], r9, r9\n\t"
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
"umaal r6, r4, %[x_i], r8\n\t"
"umlal r6, %[c], %[x_i], r8\n\t"
"umaal r4, %[c], r9, r9\n\t"
/**/
"stmia %[wij]!, { r5, r6 }\n\t"
"cmp %[xj], %[x_max1]\n\t"
"bcc 2b\n\t"
"bne 0f\n"
"1:\n\t"
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
"ldr r5, [%[wij]]\n\t"
"ldr r6, [%[xj]], #4\n\t"
"umaal r5, r4, %[x_i], r6\n\t"
"umlal r5, %[c], %[x_i], r6\n\t"
"umaal r4, %[c], r9, r9\n\t"
"str r5, [%[wij]], #4\n"
"0:\n\t"
"ldr r5, [%[wij]]\n\t"
"adds r4, r4, r5\n\t"
"adc %[c], %[c], #0\n\t"
"str r4, [%[wij]]"
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
"[wij]" (wij), "[xj]" (xj)
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc");
#else
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
"mov %[c], #0\n\t"
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
@@ -1603,6 +1643,7 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
"[wij]" (wij), "[xj]" (xj)
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
#endif
c += mpi_mul_hlp( n, np, &d[i], d[i] * mm );
}
@@ -1614,17 +1655,29 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
mpi_sub_hlp( n, np, d );
else
mpi_sub_hlp( n, d - n, d - n);
#else
t_uint a_input[n];
memcpy (a_input, &d[n], sizeof (a_input));
mpi_montmul (n, np, mm, d, a_input);
#endif
}
/*
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
*/
#if MEMORY_SIZE >= 32
#define MAX_WSIZE 6
#elif MEMORY_SIZE >= 24
#define MAX_WSIZE 5
#else
#define MAX_WSIZE 4
#endif
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
{
int ret;
size_t i = mpi_msb( E );
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
size_t wsize = ( i > 1024 ) ? MAX_WSIZE :
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
size_t wbits, one = 1;

View File

@@ -1,6 +1,6 @@
# Makefile for reGNUal
PROJECT = regnual
PROJECT = regnual-no-vidpid
OBJS = regnual.o usb-stm32f103.o reset.o
@@ -41,13 +41,18 @@ regnual.hex: regnual.elf
$(OBJCOPY) -Obinary regnual.elf regnual.bin
$(OBJCOPY) -Oihex regnual.elf regnual.hex
regnual.elf: regnual-no-vidpid.elf
cp -p regnual-no-vidpid.elf regnual.elf
env FILE="regnual.elf" PATH="../src:$$PATH" bash put-vid-pid-ver.sh
usb-stm32f103.o: ../chopstx/mcu/usb-stm32f103.c
$(CC) $(CFLAGS) -c -o usb-stm32f103.o ../chopstx/mcu/usb-stm32f103.c
regnual.elf: $(OBJS) $(LDSCRIPT)
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
regnual-no-vidpid.elf: $(OBJS) $(LDSCRIPT)
$(CC) $(LDFLAGS) -o regnual-no-vidpid.elf $(OBJS)
clean:
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin *.lst
-rm -f $(OBJS) regnual-no-vidpid.elf regnual.elf regnual.hex regnual.bin \
*.lst
distclean: clean

View File

@@ -1,7 +1,7 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012, 2013, 2015, 2016, 2017
* Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -26,12 +26,12 @@
* ReGNUal
*/
#include <string.h>
#include "types.h"
#include "usb_lld.h"
#include "sys.h"
extern void *memset (void *s, int c, size_t n);
extern void set_led (int);
extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
extern int flash_protect (void);
@@ -57,7 +57,9 @@ static const uint8_t regnual_device_desc[] = {
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
#include "../src/usb-vid-pid-ver.c.inc"
0x00, 0x00, /* idVendor (will be replaced) */
0x00, 0x00, /* idProduct (will be replaced) */
0x00, 0x00, /* bcdDevice (will be replaced) */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */
@@ -147,19 +149,33 @@ static uint32_t fetch (int i)
}
struct CRC {
__IO uint32_t DR;
__IO uint8_t IDR;
volatile uint32_t DR;
volatile uint8_t IDR;
uint8_t RESERVED0;
uint16_t RESERVED1;
__IO uint32_t CR;
volatile uint32_t CR;
};
static struct CRC *const CRC = (struct CRC *)0x40023000;
struct RCC {
volatile uint32_t CR;
volatile uint32_t CFGR;
volatile uint32_t CIR;
volatile uint32_t APB2RSTR;
volatile uint32_t APB1RSTR;
volatile uint32_t AHBENR;
/* ... */
};
static struct RCC *const RCC = (struct RCC *)0x40021000;
#define RCC_AHBENR_CRCEN 0x00000040
#define CRC_CR_RESET 0x01
static uint32_t calc_crc32 (void)
{
struct CRC *CRC = (struct CRC *)0x40023000;
int i;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
for (i = 0; i < 256/4; i++)

View File

@@ -1,5 +1,3 @@
typedef unsigned long size_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
@@ -7,7 +5,3 @@ typedef unsigned int uintptr_t;
#define TRUE 1
#define FALSE 0
#define NULL 0
#define __IO volatile

View File

@@ -34,7 +34,7 @@ USE_EVENTFLAG = yes
ifeq ($(EMULATION),)
DEFS += -DFLASH_UPGRADE_SUPPORT
else
DEFS += -DBN256_C_IMPLEMENTATION -DBIGNUM_C_IMPLEMENTATION
DEFS += -DBN256_C_IMPLEMENTATION
endif
ifneq ($(ENABLE_DEBUG),)
@@ -53,6 +53,10 @@ ifeq ($(CHIP),stm32f103)
CSRC += mcu-stm32f103.c
endif
ifneq ($(USE_DFU),)
OBJS_ADD += build/stdaln-sys-bin.o
endif
###################################
CC = $(CROSS)gcc
LD = $(CROSS)gcc
@@ -72,11 +76,27 @@ sys.c: board.h
build/bignum.o: OPT = -O3 -g
distclean: clean
-rm -f gnuk.ld config.h board.h config.mk \
usb-strings.c.inc usb-vid-pid-ver.c.inc
build/stdaln-sys.elf: build/sys-$(CHIP).o stdaln-sys.ld
@echo
$(LD) -v $< $(MCFLAGS) -nostartfiles -Tstdaln-sys.ld -Wl,--no-warn-mismatch,--gc-sections $(LLIBDIR) -o $@
ifneq ($(EMULATION),)
build/stdaln-sys-bin.o: build/stdaln-sys.elf
@echo
$(OBJCOPY) -O binary -j .sys $< build/stdaln-sys.bin
$(OBJCOPY) -I binary -O default --rename-section .data=.rodata \
build/stdaln-sys.bin $@
distclean: clean
-rm -f gnuk.ld stdaln-sys.ld config.h board.h config.mk \
usb-strings.c.inc put-vid-pid-ver.sh
ifeq ($(EMULATION),)
build/gnuk.elf: build/gnuk-no-vidpid.elf binary-edit.sh put-vid-pid-ver.sh
cp -p build/gnuk-no-vidpid.elf build/gnuk.elf
env FILE="build/gnuk.elf" bash put-vid-pid-ver.sh
$(OBJCOPY) -O ihex build/gnuk.elf build/gnuk.hex
$(OBJCOPY) -O binary build/gnuk.elf build/gnuk.bin
else
# By specifying DESTDIR on invocation of "make", you can install
# program to different ROOT.

View File

@@ -1,7 +1,7 @@
/*
* ac.c -- Check access condition
*
* Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -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;
@@ -73,12 +73,14 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
if (ks_pw1 == NULL)
{
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
const uint8_t *initial_pw;
salt = NULL;
salt_len = 0;
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|| buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|| memcmp (pw, initial_pw, pw_len))
goto failure;
}
else
@@ -97,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);
@@ -161,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;
@@ -177,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;
@@ -220,6 +231,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
}
else
{
const uint8_t *initial_pw;
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
if (ks_pw1 != NULL)
@@ -237,13 +249,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
return 0;
/*
* For the case of empty PW3 (with empty PW1), pass phrase
* should be OPENPGP_CARD_INITIAL_PW3
* For the case of empty PW3 (with empty PW1), passphrase is
* OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO.
*/
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw);
if ((pw_len_known >=0 && pw_len_known != pw_len)
|| buf_len < pw_len
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
|| memcmp (pw, initial_pw, pw_len))
goto failure;
admin_authorized = BY_ADMIN;

76
src/binary-edit.sh Normal file
View File

@@ -0,0 +1,76 @@
# This is a Bash script to be included.
# Idx Name Size VMA LMA File off Algn
# =================
# 2 .text 00004a40 080010f0 080010f0 000110f0 2**4
# 08006550 l O .text 00000012 device_desc
# =================
# VMA =0x080010f0
# FOFF=0x000110f0
# ADDR=0x08005ad0
# file_off_ADDR = ADDR - VMA + FOFF
# = 0x08005ad0 - 0x080010f0 + 0x000110f0 = 0x00015ad0
function calc_addr () {
local line_sym="" VMA FOFF ADDR
arm-none-eabi-objdump -h -t -j .text $FILE | \
egrep -e '(^ +[0-9] +\.text +|device_desc)' | \
while read -r F0 F1 F2 F3 F4 F5 F6; do
if [ -z "$line_sym" ]; then
VMA=$F3
FOFF=$F5
line_sym="next is a line for the symbol"
else
ADDR=$F0
echo "$((0x$ADDR - 0x$VMA + 0x$FOFF))"
fi
done
}
declare -a OFFSETS
OFFSETS=($(calc_addr))
file_off_ADDR=${OFFSETS[0]}
file_off_fraucheky_ADDR=${OFFSETS[1]}
echo "Offset is $file_off_ADDR"
if [ -n "$file_off_fraucheky_ADDR" ]; then
echo "Offset is $file_off_fraucheky_ADDR"
fi
function replace_file_byte_at () {
printf "\x$1" | dd of=$FILE bs=1 seek=$2 conv=notrunc >& /dev/null
}
#
# vid_lsb: 8
# vid_msb: 9
# pid_lsb: 10
# pid_msb: 11
# bcd_device_lsb: 12
# bcd_device_msb: 13
#
function replace_vid_lsb () {
replace_file_byte_at $1 $((addr + 8))
}
function replace_vid_msb () {
replace_file_byte_at $1 $((addr + 9))
}
function replace_pid_lsb () {
replace_file_byte_at $1 $((addr + 10))
}
function replace_pid_msb () {
replace_file_byte_at $1 $((addr + 11))
}
function replace_bcd_device_lsb () {
replace_file_byte_at $1 $((addr + 12))
}
function replace_bcd_device_msb () {
replace_file_byte_at $1 $((addr + 13))
}

View File

@@ -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

View File

@@ -3,9 +3,13 @@
#define ENABLE_VIRTUAL_COM_PORT 1
#endif
@DFU_DEFINE@
@ORIGIN_DEFINE@
@ORIGIN_REAL_DEFINE@
@PINPAD_DEFINE@
@PINPAD_MORE_DEFINE@
@CERTDO_DEFINE@
@HID_CARD_CHANGE_DEFINE@
@SERIALNO_STR_LEN_DEFINE@
@LIFE_CYCLE_MANAGEMENT_DEFINE@
@ACKBTN_DEFINE@
@SERIALNO_STR_LEN_DEFINE@
@KDF_DO_REQUIRED_DEFINE@

113
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
# 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.
@@ -36,15 +36,17 @@ fi
# Default settings
help=no
vidpid=none
target=FST_01
target=ST_DONGLE
with_dfu=default
debug=no
sys1_compat=yes
pinpad=no
certdo=no
hid_card_change=no
factory_reset=no
factory_reset=yes
ackbtn_support=yes
flash_override=""
kdf_do=${kdf_do:-optional}
# For emulation
prefix=/usr/local
exec_prefix='${prefix}'
@@ -135,6 +137,7 @@ Configuration:
supported targets are:
FST_01
FST_01G
FST_01SZ
OLIMEX_STM32_H103
MAPLE_MINI
ST_DONGLE
@@ -167,6 +170,8 @@ BOARD_HEADER_FILE=board-$(echo $target | tr '_[:upper:]' '-[:lower:]').h
echo "Header file is: $BOARD_HEADER_FILE"
ln -sf "../chopstx/board/$BOARD_HEADER_FILE" board.h
# Frequency
MHZ=72
# Flash page size in byte
FLASH_PAGE_SIZE=1024
# Flash memory size in KiB
@@ -196,26 +201,38 @@ STBEE)
if test "$with_dfu" = "default"; then
with_dfu=yes;
fi ;;
BLUE_PILL_G)
MHZ=96
;;
FST_01SZ)
MHZ=96
;;
*)
;;
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=${kdf_do:-required}
def_emulation="-DGNU_LINUX_EMULATION"
def_memory_size="-DMEMORY_SIZE=1024"
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"
enable_hexoutput=yes
libs=""
fi
@@ -246,6 +263,8 @@ else
echo "Debug option disabled"
fi
ORIGIN_REAL=0x08000000
ORIGIN_REAL_DEFINE="#define ORIGIN_REAL $ORIGIN_REAL"
# --with-dfu option
if test "$with_dfu" = "yes"; then
if test "$target" = "FST_01" -o "$target" = "FST_01G" \
@@ -254,15 +273,23 @@ if test "$with_dfu" = "yes"; then
exit 1
fi
echo "Configured for DFU"
ORIGIN=0x08003000
FLASH_SIZE=$((FLASH_SIZE - 12))
if test "$target" = "MAPLE_MINI"; then
# Note that the default bootloader is too large, need for instance
# STM32duino for DFU on Maple Mini
ORIGIN=0x08002000
FLASH_SIZE=$((FLASH_SIZE - 8))
else
ORIGIN=0x08003000
FLASH_SIZE=$((FLASH_SIZE - 12))
fi
DFU_DEFINE="#define DFU_SUPPORT 1"
else
with_dfu=no
echo "Configured for bare system (no-DFU)"
ORIGIN=0x08000000
ORIGIN=${ORIGIN_REAL}
DFU_DEFINE="#undef DFU_SUPPORT"
fi
ORIGIN_DEFINE="#define ORIGIN $ORIGIN"
# --enable-pinpad option
if test "$pinpad" = "no"; then
@@ -304,14 +331,31 @@ else
echo "Life cycle management is NOT supported"
fi
# Acknowledge button support
if test "$ackbtn_support" = "yes"; then
ACKBTN_DEFINE="#define ACKBTN_SUPPORT 1"
echo "Acknowledge button is supported"
else
ACKBTN_DEFINE="#undef ACKBTN_SUPPORT"
echo "Acknowledge button is not supported"
fi
# KDF Data Object is always required for GNU/Linux emulation
if test "$kdf_do" = "required"; 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)-"
SERIALNO="DTS-$(sed -e 's%^[^/]*/%%' <../VERSION)-"
SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
if test "$sys1_compat" = "yes"; then
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset"
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
else
if test "$with_dfu" = "yes"; then
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
@@ -321,12 +365,36 @@ else
FLASH_PAGE_SIZE=2048
FLASH_SIZE=128
MEMORY_SIZE=20
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset"
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
fi
output_vid_pid_version () {
echo "$VIDPID" | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\\${nl} 0x\4, 0x\3, /* idProduct */%p"
echo "$VERSION" | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
echo "$VIDPID" | \
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2\t\3\t\4%p" | \
while read -r FIRST SECOND THIRD FOURTH; do
if test $FIRST != 00; then
echo replace_vid_msb $FIRST
fi
if test $SECOND != 00; then
echo replace_vid_lsb $SECOND
fi
if test $THIRD != 00; then
echo replace_pid_msb $THIRD
fi
if test $FOURTH != 00; then
echo replace_pid_lsb $FOURTH
fi
done
echo "$VERSION" | \
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2%p" | \
while read -r FIRST SECOND; do
if test $FIRST != 00; then
echo replace_bcd_device_msb $FIRST
fi
if test $SECOND != 00; then
echo replace_bcd_device_lsb $SECOND
fi
done
}
output_vendor_product_serial_strings () {
@@ -380,10 +448,16 @@ output_vendor_product_serial_strings () {
fi
}
(echo "#! /bin/bash"
echo
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
if !(IFS=" "
while read -r VIDPID VERSION PRODUCT VENDOR; do
if test "$vidpid" = "$VIDPID"; then
output_vid_pid_version > usb-vid-pid-ver.c.inc
echo >> put-vid-pid-ver.sh
echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
output_vid_pid_version >> put-vid-pid-ver.sh
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
exit 0
fi
@@ -407,16 +481,23 @@ fi
(echo "CHIP=$chip";
echo "ARCH=$arch";
echo "EMULATION=$emulation";
echo "CROSS=$cross";
echo "MCU=$mcu";
echo "DEFS=$use_sys3 $flash_override $def_emulation";
echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size $def_mhz";
echo "LDSCRIPT=$ldscript";
echo "LIBS=$libs";
echo "$DEBUG_MAKE_OPTION";
echo "$PINPAD_MAKE_OPTION";
echo "ENABLE_FRAUCHEKY=$enable_fraucheky";
echo "ENABLE_OUTPUT_HEX=$enable_hexoutput"
if test "$ackbtn_support" = "yes"; then
echo "USE_ACKBTN=yes"
fi
if test "$with_dfu" = "yes"; then
echo "USE_DFU=yes"
fi
if test "$emulation" = "yes"; then
echo "prefix=$prefix"
echo "exec_prefix=$exec_prefix"
@@ -437,13 +518,19 @@ else
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
< gnuk.ld.in > gnuk.ld
fi
sed -e "s/@ORIGIN_REAL@/$ORIGIN_REAL/" -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
< stdaln-sys.ld.in > stdaln-sys.ld
sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
-e "s/@DFU_DEFINE@/$DFU_DEFINE/" \
-e "s/@ORIGIN_DEFINE@/$ORIGIN_DEFINE/" \
-e "s/@ORIGIN_REAL_DEFINE@/$ORIGIN_REAL_DEFINE/" \
-e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_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 @@
/*
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -71,7 +71,7 @@ static const uint8_t *data_pool;
static uint8_t *last_p;
/* The first halfword is generation for the data page (little endian) */
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
const uint8_t flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
0x00, 0x00, 0xff, 0xff
};
@@ -82,10 +82,10 @@ extern uint8_t *flash_addr_data_storage_start;
#define FLASH_ADDR_DATA_STORAGE_START flash_addr_data_storage_start
#else
/* Linker sets these symbols */
extern uint8_t _keystore_pool;
extern uint8_t _data_pool;
#define FLASH_ADDR_KEY_STORAGE_START ((&_keystore_pool))
#define FLASH_ADDR_DATA_STORAGE_START ((&_data_pool))
extern uint8_t _keystore_pool[];
extern uint8_t _data_pool[];
#define FLASH_ADDR_KEY_STORAGE_START ((_keystore_pool))
#define FLASH_ADDR_DATA_STORAGE_START ((_data_pool))
#endif
static int key_available_at (const uint8_t *k, int key_size)
@@ -157,6 +157,12 @@ flash_terminate (void)
{
int i;
#ifdef FLASH_UPGRADE_SUPPORT
const uint8_t *p;
p = gpg_get_firmware_update_key (0);
flash_erase_page ((uintptr_t)p);
#endif
for (i = 0; i < 3; i++)
flash_erase_page ((uintptr_t)flash_key_getpage (i));
flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START);

View File

@@ -22,22 +22,20 @@ extern struct apdu apdu;
#define CARD_CHANGE_REMOVE 1
#define CARD_CHANGE_TOGGLE 2
void ccid_card_change_signal (int how);
void ccid_usb_reset (int);
/* CCID thread */
#define EV_RX_DATA_READY 1 /* USB Rx data available */
#define EV_EXEC_FINISHED 2 /* OpenPGP Execution finished */
#define EV_TX_FINISHED 4 /* CCID Tx finished */
#define EV_CARD_CHANGE 8
#define EV_USB_SET_INTERFACE 16
#define EV_USB_DEVICE_RESET 32
#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_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 */
@@ -56,17 +54,17 @@ enum ccid_state {
CCID_STATE_NOCARD, /* No card available */
CCID_STATE_START, /* Initial */
CCID_STATE_WAIT, /* Waiting APDU */
/* Busy1, Busy2, Busy3, Busy5 */
CCID_STATE_EXECUTE, /* Busy4 */
CCID_STATE_RECEIVE, /* APDU Received Partially */
CCID_STATE_SEND, /* APDU Sent Partially */
CCID_STATE_EXITED, /* ICC Thread Terminated */
CCID_STATE_EXECUTE, /* Executing command */
CCID_STATE_ACK_REQUIRED_0, /* Ack required (executing)*/
CCID_STATE_ACK_REQUIRED_1, /* Waiting user's ACK (execution finished) */
CCID_STATE_EXITED, /* CCID Thread Terminated */
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
};
extern enum ccid_state *const ccid_state_p;
enum ccid_state ccid_get_ccid_state (void);
extern volatile uint8_t auth_status;
#define AC_NONE_AUTHORIZED 0x00
@@ -126,8 +124,8 @@ const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
enum kind_of_key {
GPG_KEY_FOR_SIGNING = 0,
GPG_KEY_FOR_DECRYPTION,
GPG_KEY_FOR_AUTHENTICATION,
GPG_KEY_FOR_DECRYPTION = 1,
GPG_KEY_FOR_AUTHENTICATION = 2,
};
enum size_of_key {
@@ -296,6 +294,10 @@ int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *gpg_do_read_simple (uint8_t);
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
void gpg_increment_digital_signature_counter (void);
void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len,
const uint8_t **r_p);
int gpg_do_kdf_check (int len, int how_many);
int gpg_do_get_uif (enum kind_of_key kk);
void fatal (uint8_t code) __attribute__ ((noreturn));
@@ -334,7 +336,8 @@ extern uint8_t admin_authorized;
#define NR_DO_KEYSTRING_PW1 0x11
#define NR_DO_KEYSTRING_RC 0x12
#define NR_DO_KEYSTRING_PW3 0x13
#define NR_DO__LAST__ 20 /* == 0x14 */
#define NR_DO_KDF 0x14
#define NR_DO__LAST__ 21 /* == 0x15 */
/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */
/*
* Representation of 14-bit counter:
@@ -377,7 +380,17 @@ extern uint8_t admin_authorized;
#define NR_KEY_ALGO_ATTR_DEC 0xf2
#define NR_KEY_ALGO_ATTR_AUT 0xf3
/*
* NR_UINT_SOMETHING could be here... Use 0xf[456789abcd]
* Representation of User Interaction Flag:
* 0 (UIF disabled): 0xf?00 or No record in flash memory
* 1 (UIF enabled): 0xf?01
* 2 (UIF permanently enabled): 0xf?02
*
*/
#define NR_DO_UIF_SIG 0xf6
#define NR_DO_UIF_DEC 0xf7
#define NR_DO_UIF_AUT 0xf8
/*
* NR_UINT_SOMETHING could be here... Use 0xf[459abcd]
*/
/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */
/*
@@ -433,6 +446,8 @@ extern const uint8_t gnuk_string_serial[];
#define LED_GNUK_EXEC 32
#define LED_START_COMMAND 64
#define LED_FINISH_COMMAND 128
#define LED_WAIT_FOR_BUTTON 256
#define LED_OFF LED_FINISH_COMMAND
void led_blink (int spec);
#if defined(PINPAD_SUPPORT)
@@ -459,6 +474,7 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
#endif
extern uint8_t _regnual_start, __heap_end__[];
extern uint8_t _regnual_start[], __heap_end__[];
uint8_t * sram_address (uint32_t offset);

View File

@@ -135,11 +135,11 @@ SECTIONS
{
. = ALIGN (@FLASH_PAGE_SIZE@);
_keystore_pool = .;
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
_updatekey_store = .;
. += 1024;

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017
* 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
@@ -51,6 +56,28 @@
#define LED_TIMEOUT_ONE (100*1000)
#define LED_TIMEOUT_STOP (200*1000)
#ifdef DFU_SUPPORT
static int
flash_write_any (uintptr_t dst_addr, const uint8_t *src, size_t len)
{
int status;
while (len)
{
uint16_t hw = *src++;
hw |= (*src++ << 8);
status = flash_program_halfword (dst_addr, hw);
if (status != 0)
return 0; /* error return */
dst_addr += 2;
len -= 2;
}
return 1;
}
#endif
#ifdef GNU_LINUX_EMULATION
uint8_t *flash_addr_key_storage_start;
@@ -68,7 +95,7 @@ device_initialize_once (void)
* This is the first time invocation.
* Setup serial number by unique device ID.
*/
const uint8_t *u = unique_device_id () + 8;
const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0);
int i;
for (i = 0; i < 4; i++)
@@ -83,6 +110,55 @@ device_initialize_once (void)
nibble += (nibble >= 10 ? ('A' - 10) : '0');
flash_put_data_internal (&p[i*4+2], nibble);
}
#ifdef DFU_SUPPORT
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
/*
* Overwrite DFU bootloader with a copy of SYS linked to ORIGIN_REAL.
* Then protect flash from readout.
*/
{
extern uint8_t _binary_build_stdaln_sys_bin_start;
extern uint8_t _binary_build_stdaln_sys_bin_size;
size_t stdaln_sys_size = (size_t) &_binary_build_stdaln_sys_bin_size;
extern const uint32_t FT0[256], FT1[256], FT2[256];
extern handler vector_table[];
uintptr_t addr;
uint32_t flash_page_size = 1024; /* 1KiB default */
if (((*CHIP_ID_REG)&0x07) == 0x04) /* High density device. */
flash_page_size = 2048; /* It's 2KiB. */
/* Kill DFU */
for (addr = ORIGIN_REAL; addr < ORIGIN;
addr += flash_page_size)
flash_erase_page (addr);
/* Copy SYS */
addr = ORIGIN_REAL;
flash_write_any(addr, &_binary_build_stdaln_sys_bin_start,
stdaln_sys_size);
addr += stdaln_sys_size;
flash_write_any(addr, (const uint8_t *) &FT0, sizeof(FT0));
addr += sizeof(FT0);
flash_write_any(addr, (const uint8_t *) &FT1, sizeof(FT1));
addr += sizeof(FT1);
flash_write_any(addr, (const uint8_t *) &FT2, sizeof(FT2));
addr = ORIGIN_REAL + 0x1000;
if (addr < ORIGIN) {
/* Need to patch top of stack and reset vector there */
handler *new_vector = (handler *) addr;
flash_write((uintptr_t) &new_vector[0], (const uint8_t *)
&vector_table[0], sizeof(handler));
flash_write((uintptr_t) &new_vector[1], (const uint8_t *)
&vector[1], sizeof(handler));
}
flash_protect();
nvic_system_reset();
}
#endif
}
}
#endif
@@ -90,6 +166,10 @@ device_initialize_once (void)
static volatile uint8_t fatal_code;
static struct eventflag led_event;
static chopstx_poll_cond_t led_event_poll_desc;
static struct chx_poll_head *const led_event_poll[] = {
(struct chx_poll_head *)&led_event_poll_desc
};
static void display_fatal_code (void)
{
@@ -130,17 +210,20 @@ static void display_fatal_code (void)
static uint8_t led_inverted;
static void emit_led (int on_time, int off_time)
static void
emit_led (uint32_t on_time, uint32_t off_time)
{
set_led (!led_inverted);
chopstx_usec_wait (on_time);
chopstx_poll (&on_time, 1, led_event_poll);
set_led (led_inverted);
chopstx_usec_wait (off_time);
chopstx_poll (&off_time, 1, led_event_poll);
}
static void display_status_code (void)
static void
display_status_code (void)
{
enum ccid_state ccid_state = *ccid_state_p;
enum ccid_state ccid_state = ccid_get_ccid_state ();
uint32_t usec;
if (ccid_state == CCID_STATE_START)
emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
@@ -155,12 +238,15 @@ static void display_status_code (void)
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
if (ccid_state == CCID_STATE_WAIT)
chopstx_usec_wait (LED_TIMEOUT_STOP * 2);
{
usec = LED_TIMEOUT_STOP * 2;
chopstx_poll (&usec, 1, led_event_poll);
}
else
{
chopstx_usec_wait (LED_TIMEOUT_INTERVAL);
emit_led (ccid_state == CCID_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
usec = LED_TIMEOUT_INTERVAL;
chopstx_poll (&usec, 1, led_event_poll);
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
}
}
}
@@ -227,6 +313,9 @@ main (int argc, const char *argv[])
uintptr_t entry;
#endif
chopstx_t ccid_thd;
int wait_for_ack = 0;
chopstx_conf_idle (1);
gnuk_malloc_init ();
@@ -288,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;
@@ -329,17 +446,23 @@ main (int argc, const char *argv[])
while (1)
{
if (bDeviceState != UNCONNECTED)
if (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
break;
chopstx_usec_wait (250*1000);
}
eventflag_prepare_poll (&led_event, &led_event_poll_desc);
while (1)
{
eventmask_t m;
m = eventflag_wait (&led_event);
if (wait_for_ack)
m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL);
else
m = eventflag_wait (&led_event);
switch (m)
{
case LED_ONESHOT:
@@ -360,8 +483,11 @@ main (int argc, const char *argv[])
break;
case LED_GNUK_EXEC:
goto exec;
case LED_WAIT_FOR_BUTTON:
wait_for_ack ^= 1;
/* fall through */
default:
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_ZERO);
break;
}
}
@@ -377,29 +503,13 @@ main (int argc, const char *argv[])
#ifdef FLASH_UPGRADE_SUPPORT
/* Set vector */
SCB->VTOR = (uintptr_t)&_regnual_start;
entry = calculate_regnual_entry_address (&_regnual_start);
SCB->VTOR = (uintptr_t)_regnual_start;
entry = calculate_regnual_entry_address (_regnual_start);
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
{
extern uint8_t _sys;
uintptr_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
uint32_t flash_page_size = 1024; /* 1KiB default */
if ((*CHIP_ID_REG)&0x07 == 0x04) /* High dencity device. */
flash_page_size = 2048; /* It's 2KiB. */
/* Kill DFU */
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
addr += flash_page_size)
flash_erase_page (addr);
/* copy system service routines */
flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
/* Use SYS at ORIGIN_REAL instead of the one at ORIGIN */
handler *new_vector = (handler *)ORIGIN_REAL;
void (*func) (void (*)(void)) = (void (*)(void (*)(void))) new_vector[9];
/* Leave Gnuk to exec reGNUal */
(*func) ((void (*)(void))entry);
@@ -443,23 +553,23 @@ fatal (uint8_t code)
*/
#ifdef GNU_LINUX_EMULATION
#define MEMORY_SIZE (32*1024)
uint8_t __heap_base__[MEMORY_SIZE];
#define HEAP_SIZE (32*1024)
uint8_t __heap_base__[HEAP_SIZE];
#define HEAP_START __heap_base__
#define MEMORY_END (__heap_base__ + MEMORY_SIZE)
#define MEMORY_ALIGNMENT 32
#define HEAP_END (__heap_base__ + HEAP_SIZE)
#define HEAP_ALIGNMENT 32
#else
extern uint8_t __heap_base__[];
extern uint8_t __heap_end__[];
#define HEAP_START __heap_base__
#define MEMORY_END (__heap_end__)
#define MEMORY_ALIGNMENT 16
#define MEMORY_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#define HEAP_END (__heap_end__)
#define HEAP_ALIGNMENT 16
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#endif
#define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
static uint8_t *heap_p;
static chopstx_mutex_t malloc_mtx;
@@ -472,7 +582,7 @@ struct mem_head {
};
#define MEM_HEAD_IS_CORRUPT(x) \
((x)->size != MEMORY_ALIGN((x)->size) || (x)->size > MEMORY_SIZE)
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
static struct mem_head *free_list;
@@ -486,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)(MEMORY_END - heap_p) < size)
if ((HEAP_END - heap_p) < size)
return NULL;
heap_p += size;
@@ -515,7 +625,7 @@ gnuk_malloc (size_t size)
struct mem_head *m;
struct mem_head *m0;
size = MEMORY_ALIGN (size + sizeof (uintptr_t));
size = HEAP_ALIGN (size + sizeof (uintptr_t));
chopstx_mutex_lock (&malloc_mtx);
DEBUG_INFO ("malloc: ");
@@ -526,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,7 @@
/*
* neug.c - true random number generation
*
* Copyright (C) 2011, 2012, 2013, 2016, 2017
* Copyright (C) 2011, 2012, 2013, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -115,6 +115,11 @@ rbit (uint32_t v)
v = ( v >> 16 ) | ( v << 16);
return v;
}
void
crc32_rv_stop (void)
{
}
#else
void
crc32_rv_reset (void)
@@ -143,6 +148,12 @@ rbit (uint32_t v)
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
return r;
}
void
crc32_rv_stop (void)
{
RCC->AHBENR &= ~RCC_AHBENR_CRCEN;
}
#endif
static chopstx_mutex_t mode_mtx;
@@ -894,6 +905,7 @@ neug_fini (void)
rng_should_terminate = 1;
neug_get (1);
chopstx_join (rng_thread, NULL);
crc32_rv_stop ();
}
void

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
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2020
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -112,13 +113,15 @@ const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
/* Extended Capabilities */
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
10,
0x74, /*
0x75, /*
* No Secure Messaging supported
* GET CHALLENGE supported
* Key import supported
* PW status byte can be put
* No private_use_DO
* Algorithm attrs are changable
* No DEC with AES
* KDF-DO available
*/
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, CHALLENGE_LEN, /* Max size of GET CHALLENGE */
@@ -133,6 +136,14 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
0x01, 0x00,
};
#ifdef ACKBTN_SUPPORT
/* General Feature Management */
static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = {
3,
0x81, 0x01, 0x20,
};
#endif
/* Algorithm Attributes */
#define OPENPGP_ALGO_RSA 0x01
#define OPENPGP_ALGO_ECDH 0x12
@@ -452,12 +463,18 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
#define GPG_DO_KGTIME_DEC 0x00cf
#define GPG_DO_KGTIME_AUT 0x00d0
#define GPG_DO_RESETTING_CODE 0x00d3
#define GPG_DO_UIF_SIG 0x00d6
#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
#define GPG_DO_URL 0x5f50
#define GPG_DO_HIST_BYTES 0x5f52
#define GPG_DO_CH_CERTIFICATE 0x7f21
#define GPG_DO_FEATURE_MNGMNT 0x7f74
static const uint8_t *do_ptr[NR_DO__LAST__];
@@ -494,6 +511,8 @@ do_tag_to_nr (uint16_t tag)
return NR_DO_NAME;
case GPG_DO_LANGUAGE:
return NR_DO_LANGUAGE;
case GPG_DO_KDF:
return NR_DO_KDF;
default:
return -1;
}
@@ -515,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;
@@ -546,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;
@@ -580,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;
@@ -614,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[] = {
@@ -626,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;
@@ -640,7 +656,7 @@ do_openpgpcard_aid (uint16_t tag, int with_tag)
if (vid == 0xffff || vid == 0x0000)
{
const uint8_t *u = unique_device_id () + 8;
const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0);
memcpy (res_p, openpgpcard_aid, 8);
res_p += 8;
@@ -662,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)
@@ -678,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
@@ -771,6 +815,8 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
{
gpg_reset_algo_attr (kk);
/* Read it again, since GC may occur. */
algo_attr_pp = get_algo_attr_pointer (kk);
flash_enum_clear (algo_attr_pp);
if (*algo_attr_pp != NULL)
return 0;
@@ -779,6 +825,10 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
(*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo))
{
gpg_reset_algo_attr (kk);
/* Read it again, since GC may occur. */
algo_attr_pp = get_algo_attr_pointer (kk);
if (*algo_attr_pp)
flash_enum_clear (algo_attr_pp);
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
if (*algo_attr_pp == NULL)
return 0;
@@ -798,6 +848,229 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
}
}
static uint8_t uif_flags; /* Six bits of flags */
#ifdef ACKBTN_SUPPORT
int
gpg_do_get_uif (enum kind_of_key kk)
{
return ((uif_flags >> (kk * 2)) & 3) != 0;
}
static int
rw_uif (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
{
uint8_t nr;
int v;
if (tag != GPG_DO_UIF_SIG && tag != GPG_DO_UIF_DEC && tag != GPG_DO_UIF_AUT)
return 0; /* Failure */
nr = (tag - GPG_DO_UIF_SIG) + NR_DO_UIF_SIG;
v = (uif_flags >> ((tag - GPG_DO_UIF_SIG) * 2)) & 3;
if (is_write)
{
const uint8_t *p;
if (len != 2 || data[1] != 0x20)
return 0;
if (v == 2)
return 0;
if (data[0] != 0x00 && data[0] != 0x01 && data[0] != 0x02)
return 0;
p = flash_enum_write (nr, data[0]);
if (p == NULL)
return 0;
uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
uif_flags |= (data[0] & 3) << ((nr - NR_DO_UIF_SIG) * 2);
return 1;
}
else
{
if (with_tag)
{
copy_tag (tag);
*res_p++ = 2;
}
*res_p++ = v;
*res_p++ = 0x20;
return 1;
}
}
#endif
#define SIZE_OF_KDF_DO_MIN 90
#define SIZE_OF_KDF_DO_MAX 110
#define OPENPGP_KDF_ITERSALTED_S2K 3
#define OPENPGP_SHA256 8
static int
rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
{
if (tag != GPG_DO_KDF)
return 0; /* Failure */
if (is_write)
{
const uint8_t **do_data_p = (const uint8_t **)&do_ptr[NR_DO_KDF];
/* KDF DO can be changed only when no keys are registered. */
if (do_ptr[NR_DO_PRVKEY_SIG] || do_ptr[NR_DO_PRVKEY_DEC]
|| do_ptr[NR_DO_PRVKEY_AUT])
return 0;
/* The valid data format is:
Deleting:
nothing
Minimum (for admin-less):
81 01 03 = KDF_ITERSALTED_S2K
82 01 08 = SHA256
83 04 4-byte... = count
84 08 8-byte... = salt
87 20 32-byte user hash
88 20 32-byte admin hash
Full:
81 01 03 = KDF_ITERSALTED_S2K
82 01 08 = SHA256
83 04 4-byte... = count
84 08 8-byte... = salt user
85 08 8-byte... = salt reset-code
86 08 8-byte... = salt admin
87 20 32-byte user hash
88 20 32-byte admin hash
*/
if (!(len == 0
|| (len == SIZE_OF_KDF_DO_MIN &&
(data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83
&& data[12] == 0x84 && data[22] == 0x87 && data[56] == 0x88))
|| (len == SIZE_OF_KDF_DO_MAX &&
(data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83
&& data[12] == 0x84 && data[22] == 0x85 && data[32] == 0x86
&& data[42] == 0x87 && data[76] == 0x88))))
return 0;
if (*do_data_p)
flash_do_release (*do_data_p);
/* Clear all keystrings and auth states */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0);
ac_reset_admin ();
ac_reset_pso_cds ();
ac_reset_other ();
if (len == 0)
{
*do_data_p = NULL;
return 1;
}
else
{
*do_data_p = flash_do_write (NR_DO_KDF, data, len);
if (*do_data_p)
return 1;
else
return 0;
}
}
else
{
if (do_ptr[NR_DO_KDF])
copy_do_1 (tag, do_ptr[NR_DO_KDF], with_tag);
else
return 0;
return 1;
}
}
/*
* 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;
int kdf_do_len = kdf_do[0];
int hash_len;
if (kdf_do_len == SIZE_OF_KDF_DO_MIN)
hash_len = kdf_spec[23];
else
hash_len = kdf_spec[43];
if ((hash_len * how_many) != len && hash_len != len)
return 0;
}
return 1;
}
void
gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, const uint8_t **r_p)
{
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
if (kdf_do)
{
int len = kdf_do[0];
const uint8_t *kdf_spec = kdf_do+1;
*r_len = 32;
if (len == SIZE_OF_KDF_DO_MIN)
{
if (is_pw3)
*r_p = kdf_spec + 58;
else
*r_p = kdf_spec + 24;
}
else
{
if (is_pw3)
*r_p = kdf_spec + 78;
else
*r_p = kdf_spec + 44;
}
}
else
{
if (is_pw3)
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW3);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3;
}
else
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW1);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
}
}
}
static int
proc_resetting_code (const uint8_t *data, int len)
{
@@ -811,31 +1084,45 @@ proc_resetting_code (const uint8_t *data, int len)
DEBUG_INFO ("Resetting Code!\r\n");
newpw_len = len;
newpw = data;
new_ks0[0] = newpw_len;
random_get_salt (salt);
s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks);
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2)
{
DEBUG_INFO ("memory error.\r\n");
return 0;
}
else if (r < 0)
{
DEBUG_INFO ("security error.\r\n");
return 0;
}
else if (r == 0)
{
DEBUG_INFO ("error (no prvkey).\r\n");
return 0;
if (len == 0)
{ /* Removal of resetting code. */
enum kind_of_key kk0;
for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++)
gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
}
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE);
if (gpg_do_kdf_check (len, 1) == 0)
return 0;
newpw_len = len;
newpw = data;
new_ks0[0] = newpw_len;
random_get_salt (salt);
s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks);
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2)
{
DEBUG_INFO ("memory error.\r\n");
return 0;
}
else if (r < 0)
{
DEBUG_INFO ("security error.\r\n");
return 0;
}
else if (r == 0)
{
DEBUG_INFO ("error (no prvkey).\r\n");
return 0;
}
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE);
}
}
gpg_pw_reset_err_counter (PW_ERR_RC);
@@ -1090,6 +1377,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
int pubkey_len;
uint8_t ks[KEYSTRING_MD_SIZE];
enum kind_of_key kk0;
int pw_len;
const uint8_t *initial_pw;
DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (prvkey_len);
@@ -1147,8 +1436,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
s2k (NULL, 0, initial_pw, pw_len, ks);
/* Handle existing keys and keystring DOs. */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
@@ -1329,6 +1618,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
@@ -1438,18 +1734,32 @@ static const uint16_t cmp_ch_data[] = {
};
static const uint16_t cmp_app_data[] = {
#ifdef ACKBTN_SUPPORT
4,
#else
3,
#endif
GPG_DO_AID,
GPG_DO_HIST_BYTES,
GPG_DO_DISCRETIONARY,
#ifdef ACKBTN_SUPPORT
GPG_DO_FEATURE_MNGMNT,
#endif
};
static const uint16_t cmp_discretionary[] = {
#ifdef ACKBTN_SUPPORT
11,
#else
8,
#endif
GPG_DO_EXTCAP,
GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
GPG_DO_PW_STATUS,
GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL
GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL,
#ifdef ACKBTN_SUPPORT
GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT
#endif
};
static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT };
@@ -1479,6 +1789,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 },
@@ -1488,9 +1799,19 @@ gpg_do_table[] = {
rw_algorithm_attr },
{ GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_algorithm_attr },
#ifdef ACKBTN_SUPPORT
{ GPG_DO_UIF_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
{ GPG_DO_UIF_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
{ GPG_DO_UIF_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
#endif
{ GPG_DO_KDF, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_kdf },
/* Fixed data */
{ GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes },
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
#ifdef ACKBTN_SUPPORT
{ GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt },
#endif
/* Compound data: Read access only */
{ GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
{ GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
@@ -1529,6 +1850,11 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
pw_err_counter_p[PW_ERR_PW3] = NULL;
algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL;
digital_signature_counter = 0;
uif_flags = 0;
/* Clear all data objects. */
for (i = 0; i < NR_DO__LAST__; i++)
do_ptr[i] = NULL;
/* When the card is terminated no data objects are valid. */
if (do_start == NULL)
@@ -1587,6 +1913,13 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
algo_attr_aut_p = p - 1;
p++;
break;
case NR_DO_UIF_SIG:
case NR_DO_UIF_DEC:
case NR_DO_UIF_AUT:
uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
uif_flags |= (second_byte & 3) << ((nr - NR_DO_UIF_SIG) * 2);
p++;
break;
case NR_COUNTER_123:
p++;
if (second_byte <= PW_ERR_PW3)
@@ -1686,6 +2019,13 @@ gpg_data_copy (const uint8_t *p_start)
p += 4;
}
for (i = 0; i < 3; i++)
if ((v = (uif_flags >> (i * 2)) & 3))
{
flash_enum_write_internal (p, NR_DO_UIF_SIG + i, v);
p += 2;
}
data_objects_number_of_bytes = 0;
for (i = 0; i < NR_DO__LAST__; i++)
if (do_ptr[i] != NULL)
@@ -1799,9 +2139,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:
{
@@ -2067,10 +2408,10 @@ gpg_do_keygen (uint8_t *buf)
const uint8_t *prv;
const uint8_t *rnd;
int r = 0;
#define p_q buf
#define d buf
#define d1 (&buf[64])
#define pubkey (&buf[256])
#define p_q (&buf[3])
#define d (&buf[3])
#define d1 (&buf[3+64])
#define pubkey (&buf[3+256])
DEBUG_INFO ("Keygen\r\n");
DEBUG_BYTE (kk_byte);
@@ -2088,7 +2429,7 @@ gpg_do_keygen (uint8_t *buf)
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
const uint8_t *p;
int i, r;
int i;
rnd = NULL;
do
@@ -2173,14 +2514,16 @@ gpg_do_keygen (uint8_t *buf)
if (kk == GPG_KEY_FOR_SIGNING)
{
const uint8_t *pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
int pw_len;
const uint8_t *initial_pw;
uint8_t keystring[KEYSTRING_MD_SIZE];
/* GnuPG expects it's ready for signing. */
/* Don't call ac_reset_pso_cds here, but load the private key */
gpg_reset_digital_signature_counter ();
s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
s2k (NULL, 0, initial_pw, pw_len, keystring);
gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
}
else

View File

@@ -1,7 +1,8 @@
/*
* openpgp.c -- OpenPGP card protocol support
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* 2019
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -37,6 +38,7 @@
static struct eventflag *openpgp_comm;
#define USER_PASSWD_MINLEN 6
#define ADMIN_PASSWD_MINLEN 8
#define CLS(a) a.cmd_apdu_head[0]
@@ -144,7 +146,7 @@ get_pinpad_input (int msg_code)
#endif
static void
cmd_verify (void)
cmd_verify (struct eventflag *ccid_comm)
{
int len;
uint8_t p1 = P1 (apdu);
@@ -152,6 +154,7 @@ cmd_verify (void)
int r;
const uint8_t *pw;
(void)ccid_comm;
DEBUG_INFO (" - VERIFY\r\n");
DEBUG_BYTE (p2);
@@ -170,7 +173,8 @@ cmd_verify (void)
r = ac_check_status (AC_ADMIN_AUTHORIZED);
if (r)
GPG_SUCCESS (); /* If authentication done already, return success. */
/* If authentication done already, return success. */
GPG_SUCCESS ();
else
{ /* If not, return retry counter, encoded. */
r = gpg_pw_get_retry_counter (p2);
@@ -192,6 +196,12 @@ cmd_verify (void)
return;
}
if (gpg_do_kdf_check (len, 1) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
/* This is real authentication. */
if (p2 == 0x81)
r = verify_pso_cds (pw, len);
@@ -267,7 +277,7 @@ gpg_change_keystring (int who_old, const uint8_t *old_ks,
}
static void
cmd_change_password (void)
cmd_change_password (struct eventflag *ccid_comm)
{
uint8_t old_ks[KEYSTRING_MD_SIZE];
uint8_t new_ks0[KEYSTRING_SIZE];
@@ -287,6 +297,7 @@ cmd_change_password (void)
int salt_len;
const uint8_t *ks_pw3;
(void)ccid_comm;
DEBUG_INFO ("Change PW\r\n");
DEBUG_BYTE (who);
@@ -299,6 +310,12 @@ cmd_change_password (void)
return;
}
if (gpg_do_kdf_check (len, 2) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
if (who == BY_USER) /* PW1 */
{
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
@@ -335,8 +352,9 @@ cmd_change_password (void)
newpw_len = len - pw_len;
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
/* Check length of password for admin-less mode. */
if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
/* Check length of 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 ();
@@ -351,8 +369,24 @@ cmd_change_password (void)
if (ks_pw3 == NULL)
{
salt = NULL;
salt_len = 0;
if (admin_authorized == BY_USER)
{
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
if (ks_pw1 == NULL)
{
GPG_SECURITY_FAILURE ();
return;
}
salt = KS_GET_SALT (ks_pw1);
salt_len = SALT_SIZE;
}
else
{
salt = NULL;
salt_len = 0;
}
}
else
{
@@ -376,13 +410,22 @@ cmd_change_password (void)
{
newpw = pw + pw_len;
newpw_len = len - pw_len;
if (newpw_len == 0 && admin_authorized == BY_ADMIN)
{
newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
const uint8_t *initial_pw;
gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw);
memcpy (newpw, initial_pw, newpw_len);
newsalt_len = 0;
pw3_null = 1;
}
else if (newpw_len < ADMIN_PASSWD_MINLEN)
{
DEBUG_INFO ("new password length is too short.");
GPG_CONDITION_NOT_SATISFIED ();
return;
}
who_old = admin_authorized;
}
@@ -412,11 +455,26 @@ cmd_change_password (void)
}
else if (r > 0 && who == BY_USER)
{
/* When it was already admin-less mode, admin_authorized is
* BY_USER. If no PW3 keystring, it's becoming admin-less mode,
* now. For these two cases, we need to reset admin
* authorization status. */
if (admin_authorized == BY_USER)
ac_reset_admin ();
else if (ks_pw3 == NULL)
{
enum kind_of_key kk0;
/* Remove keystrings for BY_ADMIN. */
for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++)
gpg_do_chks_prvkey (kk0, BY_ADMIN, NULL, 0, NULL);
ac_reset_admin ();
}
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
GPG_SUCCESS ();
}
@@ -492,7 +550,7 @@ s2k (const unsigned char *salt, size_t slen,
static void
cmd_reset_user_password (void)
cmd_reset_user_password (struct eventflag *ccid_comm)
{
uint8_t p1 = P1 (apdu);
int len;
@@ -503,9 +561,11 @@ cmd_reset_user_password (void)
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;
(void)ccid_comm;
DEBUG_INFO ("Reset PW1\r\n");
DEBUG_BYTE (p1);
@@ -517,6 +577,12 @@ cmd_reset_user_password (void)
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
uint8_t old_ks[KEYSTRING_MD_SIZE];
if (gpg_do_kdf_check (len, 2) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
if (gpg_pw_locked (PW_ERR_RC))
{
DEBUG_INFO ("blocked.\r\n");
@@ -536,6 +602,16 @@ cmd_reset_user_password (void)
salt_len = SALT_SIZE;
newpw = pw + pw_len;
newpw_len = len - pw_len;
/* 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 (salt, salt_len, pw, pw_len, old_ks);
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
@@ -581,8 +657,24 @@ cmd_reset_user_password (void)
return;
}
if (gpg_do_kdf_check (len, 1) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
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;
@@ -617,12 +709,13 @@ cmd_reset_user_password (void)
}
static void
cmd_put_data (void)
cmd_put_data (struct eventflag *ccid_comm)
{
uint8_t *data;
uint16_t tag;
int len;
(void)ccid_comm;
DEBUG_INFO (" - PUT DATA\r\n");
tag = ((P1 (apdu)<<8) | P2 (apdu));
@@ -632,8 +725,9 @@ cmd_put_data (void)
}
static void
cmd_pgp_gakp (void)
cmd_pgp_gakp (struct eventflag *ccid_comm)
{
(void)ccid_comm;
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
DEBUG_BYTE (P1 (apdu));
@@ -644,7 +738,12 @@ cmd_pgp_gakp (void)
{
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
GPG_SECURITY_FAILURE ();
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
#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]);
}
}
@@ -652,10 +751,10 @@ cmd_pgp_gakp (void)
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
@@ -667,12 +766,13 @@ gpg_get_firmware_update_key (uint8_t keyno)
#endif
static void
cmd_read_binary (void)
cmd_read_binary (struct eventflag *ccid_comm)
{
int is_short_EF = (P1 (apdu) & 0x80) != 0;
uint8_t file_id;
uint16_t offset;
(void)ccid_comm;
DEBUG_INFO (" - Read binary\r\n");
if (is_short_EF)
@@ -743,8 +843,9 @@ cmd_read_binary (void)
}
static void
cmd_select_file (void)
cmd_select_file (struct eventflag *ccid_comm)
{
(void)ccid_comm;
if (P1 (apdu) == 4) /* Selection by DF name */
{
DEBUG_INFO (" - select DF by name\r\n");
@@ -813,10 +914,11 @@ cmd_select_file (void)
}
static void
cmd_get_data (void)
cmd_get_data (struct eventflag *ccid_comm)
{
uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
(void)ccid_comm;
DEBUG_INFO (" - Get Data\r\n");
gpg_do_get_data (tag, 0);
@@ -831,7 +933,7 @@ cmd_get_data (void)
#define ECC_CIPHER_DO_HEADER_SIZE 7
static void
cmd_pso (void)
cmd_pso (struct eventflag *ccid_comm)
{
int len = apdu.cmd_apdu_data_len;
int r = -1;
@@ -858,6 +960,11 @@ cmd_pso (void)
return;
}
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
#endif
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
/* Check size of digestInfo */
@@ -903,13 +1010,6 @@ cmd_pso (void)
{
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,
@@ -949,6 +1049,13 @@ cmd_pso (void)
return;
}
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
#else
(void)ccid_comm;
#endif
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
/* Skip padding 0x00 */
@@ -1025,7 +1132,7 @@ cmd_pso (void)
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
static void
cmd_internal_authenticate (void)
cmd_internal_authenticate (struct eventflag *ccid_comm)
{
int attr = gpg_get_algo_attr (GPG_KEY_FOR_AUTHENTICATION);
int pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_AUTHENTICATION,
@@ -1055,6 +1162,13 @@ cmd_internal_authenticate (void)
return;
}
#ifdef ACKBTN_SUPPORT
if (gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
#else
(void)ccid_comm;
#endif
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
if (len > MAX_RSA_DIGEST_INFO_LEN)
@@ -1102,13 +1216,6 @@ cmd_internal_authenticate (void)
{
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,
@@ -1231,10 +1338,11 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
#if defined(CERTDO_SUPPORT)
static void
cmd_update_binary (void)
cmd_update_binary (struct eventflag *ccid_comm)
{
int len = apdu.cmd_apdu_data_len;
(void)ccid_comm;
DEBUG_INFO (" - UPDATE BINARY\r\n");
modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len);
DEBUG_INFO ("UPDATE BINARY done.\r\n");
@@ -1243,10 +1351,11 @@ cmd_update_binary (void)
static void
cmd_write_binary (void)
cmd_write_binary (struct eventflag *ccid_comm)
{
int len = apdu.cmd_apdu_data_len;
(void)ccid_comm;
DEBUG_INFO (" - WRITE BINARY\r\n");
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
DEBUG_INFO ("WRITE BINARY done.\r\n");
@@ -1255,7 +1364,7 @@ cmd_write_binary (void)
#ifdef FLASH_UPGRADE_SUPPORT
static void
cmd_external_authenticate (void)
cmd_external_authenticate (struct eventflag *ccid_comm)
{
const uint8_t *pubkey;
const uint8_t *signature = apdu.cmd_apdu_data;
@@ -1263,6 +1372,7 @@ cmd_external_authenticate (void)
uint8_t keyno = P2 (apdu);
int r;
(void)ccid_comm;
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
if (keyno >= 4)
@@ -1298,10 +1408,11 @@ cmd_external_authenticate (void)
#endif
static void
cmd_get_challenge (void)
cmd_get_challenge (struct eventflag *ccid_comm)
{
int len = apdu.expected_res_size;
(void)ccid_comm;
DEBUG_INFO (" - GET CHALLENGE\r\n");
if (len > CHALLENGE_LEN)
@@ -1316,6 +1427,13 @@ cmd_get_challenge (void)
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;
@@ -1326,8 +1444,9 @@ cmd_get_challenge (void)
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
static void
cmd_activate_file (void)
cmd_activate_file (struct eventflag *ccid_comm)
{
(void)ccid_comm;
if (file_selection != FILE_CARD_TERMINATED)
{
GPG_NO_RECORD ();
@@ -1340,13 +1459,13 @@ cmd_activate_file (void)
}
static void
cmd_terminate_df (void)
cmd_terminate_df (struct eventflag *ccid_comm)
{
const uint8_t *ks_pw3;
uint8_t p1 = P1 (apdu);
uint8_t p2 = P2 (apdu);
(void)ccid_comm;
if (file_selection != FILE_DF_OPENPGP)
{
GPG_NO_RECORD ();
@@ -1390,7 +1509,7 @@ cmd_terminate_df (void)
struct command
{
uint8_t command;
void (*cmd_handler) (void);
void (*cmd_handler) (struct eventflag *ccid_comm);
};
const struct command cmds[] = {
@@ -1424,7 +1543,7 @@ const struct command cmds[] = {
#define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
static void
process_command_apdu (void)
process_command_apdu (struct eventflag *ccid_comm)
{
int i;
uint8_t cmd = INS (apdu);
@@ -1448,7 +1567,7 @@ process_command_apdu (void)
else
{
chopstx_setcancelstate (1);
cmds[i].cmd_handler ();
cmds[i].cmd_handler (ccid_comm);
chopstx_setcancelstate (0);
}
}
@@ -1562,7 +1681,7 @@ openpgp_card_thread (void *arg)
break;
led_blink (LED_START_COMMAND);
process_command_apdu ();
process_command_apdu (ccid_comm);
led_blink (LED_FINISH_COMMAND);
done:
eventflag_signal (ccid_comm, EV_EXEC_FINISHED);

View File

@@ -40,14 +40,14 @@ cir_ext_disable (void)
int rcvd = (EXTI->PR & EXTI_PR) != 0;
EXTI->IMR &= ~EXTI_IMR;
EXTI->PR = EXTI_PR;
EXTI->PR |= EXTI_PR;
return rcvd;
}
static void
cir_ext_enable (void)
{
EXTI->PR = EXTI_PR;
EXTI->PR |= EXTI_PR;
EXTI->IMR |= EXTI_IMR;
}
@@ -986,6 +986,7 @@ tim_main (void *arg)
{
chopstx_intr_wait (&interrupt);
cir_timer_interrupt ();
chopstx_intr_done (&interrupt);
}
return NULL;
@@ -1006,6 +1007,7 @@ ext_main (void *arg)
{
chopstx_intr_wait (&interrupt);
cir_ext_interrupt ();
chopstx_intr_done (&interrupt);
}
return NULL;
@@ -1033,8 +1035,8 @@ cir_init (void)
/* EXTIx <= Py */
AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py;
EXTI->IMR = 0;
EXTI->FTSR = EXTI_FTSR_TR;
EXTI->IMR &= ~EXTI_IMR;
EXTI->FTSR |= EXTI_FTSR_TR;
/* TIM */
#ifdef ENABLE_RCC_APB1

View File

@@ -1,12 +1,18 @@
#ifdef GNU_LINUX_EMULATION
#define SIZE_1 4096
#define SIZE_2 4096
#define SIZE_3 (4 * 4096)
#define SIZE_3 (5 * 4096)
#else
#define SIZE_0 0x0100 /* Main */
#define SIZE_0 0x0160 /* Main */
#define SIZE_1 0x01a0 /* CCID */
#define SIZE_2 0x0180 /* RNG */
#if MEMORY_SIZE >= 32
#define SIZE_3 0x4640 /* openpgp-card */
#elif MEMORY_SIZE >= 24
#define SIZE_3 0x2640 /* openpgp-card */
#else
#define SIZE_3 0x1640 /* openpgp-card */
#endif
#define SIZE_4 0x0000 /* --- */
#define SIZE_5 0x0200 /* msc */
#define SIZE_6 0x00c0 /* timer (cir) */

39
src/stdaln-sys.ld.in Normal file
View File

@@ -0,0 +1,39 @@
/*
* ST32F103 memory setup.
*/
MEMORY
{
flash0 : org = @ORIGIN_REAL@, len = 4k
ram : org = 0x20000000, len = @MEMORY_SIZE@k
}
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
SECTIONS
{
. = 0;
.sys : ALIGN(4) SUBALIGN(4)
{
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
KEEP(*(.sys.version))
KEEP(*(.sys.board_id))
KEEP(*(.sys.board_name))
build/sys-*.o(.text)
build/sys-*.o(.text.*)
build/sys-*.o(.rodata)
build/sys-*.o(.rodata.*)
. = ALIGN(1024);
} > flash0
.aesft : ALIGN(4) SUBALIGN(4)
{
*(.sys.0)
*(.sys.1)
*(.sys.2)
} > flash0
}

View File

@@ -1,7 +1,8 @@
/*
* usb-ccid.c -- USB CCID protocol handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2019
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -29,6 +30,10 @@
#include "config.h"
#ifdef ACKBTN_SUPPORT
#include <contrib/ackbtn.h>
#endif
#ifdef DEBUG
#include "usb-cdc.h"
#include "debug.h"
@@ -182,9 +187,11 @@ struct ccid_header {
/* Data structure handled by CCID layer */
struct ccid {
enum ccid_state ccid_state;
uint8_t state;
uint8_t err;
uint32_t ccid_state : 4;
uint32_t state : 4;
uint32_t err : 1;
uint32_t tx_busy : 1;
uint32_t timeout_cnt: 3;
uint8_t *p;
size_t len;
@@ -241,6 +248,7 @@ struct ccid {
static void ccid_reset (struct ccid *c)
{
c->err = 0;
c->tx_busy = 0;
c->state = APDU_STATE_WAIT_COMMAND;
c->p = c->a->cmd_apdu_data;
c->len = MAX_CMD_APDU_DATA_SIZE;
@@ -252,10 +260,11 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo,
struct apdu *a)
{
c->ccid_state = CCID_STATE_START;
c->err = 0;
c->tx_busy = 0;
c->state = APDU_STATE_WAIT_COMMAND;
c->p = a->cmd_apdu_data;
c->len = MAX_CMD_APDU_DATA_SIZE;
c->err = 0;
memset (&c->ccid_header, 0, sizeof (struct ccid_header));
c->sw1sw2[0] = 0x90;
c->sw1sw2[1] = 0x00;
@@ -765,6 +774,7 @@ usb_tx_done (uint8_t ep_num, uint16_t len)
#endif
}
/*
* ATR (Answer To Reset) string
*
@@ -820,6 +830,7 @@ static void ccid_error (struct ccid *c, int offset)
#else
usb_lld_write (c->epi->ep_num, ccid_reply, CCID_MSG_HEADER_SIZE);
#endif
c->tx_busy = 1;
}
extern void *openpgp_card_thread (void *arg);
@@ -893,7 +904,7 @@ ccid_power_on (struct ccid *c)
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE + size_atr);
#endif
DEBUG_INFO ("ON\r\n");
c->tx_busy = 1;
return CCID_STATE_WAIT;
}
@@ -934,6 +945,7 @@ ccid_send_status (struct ccid *c)
#ifdef DEBUG_MORE
DEBUG_INFO ("St\r\n");
#endif
c->tx_busy = 1;
}
static enum ccid_state
@@ -949,6 +961,7 @@ ccid_power_off (struct ccid *c)
c->ccid_state = CCID_STATE_START; /* This status change should be here */
ccid_send_status (c);
DEBUG_INFO ("OFF\r\n");
c->tx_busy = 1;
return CCID_STATE_START;
}
@@ -982,12 +995,16 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
#endif
if (len == 0)
{
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf,
CCID_MSG_HEADER_SIZE);
#else
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE);
#endif
c->tx_busy = 1;
return;
}
@@ -1065,6 +1082,7 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
c->tx_busy = 1;
}
static void
@@ -1076,7 +1094,8 @@ ccid_send_data_block (struct ccid *c)
static void
ccid_send_data_block_time_extension (struct ccid *c)
{
ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT, 1);
ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT,
c->ccid_state == CCID_STATE_EXECUTE? 1: 0xff);
}
static void
@@ -1115,6 +1134,7 @@ ccid_send_data_block_0x9000 (struct ccid *c)
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
c->tx_busy = 1;
}
/*
@@ -1211,6 +1231,7 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len)
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
c->tx_busy = 1;
}
@@ -1259,6 +1280,7 @@ ccid_send_params (struct ccid *c)
#ifdef DEBUG_MORE
DEBUG_INFO ("PARAMS\r\n");
#endif
c->tx_busy = 1;
}
@@ -1413,6 +1435,7 @@ ccid_handle_data (struct ccid *c)
c->a->res_apdu_data_len = 0;
c->a->res_apdu_data = &c->p[5];
c->state = APDU_STATE_COMMAND_RECEIVED;
eventflag_signal (&c->openpgp_comm, EV_VERIFY_CMD_AVAILABLE);
next_state = CCID_STATE_EXECUTE;
}
@@ -1447,6 +1470,7 @@ ccid_handle_data (struct ccid *c)
c->a->res_apdu_data_len = 0;
c->a->res_apdu_data = &ccid_buffer[5];
c->state = APDU_STATE_COMMAND_RECEIVED;
eventflag_signal (&c->openpgp_comm, EV_MODIFY_CMD_AVAILABLE);
next_state = CCID_STATE_EXECUTE;
}
@@ -1461,6 +1485,8 @@ ccid_handle_data (struct ccid *c)
}
break;
case CCID_STATE_EXECUTE:
case CCID_STATE_ACK_REQUIRED_0:
case CCID_STATE_ACK_REQUIRED_1:
if (c->ccid_header.msg_type == CCID_POWER_OFF)
next_state = ccid_power_off (c);
else if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
@@ -1489,6 +1515,8 @@ ccid_handle_timeout (struct ccid *c)
switch (c->ccid_state)
{
case CCID_STATE_EXECUTE:
case CCID_STATE_ACK_REQUIRED_0:
case CCID_STATE_ACK_REQUIRED_1:
ccid_send_data_block_time_extension (c);
break;
default:
@@ -1500,7 +1528,13 @@ ccid_handle_timeout (struct ccid *c)
}
static struct ccid ccid;
enum ccid_state *const ccid_state_p = &ccid.ccid_state;
enum ccid_state
ccid_get_ccid_state (void)
{
return ccid.ccid_state;
}
void
ccid_card_change_signal (int how)
@@ -1513,14 +1547,6 @@ ccid_card_change_signal (int how)
eventflag_signal (&c->ccid_comm, EV_CARD_CHANGE);
}
void
ccid_usb_reset (int full)
{
struct ccid *c = &ccid;
eventflag_signal (&c->ccid_comm,
full ? EV_USB_DEVICE_RESET : EV_USB_SET_INTERFACE);
}
#ifdef GNU_LINUX_EMULATION
static uint8_t endp2_tx_buf[2];
@@ -1553,14 +1579,7 @@ ccid_notify_slot_change (struct ccid *c)
#define USB_CCID_TIMEOUT (1950*1000)
#define GPG_THREAD_TERMINATED 0xffff
#ifdef GNU_LINUX_EMULATION
#include <signal.h>
#define INTR_REQ_USB SIGUSR1
#else
#define INTR_REQ_USB 20
#endif
#define GPG_ACK_TIMEOUT 0x6600
extern uint32_t bDeviceState;
extern void usb_device_reset (struct usb_dev *dev);
@@ -1573,7 +1592,20 @@ extern int usb_get_status_interface (struct usb_dev *dev);
extern int usb_get_descriptor (struct usb_dev *dev);
static void
extern void random_init (void);
extern void random_fini (void);
#ifdef ACKBTN_SUPPORT
static chopstx_intr_t ack_intr;
#endif
static chopstx_intr_t usb_intr;
/*
* Return 0 for normal USB event
* -1 for USB reset
* 1 for SET_INTERFACE or SET_CONFIGURATION
*/
static int
usb_event_handle (struct usb_dev *dev)
{
uint8_t ep_num;
@@ -1581,95 +1613,124 @@ usb_event_handle (struct usb_dev *dev)
e = usb_lld_event_handler (dev);
ep_num = USB_EVENT_ENDP (e);
chopstx_intr_done (&usb_intr);
/* Transfer to endpoint (not control endpoint) */
if (ep_num != 0)
{
if (USB_EVENT_TXRX (e))
usb_tx_done (ep_num, USB_EVENT_LEN (e));
else
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
return 0;
}
else
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (dev);
break;
case USB_EVENT_DEVICE_ADDRESSED:
bDeviceState = ADDRESSED;
break;
/* Control endpoint */
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (dev);
return -1;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_DEVICE_ADDRESSED:
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
break;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (dev) < 0)
usb_lld_ctrl_error (dev);
else
{
if (bDeviceState == USB_DEVICE_STATE_ADDRESSED)
/* de-Configured */
return -1;
else
/* Configured */
return 1;
}
break;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (dev) < 0)
usb_lld_ctrl_error (dev);
else
return 1;
break;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (dev);
break;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (dev);
break;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (dev);
break;
case USB_EVENT_OK:
case USB_EVENT_DEVICE_SUSPEND:
default:
break;
}
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (dev);
break;
case USB_EVENT_DEVICE_SUSPEND:
led_blink (LED_OFF);
chopstx_usec_wait (10); /* Make sure LED off */
random_fini ();
chopstx_conf_idle (2);
bDeviceState |= USB_DEVICE_STATE_SUSPEND;
break;
case USB_EVENT_DEVICE_WAKEUP:
chopstx_conf_idle (1);
random_init ();
bDeviceState &= ~USB_DEVICE_STATE_SUSPEND;
break;
case USB_EVENT_OK:
default:
break;
}
return 0;
}
static void
poll_event_intr (uint32_t *timeout, struct eventflag *ev, chopstx_intr_t *intr)
{
chopstx_poll_cond_t poll_desc;
struct chx_poll_head *pd_array[2] = {
(struct chx_poll_head *)intr,
(struct chx_poll_head *)&poll_desc
};
eventflag_prepare_poll (ev, &poll_desc);
chopstx_poll (timeout, 2, pd_array);
}
static chopstx_poll_cond_t ccid_event_poll_desc;
static struct chx_poll_head *const ccid_poll[] = {
(struct chx_poll_head *const)&usb_intr,
(struct chx_poll_head *const)&ccid_event_poll_desc,
#ifdef ACKBTN_SUPPORT
(struct chx_poll_head *const)&ack_intr
#endif
};
#define CCID_POLL_NUM (sizeof (ccid_poll)/sizeof (struct chx_poll_head *))
void *
ccid_thread (void *arg)
{
chopstx_intr_t interrupt;
uint32_t timeout;
struct usb_dev dev;
struct ccid *c = &ccid;
uint32_t *timeout_p;
int ackbtn_active = 0;
(void)arg;
@@ -1677,65 +1738,101 @@ ccid_thread (void *arg)
eventflag_init (&ccid.openpgp_comm);
usb_lld_init (&dev, USB_INITIAL_FEATURE);
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
usb_event_handle (&dev); /* For old SYS < 3.0 */
device_reset:
#ifdef ACKBTN_SUPPORT
ackbtn_init (&ack_intr);
#endif
eventflag_prepare_poll (&c->ccid_comm, &ccid_event_poll_desc);
reset:
{
struct ep_in *epi = &endpoint_in;
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);
ccid_init (c, epi, epo, a);
}
while (bDeviceState != CONFIGURED)
timeout = USB_CCID_TIMEOUT;
if (bDeviceState == USB_DEVICE_STATE_CONFIGURED)
{
poll_event_intr (NULL, &c->ccid_comm, &interrupt);
if (interrupt.ready)
usb_event_handle (&dev);
eventflag_get (&c->ccid_comm);
/* Ignore event while not-configured. */
ccid_prepare_receive (c);
ccid_notify_slot_change (c);
}
interface_reset:
timeout = USB_CCID_TIMEOUT;
ccid_prepare_receive (c);
ccid_notify_slot_change (c);
while (1)
{
eventmask_t m;
poll_event_intr (&timeout, &c->ccid_comm, &interrupt);
if (interrupt.ready)
{
usb_event_handle (&dev);
continue;
}
if (!c->tx_busy && bDeviceState == USB_DEVICE_STATE_CONFIGURED)
timeout_p = &timeout;
else
timeout_p = NULL;
timeout = USB_CCID_TIMEOUT;
m = eventflag_get (&c->ccid_comm);
eventflag_set_mask (&c->ccid_comm, c->tx_busy ? EV_TX_FINISHED : ~0);
if (m == EV_USB_DEVICE_RESET)
#ifdef ACKBTN_SUPPORT
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
if (usb_intr.ready)
{
if (usb_event_handle (&dev) == 0)
continue;
/* RESET handling:
* (1) After DEVICE_RESET, it needs to re-start out of the loop.
* (2) After SET_CONFIGURATION or SET_INTERFACE, the
* endpoint is reset to RX_NAK. It needs to prepare
* receive again.
*/
if (c->application)
{
chopstx_cancel (c->application);
chopstx_join (c->application, NULL);
c->application = 0;
}
goto device_reset;
goto reset;
}
else if (m == EV_USB_SET_INTERFACE)
/* Upon receival of SET_INTERFACE, the endpoint is reset to RX_NAK.
* Thus, we need to prepare receive again.
*/
goto interface_reset;
else if (m == EV_CARD_CHANGE)
#ifdef ACKBTN_SUPPORT
if (!c->tx_busy && ack_intr.ready)
{
ackbtn_active = 0;
ackbtn_disable ();
led_blink (LED_WAIT_FOR_BUTTON);
chopstx_intr_done (&ack_intr);
if (c->ccid_state == CCID_STATE_ACK_REQUIRED_1)
goto exec_done;
c->ccid_state = CCID_STATE_EXECUTE;
continue;
}
#endif
if (timeout == 0)
{
timeout = USB_CCID_TIMEOUT;
c->timeout_cnt++;
}
m = eventflag_get (&c->ccid_comm);
if (m == EV_CARD_CHANGE)
{
if (c->ccid_state == CCID_STATE_NOCARD)
/* Inserted! */
@@ -1755,10 +1852,17 @@ 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)
{
#ifdef ACKBTN_SUPPORT
exec_done:
#endif
if (c->a->sw == GPG_THREAD_TERMINATED)
{
c->sw1sw2[0] = 0x90;
@@ -1788,21 +1892,35 @@ ccid_thread (void *arg)
c->ccid_state = CCID_STATE_WAIT;
}
}
#ifdef ACKBTN_SUPPORT
else if (c->ccid_state == CCID_STATE_ACK_REQUIRED_0)
c->ccid_state = CCID_STATE_ACK_REQUIRED_1;
#endif
else
{
DEBUG_INFO ("ERR07\r\n");
DEBUG_INFO ("ERR05\r\n");
}
#ifdef ACKBTN_SUPPORT
else if (m == EV_EXEC_ACK_REQUIRED)
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);
}
else
{
DEBUG_INFO ("ERR06\r\n");
}
#endif
else if (m == EV_TX_FINISHED)
{
if (c->state == APDU_STATE_RESULT)
{
c->state = APDU_STATE_WAIT_COMMAND;
c->p = c->a->cmd_apdu_data;
c->len = MAX_CMD_APDU_DATA_SIZE;
c->err = 0;
c->a->cmd_apdu_data_len = 0;
c->a->expected_res_size = 0;
}
ccid_reset (c);
else
c->tx_busy = 0;
if (c->state == APDU_STATE_WAIT_COMMAND
|| c->state == APDU_STATE_COMMAND_CHAINING
@@ -1810,7 +1928,22 @@ ccid_thread (void *arg)
ccid_prepare_receive (c);
}
else /* Timeout */
c->ccid_state = ccid_handle_timeout (c);
{
#ifdef ACKBTN_SUPPORT
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
#endif
c->ccid_state = ccid_handle_timeout (c);
}
}
if (c->application)
@@ -1820,9 +1953,9 @@ ccid_thread (void *arg)
}
/* Loading reGNUal. */
while (bDeviceState != UNCONNECTED)
while (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
{
chopstx_intr_wait (&interrupt);
chopstx_intr_wait (&usb_intr);
usb_event_handle (&dev);
}

View File

@@ -1,7 +1,7 @@
/*
* usb_ctrl.c - USB control pipe device specific code for Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -87,7 +87,7 @@ vcom_port_data_setup (struct usb_dev *dev)
#include "usb-msc.h"
#endif
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
#define USB_HID_REQ_GET_REPORT 1
#define USB_HID_REQ_GET_IDLE 2
@@ -202,8 +202,6 @@ gnuk_setup_endpoints_for_interface (struct usb_dev *dev,
void
usb_device_reset (struct usb_dev *dev)
{
int i;
usb_lld_reset (dev, USB_INITIAL_FEATURE);
/* Initialize Endpoint 0 */
@@ -214,12 +212,7 @@ usb_device_reset (struct usb_dev *dev)
64);
#endif
/* Stop the interface */
for (i = 0; i < NUM_INTERFACES; i++)
gnuk_setup_endpoints_for_interface (dev, i, 1);
bDeviceState = ATTACHED;
ccid_usb_reset (1);
bDeviceState = USB_DEVICE_STATE_DEFAULT;
}
#define USB_CCID_REQ_ABORT 0x01
@@ -234,7 +227,7 @@ static const uint8_t lun_table[] = { 0, 0, 0, 0, };
#endif
#ifdef FLASH_UPGRADE_SUPPORT
static const uint8_t *const mem_info[] = { &_regnual_start, __heap_end__, };
static const uint8_t *const mem_info[] = { _regnual_start, __heap_end__, };
#endif
#define USB_FSIJ_GNUK_MEMINFO 0
@@ -288,10 +281,10 @@ usb_setup (struct usb_dev *dev)
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
return -1;
if (addr < &_regnual_start || addr + arg->len > __heap_end__)
if (addr < _regnual_start || addr + arg->len > __heap_end__)
return -1;
if (arg->index + arg->len < 256)
@@ -306,7 +299,7 @@ usb_setup (struct usb_dev *dev)
else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
return -1;
if (((uintptr_t)addr & 0x03))
@@ -411,10 +404,10 @@ usb_ctrl_write_finish (struct usb_dev *dev)
{
if (USB_SETUP_SET (arg->type) && arg->request == USB_FSIJ_GNUK_EXEC)
{
if (*ccid_state_p != CCID_STATE_EXITED)
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
return;
bDeviceState = UNCONNECTED;
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
usb_lld_prepare_shutdown (); /* No further USB communication */
led_blink (LED_GNUK_EXEC); /* Notify the main. */
}
@@ -476,7 +469,7 @@ usb_set_configuration (struct usb_dev *dev)
usb_lld_set_configuration (dev, 1);
for (i = 0; i < NUM_INTERFACES; i++)
gnuk_setup_endpoints_for_interface (dev, i, 0);
bDeviceState = CONFIGURED;
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
}
else if (current_conf != dev->dev_req.value)
{
@@ -486,8 +479,7 @@ usb_set_configuration (struct usb_dev *dev)
usb_lld_set_configuration (dev, 0);
for (i = 0; i < NUM_INTERFACES; i++)
gnuk_setup_endpoints_for_interface (dev, i, 1);
bDeviceState = ADDRESSED;
ccid_usb_reset (1);
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
}
/* Do nothing when current_conf == value */
@@ -509,7 +501,6 @@ usb_set_interface (struct usb_dev *dev)
else
{
gnuk_setup_endpoints_for_interface (dev, interface, 0);
ccid_usb_reset (0);
return usb_lld_ctrl_ack (dev);
}
}

View File

@@ -65,12 +65,14 @@ static const
uint8_t device_desc[] = {
18, /* bLength */
DEVICE_DESCRIPTOR, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */
0x00, 0x02, /* bcdUSB = 2.0 */
0x00, /* bDeviceClass: 0 means deferred to interface */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
#include "usb-vid-pid-ver.c.inc"
0x00, 0x00, /* idVendor (will be replaced) */
0x00, 0x00, /* idProduct (will be replaced) */
0x00, 0x00, /* bcdDevice (will be replaced) */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */

View File

@@ -8,7 +8,7 @@ Feature: command GET DATA
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1

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

@@ -8,7 +8,7 @@ Feature: command GET DATA
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1

View File

@@ -8,7 +8,7 @@ Feature: command GET DATA
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1

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

@@ -6,7 +6,7 @@ Gnuk Token is supported as well.
You need to install:
$ sudo apt-get install python3-pytest python3-usb
$ sudo apt install python3-pytest python3-usb python3-cffi
Please run test by typing:

12
tests/card_const.py Normal file
View File

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

View File

@@ -1,7 +1,7 @@
"""
card_reader.py - a library for smartcard reader
Copyright (C) 2016 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
@@ -125,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)
@@ -168,7 +172,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()
@@ -179,9 +183,11 @@ class CardReader(object):
# TPDU reader configuration
self.ns = 0
self.nr = 0
# Set PPS
pps = b"\xFF\x11\x18\xF6"
status, chain, ret_pps = self.ccid_send_data_block(pps)
# For Gemalto's SmartCard Reader(s)
if self.__dev.idVendor == 0x08E6:
# Set PPS
pps = b"\xFF\x11\x18\xF6"
status, chain, ret_pps = self.ccid_send_data_block(pps)
# Set parameters
param = b"\x18\x10\xFF\x75\x00\xFE\x00"
# ^--- This shoud be adapted by ATR string, see update_param_by_atr
@@ -235,16 +241,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()
@@ -275,7 +286,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):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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
View 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

View 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

View 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

View 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

View File

@@ -1,7 +1,7 @@
"""
test_remove_keys_card.py - test removing keys on card
card_test_remove_keys.py - test removing keys on card
Copyright (C) 2016 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.
@@ -22,23 +22,24 @@ 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
KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00"
KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00"
from card_const import *
def test_rsa_import_key_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
class Test_Remove_Keys(object):
def test_rsa_import_key_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_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_import_key_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
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

View 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

52
tests/card_test_x25519.py Normal file
View File

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

View File

@@ -16,3 +16,4 @@ def card():
card.cmd_select_openpgp()
yield card
del card
reader.ccid_power_off()

View File

@@ -0,0 +1,21 @@
PW1_TEST0=b"another user pass phrase"
PW1_TEST1=b"PASSPHRASE SHOULD BE LONG"
PW1_TEST2=b"new user pass phrase"
PW1_TEST3=b"next user pass phrase"
PW1_TEST4=b"another user pass phrase"
PW3_TEST0=b"admin pass phrase"
PW3_TEST1=b"another admin pass phrase"
RESETCODE_TEST=b"example reset code 000"
PLAIN_TEXT0=b"This is a test message."
PLAIN_TEXT1=b"RSA decryption is as easy as pie."
PLAIN_TEXT2=b"This is another test message.\nMultiple lines.\n"
KDF_FULL=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\xC5\x1F\xB7\xF9\xEE\xF3\xD3\xE8\x85\x08\x75\x1A\x2A\x70\xC0\x7C\xB1\x81\x86\x08\xE6\xB2\x4E\x0C\xEE\x92\xAB\x93\x87\x20\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D\x88\x20\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03"
KDF_FULL_HASH_PW1=b"\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D"
KDF_FULL_HASH_PW3=b"\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03"
KDF_SINGLE=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\x69\x9E\xDA\xAD\x5A\x72\x5F\x4C\x87\x20\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07\x88\x20\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB"
KDF_SINGLE_HASH_PW1=b"\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07"
KDF_SINGLE_HASH_PW3=b"\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB"

108
tests/func_pso_auth.py Normal file
View File

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

1
tests/kdf_calc.py Symbolic link
View File

@@ -0,0 +1 @@
../tool/kdf_calc.py

View File

@@ -1,7 +1,7 @@
"""
openpgp_card.py - a library for OpenPGP card
Copyright (C) 2011, 2012, 2013, 2015, 2016
Copyright (C) 2011, 2012, 2013, 2015, 2016, 2018, 2019
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -21,7 +21,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 struct import pack
from struct import pack, unpack
from kdf_calc import kdf_calc
def iso7816_compose(ins, p1, p2, data, cls=0x00, le=None):
data_len = len(data)
@@ -54,6 +55,85 @@ class OpenPGP_Card(object):
"""
self.__reader = reader
self.__kdf_iters = None
self.__kdf_salt_user = None
self.__kdf_salt_reset = None
self.__kdf_salt_admin = None
self.is_gnuk = (reader.get_string(2) == "Gnuk Token")
self.is_emulated_gnuk = (reader.get_string(3)[-8:] == "EMULATED")
def configure_with_kdf(self):
kdf_data = self.cmd_get_data(0x00, 0xf9)
if kdf_data != b"":
algo, subalgo, iters, salt_user, salt_reset, salt_admin, hash_user, hash_admin = parse_kdf_data(kdf_data)
self.__kdf_iters = iters
self.__kdf_salt_user = salt_user
self.__kdf_salt_reset = salt_reset
self.__kdf_salt_admin = salt_admin
else:
self.__kdf_iters = None
self.__kdf_salt_user = None
self.__kdf_salt_reset = None
self.__kdf_salt_admin = None
# Higher layer VERIFY possibly using KDF Data Object
def verify(self, who, passwd):
if self.__kdf_iters:
salt = self.__kdf_salt_user
if who == 3 and self.__kdf_salt_admin:
salt = self.__kdf_salt_admin
pw_hash = kdf_calc(passwd, salt, self.__kdf_iters)
return self.cmd_verify(who, pw_hash)
else:
return self.cmd_verify(who, passwd)
# Higher layer CHANGE_PASSWD possibly using KDF Data Object
def change_passwd(self, who, passwd_old, passwd_new):
if self.__kdf_iters:
salt = self.__kdf_salt_user
if who == 3 and self.__kdf_salt_admin:
salt = self.__kdf_salt_admin
hash_old = kdf_calc(passwd_old, salt, self.__kdf_iters)
if passwd_new:
hash_new = kdf_calc(passwd_new, salt, self.__kdf_iters)
else:
hash_new = b""
return self.cmd_change_reference_data(who, hash_old + hash_new)
else:
if not passwd_new:
passwd_new = b""
return self.cmd_change_reference_data(who, passwd_old + passwd_new)
# Higher layer SETUP_RESET_CODE possibly using KDF Data Object
def setup_reset_code(self, resetcode):
if self.__kdf_iters:
salt = self.__kdf_salt_user
if self.__kdf_salt_reset:
salt = self.__kdf_salt_user
reset_hash = kdf_calc(resetcode, salt, self.__kdf_iters)
return self.cmd_put_data(0x00, 0xd3, reset_hash)
else:
return self.cmd_put_data(0x00, 0xd3, resetcode)
# Higher layer reset passwd possibly using KDF Data Object
def reset_passwd_by_resetcode(self, resetcode, pw1):
if self.__kdf_iters:
salt = self.__kdf_salt_user
if self.__kdf_salt_reset:
salt = self.__kdf_salt_user
reset_hash = kdf_calc(resetcode, salt, self.__kdf_iters)
pw1_hash = kdf_calc(pw1, self.__kdf_salt_user, self.__kdf_iters)
return self.cmd_reset_retry_counter(0, 0x81, reset_hash + pw1_hash)
else:
return self.cmd_reset_retry_counter(0, 0x81, resetcode + pw1)
# Higher layer reset passwd possibly using KDF Data Object
def reset_passwd_by_admin(self, pw1):
if self.__kdf_iters:
pw1_hash = kdf_calc(pw1, self.__kdf_salt_user, self.__kdf_iters)
return self.cmd_reset_retry_counter(2, 0x81, pw1_hash)
else:
return self.cmd_reset_retry_counter(2, 0x81, pw1)
def cmd_get_response(self, expected_len):
result = b""
@@ -260,16 +340,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:
@@ -280,10 +364,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:]
@@ -336,3 +419,48 @@ class OpenPGP_Card(object):
raise ValueError(sw)
if not (sw[0] == 0x90 and sw[1] == 0x00):
raise ValueError("%02x%02x" % (sw[0], sw[1]))
def parse_kdf_data(kdf_data):
if len(kdf_data) == 90:
single_salt = True
elif len(kdf_data) == 110:
single_salt = False
else:
raise ValueError("length does not much", kdf_data)
if kdf_data[0:2] != b'\x81\x01':
raise ValueError("data does not much")
algo = kdf_data[2]
if kdf_data[3:5] != b'\x82\x01':
raise ValueError("data does not much")
subalgo = kdf_data[5]
if kdf_data[6:8] != b'\x83\x04':
raise ValueError("data does not much")
iters = unpack(">I", kdf_data[8:12])[0]
if kdf_data[12:14] != b'\x84\x08':
raise ValueError("data does not much")
salt = kdf_data[14:22]
if single_salt:
salt_reset = None
salt_admin = None
if kdf_data[22:24] != b'\x87\x20':
raise ValueError("data does not much")
hash_user = kdf_data[24:56]
if kdf_data[56:58] != b'\x88\x20':
raise ValueError("data does not much")
hash_admin = kdf_data[58:90]
else:
if kdf_data[22:24] != b'\x85\x08':
raise ValueError("data does not much")
salt_reset = kdf_data[24:32]
if kdf_data[32:34] != b'\x86\x08':
raise ValueError("data does not much")
salt_admin = kdf_data[34:42]
if kdf_data[42:44] != b'\x87\x20':
raise ValueError("data does not much")
hash_user = kdf_data[44:76]
if kdf_data[76:78] != b'\x88\x20':
raise ValueError("data does not much")
hash_admin = kdf_data[78:110]
return ( algo, subalgo, iters, salt, salt_reset, salt_admin,
hash_user, hash_admin )

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

@@ -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)

View File

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

6
tests/skip_if_gnuk.py Normal file
View File

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

View File

@@ -1,7 +1,7 @@
"""
test_empty_card.py - test empty card
Copyright (C) 2016 g10 Code GmbH
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.
@@ -24,13 +24,11 @@ from binascii import hexlify
from re import match, DOTALL
from struct import pack
from util import *
from card_const import *
import pytest
EMPTY_60=bytes(60)
FACTORY_PASSPHRASE_PW1=b"123456"
FACTORY_PASSPHRASE_PW3=b"12345678"
def test_login(card):
login = get_data_object(card, 0x5e)
assert check_null(login)
@@ -52,12 +50,21 @@ def test_sex(card):
def test_name_lang_sex(card):
name = b""
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
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)
@@ -142,11 +149,12 @@ 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)
assert a == None or match(b'[\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00', a)
assert a == None or match(b'[\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00', a)
def test_algorithm_attributes_1(card):
a = get_data_object(card, 0xc1)

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,29 @@
"""
test_005_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 skip_if_emulation import *
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less import *
from card_test_personalize_reset import *
from card_test_remove_keys import *
from card_test_reset_pw3 import *

9
tests/test_006_pso.py Normal file
View File

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

25
tests/test_009_keygen.py Normal file
View File

@@ -0,0 +1,25 @@
"""
test_005_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 skip_if_emulation import *
from card_test_keygen import *
from card_test_remove_keys import *

View File

@@ -0,0 +1,29 @@
"""
test_007_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 skip_gnuk_only_tests import *
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 *

View File

@@ -0,0 +1,29 @@
"""
test_012_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 skip_gnuk_only_tests import *
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 *

View File

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

View File

@@ -0,0 +1,40 @@
"""
test_017_kdf_none.py - test KDF data object
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 skip_gnuk_only_tests import *
from card_const import *
from constants_for_test import *
def test_verify_pw3(card):
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
assert v
def test_kdf_put_none(card):
r = card.cmd_put_data(0x00, 0xf9, b"")
if r:
card.configure_with_kdf()
assert r
def test_verify_pw3_1(card):
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
assert v

View File

@@ -1,290 +0,0 @@
"""
test_personalize_card.py - test personalizing card
Copyright (C) 2016 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
FACTORY_PASSPHRASE_PW1=b"123456"
FACTORY_PASSPHRASE_PW3=b"12345678"
PW1_TEST0=b"another user pass phrase"
PW1_TEST1=b"PASSPHRASE SHOULD BE LONG"
PW1_TEST2=b"new user pass phrase"
PW1_TEST3=b"next user pass phrase"
PW1_TEST4=b"another user pass phrase"
PW3_TEST0=b"admin pass phrase"
PW3_TEST1=b"another admin pass phrase"
RESETCODE_TEST=b"example reset code 000"
def test_setup_pw3_0(card):
r = card.cmd_change_reference_data(3, FACTORY_PASSPHRASE_PW3 + PW3_TEST0)
assert r
def test_verify_pw3_0(card):
v = card.cmd_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.cmd_change_reference_data(1, FACTORY_PASSPHRASE_PW1 + PW1_TEST0)
assert r
def test_verify_pw1_0(card):
v = card.cmd_verify(1, PW1_TEST0)
assert v
def test_verify_pw1_0_2(card):
v = card.cmd_verify(2, PW1_TEST0)
assert v
def test_setup_pw1_1(card):
r = card.cmd_change_reference_data(1, PW1_TEST0 + PW1_TEST1)
assert r
def test_verify_pw1_1(card):
v = card.cmd_verify(1, PW1_TEST1)
assert v
def test_verify_pw1_1_2(card):
v = card.cmd_verify(2, PW1_TEST1)
assert v
def test_setup_reset_code(card):
r = card.cmd_put_data(0x00, 0xd3, RESETCODE_TEST)
assert r
def test_reset_code(card):
r = card.cmd_reset_retry_counter(0, 0x81, RESETCODE_TEST + PW1_TEST2)
assert r
def test_verify_pw1_2(card):
v = card.cmd_verify(1, PW1_TEST2)
assert v
def test_verify_pw1_2_2(card):
v = card.cmd_verify(2, PW1_TEST2)
assert v
def test_setup_pw3_1(card):
r = card.cmd_change_reference_data(3, PW3_TEST0 + PW3_TEST1)
assert r
def test_verify_pw3_1(card):
v = card.cmd_verify(3, PW3_TEST1)
assert v
def test_reset_userpass_admin(card):
r = card.cmd_reset_retry_counter(2, 0x81, PW1_TEST3)
assert r
def test_verify_pw1_3(card):
v = card.cmd_verify(1, PW1_TEST3)
assert v
def test_verify_pw1_3_2(card):
v = card.cmd_verify(2, PW1_TEST3)
assert v
def test_setup_pw1_4(card):
r = card.cmd_change_reference_data(1, PW1_TEST3 + PW1_TEST4)
assert r
def test_verify_pw1_4(card):
v = card.cmd_verify(1, PW1_TEST4)
assert v
def test_verify_pw1_4_2(card):
v = card.cmd_verify(2, PW1_TEST4)
assert v
def test_setup_pw3_2(card):
r = card.cmd_change_reference_data(3, PW3_TEST1 + PW3_TEST0)
assert r
def test_verify_pw3_2(card):
v = card.cmd_verify(3, PW3_TEST0)
assert v
PLAIN_TEXT0=b"This is a test message."
PLAIN_TEXT1=b"RSA decryption is as easy as pie."
PLAIN_TEXT2=b"This is another test message.\nMultiple lines.\n"
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

View File

@@ -1,91 +0,0 @@
"""
test_personalize_reset_card.py - test resetting personalization of card
Copyright (C) 2016 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
FACTORY_PASSPHRASE_PW1=b"123456"
FACTORY_PASSPHRASE_PW3=b"12345678"
PW1_TEST0=b"another user pass phrase"
PW1_TEST1=b"PASSPHRASE SHOULD BE LONG"
PW1_TEST2=b"new user pass phrase"
PW1_TEST3=b"next user pass phrase"
PW1_TEST4=b"another user pass phrase"
PW3_TEST0=b"admin pass phrase"
PW3_TEST1=b"another admin pass phrase"
RESETCODE_TEST=b"example reset code 000"
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.cmd_change_reference_data(3, PW3_TEST0 + FACTORY_PASSPHRASE_PW3)
assert r
def test_verify_pw3_0(card):
v = card.cmd_verify(3, FACTORY_PASSPHRASE_PW3)
assert v
def test_setup_pw1_0(card):
r = card.cmd_change_reference_data(1, PW1_TEST4 + FACTORY_PASSPHRASE_PW1)
assert r
def test_verify_pw1_0(card):
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
assert v
def test_verify_pw1_0_2(card):
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
assert v
def test_setup_reset_code(card):
r = card.cmd_put_data(0x00, 0xd3, b"")
assert r

View File

@@ -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:

View File

@@ -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)

Some files were not shown because too many files have changed in this diff Show More