Compare commits

..

118 Commits

Author SHA1 Message Date
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
92 changed files with 3388 additions and 1315 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,7 @@
*.lst
*.o
*.pyc
regnual/regnual-no-vidpid.elf
src/.dep
src/config.mk
src/config.h
@@ -8,10 +9,10 @@ src/gnuk.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__
emulation/gnuk_emulation

View File

@@ -1,3 +1,10 @@
Aurelien Jarno:
Modified:
src/Makefile
src/configure
src/main.c
src/stack-def.h
Anthony Romano:
Modified:
src/call-rsa.c

451
ChangeLog
View File

@@ -1,3 +1,454 @@
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.

View File

@@ -1,4 +1,5 @@
# 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
##########<TAB> ##<TAB> ##########<TAB> #################

80
NEWS
View File

@@ -1,5 +1,85 @@
Gnuk NEWS - User visible changes
* 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

73
README
View File

@@ -1,28 +1,34 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.5
2017-08-11
Version 1.2.9
2018-04-05
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.5, which has major
This is the release of Gnuk, version 1.2.9, 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
(forthcoming 2.2.6 or later). You need to prepare the KDF-DO on your
token by the card-edit/kdf-setup command.
What's Gnuk?
============
@@ -216,15 +222,17 @@ Some tools are written in Python. If your Python is not installed as
Python 2.7 and PyUSB 0.4.3 is assumed.
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 +256,7 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 1.3
* chopstx/ -- Chopstx 1.8
We use Chopstx as the kernel for Gnuk.
@@ -297,6 +305,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 +378,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.28-4+9+b2
gcc-arm-none-eabi 15:5.4.1+svn241155-1
binutils-arm-none-eabi 2.28-4+9+b3
gcc-arm-none-eabi 15:6.3.1+svn253039-1
gdb-arm-none-eabi 7.12-6+9+b2
libnewlib-arm-none-eabi 2.4.0.20160527-2
libnewlib-arm-none-eabi 2.4.0.20160527-3
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
@@ -388,6 +405,10 @@ Then, type:
Then, we will have "gnuk.elf" under src/build directory.
Next, we can get the final image by running following command.
$ make build/gnuk-vidpid.elf
How to install
==============
@@ -396,11 +417,11 @@ Olimex STM32-H103 board
-----------------------
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD
and write "gnuk.elf" to Flash ROM:
and write "gnuk-vidpid.elf" to Flash ROM:
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg \
-f board/olimex_stm32_h103.cfg \
-c "program build/gnuk.elf verify reset exit"
-c "program build/gnuk-vidpid.elf verify reset exit"
Command invocation is assumed in src/ directory.
@@ -413,7 +434,7 @@ If you are using Flying Stone Tiny 01, you need a SWD writer.
OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "program build/gnuk.elf verify reset exit"
-c "program build/gnuk-vidpid.elf verify reset exit"
@@ -424,7 +445,7 @@ Reset the board with "USER" switch pushed. Type following to write
to flash:
# cd ../tool
# ./dfuse.py ../src/build/gnuk.hex
# ./dfuse.py ../src/build/gnuk-vidpid.hex
Then, reset the board.
@@ -537,7 +558,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
@@ -576,31 +597,24 @@ 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 update --init
Gnuk 1.0 uses ChibiOS/RT, and then, we have migrated from to Chopstx
in the development phase of Gnuk 1.1. If you have old code of
ChibiOS/RT, you need:
Edit .git/config to remove chibios reference and
$ git rm --cached chibios
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:
@@ -608,7 +622,8 @@ Please see the FST-01 support pages:
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

1
THANKS
View File

@@ -7,6 +7,7 @@ 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

View File

@@ -1 +1 @@
release/1.2.5
release/1.2.9

Submodule chopstx updated: d8df82badf...aa63ac79bc

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,12 @@ 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.
Next, we can get the final image by running following command. ::
$ make build/gnuk-vidpid.elf

View File

@@ -65,7 +65,7 @@ Invoking firmware update
We specify reGNUal binary and Gnuk binary.
$ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk.bin
$ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk-vidpid.bin
Two or more tokens

View File

@@ -73,16 +73,20 @@ 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.
Next, we can get the final image by running following command.
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.
$ make build/gnuk-vidpid.elf
Invoking configure with FSIJ's USB ID (234b:0000) and generating
gnuk-vidpid.elf means that you are using FSIJ's USB ID (for reGNUal in
this case). Please note that FSIJ only allows use of its USB ID for
specific situations. Please read README of Gnuk about that.
Bulding reGNUal
@@ -117,13 +121,13 @@ your environment for Gnuk Token.
How to run the script: ::
$ cd tool
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.bin
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk-vidpid.bin
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

@@ -1,31 +0,0 @@
SRCS = usbip-server.c usb-emu.c glue.c
OBJS = $(SRCS:.c=.o)
TARGET=gnuk_emulation
GNUKDIR=../src
GNUK_SRCS = main.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
USB_SRCS=usb_desc.c usb_ctrl.c
GNUK_CSRC = $(addprefix $(GNUKDIR)/, $(GNUK_SRCS))
GNUK_OBJS = $(notdir $(GNUK_CSRC:.c=.o))
USB_CSRC = $(addprefix $(GNUKDIR)/, $(USB_SRCS))
USB_OBJS = $(notdir $(USB_CSRC:.c=.o))
# all:
# echo $(GNUK_OBJS)
$(TARGET): $(OBJS) $(USB_OBJS) Makefile
$(CC) -o $(TARGET) $(OBJS) $(USB_OBJS)
$(GNUK_OBJS): %.o : $(GNUKDIR)/%.c Makefile
$(CC) -c $(CFLAGS) -I. -I$(GNUKDIR) -I../chopstx $< -o $@
$(USB_OBJS): %.o : $(GNUKDIR)/%.c Makefile
$(CC) -c $(CFLAGS) -I. -I$(GNUKDIR) -I../chopstx $< -o $@

View File

@@ -1,54 +0,0 @@
#include <stdint.h>
uint8_t _regnual_start;
uint8_t __heap_end__;
int
check_crc32 (const uint32_t *start_p, const uint32_t *end_p)
{
return 0;
}
uint8_t *
sram_address (uint32_t offset)
{
return ((uint8_t *)0x20000000) + offset;
}
const uint8_t sys_version[8] = {
3*2+2, /* bLength */
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
/* sys version: "3.0" */
'3', 0, '.', 0, '0', 0,
};
void
led_blink (int spec)
{
}
void
ccid_usb_reset (int full)
{
}
void
ccid_card_change_signal (int how)
{
}
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_EXEC_REQUESTED, /* Exec requested */
};
static enum ccid_state ccid_state;
enum ccid_state *const ccid_state_p = &ccid_state;

View File

@@ -1,103 +0,0 @@
/*
* usb-emu.c - USB driver for USBIP emulation
*
* Copyright (C) 2017 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Chopstx, a thread library for embedded.
*
* Chopstx 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.
*
* Chopstx 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 <stdlib.h>
#include "../chopstx/usb_lld.h"
int
usb_lld_ctrl_ack (struct usb_dev *dev)
{
return 0;
}
int
usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
{
return 0;
}
int
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
{
return 0;
}
uint8_t
usb_lld_current_configuration (struct usb_dev *dev)
{
return 0;
}
void
usb_lld_prepare_shutdown (void)
{
}
void
usb_lld_ctrl_error (struct usb_dev *dev)
{
}
void
usb_lld_reset (struct usb_dev *dev, uint8_t feature)
{
}
void
usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
{
}
void
usb_lld_shutdown (void)
{
}
void
usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
int ep_rx_addr, int ep_tx_addr,
int ep_rx_memory_size)
{
}
void
usb_lld_stall (int ep_num)
{
}
void
usb_lld_stall_tx (int ep_num)
{
usb_lld_stall (ep_num);
}
void
usb_lld_stall_rx (int ep_num)
{
usb_lld_stall (ep_num);
}

View File

@@ -1,278 +0,0 @@
/*
* usbip-server.c - USB Device Emulation by USBIP Protocol
*
* Copyright (C) 2017 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Chopstx, a thread library for embedded.
*
* Chopstx 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.
*
* Chopstx 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 <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define USBIP_PORT 3240
#define CMD_REQ_LIST 0x01118005
#define CMD_REQ_ATTACH 0x01118003
#define CMD_URB 0x00000001
#define CMD_DETACH 0x00000002
struct usbip_msg_head {
uint32_t cmd;
uint32_t seq;
};
#define USBIP_REPLY_HEADER_SIZE 12
#define DEVICE_INFO_SIZE (256+32+12+6+6)
#define INTERFACE_INFO_SIZE 4
#define DEVICE_LIST_SIZE (USBIP_REPLY_HEADER_SIZE+DEVICE_INFO_SIZE*1+INTERFACE_INFO_SIZE*1)
#define USBIP_REPLY_DEVICE_LIST "\x01\x11\x00\x05"
#define NETWORK_UINT32_ZERO "\x00\x00\x00\x00"
#define NETWORK_UINT32_ONE "\x00\x00\x00\x01"
#define NETWORK_UINT32_TWO "\x00\x00\x00\x02"
#define NETWORK_UINT16_FSIJ "\x23\x4b"
#define NETWORK_UINT16_ZERO "\x00\x00"
#define NETWORK_UINT16_ONE_ONE "\x01\x01"
static char *
list_devices (size_t *len_p)
{
char *p0, *p;
*len_p = 0;
p0 = malloc (DEVICE_LIST_SIZE);
if (p0 == NULL)
return NULL;
*len_p = DEVICE_LIST_SIZE;
p = p0;
memcpy (p, USBIP_REPLY_DEVICE_LIST, 4);
p += 4;
memcpy (p, NETWORK_UINT32_ZERO, 4);
p += 4;
memcpy (p, NETWORK_UINT32_ONE, 4);
p += 4;
memset (p, 0, 256);
strcpy (p, "/sys/devices/pci0000:00/0000:00:01.1/usb1/1-1");
p += 256;
memset (p, 0, 32);
strcpy (p, "1-1");
p += 32;
memcpy (p, NETWORK_UINT32_ONE, 4); /* Bus */
p += 4;
memcpy (p, NETWORK_UINT32_TWO, 4); /* Dev */
p += 4;
memcpy (p, NETWORK_UINT32_ONE, 4); /* Speed */
p += 4;
memcpy (p, NETWORK_UINT16_FSIJ, 2);
p += 2;
memcpy (p, NETWORK_UINT16_ZERO, 2); /* Gnuk */
p += 2;
memcpy (p, NETWORK_UINT16_ONE_ONE, 2); /* USB 1.1 */
p += 2;
*p++ = 0; /* bDeviceClass */
*p++ = 0; /* bDeviceSubClass */
*p++ = 0; /* bDeviceProtocol */
*p++ = 0; /* bConfigurationValue */
*p++ = 1; /* bConfigurationValue */
*p++ = 1; /* bNumInterfaces */
*p++ = 11; /* bInterfaceClass */
*p++ = 0; /* bInterfaceSubClass */
*p++ = 0; /* bInterfaceProtocol */
*p++ = 0; /* ----pad----------- */
return p0;
}
static char *
attach_device (char busid[32], size_t *len_p)
{
*len_p = 0;
return NULL;
}
static int
handle_urb (int fd)
{
return 0;
}
static void
run_server (void)
{
int sock;
struct sockaddr_in v4addr;
const int one = 1;
if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("socket");
exit (1);
}
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&one, sizeof (int)) < 0)
perror ("WARN: setsockopt");
memset (&v4addr, 0, sizeof (v4addr));
v4addr.sin_family = AF_INET;
v4addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
v4addr.sin_port = htons (USBIP_PORT);
if (bind (sock, (const struct sockaddr *)&v4addr, sizeof (v4addr)) < 0)
{
perror ("bind");
exit (1);
}
/* We only accept a connection from a single client. */
if (listen (sock, 1) < 0)
{
perror ("listen");
exit (1);
}
for (;;)
{
int fd;
int attached = 0;
/* We don't care who is connecting. */
if ((fd = accept (sock, NULL, NULL)) < 0)
{
perror ("accept");
exit (1);
}
for (;;)
{
struct usbip_msg_head msg;
if (recv (fd, (char *)&msg, sizeof (msg), 0) != sizeof (msg))
{
perror ("msg recv");
break;
}
msg.cmd = ntohl (msg.cmd);
msg.seq = ntohl (msg.seq);
if (msg.cmd == CMD_REQ_LIST)
{
char *device_list;
size_t device_list_size;
if (attached)
{
fprintf (stderr, "REQ list while attached\n");
break;
}
device_list = list_devices (&device_list_size);
if (send (fd, device_list, device_list_size, 0) != device_list_size)
{
perror ("list send");
break;
}
free (device_list);
}
else if (msg.cmd == CMD_REQ_ATTACH)
{
char busid[32];
char *attach;
size_t attach_size;
if (attached)
{
fprintf (stderr, "REQ attach while attached\n");
break;
}
if (recv (fd, busid, 32, 0) != 32)
{
perror ("attach recv");
break;
}
attach = attach_device (busid, &attach_size);
if (send (fd, attach, attach_size, 0) != attach_size)
{
perror ("list send");
break;
}
free (attach);
attached = 1;
}
else if (msg.cmd == CMD_URB)
{
if (!attached)
{
fprintf (stderr, "URB while attached\n");
break;
}
if (handle_urb (fd) < 0)
{
fprintf (stderr, "URB handling failed\n");
break;
}
}
else if(msg.cmd == CMD_DETACH)
{
if (!attached)
{
fprintf (stderr, "DETACH while attached\n");
break;
}
/* send reply??? */
break;
}
else
{
fprintf (stderr, "Unknown command %08x, disconnecting.\n", msg.cmd);
break;
}
}
close (fd);
}
}
int
main (int argc, const char *argv[])
{
run_server ();
return 0;
}

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;
@@ -2052,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;
@@ -2203,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,
@@ -2215,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 }};
@@ -2222,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 }};
@@ -2275,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,12 +1,13 @@
# Makefile for reGNUal
PROJECT = regnual
PROJECT = regnual-no-vidpid
OBJS = regnual.o usb-stm32f103.o reset.o
LDSCRIPT= regnual.ld
include ../src/config.mk
LDSCRIPT= regnual.ld
###################################
MCU = cortex-m3
@@ -40,11 +41,15 @@ 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

View File

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

View File

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

View File

@@ -5,10 +5,7 @@ PROJECT = gnuk
CHOPSTX = ../chopstx
# Define linker script file here
LDSCRIPT= gnuk.ld
CSRC = main.c call-rsa.c mcu-stm32f103.c \
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 \
@@ -29,8 +26,17 @@ 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
@@ -43,21 +49,17 @@ ifeq ($(ENABLE_PINPAD),dnd)
CSRC += usb-msc.c
endif
CHIP=stm32f103
USE_SYS = yes
USE_USB = yes
USE_ADC = yes
ifeq ($(CHIP),stm32f103)
CSRC += mcu-stm32f103.c
endif
###################################
CROSS = arm-none-eabi-
CC = $(CROSS)gcc
LD = $(CROSS)gcc
OBJCOPY = $(CROSS)objcopy
MCU = cortex-m3
CWARN = -Wall -Wextra -Wstrict-prototypes
OPT = -O3 -Os -g
LIBS =
#######################
include $(CHOPSTX)/rules.mk
@@ -73,3 +75,22 @@ build/bignum.o: OPT = -O3 -g
distclean: clean
-rm -f gnuk.ld config.h board.h config.mk \
usb-strings.c.inc usb-vid-pid-ver.c.inc
ifeq ($(EMULATION),)
build/gnuk-vidpid.elf: build/gnuk.elf binary-edit.sh put-vid-pid-ver.sh
cp -p build/gnuk.elf build/gnuk-vidpid.elf
env FILE="build/gnuk-vidpid.elf" bash put-vid-pid-ver.sh
$(OBJCOPY) -O ihex build/gnuk-vidpid.elf build/gnuk-vidpid.hex
$(OBJCOPY) -O binary build/gnuk-vidpid.elf build/gnuk-vidpid.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,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,30 +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)
{
free (modulus);
return NULL;
}
return modulus;
return -1;
return 0;
}
@@ -144,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);
@@ -179,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);
}
@@ -234,45 +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) );
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) );
clp.arg = NULL;
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (1);
if (ret != 0)
return NULL;
return -1;
else
return p_q_modulus;
return 0;
}

198
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, 2017
# 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
@@ -44,6 +45,10 @@ certdo=no
hid_card_change=no
factory_reset=no
flash_override=""
# For emulation
prefix=/usr/local
exec_prefix='${prefix}'
libexecdir='${exec_prefix}/libexec'
# Revision number
if test -e ../.git; then
@@ -100,6 +105,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
@@ -127,11 +141,14 @@ Configuration:
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]
@@ -141,18 +158,11 @@ 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
@@ -166,8 +176,10 @@ MEMORY_SIZE=20
# Settings for TARGET
case $target in
BLUE_PILL)
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB" ;;
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;
@@ -184,13 +196,47 @@ STBEE)
if test "$with_dfu" = "default"; then
with_dfu=yes;
fi ;;
STM8S_DISCOVERY)
FLASH_SIZE=64
;;
*)
;;
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"
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"
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"
@@ -213,19 +259,14 @@ if test "$with_dfu" = "yes"; then
ORIGIN=0x08003000
FLASH_SIZE=$((FLASH_SIZE - 12))
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
DFU_DEFINE="#undef DFU_SUPPORT"
HEXOUTPUT_MAKE_OPTION=""
fi
# --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"
@@ -236,12 +277,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
@@ -278,7 +313,7 @@ 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
@@ -288,53 +323,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 '};'
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 '};'
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,"
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 '};'
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 '};'
@@ -342,16 +406,22 @@ output_vendor_product_serial_strings () {
fi
}
if ! (IFS=" "
(echo "#! /bin/bash"
echo
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
if !(IFS=" "
while read -r VIDPID VERSION PRODUCT VENDOR; do
if test "$vidpid" = "$VIDPID"; then
output_vid_pid_version > usb-vid-pid-ver.c.inc
echo >> put-vid-pid-ver.sh
echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
output_vid_pid_version >> put-vid-pid-ver.sh
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
exit 0
fi
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
@@ -368,29 +438,35 @@ else
fi
echo -e "DEFS=$use_sys3 $flash_override" '\n' \
"$DEBUG_MAKE_OPTION" '\n' \
"$PINPAD_MAKE_OPTION" '\n' \
"$HEXOUTPUT_MAKE_OPTION" \
> config.mk
(echo "CHIP=$chip";
echo "EMULATION=$emulation";
echo "CROSS=$cross";
echo "MCU=$mcu";
echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size";
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 "$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/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \

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

@@ -1,7 +1,7 @@
/*
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -53,24 +53,21 @@
* <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) */
@@ -78,8 +75,18 @@ const uint8_t const 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)
{
@@ -103,18 +110,20 @@ static int key_available_at (const uint8_t *k, int key_size)
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
void
flash_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
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;
@@ -129,13 +138,13 @@ flash_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
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;
*p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE;
*p_do_end = data_pool + flash_page_size;
@@ -148,34 +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 ((uint32_t)&ch_certificate_start);
flash_erase_page ((uintptr_t)&ch_certificate_start);
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uint32_t)(&ch_certificate_start + 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;
@@ -233,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;
@@ -251,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;
}
@@ -282,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");
@@ -338,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;
@@ -373,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 *
@@ -407,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);
@@ -433,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))
@@ -452,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);
@@ -462,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);
}
@@ -470,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);
}
@@ -484,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
@@ -498,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);
}
@@ -510,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 *
@@ -533,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;
}
@@ -549,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 *
@@ -565,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;
}
@@ -601,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
@@ -626,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
@@ -641,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);
}
}
@@ -653,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;
}
@@ -669,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;
@@ -694,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)
{
@@ -720,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,15 +22,12 @@ 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 8
/* OpenPGPcard thread */
#define EV_PINPAD_INPUT_DONE 1
@@ -112,7 +109,7 @@ 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);
@@ -139,10 +136,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);
void flash_init (const uint8_t **, const uint8_t **);
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 +149,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 +262,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,14 +285,17 @@ 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);
void fatal (uint8_t code) __attribute__ ((noreturn));
@@ -334,7 +334,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:
@@ -433,6 +434,7 @@ extern const uint8_t gnuk_string_serial[];
#define LED_GNUK_EXEC 32
#define LED_START_COMMAND 64
#define LED_FINISH_COMMAND 128
#define LED_OFF LED_FINISH_COMMAND
void led_blink (int spec);
#if defined(PINPAD_SUPPORT)
@@ -461,5 +463,4 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
extern uint8_t _regnual_start, __heap_end__[];
int check_crc32 (const uint32_t *start_p, const uint32_t *end_p);
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__ = 0x01a0; /* ccid */
__process2_stack_size__ = 0x0180; /* rng */
__process3_stack_size__ = 0x1660; /* 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
@@ -172,11 +135,11 @@ SECTIONS
{
. = ALIGN (@FLASH_PAGE_SIZE@);
_keystore_pool = .;
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
. += 512;
. += 1024;
. = ALIGN(@FLASH_PAGE_SIZE@);
_updatekey_store = .;
. += 1024;

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017
* 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
@@ -47,6 +52,10 @@
#define LED_TIMEOUT_STOP (200*1000)
#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)
@@ -76,10 +85,15 @@ device_initialize_once (void)
}
}
}
#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 +134,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;
uint32_t usec;
if (ccid_state == CCID_STATE_START)
emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
@@ -145,10 +162,14 @@ 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);
usec = LED_TIMEOUT_INTERVAL;
chopstx_poll (&usec, 1, led_event_poll);
emit_led (ccid_state == CCID_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
}
@@ -167,26 +188,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 +227,96 @@ 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;
(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,12 +342,14 @@ 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;
@@ -285,8 +390,9 @@ 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
@@ -294,12 +400,12 @@ main (int argc, char *argv[])
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
{
extern uint8_t _sys;
uint32_t addr;
uintptr_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
uint32_t flash_page_size = 1024; /* 1KiB default */
if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
if ((*CHIP_ID_REG)&0x07 == 0x04) /* High dencity device. */
flash_page_size = 2048; /* It's 2KiB. */
/* Kill DFU */
@@ -318,6 +424,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,26 +457,37 @@ 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 MEMORY_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#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 != MEMORY_ALIGN((x)->size) || (x)->size > MEMORY_SIZE)
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
static struct mem_head *free_list;
@@ -376,7 +496,7 @@ static void
gnuk_malloc_init (void)
{
chopstx_mutex_init (&malloc_mtx);
heap_p = __heap_base__;
heap_p = HEAP_START;
free_list = NULL;
}
@@ -385,7 +505,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;
@@ -410,7 +530,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: ");
@@ -450,8 +570,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);
}
}
@@ -459,7 +579,7 @@ 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)
@@ -469,7 +589,7 @@ gnuk_free (void *p)
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;

View File

@@ -25,30 +25,6 @@
#include <stdint.h>
#include "mcu/stm32f103.h"
static uint32_t
rbit (uint32_t v)
{
uint32_t r;
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
return r;
}
int
check_crc32 (const uint32_t *start_p, const uint32_t *end_p)
{
uint32_t crc32 = *end_p;
const uint32_t *p;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
for (p = start_p; p < end_p; p++)
CRC->DR = rbit (*p);
return (rbit (CRC->DR) ^ crc32) == 0xffffffff;
}
uint8_t *
sram_address (uint32_t offset)
{

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, 2017
* 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"
@@ -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 */
@@ -453,12 +454,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__];
@@ -495,6 +501,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;
}
@@ -799,6 +807,157 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
}
}
#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)
{
@@ -812,31 +971,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);
@@ -848,7 +1021,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);
@@ -867,7 +1040,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);
@@ -1083,14 +1256,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);
@@ -1098,10 +1273,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;
@@ -1129,38 +1300,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++;
@@ -1179,8 +1323,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);
@@ -1196,19 +1340,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;
}
@@ -1230,7 +1366,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;
@@ -1262,18 +1397,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
@@ -1304,18 +1436,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;
}
@@ -1370,6 +1503,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;
@@ -1409,13 +1543,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];
@@ -1427,7 +1583,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)
{
@@ -1439,7 +1596,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)
@@ -1506,6 +1664,8 @@ gpg_do_table[] = {
rw_algorithm_attr },
{ GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_algorithm_attr },
{ 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 },
@@ -1571,7 +1731,7 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
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)
@@ -2076,44 +2236,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
@@ -2140,7 +2293,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)
{
@@ -2151,7 +2307,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)
{
@@ -2162,7 +2318,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
{
@@ -2170,12 +2326,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 ();
@@ -2186,14 +2351,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,7 @@
/*
* openpgp.c -- OpenPGP card protocol support
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -37,6 +37,7 @@
static struct eventflag *openpgp_comm;
#define USER_PASSWD_MINLEN 6
#define ADMIN_PASSWD_MINLEN 8
#define CLS(a) a.cmd_apdu_head[0]
@@ -108,7 +109,7 @@ gpg_init (void)
const uint8_t *flash_do_start;
const uint8_t *flash_do_end;
flash_init (&flash_do_start, &flash_do_end);
flash_do_storage_init (&flash_do_start, &flash_do_end);
if (flash_do_start == NULL)
file_selection = FILE_CARD_TERMINATED;
@@ -116,7 +117,7 @@ gpg_init (void)
file_selection = FILE_NONE;
gpg_data_scan (flash_do_start, flash_do_end);
flash_init_keys ();
flash_key_storage_init ();
}
static void
@@ -170,7 +171,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 +194,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);
@@ -299,6 +307,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 +349,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 +366,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 +407,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 +452,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 ();
}
@@ -516,6 +571,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 +598,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 +653,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);
@@ -644,10 +722,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 +736,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
@@ -669,7 +749,6 @@ cmd_read_binary (void)
{
int is_short_EF = (P1 (apdu) & 0x80) != 0;
uint8_t file_id;
const uint8_t *p;
uint16_t offset;
DEBUG_INFO (" - Read binary\r\n");
@@ -679,13 +758,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 +777,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,6 +813,11 @@ cmd_read_binary (void)
}
}
#endif
else
{
GPG_NO_FILE ();
return;
}
}
static void
@@ -1200,6 +1281,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)
{
@@ -1216,9 +1298,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 ();
}
@@ -1248,6 +1331,7 @@ cmd_write_binary (void)
}
#ifdef FLASH_UPGRADE_SUPPORT
static void
cmd_external_authenticate (void)
{
@@ -1289,6 +1373,7 @@ cmd_external_authenticate (void)
set_res_sw (0xff, 0xff);
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
}
#endif
static void
cmd_get_challenge (void)
@@ -1395,8 +1480,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 },

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 *
@@ -986,9 +991,7 @@ tim_main (void *arg)
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 *
@@ -1030,8 +1033,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 0x0150 /* 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

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 *);

View File

@@ -1,7 +1,7 @@
/*
* usb-ccid.c -- USB CCID protocol handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -30,6 +30,7 @@
#include "config.h"
#ifdef DEBUG
#include "usb-cdc.h"
#include "debug.h"
struct stdout stdout;
#endif
@@ -345,13 +346,21 @@ static void get_sw1sw2 (struct ep_in *epi, size_t len)
epi->next_buf = no_buf;
}
#ifdef GNU_LINUX_EMULATION
static uint8_t endp1_tx_buf[64]; /* Only support single CCID interface. */
#endif
/*
* Tx done callback
*/
static void
EP1_IN_Callback (uint16_t len)
ccid_tx_done (uint8_t ep_num, uint16_t len)
{
/*
* If we support multiple CCID interfaces, we select endpoint object
* by EP_NUM. Because it has only single CCID interface now, it's
* hard-coded, here.
*/
struct ep_in *epi = &endpoint_in;
(void)len;
@@ -361,7 +370,12 @@ EP1_IN_Callback (uint16_t len)
else
{
epi->tx_done = 1;
usb_lld_tx_enable (epi->ep_num, 0); /* send ZLP */
/* send ZLP */
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (ep_num, endp1_tx_buf, 0);
#else
usb_lld_tx_enable (ep_num, 0);
#endif
}
else
{
@@ -372,7 +386,11 @@ EP1_IN_Callback (uint16_t len)
while (epi->buf)
if (epi->buf_len < remain)
{
usb_lld_txcpy (epi->buf, epi->ep_num, offset, epi->buf_len);
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+offset, epi->buf, epi->buf_len);
#else
usb_lld_txcpy (epi->buf, ep_num, offset, epi->buf_len);
#endif
offset += epi->buf_len;
remain -= epi->buf_len;
tx_size += epi->buf_len;
@@ -380,7 +398,11 @@ EP1_IN_Callback (uint16_t len)
}
else
{
usb_lld_txcpy (epi->buf, epi->ep_num, offset, remain);
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+offset, epi->buf, remain);
#else
usb_lld_txcpy (epi->buf, ep_num, offset, remain);
#endif
epi->buf += remain;
epi->cnt += remain;
epi->buf_len -= remain;
@@ -390,7 +412,12 @@ EP1_IN_Callback (uint16_t len)
if (tx_size < USB_LL_BUF_SIZE)
epi->tx_done = 1;
usb_lld_tx_enable (epi->ep_num, tx_size);
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (ep_num, endp1_tx_buf, tx_size);
#else
usb_lld_tx_enable (ep_num, tx_size);
#endif
}
}
@@ -609,6 +636,9 @@ static void ccid_abdata (struct ep_out *epo, size_t len)
}
}
#ifdef GNU_LINUX_EMULATION
static uint8_t endp1_rx_buf[64]; /* Only support single CCID interface. */
#endif
static void
ccid_prepare_receive (struct ccid *c)
@@ -619,17 +649,25 @@ ccid_prepare_receive (struct ccid *c)
c->epo->cnt = 0;
c->epo->next_buf = ccid_abdata;
c->epo->end_rx = end_ccid_rx;
#ifdef GNU_LINUX_EMULATION
usb_lld_rx_enable_buf (c->epo->ep_num, endp1_rx_buf, 64);
#else
usb_lld_rx_enable (c->epo->ep_num);
#endif
DEBUG_INFO ("Rx ready\r\n");
}
/*
* Rx ready callback
*/
static void
EP1_OUT_Callback (uint16_t len)
ccid_rx_ready (uint8_t ep_num, uint16_t len)
{
/*
* If we support multiple CCID interfaces, we select endpoint object
* by EP_NUM. Because it has only single CCID interface now, it's
* hard-coded, here.
*/
struct ep_out *epo = &endpoint_out;
int offset = 0;
int cont;
@@ -640,7 +678,11 @@ EP1_OUT_Callback (uint16_t len)
break;
else if (len <= epo->buf_len)
{
usb_lld_rxcpy (epo->buf, epo->ep_num, offset, len);
#ifdef GNU_LINUX_EMULATION
memcpy (epo->buf, endp1_rx_buf + offset, len);
#else
usb_lld_rxcpy (epo->buf, ep_num, offset, len);
#endif
epo->buf += len;
epo->cnt += len;
epo->buf_len -= len;
@@ -648,7 +690,11 @@ EP1_OUT_Callback (uint16_t len)
}
else /* len > buf_len */
{
usb_lld_rxcpy (epo->buf, epo->ep_num, offset, epo->buf_len);
#ifdef GNU_LINUX_EMULATION
memcpy (epo->buf, endp1_rx_buf + offset, epo->buf_len);
#else
usb_lld_rxcpy (epo->buf, ep_num, offset, epo->buf_len);
#endif
len -= epo->buf_len;
offset += epo->buf_len;
epo->next_buf (epo, len); /* Update epo->buf, cnt, buf_len */
@@ -661,7 +707,11 @@ EP1_OUT_Callback (uint16_t len)
cont = epo->end_rx (epo, orig_len);
if (cont)
usb_lld_rx_enable (epo->ep_num);
#ifdef GNU_LINUX_EMULATION
usb_lld_rx_enable_buf (ep_num, endp1_rx_buf, 64);
#else
usb_lld_rx_enable (ep_num);
#endif
else
notify_icc (epo);
}
@@ -669,16 +719,24 @@ EP1_OUT_Callback (uint16_t len)
extern void EP6_IN_Callback (uint16_t len);
#if defined(DEBUG) && defined(GNU_LINUX_EMULATION)
static uint8_t endp5_buf[VIRTUAL_COM_PORT_DATA_SIZE];
#endif
static void
usb_rx_ready (uint8_t ep_num, uint16_t len)
{
if (ep_num == ENDP1)
EP1_OUT_Callback (len);
ccid_rx_ready (ep_num, len);
#ifdef DEBUG
else if (ep_num == ENDP5)
{
chopstx_mutex_lock (&stdout.m_dev);
#ifdef GNU_LINUX_EMULATION
usb_lld_rx_enable (ep_num, endp5_buf, VIRTUAL_COM_PORT_DATA_SIZE);
#else
usb_lld_rx_enable (ep_num);
#endif
chopstx_mutex_unlock (&stdout.m_dev);
}
#endif
@@ -688,7 +746,7 @@ static void
usb_tx_done (uint8_t ep_num, uint16_t len)
{
if (ep_num == ENDP1)
EP1_IN_Callback (len);
ccid_tx_done (ep_num, len);
else if (ep_num == ENDP2)
{
/* INTERRUPT Transfer done */
@@ -756,14 +814,21 @@ static void ccid_error (struct ccid *c, int offset)
/* This is a single packet Bulk-IN transaction */
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, ccid_reply, CCID_MSG_HEADER_SIZE);
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf, CCID_MSG_HEADER_SIZE);
#else
usb_lld_write (c->epi->ep_num, ccid_reply, CCID_MSG_HEADER_SIZE);
#endif
}
extern void *openpgp_card_thread (void *arg);
extern uint8_t __process3_stack_base__[], __process3_stack_size__[];
#define STACK_ADDR_GPG ((uint32_t)__process3_stack_base__)
#define STACK_SIZE_GPG ((uint32_t)__process3_stack_size__)
#define STACK_PROCESS_3
#include "stack-def.h"
#define STACK_ADDR_GPG ((uintptr_t)process3_base)
#define STACK_SIZE_GPG (sizeof process3_base)
#define PRIO_GPG 1
@@ -793,9 +858,14 @@ ccid_power_on (struct ccid *c)
p[CCID_MSG_ERROR_OFFSET] = 0x00;
p[CCID_MSG_CHAIN_OFFSET] = 0x00;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, ATR_head, sizeof (ATR_head));
#else
usb_lld_txcpy (p, c->epi->ep_num, 0, CCID_MSG_HEADER_SIZE);
usb_lld_txcpy (ATR_head, c->epi->ep_num, CCID_MSG_HEADER_SIZE,
sizeof (ATR_head));
#endif
for (i = 1; i < (int)sizeof (ATR_head); i++)
xor_check ^= ATR_head[i];
memcpy (p, historical_bytes + 1, hist_len);
@@ -806,13 +876,22 @@ ccid_power_on (struct ccid *c)
for (i = 0; i < hist_len; i++)
xor_check ^= p[i];
p[i] = xor_check;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE+sizeof (ATR_head), p, hist_len+1);
#else
usb_lld_txcpy (p, c->epi->ep_num, CCID_MSG_HEADER_SIZE + sizeof (ATR_head),
hist_len+1);
#endif
/* This is a single packet Bulk-IN transaction */
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf,
CCID_MSG_HEADER_SIZE + size_atr);
#else
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE + size_atr);
#endif
DEBUG_INFO ("ON\r\n");
return CCID_STATE_WAIT;
@@ -843,7 +922,13 @@ ccid_send_status (struct ccid *c)
/* This is a single packet Bulk-IN transaction */
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, ccid_reply, CCID_MSG_HEADER_SIZE);
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf, CCID_MSG_HEADER_SIZE);
#else
usb_lld_write (c->epi->ep_num, ccid_reply, CCID_MSG_HEADER_SIZE);
#endif
led_blink (LED_SHOW_STATUS);
#ifdef DEBUG_MORE
@@ -890,19 +975,35 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
p[CCID_MSG_ERROR_OFFSET] = error;
p[CCID_MSG_CHAIN_OFFSET] = 0;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
#else
usb_lld_txcpy (p, c->epi->ep_num, 0, CCID_MSG_HEADER_SIZE);
#endif
if (len == 0)
{
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf,
CCID_MSG_HEADER_SIZE);
#else
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE);
#endif
return;
}
if (CCID_MSG_HEADER_SIZE + len <= USB_LL_BUF_SIZE)
{
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE,
c->a->res_apdu_data, c->a->res_apdu_data_len);
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE+c->a->res_apdu_data_len,
c->sw1sw2, 2);
#else
usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num,
CCID_MSG_HEADER_SIZE, c->a->res_apdu_data_len);
usb_lld_txcpy (c->sw1sw2, c->epi->ep_num,
CCID_MSG_HEADER_SIZE + c->a->res_apdu_data_len, 2);
#endif
c->epi->buf = NULL;
if (CCID_MSG_HEADER_SIZE + len < USB_LL_BUF_SIZE)
c->epi->tx_done = 1;
@@ -910,10 +1011,17 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
}
else if (CCID_MSG_HEADER_SIZE + len - 1 == USB_LL_BUF_SIZE)
{
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE,
c->a->res_apdu_data, c->a->res_apdu_data_len);
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE+c->a->res_apdu_data_len,
c->sw1sw2, 1);
#else
usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num,
CCID_MSG_HEADER_SIZE, c->a->res_apdu_data_len);
usb_lld_txcpy (c->sw1sw2, c->epi->ep_num,
CCID_MSG_HEADER_SIZE + c->a->res_apdu_data_len, 1);
#endif
c->epi->buf = &c->sw1sw2[1];
c->epi->cnt = 1;
c->epi->buf_len = 1;
@@ -921,8 +1029,13 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
}
else if (CCID_MSG_HEADER_SIZE + len - 2 == USB_LL_BUF_SIZE)
{
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE,
c->a->res_apdu_data, c->a->res_apdu_data_len);
#else
usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num,
CCID_MSG_HEADER_SIZE, c->a->res_apdu_data_len);
#endif
c->epi->buf = &c->sw1sw2[0];
c->epi->cnt = 0;
c->epi->buf_len = 2;
@@ -930,8 +1043,13 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
}
else
{
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE,
c->a->res_apdu_data, USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
#else
usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num, CCID_MSG_HEADER_SIZE,
USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
#endif
c->epi->buf = c->a->res_apdu_data + USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
c->epi->cnt = USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
c->epi->buf_len = c->a->res_apdu_data_len
@@ -939,7 +1057,11 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
c->epi->next_buf = get_sw1sw2;
}
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf, tx_size);
#else
usb_lld_tx_enable (c->epi->ep_num, tx_size);
#endif
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
@@ -976,11 +1098,20 @@ ccid_send_data_block_0x9000 (struct ccid *c)
p[CCID_MSG_CHAIN_OFFSET+1] = 0x90;
p[CCID_MSG_CHAIN_OFFSET+2] = 0x00;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE + len);
#else
usb_lld_txcpy (p, c->epi->ep_num, 0, CCID_MSG_HEADER_SIZE + len);
#endif
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf,
CCID_MSG_HEADER_SIZE + len);
#else
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE + len);
#endif
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
@@ -1007,7 +1138,11 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len)
p[CCID_MSG_ERROR_OFFSET] = 0;
p[CCID_MSG_CHAIN_OFFSET] = 0;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
#else
usb_lld_txcpy (p, c->epi->ep_num, 0, CCID_MSG_HEADER_SIZE);
#endif
set_sw1sw2 (c, chunk_len);
@@ -1022,10 +1157,19 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len)
else
size_for_sw = 0;
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->p, chunk_len);
#else
usb_lld_txcpy (c->p, c->epi->ep_num, CCID_MSG_HEADER_SIZE, chunk_len);
#endif
if (size_for_sw)
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE+chunk_len,
c->sw1sw2, size_for_sw);
#else
usb_lld_txcpy (c->sw1sw2, c->epi->ep_num,
CCID_MSG_HEADER_SIZE + chunk_len, size_for_sw);
#endif
tx_size = CCID_MSG_HEADER_SIZE + chunk_len + size_for_sw;
if (size_for_sw == 2)
{
@@ -1044,8 +1188,13 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len)
}
else
{
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE,
c->p, USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
#else
usb_lld_txcpy (c->p, c->epi->ep_num, CCID_MSG_HEADER_SIZE,
USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
#endif
c->epi->buf = c->p + USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
c->epi->cnt = 0;
c->epi->buf_len = chunk_len - (USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
@@ -1054,7 +1203,11 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len)
c->p += chunk_len;
c->len -= chunk_len;
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf, tx_size);
#else
usb_lld_tx_enable (c->epi->ep_num, tx_size);
#endif
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
@@ -1086,13 +1239,23 @@ ccid_send_params (struct ccid *c)
p[CCID_MSG_ERROR_OFFSET] = 0;
p[CCID_MSG_CHAIN_OFFSET] = 0x01; /* ProtocolNum: T=1 */
#ifdef GNU_LINUX_EMULATION
memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, params, sizeof params);
#else
usb_lld_txcpy (p, c->epi->ep_num, 0, CCID_MSG_HEADER_SIZE);
usb_lld_txcpy (params, c->epi->ep_num, CCID_MSG_HEADER_SIZE, sizeof params);
#endif
/* This is a single packet Bulk-IN transaction */
c->epi->buf = NULL;
c->epi->tx_done = 1;
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (c->epi->ep_num, endp1_tx_buf,
CCID_MSG_HEADER_SIZE + sizeof params);
#else
usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE + sizeof params);
#endif
#ifdef DEBUG_MORE
DEBUG_INFO ("PARAMS\r\n");
#endif
@@ -1350,15 +1513,10 @@ ccid_card_change_signal (int how)
eventflag_signal (&c->ccid_comm, EV_CARD_CHANGE);
}
void
ccid_usb_reset (int full)
{
struct ccid *c = &ccid;
eventflag_signal (&c->ccid_comm,
full ? EV_USB_DEVICE_RESET : EV_USB_SET_INTERFACE);
}
#ifdef GNU_LINUX_EMULATION
static uint8_t endp2_tx_buf[2];
#endif
#define NOTIFY_SLOT_CHANGE 0x50
static void
@@ -1374,7 +1532,12 @@ ccid_notify_slot_change (struct ccid *c)
notification[0] = NOTIFY_SLOT_CHANGE;
notification[1] = msg;
#ifdef GNU_LINUX_EMULATION
memcpy (endp2_tx_buf, notification, sizeof notification);
usb_lld_tx_enable_buf (ENDP2, endp2_tx_buf, sizeof notification);
#else
usb_lld_write (ENDP2, notification, sizeof notification);
#endif
led_blink (LED_TWOSHOTS);
}
@@ -1384,8 +1547,6 @@ ccid_notify_slot_change (struct ccid *c)
#define GPG_THREAD_TERMINATED 0xffff
#define INTR_REQ_USB 20
extern uint32_t bDeviceState;
extern void usb_device_reset (struct usb_dev *dev);
extern int usb_setup (struct usb_dev *dev);
@@ -1397,7 +1558,16 @@ extern int usb_get_status_interface (struct usb_dev *dev);
extern int usb_get_descriptor (struct usb_dev *dev);
static void
extern void random_init (void);
extern void random_fini (void);
/*
* Return 0 for normal USB event
* -1 for USB reset
* 1 for SET_INTERFACE or SET_CONFIGURATION
*/
static int
usb_event_handle (struct usb_dev *dev)
{
uint8_t ep_num;
@@ -1406,94 +1576,119 @@ usb_event_handle (struct usb_dev *dev)
e = usb_lld_event_handler (dev);
ep_num = USB_EVENT_ENDP (e);
/* Transfer to endpoint (not control endpoint) */
if (ep_num != 0)
{
if (USB_EVENT_TXRX (e))
usb_tx_done (ep_num, USB_EVENT_LEN (e));
else
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
return 0;
}
else
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (dev);
break;
case USB_EVENT_DEVICE_ADDRESSED:
bDeviceState = ADDRESSED;
break;
/* Control endpoint */
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (dev);
return -1;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_DEVICE_ADDRESSED:
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
break;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (dev) < 0)
usb_lld_ctrl_error (dev);
else
{
if (bDeviceState == USB_DEVICE_STATE_ADDRESSED)
/* de-Configured */
return -1;
else
/* Configured */
return 1;
}
break;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_INTERFACE:
if (usb_set_interface (dev) < 0)
usb_lld_ctrl_error (dev);
else
return 1;
break;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_GET_STATUS_INTERFACE:
if (usb_get_status_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (dev);
break;
case USB_EVENT_GET_INTERFACE:
if (usb_get_interface (dev) < 0)
usb_lld_ctrl_error (dev);
break;
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (dev);
break;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (dev);
break;
case USB_EVENT_OK:
case USB_EVENT_DEVICE_SUSPEND:
default:
break;
}
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (dev);
break;
case USB_EVENT_DEVICE_SUSPEND:
led_blink (LED_OFF);
chopstx_usec_wait (10); /* Make sure LED off */
random_fini ();
chopstx_conf_idle (2);
bDeviceState |= USB_DEVICE_STATE_SUSPEND;
break;
case USB_EVENT_DEVICE_WAKEUP:
chopstx_conf_idle (1);
random_init ();
bDeviceState &= ~USB_DEVICE_STATE_SUSPEND;
break;
case USB_EVENT_OK:
default:
break;
}
return 0;
}
static void
poll_event_intr (uint32_t *timeout, struct eventflag *ev, chopstx_intr_t *intr)
{
chopstx_poll_cond_t poll_desc;
struct chx_poll_head *pd_array[2] = {
(struct chx_poll_head *)intr,
(struct chx_poll_head *)&poll_desc
};
eventflag_prepare_poll (ev, &poll_desc);
chopstx_poll (timeout, 2, pd_array);
}
static chopstx_intr_t interrupt;
static chopstx_poll_cond_t ccid_event_poll_desc;
static struct chx_poll_head *const ccid_poll[] = {
(struct chx_poll_head *const)&interrupt,
(struct chx_poll_head *const)&ccid_event_poll_desc
};
#define CCID_POLL_NUM (sizeof (ccid_poll)/sizeof (struct chx_poll_head *))
void *
ccid_thread (void *arg)
{
chopstx_intr_t interrupt;
uint32_t timeout;
struct usb_dev dev;
struct ccid *c = &ccid;
uint32_t *timeout_p;
(void)arg;
@@ -1504,7 +1699,9 @@ ccid_thread (void *arg)
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
usb_event_handle (&dev); /* For old SYS < 3.0 */
device_reset:
eventflag_prepare_poll (&c->ccid_comm, &ccid_event_poll_desc);
reset:
{
struct ep_in *epi = &endpoint_in;
struct ep_out *epo = &endpoint_out;
@@ -1516,50 +1713,48 @@ ccid_thread (void *arg)
ccid_init (c, epi, epo, a);
}
while (bDeviceState != CONFIGURED)
timeout = USB_CCID_TIMEOUT;
if (bDeviceState == USB_DEVICE_STATE_CONFIGURED)
{
poll_event_intr (NULL, &c->ccid_comm, &interrupt);
if (interrupt.ready)
usb_event_handle (&dev);
eventflag_get (&c->ccid_comm);
/* Ignore event while not-configured. */
ccid_prepare_receive (c);
ccid_notify_slot_change (c);
}
interface_reset:
timeout = USB_CCID_TIMEOUT;
ccid_prepare_receive (c);
ccid_notify_slot_change (c);
while (1)
{
eventmask_t m;
poll_event_intr (&timeout, &c->ccid_comm, &interrupt);
if (bDeviceState == USB_DEVICE_STATE_CONFIGURED)
timeout_p = &timeout;
else
timeout_p = NULL;
chopstx_poll (timeout_p, CCID_POLL_NUM, ccid_poll);
if (interrupt.ready)
{
usb_event_handle (&dev);
continue;
}
if (usb_event_handle (&dev) == 0)
continue;
timeout = USB_CCID_TIMEOUT;
m = eventflag_get (&c->ccid_comm);
if (m == EV_USB_DEVICE_RESET)
{
/* RESET handling:
* (1) After DEVICE_RESET, it needs to re-start out of the loop.
* (2) After SET_CONFIGURATION or SET_INTERFACE, the
* endpoint is reset to RX_NAK. It needs to prepare
* receive again.
*/
if (c->application)
{
chopstx_cancel (c->application);
chopstx_join (c->application, NULL);
c->application = 0;
}
goto device_reset;
goto reset;
}
else if (m == EV_USB_SET_INTERFACE)
/* Upon receival of SET_INTERFACE, the endpoint is reset to RX_NAK.
* Thus, we need to prepare receive again.
*/
goto interface_reset;
else if (m == EV_CARD_CHANGE)
timeout = USB_CCID_TIMEOUT;
m = eventflag_get (&c->ccid_comm);
if (m == EV_CARD_CHANGE)
{
if (c->ccid_state == CCID_STATE_NOCARD)
/* Inserted! */
@@ -1644,7 +1839,7 @@ ccid_thread (void *arg)
}
/* Loading reGNUal. */
while (bDeviceState != UNCONNECTED)
while (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
{
chopstx_intr_wait (&interrupt);
usb_event_handle (&dev);
@@ -1687,7 +1882,11 @@ _write (const char *s, int len)
(len < VIRTUAL_COM_PORT_DATA_SIZE) ? len : VIRTUAL_COM_PORT_DATA_SIZE;
chopstx_mutex_lock (&stdout.m_dev);
#ifdef GNU_LINUX_EMULATION
usb_lld_tx_enable_buf (ENDP3, s, packet_len);
#else
usb_lld_write (ENDP3, s, packet_len);
#endif
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);

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
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -38,6 +38,7 @@
#include "usb_lld.h"
#include "usb_conf.h"
#include "gnuk.h"
#include "neug.h"
#ifdef ENABLE_VIRTUAL_COM_PORT
#include "usb-cdc.h"
@@ -86,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
@@ -107,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
{
@@ -128,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);
}
@@ -137,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);
}
@@ -145,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
{
@@ -160,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);
@@ -179,15 +207,18 @@ usb_device_reset (struct usb_dev *dev)
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);
gnuk_setup_endpoints_for_interface (dev, i, 1);
bDeviceState = ATTACHED;
ccid_usb_reset (1);
bDeviceState = USB_DEVICE_STATE_DEFAULT;
}
#define USB_CCID_REQ_ABORT 0x01
@@ -201,22 +232,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
#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)
{
if (check_crc32 ((const uint32_t *)&_regnual_start, end_p))
uint32_t crc32 = *end_p;
const uint32_t *p;
crc32_rv_reset ();
for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
crc32_rv_step (rbit (*p));
if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
return usb_lld_ctrl_ack (dev);
return -1;
}
#endif
int
usb_setup (struct usb_dev *dev)
@@ -228,15 +271,22 @@ 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 */
{
#ifdef FLASH_UPGRADE_SUPPORT
uint8_t *addr = sram_address ((arg->value * 0x100) + arg->index);
#endif
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
return -1;
@@ -248,9 +298,13 @@ 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)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
return -1;
@@ -258,6 +312,9 @@ usb_setup (struct usb_dev *dev)
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)
{
@@ -356,7 +413,7 @@ usb_ctrl_write_finish (struct usb_dev *dev)
if (*ccid_state_p != 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. */
}
@@ -417,8 +474,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)
{
@@ -427,9 +484,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 */
@@ -450,8 +506,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

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, 2017
Copyright (C) 2011, 2012, 2013, 2015, 2017, 2018
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
@@ -635,3 +635,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")
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,20 @@ 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
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)
gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
gnuk.cmd_select_openpgp()