Compare commits

...

126 Commits

Author SHA1 Message Date
NIIBE Yutaka
40b1d453dc Fix .gitignore. 2018-01-23 13:47:46 +09:00
NIIBE Yutaka
3b965fafc0 Fix README. 2018-01-23 13:26:41 +09:00
NIIBE Yutaka
35edbdc731 Version 1.2.8. 2018-01-23 10:13:13 +09:00
NIIBE Yutaka
d4c776e308 Fix the procedure to put VID:PID. Apply the procedure to regnual. 2018-01-23 10:11:35 +09:00
NIIBE Yutaka
6c0c510347 Update documentation. 2018-01-23 09:31:03 +09:00
NIIBE Yutaka
704d8a5cf1 Check passphrase length when changing. 2018-01-22 11:55:10 +09:00
NIIBE Yutaka
55781cb7bb Remove keystring with BY_ADMIN when it's becomming admin-less mode. 2018-01-22 11:02:02 +09:00
NIIBE Yutaka
de24655920 VIDPID substitution at the last stage of build. 2018-01-19 22:36:01 +09:00
NIIBE Yutaka
7bfe0f5427 Add binary-edit.sh. 2018-01-19 22:22:29 +09:00
NIIBE Yutaka
ec058537ed Update Chopstx to 1.8. 2018-01-19 22:15:21 +09:00
NIIBE Yutaka
abeb1015ec Update neug.c. 2018-01-18 19:42:40 +09:00
NIIBE Yutaka
c5f20dc355 Update Chopstx and follow the changes. 2018-01-18 15:14:34 +09:00
NIIBE Yutaka
4ff0b3c5f8 tests: Fix for card readers. 2018-01-09 09:39:42 +09:00
NIIBE Yutaka
4e517778d0 Update Chopstx to 1.7. 2017-12-19 10:24:28 +09:00
NIIBE Yutaka
c81544fffd Fix long-standing bug of admin-less mode. GnuPG should be fixed. 2017-11-26 21:20:46 +09:00
NIIBE Yutaka
ad42010272 Version 1.2.7. 2017-11-26 19:38:26 +09:00
NIIBE Yutaka
8ce91267be Fix regnual. 2017-11-26 19:28:03 +09:00
NIIBE Yutaka
b5c2ace2ae NEWS update. 2017-11-25 15:02:51 +09:00
NIIBE Yutaka
4cbc661fb7 Update Chopstx to 1.6. 2017-11-24 20:53:40 +09:00
NIIBE Yutaka
543f28574e Use of eventflag poll change. 2017-11-17 20:10:13 +09:00
NIIBE Yutaka
fe94e1885b LED status loop change.
Using chopstx_poll, it requires more memory on stack.
2017-11-17 17:20:52 +09:00
NIIBE Yutaka
ce82b347f9 Make sure to turn off LED soon. 2017-11-17 16:25:26 +09:00
NIIBE Yutaka
d54712c04c Less power consumption on suspend. 2017-11-17 15:49:56 +09:00
NIIBE Yutaka
9c63c874d0 Fix ReGNUal. 2017-11-17 15:47:59 +09:00
NIIBE Yutaka
bb9b31166f Fix NeuG for CRC module clock setting. 2017-11-17 15:47:22 +09:00
NIIBE Yutaka
e417846408 More change for USB suspend. 2017-11-17 12:29:32 +09:00
NIIBE Yutaka
21a481060c Make sure to turn off LED on suspend. 2017-11-16 13:08:00 +09:00
NIIBE Yutaka
d4c9d6653b Use const pointer for chopstx_poll. 2017-11-16 09:17:33 +09:00
NIIBE Yutaka
f00306627b Fix pin-cir.c for use of EXTI. 2017-11-16 08:40:49 +09:00
NIIBE Yutaka
f4b36b7503 Lower power consumption on suspend. 2017-11-15 10:59:55 +09:00
NIIBE Yutaka
e85527d302 USB suspend/resume change. 2017-11-14 12:59:18 +09:00
NIIBE Yutaka
bd58997dc9 Possibly support other hash in future, for KDF. 2017-11-08 10:28:55 +09:00
NIIBE Yutaka
9d5834d47b Avoid passphrase-error-lock by old GnuPG. 2017-11-07 13:48:08 +09:00
NIIBE Yutaka
36ecf67694 Update tool information in README. 2017-11-06 15:29:02 +09:00
NIIBE Yutaka
c9b1e511ba Fix test and tests. 2017-11-06 10:51:11 +09:00
NIIBE Yutaka
01b5aa5984 Enable KDF-DO available bit. 2017-11-02 13:53:06 +09:00
NIIBE Yutaka
b735c02ec2 Implement use of KDF data object. 2017-11-02 10:59:17 +09:00
NIIBE Yutaka
2ecb104ae4 Implement rw_kdf. 2017-11-02 09:28:43 +09:00
NIIBE Yutaka
6b4f3c9934 Start adding KDF-DO of OpenPGPcard v3. 2017-11-01 16:52:58 +09:00
NIIBE Yutaka
660aaeb04b Bug fix for keygeneration. 2017-10-31 17:10:03 +09:00
NIIBE Yutaka
1022534c02 Fix gpg_do_keygen. 2017-10-30 15:01:17 +09:00
Daniel Kahn Gillmor
46cc64cf03 fix documentation typo 2017-10-25 16:54:41 +09:00
NIIBE Yutaka
effc65381a Don't change PPS for other readers. 2017-10-24 20:39:51 +09:00
Aurelien Jarno
6cbf5a4822 linker script: fix keystore_pool size
Gnuk supports RSA keys up to 4096 bits. This require 1024 bytes of
storage (p and q are 256 bytes, n is 512 bytes). The linker script
should therefore reserve 1024 bytes per key instead of 512.

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

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

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

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

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

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

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

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

Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
2017-07-18 13:15:42 +09:00
NIIBE Yutaka
de81caba3e Update Chopstx.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-07-18 12:58:23 +09:00
NIIBE Yutaka
fa69a85826 Version 1.2.4.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-12 17:22:20 +09:00
NIIBE Yutaka
5c3c3e3001 usbip list -r 127.0.0.1 now works.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-12 14:13:53 +09:00
NIIBE Yutaka
6dcb4dd027 Add usb-emu.c.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-02 15:05:15 +09:00
NIIBE Yutaka
fa08f44cac Fix old documentation (note) for firmware update.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-05-01 14:58:15 +09:00
NIIBE Yutaka
4c2294ea6c Portability change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 16:14:30 +09:00
NIIBE Yutaka
86eaa26d32 New: src/mcu-stm32f103.c.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 15:49:38 +09:00
NIIBE Yutaka
9e52789203 Fix long standing buf of digital signature counter.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-28 14:54:15 +09:00
NIIBE Yutaka
702bc8cbde Move data objects at the end of flash.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-27 15:23:25 +09:00
NIIBE Yutaka
2cfce76d91 [SECURITY] Flash memory usage change.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-04-27 14:36:32 +09:00
NIIBE Yutaka
207652246a emulation: USB device emulation by USBIP protocol. 2017-04-18 15:45:25 +09:00
59 changed files with 2646 additions and 861 deletions

4
.gitignore vendored
View File

@@ -1,13 +1,15 @@
*.lst
*.o
*.pyc
regnual/regnual-no-vidpid.elf
src/.dep
src/Makefile
src/config.mk
src/config.h
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

17
AUTHORS
View File

@@ -1,3 +1,20 @@
Aurelien Jarno:
Modified:
src/Makefile
src/configure
src/main.c
src/stack-def.h
Anthony Romano:
Modified:
src/call-rsa.c
src/main.c
src/mod.c
Jeremy Drake:
Modified:
regnual/regnual.c
Kaz Kojima:
Added STM32 Primer2 support.

500
ChangeLog
View File

@@ -1,3 +1,503 @@
2018-01-23 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.8.
* src/Makefile (build/gnuk-vidpid.elf): Supply FILE here.
* src/configure (output_vendor_product_serial_strings): For
generating put-vid-pid-ver.sh, don't set FILE.
* regnual/regnual.c (regnual_device_desc): Make this array as a
template.
* regnual/Makefile (regnual.elf): Substitute VID:PID.
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (USER_PASSWD_MINLEN): New.
(cmd_change_password): Check passphrase length.
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_change_password): Remove access to private
key with BY_ADMIN when it's becoming admin-less mode.
2018-01-19 NIIBE Yutaka <gniibe@fsij.org>
* src/binary-edit.sh: Copied from NeuG 1.0.8. Exclude FILE.
* src/configure (output_vid_pid_version): Generate a shell script.
* src/Makefile (build/gnuk-vidpid.elf): New target.
* src/usb_desc.c (device_desc): Make this array as a template.
* chopstx: Update to 1.8.
2018-01-18 NIIBE Yutaka <gniibe@fsij.org>
* src/neug.c: Update from NeuG.
2018-01-09 NIIBE Yutaka <gniibe@fsij.org>
* tests/card_reader.py (CardReader.ccid_power_on): Fix for
other card readers for Gemalto's.
2017-12-19 NIIBE Yutaka <gniibe@fsij.org>
* chopstx: Update to 1.7.
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_change_password): Bug fix for admin-less
mode.
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.7.
2017-11-24 NIIBE Yutaka <gniibe@fsij.org>
* regnual/regnual.c (calc_crc32): Enable CRC module fix.
* chopstx: Update to 1.6.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_0): Decrease.
* src/main.c (emit_led, display_status_code, main): Use
chopstx_poll instead of eventflag_wait_timeout.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_0): Increase.
* src/main.c (emit_led, display_status_code, main): Use
eventflag_wait_timeout instead of chopstx_usec_wait.
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
* regnual/regnual.c (calc_crc32): Enable CRC module.
* src/neug.c (crc32_rv_stop): New.
(neug_fini): Call crc32_rv_stop.
* src/main.c (main): Call chopstx_conf_idle.
* src/usb-ccid.c (usb_event_handle): Use 2 for call of
chopstx_conf_idle on suspend. Call random_fini on suspend
to stop ADC module. Call random_init on wakeup.
Sleep a bit to switch main thread.
2017-11-16 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.h (LED_OFF): New.
* src/usb-ccid.c (usb_event_handle): LED off on sleep.
(ccid_thread): Use constant pointer for chopstx_poll.
(poll_event_intr): Remove.
2017-11-15 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (usb_event_handle): Allow sleep on suspend.
* src/usb_ctrl.c (usb_device_reset): Fix device state.
2017-11-14 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (ccid_usb_reset): Remove
(usb_event_handle): Return value change to notify
caller about needs for going out of the loop.
Support USB suspend/resume.
(ccid_thread): Supporting USB suspend, sleep forever with
timeout_p = NULL.
* src/main.c (main): Add USB_DEVICE_STATE_ prefix.
* src/usb_ctrl.c: Likewise.
(usb_device_reset): Don't call ccid_usb_reset.
(usb_set_configuration, usb_set_interface): Likewise.
* src/usb_desc.c (device_desc): bcdUSB = 2.0, supporting
suspend/resume.
2017-11-13 NIIBE Yutaka <gniibe@fsij.org>
* src/usb_ctrl.c: Use new const USB_DEVICE_STATE_*
* src/main.c (main): Likewise.
* src/usb-ccid.c: Likewise.
(INTR_REQ_USB): Remove. Use the definition
in usb-lld.h.
2017-11-08 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_kdf_check): New.
(proc_resetting_code): Use gpg_do_kdf_check.
* src/openpgp.c (cmd_verify, cmd_change_password)
(cmd_reset_user_password): Likewise.
2017-11-07 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (proc_resetting_code): Error when
it's not pass-hash.
* src/openpgp.c (cmd_verify, cmd_change_password)
(cmd_reset_user_password): Avoid authentication error
by old GnuPG which doesn't support KDF.
2017-11-06 NIIBE Yutaka <gniibe@fsij.org>
* tests/test_empty_card.py (test_extended_capabilities): Support
KDF-DO.
* test/features/802_get_data_static.feature: Likewise.
* test/features/402_get_data_static.feature: Likewise.
* test/features/002_get_data_static.feature: Likewise.
2017-11-02 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (rw_kdf): Only writable when no keys.
(gpg_do_get_initial_pw_setting): New.
(gpg_do_write_prvkey): Use gpg_do_get_initial_pw_setting.
(gpg_do_keygen): Likewise.
(extended_capabilities): Enable KDF-DO available bit.
* src/openpgp.c (cmd_change_password): Use
gpg_do_get_initial_pw_setting.
* src/ac.c (verify_user_0, verify_admin_0): Likewise.
2017-11-01 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (GPG_DO_KDF): New.
(GPG_DO_FEATURE_MNGMNT): New.
(do_tag_to_nr): Support GPG_DO_KDF.
(GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
(rw_kdf): New.
(gpg_do_table): Add an entry for GPG_DO_KDF.
* src/gnuk.h (NR_DO_KDF): New.
2017-10-31 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_keygen): Bug fix for memory alignment.
2017-10-24 NIIBE Yutaka <gniibe@fsij.org>
* tests/card_reader.py (CardReader.ccid_power_on): Setting
PPS only for Gemalto GemPC reader.
2017-10-18 Aurelien Jarno <aurelien@aurel32.net>
* src/gnuk.ld.in: Fix keystore_pool size.
2017-10-12 Aurelien Jarno <aurelien@aurel32.net>
* polarssl/include/polarssl/bn_mul.h (MULADDC_HUIT_DEAD): Rename
from MULADDC_HUIT.
[__ARM_FEATURE_DSP] (MULADDC_1024_CORE, MULADDC_1024_LOOP)
(MULADDC_INIT, MULADDC_CORE, MULADDC_HUIT, MULADDC_STOP): New.
* polarssl/library/bignum.c (mpi_montsqr): Check on
POLARSSL_HAVE_ASM and __arm__.
[__ARM_FEATURE_DSP] (mpi_montsqr): New.
(MAX_WSIZE): New.
(mpi_exp_mod): Use MAX_WSIZE.
* src/Makefile (DEFS): Remove BIGNUM_C_IMPLEMENTATION.
* src/main.c (HEAP_SIZE): Rename from MEMORY_SIZE.
(HEAP_END, HEAP_ALIGNMENT, HEAP_ALIGN): Likewise.
* src/stack-def.h (SIZE_3): Depend on MEMORY_SIZE.
* src/configure: Emit DEFS with MEMORY_SIZE.
2017-10-11 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.6.
* regnual/Makefile (LDSCRIPT): Move after include.
* regnual/types.h: Add uintptr_t.
* test/features/002_get_data_static.feature (data object AID): Fix
for any binary value.
* 402_get_data_static.feature: Likewise.
* 802_get_data_static.feature: Likewise.
2017-10-10 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (main): Support --debug option.
* chopstx: Update to 1.5.
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
* src/configure (flash_override): Fix suggested by Jeremy Drake.
(help): STM8S_DISCOVERY is supported again.
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in (.stacks): Specify NOLOAD type.
* src/configure: Allow not specifying VIDPID.
* src/main.c [GNU_LINUX_EMULATION] (main): Handle "--vidpid"
option to assign vendor ID and product ID of USB.
* src/usb_desc.c [GNU_LINUX_EMULATION] (device_desc): Export.
* GNUK_USB_DEVICE_ID (0000:0000): New.
2017-10-05 NIIBE Yutaka <gniibe@fsij.org>
* src/stack-def.h (SIZE_1, SIZE_3): Tweak the size.
* src/call-rsa.c (rsa_genkey): Single step.
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in single
step, using APDU buffer.
* src/openpgp.c (cmd_pgp_gakp): Supply the APDU as a buffer.
* src/Makefile (install): New target.
* src/configure (prefix. exec_prefix, libexecdir): Add.
* src/main.c [GNU_LINUX_EMULATION] (main): Option handling.
* tool/gnuk-emulation-setup: New.
* polarssl/library/bignum.c (M_LIMBS, limbs_M, MAX_A_LIMBS)
(limbs_MAX_A, mpi_gen_prime): Fix for 64-bit machine.
2017-10-04 NIIBE Yutaka <gniibe@fsij.org>
* src/configure (output_vendor_product_serial_strings): Support
GNU/Linux emulation.
* polarssl/library/bignum.c (mpi_div_mpi): Fix for 64-bit machine.
* src/main.c (gnuk_malloc, gnuk_free): Fix for 64-bit machine.
* src/stack-def.h (SIZE_3): Tweak the size.
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in two
steps.
* src/call-rsa.c (rsa_genkey_start, rsa_genkey_finish): New.
(rsa_genkey): Remove.
2017-10-03 NIIBE Yutaka <gniibe@fsij.org>
* src/call-ec.c (ecc_compute_public): No use of malloc.
* src/call-rsa.c (modulus_calc, rsa_genkey): Likewise.
* src/ecc-edwards.c (eddsa_compute_public_25519): Likewise.
* src/ecc-mont.c (ecdh_compute_public_25519): Likewise.
* src/openpgp-do.c (gpg_do_write_prvkey, gpg_do_chks_prvkey)
(proc_key_import, gpg_do_keygen): Likewise.
* polarssl/library/rsa.c: Don't include stdlib.h.
* src/gnuk-malloc.h: Rename from stdlib.h.
* polarssl/library/bignum.c: Include gnuk-malloc.h.
* src/Makefile (build/flash.data): Generate.
* src/main.c (flash_addr_key_storage_start)
(flash_addr_data_storage_start): New.
(main): Determine flash address.
* src/flash.c (FLASH_ADDR_KEY_STORAGE_START)
(FLASH_ADDR_DATA_STORAGE_START): New.
(flash_do_storage_init, flash_terminate, flash_activate)
(flash_key_storage_init, flash_copying_gc, flash_do_release)
(flash_key_getpage): Use new macros.
2017-10-02 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (device_initialize_once): Not for GNU/Linux.
* src/openpgp.c, src/flash.c: Distinguish FLASH_UPGRADE_SUPPORT.
* src/main.c [GNU_LINUX_EMULATION]: Use emulated_main.
(MEMORY_SIZE, MEMORY_END): Fix for GNU/Linux.
* src/usb-ccid.c (INTR_REQ_USB): Fix for GNU/Linux.
* polarssl/library/bignum.c (mpi_montsqr): Easy C implementation.
2017-09-30 NIIBE Yutaka <gniibe@fsij.org>
* src/flash.c (flash_terminate, flash_activate)
(flash_copying_gc, flash_do_write_internal, flash_do_release)
(flash_key_write, flash_check_all_other_keys_released)
(flash_key_fill_zero_as_released, flash_key_release)
(flash_key_release_page, flash_clear_halfword)
(flash_put_data_internal, flash_put_data, flash_bool_clear)
(flash_bool_write_internal, flash_bool_write)
(flash_enum_write_internal, flash_enum_write)
(flash_cnt123_write_internal, flash_cnt123_increment)
(flash_cnt123_clear, flash_erase_binary, flash_write_binary): Fix
for GNU/Linux.
* src/usb-ccid.c (ccid_tx_done): Rename from EP1_IN_Callback.
(ccid_rx_ready): Rename from EP1_OUT_Callback.
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
* src/usb-ccid.c (epo_init, epi_init, ccid_thread): Simplify.
(EP1_IN_Callback, ccid_prepare_receive, EP1_OUT_Callback)
(usb_rx_ready, ccid_error, ccid_power_on, ccid_send_status)
(ccid_send_data_block_internal, ccid_send_data_block_0x9000)
(ccid_send_data_block_gr, ccid_send_params)
(ccid_notify_slot_change, _write) [GNU_LINUX_EMULATION]: Use
different usb driver API.
* src/usb_ctrl.c (usb_device_reset): Fix control endpoint init.
(gnuk_setup_endpoints_for_interface): Add DEV
argument.
(usb_device_reset) [GNU_LINUX_EMULATION]: Use usb_lld_setup_endp.
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c [FLASH_UPGRADE_SUPPORT] (main): Factor out flash ROM
upgrade support.
(calculate_regnual_entry_address): Likewise.
* src/usb_ctrl.c (usb_setup, download_check_crc32): Likewise.
* src/openpgp.c (modify_binary): Fix for 64-bit machine.
* src/openpgp-do.c (encrypt, decrypt): Likewise.
(gpg_data_scan): Likewise.
(gpg_do_chks_prvkey): Fix error return path.
* src/stack-def.h: New.
* src/gnuk.ld.in: Remove stack definitions.
* src/configure: Remove stack size modifications.
* src/main.c (STACK_MAIN, STACK_PROCESS_1): Use stack-def.h.
* src/usb-ccid.c (STACK_PROCESS_3): Likewise.
* src/usb-msc.c (STACK_PROCESS_5): Likewise.
* src/pin-cir.c (STACK_PROCESS_6, STACK_PROCESS_7): Likewise.
* src/usb_ctrl.c (download_check_crc32): Use chrc32_rv_ functions.
* src/mcu-stm32f103.c (rbit, check_crc32): Remove.
* src/neug.c: Update from NeuG.
* src/neug.h: Ditto.
2017-09-28 NIIBE Yutaka <gniibe@fsij.org>
* src/ec_p256k1.c (coefficient_a): Remove.
* polarssl/library/bignum.c (mpi_fill_pseudo_random): Fix for
64-bit machine.
* src/call-rsa.c (rsa_decrypt): Fix for 64-bit machine.
* src/flash.c (flash_do_storage_init): Rename from flash_init.
(flash_key_storage_init): Rename from flash_init_keys.
* src/openpgp.c (gpg_init): Use new function names.
* src/stdlib.h: Update for GNU/Linux emulation.
* src/Makefile: Support GNU/Linux emulation.
* src/configure: Support GNU/Linux emulation.
* emulation: Remove.
2017-08-11 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.5.
* chopstx: Update to 1.4.
* src/gnuk.ld.in (__process3_stack_size__): Tweak the size.
* src/configure: Define STM32F103_OVERRIDE_FLASH_SIZE_KB for
BULE_PILL.
* src/configure: Let generate src/config.mk.
* src/Makefile: Rename from src/Makefile.in.
* regnual/Makefile: Use src/config.mk.
2017-08-03 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_terminate_df): Fix for admin-less mode.
2017-08-03 Jeremy Drake <jeremydrake+gnuk@eacceleration.com>
* regnual/regnual.c (main): Allow compile time
flash size definition by STM32F103_OVERRIDE_FLASH_SIZE_KB.
2017-08-02 Jeremy Drake <jeremydrake+gnuk@eacceleration.com>
* src/flash.c (flash_terminate): Erase Certificate DO, too.
2017-08-01 NIIBE Yutaka <gniibe@fsij.org>
* src/openpgp.c (FILE_CARD_TERMINATED_OPENPGP): Remove.
(cmd_select_file): Don't change file_selection.
2017-07-19 NIIBE Yutaka <gniibe@fsij.org>
* src/mod.c (mod_inv): Clear TMP.
* src/configure (REVISION): Generate even when no git.
* polarssl/library/bignum.c (mpi_exp_mod): Call mpi_grow for X
after the initialization of RR.
2017-07-18 NIIBE Yutaka <gniibe@fsij.org>
* src/configure: Bark when no git available.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* docker: New.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/main.c (MEMORY_SIZE, MEM_HEAD_IS_CORRUPT, MEM_HEAD_CHECK):
New.
(gnuk_malloc, gnuk_free): Add calls to MEM_HEAD_CHECK.
* src/gnuk.h (FATAL_HEAP): New.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/openpgp-do.c (gpg_reset_algo_attr): New.
(rw_algorithm_attr): Use gpg_reset_algo_attr.
Fix null dereference.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/mod.c (mod_reduce): Clean up unused code.
2017-07-18 Anthony Romano <anthony.romano@coreos.com>
* src/call-rsa.c (modulus_calc): Free modulus on error.
(rsa_genkey): Remove bogus check, and call chopstx_cleanup_pop
with 1 to release p_q_modulus on error. Assign NULL to clp.arg
when it's goes with no error.
* src/main.c (gnuk_free): Allow NULL.
2017-07-18 NIIBE Yutaka <gniibe@fsij.org>
* Update chopstx (with USBIP emulation).
2017-05-12 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.4.
2017-04-28 NIIBE Yutaka <gniibe@fsij.org>
* src/mcu-stm32f103.c: New.
(check_crc32, sram_address): New.
* src/usb_ctrl.c (download_check_crc32): Use check_crc32 and
sram_address.
* src/openpgp-do.c (gpg_write_digital_signature_counter): Fix
writing lower 10-bit.
2017-04-27 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in (_data_pool): Move to the end.
* src/flash.c (flash_init): Return address of end of data object.
* src/openpgp.c (gpg_init): Get address of end of data object.
* src/openpgp-do.c (gpg_data_scan): Check the end address.
2017-02-02 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.3.

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

83
NEWS
View File

@@ -1,5 +1,88 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.8
Released 2018-01-23, by NIIBE Yutaka
** No inclusion of VID:PID in gnuk.elf
Distribution of binary image with VID:PID would violate vendor ID
agreement to USB Forum. Now, we have new file named gnuk-vidpid.elf
for flashing. The file gnuk.elf can be used to generate
gnuk-vidpid.elf and we can check if it is reproducible or not.
** Passphrase length check
Now, Gnuk checks length of passphrase if it's too short when
changing passphrase.
** Remove unused DEK with BY_ADMIN
For admin-less mode, DEK by OPENPGP_CARD_INITIAL_PW3 remained on flash
ROM. This could be considered a backdoor, if some other person had or
kept access to the flash ROM, cheating a user. Now, the DEK is
cleared by zero when the token is set to admin-less mode.
** Upgrade of Chopstx
We use Chopstx 1.8.
* Major changes in Gnuk 1.2.7
Released 2017-11-26, by NIIBE Yutaka
** reGNUal
reGNUal enables CRC module by itself.
** Flash update change
CRC module is disabled when Gnuk stops. It's reGNUal which needs to
enable CRC module.
** Support of USB suspend
USB suspend and wakeup event are now handled.
** KDF-DO support and KDF by host
KDF-DO is now available. Host can use this feature.
** Upgrade of Chopstx
We use Chopstx 1.6.
* Major changes in Gnuk 1.2.6
Released 2017-10-11, by NIIBE Yutaka
** Port to GNU/Linux emulation
We can "run" Gnuk Token on GNU/Linux by emulation through USBIP.
** Upgrade of Chopstx
We use Chopstx 1.5.
* Major changes in Gnuk 1.2.5
Released 2017-08-11, by NIIBE Yutaka
** "factory-reset" fix
Gnuk's behavior was implemented by referring the gpg implementation.
It found that gpg implementation was not good from the viewpoint of
the OpenPGP card specification. GnuPG was fixed to match the OpenPGP
card specification already. Thus, Gnuk is now fixed.
** Upgrade of Chopstx
We use Chopstx 1.4.
* Major changes in Gnuk 1.2.4
Released 2017-05-12, by NIIBE Yutaka
** Flash ROM security fix
The partial content of flash ROM might be exposed when scanning of
data object had a problem. Added boundary check and changed layout of
flash ROM.
* Major changes in Gnuk 1.2.3
Released 2017-02-02, by NIIBE Yutaka

75
README
View File

@@ -1,28 +1,34 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.2.3
2017-02-02
Version 1.2.8
2018-01-23
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 1.2.3, which has major
This is the release of Gnuk, version 1.2.8, 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. To use the feature, you need to use
newer GnuPG (forthcoming 2.2.5 or later). And you need to manually
prepare the KDF-DO on your token. Please note that this is
experimental. Better way to prepare KDF-DO will be expected.
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.27-9+9
gcc-arm-none-eabi 15:5.4.1+svn241155-1
gdb-arm-none-eabi 7.11.1-2+9+b1
libnewlib-arm-none-eabi 2.4.0.20160527-2
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-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

4
THANKS
View File

@@ -7,16 +7,19 @@ Gnuk was originally written by NIIBE Yutaka. People contributed by
encouraging the development, testing the implementation, suggesting
improvements, or fixing bugs. Here is a list of those people.
Aurelien Jarno aurelien@aurel32.net
Achim Pietig achim@pietig.com
Aidan Thornton
Anibal Monsalve Salazar anibal@debian.org
Andre Zepezauer andre.zepezauer@student.uni-halle.de
Anthony Romano anthony.romano@coreos.com
Bertrand Jacquin bertrand@jacquin.bzh
Clint Adams clint@softwarefreedom.org
Daniel Kahn Gillmor dkg@fifthhorseman.net
Elliott Mitchell
Hironobu SUZUKI hironobu@h2np.net
Jan Suhr jan@suhr.info
Jeremy Drake jeremydrake+gnuk@eacceleration.com
Jonathan McDowell noodles@earth.li
Kaz Kojima kkojima@rr.iij4u.or.jp
Kenji Rikitake
@@ -33,6 +36,7 @@ Paul Fertser
Paul Bakker polarssl_maintainer@polarssl.org
Santiago Ruano Rincón santiago@debian.org
Shane Coughlan scoughlan@openinventionnetwork.com
Stanislas Bach sbach@0g.re
Szczepan Zalega szczepan@nitrokey.com
Vasily Evseenko
Werner Koch wk@gnupg.org

View File

@@ -1 +1 @@
release/1.2.3
release/1.2.8

Submodule chopstx updated: 89eb54929e...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

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

7
docker/Dockerfile.check Normal file
View File

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

4
docker/Dockerfile.debug Normal file
View File

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

View File

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

36
docker/Makefile Normal file
View File

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

View File

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

View File

@@ -37,7 +37,7 @@
#include "polarssl/bignum.h"
#include "polarssl/bn_mul.h"
#include <stdlib.h>
#include <gnuk-malloc.h>
#define ciL (sizeof(t_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
@@ -223,6 +223,7 @@ size_t mpi_lsb( const mpi *X )
return( 0 );
}
#if !defined(POLARSSL_HAVE_UDBL)
/*
* Count leading zero bits in a given integer
*/
@@ -240,6 +241,7 @@ static size_t int_clz( const t_uint x )
return j;
}
#endif
/*
* Return the number of most significant bits
@@ -1140,9 +1142,9 @@ static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
*/
if(( 0 == d ) || ( u1 >= d ))
{
if (r != NULL) *r = (~0);
if (r != NULL) *r = (~0UL);
return (~0);
return (~0UL);
}
#if defined(POLARSSL_HAVE_UDBL)
@@ -1268,7 +1270,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
for( i = n; i > t ; i-- )
{
if( X.p[i] >= Y.p[t] )
Z.p[i - t - 1] = ~0;
Z.p[i - t - 1] = ~0UL;
else
{
Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i-1], Y.p[t], NULL);
@@ -1295,7 +1297,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
if( mpi_cmp_int( &X, 0 ) < 0 )
while( mpi_cmp_int( &X, 0 ) < 0 )
{
MPI_CHK( mpi_copy( &T1, &Y ) );
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
@@ -1512,9 +1514,17 @@ static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
/*
* Montgomery square: A = A * A * R^-1 mod N
* A is placed at the upper half of D.
*
* n : number of limbs of N
* np: pointer to limbs of bignum N
* mm: m' = -N^(-1) mod b where b = 2^number-of-bit-in-limb
* d (destination): the result [<-- temp -->][<--- A ---->]
* lower part upper part
* n-limb n-limb
*/
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
{
#if defined(POLARSSL_HAVE_ASM) && defined(__arm__)
size_t i;
register t_uint c = 0;
@@ -1526,6 +1536,52 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
x_i = *xj;
*xj++ = c;
#if defined(__ARM_FEATURE_DSP)
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
"mov %[c], #0\n\t"
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
"mov r4, %[c]\n\t"
"umlal r5, r4, %[x_i], %[x_i]\n\t"
"str r5, [%[wij]], #4\n\t"
"cmp %[xj], %[x_max1]\n\t"
"bhi 0f\n\t"
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
"beq 1f\n"
"2:\n\t"
"ldmia %[xj]!, { r7, r8 }\n\t"
"ldmia %[wij], { r5, r6 }\n\t"
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
"umaal r5, r4, %[x_i], r7\n\t"
"umlal r5, %[c], %[x_i], r7\n\t"
"umaal r4, %[c], r9, r9\n\t"
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
"umaal r6, r4, %[x_i], r8\n\t"
"umlal r6, %[c], %[x_i], r8\n\t"
"umaal r4, %[c], r9, r9\n\t"
/**/
"stmia %[wij]!, { r5, r6 }\n\t"
"cmp %[xj], %[x_max1]\n\t"
"bcc 2b\n\t"
"bne 0f\n"
"1:\n\t"
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
"ldr r5, [%[wij]]\n\t"
"ldr r6, [%[xj]], #4\n\t"
"umaal r5, r4, %[x_i], r6\n\t"
"umlal r5, %[c], %[x_i], r6\n\t"
"umaal r4, %[c], r9, r9\n\t"
"str r5, [%[wij]], #4\n"
"0:\n\t"
"ldr r5, [%[wij]]\n\t"
"adds r4, r4, r5\n\t"
"adc %[c], %[c], #0\n\t"
"str r4, [%[wij]]"
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
"[wij]" (wij), "[xj]" (xj)
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc");
#else
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
"mov %[c], #0\n\t"
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
@@ -1587,6 +1643,7 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
"[wij]" (wij), "[xj]" (xj)
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
#endif
c += mpi_mul_hlp( n, np, &d[i], d[i] * mm );
}
@@ -1598,16 +1655,29 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
mpi_sub_hlp( n, np, d );
else
mpi_sub_hlp( n, d - n, d - n);
#else
t_uint a_input[n];
memcpy (a_input, &d[n], sizeof (a_input));
mpi_montmul (n, np, mm, d, a_input);
#endif
}
/*
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
*/
#if MEMORY_SIZE >= 32
#define MAX_WSIZE 6
#elif MEMORY_SIZE >= 24
#define MAX_WSIZE 5
#else
#define MAX_WSIZE 4
#endif
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
{
int ret;
size_t i = mpi_msb( E );
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
size_t wsize = ( i > 1024 ) ? MAX_WSIZE :
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
size_t wbits, one = 1;
@@ -1632,7 +1702,6 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
* Init temps and window size
*/
mpi_montg_init( &mm, N );
MPI_CHK( mpi_grow( X, N->n ) );
/*
* If 1st call, pre-compute R^2 mod N
@@ -1658,6 +1727,8 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
memset (d, 0, N->n * ciL); /* Set lower half of D zero. */
}
MPI_CHK( mpi_grow( X, N->n ) );
/*
* W[1] = A * R^2 * R^-1 mod N = A * R mod N
*/
@@ -2051,17 +2122,19 @@ jkiss (struct jkiss_state *s)
static int mpi_fill_pseudo_random ( mpi *X, size_t size)
{
int ret;
uint32_t *p;
uint32_t *p, *p_end;
MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
MPI_CHK( mpi_lset( X, 0 ) );
/* Assume little endian. */
p = X->p;
while (p < X->p + (size/ciL))
p = (uint32_t *)X->p;
p_end = (uint32_t *)(X->p + (size/sizeof (uint32_t)));
while (p < p_end)
*p++ = jkiss (&jkiss_state_v);
if ((size % ciL))
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % ciL))) - 1);
if ((size%sizeof (uint32_t)))
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % sizeof (uint32_t)))) - 1);
cleanup:
return ret;
@@ -2202,10 +2275,24 @@ cleanup:
* Value M: multiply all primes up to 701 (except 97) and 797
* (so that MAX_A will be convenient value)
*/
#ifdef __LP64__
#define M_LIMBS 16
#else
#define M_LIMBS 31
#endif
#define M_SIZE 122
static const t_uint limbs_M[] = { /* Little endian */
#ifdef __LP64__
0x9344A6AB84EEB59EUL, 0xEC855CDAFF21529FUL,
0x477E991E009BAB38UL, 0x2EEA23579F5B86F3UL,
0xAC17D30441D6502FUL, 0x38FF52B90A468A6DUL,
0x63630419FD42E5EFUL, 0x48CE17D091DB2572UL,
0x708AB00AE3B57D0EUL, 0xF8A9DE08CD723598UL,
0x731411374432C93BUL, 0x554DF2612779FAB3UL,
0xDEEBDA58953D2BA5UL, 0xD1D66F2F5F57D007UL,
0xB85C9607E84E9F2BUL, 0x000000000000401DUL
#else
0x84EEB59E, 0x9344A6AB, 0xFF21529F, 0xEC855CDA,
0x009BAB38, 0x477E991E, 0x9F5B86F3, 0x2EEA2357,
0x41D6502F, 0xAC17D304, 0x0A468A6D, 0x38FF52B9,
@@ -2214,6 +2301,7 @@ static const t_uint limbs_M[] = { /* Little endian */
0x4432C93B, 0x73141137, 0x2779FAB3, 0x554DF261,
0x953D2BA5, 0xDEEBDA58, 0x5F57D007, 0xD1D66F2F,
0xE84E9F2B, 0xB85C9607, 0x0000401D
#endif
};
static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
@@ -2221,10 +2309,18 @@ static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
/*
* MAX_A : 2^1024 / M - 1
*/
#ifdef __LP64__
#define MAX_A_LIMBS 1
#else
#define MAX_A_LIMBS 2
#endif
#define MAX_A_FILL_SIZE 6
static const t_uint limbs_MAX_A[] = { /* Little endian */
#ifdef __LP64__
0x0003FE2556A2B35FUL
#else
0x56A2B35F, 0x0003FE25
#endif
};
static const mpi MAX_A[1] = {{ 1, MAX_A_LIMBS, (t_uint *)limbs_MAX_A }};
@@ -2274,9 +2370,8 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
MPI_CHK ( mpi_mul_mpi ( X, X, M ) );
MPI_CHK ( mpi_add_abs ( X, X, B ) );
if (X->n <= 31 || (X->p[31] & 0xc0000000) == 0)
if (X->n <= M_LIMBS || (X->p[M_LIMBS-1] & 0xc0000000) == 0)
continue;
ret = mpi_is_prime ( X );
if (ret == 0 || ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE)
break;

View File

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

View File

@@ -1,8 +1,11 @@
# Makefile for reGNUal
PROJECT = regnual
PROJECT = regnual-no-vidpid
OBJS = regnual.o usb-stm32f103.o reset.o
include ../src/config.mk
LDSCRIPT= regnual.ld
###################################
@@ -19,7 +22,7 @@ TOPT = -mthumb -DTHUMB -mno-thumb-interwork
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes
MCFLAGS= -mcpu=$(MCU)
DEFS = -DFREE_STANDING
DEFS += -DFREE_STANDING
CFLAGS = -O2 -g
CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie
@@ -38,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
* Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -57,7 +57,9 @@ static const uint8_t regnual_device_desc[] = {
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
#include "../src/usb-vid-pid-ver.c.inc"
0x00, 0x00, /* idVendor (will be replaced) */
0x00, 0x00, /* idProduct (will be replaced) */
0x00, 0x00, /* bcdDevice (will be replaced) */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial number */
@@ -147,19 +149,33 @@ static uint32_t fetch (int i)
}
struct CRC {
__IO uint32_t DR;
__IO uint8_t IDR;
volatile uint32_t DR;
volatile uint8_t IDR;
uint8_t RESERVED0;
uint16_t RESERVED1;
__IO uint32_t CR;
volatile uint32_t CR;
};
static struct CRC *const CRC = (struct CRC *)0x40023000;
struct RCC {
volatile uint32_t CR;
volatile uint32_t CFGR;
volatile uint32_t CIR;
volatile uint32_t APB2RSTR;
volatile uint32_t APB1RSTR;
volatile uint32_t AHBENR;
/* ... */
};
static struct RCC *const RCC = (struct RCC *)0x40021000;
#define RCC_AHBENR_CRCEN 0x00000040
#define CRC_CR_RESET 0x01
static uint32_t calc_crc32 (void)
{
struct CRC *CRC = (struct CRC *)0x40023000;
int i;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
for (i = 0; i < 256/4; i++)
@@ -365,7 +381,11 @@ main (int argc, char *argv[])
set_led (0);
#if defined(STM32F103_OVERRIDE_FLASH_SIZE_KB)
flash_end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
#else
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
#endif
/*
* NVIC interrupt priority was set by Gnuk.

View File

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

View File

@@ -5,11 +5,8 @@ PROJECT = gnuk
CHOPSTX = ../chopstx
# Define linker script file here
LDSCRIPT= gnuk.ld
CSRC = main.c usb_desc.c usb_ctrl.c \
call-rsa.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 \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
@@ -27,12 +24,19 @@ CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
CSRC += $(CRYPTSRC)
INCDIR += $(CRYPTINCDIR)
@PINPAD_MAKE_OPTION@
@DEBUG_MAKE_OPTION@
@HEXOUTPUT_MAKE_OPTION@
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
@@ -45,23 +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
# DEFS: Add
DEFS = @USE_SYS3@
OPT = -O3 -Os -g
LIBS =
#######################
include $(CHOPSTX)/rules.mk
@@ -75,5 +73,24 @@ sys.c: board.h
build/bignum.o: OPT = -O3 -g
distclean: clean
-rm -f gnuk.ld config.h board.h Makefile \
-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,28 +110,23 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
/*
* LEN: length in byte
*/
uint8_t *
modulus_calc (const uint8_t *p, int len)
int
modulus_calc (const uint8_t *p, int len, uint8_t *pubkey)
{
mpi P, Q, N;
uint8_t *modulus;
int ret;
modulus = malloc (len);
if (modulus == NULL)
return NULL;
mpi_init (&P); mpi_init (&Q); mpi_init (&N);
MPI_CHK( mpi_read_binary (&P, p, len / 2) );
MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
MPI_CHK( mpi_write_binary (&N, modulus, len) );
MPI_CHK( mpi_write_binary (&N, pubkey, len) );
cleanup:
mpi_free (&P); mpi_free (&Q); mpi_free (&N);
if (ret != 0)
return NULL;
else
return modulus;
return -1;
return 0;
}
@@ -142,6 +136,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
{
mpi P1, Q1, H;
int ret;
#ifdef GNU_LINUX_EMULATION
size_t output_len;
#endif
DEBUG_INFO ("RSA decrypt:");
DEBUG_WORD ((uint32_t)&ret);
@@ -177,9 +174,16 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
#ifdef GNU_LINUX_EMULATION
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, &output_len, input,
output, MAX_RES_APDU_DATA_SIZE);
*output_len_p = (unsigned int)output_len;
#else
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, output_len_p, input,
output, MAX_RES_APDU_DATA_SIZE);
#endif
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
@@ -232,54 +236,39 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
#define RSA_EXPONENT 0x10001
uint8_t *
rsa_genkey (int pubkey_len)
int
rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q)
{
int ret;
uint8_t index = 0;
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
uint8_t *p = p_q_modulus;
uint8_t *q = p_q_modulus + pubkey_len / 2;
uint8_t *modulus = p_q_modulus + pubkey_len;
uint8_t *p = p_q;
uint8_t *q = p_q + pubkey_len / 2;
int cs;
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
extern void neug_flush (void);
if (p_q_modulus == NULL)
return NULL;
neug_flush ();
prng_seed (random_gen, &index);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = (void *)p_q_modulus;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
RSA_EXPONENT) );
if (ret != 0)
{
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
free (p_q_modulus);
rsa_free (&rsa_ctx);
return NULL;
}
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
rsa_free (&rsa_ctx);
chopstx_cleanup_pop (1);
if (ret != 0)
return NULL;
return -1;
else
return p_q_modulus;
return 0;
}

231
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
@@ -36,7 +37,6 @@ fi
help=no
vidpid=none
target=FST_01
verbose=no
with_dfu=default
debug=no
sys1_compat=yes
@@ -44,26 +44,35 @@ pinpad=no
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
REVISION=`git describe --dirty="-modified"`
if type git >/dev/null 2>&1; then
REVISION=$(git describe --dirty="-modified")
else
# echo 'No git available, please install git'
GIT_REVISION=$(sed -e 's/^\(.......\).*$/g\1/' "../.git/$(sed -e 's/^ref: //' ../.git/HEAD)")
REVISION=$(cat ../VERSION)-$GIT_REVISION
fi
else
REVISION=`cat ../VERSION`
REVISION=$(cat ../VERSION)
fi
# Process each option
for option; do
case $option in
*=*) optarg=`expr "X$option" : '[^=]*=\(.*\)'` ;;
*=*) optarg=$(expr "X$option" : '[^=]*=\(.*\)') ;;
*) optarg=yes ;;
esac
case $option in
-h | --help)
help=yes ;;
-v | --verbose)
verbose=yes ;;
--vidpid=*)
vidpid=$optarg ;;
--target=*)
@@ -96,6 +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
@@ -123,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]
@@ -137,21 +158,14 @@ Configuration:
--disable-sys1-compat disable SYS 1.0 compatibility [no]
executable is target independent
but requires SYS 2.0 or newer
--enable-factory-reset
support life cycle management [no]
--with-dfu build image for DFU [<target specific>]
EOF
exit 0
fi
if test "$vidpid" = "none"; then
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
exit 1
fi
BOARD_HEADER_FILE=board-`echo $target | tr '_[:upper:]' '-[:lower:]'`.h
echo Header file is: $BOARD_HEADER_FILE
ln -sf ../chopstx/board/$BOARD_HEADER_FILE board.h
BOARD_HEADER_FILE=board-$(echo $target | tr '_[:upper:]' '-[:lower:]').h
echo "Header file is: $BOARD_HEADER_FILE"
ln -sf "../chopstx/board/$BOARD_HEADER_FILE" board.h
# Flash page size in byte
FLASH_PAGE_SIZE=1024
@@ -162,6 +176,10 @@ MEMORY_SIZE=20
# Settings for TARGET
case $target in
BLUE_PILL|STM8S_DISCOVERY)
# It's 64KB version of STM32F103, but actually has 128KB
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB=128"
;;
CQ_STARM|STBEE_MINI)
if test "$with_dfu" = "default"; then
with_dfu=yes;
@@ -178,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"
@@ -205,21 +257,16 @@ if test "$with_dfu" = "yes"; then
fi
echo "Configured for DFU"
ORIGIN=0x08003000
FLASH_SIZE=`expr $FLASH_SIZE - 12`
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"
@@ -230,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
@@ -266,13 +307,13 @@ else
fi
### !!! Replace following string of "FSIJ" to yours !!! ####
SERIALNO="FSIJ-`cat ../VERSION | sed -e 's%^[^/]*/%%'`-"
SERIALNO="FSIJ-$(sed -e 's%^[^/]*/%%' <../VERSION)-"
SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
if test "$sys1_compat" = "yes"; then
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo"
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset"
else
if test "$with_dfu" = "yes"; then
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
@@ -282,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 "$VENDOR" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo "$PRODUCT" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
if test -n "$prefix"; then
if test -n "$name"; then
echo
echo "const uint8_t ${prefix}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "const uint8_t ${name}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo "$SERIALNO" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
if test "$emulation" = "yes"; then
echo " 'E', 0, 'M', 0, 'U', 0, 'L', 0,"
echo " 'A', 0, 'T', 0, 'E', 0, 'D', 0,"
else
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
fi
echo '};'
echo
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo "static const uint8_t ${prefix}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo "$REVISION" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo "static const uint8_t ${name}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
@@ -336,16 +406,22 @@ output_vendor_product_serial_strings () {
fi
}
(echo "#! /bin/bash"
echo
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
if !(IFS=" "
while read VIDPID VERSION PRODUCT VENDOR; do
while read -r VIDPID VERSION PRODUCT VENDOR; do
if test "$vidpid" = "$VIDPID"; then
output_vid_pid_version > usb-vid-pid-ver.c.inc
echo >> put-vid-pid-ver.sh
echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
output_vid_pid_version >> put-vid-pid-ver.sh
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
exit 0
fi
done; exit 1) < ../GNUK_USB_DEVICE_ID
then
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Check ../GNUK_USB_DEVICE_ID." >&2
exit 1
fi
@@ -362,28 +438,35 @@ else
fi
sed -e "s%@USE_SYS3@%$use_sys3%" \
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
-e "s%@HEXOUTPUT_MAKE_OPTION@%$HEXOUTPUT_MAKE_OPTION%" \
< Makefile.in > Makefile
(echo "CHIP=$chip";
echo "EMULATION=$emulation";
echo "CROSS=$cross";
echo "MCU=$mcu";
echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size";
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
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* 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)
{
@@ -102,39 +109,45 @@ static int key_available_at (const uint8_t *k, int key_size)
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
const uint8_t *
flash_init (void)
void
flash_do_storage_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
{
uint16_t gen0, gen1;
uint16_t *gen0_p = (uint16_t *)&_data_pool;
uint16_t *gen0_p = (uint16_t *)FLASH_ADDR_DATA_STORAGE_START;
uint16_t *gen1_p;
flash_page_size = 1024;
#if !defined (GNU_LINUX_EMULATION)
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
flash_page_size = 2048;
#endif
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
data_pool = &_data_pool;
gen1_p = (uint16_t *)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size);
data_pool = FLASH_ADDR_DATA_STORAGE_START;
/* Check data pool generation and choose the page */
gen0 = *gen0_p;
gen1 = *gen1_p;
if (gen0 == 0xffff && gen1 == 0xffff)
/* It's terminated. */
return NULL;
{
/* It's terminated. */
*p_do_start = *p_do_end = NULL;
return;
}
if (gen0 == 0xffff)
/* Use another page if a page is erased. */
data_pool = &_data_pool + flash_page_size;
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
else if (gen1 == 0xffff)
/* Or use different page if another page is erased. */
data_pool = &_data_pool;
data_pool = FLASH_ADDR_DATA_STORAGE_START;
else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0)
/* When both pages have valid header, use newer page. */
data_pool = &_data_pool + flash_page_size;
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
*p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE;
*p_do_end = data_pool + flash_page_size;
}
static uint8_t *flash_key_getpage (enum kind_of_key kk);
@@ -145,28 +158,33 @@ flash_terminate (void)
int i;
for (i = 0; i < 3; i++)
flash_erase_page ((uint32_t)flash_key_getpage (i));
flash_erase_page ((uint32_t)&_data_pool);
flash_erase_page ((uint32_t)(&_data_pool + flash_page_size));
data_pool = &_data_pool;
last_p = &_data_pool + FLASH_DATA_POOL_HEADER_SIZE;
flash_erase_page ((uintptr_t)flash_key_getpage (i));
flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START);
flash_erase_page ((uintptr_t)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size));
data_pool = FLASH_ADDR_DATA_STORAGE_START;
last_p = FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_HEADER_SIZE;
#if defined(CERTDO_SUPPORT)
flash_erase_page ((uintptr_t)&ch_certificate_start);
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uintptr_t)(&ch_certificate_start + flash_page_size));
#endif
}
void
flash_activate (void)
{
flash_program_halfword ((uint32_t)&_data_pool, 0);
flash_program_halfword ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START, 0);
}
void
flash_init_keys (void)
flash_key_storage_init (void)
{
const uint8_t *p;
int i;
/* For each key, find its address. */
p = &_keystore_pool;
p = FLASH_ADDR_KEY_STORAGE_START;
for (i = 0; i < 3; i++)
{
const uint8_t *k;
@@ -224,15 +242,15 @@ flash_copying_gc (void)
uint8_t *src, *dst;
uint16_t generation;
if (data_pool == &_data_pool)
if (data_pool == FLASH_ADDR_DATA_STORAGE_START)
{
src = &_data_pool;
dst = &_data_pool + flash_page_size;
src = FLASH_ADDR_DATA_STORAGE_START;
dst = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
}
else
{
src = &_data_pool + flash_page_size;
dst = &_data_pool;
src = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
dst = FLASH_ADDR_DATA_STORAGE_START;
}
generation = *(uint16_t *)src;
@@ -242,8 +260,8 @@ flash_copying_gc (void)
generation = 0;
else
generation++;
flash_program_halfword ((uint32_t)dst, generation);
flash_erase_page ((uint32_t)src);
flash_program_halfword ((uintptr_t)dst, generation);
flash_erase_page ((uintptr_t)src);
return 0;
}
@@ -273,10 +291,10 @@ void
flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len)
{
uint16_t hw;
uint32_t addr;
uintptr_t addr;
int i;
addr = (uint32_t)p;
addr = (uintptr_t)p;
hw = nr | (len << 8);
if (flash_program_halfword (addr, hw) != 0)
flash_warning ("DO WRITE ERROR");
@@ -329,13 +347,14 @@ flash_warning (const char *msg)
void
flash_do_release (const uint8_t *do_data)
{
uint32_t addr = (uint32_t)do_data - 1;
uint32_t addr_tag = addr;
uintptr_t addr = (uintptr_t)do_data - 1;
uintptr_t addr_tag = addr;
int i;
int len = do_data[0];
/* Don't filling zero for data in code (such as ds_count_initial_value) */
if (do_data < &_data_pool || do_data > &_data_pool + FLASH_DATA_POOL_SIZE)
if (do_data < FLASH_ADDR_DATA_STORAGE_START
|| do_data > FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_SIZE)
return;
addr += 2;
@@ -364,7 +383,7 @@ static uint8_t *
flash_key_getpage (enum kind_of_key kk)
{
/* There is a page for each KK. */
return &_keystore_pool + (flash_page_size * kk);
return FLASH_ADDR_KEY_STORAGE_START + (flash_page_size * kk);
}
uint8_t *
@@ -398,10 +417,10 @@ flash_key_write (uint8_t *key_addr,
const uint8_t *pubkey, int pubkey_len)
{
uint16_t hw;
uint32_t addr;
uintptr_t addr;
int i;
addr = (uint32_t)key_addr;
addr = (uintptr_t)key_addr;
for (i = 0; i < key_data_len/2; i ++)
{
hw = key_data[i*2] | (key_data[i*2+1]<<8);
@@ -424,7 +443,7 @@ flash_key_write (uint8_t *key_addr,
static int
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
{
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
uintptr_t start = (uintptr_t)key_addr & ~(flash_page_size - 1);
const uint32_t *p = (const uint32_t *)start;
while (p < (const uint32_t *)(start + flash_page_size))
@@ -443,7 +462,7 @@ static void
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
{
int i;
uint32_t addr = (uint32_t)key_addr;
uintptr_t addr = (uintptr_t)key_addr;
for (i = 0; i < key_size/2; i++)
flash_program_halfword (addr + i*2, 0);
@@ -453,7 +472,7 @@ void
flash_key_release (uint8_t *key_addr, int key_size)
{
if (flash_check_all_other_keys_released (key_addr, key_size))
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
flash_erase_page (((uintptr_t)key_addr & ~(flash_page_size - 1)));
else
flash_key_fill_zero_as_released (key_addr, key_size);
}
@@ -461,12 +480,12 @@ flash_key_release (uint8_t *key_addr, int key_size)
void
flash_key_release_page (enum kind_of_key kk)
{
flash_erase_page ((uint32_t)flash_key_getpage (kk));
flash_erase_page ((uintptr_t)flash_key_getpage (kk));
}
void
flash_clear_halfword (uint32_t addr)
flash_clear_halfword (uintptr_t addr)
{
flash_program_halfword (addr, 0);
}
@@ -475,7 +494,7 @@ flash_clear_halfword (uint32_t addr)
void
flash_put_data_internal (const uint8_t *p, uint16_t hw)
{
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
void
@@ -489,7 +508,7 @@ flash_put_data (uint16_t hw)
DEBUG_INFO ("data allocation failure.\r\n");
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
@@ -501,14 +520,14 @@ flash_bool_clear (const uint8_t **addr_p)
if ((p = *addr_p) == NULL)
return;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
*addr_p = NULL;
}
void
flash_bool_write_internal (const uint8_t *p, int nr)
{
flash_program_halfword ((uint32_t)p, nr);
flash_program_halfword ((uintptr_t)p, nr);
}
const uint8_t *
@@ -524,7 +543,7 @@ flash_bool_write (uint8_t nr)
return NULL;
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
return p;
}
@@ -540,7 +559,7 @@ flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v)
{
uint16_t hw = nr | (v << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
const uint8_t *
@@ -556,7 +575,7 @@ flash_enum_write (uint8_t nr, uint8_t v)
return NULL;
}
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
return p;
}
@@ -592,14 +611,14 @@ flash_cnt123_write_internal (const uint8_t *p, int which, int v)
uint16_t hw;
hw = NR_COUNTER_123 | (which << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
if (v == 1)
return;
else if (v == 2)
flash_program_halfword ((uint32_t)p+2, 0xc3c3);
flash_program_halfword ((uintptr_t)p+2, 0xc3c3);
else /* v == 3 */
flash_program_halfword ((uint32_t)p+2, 0);
flash_program_halfword ((uintptr_t)p+2, 0);
}
void
@@ -617,7 +636,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
return;
}
hw = NR_COUNTER_123 | (which << 8);
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
*addr_p = p + 2;
}
else
@@ -632,7 +651,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
else
hw = 0;
flash_program_halfword ((uint32_t)p, hw);
flash_program_halfword ((uintptr_t)p, hw);
}
}
@@ -644,9 +663,9 @@ flash_cnt123_clear (const uint8_t **addr_p)
if ((p = *addr_p) == NULL)
return;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
p -= 2;
flash_program_halfword ((uint32_t)p, 0);
flash_program_halfword ((uintptr_t)p, 0);
*addr_p = NULL;
}
@@ -660,9 +679,9 @@ flash_erase_binary (uint8_t file_id)
const uint8_t *p = &ch_certificate_start;
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
{
flash_erase_page ((uint32_t)p);
flash_erase_page ((uintptr_t)p);
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uint32_t)p + flash_page_size);
flash_erase_page ((uintptr_t)p + flash_page_size);
}
return 0;
@@ -685,17 +704,19 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
maxsize = 6;
p = &openpgpcard_aid[8];
}
#ifdef FLASH_UPGRADE_SUPPORT
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
{
maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
if (len == 0 && offset == 0)
{ /* This means removal of update key. */
if (flash_program_halfword ((uint32_t)p, 0) != 0)
if (flash_program_halfword ((uintptr_t)p, 0) != 0)
flash_warning ("DO WRITE ERROR");
return 0;
}
}
#endif
#if defined(CERTDO_SUPPORT)
else if (file_id == FILEID_CH_CERTIFICATE)
{
@@ -711,13 +732,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
@@ -106,13 +103,13 @@ extern uint16_t data_objects_number_of_bytes;
#define CHALLENGE_LEN 32
void gpg_data_scan (const uint8_t *p);
void gpg_data_scan (const uint8_t *start, const uint8_t *end);
void gpg_data_copy (const uint8_t *p);
void gpg_do_terminate (void);
void gpg_do_get_data (uint16_t tag, int with_tag);
void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
void gpg_do_public_key (uint8_t kk_byte);
void gpg_do_keygen (uint8_t kk_byte);
void gpg_do_keygen (uint8_t *buf);
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
@@ -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);
const uint8_t *flash_init (void);
void flash_do_storage_init (const uint8_t **, const uint8_t **);
void flash_terminate (void);
void flash_activate (void);
void flash_init_keys (void);
void flash_key_storage_init (void);
void flash_do_release (const uint8_t *);
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
uint8_t *flash_key_alloc (enum kind_of_key);
@@ -152,7 +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,19 +285,23 @@ 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));
#define FATAL_FLASH 1
#define FATAL_RANDOM 2
#define FATAL_HEAP 3
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
extern uint8_t admin_authorized;
@@ -333,7 +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:
@@ -432,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)
@@ -459,3 +462,5 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
#endif
extern uint8_t _regnual_start, __heap_end__[];
uint8_t * sram_address (uint32_t offset);

View File

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

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017
* 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,30 +457,46 @@ fatal (uint8_t code)
* reclaimed to system.
*/
#ifdef GNU_LINUX_EMULATION
#define HEAP_SIZE (32*1024)
uint8_t __heap_base__[HEAP_SIZE];
#define HEAP_START __heap_base__
#define HEAP_END (__heap_base__ + HEAP_SIZE)
#define HEAP_ALIGNMENT 32
#else
extern uint8_t __heap_base__[];
extern uint8_t __heap_end__[];
#define MEMORY_END (__heap_end__)
#define MEMORY_ALIGNMENT 16
#define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
#define HEAP_START __heap_base__
#define HEAP_END (__heap_end__)
#define HEAP_ALIGNMENT 16
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
#endif
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
static uint8_t *heap_p;
static chopstx_mutex_t malloc_mtx;
struct mem_head {
uint32_t size;
uintptr_t size;
/**/
struct mem_head *next, *prev; /* free list chain */
struct mem_head *neighbor; /* backlink to neighbor */
};
#define MEM_HEAD_IS_CORRUPT(x) \
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
static struct mem_head *free_list;
static void
gnuk_malloc_init (void)
{
chopstx_mutex_init (&malloc_mtx);
heap_p = __heap_base__;
heap_p = HEAP_START;
free_list = NULL;
}
@@ -380,7 +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;
@@ -405,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: ");
@@ -421,7 +546,7 @@ gnuk_malloc (size_t size)
m->size = size;
break;
}
MEM_HEAD_CHECK (m);
if (m->size == size)
{
remove_from_free_list (m);
@@ -445,8 +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);
}
}
@@ -454,18 +579,23 @@ gnuk_malloc (size_t size)
void
gnuk_free (void *p)
{
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uint32_t));
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uintptr_t));
struct mem_head *m0;
if (p == NULL)
return;
chopstx_mutex_lock (&malloc_mtx);
m0 = free_list;
DEBUG_INFO ("free: ");
DEBUG_SHORT (m->size);
DEBUG_WORD ((uint32_t)p);
DEBUG_WORD ((uintptr_t)p);
MEM_HEAD_CHECK (m);
m->neighbor = NULL;
while (m0)
{
MEM_HEAD_CHECK (m0);
if ((void *)m + m->size == (void *)m0)
m0->neighbor = m;
else if ((void *)m0 + m0->size == (void *)m)
@@ -481,6 +611,7 @@ gnuk_free (void *p)
heap_p -= m->size;
while (mn)
{
MEM_HEAD_CHECK (mn);
heap_p -= mn->size;
remove_from_free_list (mn);
mn = mn->neighbor;

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

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/*
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -24,7 +24,6 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
@@ -40,7 +39,7 @@
#define CLEAN_PAGE_FULL 1
#define CLEAN_SINGLE 0
static void gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full);
static void gpg_reset_digital_signature_counter (void);
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
static const uint8_t *pw_err_counter_p[3];
@@ -113,13 +112,15 @@ const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
/* Extended Capabilities */
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
10,
0x74, /*
0x75, /*
* No Secure Messaging supported
* GET CHALLENGE supported
* Key import supported
* PW status byte can be put
* No private_use_DO
* Algorithm attrs are changable
* No DEC with AES
* KDF-DO available
*/
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, CHALLENGE_LEN, /* Max size of GET CHALLENGE */
@@ -250,6 +251,28 @@ gpg_get_algo_attr (enum kind_of_key kk)
return algo_attr_p[1];
}
static void
gpg_reset_algo_attr (enum kind_of_key kk)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
}
static const uint8_t *
get_algo_attr_data_object (enum kind_of_key kk)
{
@@ -336,7 +359,7 @@ gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc)
else
{
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
hw1 = NR_COUNTER_DS_LSB;
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
flash_put_data_internal (p, hw0);
flash_put_data_internal (p+2, hw1);
return p+4;
@@ -431,12 +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__];
@@ -473,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;
}
@@ -749,47 +779,15 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
return 0; /* Error. */
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
gpg_reset_algo_attr (kk);
flash_enum_clear (algo_attr_pp);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
if (*algo_attr_pp != NULL)
return 0;
}
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL)
|| (*algo_attr_pp)[1] != algo)
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL) ||
(*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo))
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
if (kk == GPG_KEY_FOR_SIGNING)
{
gpg_reset_digital_signature_counter ();
gpg_do_write_simple (NR_DO_FP_SIG, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_SIG, NULL, 0);
}
else if (kk == GPG_KEY_FOR_DECRYPTION)
{
gpg_do_write_simple (NR_DO_FP_DEC, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_DEC, NULL, 0);
}
else
{
gpg_do_write_simple (NR_DO_FP_AUT, NULL, 0);
gpg_do_write_simple (NR_DO_KGTIME_AUT, NULL, 0);
}
gpg_reset_algo_attr (kk);
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
if (*algo_attr_pp == NULL)
return 0;
@@ -809,6 +807,103 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
}
}
#define SIZE_OF_KDF_DO 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;
if (*do_data_p)
flash_do_release (*do_data_p);
if (len == 0)
{
*do_data_p = NULL;
return 1;
}
else if (len != SIZE_OF_KDF_DO ||
!(data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83
&& data[12] == 0x84 && data[22] == 0x85 && data[32] == 0x86
&& data[42] == 0x87 && data[76] == 0x88))
/* Format validation failed. The valid format is:
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
*/
return 0;
else
{
*do_data_p = flash_do_write (NR_DO_KDF, data, SIZE_OF_KDF_DO);
if (*do_data_p)
return 1;
else
return 0;
}
}
else
{
copy_do_1 (tag, do_ptr[NR_DO_KDF], with_tag);
return 1;
}
}
int
gpg_do_kdf_check (int len, int how_many)
{
const uint8_t *kdf_spec = gpg_do_read_simple (NR_DO_KDF);
if (kdf_spec && (kdf_spec[43] * how_many) != 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_spec = gpg_do_read_simple (NR_DO_KDF);
if (kdf_spec)
{
*r_len = 32;
if (is_pw3)
*r_p = kdf_spec + 78;
else
*r_p = kdf_spec + 44;
}
else
{
if (is_pw3)
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW3);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3;
}
else
{
*r_len = strlen (OPENPGP_CARD_INITIAL_PW1);
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
}
}
}
static int
proc_resetting_code (const uint8_t *data, int len)
{
@@ -822,6 +917,9 @@ proc_resetting_code (const uint8_t *data, int len)
DEBUG_INFO ("Resetting Code!\r\n");
if (gpg_do_kdf_check (len, 1) == 0)
return 0;
newpw_len = len;
newpw = data;
new_ks0[0] = newpw_len;
@@ -858,7 +956,7 @@ encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
{
aes_context aes;
uint8_t iv0[INITIAL_VECTOR_SIZE];
unsigned int iv_offset;
size_t iv_offset;
DEBUG_INFO ("ENC\r\n");
DEBUG_BINARY (data, len);
@@ -877,7 +975,7 @@ decrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
{
aes_context aes;
uint8_t iv0[INITIAL_VECTOR_SIZE];
unsigned int iv_offset;
size_t iv_offset;
aes_setkey_enc (&aes, key, 128); /* This is setkey_enc, because of CFB. */
memcpy (iv0, iv, INITIAL_VECTOR_SIZE);
@@ -1093,14 +1191,16 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
int attr = gpg_get_algo_attr (kk);;
const uint8_t *p;
int r;
struct prvkey_data *pd;
struct prvkey_data prv;
struct prvkey_data *pd = &prv;
uint8_t *key_addr;
const uint8_t *dek, *iv;
struct key_data_internal kdi;
uint8_t *pubkey_allocated_here = NULL;
int pubkey_len;
uint8_t ks[KEYSTRING_MD_SIZE];
enum kind_of_key kk0;
int pw_len;
const uint8_t *initial_pw;
DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (prvkey_len);
@@ -1108,10 +1208,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
/* Delete it first, if any. */
gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
if (pd == NULL)
return -1;
if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
pubkey_len = prvkey_len * 2;
@@ -1139,38 +1235,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
return -1;
}
if (pubkey == NULL)
{
if (attr == ALGO_SECP256K1)
pubkey_allocated_here = ecc_compute_public_p256k1 (key_data);
else if (attr == ALGO_NISTP256R1)
pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
else if (attr == ALGO_ED25519)
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
else if (attr == ALGO_CURVE25519)
pubkey_allocated_here = ecdh_compute_public_25519 (key_data);
else /* RSA */
pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
if (pubkey_allocated_here == NULL)
{
free (pd);
return -1;
}
}
DEBUG_INFO ("Getting keystore address...\r\n");
key_addr = flash_key_alloc (kk);
if (key_addr == NULL)
{
if (pubkey_allocated_here)
{
memset (pubkey_allocated_here, 0, pubkey_len);
free (pubkey_allocated_here);
}
free (pd);
return -1;
}
return -1;
kd[kk].pubkey = key_addr + prvkey_len;
num_prv_keys++;
@@ -1189,8 +1258,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
s2k (NULL, 0, initial_pw, pw_len, ks);
/* Handle existing keys and keystring DOs. */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
@@ -1206,19 +1275,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len,
pubkey_allocated_here? pubkey_allocated_here: pubkey,
pubkey_len);
if (pubkey_allocated_here)
{
memset (pubkey_allocated_here, 0, pubkey_len);
free (pubkey_allocated_here);
}
pubkey, pubkey_len);
if (r < 0)
{
random_bytes_free (dek);
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
return r;
}
@@ -1240,7 +1301,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
random_bytes_free (dek);
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
if (p == NULL)
return -1;
@@ -1272,18 +1332,15 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
uint8_t nr = get_do_ptr_nr_for_kk (kk);
const uint8_t *do_data = do_ptr[nr];
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
struct prvkey_data *pd;
const uint8_t *p;
struct prvkey_data prv;
struct prvkey_data *pd = &prv;
uint8_t *dek_p;
int update_needed = 0;
int r = 1; /* Success */
if (do_data == NULL)
return 0; /* No private key */
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
if (pd == NULL)
return -1;
memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE
@@ -1314,18 +1371,19 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
if (update_needed)
{
const uint8_t *p;
flash_do_release (do_data);
do_ptr[nr] = NULL;
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr] = p;
if (p == NULL)
r = -1;
}
memset (pd, 0, sizeof (struct prvkey_data));
free (pd);
if (update_needed && p == NULL)
return -1;
return 1;
return r;
}
@@ -1380,6 +1438,7 @@ proc_key_import (const uint8_t *data, int len)
const uint8_t *keystring_admin;
int attr;
const uint8_t *p = data;
uint8_t pubkey[512];
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
@@ -1419,13 +1478,35 @@ proc_key_import (const uint8_t *data, int len)
}
if (attr == ALGO_RSA2K)
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
{
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = modulus_calc (&data[26], len - 26, pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin,
pubkey);
}
else if (attr == ALGO_RSA4K)
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, NULL);
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
{
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
r = modulus_calc (&data[28], len - 28, pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin,
pubkey);
}
else if (attr == ALGO_NISTP256R1)
{
r = ecc_compute_public_p256r1 (&data[12], pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
pubkey);
}
else if (attr == ALGO_SECP256K1)
{
r = ecc_compute_public_p256k1 (&data[12], pubkey);
if (r >= 0)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
pubkey);
}
else if (attr == ALGO_ED25519)
{
uint8_t hash[64];
@@ -1437,7 +1518,8 @@ proc_key_import (const uint8_t *data, int len)
hash[0] &= 248;
hash[31] &= 127;
hash[31] |= 64;
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
eddsa_compute_public_25519 (hash, pubkey);
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, pubkey);
}
else if (attr == ALGO_CURVE25519)
{
@@ -1449,7 +1531,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)
@@ -1516,6 +1599,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 },
@@ -1543,7 +1628,7 @@ gpg_do_table[] = {
* Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc.
*/
void
gpg_data_scan (const uint8_t *p_start)
gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
{
const uint8_t *p;
int i;
@@ -1556,10 +1641,15 @@ gpg_data_scan (const uint8_t *p_start)
pw_err_counter_p[PW_ERR_RC] = NULL;
pw_err_counter_p[PW_ERR_PW3] = NULL;
algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL;
digital_signature_counter = 0;
/* When the card is terminated no data objects are valid. */
if (do_start == NULL)
return;
/* Traverse DO, counters, etc. in DATA pool */
p = p_start;
while (p && *p != NR_EMPTY)
p = do_start;
while (p < do_end && *p != NR_EMPTY)
{
uint8_t nr = *p++;
uint8_t second_byte = *p;
@@ -1571,10 +1661,12 @@ gpg_data_scan (const uint8_t *p_start)
if (nr < 0x80)
{
/* It's Data Object */
do_ptr[nr] = p;
if (nr < NR_DO__LAST__)
do_ptr[nr] = p;
p += second_byte + 1; /* second_byte has length */
if (((uint32_t)p & 1))
if (((uintptr_t)p & 1))
p++;
}
else if (nr >= 0x80 && nr <= 0xbf)
@@ -2079,44 +2171,37 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
}
void
gpg_do_keygen (uint8_t kk_byte)
gpg_do_keygen (uint8_t *buf)
{
uint8_t kk_byte = buf[0];
enum kind_of_key kk = kkb_to_kk (kk_byte);
int attr = gpg_get_algo_attr (kk);;
int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE);
const uint8_t *keystring_admin;
uint8_t *p_q_modulus = NULL;
uint8_t d[64];
const uint8_t *rnd;
const uint8_t *prv;
const uint8_t *pubkey;
int r;
const uint8_t *rnd;
int r = 0;
#define p_q (&buf[3])
#define d (&buf[3])
#define d1 (&buf[3+64])
#define pubkey (&buf[3+256])
DEBUG_INFO ("Keygen\r\n");
DEBUG_BYTE (kk_byte);
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
else
keystring_admin = NULL;
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
p_q_modulus = rsa_genkey (prvkey_len);
if (p_q_modulus == NULL)
if (rsa_genkey (prvkey_len, pubkey, p_q) < 0)
{
GPG_MEMORY_FAILURE ();
return;
}
prv = p_q_modulus;
pubkey = p_q_modulus + prvkey_len;
prv = p_q;
}
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
uint8_t d1[32];
const uint8_t *p;
int i, r;
int i;
rnd = NULL;
do
@@ -2143,7 +2228,10 @@ gpg_do_keygen (uint8_t kk_byte)
random_bytes_free (rnd);
prv = d;
pubkey = NULL;
if (attr == ALGO_SECP256K1)
r = ecc_compute_public_p256k1 (prv, pubkey);
else if (attr == ALGO_NISTP256R1)
r = ecc_compute_public_p256r1 (prv, pubkey);
}
else if (attr == ALGO_ED25519)
{
@@ -2154,7 +2242,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
eddsa_compute_public_25519 (d, pubkey);
}
else if (attr == ALGO_CURVE25519)
{
@@ -2165,7 +2253,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
ecdh_compute_public_25519 (prv, pubkey);
}
else
{
@@ -2173,12 +2261,21 @@ gpg_do_keygen (uint8_t kk_byte)
return;
}
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
if (p_q_modulus)
if (r >= 0)
{
memset (p_q_modulus, 0, prvkey_len * 2);
free (p_q_modulus);
const uint8_t *keystring_admin;
if (admin_authorized == BY_ADMIN)
keystring_admin = keystring_md_pw3;
else
keystring_admin = NULL;
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
}
/* Clear private key data in the buffer. */
memset (buf, 0, 256);
if (r < 0)
{
GPG_ERROR ();
@@ -2189,14 +2286,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
* 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]
@@ -98,7 +99,6 @@ set_res_sw (uint8_t sw1, uint8_t sw2)
#define FILE_EF_UPDATE_KEY_2 7
#define FILE_EF_UPDATE_KEY_3 8
#define FILE_EF_CH_CERTIFICATE 9
#define FILE_CARD_TERMINATED_OPENPGP 254
#define FILE_CARD_TERMINATED 255
uint8_t file_selection;
@@ -106,17 +106,18 @@ uint8_t file_selection;
static void
gpg_init (void)
{
const uint8_t *flash_data_start;
const uint8_t *flash_do_start;
const uint8_t *flash_do_end;
flash_data_start = flash_init ();
flash_do_storage_init (&flash_do_start, &flash_do_end);
if (flash_data_start == NULL)
if (flash_do_start == NULL)
file_selection = FILE_CARD_TERMINATED;
else
file_selection = FILE_NONE;
gpg_data_scan (flash_data_start);
flash_init_keys ();
gpg_data_scan (flash_do_start, flash_do_end);
flash_key_storage_init ();
}
static void
@@ -192,6 +193,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 +306,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 +348,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 ();
@@ -376,13 +390,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 +435,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 ();
}
@@ -517,6 +555,12 @@ cmd_reset_user_password (void)
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
uint8_t old_ks[KEYSTRING_MD_SIZE];
if (gpg_do_kdf_check (len, 2) == 0)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
if (gpg_pw_locked (PW_ERR_RC))
{
DEBUG_INFO ("blocked.\r\n");
@@ -581,6 +625,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 +694,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 +708,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 +721,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 +730,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 +749,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 +785,11 @@ cmd_read_binary (void)
}
}
#endif
else
{
GPG_NO_FILE ();
return;
}
}
static void
@@ -759,8 +812,7 @@ cmd_select_file (void)
if (file_selection == FILE_CARD_TERMINATED)
{
file_selection = FILE_CARD_TERMINATED_OPENPGP;
GPG_APPLICATION_TERMINATED();
GPG_APPLICATION_TERMINATED ();
return;
}
@@ -1201,6 +1253,7 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
return;
}
#ifdef FLASH_UPGRADE_SUPPORT
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3
&& len == 0 && offset == 0)
{
@@ -1217,9 +1270,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 ();
}
@@ -1249,6 +1303,7 @@ cmd_write_binary (void)
}
#ifdef FLASH_UPGRADE_SUPPORT
static void
cmd_external_authenticate (void)
{
@@ -1290,6 +1345,7 @@ cmd_external_authenticate (void)
set_res_sw (0xff, 0xff);
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
}
#endif
static void
cmd_get_challenge (void)
@@ -1322,9 +1378,9 @@ cmd_get_challenge (void)
static void
cmd_activate_file (void)
{
if (file_selection != FILE_CARD_TERMINATED_OPENPGP)
if (file_selection != FILE_CARD_TERMINATED)
{
GPG_NO_RECORD();
GPG_NO_RECORD ();
return;
}
@@ -1336,12 +1392,14 @@ cmd_activate_file (void)
static void
cmd_terminate_df (void)
{
const uint8_t *ks_pw3;
uint8_t p1 = P1 (apdu);
uint8_t p2 = P2 (apdu);
if (file_selection != FILE_DF_OPENPGP)
{
GPG_NO_RECORD();
GPG_NO_RECORD ();
return;
}
@@ -1357,8 +1415,11 @@ cmd_terminate_df (void)
return;
}
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (!ac_check_status (AC_ADMIN_AUTHORIZED) && !gpg_pw_locked (PW_ERR_PW3))
if (!ac_check_status (AC_ADMIN_AUTHORIZED)
&& !((ks_pw3 && gpg_pw_locked (PW_ERR_PW3))
|| (ks_pw3 == NULL && gpg_pw_locked (PW_ERR_PW1))))
{
/* Only allow the case admin authorized, or, admin pass is locked. */
GPG_SECURITY_FAILURE();
@@ -1391,8 +1452,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 },
@@ -1425,13 +1488,13 @@ process_command_apdu (void)
if (file_selection == FILE_CARD_TERMINATED
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE)
GPG_APPLICATION_TERMINATED();
GPG_APPLICATION_TERMINATED ();
else if (file_selection != FILE_DF_OPENPGP
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE
&& cmd != INS_WRITE_BINARY && cmd != INS_UPDATE_BINARY
&& cmd != INS_READ_BINARY)
GPG_NO_RECORD();
GPG_NO_RECORD ();
else
{
chopstx_setcancelstate (1);

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,7 +38,7 @@
#include "usb_lld.h"
#include "usb_conf.h"
#include "gnuk.h"
#include "mcu/stm32f103.h"
#include "neug.h"
#ifdef ENABLE_VIRTUAL_COM_PORT
#include "usb-cdc.h"
@@ -87,7 +87,7 @@ vcom_port_data_setup (struct usb_dev *dev)
#include "usb-msc.h"
#endif
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
#define USB_HID_REQ_GET_REPORT 1
#define USB_HID_REQ_GET_IDLE 2
@@ -108,15 +108,25 @@ static uint16_t hid_report;
#endif
static void
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
gnuk_setup_endpoints_for_interface (struct usb_dev *dev,
uint16_t interface, int stop)
{
#if !defined(GNU_LINUX_EMULATION)
(void)dev;
#endif
if (interface == CCID_INTERFACE)
{
if (!stop)
{
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP1, 1, 1);
usb_lld_setup_endp (dev, ENDP2, 0, 1);
#else
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR,
ENDP1_TXADDR, GNUK_MAX_PACKET_SIZE);
usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
#endif
}
else
{
@@ -129,7 +139,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == HID_INTERFACE)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP7, 0, 1);
#else
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
#endif
else
usb_lld_stall_tx (ENDP7);
}
@@ -138,7 +152,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == VCOM_INTERFACE_0)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP4, 0, 1);
#else
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
#endif
else
usb_lld_stall_tx (ENDP4);
}
@@ -146,9 +164,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
{
if (!stop)
{
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP3, 0, 1);
usb_lld_setup_endp (dev, ENDP5, 1, 0);
#else
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0);
usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0,
VIRTUAL_COM_PORT_DATA_SIZE);
#endif
}
else
{
@@ -161,8 +184,12 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == MSC_INTERFACE)
{
if (!stop)
#ifdef GNU_LINUX_EMULATION
usb_lld_setup_endp (dev, ENDP6, 1, 1);
#else
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
ENDP6_RXADDR, ENDP6_TXADDR, 64);
#endif
else
{
usb_lld_stall_tx (ENDP6);
@@ -180,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
@@ -202,38 +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
static uint32_t rbit (uint32_t v)
{
uint32_t r;
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
return r;
}
#ifdef FLASH_UPGRADE_SUPPORT
/* After calling this function, CRC module remain enabled. */
static int download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
static int
download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
{
uint32_t crc32 = *end_p;
const uint32_t *p;
RCC->AHBENR |= RCC_AHBENR_CRCEN;
CRC->CR = CRC_CR_RESET;
crc32_rv_reset ();
for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
CRC->DR = rbit (*p);
crc32_rv_step (rbit (*p));
if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
return usb_lld_ctrl_ack (dev);
return -1;
}
#endif
int
usb_setup (struct usb_dev *dev)
@@ -245,16 +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 */
{
uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100
+ arg->index);
#ifdef FLASH_UPGRADE_SUPPORT
uint8_t *addr = sram_address ((arg->value * 0x100) + arg->index);
#endif
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
return -1;
@@ -266,16 +298,23 @@ usb_setup (struct usb_dev *dev)
256 - (arg->index + arg->len));
return usb_lld_ctrl_recv (dev, addr, arg->len);
#else
return -1;
#endif
}
else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0)
{
#ifdef FLASH_UPGRADE_SUPPORT
if (*ccid_state_p != CCID_STATE_EXITED)
return -1;
if (((uint32_t)addr & 0x03))
if (((uintptr_t)addr & 0x03))
return -1;
return download_check_crc32 (dev, (uint32_t *)addr);
#else
return -1;
#endif
}
else if (arg->request == USB_FSIJ_GNUK_CARD_CHANGE && arg->len == 0)
{
@@ -374,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. */
}
@@ -435,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)
{
@@ -445,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 */
@@ -468,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

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

@@ -146,7 +146,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)

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