Compare commits

...

220 Commits

Author SHA1 Message Date
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
NIIBE Yutaka
ad704edc4e Version 1.2.6.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-10-11 16:50:13 +09:00
NIIBE Yutaka
97a1870e6e Fix test/*. 2017-10-11 16:08:17 +09:00
NIIBE Yutaka
f72e132967 Fix configure. 2017-10-11 11:24:12 +09:00
NIIBE Yutaka
a22b695f96 No --vidpid for GNU/Linux. 2017-10-10 21:06:42 +09:00
NIIBE Yutaka
0c901d8052 Support --debug option for GNU/Linux emulation. 2017-10-10 14:36:34 +09:00
NIIBE Yutaka
a1b8e7f40c STM8S Discovery kit is supported again. 2017-10-06 17:19:55 +09:00
NIIBE Yutaka
dccda32b93 Fix for 64KB STM32F103. 2017-10-06 17:04:45 +09:00
NIIBE Yutaka
75049ce949 Fix linker script. 2017-10-06 17:00:00 +09:00
NIIBE Yutaka
be80a3ef2f For emulation, support --vidpid at runtime. 2017-10-06 10:20:54 +09:00
NIIBE Yutaka
94424e85c3 Fix stack size for ARM. 2017-10-05 17:07:06 +09:00
NIIBE Yutaka
43980d1c81 RSA in a single step. 2017-10-05 17:06:50 +09:00
NIIBE Yutaka
183cec8a04 Emulation tool added. 2017-10-05 13:53:48 +09:00
NIIBE Yutaka
7bae61f300 Fix bignum for 64-bit machine. 2017-10-05 13:45:24 +09:00
NIIBE Yutaka
7e4ee2b361 Serial string for GNU/Linux emulation. 2017-10-04 18:54:16 +09:00
NIIBE Yutaka
30fde2a0f0 Fix bignum for 64-bit machine. 2017-10-04 17:08:42 +09:00
NIIBE Yutaka
eee8d046a9 Fix gnuk_malloc for 64-bit. 2017-10-04 12:38:37 +09:00
NIIBE Yutaka
550010f25f Tweak the size of stack of openpgp-card thread. 2017-10-04 10:45:39 +09:00
NIIBE Yutaka
3adbe30c4d RSA key generation in two steps. 2017-10-04 09:44:19 +09:00
NIIBE Yutaka
d9ec8778fc Don't use malloc if not needed. 2017-10-03 16:12:41 +09:00
NIIBE Yutaka
eff0c7077d Don't provide stdlib.h, but provide gnuk-malloc.h. 2017-10-03 16:04:43 +09:00
NIIBE Yutaka
289d3db8c4 generate flash.data. 2017-10-03 13:50:51 +09:00
NIIBE Yutaka
7c5eb7efd2 Fix non-use of stdlib.h. 2017-10-03 13:27:12 +09:00
NIIBE Yutaka
6f1fbdd82d flash memory handling change to support GNU/Linux. 2017-10-03 11:50:48 +09:00
NIIBE Yutaka
cbedf98a52 Not for GNU/Linux. 2017-10-02 16:45:08 +09:00
NIIBE Yutaka
15689b5b86 FLASH_UPGRADE_SUPPORT is not relevant to GNU/Linux. 2017-10-02 16:24:56 +09:00
NIIBE Yutaka
8170b60ee2 Fix for main.c. 2017-10-02 16:08:20 +09:00
NIIBE Yutaka
ca7f4c8758 More USB fix for GNU/Linux. 2017-10-02 15:29:45 +09:00
NIIBE Yutaka
0b4099d6d1 mpi_montsqr fix for GNU/Linux. 2017-10-02 15:27:27 +09:00
NIIBE Yutaka
65fee7eb2a Fix flash.c for GNU/Linux emulation. 2017-09-30 21:03:17 +09:00
NIIBE Yutaka
0c229f5712 Small USB clean up. 2017-09-30 20:51:21 +09:00
NIIBE Yutaka
5948f6ec50 Revert part of simplification. 2017-09-30 20:20:36 +09:00
NIIBE Yutaka
7b1ea00307 More fix for USB. 2017-09-29 21:06:15 +09:00
NIIBE Yutaka
277be86958 Fix USB code for USBIP on GNU/Linux. 2017-09-29 19:23:39 +09:00
NIIBE Yutaka
a6b90ad648 Fix for FLASH_UPGRADE_SUPPORT. 2017-09-29 16:58:59 +09:00
NIIBE Yutaka
547e263d6b Fix for 64-bit machine (emulation). 2017-09-29 14:15:48 +09:00
NIIBE Yutaka
7004453669 Stack definition change. 2017-09-29 13:18:49 +09:00
NIIBE Yutaka
81b18f2db4 More for GNU/Linux emulation. 2017-09-28 16:44:54 +09:00
NIIBE Yutaka
86715dd4fe More fixes. 2017-09-28 15:36:59 +09:00
NIIBE Yutaka
62f27f319c Fix for GNU/Linux. 2017-09-28 15:25:06 +09:00
NIIBE Yutaka
7345f3c241 Rename flash functions. 2017-09-28 15:10:20 +09:00
NIIBE Yutaka
f4b9073b11 stdlib fixes. 2017-09-28 15:09:21 +09:00
NIIBE Yutaka
6678ac28c2 GNU/Linux emulation is done by Chopstx. 2017-09-28 11:04:28 +09:00
NIIBE Yutaka
83414a747a Version 1.2.5. 2017-08-11 22:12:09 +09:00
NIIBE Yutaka
8a615d087b Update .gitignore. 2017-08-11 22:11:49 +09:00
NIIBE Yutaka
967b949967 Tweak process size of gpg. 2017-08-11 22:00:01 +09:00
NIIBE Yutaka
11afbdde14 src/config.mk generation. 2017-08-11 21:06:59 +09:00
NIIBE Yutaka
328766af12 Merge branch 'master' of git.gniibe.org:gnuk/gnuk 2017-08-04 08:33:46 +09:00
NIIBE Yutaka
2b340ee1c5 Fix factory-reset for admin-less mode.
Reported-by: Stanislas Bach <sbach@0g.re>
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-08-04 08:32:39 +09:00
NIIBE Yutaka
86e6adf47e Fix factory-reset for admin-less mode.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-08-03 21:35:20 +09:00
Jeremy Drake
eea011fe70 Allow compile-time override of detected flash size.
On the STM32F103C8, as used in the "blue pill" boards, it has been
determined that, despite these only officially having 64KiB flash, it is
possible to actually use 128KiB of flash.

This commit allows for a preprocessor define
STM32F103_OVERRIDE_FLASH_SIZE which, when set, is used as the size of
flash in KiB instead of reading it from the FLASH_SIZE_REG.
2017-08-03 21:20:47 +09:00
Jeremy Drake
e736227de7 Erase CERTDO on terminate.
When both certdo and lifecycle support are enabled, flash_terminate
neglected to erase the certdo pages.  It now does so.
2017-08-02 11:13:02 +09:00
NIIBE Yutaka
22156ea7f9 Fix factory-reset. 2017-08-01 13:30:02 +09:00
Anthony Romano
db45e62ebe configure: sanitize for shellcheck
Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-20 12:25:24 +09:00
Anthony Romano
3270740631 docker: source checking container
Includes shellcheck and scan-build

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-20 12:24:44 +09:00
NIIBE Yutaka
e4e72a29ae Initialize TMP to avoid confusion by static analysis.
--

The computation using TMP is keeping it constant-time only, but
it is better not to confuse static analysis.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-07-19 11:55:20 +09:00
NIIBE Yutaka
25d3f021c1 Support no git situation.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-07-19 11:25:38 +09:00
NIIBE Yutaka
ae76d66d53 Fix accessing garbage on error path.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Reported-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-19 10:48:16 +09:00
NIIBE Yutaka
10c5010141 Git is assumed for the source with .git.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-07-18 14:12:20 +09:00
Anthony Romano
d12483c3c9 Support building with docker.
Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:38:46 +09:00
Anthony Romano
67acb670d1 call fatal if mem_head size is corrupted.
Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:31:06 +09:00
Anthony Romano
a44244b27e avoid null dereference when openpgp algo goes from !rsa2k to rsa2k.
Detected with scan-build.

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:27:12 +09:00
Anthony Romano
2622840e27 remove unused calculations from mod_reduce.
Detected with scan-build.

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:19:42 +09:00
Anthony Romano
a51ac8593b call-rsa: free modulus buffers on error paths.
* MPI_CHK jumps to cleanup on ret != 0, so p_q_modulus is never freed if
  rsa_gen_key fails (detected via scan-build).
* modulus_calc never freed its modulus buffer on error.

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:15:42 +09:00
NIIBE Yutaka
de81caba3e Update Chopstx.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-07-18 12:58:23 +09:00
NIIBE Yutaka
fa69a85826 Version 1.2.4.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-12 17:22:20 +09:00
NIIBE Yutaka
5c3c3e3001 usbip list -r 127.0.0.1 now works.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-12 14:13:53 +09:00
NIIBE Yutaka
6dcb4dd027 Add usb-emu.c.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-02 15:05:15 +09:00
NIIBE Yutaka
fa08f44cac Fix old documentation (note) for firmware update.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-01 14:58:15 +09:00
NIIBE Yutaka
4c2294ea6c Portability change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 16:14:30 +09:00
NIIBE Yutaka
86eaa26d32 New: src/mcu-stm32f103.c.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 15:49:38 +09:00
NIIBE Yutaka
9e52789203 Fix long standing buf of digital signature counter.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 14:54:15 +09:00
NIIBE Yutaka
702bc8cbde Move data objects at the end of flash.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-27 15:23:25 +09:00
NIIBE Yutaka
2cfce76d91 [SECURITY] Flash memory usage change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-27 14:36:32 +09:00
NIIBE Yutaka
207652246a emulation: USB device emulation by USBIP protocol. 2017-04-18 15:45:25 +09:00
NIIBE Yutaka
32779b6f96 Version 1.2.3. 2017-02-02 16:33:30 +09:00
NIIBE Yutaka
55c1015faa Increase CCID thread stack size by 0x20 for newer GCC. 2017-02-02 14:11:11 +09:00
NIIBE Yutaka
0932465f0b Update Chopstx to 1.3. 2017-02-02 13:07:35 +09:00
NIIBE Yutaka
4417799a51 Update README 2017-02-01 17:16:54 +09:00
Szczepan Zalega
b424cecf1e Regnual update tool: do not allow other than binary formats (upgrade_by_passwd)
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2017-02-01 15:40:56 +09:00
NIIBE Yutaka
7ef417ae36 tool: Improve tool/*.py.
--

Szczepan Zalega's idea of using the file GNUK_USB_DEVICE_ID would
good, but not merged yet.  Because it makes difficult to distribute
the scripts.  We need to consider installing tools and the file
like GNUK_USB_DEVICE_ID altogether.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-02-01 12:34:35 +09:00
NIIBE Yutaka
d4469c24ec fix NIST P-256 / secp256k1 key generation. 2016-10-21 15:30:07 +09:00
101 changed files with 4777 additions and 1192 deletions

6
.gitignore vendored
View File

@@ -1,16 +1,20 @@
*.lst
*.o
*.pyc
regnual/regnual-no-vidpid.elf
src/.dep
src/Makefile
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

26
AUTHORS
View File

@@ -1,3 +1,20 @@
Aurelien Jarno:
Modified:
src/Makefile
src/configure
src/main.c
src/stack-def.h
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.
@@ -48,3 +65,12 @@ NIIBE Yutaka:
src/usb_lld.h
*
and others.
Peter Lebbing:
Modified:
src/config.h.in
src/configure
src/main.c
src/Makefile
Wrote:
src/stdaln-sys.ld.in

816
ChangeLog
View File

@@ -1,3 +1,819 @@
2019-03-04 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.14.
* chopstx: Update to 1.14.
* tool/gnuk_token.py: Add 1209:2440.
2019-02-24 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_thread): Clean up the ack button state
at reset (by SET_INTERFACE).
* tool/gnuk_token.py (gnuk_token.__init__): Add back
setAltInterface to issue SET_INTERFACE control transfer.
2019-02-22 NIIBE Yutaka <gniibe@fsij.org>
* tool/gnuk_get_random.py: New.
* src/openpgp.c (cmd_external_authenticate): move
ACKBTN_SUPPORT to...
(cmd_get_challenge): ... here.
* src/gnuk.h (EV_*): Change the values.
* src/usb-ccid.c (GPG_ACK_TIMEOUT): New.
(ccid_thread): Implement timout for the user interaction.
2019-02-21 NIIBE Yutaka <gniibe@fsij.org>
* GNUK_USB_DEVICE_ID: Add 1209:2440.
2018-12-26 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.13.
2018-12-22 Peter Lebbing <peter@digitalbrains.com>
* src/main.c (device_initialize_once): Fill the stack address and
reset vector of Gnuk application (was the one of old SYS).
Reset the board after updating the first five pages of flash.
2018-12-21 Peter Lebbing <peter@digitalbrains.com>
* src/main.c [DFU_SUPPORT] (flash_write_any): New.
(device_initialize_once): Overwrite DFU bootloader by SYS.
(main): Use SYS at ORIGIN_REAL.
* src/stdaln-sys.ld.in: New.
* src/Makefile [USE_DFU] (OBJS_ADD): Add standalone SYS object.
Add rules for stdaln-sys-bin.o and src/stdaln-sys.ld.
* src/configure: Generate stdaln-sys.ld.
[MAPLE_MINI]: Tweak ORIGIN and FLASH_SIZE.
(ORIGIN_DEFINE, ORIGIN_REAL_DEFINE): New macros.
(USE_DFU): New make variable.
* src/config.h.in (ORIGIN_DEFINE, ORIGIN_REAL_DEFINE): New.
2018-12-20 NIIBE Yutaka <gniibe@fsij.org>
* chopstx: Update to 1.13.
2018-12-07 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (EV_EXEC_ACK_REQUIRED): Have precedence
than EV_EXEC_FINISHED.
2018-12-06 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_thread): Priority of handling
EV_TX_FINISHED is most important. Don't handle
Ack button event when c->tx_busy = 1.
2018-12-05 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_external_authenticate): Support
ACK button for firmware update.
2018-12-04 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_data_copy): Fix for NR_DO_UIF_SIG.
2018-11-25 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.12.
2018-11-21 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_thread): Fix a race condition sending
result APDU by ack button, time out, sending time extension block
again while tx_busy=1.
2018-11-17 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (device_initialize_once): Depends on MHZ to
distinguish GD32F103.
* src/openpgp-do.c (do_openpgpcard_aid): Ditto.
2018-11-12 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.11.
* chopstx: Update to 1.12.
* src/configure (ackbtn_support): Always yes.
* src/usb-ccid.c: Fix comma separator.
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
* tool/kdf_calc.py (kdf_calc): Use libgcrypt.so.20.
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_pso, cmd_internal_authenticate): Use
ccid_comm.
* src/usb-ccid.c (struct ccid): New field tx_busy.
(ccid_error, ccid_power_on, ccid_send_status, ccid_power_off)
(ccid_send_data_block_internal, ccid_send_data_block_0x9000)
(ccid_send_data_block_gr, ccid_send_params): Set c->tx_busy.
(ccid_state_p): Remove.
(ccid_get_ccid_state): New.
(ccid_thread): Only handle EV_TX_FINISHED event when c->tx_busy.
* src/usb_ctrl.c (usb_setup, usb_ctrl_write_finish): Use
ccid_get_ccid_state.
* src/main.c (display_status_code): Likewise.
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_handle_data): Set c->state for pinpad input.
(ccid_send_data_block_internal): Fix the case of len == 0.
* src/main.c (display_status_code): There is
no case where ccid_state == CCID_STATE_RECEIVE.
* src/gnuk.h (CCID_STATE_RECEIVE): Remove.
(CCID_STATE_SEND): Remove.
2018-10-12 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_thread): Notify host about ack button.
2018-10-02 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_0): Increase.
* chopstx: Update to 1.11.
2018-10-01 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (EV_EXEC_ACK_REQUIRED): New.
(EV_EXEC_FINISHED_ACK): Remove.
(CCID_STATE_CONFIRM_ACK): Remove.
(CCID_STATE_ACK_REQUIRED_0, CCID_STATE_ACK_REQUIRED_1): New.
* src/openpgp.c (cmd_pso): Send EV_EXEC_ACK_REQUIRED, if needed.
(cmd_internal_authenticate): Likewise.
(process_command_apdu): No return value.
(openpgp_card_thread): Always send EV_EXEC_FINISHED.
* src/usb-ccid.c (ccid_send_data_block_time_extension): Follow the
change of state.
(ccid_handle_data, ccid_handle_timeout): Likewise.
(ccid_thread): Handle EV_EXEC_ACK_REQUIRED.
Change for LED blink.
* src/main.c (main): LED blink during waiting ACK.
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (NR_DO_UIF_SIG, NR_DO_UIF_DEC, NR_DO_UIF_AUT): New.
* src/openpgp-do.c (rw_uif) [ACKBTN_SUPPORT]: New.
(GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
(feature_mngmnt) [ACKBTN_SUPPORT]: New.
(cmp_app_data, cmp_discretionary): Add ACKBTN_SUPPORT.
(gpg_do_table): Add for GPG_DO_UIF_SIG, GPG_DO_UIF_DEC,
GPG_DO_UIF_AUT, and GPG_DO_FEATURE_MNGMNT.
(gpg_do_get_uif) [ACKBTN_SUPPORT]: New.
(gpg_data_scan): Handle uif_flags.
* src/openpgp.c (process_command_apdu) [ACKBTN_SUPPORT]: Add user
interaction handling.
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (LED_WAIT_FOR_BUTTON): New.
* src/main.c (main): Blink rapidly when asking ACK.
* src/usb-ccid.c (ccid_thread): Use LED_WAIT_FOR_BUTTON.
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
* src/config.h.in: Add @ACKBTN_DEFINE@.
* src/configure: Add ACKBTN_SUPPORT.
* src/gnuk.h (EV_EXEC_FINISHED_ACK): New.
(CCID_STATE_CONFIRM_ACK): New.
* src/openpgp.c (process_command_apdu): Change for cmd_pso, and
cmd_internal_authenticate.
* src/usb-ccid.c (ccid_send_data_block_time_extension): Report
time extension differently when waiting ack button.
(ccid_handle_data): Support case of CCID_STATE_CONFIRM_ACK.
(ccid_handle_timeout): Likewise.
(ack_intr) [ACKBTN_SUPPORT]: New.
(ccid_thread) [ACKBTN_SUPPORT]: Add ack button handling.
2018-09-26 NIIBE Yutaka <gniibe@fsij.org>
* chopstx: Update.
* src/usb-ccid.c (usb_event_handle): Fix for chopstx_intr_done.
* src/pin-cir.c (tim_main, ext_main): Likewise.
* src/configure (FST_01SZ): Set MHZ=96.
2018-07-04 Szczepan Zalega <szczepan@nitrokey.com>
* tool/upgrade_by_passwd.py: Catch exception, when no KDF data is
found.
Output 'second' for 1 second.
2018-05-10 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.10.
* src/Makefile (build/gnuk.elf): New target.
(build/gnuk-vidpid.elf): Remove.
* chopstx: Update to 1.9.
2018-04-26 NIIBE Yutaka <gniibe@fsij.org>
* src/usb_ctrl.c (usb_device_reset): Don't stop the endpoints.
* src/configure (MHZ, def_mhz): New.
2018-04-05 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.9.
* tests: Add test cases for admin-less mode.
* src/openpgp.c (cmd_change_password): Care admin-less mode.
2018-04-04 NIIBE Yutaka <gniibe@fsij.org>
* tests: Add more tests, key generation and KDF support.
* src/openpgp.c (cmd_reset_user_password): Check length of
new passphrase.
* src/openpgp-do.c (proc_resetting_code): Support removal.
(gpg_do_kdf_check): Fix for the case of resetting PW3.
* tests/test_004_reset_pw3.py: New.
2018-04-03 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Clear all auth state.
* tool/upgrade_by_passwd.py (main): Fix for byte compare.
* tool/gnuk_remove_keys_libusb.py (main): Likewise.
2018-04-02 NIIBE Yutaka <gniibe@fsij.org>
* tool/gnuk_token.py (parse_kdf_data): New.
* tool/kdf_calc.py: New.
* tool/gnuk_remove_keys_libusb.py (main): Support KDF auth.
* tool/upgrade_by_passwd.py (main): Likewise.
2018-03-30 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Support single-salt KDF.
(gpg_do_get_initial_pw_setting): Likewise.
(gpg_do_kdf_check): Likewise.
2018-03-22 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Do format validation earlier.
2018-03-13 NIIBE Yutaka <gniibe@fsij.org>
* src/flash.c [FLASH_UPGRADE_SUPPORT] (flash_terminate): Erase
the page for upgrade public keys.
2018-02-12 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Return 0 when NULL.
2018-01-23 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.8.
* src/Makefile (build/gnuk-vidpid.elf): Supply FILE here.
* src/configure (output_vendor_product_serial_strings): For
generating put-vid-pid-ver.sh, don't set FILE.
* regnual/regnual.c (regnual_device_desc): Make this array as a
template.
* regnual/Makefile (regnual.elf): Substitute VID:PID.
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (USER_PASSWD_MINLEN): New.
(cmd_change_password): Check passphrase length.
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_change_password): Remove access to private
key with BY_ADMIN when it's becoming admin-less mode.
2018-01-19 NIIBE Yutaka <gniibe@fsij.org>
* src/binary-edit.sh: Copied from NeuG 1.0.8. Exclude FILE.
* src/configure (output_vid_pid_version): Generate a shell script.
* src/Makefile (build/gnuk-vidpid.elf): New target.
* src/usb_desc.c (device_desc): Make this array as a template.
* chopstx: Update to 1.8.
2018-01-18 NIIBE Yutaka <gniibe@fsij.org>
* src/neug.c: Update from NeuG.
2018-01-09 NIIBE Yutaka <gniibe@fsij.org>
* tests/card_reader.py (CardReader.ccid_power_on): Fix for
other card readers for Gemalto's.
2017-12-19 NIIBE Yutaka <gniibe@fsij.org>
* chopstx: Update to 1.7.
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_change_password): Bug fix for admin-less
mode.
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.7.
2017-11-24 NIIBE Yutaka <gniibe@fsij.org>
* regnual/regnual.c (calc_crc32): Enable CRC module fix.
* chopstx: Update to 1.6.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_0): Decrease.
* src/main.c (emit_led, display_status_code, main): Use
chopstx_poll instead of eventflag_wait_timeout.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_0): Increase.
* src/main.c (emit_led, display_status_code, main): Use
eventflag_wait_timeout instead of chopstx_usec_wait.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* regnual/regnual.c (calc_crc32): Enable CRC module.
* src/neug.c (crc32_rv_stop): New.
(neug_fini): Call crc32_rv_stop.
* src/main.c (main): Call chopstx_conf_idle.
* src/usb-ccid.c (usb_event_handle): Use 2 for call of
chopstx_conf_idle on suspend. Call random_fini on suspend
to stop ADC module. Call random_init on wakeup.
Sleep a bit to switch main thread.
2017-11-16 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (LED_OFF): New.
* src/usb-ccid.c (usb_event_handle): LED off on sleep.
(ccid_thread): Use constant pointer for chopstx_poll.
(poll_event_intr): Remove.
2017-11-15 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (usb_event_handle): Allow sleep on suspend.
* src/usb_ctrl.c (usb_device_reset): Fix device state.
2017-11-14 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_usb_reset): Remove
(usb_event_handle): Return value change to notify
caller about needs for going out of the loop.
Support USB suspend/resume.
(ccid_thread): Supporting USB suspend, sleep forever with
timeout_p = NULL.
* src/main.c (main): Add USB_DEVICE_STATE_ prefix.
* src/usb_ctrl.c: Likewise.
(usb_device_reset): Don't call ccid_usb_reset.
(usb_set_configuration, usb_set_interface): Likewise.
* src/usb_desc.c (device_desc): bcdUSB = 2.0, supporting
suspend/resume.
2017-11-13 NIIBE Yutaka <gniibe@fsij.org>
* src/usb_ctrl.c: Use new const USB_DEVICE_STATE_*
* src/main.c (main): Likewise.
* src/usb-ccid.c: Likewise.
(INTR_REQ_USB): Remove. Use the definition
in usb-lld.h.
2017-11-08 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_kdf_check): New.
(proc_resetting_code): Use gpg_do_kdf_check.
* src/openpgp.c (cmd_verify, cmd_change_password)
(cmd_reset_user_password): Likewise.
2017-11-07 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (proc_resetting_code): Error when
it's not pass-hash.
* src/openpgp.c (cmd_verify, cmd_change_password)
(cmd_reset_user_password): Avoid authentication error
by old GnuPG which doesn't support KDF.
2017-11-06 NIIBE Yutaka <gniibe@fsij.org>
* tests/test_empty_card.py (test_extended_capabilities): Support
KDF-DO.
* test/features/802_get_data_static.feature: Likewise.
* test/features/402_get_data_static.feature: Likewise.
* test/features/002_get_data_static.feature: Likewise.
2017-11-02 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Only writable when no keys.
(gpg_do_get_initial_pw_setting): New.
(gpg_do_write_prvkey): Use gpg_do_get_initial_pw_setting.
(gpg_do_keygen): Likewise.
(extended_capabilities): Enable KDF-DO available bit.
* src/openpgp.c (cmd_change_password): Use
gpg_do_get_initial_pw_setting.
* src/ac.c (verify_user_0, verify_admin_0): Likewise.
2017-11-01 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (GPG_DO_KDF): New.
(GPG_DO_FEATURE_MNGMNT): New.
(do_tag_to_nr): Support GPG_DO_KDF.
(GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
(rw_kdf): New.
(gpg_do_table): Add an entry for GPG_DO_KDF.
* src/gnuk.h (NR_DO_KDF): New.
2017-10-31 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_keygen): Bug fix for memory alignment.
2017-10-24 NIIBE Yutaka <gniibe@fsij.org>
* tests/card_reader.py (CardReader.ccid_power_on): Setting
PPS only for Gemalto GemPC reader.
2017-10-18 Aurelien Jarno <aurelien@aurel32.net>
* src/gnuk.ld.in: Fix keystore_pool size.
2017-10-12 Aurelien Jarno <aurelien@aurel32.net>
* polarssl/include/polarssl/bn_mul.h (MULADDC_HUIT_DEAD): Rename
from MULADDC_HUIT.
[__ARM_FEATURE_DSP] (MULADDC_1024_CORE, MULADDC_1024_LOOP)
(MULADDC_INIT, MULADDC_CORE, MULADDC_HUIT, MULADDC_STOP): New.
* polarssl/library/bignum.c (mpi_montsqr): Check on
POLARSSL_HAVE_ASM and __arm__.
[__ARM_FEATURE_DSP] (mpi_montsqr): New.
(MAX_WSIZE): New.
(mpi_exp_mod): Use MAX_WSIZE.
* src/Makefile (DEFS): Remove BIGNUM_C_IMPLEMENTATION.
* src/main.c (HEAP_SIZE): Rename from MEMORY_SIZE.
(HEAP_END, HEAP_ALIGNMENT, HEAP_ALIGN): Likewise.
* src/stack-def.h (SIZE_3): Depend on MEMORY_SIZE.
* src/configure: Emit DEFS with MEMORY_SIZE.
2017-10-11 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.6.
* regnual/Makefile (LDSCRIPT): Move after include.
* regnual/types.h: Add uintptr_t.
* test/features/002_get_data_static.feature (data object AID): Fix
for any binary value.
* 402_get_data_static.feature: Likewise.
* 802_get_data_static.feature: Likewise.
2017-10-10 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (main): Support --debug option.
* chopstx: Update to 1.5.
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
* src/configure (flash_override): Fix suggested by Jeremy Drake.
(help): STM8S_DISCOVERY is supported again.
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in (.stacks): Specify NOLOAD type.
* src/configure: Allow not specifying VIDPID.
* src/main.c [GNU_LINUX_EMULATION] (main): Handle "--vidpid"
option to assign vendor ID and product ID of USB.
* src/usb_desc.c [GNU_LINUX_EMULATION] (device_desc): Export.
* GNUK_USB_DEVICE_ID (0000:0000): New.
2017-10-05 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_1, SIZE_3): Tweak the size.
* src/call-rsa.c (rsa_genkey): Single step.
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in single
step, using APDU buffer.
* src/openpgp.c (cmd_pgp_gakp): Supply the APDU as a buffer.
* src/Makefile (install): New target.
* src/configure (prefix. exec_prefix, libexecdir): Add.
* src/main.c [GNU_LINUX_EMULATION] (main): Option handling.
* tool/gnuk-emulation-setup: New.
* polarssl/library/bignum.c (M_LIMBS, limbs_M, MAX_A_LIMBS)
(limbs_MAX_A, mpi_gen_prime): Fix for 64-bit machine.
2017-10-04 NIIBE Yutaka <gniibe@fsij.org>
* src/configure (output_vendor_product_serial_strings): Support
GNU/Linux emulation.
* polarssl/library/bignum.c (mpi_div_mpi): Fix for 64-bit machine.
* src/main.c (gnuk_malloc, gnuk_free): Fix for 64-bit machine.
* src/stack-def.h (SIZE_3): Tweak the size.
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in two
steps.
* src/call-rsa.c (rsa_genkey_start, rsa_genkey_finish): New.
(rsa_genkey): Remove.
2017-10-03 NIIBE Yutaka <gniibe@fsij.org>
* src/call-ec.c (ecc_compute_public): No use of malloc.
* src/call-rsa.c (modulus_calc, rsa_genkey): Likewise.
* src/ecc-edwards.c (eddsa_compute_public_25519): Likewise.
* src/ecc-mont.c (ecdh_compute_public_25519): Likewise.
* src/openpgp-do.c (gpg_do_write_prvkey, gpg_do_chks_prvkey)
(proc_key_import, gpg_do_keygen): Likewise.
* polarssl/library/rsa.c: Don't include stdlib.h.
* src/gnuk-malloc.h: Rename from stdlib.h.
* polarssl/library/bignum.c: Include gnuk-malloc.h.
* src/Makefile (build/flash.data): Generate.
* src/main.c (flash_addr_key_storage_start)
(flash_addr_data_storage_start): New.
(main): Determine flash address.
* src/flash.c (FLASH_ADDR_KEY_STORAGE_START)
(FLASH_ADDR_DATA_STORAGE_START): New.
(flash_do_storage_init, flash_terminate, flash_activate)
(flash_key_storage_init, flash_copying_gc, flash_do_release)
(flash_key_getpage): Use new macros.
2017-10-02 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (device_initialize_once): Not for GNU/Linux.
* src/openpgp.c, src/flash.c: Distinguish FLASH_UPGRADE_SUPPORT.
* src/main.c [GNU_LINUX_EMULATION]: Use emulated_main.
(MEMORY_SIZE, MEMORY_END): Fix for GNU/Linux.
* src/usb-ccid.c (INTR_REQ_USB): Fix for GNU/Linux.
* polarssl/library/bignum.c (mpi_montsqr): Easy C implementation.
2017-09-30 NIIBE Yutaka <gniibe@fsij.org>
* src/flash.c (flash_terminate, flash_activate)
(flash_copying_gc, flash_do_write_internal, flash_do_release)
(flash_key_write, flash_check_all_other_keys_released)
(flash_key_fill_zero_as_released, flash_key_release)
(flash_key_release_page, flash_clear_halfword)
(flash_put_data_internal, flash_put_data, flash_bool_clear)
(flash_bool_write_internal, flash_bool_write)
(flash_enum_write_internal, flash_enum_write)
(flash_cnt123_write_internal, flash_cnt123_increment)
(flash_cnt123_clear, flash_erase_binary, flash_write_binary): Fix
for GNU/Linux.
* src/usb-ccid.c (ccid_tx_done): Rename from EP1_IN_Callback.
(ccid_rx_ready): Rename from EP1_OUT_Callback.
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (epo_init, epi_init, ccid_thread): Simplify.
(EP1_IN_Callback, ccid_prepare_receive, EP1_OUT_Callback)
(usb_rx_ready, ccid_error, ccid_power_on, ccid_send_status)
(ccid_send_data_block_internal, ccid_send_data_block_0x9000)
(ccid_send_data_block_gr, ccid_send_params)
(ccid_notify_slot_change, _write) [GNU_LINUX_EMULATION]: Use
different usb driver API.
* src/usb_ctrl.c (usb_device_reset): Fix control endpoint init.
(gnuk_setup_endpoints_for_interface): Add DEV
argument.
(usb_device_reset) [GNU_LINUX_EMULATION]: Use usb_lld_setup_endp.
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c [FLASH_UPGRADE_SUPPORT] (main): Factor out flash ROM
upgrade support.
(calculate_regnual_entry_address): Likewise.
* src/usb_ctrl.c (usb_setup, download_check_crc32): Likewise.
* src/openpgp.c (modify_binary): Fix for 64-bit machine.
* src/openpgp-do.c (encrypt, decrypt): Likewise.
(gpg_data_scan): Likewise.
(gpg_do_chks_prvkey): Fix error return path.
* src/stack-def.h: New.
* src/gnuk.ld.in: Remove stack definitions.
* src/configure: Remove stack size modifications.
* src/main.c (STACK_MAIN, STACK_PROCESS_1): Use stack-def.h.
* src/usb-ccid.c (STACK_PROCESS_3): Likewise.
* src/usb-msc.c (STACK_PROCESS_5): Likewise.
* src/pin-cir.c (STACK_PROCESS_6, STACK_PROCESS_7): Likewise.
* src/usb_ctrl.c (download_check_crc32): Use chrc32_rv_ functions.
* src/mcu-stm32f103.c (rbit, check_crc32): Remove.
* src/neug.c: Update from NeuG.
* src/neug.h: Ditto.
2017-09-28 NIIBE Yutaka <gniibe@fsij.org>
* src/ec_p256k1.c (coefficient_a): Remove.
* polarssl/library/bignum.c (mpi_fill_pseudo_random): Fix for
64-bit machine.
* src/call-rsa.c (rsa_decrypt): Fix for 64-bit machine.
* src/flash.c (flash_do_storage_init): Rename from flash_init.
(flash_key_storage_init): Rename from flash_init_keys.
* src/openpgp.c (gpg_init): Use new function names.
* src/stdlib.h: Update for GNU/Linux emulation.
* src/Makefile: Support GNU/Linux emulation.
* src/configure: Support GNU/Linux emulation.
* emulation: Remove.
2017-08-11 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.5.
* chopstx: Update to 1.4.
* src/gnuk.ld.in (__process3_stack_size__): Tweak the size.
* src/configure: Define STM32F103_OVERRIDE_FLASH_SIZE_KB for
BULE_PILL.
* src/configure: Let generate src/config.mk.
* src/Makefile: Rename from src/Makefile.in.
* regnual/Makefile: Use src/config.mk.
2017-08-03 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_terminate_df): Fix for admin-less mode.
2017-08-03 Jeremy Drake <jeremydrake+gnuk@eacceleration.com>
* regnual/regnual.c (main): Allow compile time
flash size definition by STM32F103_OVERRIDE_FLASH_SIZE_KB.
2017-08-02 Jeremy Drake <jeremydrake+gnuk@eacceleration.com>
* src/flash.c (flash_terminate): Erase Certificate DO, too.
2017-08-01 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (FILE_CARD_TERMINATED_OPENPGP): Remove.
(cmd_select_file): Don't change file_selection.
2017-07-19 NIIBE Yutaka <gniibe@fsij.org>
* src/mod.c (mod_inv): Clear TMP.
* src/configure (REVISION): Generate even when no git.
* polarssl/library/bignum.c (mpi_exp_mod): Call mpi_grow for X
after the initialization of RR.
2017-07-18 NIIBE Yutaka <gniibe@fsij.org>
* src/configure: Bark when no git available.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* docker: New.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/main.c (MEMORY_SIZE, MEM_HEAD_IS_CORRUPT, MEM_HEAD_CHECK):
New.
(gnuk_malloc, gnuk_free): Add calls to MEM_HEAD_CHECK.
* src/gnuk.h (FATAL_HEAP): New.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/openpgp-do.c (gpg_reset_algo_attr): New.
(rw_algorithm_attr): Use gpg_reset_algo_attr.
Fix null dereference.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/mod.c (mod_reduce): Clean up unused code.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/call-rsa.c (modulus_calc): Free modulus on error.
(rsa_genkey): Remove bogus check, and call chopstx_cleanup_pop
with 1 to release p_q_modulus on error. Assign NULL to clp.arg
when it's goes with no error.
* src/main.c (gnuk_free): Allow NULL.
2017-07-18 NIIBE Yutaka <gniibe@fsij.org>
* Update chopstx (with USBIP emulation).
2017-05-12 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.4.
2017-04-28 NIIBE Yutaka <gniibe@fsij.org>
* src/mcu-stm32f103.c: New.
(check_crc32, sram_address): New.
* src/usb_ctrl.c (download_check_crc32): Use check_crc32 and
sram_address.
* src/openpgp-do.c (gpg_write_digital_signature_counter): Fix
writing lower 10-bit.
2017-04-27 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in (_data_pool): Move to the end.
* src/flash.c (flash_init): Return address of end of data object.
* src/openpgp.c (gpg_init): Get address of end of data object.
* src/openpgp-do.c (gpg_data_scan): Check the end address.
2017-02-02 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.3.
* src/gnuk.ld.in (__process1_stack_size__): Increase by 0x20.
* chopstx: Update to 1.3.
* src/configure: Add BLUE_PILL in the help message.
2017-02-01 NIIBE Yutaka <gniibe@fsij.org>
* README: Update README. Thanks to Paul Fertser.
2017-01-02 Szczepan Zalega <szczepan@nitrokey.com>
* tool/upgrade_by_passwd.py: Add file extention check.
2017-02-01 NIIBE Yutaka <gniibe@fsij.org>
* tool/upgrade_by_passwd.py (main): More verbose messages
suggested by Szczepan Zalega <szczepan@nitrokey.com>.
* tool/gnuk_token.py (USB_PRODUCT_LIST): New.
(gnuk_devices_by_vidpid): Support searching by USB_PRODUCT_LIST.
Thanks to Szczepan Zalega <szczepan@nitrokey.com>.
* tool/usb_strings.py: Use gnuk_token.py.
2016-10-21 Niibe Yutaka <gniibe@fsij.org>
* src/ecc.c (check_secret): Fix condition.
2016-10-15 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.2.

View File

@@ -1,4 +1,6 @@
# VID:PID bcdDev Product_STRING Vendor_STRING
0000:0000 0200 Gnuk Emulation Free Software Initiative of Japan
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
20a0:4211 0200 Nitrokey Start Nitrokey
1209:2440 0200 Gnuk Token GnuPG e.V.
##########<TAB> ##<TAB> ##########<TAB> #################

191
NEWS
View File

@@ -1,5 +1,189 @@
Gnuk NEWS - User visible changes
* 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
** Port to GNU/Linux emulation
We can "run" Gnuk Token on GNU/Linux by emulation through USBIP.
** Upgrade of Chopstx
We use Chopstx 1.5.
* Major changes in Gnuk 1.2.5
Released 2017-08-11, by NIIBE Yutaka
** "factory-reset" fix
Gnuk's behavior was implemented by referring the gpg implementation.
It found that gpg implementation was not good from the viewpoint of
the OpenPGP card specification. GnuPG was fixed to match the OpenPGP
card specification already. Thus, Gnuk is now fixed.
** Upgrade of Chopstx
We use Chopstx 1.4.
* Major changes in Gnuk 1.2.4
Released 2017-05-12, by NIIBE Yutaka
** Flash ROM security fix
The partial content of flash ROM might be exposed when scanning of
data object had a problem. Added boundary check and changed layout of
flash ROM.
* Major changes in Gnuk 1.2.3
Released 2017-02-02, by NIIBE Yutaka
** ECC key generation on the device
Bug fixed.
** Upgrade of Chopstx
We use Chopstx 1.3.
* Major changes in Gnuk 1.2.2
Released 2016-10-15, by NIIBE Yutaka
@@ -736,6 +920,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:

145
README
View File

@@ -1,35 +1,43 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.2
2016-10-15
Version 1.2.14
2019-03-05
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.2, which has major
This is the release of Gnuk, version 1.2.14, 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. Please update your documentation for Gnuk Token, so
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.1 with libgcrypt
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.
It supports new KDF-DO feature. Please note that this is
experimental. To use the feature, you need to use newer GnuPG (2.2.6
or later). You need to prepare the KDF-DO on your token by the
card-edit/kdf-setup command.
With FST-01SZ, experimental ack button support is available for test.
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.
STM32F103 processor (and its compatible).
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.
@@ -47,7 +55,7 @@ FAQ
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, YubiKey, etc.) ?
http://www.g10code.de/p-card.html
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
@@ -77,12 +85,11 @@ A3: Orthodox choice is Olimex STM32-H103.
choice for experiment.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.13 in
experimental.
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.18.
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
without them.
Token without them.
I tested pcscd 1.5.5-4 and libccid 1.3.11-2 which were in Debian
squeeze.
@@ -172,15 +179,6 @@ Original features of Gnuk, tested manually lightly:
* 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
=======
@@ -213,18 +211,21 @@ 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.
Python 2.7 and PyUSB 0.4.3 is assumed. I also use Python 3.5 and
PyUSB 1.0.0.
Souce code
==========
Source 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://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
http://brg.a2hosted.com//oldsite/cryptography_technology/sha/index.php
(was at:
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php)
License
@@ -248,7 +249,7 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 1.1
* chopstx/ -- Chopstx 1.14
We use Chopstx as the kernel for Gnuk.
@@ -297,6 +298,15 @@ Gnuk is distributed with external source code.
POLARSSL_SELF_TEST, and POLARSSL_PADLOCK_C, and only define
POLARSSL_GENPRIME when defined KEYGEN_SUPPORT.
And polarssl/library/bignum.c is modified to work on 64-bit machine.
Aurelien Jarno also modified:
polarssl/include/polarssl/bn_mul.h
polarssl/library/bignum.c
See ChangeLog (and/or history of git) for detail.
USB vendor ID and product ID (USB device ID)
============================================
@@ -361,10 +371,10 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
On Debian we can install the packages of gcc-arm-none-eabi,
gdb-arm-none-eabi and its friends. I'm using:
binutils-arm-none-eabi 2.26-4+8
gcc-arm-none-eabi 15:4.9.3+svn231177-1
gdb-arm-none-eabi 7.10-1+9
libnewlib-arm-none-eabi 2.2.0+git20150830.5a3d536-1
binutils-arm-none-eabi 2.31.1-2+10
gcc-arm-none-eabi 15:7-2018-q2-6
gdb-multiarch 8.2.1-1
libnewlib-arm-none-eabi 3.1.0.20181231-1
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
@@ -388,6 +398,12 @@ Then, type:
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.
How to install
==============
@@ -395,18 +411,14 @@ How to install
Olimex STM32-H103 board
-----------------------
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
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
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg \
-f board/olimex_stm32_h103.cfg \
-c "program build/gnuk.elf verify reset exit"
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
Command invocation is assumed in src/ directory.
Flying Stone Tiny 01
@@ -414,9 +426,10 @@ Flying Stone Tiny 01
If you are using Flying Stone Tiny 01, you need a SWD writer.
OpenOCD 0.9 now supports ST-Link/V2. We can use it:
OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "program build/gnuk.elf verify reset exit"
@@ -435,20 +448,24 @@ Then, reset the board.
How to protect flash ROM
========================
Invoke your OpenOCD and type:
To protect, invoke OpenOCD like (for FST-01):
$ telnet localhost 4444
> reset halt
> stm32f1x lock 0
> reset
> shutdown
$ 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. If you want to protect, killing DfuSe and
accessing by JTAG debugger is recommended.
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
@@ -513,8 +530,8 @@ Type following command to see Gnuk runs:
$ gpg --card-status
Besides, there is a functionality test under test/ directory. See
test/README.
Besides, there is a functionality test under tests/ directory. See
tests/README.
Personalize the Token, import keys, and change the password
@@ -536,7 +553,7 @@ 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: http://www.fsij.org/doc-gnuk/
version at: https://www.fsij.org/doc-gnuk/
How to debug
@@ -551,6 +568,10 @@ 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:
@@ -571,39 +592,33 @@ See doc/note/firmware-update.
Git Repositories
================
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
Please use: https://salsa.debian.org/gnuk-team/gnuk/
You can get it by:
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
$ git clone https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
It's also available at: www.gniibe.org
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
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 init
$ git submodule update
We have migrated from ChibiOS/RT to Chopstx in Gnuk 1.1. If you have
old code of ChibiOS/RT, you need:
Edit .git/config to remove chibios reference
git rm --cached chibios
$ git submodule update --init
Information on the Web
======================
Please visit: http://www.fsij.org/gnuk/
For more information, please visit: https://www.fsij.org/gnuk/
Please see the FST-01 support pages:
http://www.gniibe.org/category/fst-01.html
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
https://lists.gnupg.org/mailman/listinfo/gnuk-users
Your Contributions

8
THANKS
View File

@@ -7,16 +7,20 @@ 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.
Aurelien Jarno aurelien@aurel32.net
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
Fabio Utzig utzig@apache.org
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
@@ -29,9 +33,13 @@ 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
Peter Lebbing peter@digitalbrains.com
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.2
release/1.2.14

Submodule chopstx updated: d448d3c678...aeea3c31f8

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"
@@ -50,39 +50,9 @@ With the script below, I extract public key of the keygrip
$ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
Here is the script, get_raw_public_key.py::
#! /usr/bin/python
import sys, binascii
from subprocess import check_output
def get_gpg_public_key(keygrip):
result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"])
key = ""
while True:
i = result.find('%')
if i < 0:
key += result
break
hex_str = result[i+1:i+3]
key += result[0:i]
key += chr(int(hex_str,16))
result = result[i+3:]
pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too
key = key[pos:-17] # )(1:e3:XYZ)))\nOK\n
if len(key) != 256:
raise ValueError, binascii.hexlify(key)
return key
if __name__ == '__main__':
keygrip = sys.argv[1]
k = get_gpg_public_key(keygrip)
shorthand = keygrip[0:8] + ".bin"
f = open(shorthand,"w")
f.write(k)
f.close()
(The script is available in the directory gnuk/tool. Please note that
it was written in the early stage of the development. The quality of
the code is somewhat questionable.)
Then, we can put the data of public key into token by::

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
@@ -122,8 +127,8 @@ How to run the script: ::
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

7
docker/Dockerfile.check Normal file
View File

@@ -0,0 +1,7 @@
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

4
docker/Dockerfile.debug Normal file
View File

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

View File

@@ -0,0 +1,6 @@
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"]

36
docker/Makefile Normal file
View File

@@ -0,0 +1,36 @@
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

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

@@ -37,7 +37,7 @@
#include "polarssl/bignum.h"
#include "polarssl/bn_mul.h"
#include <stdlib.h>
#include <gnuk-malloc.h>
#define ciL (sizeof(t_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
@@ -223,6 +223,7 @@ size_t mpi_lsb( const mpi *X )
return( 0 );
}
#if !defined(POLARSSL_HAVE_UDBL)
/*
* Count leading zero bits in a given integer
*/
@@ -240,6 +241,7 @@ static size_t int_clz( const t_uint x )
return j;
}
#endif
/*
* Return the number of most significant bits
@@ -1140,9 +1142,9 @@ static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
*/
if(( 0 == d ) || ( u1 >= d ))
{
if (r != NULL) *r = (~0);
if (r != NULL) *r = (~0UL);
return (~0);
return (~0UL);
}
#if defined(POLARSSL_HAVE_UDBL)
@@ -1268,7 +1270,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
for( i = n; i > t ; i-- )
{
if( X.p[i] >= Y.p[t] )
Z.p[i - t - 1] = ~0;
Z.p[i - t - 1] = ~0UL;
else
{
Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i-1], Y.p[t], NULL);
@@ -1295,7 +1297,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
if( mpi_cmp_int( &X, 0 ) < 0 )
while( mpi_cmp_int( &X, 0 ) < 0 )
{
MPI_CHK( mpi_copy( &T1, &Y ) );
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
@@ -1512,9 +1514,17 @@ static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
/*
* Montgomery square: A = A * A * R^-1 mod N
* A is placed at the upper half of D.
*
* n : number of limbs of N
* np: pointer to limbs of bignum N
* mm: m' = -N^(-1) mod b where b = 2^number-of-bit-in-limb
* d (destination): the result [<-- temp -->][<--- A ---->]
* lower part upper part
* n-limb n-limb
*/
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
{
#if defined(POLARSSL_HAVE_ASM) && defined(__arm__)
size_t i;
register t_uint c = 0;
@@ -1526,6 +1536,52 @@ 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; */
@@ -1587,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 );
}
@@ -1598,16 +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;
@@ -1632,7 +1702,6 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
* Init temps and window size
*/
mpi_montg_init( &mm, N );
MPI_CHK( mpi_grow( X, N->n ) );
/*
* If 1st call, pre-compute R^2 mod N
@@ -1658,6 +1727,8 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
memset (d, 0, N->n * ciL); /* Set lower half of D zero. */
}
MPI_CHK( mpi_grow( X, N->n ) );
/*
* W[1] = A * R^2 * R^-1 mod N = A * R mod N
*/
@@ -2051,17 +2122,19 @@ jkiss (struct jkiss_state *s)
static int mpi_fill_pseudo_random ( mpi *X, size_t size)
{
int ret;
uint32_t *p;
uint32_t *p, *p_end;
MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
MPI_CHK( mpi_lset( X, 0 ) );
/* Assume little endian. */
p = X->p;
while (p < X->p + (size/ciL))
p = (uint32_t *)X->p;
p_end = (uint32_t *)(X->p + (size/sizeof (uint32_t)));
while (p < p_end)
*p++ = jkiss (&jkiss_state_v);
if ((size % ciL))
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % ciL))) - 1);
if ((size%sizeof (uint32_t)))
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % sizeof (uint32_t)))) - 1);
cleanup:
return ret;
@@ -2202,10 +2275,24 @@ cleanup:
* Value M: multiply all primes up to 701 (except 97) and 797
* (so that MAX_A will be convenient value)
*/
#ifdef __LP64__
#define M_LIMBS 16
#else
#define M_LIMBS 31
#endif
#define M_SIZE 122
static const t_uint limbs_M[] = { /* Little endian */
#ifdef __LP64__
0x9344A6AB84EEB59EUL, 0xEC855CDAFF21529FUL,
0x477E991E009BAB38UL, 0x2EEA23579F5B86F3UL,
0xAC17D30441D6502FUL, 0x38FF52B90A468A6DUL,
0x63630419FD42E5EFUL, 0x48CE17D091DB2572UL,
0x708AB00AE3B57D0EUL, 0xF8A9DE08CD723598UL,
0x731411374432C93BUL, 0x554DF2612779FAB3UL,
0xDEEBDA58953D2BA5UL, 0xD1D66F2F5F57D007UL,
0xB85C9607E84E9F2BUL, 0x000000000000401DUL
#else
0x84EEB59E, 0x9344A6AB, 0xFF21529F, 0xEC855CDA,
0x009BAB38, 0x477E991E, 0x9F5B86F3, 0x2EEA2357,
0x41D6502F, 0xAC17D304, 0x0A468A6D, 0x38FF52B9,
@@ -2214,6 +2301,7 @@ static const t_uint limbs_M[] = { /* Little endian */
0x4432C93B, 0x73141137, 0x2779FAB3, 0x554DF261,
0x953D2BA5, 0xDEEBDA58, 0x5F57D007, 0xD1D66F2F,
0xE84E9F2B, 0xB85C9607, 0x0000401D
#endif
};
static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
@@ -2221,10 +2309,18 @@ static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
/*
* MAX_A : 2^1024 / M - 1
*/
#ifdef __LP64__
#define MAX_A_LIMBS 1
#else
#define MAX_A_LIMBS 2
#endif
#define MAX_A_FILL_SIZE 6
static const t_uint limbs_MAX_A[] = { /* Little endian */
#ifdef __LP64__
0x0003FE2556A2B35FUL
#else
0x56A2B35F, 0x0003FE25
#endif
};
static const mpi MAX_A[1] = {{ 1, MAX_A_LIMBS, (t_uint *)limbs_MAX_A }};
@@ -2274,9 +2370,8 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
MPI_CHK ( mpi_mul_mpi ( X, X, M ) );
MPI_CHK ( mpi_add_abs ( X, X, B ) );
if (X->n <= 31 || (X->p[31] & 0xc0000000) == 0)
if (X->n <= M_LIMBS || (X->p[M_LIMBS-1] & 0xc0000000) == 0)
continue;
ret = mpi_is_prime ( X );
if (ret == 0 || ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE)
break;

View File

@@ -39,7 +39,6 @@
#include "polarssl/md.h"
#endif
#include <stdlib.h>
#include <stdio.h>
/*

View File

@@ -1,8 +1,11 @@
# Makefile for reGNUal
PROJECT = regnual
PROJECT = regnual-no-vidpid
OBJS = regnual.o usb-stm32f103.o reset.o
include ../src/config.mk
LDSCRIPT= regnual.ld
###################################
@@ -19,7 +22,7 @@ TOPT = -mthumb -DTHUMB -mno-thumb-interwork
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes
MCFLAGS= -mcpu=$(MCU)
DEFS = -DFREE_STANDING
DEFS += -DFREE_STANDING
CFLAGS = -O2 -g
CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie
@@ -38,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
* Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -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++)
@@ -365,7 +381,11 @@ main (int argc, char *argv[])
set_led (0);
#if defined(STM32F103_OVERRIDE_FLASH_SIZE_KB)
flash_end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
#else
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
#endif
/*
* NVIC interrupt priority was set by Gnuk.

View File

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

110
src/Makefile Normal file
View File

@@ -0,0 +1,110 @@
# Makefile for Gnuk
# Define project name here
PROJECT = gnuk
CHOPSTX = ../chopstx
CSRC = main.c call-rsa.c \
usb_desc.c usb_ctrl.c \
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
bn.c mod.c \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
mod25638.c ecc-edwards.c ecc-mont.c sha512.c \
random.c neug.c sha256.c
INCDIR =
CRYPTDIR = ../polarssl
CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
CSRC += $(CRYPTSRC)
INCDIR += $(CRYPTINCDIR)
include config.mk
USE_SYS = yes
USE_USB = yes
USE_ADC = yes
USE_EVENTFLAG = yes
ifeq ($(EMULATION),)
DEFS += -DFLASH_UPGRADE_SUPPORT
else
DEFS += -DBN256_C_IMPLEMENTATION
endif
ifneq ($(ENABLE_DEBUG),)
CSRC += debug.c
endif
ifneq ($(ENABLE_PINPAD),)
CSRC += pin-$(ENABLE_PINPAD).c
endif
ifeq ($(ENABLE_PINPAD),dnd)
CSRC += usb-msc.c
endif
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
OBJCOPY = $(CROSS)objcopy
CWARN = -Wall -Wextra -Wstrict-prototypes
OPT = -O3 -Os -g
#######################
include $(CHOPSTX)/rules.mk
board.h:
@echo Please run configure to have a symbolic link \'board.h\'
@exit 1
sys.c: board.h
build/bignum.o: OPT = -O3 -g
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 $@
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.
# The variables prefix, exec_prefix, libexecdir are defined in
# config.mk.
install: build/gnuk
test -d "$(DESTDIR)$(libexecdir)" || mkdir -p "$(DESTDIR)$(libexecdir)"
install -c build/gnuk "$(DESTDIR)$(libexecdir)"
endif

View File

@@ -1,79 +0,0 @@
# Makefile for Gnuk
# Define project name here
PROJECT = gnuk
CHOPSTX = ../chopstx
# Define linker script file here
LDSCRIPT= gnuk.ld
CSRC = main.c usb_desc.c usb_ctrl.c \
call-rsa.c \
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
bn.c mod.c \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
mod25638.c ecc-edwards.c ecc-mont.c sha512.c \
random.c neug.c sha256.c
INCDIR =
CRYPTDIR = ../polarssl
CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
CSRC += $(CRYPTSRC)
INCDIR += $(CRYPTINCDIR)
@PINPAD_MAKE_OPTION@
@DEBUG_MAKE_OPTION@
@HEXOUTPUT_MAKE_OPTION@
USE_EVENTFLAG = yes
ifneq ($(ENABLE_DEBUG),)
CSRC += debug.c
endif
ifneq ($(ENABLE_PINPAD),)
CSRC += pin-$(ENABLE_PINPAD).c
endif
ifeq ($(ENABLE_PINPAD),dnd)
CSRC += usb-msc.c
endif
CHIP=stm32f103
USE_SYS = yes
USE_USB = yes
USE_ADC = yes
###################################
CROSS = arm-none-eabi-
CC = $(CROSS)gcc
LD = $(CROSS)gcc
OBJCOPY = $(CROSS)objcopy
MCU = cortex-m3
CWARN = -Wall -Wextra -Wstrict-prototypes
# DEFS: Add
DEFS = @USE_SYS3@
OPT = -O3 -Os -g
LIBS =
#######################
include $(CHOPSTX)/rules.mk
board.h:
@echo Please run configure to have a symbolic link \'board.h\'
@exit 1
sys.c: board.h
build/bignum.o: OPT = -O3 -g
distclean: clean
-rm -f gnuk.ld config.h board.h Makefile \
usb-strings.c.inc usb-vid-pid-ver.c.inc

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.
@@ -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
@@ -220,6 +222,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 +240,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,7 @@
/*
* call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
*
* Copyright (C) 2013, 2014 Free Software Initiative of Japan
* Copyright (C) 2013, 2014, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -54,28 +54,21 @@ FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
return 0;
}
uint8_t *
FUNC(ecc_compute_public) (const uint8_t *key_data)
int
FUNC(ecc_compute_public) (const uint8_t *key_data, uint8_t *pubkey)
{
uint8_t *p0, *p, *p1;
uint8_t *p, *p1;
ac q[1];
bn256 k[1];
int i;
p0 = (uint8_t *)malloc (ECDSA_BYTE_SIZE * 2);
if (p0 == NULL)
return NULL;
p = (uint8_t *)k;
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
if (FUNC(compute_kG) (q, k) < 0)
{
free (p0);
return NULL;
}
return -1;
p = p0;
p = pubkey;
p1 = (uint8_t *)q->x;
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
@@ -83,7 +76,7 @@ FUNC(ecc_compute_public) (const uint8_t *key_data)
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
return p0;
return 0;
}
int

View File

@@ -2,7 +2,7 @@
* call-ec_p256k1.c - interface between Gnuk and Elliptic curve over
* GF(p256k1)
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bn.h"
#include "affine.h"

View File

@@ -2,7 +2,7 @@
* call-ec_p256r1.c - interface between Gnuk and Elliptic curve over
* GF(p256r1)
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bn.h"
#include "affine.h"

View File

@@ -1,7 +1,7 @@
/*
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2017
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <chopstx.h>
#include "config.h"
@@ -41,7 +40,7 @@ static struct chx_cleanup clp;
static void
rsa_cleanup (void *arg)
{
free (arg);
(void)arg;
rsa_free (&rsa_ctx);
}
@@ -111,28 +110,23 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
/*
* LEN: length in byte
*/
uint8_t *
modulus_calc (const uint8_t *p, int len)
int
modulus_calc (const uint8_t *p, int len, uint8_t *pubkey)
{
mpi P, Q, N;
uint8_t *modulus;
int ret;
modulus = malloc (len);
if (modulus == NULL)
return NULL;
mpi_init (&P); mpi_init (&Q); mpi_init (&N);
MPI_CHK( mpi_read_binary (&P, p, len / 2) );
MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
MPI_CHK( mpi_write_binary (&N, modulus, len) );
MPI_CHK( mpi_write_binary (&N, pubkey, len) );
cleanup:
mpi_free (&P); mpi_free (&Q); mpi_free (&N);
if (ret != 0)
return NULL;
else
return modulus;
return -1;
return 0;
}
@@ -142,6 +136,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
{
mpi P1, Q1, H;
int ret;
#ifdef GNU_LINUX_EMULATION
size_t output_len;
#endif
DEBUG_INFO ("RSA decrypt:");
DEBUG_WORD ((uint32_t)&ret);
@@ -177,9 +174,16 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
#ifdef GNU_LINUX_EMULATION
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, &output_len, input,
output, MAX_RES_APDU_DATA_SIZE);
*output_len_p = (unsigned int)output_len;
#else
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, output_len_p, input,
output, MAX_RES_APDU_DATA_SIZE);
#endif
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
@@ -232,54 +236,39 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
#define RSA_EXPONENT 0x10001
uint8_t *
rsa_genkey (int pubkey_len)
int
rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q)
{
int ret;
uint8_t index = 0;
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
uint8_t *p = p_q_modulus;
uint8_t *q = p_q_modulus + pubkey_len / 2;
uint8_t *modulus = p_q_modulus + pubkey_len;
uint8_t *p = p_q;
uint8_t *q = p_q + pubkey_len / 2;
int cs;
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
extern void neug_flush (void);
if (p_q_modulus == NULL)
return NULL;
neug_flush ();
prng_seed (random_gen, &index);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = (void *)p_q_modulus;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
RSA_EXPONENT) );
if (ret != 0)
{
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
free (p_q_modulus);
rsa_free (&rsa_ctx);
return NULL;
}
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
rsa_free (&rsa_ctx);
chopstx_cleanup_pop (1);
if (ret != 0)
return NULL;
return -1;
else
return p_q_modulus;
return 0;
}

View File

@@ -3,9 +3,12 @@
#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@

282
src/configure vendored
View File

@@ -6,10 +6,11 @@ nl=$'\n'
#
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
# Free Software Initiative of Japan
#
# 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
@@ -36,7 +37,6 @@ fi
help=no
vidpid=none
target=FST_01
verbose=no
with_dfu=default
debug=no
sys1_compat=yes
@@ -44,26 +44,36 @@ pinpad=no
certdo=no
hid_card_change=no
factory_reset=no
ackbtn_support=yes
flash_override=""
# For emulation
prefix=/usr/local
exec_prefix='${prefix}'
libexecdir='${exec_prefix}/libexec'
# Revision number
if test -e ../.git; then
REVISION=`git describe --dirty="-modified"`
if type git >/dev/null 2>&1; then
REVISION=$(git describe --dirty="-modified")
else
# echo 'No git available, please install git'
GIT_REVISION=$(sed -e 's/^\(.......\).*$/g\1/' "../.git/$(sed -e 's/^ref: //' ../.git/HEAD)")
REVISION=$(cat ../VERSION)-$GIT_REVISION
fi
else
REVISION=`cat ../VERSION`
REVISION=$(cat ../VERSION)
fi
# Process each option
for option; do
case $option in
*=*) optarg=`expr "X$option" : '[^=]*=\(.*\)'` ;;
*=*) optarg=$(expr "X$option" : '[^=]*=\(.*\)') ;;
*) optarg=yes ;;
esac
case $option in
-h | --help)
help=yes ;;
-v | --verbose)
verbose=yes ;;
--vidpid=*)
vidpid=$optarg ;;
--target=*)
@@ -96,6 +106,15 @@ for option; do
with_dfu=yes ;;
--without-dfu)
with_dfu=no ;;
#
# For emulation
#
--prefix=*)
prefix=optarg ;;
--exec-prefix=*)
exec_prefix=optarg ;;
--libexecdir=*)
libexecdir=optarg ;;
*)
echo "Unrecognized option \`$option'" >&2
echo "Try \`$0 --help' for more information." >&2
@@ -117,16 +136,21 @@ Configuration:
supported targets are:
FST_01
FST_01G
FST_01SZ
OLIMEX_STM32_H103
STM32_PRIMER2
STBEE
STBEE_MINI
MAPLE_MINI
ST_DONGLE
ST_NUCLEO_F103
NITROKEY_START
BLUE_PILL
STM8S_DISCOVERY
CQ_STARM
STM32_PRIMER2
STBEE
STBEE_MINI
FST_01_00 (unreleased version with 8MHz XTAL)
--enable-factory-reset
support life cycle management [no]
--enable-debug debug with virtual COM port [no]
--enable-pinpad=cir
PIN entry support [no]
@@ -136,22 +160,17 @@ Configuration:
--disable-sys1-compat disable SYS 1.0 compatibility [no]
executable is target independent
but requires SYS 2.0 or newer
--enable-factory-reset
support life cycle management [no]
--with-dfu build image for DFU [<target specific>]
EOF
exit 0
fi
if test "$vidpid" = "none"; then
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
exit 1
fi
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
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
@@ -161,6 +180,10 @@ MEMORY_SIZE=20
# Settings for TARGET
case $target in
BLUE_PILL|STM8S_DISCOVERY)
# It's 64KB version of STM32F103, but actually has 128KB
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB=128"
;;
CQ_STARM|STBEE_MINI)
if test "$with_dfu" = "default"; then
with_dfu=yes;
@@ -177,13 +200,55 @@ STBEE)
if test "$with_dfu" = "default"; then
with_dfu=yes;
fi ;;
STM8S_DISCOVERY)
FLASH_SIZE=64
BLUE_PILL_G)
MHZ=96
;;
FST_01SZ)
MHZ=96
;;
*)
;;
esac
if test "$target" = "GNU_LINUX"; then
ldscript=""
chip="gnu-linux"
emulation="yes"
cross=""
mcu="none"
def_emulation="-DGNU_LINUX_EMULATION"
def_memory_size="-DMEMORY_SIZE=1024"
def_mhz=""
enable_hexoutput=""
libs="-lpthread"
else
ldscript="gnuk.ld"
chip="stm32f103"
emulation=""
cross="arm-none-eabi-"
mcu="cortex-m3"
def_emulation=""
def_memory_size="-DMEMORY_SIZE=$MEMORY_SIZE"
def_mhz="-DMHZ=$MHZ"
enable_hexoutput=yes
libs=""
fi
if test "$emulation" = "yes"; then
if test "$vidpid" = "none"; then
vidpid=0000:0000
else
echo "Please don't specify VID:PID for emulation at compile time;"
echo "It is a user who should specify VID:PID at run time."
exit 1
fi
else
if test "$vidpid" = "none"; then
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
exit 1
fi
fi
# --enable-debug option
if test "$debug" = "yes"; then
DEBUG_MAKE_OPTION="ENABLE_DEBUG=1"
@@ -195,6 +260,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" \
@@ -203,22 +270,25 @@ if test "$with_dfu" = "yes"; then
exit 1
fi
echo "Configured for DFU"
ORIGIN=0x08003000
FLASH_SIZE=`expr $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"
HEXOUTPUT_MAKE_OPTION="ENABLE_OUTPUT_HEX=yes"
else
with_dfu=no
echo "Configured for bare system (no-DFU)"
ORIGIN=0x08000000
ORIGIN=${ORIGIN_REAL}
DFU_DEFINE="#undef DFU_SUPPORT"
HEXOUTPUT_MAKE_OPTION=""
fi
ORIGIN_DEFINE="#define ORIGIN $ORIGIN"
# --enable-pinpad option
MSC_SIZE="0"
TIM_SIZE="0"
EXT_SIZE="0"
if test "$pinpad" = "no"; then
PINPAD_MAKE_OPTION="# ENABLE_PINPAD="
PINPAD_DEFINE="#undef PINPAD_SUPPORT"
@@ -229,12 +299,6 @@ else
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
PINPAD_MORE_DEFINE="#define PINPAD_${pinpad^^[a-z]}_SUPPORT 1"
echo "PIN pad option enabled ($pinpad)"
if test "$pinpad" = "dnd"; then
MSC_SIZE="0x0200"
elif test "$pinpad" = "cir"; then
TIM_SIZE="0x00c0"
EXT_SIZE="0x00c0"
fi
fi
# --enable-certdo option
@@ -264,14 +328,23 @@ 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
### !!! Replace following string of "FSIJ" to yours !!! ####
SERIALNO="FSIJ-`cat ../VERSION | sed -e 's%^[^/]*/%%'`-"
SERIALNO="FSIJ-$(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"
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset"
else
if test "$with_dfu" = "yes"; then
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
@@ -281,53 +354,82 @@ else
FLASH_PAGE_SIZE=2048
FLASH_SIZE=128
MEMORY_SIZE=20
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo"
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset"
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 () {
prefix=$1
name=$1
echo "static const uint8_t ${prefix}string_vendor[] = {"
echo " ${#VENDOR}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}string_vendor[] = {"
echo " ${#VENDOR}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Manufacturer: \"$VENDOR\" */"
echo $VENDOR | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo "$VENDOR" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo "$PRODUCT" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
if test -n "$prefix"; then
if test -n "$name"; then
echo
echo "const uint8_t ${prefix}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "const uint8_t ${name}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo "$SERIALNO" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
if test "$emulation" = "yes"; then
echo " 'E', 0, 'M', 0, 'U', 0, 'L', 0,"
echo " 'A', 0, 'T', 0, 'E', 0, 'D', 0,"
else
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
fi
echo '};'
echo
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo "static const uint8_t ${prefix}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo "$REVISION" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
@@ -335,16 +437,22 @@ output_vendor_product_serial_strings () {
fi
}
(echo "#! /bin/bash"
echo
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
if !(IFS=" "
while read VIDPID VERSION PRODUCT VENDOR; do
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
done; exit 1) < ../GNUK_USB_DEVICE_ID
then
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Check ../GNUK_USB_DEVICE_ID." >&2
exit 1
fi
@@ -361,37 +469,55 @@ else
fi
sed -e "s%@USE_SYS3@%$use_sys3%" \
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
-e "s%@HEXOUTPUT_MAKE_OPTION@%$HEXOUTPUT_MAKE_OPTION%" \
< Makefile.in > Makefile
(echo "CHIP=$chip";
echo "EMULATION=$emulation";
echo "CROSS=$cross";
echo "MCU=$mcu";
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"
echo "libexecdir=$libexecdir"
fi
) > config.mk
if test "$certdo" = "yes"; then
sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
< gnuk.ld.in > gnuk.ld
else
sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
-e "s/@EXT_SIZE@/$EXT_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/" \
< config.h.in > config.h
exit 0

View File

@@ -42,9 +42,11 @@
/*
* a = 0, b = 7
*/
#if 0
static const bn256 coefficient_a[1] = {
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
};
#endif
static const bn256 coefficient_b[1] = {
{{ 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}

View File

@@ -2,7 +2,7 @@
* ecc-edwards.c - Elliptic curve computation for
* the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bn.h"
@@ -708,7 +707,7 @@ eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
return 0;
}
void
static void
eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
{
ac R[1];
@@ -730,18 +729,10 @@ eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
}
uint8_t *
eddsa_compute_public_25519 (const uint8_t *kd)
void
eddsa_compute_public_25519 (const uint8_t *kd, uint8_t *pubkey)
{
uint8_t *p0;
const bn256 *a = (const bn256 *)kd;
p0 = (uint8_t *)malloc (sizeof (bn256));
if (p0 == NULL)
return NULL;
eddsa_public_key_25519 ((bn256 *)p0, a);
return p0;
eddsa_public_key_25519 ((bn256 *)pubkey, (const bn256 *)kd);
}

View File

@@ -2,7 +2,7 @@
* ecc-mont.c - Elliptic curve computation for
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
*
* Copyright (C) 2014, 2015 Free Software Initiative of Japan
* Copyright (C) 2014, 2015, 2017 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "bn.h"
#include "mod25638.h"
#include "mod.h"
@@ -198,22 +197,17 @@ compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
}
uint8_t *
ecdh_compute_public_25519 (const uint8_t *key_data)
void
ecdh_compute_public_25519 (const uint8_t *key_data, uint8_t *pubkey)
{
uint8_t *p;
bn256 gx[1];
bn256 k[1];
memset (gx, 0, sizeof (bn256));
gx[0].word[0] = 9; /* Gx = 9 */
memcpy (k, key_data, sizeof (bn256));
p = (uint8_t *)malloc (sizeof (bn256));
if (p == NULL)
return NULL;
compute_nQ ((bn256 *)p, k, gx);
return p;
compute_nQ ((bn256 *)pubkey, k, gx);
}
int

View File

@@ -384,7 +384,7 @@ FUNC(check_secret) (const bn256 *d0, bn256 *d1)
{
ac Q0[1], Q1[1];
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) <= 0)
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) != 0)
/* == 0 or >= N, it's not valid. */
return 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
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -53,33 +53,40 @@
* <alignment to page>
* ch_certificate_startp
* <2048 bytes>
* _data_pool
* <two pages>
* _keystore_pool
* Three flash pages for keystore
* a page contains a key data of:
* For RSA-2048: 512-byte (p, q and N)
* For RSA-4096: 1024-byte (p, q and N)
* For ECDSA/ECDH and EdDSA, there are padding after public key
* _data_pool
* <two pages>
*/
#define FLASH_DATA_POOL_HEADER_SIZE 2
#define FLASH_DATA_POOL_SIZE (flash_page_size*2)
static uint16_t flash_page_size;
static const uint8_t *data_pool;
extern uint8_t _keystore_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
};
/* Linker set this symbol */
#ifdef GNU_LINUX_EMULATION
extern uint8_t *flash_addr_key_storage_start;
extern uint8_t *flash_addr_data_storage_start;
#define FLASH_ADDR_KEY_STORAGE_START flash_addr_key_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))
#endif
static int key_available_at (const uint8_t *k, int key_size)
{
@@ -102,39 +109,45 @@ static int key_available_at (const uint8_t *k, int key_size)
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
const uint8_t *
flash_init (void)
void
flash_do_storage_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
{
uint16_t gen0, gen1;
uint16_t *gen0_p = (uint16_t *)&_data_pool;
uint16_t *gen0_p = (uint16_t *)FLASH_ADDR_DATA_STORAGE_START;
uint16_t *gen1_p;
flash_page_size = 1024;
#if !defined (GNU_LINUX_EMULATION)
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
flash_page_size = 2048;
#endif
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
data_pool = &_data_pool;
gen1_p = (uint16_t *)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size);
data_pool = FLASH_ADDR_DATA_STORAGE_START;
/* Check data pool generation and choose the page */
gen0 = *gen0_p;
gen1 = *gen1_p;
if (gen0 == 0xffff && gen1 == 0xffff)
/* It's terminated. */
return NULL;
{
/* It's terminated. */
*p_do_start = *p_do_end = NULL;
return;
}
if (gen0 == 0xffff)
/* Use another page if a page is erased. */
data_pool = &_data_pool + flash_page_size;
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
else if (gen1 == 0xffff)
/* Or use different page if another page is erased. */
data_pool = &_data_pool;
data_pool = FLASH_ADDR_DATA_STORAGE_START;
else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0)
/* When both pages have valid header, use newer page. */
data_pool = &_data_pool + flash_page_size;
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
*p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE;
*p_do_end = data_pool + flash_page_size;
}
static uint8_t *flash_key_getpage (enum kind_of_key kk);
@@ -144,29 +157,40 @@ 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 ((uint32_t)flash_key_getpage (i));
flash_erase_page ((uint32_t)&_data_pool);
flash_erase_page ((uint32_t)(&_data_pool + flash_page_size));
data_pool = &_data_pool;
last_p = &_data_pool + FLASH_DATA_POOL_HEADER_SIZE;
flash_erase_page ((uintptr_t)flash_key_getpage (i));
flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START);
flash_erase_page ((uintptr_t)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size));
data_pool = FLASH_ADDR_DATA_STORAGE_START;
last_p = FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_HEADER_SIZE;
#if defined(CERTDO_SUPPORT)
flash_erase_page ((uintptr_t)&ch_certificate_start);
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uintptr_t)(&ch_certificate_start + flash_page_size));
#endif
}
void
flash_activate (void)
{
flash_program_halfword ((uint32_t)&_data_pool, 0);
flash_program_halfword ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START, 0);
}
void
flash_init_keys (void)
flash_key_storage_init (void)
{
const uint8_t *p;
int i;
/* For each key, find its address. */
p = &_keystore_pool;
p = FLASH_ADDR_KEY_STORAGE_START;
for (i = 0; i < 3; i++)
{
const uint8_t *k;
@@ -224,15 +248,15 @@ flash_copying_gc (void)
uint8_t *src, *dst;
uint16_t generation;
if (data_pool == &_data_pool)
if (data_pool == FLASH_ADDR_DATA_STORAGE_START)
{
src = &_data_pool;
dst = &_data_pool + flash_page_size;
src = FLASH_ADDR_DATA_STORAGE_START;
dst = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
}
else
{
src = &_data_pool + flash_page_size;
dst = &_data_pool;
src = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
dst = FLASH_ADDR_DATA_STORAGE_START;
}
generation = *(uint16_t *)src;
@@ -242,8 +266,8 @@ flash_copying_gc (void)
generation = 0;
else
generation++;
flash_program_halfword ((uint32_t)dst, generation);
flash_erase_page ((uint32_t)src);
flash_program_halfword ((uintptr_t)dst, generation);
flash_erase_page ((uintptr_t)src);
return 0;
}
@@ -273,10 +297,10 @@ void
flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len)
{
uint16_t hw;
uint32_t addr;
uintptr_t addr;
int i;
addr = (uint32_t)p;
addr = (uintptr_t)p;
hw = nr | (len << 8);
if (flash_program_halfword (addr, hw) != 0)
flash_warning ("DO WRITE ERROR");
@@ -329,13 +353,14 @@ flash_warning (const char *msg)
void
flash_do_release (const uint8_t *do_data)
{
uint32_t addr = (uint32_t)do_data - 1;
uint32_t addr_tag = addr;
uintptr_t addr = (uintptr_t)do_data - 1;
uintptr_t addr_tag = addr;
int i;
int len = do_data[0];
/* Don't filling zero for data in code (such as ds_count_initial_value) */
if (do_data < &_data_pool || do_data > &_data_pool + FLASH_DATA_POOL_SIZE)
if (do_data < FLASH_ADDR_DATA_STORAGE_START
|| do_data > FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_SIZE)
return;
addr += 2;
@@ -364,7 +389,7 @@ static uint8_t *
flash_key_getpage (enum kind_of_key kk)
{
/* There is a page for each KK. */
return &_keystore_pool + (flash_page_size * kk);
return FLASH_ADDR_KEY_STORAGE_START + (flash_page_size * kk);
}
uint8_t *
@@ -398,10 +423,10 @@ flash_key_write (uint8_t *key_addr,
const uint8_t *pubkey, int pubkey_len)
{
uint16_t hw;
uint32_t addr;
uintptr_t addr;
int i;
addr = (uint32_t)key_addr;
addr = (uintptr_t)key_addr;
for (i = 0; i < key_data_len/2; i ++)
{
hw = key_data[i*2] | (key_data[i*2+1]<<8);
@@ -424,7 +449,7 @@ flash_key_write (uint8_t *key_addr,
static int
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
{
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
uintptr_t start = (uintptr_t)key_addr & ~(flash_page_size - 1);
const uint32_t *p = (const uint32_t *)start;
while (p < (const uint32_t *)(start + flash_page_size))
@@ -443,7 +468,7 @@ static void
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
{
int i;
uint32_t addr = (uint32_t)key_addr;
uintptr_t addr = (uintptr_t)key_addr;
for (i = 0; i < key_size/2; i++)
flash_program_halfword (addr + i*2, 0);
@@ -453,7 +478,7 @@ void
flash_key_release (uint8_t *key_addr, int key_size)
{
if (flash_check_all_other_keys_released (key_addr, key_size))
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
flash_erase_page (((uintptr_t)key_addr & ~(flash_page_size - 1)));
else
flash_key_fill_zero_as_released (key_addr, key_size);
}
@@ -461,12 +486,12 @@ flash_key_release (uint8_t *key_addr, int key_size)
void
flash_key_release_page (enum kind_of_key kk)
{
flash_erase_page ((uint32_t)flash_key_getpage (kk));
flash_erase_page ((uintptr_t)flash_key_getpage (kk));
}
void
flash_clear_halfword (uint32_t addr)
flash_clear_halfword (uintptr_t addr)
{
flash_program_halfword (addr, 0);
}
@@ -475,7 +500,7 @@ flash_clear_halfword (uint32_t addr)
void
flash_put_data_internal (const uint8_t *p, uint16_t hw)
{
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
void
@@ -489,7 +514,7 @@ flash_put_data (uint16_t hw)
DEBUG_INFO ("data allocation failure.\r\n");
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
@@ -501,14 +526,14 @@ flash_bool_clear (const uint8_t **addr_p)
if ((p = *addr_p) == NULL)
return;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
*addr_p = NULL;
}
void
flash_bool_write_internal (const uint8_t *p, int nr)
{
flash_program_halfword ((uint32_t)p, nr);
flash_program_halfword ((uintptr_t)p, nr);
}
const uint8_t *
@@ -524,7 +549,7 @@ flash_bool_write (uint8_t nr)
return NULL;
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
return p;
}
@@ -540,7 +565,7 @@ flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v)
{
uint16_t hw = nr | (v << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
const uint8_t *
@@ -556,7 +581,7 @@ flash_enum_write (uint8_t nr, uint8_t v)
return NULL;
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
return p;
}
@@ -592,14 +617,14 @@ flash_cnt123_write_internal (const uint8_t *p, int which, int v)
uint16_t hw;
hw = NR_COUNTER_123 | (which << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
if (v == 1)
return;
else if (v == 2)
flash_program_halfword ((uint32_t)p+2, 0xc3c3);
flash_program_halfword ((uintptr_t)p+2, 0xc3c3);
else /* v == 3 */
flash_program_halfword ((uint32_t)p+2, 0);
flash_program_halfword ((uintptr_t)p+2, 0);
}
void
@@ -617,7 +642,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
return;
}
hw = NR_COUNTER_123 | (which << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
*addr_p = p + 2;
}
else
@@ -632,7 +657,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
else
hw = 0;
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
}
@@ -644,9 +669,9 @@ flash_cnt123_clear (const uint8_t **addr_p)
if ((p = *addr_p) == NULL)
return;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
p -= 2;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
*addr_p = NULL;
}
@@ -660,9 +685,9 @@ flash_erase_binary (uint8_t file_id)
const uint8_t *p = &ch_certificate_start;
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
{
flash_erase_page ((uint32_t)p);
flash_erase_page ((uintptr_t)p);
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uint32_t)p + flash_page_size);
flash_erase_page ((uintptr_t)p + flash_page_size);
}
return 0;
@@ -685,17 +710,19 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
maxsize = 6;
p = &openpgpcard_aid[8];
}
#ifdef FLASH_UPGRADE_SUPPORT
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
{
maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
if (len == 0 && offset == 0)
{ /* This means removal of update key. */
if (flash_program_halfword ((uint32_t)p, 0) != 0)
if (flash_program_halfword ((uintptr_t)p, 0) != 0)
flash_warning ("DO WRITE ERROR");
return 0;
}
}
#endif
#if defined(CERTDO_SUPPORT)
else if (file_id == FILEID_CH_CERTIFICATE)
{
@@ -711,13 +738,13 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
else
{
uint16_t hw;
uint32_t addr;
uintptr_t addr;
int i;
if (flash_check_blank (p + offset, len) == 0)
return -1;
addr = (uint32_t)p + offset;
addr = (uintptr_t)p + offset;
for (i = 0; i < len/2; i++)
{
hw = data[i*2] | (data[i*2+1]<<8);

16
src/gnuk-malloc.h Normal file
View File

@@ -0,0 +1,16 @@
/*
* Gnuk uses its own malloc functions.
*
* The intention is no-dependency to C library. But, we provide
* malloc and free here, since RSA routines uses malloc/free
* internally.
*
*/
#include <stddef.h> /* NULL and size_t */
#define malloc(size) gnuk_malloc (size)
#define free(p) gnuk_free (p)
void *gnuk_malloc (size_t);
void gnuk_free (void *);

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
@@ -106,13 +104,13 @@ extern uint16_t data_objects_number_of_bytes;
#define CHALLENGE_LEN 32
void gpg_data_scan (const uint8_t *p);
void gpg_data_scan (const uint8_t *start, const uint8_t *end);
void gpg_data_copy (const uint8_t *p);
void gpg_do_terminate (void);
void gpg_do_get_data (uint16_t tag, int with_tag);
void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
void gpg_do_public_key (uint8_t kk_byte);
void gpg_do_keygen (uint8_t kk_byte);
void gpg_do_keygen (uint8_t *buf);
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
@@ -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 {
@@ -139,10 +137,10 @@ enum size_of_key {
int gpg_get_algo_attr (enum kind_of_key kk);
int gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s);
const uint8_t *flash_init (void);
void flash_do_storage_init (const uint8_t **, const uint8_t **);
void flash_terminate (void);
void flash_activate (void);
void flash_init_keys (void);
void flash_key_storage_init (void);
void flash_do_release (const uint8_t *);
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
uint8_t *flash_key_alloc (enum kind_of_key);
@@ -152,7 +150,7 @@ int flash_key_write (uint8_t *key_addr,
const uint8_t *key_data, int key_data_len,
const uint8_t *pubkey, int pubkey_len);
void flash_set_data_pool_last (const uint8_t *p);
void flash_clear_halfword (uint32_t addr);
void flash_clear_halfword (uintptr_t addr);
void flash_increment_counter (uint8_t counter_tag_nr);
void flash_reset_counter (uint8_t counter_tag_nr);
@@ -265,22 +263,22 @@ void put_binary (const char *s, int len);
#endif
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
uint8_t *modulus_calc (const uint8_t *, int);
int modulus_calc (const uint8_t *, int, uint8_t *);
int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *,
unsigned int *);
int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *);
uint8_t *rsa_genkey (int);
int rsa_genkey (int, uint8_t *, uint8_t *);
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
int ecc_compute_public_p256r1 (const uint8_t *key_data, uint8_t *);
int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
int ecc_compute_public_p256k1 (const uint8_t *key_data, uint8_t *);
int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
@@ -288,19 +286,24 @@ int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
const uint8_t *sk_a, const uint8_t *seed,
const uint8_t *pk);
uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
void eddsa_compute_public_25519 (const uint8_t *a, uint8_t *);
void ecdh_compute_public_25519 (const uint8_t *a, uint8_t *);
int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
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));
#define FATAL_FLASH 1
#define FATAL_RANDOM 2
#define FATAL_HEAP 3
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
extern uint8_t admin_authorized;
@@ -333,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:
@@ -376,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). */
/*
@@ -432,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)
@@ -458,4 +474,7 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
#endif
extern uint8_t _regnual_start, __heap_end__[];
uint8_t * sram_address (uint32_t offset);

View File

@@ -1,16 +1,6 @@
/*
* ST32F103 memory setup.
*/
__main_stack_size__ = 0x0080; /* Exception handlers */
__process0_stack_size__ = 0x0100; /* main */
__process1_stack_size__ = 0x0180; /* ccid */
__process2_stack_size__ = 0x0180; /* rng */
__process3_stack_size__ = 0x1640; /* gpg */
__process4_stack_size__ = 0; /* --- */
__process5_stack_size__ = @MSC_SIZE@; /* msc */
__process6_stack_size__ = @TIM_SIZE@; /* intr: timer */
__process7_stack_size__ = @EXT_SIZE@; /* intr: ext */
MEMORY
{
flash0 : org = @ORIGIN@, len = 4k
@@ -82,45 +72,18 @@ SECTIONS
_etext = .;
_textdata = _etext;
.stacks :
.stacks (NOLOAD) :
{
. = ALIGN(8);
__main_stack_base__ = .;
. += __main_stack_size__;
. = ALIGN(8);
__main_stack_end__ = .;
__process0_stack_base__ = .;
. += __process0_stack_size__;
. = ALIGN(8);
__process0_stack_end__ = .;
__process1_stack_base__ = .;
. += __process1_stack_size__;
. = ALIGN(8);
__process1_stack_end__ = .;
__process2_stack_base__ = .;
. += __process2_stack_size__;
. = ALIGN(8);
__process2_stack_end__ = .;
__process3_stack_base__ = .;
. += __process3_stack_size__;
. = ALIGN(8);
__process3_stack_end__ = .;
__process4_stack_base__ = .;
. += __process4_stack_size__;
. = ALIGN(8);
__process4_stack_end__ = .;
__process5_stack_base__ = .;
. += __process5_stack_size__;
. = ALIGN(8);
__process5_stack_end__ = .;
__process6_stack_base__ = .;
. += __process6_stack_size__;
. = ALIGN(8);
__process6_stack_end__ = .;
__process7_stack_base__ = .;
. += __process7_stack_size__;
. = ALIGN(8);
__process7_stack_end__ = .;
*(.main_stack)
*(.process_stack.0)
*(.process_stack.1)
*(.process_stack.2)
*(.process_stack.3)
*(.process_stack.4)
*(.process_stack.5)
*(.process_stack.6)
*(.process_stack.7)
. = ALIGN(8);
} > ram
@@ -171,20 +134,20 @@ SECTIONS
.gnuk_flash :
{
. = ALIGN (@FLASH_PAGE_SIZE@);
_data_pool = .;
KEEP(*(.gnuk_data))
. = ALIGN(@FLASH_PAGE_SIZE@);
. += @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;
. = ALIGN(@FLASH_PAGE_SIZE@);
_data_pool = .;
KEEP(*(.gnuk_data))
. = ALIGN(@FLASH_PAGE_SIZE@);
. += @FLASH_PAGE_SIZE@;
} > flash =0xffffffff
}

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -35,8 +35,13 @@
#include "usb_lld.h"
#include "usb-cdc.h"
#include "random.h"
#ifdef GNU_LINUX_EMULATION
#include <stdio.h>
#include <stdlib.h>
#define main emulated_main
#else
#include "mcu/stm32f103.h"
#endif
/*
* main thread does 1-bit LED display output
@@ -46,7 +51,33 @@
#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;
uint8_t *flash_addr_data_storage_start;
#else
#define ID_OFFSET (2+SERIALNO_STR_LEN*2)
static void
device_initialize_once (void)
@@ -59,7 +90,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++)
@@ -74,12 +105,66 @@ 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
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)
{
@@ -120,17 +205,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);
@@ -145,12 +233,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);
}
}
}
@@ -167,26 +258,30 @@ led_blink (int spec)
eventflag_signal (&led_event, spec);
}
#ifdef FLASH_UPGRADE_SUPPORT
/*
* In Gnuk 1.0.[12], reGNUal was not relocatable.
* Now, it's relocatable, but we need to calculate its entry address
* based on it's pre-defined address.
*/
#define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
static uint32_t
static uintptr_t
calculate_regnual_entry_address (const uint8_t *addr)
{
const uint8_t *p = addr + 4;
uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
uintptr_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
v -= REGNUAL_START_ADDRESS_COMPATIBLE;
v += (uint32_t)addr;
v += (uintptr_t)addr;
return v;
}
#endif
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
#define STACK_ADDR_CCID ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_CCID ((uint32_t)__process1_stack_size__)
#define STACK_MAIN
#define STACK_PROCESS_1
#include "stack-def.h"
#define STACK_ADDR_CCID ((uintptr_t)process1_base)
#define STACK_SIZE_CCID (sizeof process1_base)
#define PRIO_CCID 3
#define PRIO_MAIN 5
@@ -202,18 +297,97 @@ extern uint32_t bDeviceState;
* Entry point.
*/
int
main (int argc, char *argv[])
main (int argc, const char *argv[])
{
uint32_t entry;
#ifdef GNU_LINUX_EMULATION
uintptr_t flash_addr;
const char *flash_image_path;
char *path_string = NULL;
#endif
#ifdef FLASH_UPGRADE_SUPPORT
uintptr_t entry;
#endif
chopstx_t ccid_thd;
int wait_for_ack = 0;
(void)argc;
(void)argv;
chopstx_conf_idle (1);
gnuk_malloc_init ();
#ifdef GNU_LINUX_EMULATION
#define FLASH_IMAGE_NAME ".gnuk-flash-image"
if (argc >= 4 || (argc == 2 && !strcmp (argv[1], "--help")))
{
fprintf (stdout, "Usage: %s [--vidpid=Vxxx:Pxxx] [flash-image-file]",
argv[0]);
exit (0);
}
if (argc >= 2 && !strncmp (argv[1], "--debug=", 8))
{
debug = strtol (&argv[1][8], NULL, 10);
argc--;
argv++;
}
if (argc >= 2 && !strncmp (argv[1], "--vidpid=", 9))
{
extern uint8_t device_desc[];
uint32_t id;
char *p;
id = (uint32_t)strtol (&argv[1][9], &p, 16);
device_desc[8] = (id & 0xff);
device_desc[9] = (id >> 8);
if (p && p[0] == ':')
{
id = (uint32_t)strtol (&p[1], NULL, 16);
device_desc[10] = (id & 0xff);
device_desc[11] = (id >> 8);
}
argc--;
argv++;
}
if (argc == 1)
{
char *p = getenv ("HOME");
if (p == NULL)
{
fprintf (stderr, "Can't find $HOME\n");
exit (1);
}
path_string = malloc (strlen (p) + strlen (FLASH_IMAGE_NAME) + 2);
p = stpcpy (path_string, p);
*p++ = '/';
strcpy (p, FLASH_IMAGE_NAME);
flash_image_path = path_string;
}
else
flash_image_path = argv[1];
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;
#else
(void)argc;
(void)argv;
#endif
flash_unlock ();
#ifdef GNU_LINUX_EMULATION
if (path_string)
free (path_string);
#else
device_initialize_once ();
#endif
adc_init ();
@@ -239,17 +413,23 @@ main (int argc, 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:
@@ -270,8 +450,11 @@ main (int argc, 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;
}
}
@@ -285,30 +468,15 @@ main (int argc, char *argv[])
/* Finish application. */
chopstx_join (ccid_thd, NULL);
#ifdef FLASH_UPGRADE_SUPPORT
/* Set vector */
SCB->VTOR = (uint32_t)&_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;
uint32_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_ADDR)&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);
@@ -318,6 +486,9 @@ main (int argc, char *argv[])
/* Leave Gnuk to exec reGNUal */
flash_erase_all_and_exec ((void (*)(void))entry);
#endif
#else
exit (0);
#endif
/* Never reached */
return 0;
@@ -348,30 +519,46 @@ fatal (uint8_t code)
* reclaimed to system.
*/
#ifdef GNU_LINUX_EMULATION
#define HEAP_SIZE (32*1024)
uint8_t __heap_base__[HEAP_SIZE];
#define HEAP_START __heap_base__
#define HEAP_END (__heap_base__ + HEAP_SIZE)
#define HEAP_ALIGNMENT 32
#else
extern uint8_t __heap_base__[];
extern uint8_t __heap_end__[];
#define MEMORY_END (__heap_end__)
#define MEMORY_ALIGNMENT 16
#define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
#define HEAP_START __heap_base__
#define HEAP_END (__heap_end__)
#define HEAP_ALIGNMENT 16
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#endif
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
static uint8_t *heap_p;
static chopstx_mutex_t malloc_mtx;
struct mem_head {
uint32_t size;
uintptr_t size;
/**/
struct mem_head *next, *prev; /* free list chain */
struct mem_head *neighbor; /* backlink to neighbor */
};
#define MEM_HEAD_IS_CORRUPT(x) \
((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;
static void
gnuk_malloc_init (void)
{
chopstx_mutex_init (&malloc_mtx);
heap_p = __heap_base__;
heap_p = HEAP_START;
free_list = NULL;
}
@@ -380,7 +567,7 @@ sbrk (size_t size)
{
void *p = (void *)heap_p;
if ((size_t)(MEMORY_END - heap_p) < size)
if ((size_t)(HEAP_END - heap_p) < size)
return NULL;
heap_p += size;
@@ -405,7 +592,7 @@ gnuk_malloc (size_t size)
struct mem_head *m;
struct mem_head *m0;
size = MEMORY_ALIGN (size + sizeof (uint32_t));
size = HEAP_ALIGN (size + sizeof (uintptr_t));
chopstx_mutex_lock (&malloc_mtx);
DEBUG_INFO ("malloc: ");
@@ -421,7 +608,7 @@ gnuk_malloc (size_t size)
m->size = size;
break;
}
MEM_HEAD_CHECK (m);
if (m->size == size)
{
remove_from_free_list (m);
@@ -445,8 +632,8 @@ gnuk_malloc (size_t size)
}
else
{
DEBUG_WORD ((uint32_t)m + sizeof (uint32_t));
return (void *)m + sizeof (uint32_t);
DEBUG_WORD ((uintptr_t)m + sizeof (uintptr_t));
return (void *)m + sizeof (uintptr_t);
}
}
@@ -454,18 +641,23 @@ gnuk_malloc (size_t size)
void
gnuk_free (void *p)
{
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uint32_t));
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uintptr_t));
struct mem_head *m0;
if (p == NULL)
return;
chopstx_mutex_lock (&malloc_mtx);
m0 = free_list;
DEBUG_INFO ("free: ");
DEBUG_SHORT (m->size);
DEBUG_WORD ((uint32_t)p);
DEBUG_WORD ((uintptr_t)p);
MEM_HEAD_CHECK (m);
m->neighbor = NULL;
while (m0)
{
MEM_HEAD_CHECK (m0);
if ((void *)m + m->size == (void *)m0)
m0->neighbor = m;
else if ((void *)m0 + m0->size == (void *)m)
@@ -481,6 +673,7 @@ gnuk_free (void *p)
heap_p -= m->size;
while (mn)
{
MEM_HEAD_CHECK (mn);
heap_p -= mn->size;
remove_from_free_list (mn);
mn = mn->neighbor;

32
src/mcu-stm32f103.c Normal file
View File

@@ -0,0 +1,32 @@
/*
* mcu-stm32f103.c - STM32F103 specific routines
*
* Copyright (C) 2017
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdint.h>
#include "mcu/stm32f103.h"
uint8_t *
sram_address (uint32_t offset)
{
return ((uint8_t *)0x20000000) + offset;
}

View File

@@ -36,7 +36,6 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
bn512 q_big[1], tmp[1];
uint32_t carry;
#define borrow carry
uint32_t borrow_next;
memset (q, 0, sizeof (bn256));
q->word[0] = A->word[15];
@@ -110,9 +109,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
= tmp->word[11] = tmp->word[10] = tmp->word[9] = 0;
borrow = bn256_sub (X, (bn256 *)&q_big->word[0], (bn256 *)&tmp->word[0]);
borrow_next = (q_big->word[8] < borrow);
q_big->word[8] -= borrow;
borrow_next += (q_big->word[8] < tmp->word[8]);
q_big->word[8] -= tmp->word[8];
carry = q_big->word[8];
@@ -122,7 +119,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
bn256_sub (q, X, B);
if (carry)
carry -= bn256_sub (X, X, B);
bn256_sub (X, X, B);
else
bn256_sub (q, X, B);
@@ -159,6 +156,7 @@ mod_inv (bn256 *C, const bn256 *X, const bn256 *N)
#define borrow carry
int n = MAX_GCD_STEPS_BN256;
memset (tmp, 0, sizeof (bn256));
memset (C, 0, sizeof (bn256));
memcpy (u, X, sizeof (bn256));
memcpy (v, N, sizeof (bn256));

View File

@@ -1,7 +1,7 @@
/*
* neug.c - true random number generation
*
* Copyright (C) 2011, 2012, 2013, 2016
* Copyright (C) 2011, 2012, 2013, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -29,10 +29,133 @@
#include "sys.h"
#include "neug.h"
#ifndef GNU_LINUX_EMULATION
#include "mcu/stm32f103.h"
#endif
#include "adc.h"
#include "sha256.h"
#ifdef GNU_LINUX_EMULATION
static const uint32_t crc32_rv_table[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
static uint32_t crc;
void
crc32_rv_reset (void)
{
crc = 0xffffffff;
}
void
crc32_rv_step (uint32_t v)
{
crc = crc32_rv_table[(crc ^ (v << 0)) >> 24] ^ (crc << 8);
crc = crc32_rv_table[(crc ^ (v << 8)) >> 24] ^ (crc << 8);
crc = crc32_rv_table[(crc ^ (v << 16)) >> 24] ^ (crc << 8);
crc = crc32_rv_table[(crc ^ (v << 24)) >> 24] ^ (crc << 8);
}
uint32_t
crc32_rv_get (void)
{
return crc;
}
uint32_t
rbit (uint32_t v)
{
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
v = ( v >> 16 ) | ( v << 16);
return v;
}
void
crc32_rv_stop (void)
{
}
#else
void
crc32_rv_reset (void)
{
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
}
void
crc32_rv_step (uint32_t v)
{
CRC->DR = v;
}
uint32_t
crc32_rv_get (void)
{
return CRC->DR;
}
uint32_t
rbit (uint32_t v)
{
uint32_t r;
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;
static chopstx_cond_t mode_cond;
@@ -94,11 +217,11 @@ static void noise_source_continuous_test_word (uint8_t b0, uint8_t b1,
* Then, three-byte from noise source follows.
*
* One-byte was used in the previous turn, and we have three bytes in
* CRC->DR.
* CRC32.
*/
static void ep_fill_initial_string (void)
{
uint32_t v = CRC->DR;
uint32_t v = crc32_rv_get ();
uint8_t b1, b2, b3;
b3 = v >> 24;
@@ -164,11 +287,11 @@ static int ep_process (int mode)
sha256_ctx_data.wbuf[1] = adc_buf[1];
for (i = 0; i < EP_ROUND_0_INPUTS / 4; i++)
{
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
CRC->DR = adc_buf[i*4 + 4];
CRC->DR = adc_buf[i*4 + 5];
v = CRC->DR;
crc32_rv_step (adc_buf[i*4 + 2]);
crc32_rv_step (adc_buf[i*4 + 3]);
crc32_rv_step (adc_buf[i*4 + 4]);
crc32_rv_step (adc_buf[i*4 + 5]);
v = crc32_rv_get ();
ep_fill_wbuf_v (i+2, 1, v);
}
@@ -181,11 +304,11 @@ static int ep_process (int mode)
{
for (i = 0; i < EP_ROUND_1_INPUTS / 4; i++)
{
CRC->DR = adc_buf[i*4];
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR;
crc32_rv_step (adc_buf[i*4]);
crc32_rv_step (adc_buf[i*4 + 1]);
crc32_rv_step (adc_buf[i*4 + 2]);
crc32_rv_step (adc_buf[i*4 + 3]);
v = crc32_rv_get ();
ep_fill_wbuf_v (i, 1, v);
}
@@ -198,23 +321,23 @@ static int ep_process (int mode)
{
for (i = 0; i < EP_ROUND_2_INPUTS / 4; i++)
{
CRC->DR = adc_buf[i*4];
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR;
crc32_rv_step (adc_buf[i*4]);
crc32_rv_step (adc_buf[i*4 + 1]);
crc32_rv_step (adc_buf[i*4 + 2]);
crc32_rv_step (adc_buf[i*4 + 3]);
v = crc32_rv_get ();
ep_fill_wbuf_v (i, 1, v);
}
CRC->DR = adc_buf[i*4];
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR & 0xff; /* First byte of CRC->DR is used here. */
crc32_rv_step (adc_buf[i*4]);
crc32_rv_step (adc_buf[i*4 + 1]);
crc32_rv_step (adc_buf[i*4 + 2]);
crc32_rv_step (adc_buf[i*4 + 3]);
v = crc32_rv_get () & 0xff; /* First byte of CRC32 is used here. */
noise_source_continuous_test (v);
sha256_ctx_data.wbuf[i] = v;
ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
CRC->DR is used here. */
CRC32 is used here. */
n = SHA256_DIGEST_SIZE / 2;
memcpy (((uint8_t *)sha256_ctx_data.wbuf) + EP_ROUND_2_INPUTS,
sha256_output, n);
@@ -226,11 +349,11 @@ static int ep_process (int mode)
{
for (i = 0; i < EP_ROUND_RAW_INPUTS / 4; i++)
{
CRC->DR = adc_buf[i*4];
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR;
crc32_rv_step (adc_buf[i*4]);
crc32_rv_step (adc_buf[i*4 + 1]);
crc32_rv_step (adc_buf[i*4 + 2]);
crc32_rv_step (adc_buf[i*4 + 3]);
v = crc32_rv_get ();
ep_fill_wbuf_v (i, 1, v);
}
@@ -640,9 +763,11 @@ rng (void *arg)
static struct rng_rb the_ring_buffer;
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
#define STACK_ADDR_RNG ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_RNG ((uint32_t)__process2_stack_size__)
#define STACK_PROCESS_2
#include "stack-def.h"
#define STACK_ADDR_RNG ((uintptr_t)process2_base)
#define STACK_SIZE_RNG (sizeof process2_base)
#define PRIO_RNG 2
/**
@@ -655,15 +780,14 @@ neug_init (uint32_t *buf, uint8_t size)
struct rng_rb *rb = &the_ring_buffer;
int i;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
crc32_rv_reset ();
/*
* This initialization ensures that it generates different sequence
* even if all physical conditions are same.
*/
for (i = 0; i < 3; i++)
CRC->DR = *u++;
crc32_rv_step (*u++);
neug_mode = NEUG_MODE_CONDITIONED;
rb_init (rb, buf, size);
@@ -781,6 +905,7 @@ neug_fini (void)
rng_should_terminate = 1;
neug_get (1);
chopstx_join (rng_thread, NULL);
crc32_rv_stop ();
}
void

View File

@@ -26,3 +26,8 @@ void neug_fini (void);
void neug_mode_select (uint8_t mode);
int neug_consume_random (void (*proc) (uint32_t, int));
void crc32_rv_reset (void);
void crc32_rv_step (uint32_t v);
uint32_t crc32_rv_get (void);
uint32_t rbit (uint32_t v);

View File

@@ -1,7 +1,7 @@
/*
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
@@ -40,7 +39,7 @@
#define CLEAN_PAGE_FULL 1
#define CLEAN_SINGLE 0
static void gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full);
static void gpg_reset_digital_signature_counter (void);
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
static const uint8_t *pw_err_counter_p[3];
@@ -113,13 +112,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 */
@@ -134,6 +135,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
@@ -250,6 +259,28 @@ gpg_get_algo_attr (enum kind_of_key kk)
return algo_attr_p[1];
}
static void
gpg_reset_algo_attr (enum kind_of_key kk)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
}
static const uint8_t *
get_algo_attr_data_object (enum kind_of_key kk)
{
@@ -336,7 +367,7 @@ gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc)
else
{
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
hw1 = NR_COUNTER_DS_LSB;
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
flash_put_data_internal (p, hw0);
flash_put_data_internal (p+2, hw1);
return p+4;
@@ -431,12 +462,17 @@ 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_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__];
@@ -473,6 +509,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;
}
@@ -619,7 +657,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;
@@ -749,47 +787,15 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
return 0; /* Error. */
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
gpg_reset_algo_attr (kk);
flash_enum_clear (algo_attr_pp);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
if (*algo_attr_pp != NULL)
return 0;
}
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL)
|| (*algo_attr_pp)[1] != algo)
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL) ||
(*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo))
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
gpg_reset_algo_attr (kk);
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
if (*algo_attr_pp == NULL)
return 0;
@@ -809,6 +815,215 @@ 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;
}
}
int
gpg_do_kdf_check (int len, int how_many)
{
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
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)
{
@@ -822,31 +1037,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);
@@ -858,7 +1087,7 @@ encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
{
aes_context aes;
uint8_t iv0[INITIAL_VECTOR_SIZE];
unsigned int iv_offset;
size_t iv_offset;
DEBUG_INFO ("ENC\r\n");
DEBUG_BINARY (data, len);
@@ -877,7 +1106,7 @@ decrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
{
aes_context aes;
uint8_t iv0[INITIAL_VECTOR_SIZE];
unsigned int iv_offset;
size_t iv_offset;
aes_setkey_enc (&aes, key, 128); /* This is setkey_enc, because of CFB. */
memcpy (iv0, iv, INITIAL_VECTOR_SIZE);
@@ -1093,14 +1322,16 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
int attr = gpg_get_algo_attr (kk);;
const uint8_t *p;
int r;
struct prvkey_data *pd;
struct prvkey_data prv;
struct prvkey_data *pd = &prv;
uint8_t *key_addr;
const uint8_t *dek, *iv;
struct key_data_internal kdi;
uint8_t *pubkey_allocated_here = NULL;
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);
@@ -1108,10 +1339,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
/* Delete it first, if any. */
gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
if (pd == NULL)
return -1;
if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
pubkey_len = prvkey_len * 2;
@@ -1139,38 +1366,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
return -1;
}
if (pubkey == NULL)
{
if (attr == ALGO_SECP256K1)
pubkey_allocated_here = ecc_compute_public_p256k1 (key_data);
else if (attr == ALGO_NISTP256R1)
pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
else if (attr == ALGO_ED25519)
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
else if (attr == ALGO_CURVE25519)
pubkey_allocated_here = ecdh_compute_public_25519 (key_data);
else /* RSA */
pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
if (pubkey_allocated_here == NULL)
{
free (pd);
return -1;
}
}
DEBUG_INFO ("Getting keystore address...\r\n");
key_addr = flash_key_alloc (kk);
if (key_addr == NULL)
{
if (pubkey_allocated_here)
{
memset (pubkey_allocated_here, 0, pubkey_len);
free (pubkey_allocated_here);
}
free (pd);
return -1;
}
return -1;
kd[kk].pubkey = key_addr + prvkey_len;
num_prv_keys++;
@@ -1189,8 +1389,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);
@@ -1206,19 +1406,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len,
pubkey_allocated_here? pubkey_allocated_here: pubkey,
pubkey_len);
if (pubkey_allocated_here)
{
memset (pubkey_allocated_here, 0, pubkey_len);
free (pubkey_allocated_here);
}
pubkey, pubkey_len);
if (r < 0)
{
random_bytes_free (dek);
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
return r;
}
@@ -1240,7 +1432,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
random_bytes_free (dek);
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
if (p == NULL)
return -1;
@@ -1272,18 +1463,15 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
uint8_t nr = get_do_ptr_nr_for_kk (kk);
const uint8_t *do_data = do_ptr[nr];
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
struct prvkey_data *pd;
const uint8_t *p;
struct prvkey_data prv;
struct prvkey_data *pd = &prv;
uint8_t *dek_p;
int update_needed = 0;
int r = 1; /* Success */
if (do_data == NULL)
return 0; /* No private key */
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
if (pd == NULL)
return -1;
memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE
@@ -1314,18 +1502,19 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
if (update_needed)
{
const uint8_t *p;
flash_do_release (do_data);
do_ptr[nr] = NULL;
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr] = p;
if (p == NULL)
r = -1;
}
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
if (update_needed && p == NULL)
return -1;
return 1;
return r;
}
@@ -1380,6 +1569,7 @@ proc_key_import (const uint8_t *data, int len)
const uint8_t *keystring_admin;
int attr;
const uint8_t *p = data;
uint8_t pubkey[512];
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
@@ -1419,13 +1609,35 @@ proc_key_import (const uint8_t *data, int len)
}
if (attr == ALGO_RSA2K)
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
{
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = modulus_calc (&data[26], len - 26, pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin,
pubkey);
}
else if (attr == ALGO_RSA4K)
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, NULL);
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
{
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = modulus_calc (&data[28], len - 28, pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin,
pubkey);
}
else if (attr == ALGO_NISTP256R1)
{
r = ecc_compute_public_p256r1 (&data[12], pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
pubkey);
}
else if (attr == ALGO_SECP256K1)
{
r = ecc_compute_public_p256k1 (&data[12], pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
pubkey);
}
else if (attr == ALGO_ED25519)
{
uint8_t hash[64];
@@ -1437,7 +1649,8 @@ proc_key_import (const uint8_t *data, int len)
hash[0] &= 248;
hash[31] &= 127;
hash[31] |= 64;
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
eddsa_compute_public_25519 (hash, pubkey);
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, pubkey);
}
else if (attr == ALGO_CURVE25519)
{
@@ -1449,7 +1662,8 @@ proc_key_import (const uint8_t *data, int len)
for (i = 0; i < 32; i++)
priv[31-i] = data[12+i];
r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, NULL);
ecdh_compute_public_25519 (priv, pubkey);
r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, pubkey);
}
if (r < 0)
@@ -1466,18 +1680,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 };
@@ -1516,9 +1744,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 },
@@ -1543,7 +1781,7 @@ gpg_do_table[] = {
* Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc.
*/
void
gpg_data_scan (const uint8_t *p_start)
gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
{
const uint8_t *p;
int i;
@@ -1556,10 +1794,20 @@ gpg_data_scan (const uint8_t *p_start)
pw_err_counter_p[PW_ERR_RC] = NULL;
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)
return;
/* Traverse DO, counters, etc. in DATA pool */
p = p_start;
while (p && *p != NR_EMPTY)
p = do_start;
while (p < do_end && *p != NR_EMPTY)
{
uint8_t nr = *p++;
uint8_t second_byte = *p;
@@ -1571,10 +1819,12 @@ gpg_data_scan (const uint8_t *p_start)
if (nr < 0x80)
{
/* It's Data Object */
do_ptr[nr] = p;
if (nr < NR_DO__LAST__)
do_ptr[nr] = p;
p += second_byte + 1; /* second_byte has length */
if (((uint32_t)p & 1))
if (((uintptr_t)p & 1))
p++;
}
else if (nr >= 0x80 && nr <= 0xbf)
@@ -1608,6 +1858,13 @@ gpg_data_scan (const uint8_t *p_start)
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)
@@ -1707,6 +1964,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)
@@ -2079,44 +2343,37 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
}
void
gpg_do_keygen (uint8_t kk_byte)
gpg_do_keygen (uint8_t *buf)
{
uint8_t kk_byte = buf[0];
enum kind_of_key kk = kkb_to_kk (kk_byte);
int attr = gpg_get_algo_attr (kk);;
int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE);
const uint8_t *keystring_admin;
uint8_t *p_q_modulus = NULL;
uint8_t d[64];
const uint8_t *rnd;
const uint8_t *prv;
const uint8_t *pubkey;
int r;
const uint8_t *rnd;
int r = 0;
#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);
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
else
keystring_admin = NULL;
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
p_q_modulus = rsa_genkey (prvkey_len);
if (p_q_modulus == NULL)
if (rsa_genkey (prvkey_len, pubkey, p_q) < 0)
{
GPG_MEMORY_FAILURE ();
return;
}
prv = p_q_modulus;
pubkey = p_q_modulus + prvkey_len;
prv = p_q;
}
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
uint8_t d1[32];
const uint8_t *p;
int i, r;
int i;
rnd = NULL;
do
@@ -2143,7 +2400,10 @@ gpg_do_keygen (uint8_t kk_byte)
random_bytes_free (rnd);
prv = d;
pubkey = NULL;
if (attr == ALGO_SECP256K1)
r = ecc_compute_public_p256k1 (prv, pubkey);
else if (attr == ALGO_NISTP256R1)
r = ecc_compute_public_p256r1 (prv, pubkey);
}
else if (attr == ALGO_ED25519)
{
@@ -2154,7 +2414,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
eddsa_compute_public_25519 (d, pubkey);
}
else if (attr == ALGO_CURVE25519)
{
@@ -2165,7 +2425,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
ecdh_compute_public_25519 (prv, pubkey);
}
else
{
@@ -2173,12 +2433,21 @@ gpg_do_keygen (uint8_t kk_byte)
return;
}
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
if (p_q_modulus)
if (r >= 0)
{
memset (p_q_modulus, 0, prvkey_len * 2);
free (p_q_modulus);
const uint8_t *keystring_admin;
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
else
keystring_admin = NULL;
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
}
/* Clear private key data in the buffer. */
memset (buf, 0, 256);
if (r < 0)
{
GPG_ERROR ();
@@ -2189,14 +2458,16 @@ gpg_do_keygen (uint8_t kk_byte)
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
* 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]
@@ -98,7 +100,6 @@ set_res_sw (uint8_t sw1, uint8_t sw2)
#define FILE_EF_UPDATE_KEY_2 7
#define FILE_EF_UPDATE_KEY_3 8
#define FILE_EF_CH_CERTIFICATE 9
#define FILE_CARD_TERMINATED_OPENPGP 254
#define FILE_CARD_TERMINATED 255
uint8_t file_selection;
@@ -106,17 +107,18 @@ uint8_t file_selection;
static void
gpg_init (void)
{
const uint8_t *flash_data_start;
const uint8_t *flash_do_start;
const uint8_t *flash_do_end;
flash_data_start = flash_init ();
flash_do_storage_init (&flash_do_start, &flash_do_end);
if (flash_data_start == NULL)
if (flash_do_start == NULL)
file_selection = FILE_CARD_TERMINATED;
else
file_selection = FILE_NONE;
gpg_data_scan (flash_data_start);
flash_init_keys ();
gpg_data_scan (flash_do_start, flash_do_end);
flash_key_storage_init ();
}
static void
@@ -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;
@@ -506,6 +564,7 @@ cmd_reset_user_password (void)
const uint8_t *salt;
int salt_len;
(void)ccid_comm;
DEBUG_INFO ("Reset PW1\r\n");
DEBUG_BYTE (p1);
@@ -516,6 +575,13 @@ 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];
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (gpg_do_kdf_check (len, 2) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
if (gpg_pw_locked (PW_ERR_RC))
{
@@ -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,6 +657,12 @@ cmd_reset_user_password (void)
return;
}
if (gpg_do_kdf_check (len, 1) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
newpw_len = len;
newpw = pw;
random_get_salt (new_salt);
@@ -617,12 +699,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 +715,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,10 +728,11 @@ cmd_pgp_gakp (void)
{
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
GPG_SECURITY_FAILURE ();
gpg_do_keygen (apdu.cmd_apdu_data[0]);
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
}
}
#ifdef FLASH_UPGRADE_SUPPORT
const uint8_t *
gpg_get_firmware_update_key (uint8_t keyno)
{
@@ -657,6 +742,7 @@ gpg_get_firmware_update_key (uint8_t keyno)
p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
return p;
}
#endif
#ifdef CERTDO_SUPPORT
#define FILEID_CH_CERTIFICATE_IS_VALID 1
@@ -665,13 +751,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;
const uint8_t *p;
uint16_t offset;
(void)ccid_comm;
DEBUG_INFO (" - Read binary\r\n");
if (is_short_EF)
@@ -679,13 +765,6 @@ cmd_read_binary (void)
else
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
if ((!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE)
|| file_id > FILEID_CH_CERTIFICATE)
{
GPG_NO_FILE ();
return;
}
if (is_short_EF)
{
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
@@ -705,22 +784,26 @@ cmd_read_binary (void)
}
return;
}
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
#ifdef FLASH_UPGRADE_SUPPORT
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
{
if (offset != 0)
GPG_MEMORY_FAILURE ();
else
{
const uint8_t *p;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN);
GPG_SUCCESS ();
}
}
#endif
#if defined(CERTDO_SUPPORT)
else /* file_id == FILEID_CH_CERTIFICATE */
else if (file_id == FILEID_CH_CERTIFICATE)
{
const uint8_t *p;
uint16_t len = 256;
p = &ch_certificate_start;
@@ -737,11 +820,17 @@ cmd_read_binary (void)
}
}
#endif
else
{
GPG_NO_FILE ();
return;
}
}
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");
@@ -759,8 +848,7 @@ cmd_select_file (void)
if (file_selection == FILE_CARD_TERMINATED)
{
file_selection = FILE_CARD_TERMINATED_OPENPGP;
GPG_APPLICATION_TERMINATED();
GPG_APPLICATION_TERMINATED ();
return;
}
@@ -811,10 +899,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);
@@ -829,7 +918,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;
@@ -856,6 +945,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 */
@@ -947,6 +1041,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 */
@@ -1023,7 +1124,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,
@@ -1053,6 +1154,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)
@@ -1201,6 +1309,7 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
return;
}
#ifdef FLASH_UPGRADE_SUPPORT
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3
&& len == 0 && offset == 0)
{
@@ -1217,9 +1326,10 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
if (i == 4) /* all update keys are removed */
{
p = gpg_get_firmware_update_key (0);
flash_erase_page ((uint32_t)p);
flash_erase_page ((uintptr_t)p);
}
}
#endif
GPG_SUCCESS ();
}
@@ -1227,10 +1337,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");
@@ -1239,18 +1350,20 @@ 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");
}
#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;
@@ -1258,6 +1371,7 @@ cmd_external_authenticate (void)
uint8_t keyno = P2 (apdu);
int r;
(void)ccid_comm;
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
if (keyno >= 4)
@@ -1290,12 +1404,14 @@ cmd_external_authenticate (void)
set_res_sw (0xff, 0xff);
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
}
#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)
@@ -1310,6 +1426,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;
@@ -1320,11 +1443,12 @@ cmd_get_challenge (void)
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
static void
cmd_activate_file (void)
cmd_activate_file (struct eventflag *ccid_comm)
{
if (file_selection != FILE_CARD_TERMINATED_OPENPGP)
(void)ccid_comm;
if (file_selection != FILE_CARD_TERMINATED)
{
GPG_NO_RECORD();
GPG_NO_RECORD ();
return;
}
@@ -1334,14 +1458,16 @@ 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();
GPG_NO_RECORD ();
return;
}
@@ -1357,8 +1483,11 @@ cmd_terminate_df (void)
return;
}
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (!ac_check_status (AC_ADMIN_AUTHORIZED) && !gpg_pw_locked (PW_ERR_PW3))
if (!ac_check_status (AC_ADMIN_AUTHORIZED)
&& !((ks_pw3 && gpg_pw_locked (PW_ERR_PW3))
|| (ks_pw3 == NULL && gpg_pw_locked (PW_ERR_PW1))))
{
/* Only allow the case admin authorized, or, admin pass is locked. */
GPG_SECURITY_FAILURE();
@@ -1379,7 +1508,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[] = {
@@ -1391,8 +1520,10 @@ const struct command cmds[] = {
{ INS_ACTIVATE_FILE, cmd_activate_file },
#endif
{ INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
#ifdef FLASH_UPGRADE_SUPPORT
{ INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */
cmd_external_authenticate },
#endif
{ INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */
{ INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
{ INS_SELECT_FILE, cmd_select_file },
@@ -1411,7 +1542,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);
@@ -1425,17 +1556,17 @@ process_command_apdu (void)
if (file_selection == FILE_CARD_TERMINATED
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE)
GPG_APPLICATION_TERMINATED();
GPG_APPLICATION_TERMINATED ();
else if (file_selection != FILE_DF_OPENPGP
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE
&& cmd != INS_WRITE_BINARY && cmd != INS_UPDATE_BINARY
&& cmd != INS_READ_BINARY)
GPG_NO_RECORD();
GPG_NO_RECORD ();
else
{
chopstx_setcancelstate (1);
cmds[i].cmd_handler ();
cmds[i].cmd_handler (ccid_comm);
chopstx_setcancelstate (0);
}
}
@@ -1549,7 +1680,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;
}
@@ -964,9 +964,14 @@ cir_timer_interrupt (void)
}
extern uint8_t __process6_stack_base__[], __process6_stack_size__[];
#define STACK_ADDR_TIM ((uint32_t)__process6_stack_base__)
#define STACK_SIZE_TIM ((uint32_t)__process6_stack_size__)
#define STACK_PROCESS_6
#define STACK_PROCESS_7
#include "stack-def.h"
#define STACK_ADDR_TIM ((uintptr_t)process6_base)
#define STACK_SIZE_TIM (sizeof process6_base)
#define STACK_ADDR_EXT ((uintptr_t)process7_base)
#define STACK_SIZE_EXT (sizeof process7_base)
#define PRIO_TIM 4
static void *
@@ -981,14 +986,13 @@ tim_main (void *arg)
{
chopstx_intr_wait (&interrupt);
cir_timer_interrupt ();
chopstx_intr_done (&interrupt);
}
return NULL;
}
extern uint8_t __process7_stack_base__, __process7_stack_size__;
const uint32_t __stackaddr_ext = (uint32_t)&__process7_stack_base__;
const size_t __stacksize_ext = (size_t)&__process7_stack_size__;
#define PRIO_EXT 4
static void *
@@ -1003,6 +1007,7 @@ ext_main (void *arg)
{
chopstx_intr_wait (&interrupt);
cir_ext_interrupt ();
chopstx_intr_done (&interrupt);
}
return NULL;
@@ -1030,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

@@ -47,7 +47,6 @@
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "sha256.h"
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)

View File

@@ -32,7 +32,6 @@
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "sha512.h"
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)

65
src/stack-def.h Normal file
View File

@@ -0,0 +1,65 @@
#ifdef GNU_LINUX_EMULATION
#define SIZE_1 4096
#define SIZE_2 4096
#define SIZE_3 (5 * 4096)
#else
#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) */
#define SIZE_7 0x00c0 /* ext (cir) */
#endif
#if defined(STACK_MAIN) && !defined(GNU_LINUX_EMULATION)
/* Idle+Exception handlers */
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
char main_base[0x0080] __attribute__ ((section(".main_stack")));
/* Main program */
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0")));
#endif
/* First thread program */
#if defined(STACK_PROCESS_1)
char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1")));
#endif
/* Second thread program */
#if defined(STACK_PROCESS_2)
char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2")));
#endif
/* Third thread program */
#if defined(STACK_PROCESS_3)
char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3")));
#endif
/* Fourth thread program */
#if defined(STACK_PROCESS_4)
char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4")));
#endif
/* Fifth thread program */
#if defined(STACK_PROCESS_5)
char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5")));
#endif
/* Sixth thread program */
#if defined(STACK_PROCESS_6)
char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6")));
#endif
/* Seventh thread program */
#if defined(STACK_PROCESS_7)
char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7")));
#endif

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,13 +0,0 @@
/*
* stdlib.h replacement to replace malloc functions
*/
typedef unsigned int size_t;
#include <stddef.h> /* NULL */
#define malloc(size) gnuk_malloc (size)
#define free(p) gnuk_free (p)
void *gnuk_malloc (size_t);
void gnuk_free (void *);

File diff suppressed because it is too large Load Diff

View File

@@ -31,9 +31,11 @@
#include "usb_lld.h"
#include "usb-msc.h"
extern uint8_t __process5_stack_base__[], __process5_stack_size__[];
#define STACK_ADDR_MSC ((uint32_t)__process5_stack_base__)
#define STACK_SIZE_MSC ((uint32_t)__process5_stack_size__)
#define STACK_PROCESS_5
#include "stack-def.h"
#define STACK_ADDR_MSC ((uintptr_t)process5_base)
#define STACK_SIZE_MSC (sizeof process5_base)
#define PRIO_MSC 3
static chopstx_mutex_t a_pinpad_mutex;

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
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -38,7 +38,7 @@
#include "usb_lld.h"
#include "usb_conf.h"
#include "gnuk.h"
#include "mcu/stm32f103.h"
#include "neug.h"
#ifdef ENABLE_VIRTUAL_COM_PORT
#include "usb-cdc.h"
@@ -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
@@ -108,15 +108,25 @@ static uint16_t hid_report;
#endif
static void
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
gnuk_setup_endpoints_for_interface (struct usb_dev *dev,
uint16_t interface, int stop)
{
#if !defined(GNU_LINUX_EMULATION)
(void)dev;
#endif
if (interface == CCID_INTERFACE)
{
if (!stop)
{
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP1, 1, 1);
usb_lld_setup_endp (dev, ENDP2, 0, 1);
#else
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR,
ENDP1_TXADDR, GNUK_MAX_PACKET_SIZE);
usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
#endif
}
else
{
@@ -129,7 +139,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == HID_INTERFACE)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP7, 0, 1);
#else
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
#endif
else
usb_lld_stall_tx (ENDP7);
}
@@ -138,7 +152,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == VCOM_INTERFACE_0)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP4, 0, 1);
#else
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
#endif
else
usb_lld_stall_tx (ENDP4);
}
@@ -146,9 +164,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
{
if (!stop)
{
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP3, 0, 1);
usb_lld_setup_endp (dev, ENDP5, 1, 0);
#else
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0);
usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0,
VIRTUAL_COM_PORT_DATA_SIZE);
#endif
}
else
{
@@ -161,8 +184,12 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == MSC_INTERFACE)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP6, 1, 1);
#else
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
ENDP6_RXADDR, ENDP6_TXADDR, 64);
#endif
else
{
usb_lld_stall_tx (ENDP6);
@@ -175,20 +202,17 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
void
usb_device_reset (struct usb_dev *dev)
{
int i;
usb_lld_reset (dev, USB_INITIAL_FEATURE);
/* Initialize Endpoint 0 */
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP0, 1, 1);
#else
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
GNUK_MAX_PACKET_SIZE);
64);
#endif
/* Stop the interface */
for (i = 0; i < NUM_INTERFACES; i++)
gnuk_setup_endpoints_for_interface (i, 1);
bDeviceState = ATTACHED;
ccid_usb_reset (1);
bDeviceState = USB_DEVICE_STATE_DEFAULT;
}
#define USB_CCID_REQ_ABORT 0x01
@@ -202,38 +226,34 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
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__, };
#endif
#define USB_FSIJ_GNUK_MEMINFO 0
#define USB_FSIJ_GNUK_DOWNLOAD 1
#define USB_FSIJ_GNUK_EXEC 2
#define USB_FSIJ_GNUK_CARD_CHANGE 3
static uint32_t rbit (uint32_t v)
{
uint32_t r;
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
return r;
}
#ifdef FLASH_UPGRADE_SUPPORT
/* After calling this function, CRC module remain enabled. */
static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
static int
download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
{
uint32_t crc32 = *end_p;
const uint32_t *p;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
crc32_rv_reset ();
for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
CRC->DR = rbit (*p);
crc32_rv_step (rbit (*p));
if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
return usb_lld_ctrl_ack (dev);
return -1;
}
#endif
int
usb_setup (struct usb_dev *dev)
@@ -245,17 +265,23 @@ usb_setup (struct usb_dev *dev)
{
if (USB_SETUP_GET (arg->type))
{
#ifdef FLASH_UPGRADE_SUPPORT
if (arg->request == USB_FSIJ_GNUK_MEMINFO)
return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
#else
return -1;
#endif
}
else /* SETUP_SET */
{
uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100
+ arg->index);
#ifdef FLASH_UPGRADE_SUPPORT
uint8_t *addr = sram_address ((arg->value * 0x100) + arg->index);
#endif
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
{
if (*ccid_state_p != CCID_STATE_EXITED)
#ifdef FLASH_UPGRADE_SUPPORT
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
return -1;
if (addr < &_regnual_start || addr + arg->len > __heap_end__)
@@ -266,16 +292,23 @@ usb_setup (struct usb_dev *dev)
256 - (arg->index + arg->len));
return usb_lld_ctrl_recv (dev, addr, arg->len);
#else
return -1;
#endif
}
else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0)
{
if (*ccid_state_p != CCID_STATE_EXITED)
#ifdef FLASH_UPGRADE_SUPPORT
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
return -1;
if (((uint32_t)addr & 0x03))
if (((uintptr_t)addr & 0x03))
return -1;
return download_check_crc32 (dev, (uint32_t *)addr);
#else
return -1;
#endif
}
else if (arg->request == USB_FSIJ_GNUK_CARD_CHANGE && arg->len == 0)
{
@@ -371,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. */
}
@@ -435,8 +468,8 @@ 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 (i, 0);
bDeviceState = CONFIGURED;
gnuk_setup_endpoints_for_interface (dev, i, 0);
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
}
else if (current_conf != dev->dev_req.value)
{
@@ -445,9 +478,8 @@ 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 (i, 1);
bDeviceState = ADDRESSED;
ccid_usb_reset (1);
gnuk_setup_endpoints_for_interface (dev, i, 1);
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
}
/* Do nothing when current_conf == value */
@@ -468,8 +500,7 @@ usb_set_interface (struct usb_dev *dev)
return -1;
else
{
gnuk_setup_endpoints_for_interface (interface, 0);
ccid_usb_reset (0);
gnuk_setup_endpoints_for_interface (dev, interface, 0);
return usb_lld_ctrl_ack (dev);
}
}

View File

@@ -59,15 +59,20 @@ static const uint8_t hid_report_desc[] = {
#define USB_CCID_DATA_SIZE 64
/* USB Standard Device Descriptor */
static const uint8_t device_desc[] = {
#if !defined(GNU_LINUX_EMULATION)
static const
#endif
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
@@ -24,4 +24,4 @@ Feature: command GET DATA
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00

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
@@ -24,4 +24,4 @@ Feature: command GET DATA
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00

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
@@ -24,4 +24,4 @@ Feature: command GET DATA
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00

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:

4
tests/card_const.py Normal file
View File

@@ -0,0 +1,4 @@
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"

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 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -179,9 +179,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

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"

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
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,83 @@ 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
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""
@@ -336,3 +414,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

@@ -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)
@@ -146,7 +144,7 @@ def test_historical_bytes(card):
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

@@ -1,7 +1,7 @@
"""
test_personalize_card.py - test personalizing 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,25 +24,15 @@ 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"
from card_const import *
from constants_for_test import *
def test_setup_pw3_0(card):
r = card.cmd_change_reference_data(3, FACTORY_PASSPHRASE_PW3 + PW3_TEST0)
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, PW3_TEST0)
assert r
def test_verify_pw3_0(card):
v = card.cmd_verify(3, PW3_TEST0)
v = card.verify(3, PW3_TEST0)
assert v
def test_login_put(card):
@@ -164,89 +154,85 @@ def test_public_key_3(card):
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)
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
assert r
def test_verify_pw1_0(card):
v = card.cmd_verify(1, PW1_TEST0)
v = card.verify(1, PW1_TEST0)
assert v
def test_verify_pw1_0_2(card):
v = card.cmd_verify(2, PW1_TEST0)
v = card.verify(2, PW1_TEST0)
assert v
def test_setup_pw1_1(card):
r = card.cmd_change_reference_data(1, PW1_TEST0 + PW1_TEST1)
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
assert r
def test_verify_pw1_1(card):
v = card.cmd_verify(1, PW1_TEST1)
v = card.verify(1, PW1_TEST1)
assert v
def test_verify_pw1_1_2(card):
v = card.cmd_verify(2, PW1_TEST1)
v = card.verify(2, PW1_TEST1)
assert v
def test_setup_reset_code(card):
r = card.cmd_put_data(0x00, 0xd3, RESETCODE_TEST)
r = card.setup_reset_code(RESETCODE_TEST)
assert r
def test_reset_code(card):
r = card.cmd_reset_retry_counter(0, 0x81, RESETCODE_TEST + PW1_TEST2)
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
assert r
def test_verify_pw1_2(card):
v = card.cmd_verify(1, PW1_TEST2)
v = card.verify(1, PW1_TEST2)
assert v
def test_verify_pw1_2_2(card):
v = card.cmd_verify(2, PW1_TEST2)
v = card.verify(2, PW1_TEST2)
assert v
def test_setup_pw3_1(card):
r = card.cmd_change_reference_data(3, PW3_TEST0 + PW3_TEST1)
r = card.change_passwd(3, PW3_TEST0, PW3_TEST1)
assert r
def test_verify_pw3_1(card):
v = card.cmd_verify(3, PW3_TEST1)
v = card.verify(3, PW3_TEST1)
assert v
def test_reset_userpass_admin(card):
r = card.cmd_reset_retry_counter(2, 0x81, PW1_TEST3)
r = card.reset_passwd_by_admin(PW1_TEST3)
assert r
def test_verify_pw1_3(card):
v = card.cmd_verify(1, PW1_TEST3)
v = card.verify(1, PW1_TEST3)
assert v
def test_verify_pw1_3_2(card):
v = card.cmd_verify(2, PW1_TEST3)
v = card.verify(2, PW1_TEST3)
assert v
def test_setup_pw1_4(card):
r = card.cmd_change_reference_data(1, PW1_TEST3 + PW1_TEST4)
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
assert r
def test_verify_pw1_4(card):
v = card.cmd_verify(1, PW1_TEST4)
v = card.verify(1, PW1_TEST4)
assert v
def test_verify_pw1_4_2(card):
v = card.cmd_verify(2, PW1_TEST4)
v = card.verify(2, PW1_TEST4)
assert v
def test_setup_pw3_2(card):
r = card.cmd_change_reference_data(3, PW3_TEST1 + PW3_TEST0)
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
assert r
def test_verify_pw3_2(card):
v = card.cmd_verify(3, PW3_TEST0)
v = card.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)

View File

@@ -1,7 +1,7 @@
"""
test_personalize_reset_card.py - test resetting personalization of card
test_personalize_reset.py - test resetting personalization of 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,18 +24,8 @@ 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"
from card_const import *
from constants_for_test import *
def test_login_put(card):
r = card.cmd_put_data(0x00, 0x5e, b"")
@@ -67,25 +57,25 @@ def test_pw1_status_put(card):
assert r
def test_setup_pw3_0(card):
r = card.cmd_change_reference_data(3, PW3_TEST0 + FACTORY_PASSPHRASE_PW3)
r = card.change_passwd(3, PW3_TEST0, FACTORY_PASSPHRASE_PW3)
assert r
def test_verify_pw3_0(card):
v = card.cmd_verify(3, FACTORY_PASSPHRASE_PW3)
v = card.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)
r = card.change_passwd(1, PW1_TEST4, FACTORY_PASSPHRASE_PW1)
assert r
def test_verify_pw1_0(card):
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
assert v
def test_verify_pw1_0_2(card):
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
assert v
def test_setup_reset_code(card):
def test_delete_reset_code(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
test_remove_keys.py - test removing keys on 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.
@@ -22,22 +22,21 @@ 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):
def test_rsa_keyattr_change_1(card):
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K)
if r:
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K)
assert r
def test_rsa_import_key_2(card):
def test_rsa_keyattr_change_2(card):
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K)
if r:
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K)
assert r
def test_rsa_import_key_3(card):
def test_rsa_keyattr_change_3(card):
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K)
if r:
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K)

View File

@@ -0,0 +1,41 @@
"""
test_004_reset_pw3.py - test resetting pw3
Copyright (C) 2018 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_const import *
# Gnuk specific feature of clear PW3
def test_setup_pw3_null(card):
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, None)
assert r
def test_verify_pw3(card):
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
assert v
# Check PW1 again to see the possiblity of admin-less mode
def test_verify_pw1(card):
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
assert v
def test_verify_pw1_2(card):
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
assert v

View File

@@ -0,0 +1,310 @@
"""
test_005_personalize_admin_less.py - test admin-less mode
Copyright (C) 2016, 2018 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from struct import pack
from re import match, DOTALL
from util import *
import rsa_keys
from card_const import *
from constants_for_test import *
def test_verify_pw3_0(card):
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
assert v
def test_rsa_import_key_1(card):
t = rsa_keys.build_privkey_template(1, 0)
r = card.cmd_put_data_odd(0x3f, 0xff, t)
assert r
def test_rsa_import_key_2(card):
t = rsa_keys.build_privkey_template(2, 1)
r = card.cmd_put_data_odd(0x3f, 0xff, t)
assert r
def test_rsa_import_key_3(card):
t = rsa_keys.build_privkey_template(3, 2)
r = card.cmd_put_data_odd(0x3f, 0xff, t)
assert r
def test_fingerprint_1_put(card):
fpr1 = rsa_keys.fpr[0]
r = card.cmd_put_data(0x00, 0xc7, fpr1)
assert r
def test_fingerprint_2_put(card):
fpr2 = rsa_keys.fpr[1]
r = card.cmd_put_data(0x00, 0xc8, fpr2)
assert r
def test_fingerprint_3_put(card):
fpr3 = rsa_keys.fpr[2]
r = card.cmd_put_data(0x00, 0xc9, fpr3)
assert r
def test_timestamp_1_put(card):
timestamp1 = rsa_keys.timestamp[0]
r = card.cmd_put_data(0x00, 0xce, timestamp1)
assert r
def test_timestamp_2_put(card):
timestamp2 = rsa_keys.timestamp[1]
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
assert r
def test_timestamp_3_put(card):
timestamp3 = rsa_keys.timestamp[2]
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
assert r
def test_ds_counter_0(card):
c = get_data_object(card, 0x7a)
assert c == b'\x93\x03\x00\x00\x00'
def test_pw1_status(card):
s = get_data_object(card, 0xc4)
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
def test_app_data(card):
app_data = get_data_object(card, 0x6e)
hist_len = app_data[20]
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
app_data[18:18+2] == b"\x5f\x52"
def test_public_key_1(card):
pk = card.cmd_get_public_key(1)
assert rsa_keys.key[0][0] == pk[9:9+256]
def test_public_key_2(card):
pk = card.cmd_get_public_key(2)
assert rsa_keys.key[1][0] == pk[9:9+256]
def test_public_key_3(card):
pk = card.cmd_get_public_key(3)
assert rsa_keys.key[2][0] == pk[9:9+256]
# Changing PW1 to admin-less mode
def test_setup_pw1_0(card):
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
assert r
# Now, it's admin-less mode, auth-status admin cleared
def test_verify_pw3_fail_1(card):
try:
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
except ValueError as e:
v = False
assert not v
def test_verify_pw1_0(card):
v = card.verify(1, PW1_TEST0)
assert v
def test_verify_pw1_0_2(card):
v = card.verify(2, PW1_TEST0)
assert v
def test_setup_pw1_1(card):
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
assert r
def test_verify_pw1_1(card):
v = card.verify(1, PW1_TEST1)
assert v
def test_verify_pw1_1_2(card):
v = card.verify(2, PW1_TEST1)
assert v
def test_verify_pw3_admin_less_1(card):
v = card.verify(3, PW1_TEST1)
assert v
def test_setup_reset_code(card):
r = card.setup_reset_code(RESETCODE_TEST)
assert r
def test_reset_code(card):
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
assert r
# Changing PW1, auth status for admin cleared
def test_login_put_fail(card):
try:
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
except ValueError as e:
r = e.args[0]
assert r == "6982"
def test_verify_pw1_2(card):
v = card.verify(1, PW1_TEST2)
assert v
def test_verify_pw1_2_2(card):
v = card.verify(2, PW1_TEST2)
assert v
def test_verify_pw3_fail_2(card):
try:
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
except ValueError as e:
v = e.args[0]
assert v == "6982"
def test_sign_0(card):
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
sig = rsa_keys.compute_signature(0, digestinfo)
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
assert r == sig_bytes
# Since forcesig setting, failed
def test_sign_1(card):
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
try:
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
except ValueError as e:
r = e.args[0]
assert r == "6982"
def test_ds_counter_1(card):
c = get_data_object(card, 0x7a)
assert c == b'\x93\x03\x00\x00\x01'
def test_sign_auth_0(card):
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
r = card.cmd_internal_authenticate(digestinfo)
sig = rsa_keys.compute_signature(2, digestinfo)
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
assert r == sig_bytes
def test_sign_auth_1(card):
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
r = card.cmd_internal_authenticate(digestinfo)
sig = rsa_keys.compute_signature(2, digestinfo)
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
assert r == sig_bytes
def test_decrypt_0(card):
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
r = card.cmd_pso(0x80, 0x86, ciphertext)
assert r == PLAIN_TEXT0
def test_decrypt_1(card):
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
r = card.cmd_pso(0x80, 0x86, ciphertext)
assert r == PLAIN_TEXT1
def test_verify_pw3_admin_less_2(card):
v = card.verify(3, PW1_TEST2)
assert v
def test_login_put(card):
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
assert r
def test_name_put(card):
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
assert r
def test_lang_put(card):
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
assert r
def test_sex_put(card):
r = card.cmd_put_data(0x5f, 0x35, b"1")
assert r
def test_url_put(card):
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
assert r
def test_pw1_status_put(card):
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
assert r
def test_login(card):
login = get_data_object(card, 0x5e)
assert login == b"gpg_user"
def test_name_lang_sex(card):
name = b"GnuPG User"
lang = b"ja"
sex = b"1"
expected = b'\x5b' + pack('B', len(name)) + name \
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
+ b'\x5f\x35' + pack('B', len(sex)) + sex
name_lang_sex = get_data_object(card, 0x65)
assert name_lang_sex == expected
def test_url(card):
url = get_data_object(card, 0x5f50)
assert url == b"https://www.fsij.org/gnuk/"
def test_pw1_status(card):
s = get_data_object(card, 0xc4)
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
# Setting PW3, changed to admin-full mode
def test_setup_pw3_1(card):
r = card.change_passwd(3, PW1_TEST2, PW3_TEST1)
assert r
def test_verify_pw3_1(card):
v = card.verify(3, PW3_TEST1)
assert v
def test_reset_userpass_admin(card):
r = card.reset_passwd_by_admin(PW1_TEST3)
assert r
def test_verify_pw1_3(card):
v = card.verify(1, PW1_TEST3)
assert v
def test_verify_pw1_3_2(card):
v = card.verify(2, PW1_TEST3)
assert v
def test_setup_pw1_4(card):
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
assert r
def test_verify_pw1_4(card):
v = card.verify(1, PW1_TEST4)
assert v
def test_verify_pw1_4_2(card):
v = card.verify(2, PW1_TEST4)
assert v
def test_setup_pw3_2(card):
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
assert r
def test_verify_pw3_2(card):
v = card.verify(3, PW3_TEST0)
assert v

View File

@@ -0,0 +1 @@
test_002_personalize_reset.py

View File

@@ -0,0 +1 @@
test_003_remove_keys.py

1
tests/test_008_reset_pw3.py Symbolic link
View File

@@ -0,0 +1 @@
test_004_reset_pw3.py

83
tests/test_009_keygen.py Normal file
View File

@@ -0,0 +1,83 @@
"""
test_005_keygen.py - test key generation
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 binascii import hexlify
import rsa_keys
from card_const import *
def test_keygen_1(card):
pk = card.cmd_genkey(1)
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
r = card.cmd_put_data(0x00, 0xc7, fpr_date[0])
if r:
r = card.cmd_put_data(0x00, 0xce, fpr_date[1])
assert r
def test_keygen_2(card):
pk = card.cmd_genkey(2)
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
r = card.cmd_put_data(0x00, 0xc8, fpr_date[0])
if r:
r = card.cmd_put_data(0x00, 0xcf, fpr_date[1])
assert r
def test_keygen_3(card):
pk = card.cmd_genkey(3)
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
r = card.cmd_put_data(0x00, 0xc9, fpr_date[0])
if r:
r = card.cmd_put_data(0x00, 0xd0, fpr_date[1])
assert r
def test_verify_pw1(card):
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
assert v
def test_signature_sigkey(card):
msg = b"Sign me please"
pk = card.cmd_get_public_key(1)
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
digest = rsa_keys.compute_digestinfo(msg)
sig = int(hexlify(card.cmd_pso(0x9e, 0x9a, digest)),16)
r = rsa_keys.verify_signature(pk_info, digest, sig)
assert r
def test_verify_pw1_2(card):
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
assert v
def test_decryption(card):
msg = b"encrypt me please"
pk = card.cmd_get_public_key(2)
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
ciphertext = rsa_keys.encrypt_with_pubkey(pk_info, msg)
r = card.cmd_pso(0x80, 0x86, ciphertext)
assert r == msg
def test_signature_authkey(card):
msg = b"Sign me please to authenticate"
pk = card.cmd_get_public_key(3)
pk_info = (pk[9:9+256], pk[9+256+2:9+256+2+3])
digest = rsa_keys.compute_digestinfo(msg)
sig = int(hexlify(card.cmd_internal_authenticate(digest)),16)
r = rsa_keys.verify_signature(pk_info, digest, sig)
assert r

View File

@@ -0,0 +1 @@
test_003_remove_keys.py

View File

@@ -0,0 +1,34 @@
"""
test_007_kdf_full.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 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_full(card):
r = card.cmd_put_data(0x00, 0xf9, KDF_FULL)
if r:
card.configure_with_kdf()
assert r

View File

@@ -0,0 +1 @@
test_001_personalize_card.py

View File

@@ -0,0 +1 @@
test_002_personalize_reset.py

View File

@@ -0,0 +1 @@
test_003_remove_keys.py

1
tests/test_015_reset_pw3.py Symbolic link
View File

@@ -0,0 +1 @@
test_004_reset_pw3.py

View File

@@ -0,0 +1,34 @@
"""
test_012_kdf_single.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 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_single(card):
r = card.cmd_put_data(0x00, 0xf9, KDF_SINGLE)
if r:
card.configure_with_kdf()
assert r

View File

@@ -0,0 +1 @@
test_001_personalize_card.py

View File

@@ -0,0 +1 @@
test_002_personalize_reset.py

View File

@@ -0,0 +1 @@
test_003_remove_keys.py

1
tests/test_020_reset_pw3.py Symbolic link
View File

@@ -0,0 +1 @@
test_004_reset_pw3.py

View File

@@ -0,0 +1 @@
test_005_personalize_admin_less.py

View File

@@ -0,0 +1 @@
test_002_personalize_reset.py

View File

@@ -0,0 +1 @@
test_003_remove_keys.py

1
tests/test_024_reset_pw3.py Symbolic link
View File

@@ -0,0 +1 @@
test_004_reset_pw3.py

View File

@@ -0,0 +1,38 @@
"""
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 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

48
tool/gnuk-emulation-setup Executable file
View File

@@ -0,0 +1,48 @@
#! /bin/sh
#
# gnuk-emulation-setup - Generate flash image for Gnuk
#
# Copyright (C) 2017 Free Software Initiative of Japan
# Author: NIIBE Yutaka <gniibe@fsij.org>
#
# This file is a part of Gnuk, a GnuPG USB Token implementation.
#
# Gnuk is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Gnuk is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if test "$1" = "--help"; then
echo "Usage:"
echo " $0 [output-file]"
echo " Generate Gnuk flash image"
echo " $0 --help"
echo " Show this message"
exit 0
fi
OUTPUT_FILE=${1:-$HOME/.gnuk-flash-image}
# Generate 8192-byte flash data into OUTPUT_FILE
exec > $OUTPUT_FILE
for i in $(seq 512); do
/bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff'
done
/bin/echo -n -e '\x00\x00\xff\xff\xff\xff\xff\xff'
for i in $(seq 511); do
/bin/echo -n -e '\xff\xff\xff\xff\xff\xff\xff\xff'
done
chmod og-rw $OUTPUT_FILE

21
tool/gnuk_get_random.py Executable file
View File

@@ -0,0 +1,21 @@
#! /usr/bin/python3
from gnuk_token import get_gnuk_device, gnuk_token
from binascii import hexlify
import sys
if __name__ == '__main__':
count = 0
gnuk = get_gnuk_device()
gnuk.cmd_select_openpgp()
looping = (len(sys.argv) > 1)
while True:
try:
challenge = gnuk.cmd_get_challenge().tostring()
except Exception as e:
print(count)
raise e
print(hexlify(challenge))
count = count + 1
if not looping:
break

View File

@@ -3,7 +3,7 @@
"""
gnuk_remove_keys_libusb.py - a tool to remove keys in Gnuk Token
Copyright (C) 2012 Free Software Initiative of Japan
Copyright (C) 2012, 2018 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -24,7 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys, os
from gnuk_token import *
from gnuk_token import gnuk_devices, gnuk_token, parse_kdf_data
from kdf_calc import kdf_calc
# Assume only single CCID device is attached to computer and it's Gnuk Token
@@ -42,13 +43,28 @@ def main(passwd):
break
except:
pass
if not gnuk:
raise ValueError("No ICC present")
if gnuk.icc_get_status() == 2:
raise ValueError("No ICC present")
elif gnuk.icc_get_status() == 1:
gnuk.icc_power_on()
gnuk.cmd_select_openpgp()
gnuk.cmd_verify(BY_ADMIN, passwd.encode('UTF-8'))
gnuk.cmd_select_openpgp()
# Compute passwd data
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring()
if kdf_data == b"":
passwd_data = passwd.encode('UTF-8')
else:
algo, subalgo, iters, salt_user, salt_reset, salt_admin, \
hash_user, hash_admin = parse_kdf_data(kdf_data)
if salt_admin:
salt = salt_admin
else:
salt = salt_user
passwd_data = kdf_calc(passwd, salt, iters)
# And authenticate with the passwd data
gnuk.cmd_verify(BY_ADMIN, passwd_data)
# Do remove keys and related data objects
gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG
gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG
gnuk.cmd_put_data_key_import_remove(1)

View File

@@ -1,7 +1,7 @@
"""
gnuk_token.py - a library for Gnuk Token
Copyright (C) 2011, 2012, 2013, 2015
Copyright (C) 2011, 2012, 2013, 2015, 2017, 2018
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -26,6 +26,13 @@ import binascii
import usb, time
from array import array
# Possible Gnuk Token products
USB_PRODUCT_LIST=[
{ 'vendor' : 0x234b, 'product' : 0x0000 }, # FSIJ Gnuk Token
{ 'vendor' : 0x20a0, 'product' : 0x4211 }, # Nitrokey Start
{ 'vendor' : 0x1209, 'product' : 0x2440 }, # GnuPG e.V.
]
# USB class, subclass, protocol
CCID_CLASS = 0x0B
CCID_SUBCLASS = 0x00
@@ -68,6 +75,7 @@ class gnuk_token(object):
raise ValueError("Wrong interface sub class")
self.__devhandle = device.open()
self.__devhandle.claimInterface(interface)
self.__devhandle.setAltInterface(interface)
self.__intf = interface.interfaceNumber
self.__alt = interface.alternateSetting
@@ -586,19 +594,18 @@ def gnuk_devices():
alt.interfaceProtocol == CCID_PROTOCOL_0:
yield dev, config, alt
USB_VENDOR_FSIJ=0x234b
USB_PRODUCT_GNUK=0x0000
def gnuk_devices_by_vidpid():
busses = usb.busses()
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.idVendor != USB_VENDOR_FSIJ:
continue
if dev.idProduct != USB_PRODUCT_GNUK:
continue
yield dev
for cand in USB_PRODUCT_LIST:
if dev.idVendor != cand['vendor']:
continue
if dev.idProduct != cand['product']:
continue
yield dev
break
def get_gnuk_device():
icc = None
@@ -630,3 +637,48 @@ def UNSIGNED(n):
def crc32(bytestr):
crc = binascii.crc32(bytestr)
return UNSIGNED(crc)
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 )

51
tool/kdf_calc.py Normal file
View File

@@ -0,0 +1,51 @@
"""
kdf_calc.py - a library for calculating hash by KDF
Copyright (C) 2018 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from cffi import FFI
DEF_gcry_kdf_derive="""
typedef unsigned int gpg_error_t;
gpg_error_t gcry_kdf_derive (const void *passphrase, size_t passphraselen,
int algo, int subalgo, const void *salt,
size_t saltlen, unsigned long iterations,
size_t keysize, void *keybuffer);
"""
GCRY_KDF_ITERSALTED_S2K = 19
GCRY_MD_SHA256 = 8
def kdf_calc(pw_string, salt_byte, iterations):
ffi = FFI()
ffi.cdef(DEF_gcry_kdf_derive)
libgcrypt = ffi.dlopen("libgcrypt.so.20")
if isinstance(pw_string, str):
pw_byte = pw_string.encode('UTF-8')
else:
pw_byte = pw_string
pw=ffi.new("char []", pw_byte)
salt = ffi.new("char []", salt_byte)
kb = ffi.new("char []", 32)
r = libgcrypt.gcry_kdf_derive(pw, len(pw_string), GCRY_KDF_ITERSALTED_S2K,
GCRY_MD_SHA256, salt, 8, iterations, 32, kb)
if r != 0:
raise ValueError("libgcrypt error", r)
return ffi.unpack(kb, 32)

View File

@@ -4,7 +4,8 @@
upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token
which is just shipped from factory
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
Copyright (C) 2012, 2013, 2015, 2018
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,9 +24,13 @@ 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 gnuk_token import *
from gnuk_token import get_gnuk_device, gnuk_devices_by_vidpid, \
gnuk_token, regnual, SHA256_OID_PREFIX, crc32, parse_kdf_data
from kdf_calc import kdf_calc
import sys, binascii, time, os
import rsa
from struct import pack
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
@@ -45,7 +50,23 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
gnuk = get_gnuk_device()
gnuk.cmd_select_openpgp()
gnuk.cmd_verify(BY_ADMIN, passwd.encode('UTF-8'))
# Compute passwd data
try:
kdf_data = gnuk.cmd_get_data(0x00, 0xf9).tostring()
except:
kdf_data = b""
if kdf_data == b"":
passwd_data = passwd.encode('UTF-8')
else:
algo, subalgo, iters, salt_user, salt_reset, salt_admin, \
hash_user, hash_admin = parse_kdf_data(kdf_data)
if salt_admin:
salt = salt_admin
else:
salt = salt_user
passwd_data = kdf_calc(passwd, salt, iters)
# And authenticate with the passwd data
gnuk.cmd_verify(BY_ADMIN, passwd_data)
gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
gnuk.cmd_select_openpgp()
@@ -69,8 +90,9 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
gnuk = None
#
reg = None
print("Waiting for device to appear:")
while reg == None:
print("Wait %d seconds..." % wait_e)
print(" Wait {} second{}...".format(wait_e, 's' if wait_e > 1 else ''))
time.sleep(wait_e)
for dev in gnuk_devices_by_vidpid():
try:
@@ -84,9 +106,13 @@ def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
print("%08x:%08x" % mem_info)
print("Downloading the program")
reg.download(mem_info[0], data_upgrade)
print("Protecting device")
reg.protect()
print("Finish flashing")
reg.finish()
print("Resetting device")
reg.reset_device()
print("Update procedure finished")
return 0
from getpass import getpass
@@ -119,6 +145,9 @@ if __name__ == '__main__':
passwd = getpass("Admin password: ")
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
if not filename_regnual.endswith('bin') or not filename_upgrade.endswith('bin'):
print("Both input files must be in binary format (*.bin)!")
exit(1)
f = open(filename_regnual,"rb")
data_regnual = f.read()
f.close()

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