Compare commits

...

65 Commits

Author SHA1 Message Date
NIIBE Yutaka
f86f97cdbe Version 1.2.0 2016-05-20 14:10:39 +09:00
NIIBE Yutaka
1e004bec78 Fix reGNUal upgrade 2016-05-19 17:34:38 +09:00
NIIBE Yutaka
d68bee21e5 mv usb-icc.c usb-ccid.c 2016-05-19 16:58:52 +09:00
NIIBE Yutaka
2903e88986 Update Chopstx to 0.11 2016-05-19 14:04:31 +09:00
NIIBE Yutaka
25fed157e1 Follow the change of eventflag change, fixining long-standing bug of LED 2016-05-19 11:50:13 +09:00
NIIBE Yutaka
d5c5571423 LED blink change 2016-05-18 21:57:34 +09:00
NIIBE Yutaka
51d4b754e6 integrate ccid and usb threads 2016-05-18 21:34:14 +09:00
NIIBE Yutaka
48905155c5 Follow Chopstx change 2016-05-18 19:43:47 +09:00
NIIBE Yutaka
772071d1ba Update reGNUal wrt sys 3.0 2016-05-18 13:32:00 +09:00
NIIBE Yutaka
1fa45e3273 Fix reGNUal 2016-05-16 22:43:51 +09:00
NIIBE Yutaka
1a5eb0ec3b update from Chopstx 2016-05-16 22:37:23 +09:00
NIIBE Yutaka
106b042e75 neug follow update of chopstx 2016-05-13 22:31:09 +09:00
NIIBE Yutaka
eebd40d946 usb call back moved to usb_ctrl.c 2016-05-13 22:30:47 +09:00
NIIBE Yutaka
5e37c7722a Update chopstx 2016-05-12 21:57:53 +09:00
NIIBE Yutaka
b1a582e87c Fix USB stack a bit 2016-03-08 11:58:43 +09:00
NIIBE Yutaka
3f1ee534fe Support VERIFY reset feature 2016-02-09 14:19:36 +09:00
NIIBE Yutaka
522ec3299e Bignum fixes 2016-02-09 14:13:13 +09:00
NIIBE Yutaka
34e2099b23 change of S2K 2016-02-09 14:01:07 +09:00
NIIBE Yutaka
baf09ecac9 Fix the implementation for NIST P-256 and secp256k1 2016-02-08 11:24:55 +09:00
NIIBE Yutaka
db23a1d051 submodule check in configure 2016-02-08 10:11:02 +09:00
NIIBE Yutaka
3f8c4d1f17 Fix offset of bConfirmPIN 2015-11-30 13:38:00 +09:00
NIIBE Yutaka
1648a538df Version 1.1.9 2015-09-18 21:27:50 +09:00
NIIBE Yutaka
3ffac57509 Version 1.1.8 2015-09-17 17:41:27 +09:00
NIIBE Yutaka
1654a83366 Update THANKS 2015-09-16 15:22:35 +09:00
NIIBE Yutaka
022bb44f12 more tuning of stack size 2015-09-15 13:10:44 +09:00
NIIBE Yutaka
03c024f8f6 fix main and upgrade to Chopstx 0.10 2015-09-15 10:45:22 +09:00
NIIBE Yutaka
9b7d400550 usb reset doesn't cause ccid exit 2015-09-15 10:17:40 +09:00
NIIBE Yutaka
c53bd96eb8 usb reset bug fix 2015-09-15 10:04:59 +09:00
NIIBE Yutaka
1f9e8ca77f usb bug fix 2015-09-15 10:00:09 +09:00
NIIBE Yutaka
deeb8aad1c stack size tune 2015-09-15 09:55:12 +09:00
NIIBE Yutaka
f02d7d8565 cleanup for upgrade 2015-09-14 18:41:28 +09:00
NIIBE Yutaka
a5f7072a64 chopstx fix 2015-09-11 17:09:58 +09:00
NIIBE Yutaka
2c79280441 fix tool/upgrade_by_passwd.py 2015-09-11 17:09:28 +09:00
NIIBE Yutaka
d4d36bebab fix changelog 2015-09-10 16:45:32 +09:00
NIIBE Yutaka
d423678f59 fix cleanup_pop 2015-09-10 14:23:07 +09:00
NIIBE Yutaka
4b7cfd04af Update sys.h from chopstx 2015-09-10 14:20:29 +09:00
NIIBE Yutaka
115a7ba67a fix cancellation 2015-09-10 14:14:37 +09:00
NIIBE Yutaka
d0e7aad11e Update adc_stm32f103.c from NeuG 2015-09-09 19:19:23 +09:00
NIIBE Yutaka
645f42a890 allow cancelling execution of commands which take long time 2015-09-09 19:14:19 +09:00
NIIBE Yutaka
f505dea314 USB Reset handling 2015-09-09 18:49:01 +09:00
NIIBE Yutaka
748c3cac6c CDC DTR 2015-09-09 13:13:05 +09:00
NIIBE Yutaka
fa8bc533a3 Upgrade chopstx 2015-09-08 17:54:19 +09:00
NIIBE Yutaka
00062a0ac7 Add ST_DONGLE and ST_NUCLEO_F103 2015-09-08 17:51:31 +09:00
NIIBE Yutaka
c9f88bb9f1 card serial number change 2015-09-04 17:03:52 +09:00
NIIBE Yutaka
482742394d update chopstx 2015-09-04 16:54:26 +09:00
Mateusz Zalega
05867d84f6 GNUK_USB_DEVICE_ID: add Nitrokey Start 2015-09-04 16:53:39 +09:00
NIIBE Yutaka
92cbb5364a Fix 'verndor' 2015-08-11 12:35:35 +09:00
NIIBE Yutaka
61e4551b76 Version 1.1.7 2015-08-05 09:56:20 +09:00
NIIBE Yutaka
254742bc6d more change for Python 2015-08-04 12:32:56 +09:00
NIIBE Yutaka
a6fd40d4fd update Chopstx and ADC driver 2015-08-04 11:11:20 +09:00
NIIBE Yutaka
9a11e954d8 More PythonUSB change 2015-08-04 11:11:03 +09:00
NIIBE Yutaka
b2ca03dc19 Python3 fixes 2015-08-03 19:51:50 +09:00
NIIBE Yutaka
0fb6853fc7 more python3 fix 2015-08-03 19:22:02 +09:00
NIIBE Yutaka
94d6208542 More python3 fixes 2015-08-03 16:44:38 +09:00
NIIBE Yutaka
eb62609c86 Add pinpadtest info from Thomas Jarosch 2015-07-31 23:12:01 +09:00
NIIBE Yutaka
d596493831 fix sed script in configure 2015-07-31 23:00:34 +09:00
NIIBE Yutaka
70463566bf update regnual 2015-07-31 16:13:06 +09:00
NIIBE Yutaka
99c55fce60 support ST-Link/V2-1 2015-07-31 16:10:47 +09:00
NIIBE Yutaka
ec2a2e049f stlinkv2.py now works with newer PyUSB 2015-07-28 23:02:33 +09:00
NIIBE Yutaka
43331cbeaf fix for python3 2015-07-28 14:45:18 +09:00
NIIBE Yutaka
fbdac6a96a More USB driver change 2015-07-28 10:18:39 +09:00
NIIBE Yutaka
9e3af06141 USB driver update 2015-07-27 21:16:28 +09:00
NIIBE Yutaka
1de2f33d23 remove PC/SC tools 2015-07-27 18:55:10 +09:00
NIIBE Yutaka
06b364b1ac fix quote in sed scripts 2015-07-23 12:14:18 +09:00
NIIBE Yutaka
9786da7009 Use for \n 2015-07-23 11:18:50 +09:00
58 changed files with 1915 additions and 1717 deletions

260
ChangeLog
View File

@@ -1,3 +1,263 @@
2016-05-20 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: 1.2.0.
* src/usb-ccid.c (ccid_thread): Fix timeout.
(icc_handle_timeout, icc_send_status): Tweak.
2016-05-19 Niibe Yutaka <gniibe@fsij.org>
* src/usb_ctrl.c (usb_cb_ctrl_write_finish): Set bDeviceState.
* src/usb-ccid.c: Rename from usb-icc.c.
(ccid_thread): Handle reGNUal upgrade.
* src/Makefile.in (CSRC): Follow the change.
* chopstx: Update to 0.11.
2016-05-18 Niibe Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in: Tweak thread size.
* src/main.c (main): Use chopstx_setpriority.
* src/usb-icc.c (ccid_init): Use new eventflag API.
* regnual/regnual.c (nvic_enable_intr): New.
(main): Call nvic_enable_intr.
* chopstx: Update.
2016-05-16 Niibe Yutaka <gniibe@fsij.org>
* regnual/regnual.c (usb_cb_rx_ready, usb_cb_tx_done)
(usb_cb_device_reset): Follow the change of USB API.
* chopstx: Update.
* src/sys.c: Update from Chopstx.
2016-05-13 Niibe Yutaka <gniibe@fsij.org>
* src/neug.c (rng): Call chopstx_claim_irq before adc_start.
Remove call of chopstx_release_irq.
2016-05-12 Niibe Yutaka <gniibe@fsij.org>
* chopstx: Update.
* src/sys.c: Update from Chopstx.
* src/usb_lld.h: Likewise.
* src/usb_stm32f103.c: Likewise.
* src/usb_ctrl.c (usb_intr): Follow the change of USB API.
(usb_cb_rx_ready, usb_cb_tx_done): Likewise.
* src/adc.h: Remove unused declarations.
2016-03-08 Niibe Yutaka <gniibe@fsij.org>
* tool/gnuk_token.py (gnuk_token.__init__, regnual.__init__):
Don't call setConfiguration method.
* src/usb_lld.h (usb_cb_ctrl_write_finish): Change the API of
callback, which possibly needs INDEX, VALUE, and LEN parameters.
(usb_lld_set_data_to_recv): Fix the type of P.
(USB_DEVICE_DESCRIPTOR_TYPE, USB_CONFIGURATION_DESCRIPTOR_TYPE)
(USB_STRING_DESCRIPTOR_TYPE, USB_INTERFACE_DESCRIPTOR_TYPE)
(USB_ENDPOINT_DESCRIPTOR_TYPE): Remove, as we have the enumeration
values for same things.
* src/usb_stm32f103.c (handle_in0): Follow the change.
* src/usb_ctrl.c (usb_cb_ctrl_write_finish): Likewise.
* src/usb_desc.c (usb_cb_get_descriptor): Use HID_INTERFACE.
(device_desc, config_desc, string_descriptors)
(usb_cb_get_descriptor): Use the enumeration types.
* src/configure: Use the enumeration types.
* regnual/regnual.c: Follow the change of usb_lld.h.
2016-02-09 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_verify): Support VERIFY reset, which is
described in the specification V2.2 and V3.1.
* polarssl/library/bignum.c (mpi_exp_mod): Fix to our local
change. Thanks to Aidan Thornton for the failure test case.
Fix of mpi_div_mpi from upstream.
* polarssl/library/bignum.c (int_clz, int_div_int): New.
(mpi_div_mpi): Use int_div_int.
2016-02-09 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (s2k): Include the unique ID of MCU into the
computation of S2K function.
2016-02-08 Niibe Yutaka <gniibe@fsij.org>
* src/modp256r1.c (modp256r1_add, modp256r1_sub): Keep the result
less than P256R1.
(modp256r1_reduce): Fix wrong calculation.
* src/modp256k1.c (modp256k1_add, modp256k1_sub): Likewise.
Thanks to Aidan Thornton.
2016-02-05 Niibe Yutaka <gniibe@fsij.org>
* src/configure: Add submodule check suggested by Elliott
Mitchell.
2015-11-30 perillamint <perillamint@gentoo.moe>
* src/openpgp.c (card_thread): Fix offset of bConfirmPIN.
2015-09-18 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.1.9.
* src/openpgp-do.c (proc_key_import): Fix error return.
(rw_algorithm_attr): Check it's not ALGO_RSA2K.
2015-09-17 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.1.8.
2015-09-15 Niibe Yutaka <gniibe@fsij.org>
* chopstx: Update to 0.10.
* src/main.c (main): Don't join after calling ccid_usb_reset.
* src/usb-icc.c (ccid_thread): Don't finish on reset, but
keep running.
* src/usb_ctrl.c (usb_cb_device_reset): Stop the interface.
* src/usb_stm32f103.c (std_set_interface): Bug fix for conf.
* src/gnuk.ld.in (__process3_stack_size__): Increase stack size of
GPG thread.
(__process2_stack_size__): Increase stack size of RNG.
(__process4_stack_size__): Increase stack size of USB.
(__main_stack_size__): Decrease stack size of exception handlers.
(__process1_stack_size__): Decrease stack size of CCID.
2015-09-14 Niibe Yutaka <gniibe@fsij.org>
* src/gnuk.h (LED_GNUK_EXEC): New.
* src/main.c, src/usb-icc.c, src/usb_ctrl.c: icc_state_p access
clean up.
2015-09-11 Niibe Yutaka <gniibe@fsij.org>
* tool/upgrade_by_passwd.py (main): Loop until finding reGNUal
device.
2015-09-10 Niibe Yutaka <gniibe@fsij.org>
* src/call-rsa.c (rsa_cleanup): New.
(rsa_sign, rsa_decrypt, rsa_genkey): Allow cancellation.
* src/openpgp.c (cmd_pso, cmd_internal_authenticate): Cancellation
is handled by each functions in case of RSA.
2015-09-09 Niibe Yutaka <gniibe@fsij.org>
* src/sys.h: Update from Chopstx.
* src/adc_stm32f103.c: Update from NeuG.
* src/openpgp.c (process_command_apdu): Protect command execution
against cancelling the execution thread.
(cmd_pso, cmd_internal_authenticate): Allow cancellation.
* src/main.c (main): Handle LED_USB_RESET.
* src/usb-icc.c (ccid_usb_reset): New.
(ccid_thread): Upon receival of EV_USB_RESET, finish
the thread, canceling the card thread.
2015-09-08 Niibe Yutaka <gniibe@fsij.org>
* src/gnuk.h (EV_USB_RESET, LED_USB_RESET): New.
* src/usb_ctrl.c (CDC_CTRL_DTR): New.
(vcom_port_data_setup): Distinguish detail->value for DTR.
* src/configure (help): Add ST_DONGLE and ST_NUCLEO_F103.
2015-09-04 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (do_openpgpcard_aid): Use upper bytes of unique
ID of MCU; same as USB serial number.
* src/configure (help): Add NITROKEY_START.
2015-08-26 Mateusz Zalega <mateusz@nitrokey.com>
* GNUK_USB_DEVICE_ID: Add Nitrokey Start.
2015-08-05 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.1.7.
2015-08-04 Niibe Yutaka <gniibe@fsij.org>
* src/adc_stm32f103.c: Update from NeuG 1.0.3.
* chopstx: Update to 0.08.
* src/sys.h: Update.
2015-08-03 Niibe Yutaka <gniibe@fsij.org>
* test/features/steps.py (set_msg): Python3 fix.
* test/generate_keys.py: Likewise.
* test/rsa_keys.py: Likewise.
* tool/gnuk_token.py (gnuk_token.download, gnuk_token.execute)
(regnual.download): Python3 fix.
(list_to_string): Remove.
* tool/upgrade_by_passwd.py (maian): Python3 fix.
* tool/usb_strings.py (main): Python3 fix.
2015-07-31 Niibe Yutaka <gniibe@fsij.org>
* src/configure (output_vendor_product_serial_strings): Fix sed
script when string is short. Remove empty line.
* regnual/regnual.c (usb_cb_ctrl_write_finish, usb_cb_setup)
(usb_cb_get_descriptor, usb_cb_interface): Follow the change
of USB API.
* tool/stlinkv2.py: Support ST-Link/V2-1.
2015-07-28 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py: Fix for Python3. Thanks to Bertrand Jacquin.
* tool/gpg_agent.py: Fix for Python3.
* src/usb-msc.c: Update from Fraucheky.
* src/usb_stm32f103.c (struct DATA_INFO): Remove offset.
(struct DEVICE_INFO): Integrate CONTROL_INFO.
2015-07-27 Niibe Yutaka <gniibe@fsij.org>
* src/usb_stm32f103.c (usb_lld_reply_request): New.
(usb_lld_set_data_to_send): Remove.
(usb_lld_set_data_to_recv): Not a macro but a function.
(std_get_status): Don't use statically allocated memory.
(std_get_configuration): Use usb_lld_reply_request.
(handle_setup0): Follow the change.
* src/usb_ctrl.c (vcom_port_data_setup, usb_cb_setup)
(usb_cb_interface): Use usb_lld_reply_request.
* src/usb_desc.c (usb_cb_get_descriptor): Likewise.
2015-07-24 Niibe Yutaka <gniibe@fsij.org>
* tool/gnuk_put_binary.py: Remove.
* tool/gnuk_remove_keys.py: Remove.
2015-07-23 Niibe Yutaka <gniibe@fsij.org>
* src/configure (nl): New. Follow the change of NeuG.
2015-07-21 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.1.6.

View File

@@ -1,3 +1,4 @@
# VID:PID bcdDev Product_STRING Vender_STRING
# VID:PID bcdDev Product_STRING Vendor_STRING
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
20a0:4211 0200 Nitrokey Start Nitrokey
##########<TAB> ##<TAB> ##########<TAB> #################

62
NEWS
View File

@@ -1,8 +1,66 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.0
Released 2016-05-20, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.11.
** Support authentication status reset by VERIFY command.
This feature is described in the OpenPGPcard specification V2.2 and
V3.1, which allow user to reset authentication status.
** S2K algorithm tweak to defeat "copycat" service of MCU.
Even if the existence of some services copying MCU, your private key
will not be controled by others, in some cases.
** Bug fix for secp256k1 and NIST P-256.
Bugs in basic computation were fixed.
** Bug fix for bignum routines.
Bignum routine update from upstream (failure doesn't occur for our RSA
computation, though). Another fix for mpi_exp_mod.
* Major changes in Gnuk 1.1.9
Released 2015-09-18, by NIIBE Yutaka
** Bug fix for Ed25519 and Curve25519
When registering key, wrong operations were not detected correctly.
This is fixed.
* Major changes in Gnuk 1.1.8
Released 2015-09-17, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.10, which supports Nitrokey-Start.
** Card serial number
The way to determine a serial number of Gnuk Token for card has been
changed. It uses the 96-bit unique bits of MCU, but the portion for
use is changed.
** USB Reset handling
USB reset lets Gnuk Token restart. It would not be perfect, when it's
during computation of some function, but most parts are protected by
Chopstx's feature of cancellation.
* Major changes in Gnuk 1.1.7
Released 2015-08-05, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.08, which supports STM32 Nucleo and ST Dongle.
* Major changes in Gnuk 1.1.6
Released 2015-07-21
Released 2015-07-21, by NIIBE Yutaka
** USB SerialNumber String
The way to determine a serial number of Gnuk Token has been changed.
@@ -14,7 +72,7 @@ We use Chopstx 0.07, which supports STM32 Primer2 and CQ STARM, too.
** Experimental Curve25519 support.
Gnuk can support Curve25519 (for deecryption). Note that this is
Gnuk can support Curve25519 (for decryption). Note that this is
pretty much experimental, and subjects to change. The low level code
is somehow stable, but there are no consensus in higer level.
Especially, OID in the key attribute would be changed in future.

151
README
View File

@@ -1,29 +1,27 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.1.6
2015-07-21
Version 1.2.0
2016-05-20
Niibe Yutaka
Free Software Initiative of Japan
Warning
=======
Release Notes
=============
This is another experimental release of Gnuk, version 1.1.6, which has
This is new release of Gnuk, version 1.2.0, 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
that the instruction of importing keys won't cause any confusion. It
has supports of ECDSA (with NIST P256 and secp256k1), EdDSA, and ECDH
(with NIST P256, secp256k1, and Curve25519), but this ECC feature is
pretty much experimental, and it requires development version of GnuPG
with newest version of libgcrypt (Further, for Curve25519, it requires
additional patches by me).
that the instruction of importing keys won't cause any confusion.
It also support RSA-4096 experimentally, but users should know that it
takes more than 8 second to sign/decrypt.
It has supports of EdDSA, ECDSA (with NIST P256 and secp256k1), and
ECDH (with NIST P256, secp256k1, and X25519), but this ECC feature is
somehow experimental, and it requires modern GnuPG 2.1.x with
libgcrypt 1.7.0 or later.
You will not able to keep using Curve25519 keys, as the key format is
subject to change.
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.
What's Gnuk?
@@ -48,9 +46,9 @@ FAQ
===
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, GPF Crypto Stick, etc.) ?
card 2.0, YubiKey, etc.) ?
http://www.g10code.de/p-card.html
http://www.privacyfoundation.de/crypto_stick/
https://www.yubico.com/
A0: Good points of Gnuk are:
* If you have skill of electronics and like DIY, you can build
Gnuk Token cheaper (see Q8-A8).
@@ -63,21 +61,24 @@ A0: Good points of Gnuk are:
"for Free Software"; Gnuk supports GnuPG.
Q1: What kind of key algorithm is supported?
A1: Gnuk version 1.0 only supports RSA 2048.
Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA,
as well as RSA 4096-bit. But it takes long time to sign with RSA 4096.
A1: Gnuk version 1.0 only supports RSA-2048.
Gnuk version 1.2.x supports 256-bit EdDSA and ECDSA, as well as
RSA-4096. But it takes long time to sign with RSA-4096.
Q2: How long does it take for digital signing?
A2: It takes a second and a half or so.
A2: It takes a second and a half or so for RSA-2048.
It takes more than 8 secondd for RSA-4096.
Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103.
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
kind of the best choice, hopefully.
If you have a skill of electronics, STM32 Nucleo F103 is the best
choice for experiment.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use gnupg 1.4.12-7 and gnupg-agent
2.0.20-1.
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.12 in
experimental.
Q5: What's version of pcscd and libccid are you using?
A5: I don't use them, pcscd and libccid are optional, you can use Gnuk
@@ -94,8 +95,11 @@ A6: You need a target board plus a JTAG/SWD debugger. If you just
Q7: How much does it cost?
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
Q8: How much does it cost for DIY version?
A8: STM32 Nucleo F103 costs about $10 USD.
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
A9: Older GnuPG's SCDaemon has problems for handling insertion/removal of
card/reader. When your newly inserted token is not found by
GnuPG, try killing scdaemon and let it to be invoked again. I do:
@@ -134,24 +138,15 @@ Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
Qd: Do you know a good SWD debugger to connect FST-01 or something?
Ad: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program.
writer program. STM32 Nucleo F103 comes with the valiant of
ST-Link/V2. However, the firmware of ST-Link/V2 is proprietary.
Now, I develop BBG-SWD, SWD debugger by BeagleBone Green.
Tested features
===============
Release notes
=============
This is third experimental release in version 1.1 series of Gnuk.
While it is daily use by its developer, some newly introduced features
(including ECDSA/EdDSA/ECDH, key generation and firmware upgrade)
should be considered experimental. ECDSA/EdDSA/ECDH is really
experimental. Further, ECDH on Curve25519 is much experimental. You
won't be able to keep using the key, since the key format of GnuPG is
not defined and it's subject to change.
Tested features are:
Gnuk is tested by test suite. Please see the test directory.
* Personalization of the card
* Changing Login name, URL, Name, Sex, Language, etc.
@@ -168,10 +163,10 @@ Tested features are:
* Modify with pin pad
* Card holder certificate (read)
* Removal of keys
* Key generation on device side
* Key generation on device side for RSA-2048
* Overriding key import
Original features of Gnuk, tested lightly:
Original features of Gnuk, tested manually lightly:
* OpenPGP card serial number setup
* Card holder certificate (write by UPDATE BINARY)
@@ -179,12 +174,12 @@ Original features of Gnuk, tested lightly:
It is known not-working well:
* It is known that the combination of libccid 1.4.1 (or newer)
with libusb 1.0.8 (or older) has a minor problem. It is
rare but it is possible for USB communication to be failed,
because of a bug in libusb implementation. Use libusbx
1.0.9 or newer, or don't use PC/SC, but use internal CCID
driver of GnuPG.
* It is known that the specific combination of libccid 1.4.1
(or newer) with libusb 1.0.8 (or older) had a minor problem.
It is rare but it is possible for USB communication to be
failed, because of a bug in libusb implementation. Use
libusbx 1.0.9 or newer, or don't use PC/SC, but use internal
CCID driver of GnuPG.
Targets
@@ -197,17 +192,30 @@ DfuSe is for experiment only, because it is impossible for DfuSe to
disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger.
For PIN-pad support, I connect a consumer IR receive module to FST-01,
and use controller for TV. PIN verification is supported by this
configuration. Yes, it is not secure at all, since it is very easy to
monitor IR output of the controllers. It is just an experiment. Note
that hardware needed for this experiment is only a consumer IR receive
module which is as cheap as 50 JPY.
For experimental PIN-pad support, I connect a consumer IR receive
module to FST-01, and use controller for TV. PIN verification is
supported by this configuration. Yes, it is not secure at all, since
it is very easy to monitor IR output of the controllers. It is just
an experiment. Note that hardware needed for this experiment is only
a consumer IR receive module which is as cheap as 50 JPY.
Note that you need pinpad support for GnuPG to use PIN-pad enabled
Gnuk. The pinpad support for GnuPG is only available in version 2.
Build system and Host system
============================
Makefile is written for GNU make. You need Bash 4.x for configure.
If your bash is not installed as /bin/bash, you need to run configure
script prepending 'bash' before './configure'.
Some tools are written in Python. If your Python is not installed as
/usr/bin/python, please prepend 'python' for your command invocation.
Python 2.7 and PyUSB 0.4.3 is assumed.
Souce code
==========
@@ -240,7 +248,7 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 0.07
* chopstx/ -- Chopstx 0.11
We use Chopstx as the kernel for Gnuk.
@@ -293,7 +301,7 @@ Gnuk is distributed with external source code.
USB vendor ID and product ID (USB device ID)
============================================
When you have a vender ID and assign a product ID for Gnuk, edit the
When you have a vendor ID and assign a product ID for Gnuk, edit the
file GNUK_USB_DEVICE_ID and add an entry for yours. In this case,
please contact Niibe, so that it is listed to the file in the official
release of the source code.
@@ -350,10 +358,16 @@ How to compile
You need GNU toolchain and newlib for 'arm-none-eabi' target.
There is "gcc-arm-embedded" project. See:
On Debian we can install the packages of gcc-arm-none-eabi,
gdb-arm-none-eabi and its friends. I'm using:
https://launchpad.net/gcc-arm-embedded/
binutils-arm-none-eabi 2.26-4+8
gcc-arm-none-eabi 15:4.9.3+svn231177-1
gdb-arm-none-eabi 7.10-1+9
libnewlib-arm-none-eabi 2.2.0+git20150830.5a3d536-1
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
Change directory to `src':
@@ -367,7 +381,8 @@ Here, you need to specify USB vendor ID and product ID. For FSIJ's,
it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and
product ID' above.
Type:
Then, type:
$ make
@@ -436,11 +451,13 @@ to access the contents. If you want to protect, killing DfuSe and
accessing by JTAG debugger is recommended.
How to configure
================
(Optional) Configure serial number and X.509 certificate
========================================================
You need python and pyscard (python-pyscard package in Debian) or
PyUSB 0.4.3 (python-usb package in Debian).
This is completely optional.
For this procedure, you need python and pyscard (python-pyscard
package in Debian) or PyUSB 0.4.3 (python-usb package in Debian).
(1) [pyscard] Stop scdaemon
[PyUSB] Stop the pcsc daemon.
@@ -459,7 +476,7 @@ In case of PyUSB tool, you need to stop pcscd.
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary.py -s ../GNUK_SERIAL_NUMBER
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary_usb.py -s ../GNUK_SERIAL_NUMBER
Writing serial number
...
@@ -467,7 +484,7 @@ If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
If you have card holder certificate binary file, you can do:
$ ../tool/gnuk_put_binary.py ../../<YOUR-CERTIFICATE>.bin
$ ../tool/gnuk_put_binary_usb.py ../../<YOUR-CERTIFICATE>.bin
../../<YOUR-CERTIFICATE>.bin: <LENGTH-OF-YOUR-CERTIFICATE>
Updating card holder certificate
...
@@ -568,8 +585,8 @@ I put Chopstx as a submodule of Git. Please do this:
$ git submodule init
$ git submodule update
We have migrated from ChibiOS/RT to Chopstx. If you have old code of
ChibiOS/RT, you need:
We have migrated from ChibiOS/RT to Chopstx in Gnuk 1.1. If you have
old code of ChibiOS/RT, you need:
Edit .git/config to remove chibios reference
git rm --cached chibios
@@ -593,7 +610,7 @@ Your Contributions
==================
FSIJ welcomes your contributions. Please assign your copyright
to FSIJ (if possible).
to FSIJ (if possible), as I do.
Foot note

10
THANKS
View File

@@ -9,17 +9,27 @@ improvements, or fixing bugs. Here is a list of those people.
Achim Pietig achim@pietig.com
Aidan Thornton
Anibal Monsalve Salazar anibal@debian.org
Andre Zepezauer andre.zepezauer@student.uni-halle.de
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
Jonathan McDowell noodles@earth.li
Kaz Kojima kkojima@rr.iij4u.or.jp
Ludovic Rousseau ludovic.rousseau@free.fr
Luis Felipe R. Murillo luisfelipe@ucla.edu
Mateusz Zalega mateusz@nitrokey.com
MATSUU Takuto matsuu@gentoo.org
Micah Anderson micah@debian.org
NAGAMI Takeshi nagami-takeshi@aist.go.jp
Nguyễn Hồng Quân quannguyen@mbm.vn
Nico Rikken nico@nicorikken.eu
NOKUBI Takatsugu knok@daionet.gr.jp
Paul Bakker polarssl_maintainer@polarssl.org
Santiago Ruano Rincón santiago@debian.org
Shane Coughlan scoughlan@openinventionnetwork.com
Vasily Evseenko
Werner Koch wk@gnupg.org

View File

@@ -1 +1 @@
release/1.1.6
release/1.2.0

Submodule chopstx updated: bdaae5661d...5458b77d36

View File

@@ -37,9 +37,3 @@ The tool ``../tool/gnuk_put_binary_libusb.py`` examines environment variable of
Configuration: 1
Interface: 0
d2 76 00 01 24 01 02 00 f5 17 00 00 00 01 00 00
The example above is the case of libusb version.
Use the tool ``../tool/gnuk_put_binary.py`` instead , for PC/SC Lite.
You need PyScard for this.

131
doc/note/firmware-update-2 Normal file
View File

@@ -0,0 +1,131 @@
Please refer:
How can I reflash FST-01 with SWD port?:
http://www.gniibe.org/FST-01/q_and_a/swd-debugger.html
Installing newer version of Gnuk onto FST-01 with Gnuk 1.0.1
============================================================
Please note that the feature of firmware upgrade is somewhat
experimental. I haven't got any success reports yet, but it's only
used by me, so far. When you will get some failure during your
firmware installation, you will need SWD debugger. YOU HAVE BEEN
WARNED. It is best to try firmware upgrade after you get a SWD
debugger.
The firmare upgrade feature of Gnuk
------------------------------------
Gnuk supports firmware upgrade by reGNUal. It works in the following
steps.
1. User registers RSA public key to Gnuk Token for firmware upgrade
2. When User wants firmware upgrade, user sends
the GET_CHALLENGE command then the EXTERNAL_AUTHENTICATE command
to Gnuk Token from host PC to authenticate.
The EXTERNAL_AUTHENTICATE command message consists of
signature (of challenge) by corresponding RSA private key.
3. When Gnuk Token receives the EXTERNAL_AUTHENTICATE command message
and validates signature successfully, Gnuk finishes its normal
operation and goes to enter mode of loading special program onto RAM.
4. Host PC sends reflashing program (reGNUal) to Gnuk Token.
5. Gnuk clears up all content of flash ROM (but first 4KiB of system)
at the end of receiving special program and transfers its control
to reGNUal.
6. reGNUal on Gnuk Token receives new firmware image from host PC and writes
to each page.
7. Done.
Host PC setting for Gnuk
------------------------
You need proper configuration for permission of Gnuk Token (udev
setting). It should have lines something like: ::
# Gnuk Token by FSIJ
SUBSYSTEMS=="usb", ACTION=="add", \
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
I have those lines in /etc/udev/rules.d/69-gnuk.rules.
Building another version (newer) of Gnuk
----------------------------------------
Please see README of Gnuk for detail, but it's like configure
and make: ::
$ pwd
/home/user/src/gnuk
$ cd src
$ ./configure --vidpid=234b:0000
$ 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
is FST-01.
Then you get build/gnuk.elf and build/gnuk.bin.
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.
Bulding reGNUal
---------------
You need to compile reGNUal. ::
$ cd ../regnual
$ make
Then, you should have regnual.bin. Note that 'configure' of Gnuk
itself is needed before compiling reGNUal.
upgrade_by_passwd.py
--------------------
In the source code distribution of 1.0.4 (or current development
version) of Gnuk, there is a tool named 'upgrade_by_passwd.py'.
This is an easy tool to hide lengthy steps from user and to allow user
firmware upgrade only by password of Gnuk Token.
Before running the script, you need to kill scdaemon: ::
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
The command line invokation above assumes that you properly configure
your environment for Gnuk Token.
How to run the script: ::
$ cd tool
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.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).
If you already have configured another upgrade key installed, you can
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0
to 3.
--

View File

@@ -223,6 +223,24 @@ size_t mpi_lsb( const mpi *X )
return( 0 );
}
/*
* Count leading zero bits in a given integer
*/
static size_t int_clz( const t_uint x )
{
size_t j;
t_uint mask = (t_uint) 1 << (biL - 1);
for( j = 0; j < biL; j++ )
{
if( x & mask ) break;
mask >>= 1;
}
return j;
}
/*
* Return the number of most significant bits
*/
@@ -1102,6 +1120,100 @@ int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
return( mpi_mul_mpi( X, A, &_B ) );
}
/*
* Unsigned integer divide - 64bit dividend and 32bit divisor
*/
static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
{
#if defined(POLARSSL_HAVE_UDBL)
t_udbl dividend, quotient;
#else
const t_uint radix = (t_uint) 1 << biH;
const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
t_uint d0, d1, q0, q1, rAX, r0, quotient;
t_uint u0_msw, u0_lsw;
size_t s;
#endif
/*
* Check for overflow
*/
if(( 0 == d ) || ( u1 >= d ))
{
if (r != NULL) *r = (~0);
return (~0);
}
#if defined(POLARSSL_HAVE_UDBL)
dividend = (t_udbl) u1 << biL;
dividend |= (t_udbl) u0;
quotient = dividend / d;
if( quotient > ( (t_udbl) 1 << biL ) - 1 )
quotient = ( (t_udbl) 1 << biL ) - 1;
if( r != NULL )
*r = (t_uint)( dividend - (quotient * d ) );
return (t_uint) quotient;
#else
/*
* Algorithm D, Section 4.3.1 - The Art of Computer Programming
* Vol. 2 - Seminumerical Algorithms, Knuth
*/
/*
* Normalize the divisor, d, and dividend, u0, u1
*/
s = int_clz( d );
d = d << s;
u1 = u1 << s;
u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
u0 = u0 << s;
d1 = d >> biH;
d0 = d & uint_halfword_mask;
u0_msw = u0 >> biH;
u0_lsw = u0 & uint_halfword_mask;
/*
* Find the first quotient and remainder
*/
q1 = u1 / d1;
r0 = u1 - d1 * q1;
while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
{
q1 -= 1;
r0 += d1;
if ( r0 >= radix ) break;
}
rAX = (u1 * radix) + (u0_msw - q1 * d);
q0 = rAX / d1;
r0 = rAX - q0 * d1;
while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
{
q0 -= 1;
r0 += d1;
if ( r0 >= radix ) break;
}
if (r != NULL)
*r = (rAX * radix + u0_lsw - q0 * d) >> s;
quotient = q1 * radix + q0;
return quotient;
#endif
}
/*
* Division by mpi: A = Q * B + R (HAC 14.20)
*/
@@ -1159,57 +1271,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Z.p[i - t - 1] = ~0;
else
{
#if defined(POLARSSL_HAVE_UDBL)
t_udbl r;
r = (t_udbl) X.p[i] << biL;
r |= (t_udbl) X.p[i - 1];
r /= Y.p[t];
if( r > ((t_udbl) 1 << biL) - 1)
r = ((t_udbl) 1 << biL) - 1;
Z.p[i - t - 1] = (t_uint) r;
#else
/*
* __udiv_qrnnd_c, from gmp/longlong.h
*/
t_uint q0, q1, r0, r1;
t_uint d0, d1, d, m;
d = Y.p[t];
d0 = ( d << biH ) >> biH;
d1 = ( d >> biH );
q1 = X.p[i] / d1;
r1 = X.p[i] - d1 * q1;
r1 <<= biH;
r1 |= ( X.p[i - 1] >> biH );
m = q1 * d0;
if( r1 < m )
{
q1--, r1 += d;
while( r1 >= d && r1 < m )
q1--, r1 += d;
}
r1 -= m;
q0 = r1 / d1;
r0 = r1 - d1 * q0;
r0 <<= biH;
r0 |= ( X.p[i - 1] << biH ) >> biH;
m = q0 * d0;
if( r0 < m )
{
q0--, r0 += d;
while( r0 >= d && r0 < m )
q0--, r0 += d;
}
r0 -= m;
Z.p[i - t - 1] = ( q1 << biH ) | q0;
#endif
Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i-1], Y.p[t], NULL);
}
Z.p[i - t - 1]++;
@@ -1584,6 +1646,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
memset (d, 0, 2 * N->n * ciL); /* Set D zero. */
mpi_sub_hlp( N->n, N->p, d + N->n);
MPI_CHK( mpi_mod_mpi( &RR, &T, N ) );
MPI_CHK( mpi_grow( &RR, N->n ) );
if( _RR != NULL )
memcpy( _RR, &RR, sizeof( mpi ) );

View File

@@ -32,7 +32,7 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
all: regnual.hex
regnual.o: regnual.c ../src/sys.h
regnual.o: regnual.c ../src/sys.h ../src/usb_lld.h
regnual.hex: regnual.elf
$(OBJCOPY) -Obinary regnual.elf regnual.bin

View File

@@ -1,7 +1,8 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2012, 2013, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -32,19 +33,25 @@
extern void *memset (void *s, int c, size_t n);
extern void set_led (int);
extern uint8_t _flash_start, _flash_end;
extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
extern int flash_protect (void);
extern void nvic_system_reset (void);
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F1. */
#define FLASH_OFFSET 0x1000 /* First pages are not-writable. */
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
static uint32_t flash_end;
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
/* USB Standard Device Descriptor */
static const uint8_t regnual_device_desc[] = {
18, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
DEVICE_DESCRIPTOR, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */
0xFF, /* bDeviceClass: VENDOR */
0x00, /* bDeviceSubClass */
@@ -57,24 +64,26 @@ static const uint8_t regnual_device_desc[] = {
0x01 /* bNumConfigurations */
};
#if defined(USB_SELF_POWERED)
#define REGNUAL_FEATURE_INIT 0xC0 /* self powered */
#else
#define REGNUAL_FEATURE_INIT 0x80 /* bus powered */
#endif
static const uint8_t regnual_config_desc[] = {
9,
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
18, 0, /* wTotalLength: no of returned bytes */
1, /* bNumInterfaces: single vender interface */
CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
18, 0, /* wTotalLength: no of returned bytes */
1, /* bNumInterfaces: single vendor interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: None */
#if defined(USB_SELF_POWERED)
0xC0, /* bmAttributes: self powered */
#else
0x80, /* bmAttributes: bus powered */
#endif
50, /* MaxPower 100 mA */
REGNUAL_FEATURE_INIT, /* bmAttributes: bus powered */
50, /* MaxPower 100 mA */
/* Interface Descriptor */
9,
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0, /* bInterfaceNumber: Index of this interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
0, /* bInterfaceNumber: Index of this interface */
0, /* Alternate setting for this interface */
0, /* bNumEndpoints: None */
0xFF,
@@ -85,7 +94,7 @@ static const uint8_t regnual_config_desc[] = {
static const uint8_t regnual_string_lang_id[] = {
4, /* bLength */
USB_STRING_DESCRIPTOR_TYPE,
STRING_DESCRIPTOR,
0x09, 0x04 /* LangID = 0x0409: US-English */
};
@@ -93,7 +102,7 @@ static const uint8_t regnual_string_lang_id[] = {
static const uint8_t regnual_string_serial[] = {
8*2+2,
USB_STRING_DESCRIPTOR_TYPE,
STRING_DESCRIPTOR,
/* FSIJ-0.0 */
'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0,
'0', 0, '.', 0, '0', 0,
@@ -103,13 +112,7 @@ static const uint8_t regnual_string_serial[] = {
void
usb_cb_device_reset (void)
{
/* Set DEVICE as not configured */
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (regnual_config_desc[7]);
usb_lld_reset ();
usb_lld_reset (REGNUAL_FEATURE_INIT);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
@@ -166,33 +169,30 @@ static uint32_t calc_crc32 (void)
}
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
struct req_args *arg)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
{
if (req_no == USB_REGNUAL_SEND && value == 0)
if (req_no == USB_REGNUAL_SEND && arg->value == 0)
result = calc_crc32 ();
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
else if (req_no == USB_REGNUAL_FLASH)
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
result = flash_write (dst_addr, (const uint8_t *)mem, 256);
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
else if (req_no == USB_REGNUAL_PROTECT && arg->value == 0)
result = flash_protect ();
else if (req_no == USB_REGNUAL_FINISH && len == 0
&& value == 0 && index == 0)
else if (req_no == USB_REGNUAL_FINISH && arg->value == 0)
nvic_system_reset ();
}
}
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -202,45 +202,42 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
{
if (req_no == USB_REGNUAL_MEMINFO)
{
static const uint8_t *mem_info[2];
const uint8_t *mem_info[2];
mem_info[0] = &_flash_start;
mem_info[1] = &_flash_end;
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
return USB_SUCCESS;
mem_info[0] = (const uint8_t *)FLASH_START;
mem_info[1] = (const uint8_t *)flash_end;
return usb_lld_reply_request (mem_info, sizeof (mem_info), arg);
}
else if (req_no == USB_REGNUAL_RESULT)
{
usb_lld_set_data_to_send (&result, sizeof (uint32_t));
return USB_SUCCESS;
}
return usb_lld_reply_request (&result, sizeof (uint32_t), arg);
}
else /* SETUP_SET */
{
if (req_no == USB_REGNUAL_SEND)
{
if (value != 0 || index + len > 256)
if (arg->value != 0 || arg->index + arg->len > 256)
return USB_UNSUPPORT;
if (index + len < 256)
memset ((uint8_t *)mem + index + len, 0xff,
256 - (index + len));
if (arg->index + arg->len < 256)
memset ((uint8_t *)mem + arg->index + arg->len, 0xff,
256 - (arg->index + arg->len));
usb_lld_set_data_to_recv (mem + index, len);
usb_lld_set_data_to_recv (mem + arg->index, arg->len);
return USB_SUCCESS;
}
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
else if (req_no == USB_REGNUAL_FLASH && arg->len == 0
&& arg->index == 0)
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
if (dst_addr + 256 <= (uint32_t)&_flash_end)
if (dst_addr + 256 <= flash_end)
return USB_SUCCESS;
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
else if (req_no == USB_REGNUAL_PROTECT && arg->len == 0
&& arg->value == 0 && arg->index == 0)
return USB_SUCCESS;
else if (req_no == USB_REGNUAL_FINISH && len == 0
&& value == 0 && index == 0)
else if (req_no == USB_REGNUAL_FINISH && arg->len == 0
&& arg->value == 0 && arg->index == 0)
return USB_SUCCESS;
}
}
@@ -250,25 +247,17 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index, uint16_t length)
struct req_args *arg)
{
(void)index;
(void)length;
if (rcp != DEVICE_RECIPIENT)
return USB_UNSUPPORT;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (regnual_device_desc,
sizeof (regnual_device_desc));
return USB_SUCCESS;
}
return usb_lld_reply_request (regnual_device_desc,
sizeof (regnual_device_desc), arg);
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (regnual_config_desc,
sizeof (regnual_config_desc));
return USB_SUCCESS;
}
return usb_lld_reply_request (regnual_config_desc,
sizeof (regnual_config_desc), arg);
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -281,12 +270,12 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
size = sizeof (regnual_string_lang_id);
break;
case 1:
str = gnukStringVendor;
size = sizeof (gnukStringVendor);
str = gnuk_string_vendor;
size = sizeof (gnuk_string_vendor);
break;
case 2:
str = gnukStringProduct;
size = sizeof (gnukStringProduct);
str = gnuk_string_product;
size = sizeof (gnuk_string_product);
break;
case 3:
str = regnual_string_serial;
@@ -296,8 +285,7 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
return USB_UNSUPPORT;
}
usb_lld_set_data_to_send (str, size);
return USB_SUCCESS;
return usb_lld_reply_request (str, size, arg);
}
return USB_UNSUPPORT;
@@ -319,12 +307,21 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, struct req_args *arg)
{
(void)cmd; (void)interface; (void)alt;
(void)cmd; (void)arg;
return USB_UNSUPPORT;
}
void usb_cb_rx_ready (uint8_t ep_num)
{
(void)ep_num;
}
void usb_cb_tx_done (uint8_t ep_num)
{
(void)ep_num;
}
static void wait (int count)
{
@@ -336,6 +333,30 @@ static void wait (int count)
#define WAIT 2400000
/* NVIC: Nested Vectored Interrupt Controller. */
struct NVIC {
volatile uint32_t ISER[8];
uint32_t unused1[24];
volatile uint32_t ICER[8];
uint32_t unused2[24];
volatile uint32_t ISPR[8];
uint32_t unused3[24];
volatile uint32_t ICPR[8];
uint32_t unused4[24];
volatile uint32_t IABR[8];
uint32_t unused5[56];
volatile uint32_t IPR[60];
};
static struct NVIC *const NVIC = (struct NVIC *const)0xE000E100;
#define NVIC_ISER(n) (NVIC->ISER[n >> 5])
static void nvic_enable_intr (uint8_t irq_num)
{
NVIC_ISER (irq_num) = 1 << (irq_num & 0x1f);
}
#define USB_LP_CAN1_RX0_IRQn 20
int
main (int argc, char *argv[])
{
@@ -343,7 +364,15 @@ main (int argc, char *argv[])
set_led (0);
usb_lld_init (regnual_config_desc[7]);
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
/*
* NVIC interrupt priority was set by Gnuk.
* USB interrupt is disabled by NVIC setting.
* We enable the interrupt again by nvic_enable_intr.
*/
usb_lld_init (REGNUAL_FEATURE_INIT);
nvic_enable_intr (USB_LP_CAN1_RX0_IRQn);
while (1)
{

View File

@@ -12,8 +12,6 @@ MEMORY
}
vector = 0x08000000;
_flash_start = 0x08001000;
_flash_end = 0x08020000;
__ram_start__ = ORIGIN(ram0);
__ram_size__ = 20k;

View File

@@ -11,7 +11,7 @@ LDSCRIPT= gnuk.ld
CSRC = main.c usb_stm32f103.c adc_stm32f103.c \
usb_desc.c usb_ctrl.c \
call-rsa.c \
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
bn.c mod.c \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \

View File

@@ -169,7 +169,7 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
pw_len = ks[0] & PW_LEN_MASK;
salt = KS_GET_SALT (ks);
salt_len = SALT_SIZE;
if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len)
return -1;

View File

@@ -1,15 +1,7 @@
extern chopstx_mutex_t adc_mtx;
extern chopstx_cond_t adc_cond;
extern int adc_waiting;
extern int adc_data_available;
void adc_init (void);
void adc_start (void);
void adc_stop (void);
#define ADC_SAMPLE_MODE 0
#define ADC_CRC32_MODE 1
extern uint32_t adc_buf[64];
void adc_start_conversion (int offset, int count);

View File

@@ -90,7 +90,7 @@
#define NEUG_ADC_SETTING1_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT) \
| ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) \
| ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR) \
| ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
| ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
#define NEUG_ADC_SETTING1_NUM_CHANNELS 4
@@ -149,7 +149,7 @@ get_adc_config (uint32_t config[4])
case BOARD_ID_OLIMEX_STM32_H103:
case BOARD_ID_STBEE:
config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5);
config[1] = 0;
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10)
@@ -169,6 +169,9 @@ get_adc_config (uint32_t config[4])
case BOARD_ID_MAPLE_MINI:
case BOARD_ID_STM32_PRIMER2:
case BOARD_ID_STM8S_DISCOVERY:
case BOARD_ID_ST_DONGLE:
case BOARD_ID_ST_NUCLEO_F103:
case BOARD_ID_NITROKEY_START:
default:
config[0] = 0;
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)

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
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -25,6 +25,8 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <chopstx.h>
#include "config.h"
#include "gnuk.h"
@@ -34,6 +36,15 @@
#include "polarssl/rsa.h"
static rsa_context rsa_ctx;
static struct chx_cleanup clp;
static void
rsa_cleanup (void *arg)
{
free (arg);
rsa_free (&rsa_ctx);
}
int
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
@@ -66,12 +77,20 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
mpi_free (&P1); mpi_free (&Q1); mpi_free (&H);
if (ret == 0)
{
DEBUG_INFO ("RSA sign...");
int cs;
DEBUG_INFO ("RSA sign...");
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
ret = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, temp);
memcpy (output, temp, pubkey_len);
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
rsa_free (&rsa_ctx);
@@ -150,10 +169,19 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
mpi_free (&P1); mpi_free (&Q1); mpi_free (&H);
if (ret == 0)
{
int cs;
DEBUG_INFO ("RSA decrypt ...");
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, output_len_p, input,
output, MAX_RES_APDU_DATA_SIZE);
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
rsa_free (&rsa_ctx);
@@ -213,6 +241,8 @@ rsa_genkey (int pubkey_len)
uint8_t *p = p_q_modulus;
uint8_t *q = p_q_modulus + pubkey_len / 2;
uint8_t *modulus = p_q_modulus + pubkey_len;
int cs;
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
extern void neug_flush (void);
@@ -222,12 +252,19 @@ rsa_genkey (int pubkey_len)
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;
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;
@@ -238,6 +275,8 @@ rsa_genkey (int pubkey_len)
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
rsa_free (&rsa_ctx);
if (ret != 0)
return NULL;

49
src/configure vendored
View File

@@ -1,9 +1,12 @@
#! /bin/bash
# This is bash which supports ANSI-C Quoting
nl=$'\n'
#
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
# Free Software Initiative of Japan
#
# This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -20,6 +23,15 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Submodule check
#
if ! test -f ../chopstx/rules.mk; then
echo "Submodule 'chopstx' not found" >&2
echo "You might need: git submodule update --init" >&2
exit 1
fi
# Default settings
help=no
vidpid=none
@@ -104,6 +116,9 @@ Configuration:
STBEE
STBEE_MINI
MAPLE_MINI
ST_DONGLE
ST_NUCLEO_F103
NITROKEY_START
CQ_STARM
FST_01_00 (unreleased version with 8MHz XTAL)
--enable-debug debug with virtual COM port [no]
@@ -121,7 +136,7 @@ EOF
fi
if test "$vidpid" = "none"; then
echo "Please specify Vendor ID and Product ID by --vidpid option."
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
exit 1
fi
@@ -175,7 +190,7 @@ fi
# --with-dfu option
if test "$with_dfu" = "yes"; then
if test "$target" = "FST_01" -o "$target" = "FST_01_00"; then
echo "FST-01 doesn't have DFU loader, you should not use --with-dfu."
echo "FST-01 doesn't have DFU loader, you should not use --with-dfu." >&2
exit 1
fi
echo "Configured for DFU"
@@ -241,7 +256,7 @@ if test "$sys1_compat" = "yes"; then
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo"
else
if test "$with_dfu" = "yes"; then
echo "Common binary can't support DFU loader, don't use --with-dfu."
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
exit 1
fi
# Override settings for common binary. Safer side.
@@ -252,7 +267,7 @@ else
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 */\n 0x\4, 0x\3, /* idProduct */%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]\)$% 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"
}
@@ -261,25 +276,25 @@ output_vendor_product_serial_strings () {
echo "static const uint8_t ${prefix}string_vendor[] = {"
echo " ${#VENDOR}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Manufacturer: \"$VENDOR\" */"
echo $VENDOR | sed -n -e "s/\(........\)/\1\n/gp" | 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 " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | 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
echo
echo "uint8_t ${prefix}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
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 '};'
@@ -287,16 +302,16 @@ output_vendor_product_serial_strings () {
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo "static const uint8_t ${prefix}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -n -e "s/\(........\)/\1\n/gp" | 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 " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo '#endif'
fi
@@ -311,8 +326,8 @@ if !(IFS=" "
fi
done; exit 1) < ../GNUK_USB_DEVICE_ID
then
echo "Please specify valid Vendor ID and Product ID."
echo "Check ../GNUK_USB_DEVICE_ID."
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Check ../GNUK_USB_DEVICE_ID." >&2
exit 1
fi

View File

@@ -50,7 +50,7 @@
* IMPLEMENTATION NOTE
*
* (0) We assume that the processor has no cache, nor branch target
* prediction. Thus, we don't avoid indexing by secret value.
* prediction. Thus, we don't avoid indexing by secret value.
* We don't avoid conditional jump if both cases have same timing,
* either.
*
@@ -235,7 +235,7 @@ point_add (ptc *X, const ptc *A, const ac *B)
* @param X Destination AC
* @param A PTC
*
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
*/
static void
point_ptc_to_ac (ac *X, const ptc *A)
@@ -258,195 +258,195 @@ point_ptc_to_ac (ac *X, const ptc *A)
static const ac precomputed_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
{ {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}} },
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
0xa815e038, 0xce0d0064, 0xbca90151, 0x041c030f }}},
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
0x655e5c16, 0xc67dc71c, 0xee43fb7a, 0x72467625 }}} },
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
0x6aeae260, 0x31f39299, 0x5f4a9bb2, 0x6d9e4545 }}},
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
0xa259dc8a, 0xaab95e0b, 0x99013cd0, 0x28bd5fc3 }}} },
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
0xda13ef4b, 0x4583ff4c, 0x95083f85, 0x1f13202c }}},
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
0xfdfd7ffa, 0xf21109e7, 0x6c381b7e, 0x66336d35 }}} },
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
0x1a52df87, 0x0de65625, 0xbd675870, 0x5f0dd494 }}},
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
0xa80e1eb6, 0x497e74bd, 0xe9365b15, 0x1648eaac }}} },
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
0xb34cf697, 0xb75832f4, 0x3a2bce94, 0x7aaf57c5 }}},
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
0x48742dd1, 0xaebd15dd, 0x55d38439, 0x6311bb16 }}} },
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
0x70611a3f, 0x91c1cd94, 0x8075dbcb, 0x1d0c34f6 }}},
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
0x46f167bb, 0x54b1992f, 0xb74a9944, 0x01a11f3c }}} },
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
0x2f6cc814, 0x359c5b5f, 0x7786383d, 0x7b6a5565 }}},
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
0xeddb8571, 0x61d526f6, 0x0eac739a, 0x0cb7acea }}} },
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
0x8397f958, 0x4870f214, 0x8a175fbb, 0x5aa0c67c }}},
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
0x7cbe4e3b, 0x87e293fa, 0xbda72395, 0x17040799 }}} },
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
0x2216fa67, 0x383a533a, 0x684d3925, 0x338bbe0a }}},
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
0x2e30380e, 0xa7c2e708, 0x9e4b3d62, 0x69f13e09 }}} },
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
0x9ebc7613, 0xb642f86a, 0xcb77c3b9, 0x5ce45e73 }}},
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
0xd8782345, 0x55c53916, 0xdb7b202a, 0x6b1dfa87 }}} },
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
0x3a6e8673, 0x0fcafd1d, 0x45d10f48, 0x0d264435 }}},
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
0xd2119aa4, 0x41d5b8eb, 0x8b09b6a5, 0x36bd9ab4 }}} },
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
0xa4730880, 0xefc0dd80, 0x4079fe2f, 0x40617e56 }}},
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
0xda13cdcb, 0xe315c425, 0x67ff5370, 0x37bc6e84 }}} },
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
0xf4085f62, 0x0f540498, 0x0db7bd1b, 0x6f0bb035 }}},
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
0x355facf6, 0x07f45010, 0x3a989a9c, 0x5cd416a9 }}} },
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
0x57aa0119, 0x44afdd5f, 0x430dc946, 0x05d68802 }}},
{{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33,
{{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33,
0x48c51347, 0x37520265, 0x00a21bfb, 0x6f4be0af }}} }
};
static const ac precomputed_2E_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16,
{ {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16,
0xedd4d15f, 0xab1c92b8, 0x57d9eada, 0x482a4cdf }}},
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
0x14519298, 0x0b3c5fc6, 0x81c2f7a8, 0x7391de43 }}} },
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
0x63e7328e, 0x44c6e34f, 0xca63ab3e, 0x3f748617 }}},
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
0x1ba9acee, 0x3938a289, 0x420fc47b, 0x0fed89e6 }}} },
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
0x9d128c33, 0xda44186c, 0xbf98c24f, 0x54183ede }}},
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
0xb4ab035d, 0xb3fe651b, 0xa0b0d4e5, 0x426c99c3 }}} },
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
0x24240b15, 0x18795ff8, 0x9989ffcc, 0x13aea184 }}},
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
0x1b25e570, 0xfbddbff2, 0x8ca12b70, 0x0884949c }}} },
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
0xeb17ad71, 0xb6719dfb, 0xc0bc3517, 0x46871ad0 }}},
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
0x884785dc, 0xad295dd0, 0x74a1276a, 0x359debad }}} },
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
0x9c969001, 0xef4c051e, 0x02cb45f4, 0x0d4ea946 }}},
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
0x2b372386, 0x5c12fd04, 0xdbfee11f, 0x1aedbd3e }}} },
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
0xa17dc97e, 0xeea9bddf, 0x3350a2bd, 0x0d12fe3d }}},
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
0x3dbbf921, 0x75c63df4, 0x2958a5a6, 0x545b109c }}} },
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
0x5985dcbe, 0x57a69c0f, 0xeb87a534, 0x3c0c1e7b }}},
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
0x6e2f1973, 0x922c4554, 0xf1347631, 0x74e826b2 }}} },
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
0x2c874953, 0xe298a02e, 0x8932b73f, 0x225093ed }}},
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
0x85dba986, 0xdf41da94, 0xccee8edc, 0x36fe85e7 }}} },
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
0x6a966d2d, 0x8242aa25, 0x4cd36d32, 0x03500a94 }}},
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
0x06eab6b4, 0xd0030f92, 0x62c91d46, 0x2dc80d5f }}} },
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
0x8159db27, 0x4591b980, 0xd3d84740, 0x36c6533c }}},
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
0x71b9dc16, 0xbd306903, 0xf88f8d32, 0x7edd5a95 }}} },
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
0x02b56105, 0x67c9d9d0, 0x5971b456, 0x4d318012 }}},
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
0x00607ea0, 0x4dbeaa6f, 0x6959e688, 0x115c221d }}} },
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
0xc2e9d5f4, 0xefa699bb, 0x021da209, 0x2469e813 }}},
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
0x2fb3ec8f, 0xd21b75e4, 0xd72a7545, 0x10dd726a }}} },
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
0x44f1161f, 0xbda6f3ee, 0xf339efe5, 0x7680aebf }}},
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
0xa320c916, 0xd81ef6f2, 0x62a3b54d, 0x3e22a1fb }}} },
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
0xea49af98, 0xc0a880b9, 0xf2dfddd0, 0x53bf600b }}},
{{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee,
{{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee,
0x2b9f233c, 0xb17712ae, 0xd0eb909e, 0x71f0b344 }}} }
};
static const ac precomputed_4E_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283,
{ {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283,
0xa9a6eb83, 0x2259174d, 0x45500054, 0x184b48cb }}},
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
0x2380ef73, 0xdd60c268, 0x03dc33a9, 0x3ee0e07a }}} },
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
0xecd898fb, 0xec57038c, 0xb663ed49, 0x2898ffaa }}},
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
0xb9934557, 0xe759d6bc, 0xab6c9477, 0x094f3b96 }}} },
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
0xda17203d, 0xa4850a2b, 0x77289e0f, 0x0062f7a7 }}},
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
0x475795f6, 0x9f38bda4, 0xdece4a4c, 0x560ed4b3 }}} },
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
0xdb08fe30, 0xd7a8d50d, 0xa2851109, 0x7efb45d3 }}},
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
0x9d71f8b7, 0x867091c6, 0x11a1bf56, 0x0fe1198b }}} },
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
0x0140502b, 0xad882043, 0x6ea1e46a, 0x34b5c0cb }}},
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
0xbd4801fb, 0x78b4d622, 0xcf18ae9a, 0x6cf4e146 }}} },
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
0x0205cf0e, 0x71908cc2, 0x32bcd754, 0x0cc15edd }}},
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
0x5e5a9312, 0xf22f64ef, 0x3c5e6155, 0x649b8859 }}} },
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
0x0df500ff, 0xe81faaa4, 0x6f50e615, 0x0792c79b }}},
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
0xc1d02d32, 0xdc57c526, 0x3c8aaa55, 0x5fb9a9a6 }}} },
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
0x446ac562, 0x1f8c510f, 0x2cc6b66e, 0x4676d381 }}},
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
0x457fa0eb, 0x051450a0, 0x744c57b1, 0x7d89e2b7 }}} },
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
0xf4d22d72, 0xd4c2f1a9, 0x4dc516b5, 0x73ecfdf1 }}},
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
0xa098cbb3, 0x9ba84f2e, 0xf9bdd37a, 0x1425aa8b }}} },
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
0xee26f5ff, 0x835dff85, 0xe509e1ea, 0x4927e622 }}},
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
0x682fd457, 0x9b87a676, 0x1a53145f, 0x75f382ff }}} },
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
0x9ccf2dc8, 0xf1c2b116, 0x808283d8, 0x7417e00f }}},
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
0x8f3d5d57, 0x231fc664, 0xe5853194, 0x38141a19 }}} },
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
0xe1dbdd65, 0x65d7f9b9, 0xf7c6698a, 0x7133424c }}},
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
0xb518e3eb, 0xa53e50e0, 0x98a40196, 0x2b4b9267 }}} },
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
0xcd2517af, 0x420cdef8, 0x0b695a8a, 0x513a307e }}},
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
0x973afe12, 0x8f3cbbea, 0x872f2538, 0x005c2350 }}} },
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
0x6e79d539, 0xc1f6d766, 0x795b5248, 0x34ec043f }}},
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
0x1666c1f1, 0xaeac7792, 0x66084bc0, 0x72426e97 }}} },
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
0x69e9b92b, 0xaf0984b4, 0x3ffe9093, 0x5fe6736f }}},
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
0x3c65a606, 0x94f893b1, 0x2d65496f, 0x2fee5e8c }}} }
};
@@ -586,7 +586,7 @@ bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size)
/**
* @brief R = A mod M (using M=2^252+C) (Barret reduction)
*
*
* See HAC 14.47.
*/
static void

View File

@@ -33,7 +33,7 @@
* References:
*
* [1] D. J. Bernstein. Curve25519: new Diffie-Hellman speed records.
* Proceedings of PKC 2006, to appear.
* Proceedings of PKC 2006, to appear.
* http://cr.yp.to/papers.html#curve25519. Date: 2006.02.09.
*
* [2] D. J. Bernstein. Can we avoid tests for zero in fast
@@ -46,7 +46,7 @@
* IMPLEMENTATION NOTE
*
* (0) We assume that the processor has no cache, nor branch target
* prediction. Thus, we don't avoid indexing by secret value.
* prediction. Thus, we don't avoid indexing by secret value.
* We don't avoid conditional jump if both cases have same timing,
* either.
*

View File

@@ -34,7 +34,7 @@
* Pages 250-265, Springer-Verlag London, UK, 2001
* ISBN:3-540-41898-9
*
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
* A comb method to render ECC resistant against Side Channel Attacks,
* 2004
*/

View File

@@ -338,7 +338,7 @@ uint8_t *
flash_key_alloc (enum kind_of_key kk)
{
uint8_t *k, *k0 = flash_key_getpage (kk);
int i;
int i;
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
/* Seek free space in the page. */

View File

@@ -22,19 +22,21 @@ 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 (void);
/* 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_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_RESET 16
/* OpenPGPcard thread */
#define EV_PINPAD_INPUT_DONE (1)
#define EV_EXIT (2)
#define EV_CMD_AVAILABLE (4)
#define EV_VERIFY_CMD_AVAILABLE (8)
#define EV_MODIFY_CMD_AVAILABLE (16)
#define EV_PINPAD_INPUT_DONE 1
#define EV_EXIT 2
#define EV_CMD_AVAILABLE 4
#define EV_VERIFY_CMD_AVAILABLE 8
#define EV_MODIFY_CMD_AVAILABLE 16
/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */
#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */
@@ -163,7 +165,6 @@ int flash_write_binary (uint8_t file_id, const uint8_t *data,
/* Linker set these two symbols */
extern uint8_t ch_certificate_start;
extern uint8_t random_bits_start;
#define FIRMWARE_UPDATE_KEY_CONTENT_LEN 256 /* RSA-2048 (p and q) */
@@ -417,12 +418,13 @@ void flash_do_write_internal (const uint8_t *p, int nr,
extern const uint8_t gnuk_string_serial[];
#define LED_ONESHOT (1)
#define LED_TWOSHOTS (2)
#define LED_SHOW_STATUS (4)
#define LED_START_COMMAND (8)
#define LED_FINISH_COMMAND (16)
#define LED_FATAL (32)
#define LED_ONESHOT 1
#define LED_TWOSHOTS 2
#define LED_SHOW_STATUS 4
#define LED_START_COMMAND 8
#define LED_FINISH_COMMAND 16
#define LED_FATAL 32
#define LED_GNUK_EXEC 64
void led_blink (int spec);
#if defined(PINPAD_SUPPORT)

View File

@@ -1,12 +1,12 @@
/*
* ST32F103 memory setup.
*/
__main_stack_size__ = 0x0100; /* Exception handlers */
__main_stack_size__ = 0x0080; /* Exception handlers */
__process0_stack_size__ = 0x0100; /* main */
__process1_stack_size__ = 0x0140; /* ccid */
__process2_stack_size__ = 0x0180; /* rng */
__process3_stack_size__ = 0x1600; /* gpg */
__process4_stack_size__ = 0x0100; /* intr: usb */
__process1_stack_size__ = 0x0180; /* ccid */
__process2_stack_size__ = 0x0160; /* 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 */

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013, 2015
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -37,85 +37,10 @@
#include "random.h"
#include "stm32f103.h"
#ifdef DEBUG
#include "debug.h"
struct stdout stdout;
static void
stdout_init (void)
{
chopstx_mutex_init (&stdout.m);
chopstx_mutex_init (&stdout.m_dev);
chopstx_cond_init (&stdout.cond_dev);
stdout.connected = 0;
}
void
_write (const char *s, int len)
{
int packet_len;
if (len == 0)
return;
chopstx_mutex_lock (&stdout.m);
chopstx_mutex_lock (&stdout.m_dev);
if (!stdout.connected)
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
do
{
packet_len =
(len < VIRTUAL_COM_PORT_DATA_SIZE) ? len : VIRTUAL_COM_PORT_DATA_SIZE;
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_write (ENDP3, s, packet_len);
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
s += packet_len;
len -= packet_len;
}
/* Send a Zero-Length-Packet if the last packet is full size. */
while (len != 0 || packet_len == VIRTUAL_COM_PORT_DATA_SIZE);
chopstx_mutex_unlock (&stdout.m);
}
void
EP3_IN_Callback (void)
{
chopstx_mutex_lock (&stdout.m_dev);
chopstx_cond_signal (&stdout.cond_dev);
chopstx_mutex_unlock (&stdout.m_dev);
}
void
EP5_OUT_Callback (void)
{
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_rx_enable (ENDP5);
chopstx_mutex_unlock (&stdout.m_dev);
}
#else
void
_write (const char *s, int size)
{
(void)s;
(void)size;
}
#endif
extern void *USBthread (void *arg);
/*
* main thread does 1-bit LED display output
*/
#define MAIN_TIMEOUT_INTERVAL (5000*1000)
#define LED_TIMEOUT_INTERVAL (75*1000)
#define LED_TIMEOUT_ZERO (25*1000)
#define LED_TIMEOUT_ONE (100*1000)
@@ -195,64 +120,38 @@ static void display_fatal_code (void)
static uint8_t led_inverted;
static eventmask_t emit_led (int on_time, int off_time)
static void emit_led (int on_time, int off_time)
{
eventmask_t m;
set_led (!led_inverted);
m = eventflag_wait_timeout (&led_event, on_time);
chopstx_usec_wait (on_time);
set_led (led_inverted);
if (m) return m;
if ((m = eventflag_wait_timeout (&led_event, off_time)))
return m;
return 0;
chopstx_usec_wait (off_time);
}
static eventmask_t display_status_code (void)
static void display_status_code (void)
{
enum icc_state icc_state;
eventmask_t m;
if (icc_state_p == NULL)
icc_state = ICC_STATE_START;
else
icc_state = *icc_state_p;
enum icc_state icc_state = *icc_state_p;
if (icc_state == ICC_STATE_START)
return emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
else
/* OpenPGP card thread running */
/* OpenPGP card thread is running */
{
if ((m = emit_led ((auth_status & AC_ADMIN_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led ((auth_status & AC_OTHER_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led ((auth_status & AC_PSO_CDS_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
emit_led ((auth_status & AC_ADMIN_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
emit_led ((auth_status & AC_OTHER_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
emit_led ((auth_status & AC_PSO_CDS_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
if (icc_state == ICC_STATE_WAIT)
{
if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP * 2)))
return m;
}
chopstx_usec_wait (LED_TIMEOUT_STOP * 2);
else
{
if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led (icc_state == ICC_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_STOP)))
return m;
chopstx_usec_wait (LED_TIMEOUT_INTERVAL);
emit_led (icc_state == ICC_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
}
return 0;
}
}
@@ -280,19 +179,13 @@ calculate_regnual_entry_address (const uint8_t *addr)
}
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process4_stack_base__, __process4_stack_size__;
const uint32_t __stackaddr_ccid = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_ccid = (size_t)&__process1_stack_size__;
const uint32_t __stackaddr_usb = (uint32_t)&__process4_stack_base__;
const size_t __stacksize_usb = (size_t)&__process4_stack_size__;
#define PRIO_CCID 3
#define PRIO_USB 4
#define PRIO_MAIN 5
#define PRIO_MAIN 5
extern void *usb_intr (void *arg);
extern void *ccid_thread (void *arg);
static void gnuk_malloc_init (void);
@@ -301,16 +194,11 @@ extern uint32_t bDeviceState;
/*
* Entry point.
*
* NOTE: the main function is already a thread in the system on entry.
* See the hwinit1_common function.
*/
int
main (int argc, char *argv[])
{
unsigned int count = 0;
uint32_t entry;
chopstx_t usb_thd;
chopstx_t ccid_thd;
(void)argc;
@@ -323,7 +211,7 @@ main (int argc, char *argv[])
adc_init ();
eventflag_init (&led_event, chopstx_main);
eventflag_init (&led_event);
random_init ();
@@ -331,8 +219,8 @@ main (int argc, char *argv[])
stdout_init ();
#endif
ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid,
__stacksize_ccid, USBthread, NULL);
ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid, __stacksize_ccid,
ccid_thread, NULL);
#ifdef PINPAD_CIR_SUPPORT
cir_init ();
@@ -341,10 +229,7 @@ main (int argc, char *argv[])
msc_init ();
#endif
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
usb_intr, NULL);
chopstx_main_init (PRIO_MAIN);
chopstx_setpriority (PRIO_MAIN);
while (1)
{
@@ -358,56 +243,40 @@ main (int argc, char *argv[])
{
eventmask_t m;
if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED)
break;
m = eventflag_wait_timeout (&led_event, MAIN_TIMEOUT_INTERVAL);
got_it:
count++;
m = eventflag_wait (&led_event);
switch (m)
{
case LED_ONESHOT:
if ((m = emit_led (100*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it;
emit_led (100*1000, LED_TIMEOUT_STOP);
break;
case LED_TWOSHOTS:
if ((m = emit_led (50*1000, 50*1000))) goto got_it;
if ((m = emit_led (50*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it;
emit_led (50*1000, 50*1000);
emit_led (50*1000, LED_TIMEOUT_STOP);
break;
case LED_SHOW_STATUS:
if ((count & 0x07) != 0) continue; /* Display once for eight times */
if ((m = display_status_code ())) goto got_it;
display_status_code ();
break;
case LED_START_COMMAND:
set_led (1);
led_inverted = 1;
chopstx_usec_wait (LED_TIMEOUT_STOP);
break;
case LED_FINISH_COMMAND:
m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP);
led_inverted = 0;
set_led (0);
if (m)
goto got_it;
break;
case LED_FATAL:
display_fatal_code ();
break;
case LED_GNUK_EXEC:
goto exec;
default:
if ((m = emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP)))
goto got_it;
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
break;
}
#ifdef DEBUG_MORE
if (stdout.connected && (count % 10) == 0)
{
DEBUG_SHORT (count / 10);
_write ("\r\nThis is Gnuk on STM32F103.\r\n"
"Testing USB driver.\n\n"
"Hello world\r\n\r\n", 30+21+15);
}
#endif
}
exec:
random_fini ();
set_led (1);
@@ -416,9 +285,6 @@ main (int argc, char *argv[])
/* Finish application. */
chopstx_join (ccid_thd, NULL);
chopstx_cancel (usb_thd);
chopstx_join (usb_thd, NULL);
/* Set vector */
SCB->VTOR = (uint32_t)&_regnual_start;
entry = calculate_regnual_entry_address (&_regnual_start);
@@ -460,6 +326,8 @@ main (int argc, char *argv[])
void
fatal (uint8_t code)
{
extern void _write (const char *s, int len);
fatal_code = code;
eventflag_signal (&led_event, LED_FATAL);
_write ("fatal\r\n", 7);

View File

@@ -27,7 +27,7 @@
/**
* @brief X = A mod B (using MU=(1<<(256)+MU_lower)) (Barret reduction)
*
*
*/
void
mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
@@ -145,7 +145,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
/**
* @brief C = X^(-1) mod N
*
*
* Assume X and N are co-prime (or N is prime).
* NOTE: If X==0, it return 0.
*

View File

@@ -1,7 +1,7 @@
/*
* modp256k1.c -- modulo arithmetic for p256k1
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Copyright (C) 2014, 2016 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -55,12 +55,12 @@ const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff,
/*
* Implementation Note.
*
* It's not always modulo p256k1. The representation is redundant
* during computation. For example, when we add the prime - 1 and 1,
* it won't overflow to 2^256, and the result is represented within
* 256-bit.
* It's always modulo p256k1.
*
* Once, I tried redundant representation which caused wrong
* calculation. Implementation could be correct with redundant
* representation, but it found that it's more expensive.
*
* It is guaranteed that modp256k1_reduce reduces to modulo p256k1.
*/
/**
@@ -69,14 +69,16 @@ const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff,
void
modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t carry;
uint32_t cond;
bn256 tmp[1];
carry = bn256_add (X, A, B);
if (carry)
bn256_sub (X, X, P256K1);
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256K1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
bn256_sub (tmp, X, P256K1);
memcpy (X, tmp, sizeof (bn256));
}
/**
@@ -89,10 +91,11 @@ modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B)
bn256 tmp[1];
borrow = bn256_sub (X, A, B);
bn256_add (tmp, X, P256K1);
if (borrow)
bn256_add (X, X, P256K1);
memcpy (X, tmp, sizeof (bn256));
else
bn256_add (tmp, X, P256K1);
memcpy (tmp, tmp, sizeof (bn256));
}
/**
@@ -181,12 +184,12 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
*/
S->word[7] = S->word[6] = S->word[5] = S->word[4] = S->word[3] = 0;
/* (S02, S01, S00) = (S1, S0) + (S1, S0)*2^32 */
/* (S02, S01, S00) = (S1, S0) + (S1, S0)*2^32 */
s00 = s0;
s01 = s0 + s1;
s02 = s1 + ((s01 < s0)? 1 : 0);
/* (S02, S01, S00) += (S1, S0)*2^9 */
/* (S02, S01, S00) += (S1, S0)*2^9 */
carry = (s0 >> 23) + s01;
s02 += (s1 >> 23) + ((carry < s01)? 1 : 0);
s01 = (s1 << 9) + carry;
@@ -196,7 +199,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
s01 += carry;
s02 += ((s01 < carry)? 1 : 0);
/* (S02, S01, S00) += (S1, S0)*2^8 */
/* (S02, S01, S00) += (S1, S0)*2^8 */
carry = (s0 >> 24) + s01;
s02 += (s1 >> 24) + ((carry < s01)? 1 : 0);
s01 = (s1 << 8) + carry;
@@ -206,7 +209,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
s01 += carry;
s02 += ((s01 < carry)? 1 : 0);
/* (S02, S01, S00) += (S1, S0)*2^7 */
/* (S02, S01, S00) += (S1, S0)*2^7 */
carry = (s0 >> 25) + s01;
s02 += (s1 >> 25) + ((carry < s01)? 1 : 0);
s01 = (s1 << 7) + carry;
@@ -216,7 +219,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
s01 += carry;
s02 += ((s01 < carry)? 1 : 0);
/* (S02, S01, S00) += (S1, S0)*2^6 */
/* (S02, S01, S00) += (S1, S0)*2^6 */
carry = (s0 >> 26) + s01;
s02 += (s1 >> 26) + ((carry < s01)? 1 : 0);
s01 = (s1 << 6) + carry;
@@ -226,7 +229,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
s01 += carry;
s02 += ((s01 < carry)? 1 : 0);
/* (S02, S01, S00) += (S1, S0)*2^4 */
/* (S02, S01, S00) += (S1, S0)*2^4 */
carry = (s0 >> 28) + s01;
s02 += (s1 >> 28) + ((carry < s01)? 1 : 0);
s01 = (s1 << 4) + carry;

View File

@@ -1,7 +1,8 @@
/*
* modp256r1.c -- modulo arithmetic for p256r1
*
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
* Copyright (C) 2011, 2013, 2014, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -49,12 +50,12 @@ const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
/*
* Implementation Note.
*
* It's not always modulo p256r1. The representation is redundant
* during computation. For example, when we add the prime - 1 and 1,
* it won't overflow to 2^256, and the result is represented within
* 256-bit.
* It's always modulo p256r1.
*
* Once, I tried redundant representation which caused wrong
* calculation. Implementation could be correct with redundant
* representation, but it found that it's more expensive.
*
* It is guaranteed that modp256r1_reduce reduces to modulo p256r1.
*/
/**
@@ -63,14 +64,16 @@ const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
void
modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t carry;
uint32_t cond;
bn256 tmp[1];
carry = bn256_add (X, A, B);
if (carry)
bn256_sub (X, X, P256R1);
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256R1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
bn256_sub (tmp, X, P256R1);
memcpy (X, tmp, sizeof (bn256));
}
/**
@@ -83,10 +86,11 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
bn256 tmp[1];
borrow = bn256_sub (X, A, B);
bn256_add (tmp, X, P256R1);
if (borrow)
bn256_add (X, X, P256R1);
memcpy (X, tmp, sizeof (bn256));
else
bn256_add (tmp, X, P256R1);
memcpy (tmp, tmp, sizeof (bn256));
}
/**
@@ -95,7 +99,7 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
void
modp256r1_reduce (bn256 *X, const bn512 *A)
{
bn256 tmp[1];
bn256 tmp[1], tmp0[1];
uint32_t borrow;
#define S1 X
@@ -116,6 +120,11 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S1->word[2] = A->word[2];
S1->word[1] = A->word[1];
S1->word[0] = A->word[0];
borrow = bn256_sub (tmp0, S1, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S1, tmp0, sizeof (bn256));
/* X = S1 */
S2->word[7] = A->word[15];
@@ -155,6 +164,11 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S5->word[2] = A->word[11];
S5->word[1] = A->word[10];
S5->word[0] = A->word[9];
borrow = bn256_sub (tmp0, S5, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S5, tmp0, sizeof (bn256));
/* X += S5 */
modp256r1_add (X, X, S5);
@@ -164,6 +178,11 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S6->word[2] = A->word[13];
S6->word[1] = A->word[12];
S6->word[0] = A->word[11];
borrow = bn256_sub (tmp0, S6, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S6, tmp0, sizeof (bn256));
/* X -= S6 */
modp256r1_sub (X, X, S6);
@@ -174,6 +193,11 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
S7->word[2] = A->word[14];
S7->word[1] = A->word[13];
S7->word[0] = A->word[12];
borrow = bn256_sub (tmp0, S7, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S7, tmp0, sizeof (bn256));
/* X -= S7 */
modp256r1_sub (X, X, S7);

View File

@@ -582,8 +582,8 @@ rng (void *arg)
chopstx_cond_init (&mode_cond);
/* Enable ADCs */
adc_start ();
chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
adc_start ();
ep_init (mode);
while (!rng_should_terminate)
@@ -641,7 +641,6 @@ rng (void *arg)
}
adc_stop ();
chopstx_release_irq (&adc_intr);
return NULL;
}

View File

@@ -201,7 +201,7 @@ gpg_get_pw1_lifetime (void)
/*
* Representation of algorithm attributes:
* 0: ALGO_ATTR_<>_P == NULL : RSA-2048
* N: ALGO_ATTR_<>_P != NULL :
* N: ALGO_ATTR_<>_P != NULL :
*
*/
static const uint8_t *algo_attr_sig_p;
@@ -489,11 +489,13 @@ static int
do_hist_bytes (uint16_t tag, int with_tag)
{
/*
* Currently, we support no life cycle management.
* In case of Gnuk, user could flash the MCU, instead.
* Thus, just return the template as is.
* Currently, we support no life cycle management. In case of Gnuk,
* user could flash the MCU with SWD/JTAG, instead. It is also
* possible for user to do firmware upgrade through USB.
*
* In future (when Gnuk will be onn the real smartcard),
* Thus, here, it just returns the template as is.
*
* In future (when Gnuk will be on the real smartcard),
* we can support life cycle management by implementing
* TERMINATE DF / ACTIVATE FILE and fix code around here.
*/
@@ -629,16 +631,19 @@ do_openpgpcard_aid (uint16_t tag, int with_tag)
if (vid == 0xffff || vid == 0x0000)
{
const uint8_t *u = unique_device_id ();
const uint8_t *u = unique_device_id () + 8;
memcpy (res_p, openpgpcard_aid, 8);
res_p += 8;
/* vid == 0xfffe: serial number is random byte */
/* vid == 0xfffe: serial number is four random bytes */
*res_p++ = 0xff;
*res_p++ = 0xfe;
memcpy (res_p, u, 4);
res_p += 4;
*res_p++ = u[3];
*res_p++ = u[2];
*res_p++ = u[1];
*res_p++ = u[0];
}
else
{
@@ -753,7 +758,7 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
algo = ALGO_CURVE25519;
if (algo < 0)
return 0; /* Error */
return 0; /* Error. */
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
@@ -761,7 +766,8 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
if (*algo_attr_pp != NULL)
return 0;
}
else if (*algo_attr_pp == NULL || (*algo_attr_pp)[1] != algo)
else if ((algo != ALGO_RSA2K && *algo_attr_pp == NULL)
|| (*algo_attr_pp)[1] != algo)
{
gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
@@ -1383,7 +1389,7 @@ proc_key_import (const uint8_t *data, int len)
uint8_t hash[64];
if (len - 12 != 32)
return 1; /* Error. */
return 0; /* Error. */
sha512 (&data[12], 32, hash);
hash[0] &= 248;
@@ -1397,7 +1403,7 @@ proc_key_import (const uint8_t *data, int len)
int i;
if (len - 12 != 32)
return 1; /* Error. */
return 0; /* Error. */
for (i = 0; i < 32; i++)
priv[31-i] = data[12+i];
@@ -2092,10 +2098,10 @@ gpg_do_keygen (uint8_t kk_byte)
for (i = 0; i < 32; i++)
d[32 - i - 1] = p[i];
random_bytes_free (rnd);
random_bytes_free (rnd);
prv = d;
pubkey = NULL;
pubkey = NULL;
}
else if (attr == ALGO_ED25519)
{
@@ -2106,7 +2112,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
pubkey = NULL;
}
else if (attr == ALGO_CURVE25519)
{
@@ -2117,7 +2123,7 @@ gpg_do_keygen (uint8_t kk_byte)
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
pubkey = NULL;
}
else
{

View File

@@ -1,7 +1,7 @@
/*
* openpgp.c -- OpenPGP card protocol support
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -138,6 +138,7 @@ static void
cmd_verify (void)
{
int len;
uint8_t p1 = P1 (apdu);
uint8_t p2 = P2 (apdu);
int r;
const uint8_t *pw;
@@ -149,22 +150,36 @@ cmd_verify (void)
pw = apdu.cmd_apdu_data;
if (len == 0)
{ /* This is to examine status. */
if (p2 == 0x81)
r = ac_check_status (AC_PSO_CDS_AUTHORIZED);
else if (p2 == 0x82)
r = ac_check_status (AC_OTHER_AUTHORIZED);
else
r = ac_check_status (AC_ADMIN_AUTHORIZED);
{
if (p1 == 0)
{ /* This is to examine status. */
if (p2 == 0x81)
r = ac_check_status (AC_PSO_CDS_AUTHORIZED);
else if (p2 == 0x82)
r = ac_check_status (AC_OTHER_AUTHORIZED);
else
r = ac_check_status (AC_ADMIN_AUTHORIZED);
if (r)
GPG_SUCCESS (); /* If authentication done already, return success. */
else
{ /* If not, return retry counter, encoded. */
r = gpg_pw_get_retry_counter (p2);
set_res_sw (0x63, 0xc0 | (r&0x0f));
if (r)
GPG_SUCCESS (); /* If authentication done already, return success. */
else
{ /* If not, return retry counter, encoded. */
r = gpg_pw_get_retry_counter (p2);
set_res_sw (0x63, 0xc0 | (r&0x0f));
}
}
else if (p1 == 0xff)
{ /* Reset the status. */
if (p2 == 0x81)
ac_reset_pso_cds ();
else if (p2 == 0x82)
ac_reset_other ();
else
ac_reset_admin ();
GPG_SUCCESS ();
}
else
GPG_BAD_P1_P2 ();
return;
}
@@ -437,9 +452,12 @@ s2k (const unsigned char *salt, size_t slen,
{
sha256_context ctx;
size_t count = S2KCOUNT;
const uint8_t *unique = unique_device_id ();
sha256_start (&ctx);
sha256_update (&ctx, unique, 12);
while (count > slen + ilen)
{
if (slen)
@@ -817,6 +835,7 @@ cmd_pso (void)
int attr;
int pubkey_len;
unsigned int result_len = 0;
int cs;
DEBUG_INFO (" - PSO: ");
DEBUG_WORD ((uint32_t)&r);
@@ -867,6 +886,7 @@ cmd_pso (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = ECDSA_SIGNATURE_LENGTH;
if (attr == ALGO_NISTP256R1)
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
@@ -874,6 +894,7 @@ cmd_pso (void)
else /* ALGO_SECP256K1 */
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
kd[GPG_KEY_FOR_SIGNING].data);
chopstx_setcancelstate (cs);
}
else if (attr == ALGO_ED25519)
{
@@ -886,11 +907,13 @@ cmd_pso (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = EDDSA_SIGNATURE_LENGTH;
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
kd[GPG_KEY_FOR_SIGNING].data,
kd[GPG_KEY_FOR_SIGNING].data+32,
kd[GPG_KEY_FOR_SIGNING].pubkey);
chopstx_setcancelstate (cs);
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
}
else
@@ -947,6 +970,7 @@ cmd_pso (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = 65;
if (attr == ALGO_NISTP256R1)
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header, res_APDU,
@@ -954,6 +978,7 @@ cmd_pso (void)
else
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header, res_APDU,
kd[GPG_KEY_FOR_DECRYPTION].data);
chopstx_setcancelstate (cs);
}
else if (attr == ALGO_CURVE25519)
{
@@ -965,9 +990,11 @@ cmd_pso (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = 32;
r = ecdh_decrypt_curve25519 (apdu.cmd_apdu_data + header, res_APDU,
kd[GPG_KEY_FOR_DECRYPTION].data);
chopstx_setcancelstate (cs);
}
else
{
@@ -1003,6 +1030,7 @@ cmd_internal_authenticate (void)
int len = apdu.cmd_apdu_data_len;
int r = -1;
unsigned int result_len = 0;
int cs;
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
@@ -1036,7 +1064,7 @@ cmd_internal_authenticate (void)
result_len = pubkey_len;
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
&kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
}
}
else if (attr == ALGO_NISTP256R1)
{
if (len != ECDSA_HASH_LEN)
@@ -1046,9 +1074,11 @@ cmd_internal_authenticate (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = ECDSA_SIGNATURE_LENGTH;
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
kd[GPG_KEY_FOR_AUTHENTICATION].data);
chopstx_setcancelstate (cs);
}
else if (attr == ALGO_SECP256K1)
{
@@ -1059,9 +1089,11 @@ cmd_internal_authenticate (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = ECDSA_SIGNATURE_LENGTH;
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
kd[GPG_KEY_FOR_AUTHENTICATION].data);
chopstx_setcancelstate (cs);
}
else if (attr == ALGO_ED25519)
{
@@ -1074,11 +1106,13 @@ cmd_internal_authenticate (void)
return;
}
cs = chopstx_setcancelstate (0);
result_len = EDDSA_SIGNATURE_LENGTH;
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
kd[GPG_KEY_FOR_AUTHENTICATION].data,
kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
chopstx_setcancelstate (cs);
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
}
@@ -1322,7 +1356,11 @@ process_command_apdu (void)
break;
if (i < NUM_CMDS)
cmds[i].cmd_handler ();
{
chopstx_setcancelstate (1);
cmds[i].cmd_handler ();
chopstx_setcancelstate (0);
}
else
{
DEBUG_INFO (" - ??");
@@ -1355,10 +1393,10 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
while (1)
{
eventmask_t m = eventflag_wait (openpgp_comm);
#if defined(PINPAD_SUPPORT)
int len, pw_len, newpw_len;
#endif
eventmask_t m = eventflag_wait (openpgp_comm);
DEBUG_INFO ("GPG!: ");
@@ -1387,7 +1425,7 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
else if (m == EV_MODIFY_CMD_AVAILABLE)
{
#if defined(PINPAD_SUPPORT)
uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
uint8_t bConfirmPIN = apdu.cmd_apdu_data[0];
uint8_t *p = apdu.cmd_apdu_data;
if (INS (apdu) != INS_CHANGE_REFERENCE_DATA

View File

@@ -1044,7 +1044,7 @@ cir_init (void)
TIMx->PSC = 72 - 1; /* 1 MHz */
TIMx->ARR = 18000; /* 18 ms */
/* Generate UEV to upload PSC and ARR */
TIMx->EGR = TIM_EGR_UG;
TIMx->EGR = TIM_EGR_UG;
chopstx_create (PRIO_TIM, __stackaddr_tim, __stacksize_tim, tim_main, NULL);
chopstx_create (PRIO_EXT, __stackaddr_ext, __stacksize_ext, ext_main, NULL);

View File

@@ -1,7 +1,7 @@
/*
* sha512.c -- Compute SHA-512 hash (for little endian architecture).
*
* This module is written by gniibe, following the API of sha256.c.
* This module is written by gniibe, following the API of sha256.c.
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>

View File

@@ -1,7 +1,7 @@
/*
* sys.c - system routines for the initial page for STM32F103.
*
* Copyright (C) 2013, 2014, 2015 Flying Stone Technology
* Copyright (C) 2013, 2014, 2015, 2016 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* Copying and distribution of this file, with or without modification,
@@ -17,41 +17,8 @@
#include <stdlib.h>
#include "board.h"
#include "clk_gpio_init.c"
#include "clk_gpio_init-stm32.c"
#define CORTEX_PRIORITY_BITS 4
#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
#define USB_LP_CAN1_RX0_IRQn 20
#define STM32_USB_IRQ_PRIORITY 11
struct NVIC {
uint32_t ISER[8];
uint32_t unused1[24];
uint32_t ICER[8];
uint32_t unused2[24];
uint32_t ISPR[8];
uint32_t unused3[24];
uint32_t ICPR[8];
uint32_t unused4[24];
uint32_t IABR[8];
uint32_t unused5[56];
uint32_t IPR[60];
};
static struct NVIC *const NVICBase = ((struct NVIC *const)0xE000E100);
#define NVIC_ISER(n) (NVICBase->ISER[n >> 5])
#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5])
#define NVIC_IPR(n) (NVICBase->IPR[n >> 2])
static void
nvic_enable_vector (uint32_t n, uint32_t prio)
{
unsigned int sh = (n & 3) << 3;
NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (prio << sh);
NVIC_ICPR (n) = 1 << (n & 0x1F);
NVIC_ISER (n) = 1 << (n & 0x1F);
}
static void
usb_cable_config (int enable)
@@ -118,13 +85,6 @@ usb_lld_sys_init (void)
usb_cable_config (1);
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
nvic_enable_vector (USB_LP_CAN1_RX0_IRQn,
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
/*
* Note that we also have other IRQ(s):
* USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
* USBWakeUp_IRQn (suspend/resume)
*/
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB1RSTR = 0;
}
@@ -423,8 +383,8 @@ handler vector[] __attribute__ ((section(".vectors"))) = {
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
3*2+2, /* bLength */
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
/* sys version: "2.1" */
'2', 0, '.', 0, '1', 0,
/* sys version: "3.0" */
'3', 0, '.', 0, '0', 0,
};
const uint32_t __attribute__((section(".sys.board_id")))

View File

@@ -7,6 +7,9 @@
#define BOARD_ID_STBEE 0x945c37e8
#define BOARD_ID_STM32_PRIMER2 0x21e5798d
#define BOARD_ID_STM8S_DISCOVERY 0x2f0976bb
#define BOARD_ID_ST_DONGLE 0x2cd4e471
#define BOARD_ID_ST_NUCLEO_F103 0x9b87c16d
#define BOARD_ID_NITROKEY_START 0xad1e7ebd
extern const uint8_t sys_version[8];
extern const uint32_t sys_board_id;

View File

@@ -1,7 +1,7 @@
/*
* usb-icc.c -- USB CCID protocol handling
* usb-ccid.c -- USB CCID protocol handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -29,8 +29,14 @@
#include "config.h"
#ifdef DEBUG
#include "debug.h"
struct stdout stdout;
#endif
#include "gnuk.h"
#include "usb_lld.h"
#include "usb_conf.h"
/*
* USB buffer size of USB-CCID driver
@@ -179,8 +185,6 @@ struct icc_header {
} __attribute__((packed));
enum icc_state *icc_state_p;
/* Data structure handled by CCID layer */
struct ccid {
enum icc_state icc_state;
@@ -250,24 +254,19 @@ static void ccid_reset (struct ccid *c)
}
static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo,
struct apdu *a, chopstx_t thd)
struct apdu *a)
{
icc_state_p = &c->icc_state;
c->icc_state = ICC_STATE_NOCARD;
c->state = APDU_STATE_WAIT_COMMAND;
/*
* Note: a is not yet initialized yet, we can't use c->a->cmd_apdu_data here.
*/
c->p = &icc_buffer[5];
c->p = a->cmd_apdu_data;
c->len = MAX_CMD_APDU_DATA_SIZE;
c->err = 0;
memset (&c->icc_header, 0, sizeof (struct icc_header));
c->sw1sw2[0] = 0x90;
c->sw1sw2[1] = 0x00;
eventflag_init (&c->ccid_comm, thd);
c->application = 0;
eventflag_init (&c->openpgp_comm, 0);
c->epi = epi;
c->epo = epo;
c->a = a;
@@ -358,7 +357,7 @@ static void get_sw1sw2 (struct ep_in *epi, size_t len)
/*
* Tx done callback
*/
void
static void
EP1_IN_Callback (void)
{
struct ep_in *epi = &endpoint_in;
@@ -635,7 +634,7 @@ icc_prepare_receive (struct ccid *c)
* Rx ready callback
*/
void
static void
EP1_OUT_Callback (void)
{
struct ep_out *epo = &endpoint_out;
@@ -676,6 +675,46 @@ EP1_OUT_Callback (void)
}
extern void EP6_IN_Callback (void);
void
usb_cb_rx_ready (uint8_t ep_num)
{
if (ep_num == ENDP1)
EP1_OUT_Callback ();
#ifdef DEBUG
else if (ep_num == ENDP5)
{
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_rx_enable (ep_num);
chopstx_mutex_unlock (&stdout.m_dev);
}
#endif
}
void
usb_cb_tx_done (uint8_t ep_num)
{
if (ep_num == ENDP1)
EP1_IN_Callback ();
else if (ep_num == ENDP2)
{
/* INTERRUPT Transfer done */
}
#ifdef DEBUG
else if (ep_num == ENDP3)
{
chopstx_mutex_lock (&stdout.m_dev);
chopstx_cond_signal (&stdout.cond_dev);
chopstx_mutex_unlock (&stdout.m_dev);
}
#endif
#ifdef PINPAD_SUPPORT
else if (ep_num == ENDP6)
EP6_IN_Callback ();
#endif
}
/*
* ATR (Answer To Reset) string
*
@@ -748,7 +787,7 @@ const size_t __stacksize_gpg = (size_t)&__process3_stack_size__;
/* Send back ATR (Answer To Reset) */
enum icc_state
static enum icc_state
icc_power_on (struct ccid *c)
{
size_t size_atr = sizeof (ATR);
@@ -814,7 +853,7 @@ icc_send_status (struct ccid *c)
#endif
}
enum icc_state
static enum icc_state
icc_power_off (struct ccid *c)
{
if (c->application)
@@ -1290,41 +1329,17 @@ icc_handle_timeout (struct ccid *c)
{
case ICC_STATE_EXECUTE:
icc_send_data_block_time_extension (c);
led_blink (LED_ONESHOT);
break;
default:
break;
}
led_blink (LED_ONESHOT);
return next_state;
}
static struct ccid ccid;
/*
* Another Tx done callback
*/
void
EP2_IN_Callback (void)
{
}
#define USB_ICC_TIMEOUT (1950*1000)
#define GPG_THREAD_TERMINATED 0xffff
static void *ccid_thread (chopstx_t) __attribute__ ((noinline));
void * __attribute__ ((naked))
USBthread (void *arg)
{
chopstx_t thd;
(void)arg;
asm ("mov %0, sp" : "=r" (thd));
return ccid_thread (thd);
}
enum icc_state *icc_state_p = &ccid.icc_state;
void
ccid_card_change_signal (int how)
@@ -1337,34 +1352,82 @@ ccid_card_change_signal (int how)
eventflag_signal (&c->ccid_comm, EV_CARD_CHANGE);
}
void
ccid_usb_reset (void)
{
struct ccid *c = &ccid;
eventflag_signal (&c->ccid_comm, EV_USB_RESET);
}
#define USB_ICC_TIMEOUT (1950*1000)
#define GPG_THREAD_TERMINATED 0xffff
#define NOTIFY_SLOT_CHANGE 0x50
static void * __attribute__ ((noinline))
ccid_thread (chopstx_t thd)
#define INTR_REQ_USB 20
void *
ccid_thread (void *arg)
{
extern uint32_t bDeviceState;
chopstx_intr_t interrupt;
uint32_t timeout;
struct ep_in *epi = &endpoint_in;
struct ep_out *epo = &endpoint_out;
struct ccid *c = &ccid;
struct apdu *a = &apdu;
uint8_t int_msg[2];
int_msg[0] = NOTIFY_SLOT_CHANGE;
(void)arg;
eventflag_init (&ccid.ccid_comm);
eventflag_init (&ccid.openpgp_comm);
usb_lld_init (USB_INITIAL_FEATURE);
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
usb_interrupt_handler (); /* For old SYS < 3.0 */
reset:
epi_init (epi, ENDP1, notify_tx, c);
epo_init (epo, ENDP1, notify_icc, c);
ccid_init (c, epi, epo, a, thd);
apdu_init (a);
ccid_init (c, epi, epo, a);
timeout = USB_ICC_TIMEOUT;
icc_prepare_receive (c);
while (1)
{
eventmask_t m;
chopstx_poll_cond_t poll_desc;
m = eventflag_wait_timeout (&c->ccid_comm, USB_ICC_TIMEOUT);
if (m == EV_CARD_CHANGE)
eventflag_prepare_poll (&c->ccid_comm, &poll_desc);
chopstx_poll (&timeout, 2, &interrupt, &poll_desc);
if (interrupt.ready)
{
usb_interrupt_handler ();
continue;
}
timeout = USB_ICC_TIMEOUT;
m = eventflag_get (&c->ccid_comm);
if (m == EV_USB_RESET)
{
if (c->application)
{
chopstx_cancel (c->application);
chopstx_join (c->application, NULL);
c->application = 0;
}
goto reset;
}
else if (m == EV_CARD_CHANGE)
{
uint8_t int_msg[2];
int_msg[0] = NOTIFY_SLOT_CHANGE;
if (c->icc_state == ICC_STATE_NOCARD)
{ /* Inserted! */
c->icc_state = ICC_STATE_START;
@@ -1451,5 +1514,66 @@ ccid_thread (chopstx_t thd)
c->application = 0;
}
/* Loading reGNUal. */
while (bDeviceState != UNCONNECTED)
{
chopstx_poll (NULL, 1, &interrupt);
usb_interrupt_handler ();
}
return NULL;
}
#ifdef DEBUG
static void
stdout_init (void)
{
chopstx_mutex_init (&stdout.m);
chopstx_mutex_init (&stdout.m_dev);
chopstx_cond_init (&stdout.cond_dev);
stdout.connected = 0;
}
void
_write (const char *s, int len)
{
int packet_len;
if (len == 0)
return;
chopstx_mutex_lock (&stdout.m);
chopstx_mutex_lock (&stdout.m_dev);
if (!stdout.connected)
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
do
{
packet_len =
(len < VIRTUAL_COM_PORT_DATA_SIZE) ? len : VIRTUAL_COM_PORT_DATA_SIZE;
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_write (ENDP3, s, packet_len);
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
s += packet_len;
len -= packet_len;
}
/* Send a Zero-Length-Packet if the last packet is full size. */
while (len != 0 || packet_len == VIRTUAL_COM_PORT_DATA_SIZE);
chopstx_mutex_unlock (&stdout.m);
}
#else
void
_write (const char *s, int size)
{
(void)s;
(void)size;
}
#endif

View File

@@ -1,7 +1,8 @@
/*
* usb-msc.c -- USB Mass Storage Class protocol handling
*
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2011, 2012, 2013, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -170,11 +171,13 @@ EP6_OUT_Callback (void)
}
static const uint8_t scsi_inquiry_data_00[] = { 0, 0, 0, 0, 0 };
static const uint8_t scsi_inquiry_data_83[] = { 0, 0x83, 0, 0 };
static const uint8_t scsi_inquiry_data[] = {
0x00, /* Direct Access Device. */
0x80, /* RMB = 1: Removable Medium. */
0x05, /* Version: SPC-3. */
0x00, /* Version: not claim conformance. */
0x02, /* Response format: SPC-3. */
36 - 4, /* Additional Length. */
0x00,
@@ -316,7 +319,7 @@ msc_handle_command (void)
/* Error occured, ignore the request and go into error state */
msc_state = MSC_ERROR;
usb_lld_stall_rx (ENDP6);
goto done;
goto done;
}
n = ep6_out.rxcnt;
@@ -330,6 +333,11 @@ msc_handle_command (void)
CSW.dCSWTag = CBW.dCBWTag;
switch (CBW.CBWCB[0]) {
case SCSI_REPORT_LUN:
buf[0] = buf[1] = buf[2] = buf[3] = 0;
buf[4] = buf[5] = buf[6] = buf[7] = 0;
msc_send_result (buf, 8);
goto done;
case SCSI_REQUEST_SENSE:
if (CBW.CBWCB[1] & 0x01) /* DESC */
msc_send_result ((uint8_t *)&scsi_sense_data_desc,
@@ -345,10 +353,18 @@ msc_handle_command (void)
}
goto done;
case SCSI_INQUIRY:
if (CBW.CBWCB[1] & 0x01) /* EVPD */
/* assume page 00 */
msc_send_result ((uint8_t *)&scsi_inquiry_data_00,
sizeof scsi_inquiry_data_00);
if (CBW.CBWCB[1] & 0x01)
/* EVPD */
{
if (CBW.CBWCB[2] == 0x83)
/* Handle the case Page Code 0x83 */
msc_send_result ((uint8_t *)&scsi_inquiry_data_83,
sizeof scsi_inquiry_data_83);
else
/* Otherwise, assume page 00 */
msc_send_result ((uint8_t *)&scsi_inquiry_data_00,
sizeof scsi_inquiry_data_00);
}
else
msc_send_result ((uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data);
@@ -462,6 +478,7 @@ msc_handle_command (void)
if (CBW.CBWCB[8]-- == 0)
CBW.CBWCB[7]--;
CSW.dCSWDataResidue += 512;
lba++;
}
else
{
@@ -507,6 +524,7 @@ msc_handle_command (void)
if (CBW.CBWCB[8]-- == 0)
CBW.CBWCB[7]--;
CSW.dCSWDataResidue -= 512;
lba++;
}
else
{

View File

@@ -1,7 +1,8 @@
/*
* usb_ctrl.c - USB control pipe device specific code for Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -57,16 +58,15 @@ static struct line_coding line_coding = {
0x08 /* bits: 8 */
};
#define CDC_CTRL_DTR 0x0001
static int
vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
{
if (USB_SETUP_GET (req))
{
if (req_no == USB_CDC_REQ_GET_LINE_CODING)
{
usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
return USB_SUCCESS;
}
return usb_lld_reply_request (&line_coding, sizeof(line_coding), arg);
}
else /* USB_SETUP_SET (req) */
{
@@ -79,7 +79,7 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
{
uint8_t connected_saved = stdout.connected;
if (value != 0)
if ((arg->value & CDC_CTRL_DTR) != 0)
{
if (stdout.connected == 0)
/* It's Open call */
@@ -199,22 +199,18 @@ usb_cb_device_reset (void)
{
int i;
/* Set DEVICE as not configured */
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (USB_INITIAL_FEATURE);
usb_lld_reset ();
usb_lld_reset (USB_INITIAL_FEATURE);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
GNUK_MAX_PACKET_SIZE);
/* Stop the interface */
for (i = 0; i < NUM_INTERFACES; i++)
gnuk_setup_endpoints_for_interface (i, 0);
gnuk_setup_endpoints_for_interface (i, 1);
bDeviceState = ATTACHED;
ccid_usb_reset ();
}
#define USB_CCID_REQ_ABORT 0x01
@@ -262,8 +258,7 @@ static int download_check_crc32 (const uint32_t *end_p)
}
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -272,32 +267,31 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
if (USB_SETUP_GET (req))
{
if (req_no == USB_FSIJ_GNUK_MEMINFO)
{
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
return USB_SUCCESS;
}
return usb_lld_reply_request (mem_info, sizeof (mem_info), arg);
}
else /* SETUP_SET */
{
uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100
+ arg->index);
if (req_no == USB_FSIJ_GNUK_DOWNLOAD)
{
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
if (*icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT;
if (addr < &_regnual_start || addr + len > __heap_end__)
if (addr < &_regnual_start || addr + arg->len > __heap_end__)
return USB_UNSUPPORT;
if (index + len < 256)
memset (addr + index + len, 0, 256 - (index + len));
if (arg->index + arg->len < 256)
memset (addr + arg->index + arg->len, 0,
256 - (arg->index + arg->len));
usb_lld_set_data_to_recv (addr, len);
usb_lld_set_data_to_recv (addr, arg->len);
return USB_SUCCESS;
}
else if (req_no == USB_FSIJ_GNUK_EXEC && len == 0)
else if (req_no == USB_FSIJ_GNUK_EXEC && arg->len == 0)
{
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
if (*icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT;
if (((uint32_t)addr & 0x03))
@@ -305,33 +299,28 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
return download_check_crc32 ((uint32_t *)addr);
}
else if (req_no == USB_FSIJ_GNUK_CARD_CHANGE && len == 0)
else if (req_no == USB_FSIJ_GNUK_CARD_CHANGE && arg->len == 0)
{
if (value != 0 && value != 1 && value != 2)
if (arg->value != 0 && arg->value != 1 && arg->value != 2)
return USB_UNSUPPORT;
ccid_card_change_signal (value);
ccid_card_change_signal (arg->value);
return USB_SUCCESS;
}
}
}
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
if (index == ICC_INTERFACE)
if (arg->index == ICC_INTERFACE)
{
if (USB_SETUP_GET (req))
{
if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
{
usb_lld_set_data_to_send (freq_table, sizeof (freq_table));
return USB_SUCCESS;
}
return usb_lld_reply_request (freq_table, sizeof (freq_table),
arg);
else if (req_no == USB_CCID_REQ_GET_DATA_RATES)
{
usb_lld_set_data_to_send (data_rate_table,
sizeof (data_rate_table));
return USB_SUCCESS;
}
return usb_lld_reply_request (data_rate_table,
sizeof (data_rate_table), arg);
}
else
{
@@ -342,26 +331,24 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
}
}
#ifdef HID_CARD_CHANGE_SUPPORT
else if (index == HID_INTERFACE)
else if (arg->index == HID_INTERFACE)
{
switch (req_no)
{
case USB_HID_REQ_GET_IDLE:
usb_lld_set_data_to_send (&hid_idle_rate, 1);
return USB_SUCCESS;
return usb_lld_reply_request (&hid_idle_rate, 1, arg);
case USB_HID_REQ_SET_IDLE:
usb_lld_set_data_to_recv (&hid_idle_rate, 1);
return USB_SUCCESS;
case USB_HID_REQ_GET_REPORT:
/* Request of LED status and key press */
usb_lld_set_data_to_send (&hid_report, 2);
return USB_SUCCESS;
return usb_lld_reply_request (&hid_report, 2, arg);
case USB_HID_REQ_SET_REPORT:
/* Received LED set request */
if (len == 1)
usb_lld_set_data_to_recv (&hid_report, len);
if (arg->len == 1)
usb_lld_set_data_to_recv (&hid_report, arg->len);
return USB_SUCCESS;
case USB_HID_REQ_GET_PROTOCOL:
@@ -375,19 +362,17 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
}
#endif
#ifdef ENABLE_VIRTUAL_COM_PORT
else if (index == VCOM_INTERFACE_0)
return vcom_port_data_setup (req, req_no, value);
else if (arg->index == VCOM_INTERFACE_0)
return vcom_port_data_setup (req, req_no, arg);
#endif
#ifdef PINPAD_DND_SUPPORT
else if (index == MSC_INTERFACE)
else if (arg->index == MSC_INTERFACE)
{
if (USB_SETUP_GET (req))
{
if (req_no == MSC_GET_MAX_LUN_COMMAND)
{
usb_lld_set_data_to_send (lun_table, sizeof (lun_table));
return USB_SUCCESS;
}
return usb_lld_reply_request (lun_table, sizeof (lun_table),
arg);
}
else
if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
@@ -402,27 +387,27 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
void
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
(void)arg;
if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
{
if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC && len == 0)
if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC)
{
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
if (*icc_state_p != ICC_STATE_EXITED)
return;
(void)value; (void)index;
bDeviceState = UNCONNECTED;
usb_lld_prepare_shutdown (); /* No further USB communication */
*icc_state_p = ICC_STATE_EXEC_REQUESTED;
led_blink (LED_GNUK_EXEC); /* Notify the main. */
}
}
#ifdef HID_CARD_CHANGE_SUPPORT
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
if (index == HID_INTERFACE && req_no == USB_HID_REQ_SET_REPORT)
if (arg->index == HID_INTERFACE && req_no == USB_HID_REQ_SET_REPORT)
{
if ((hid_report ^ hid_report_saved) & HID_LED_STATUS_CARDCHANGE)
ccid_card_change_signal (CARD_CHANGE_TOGGLE);
@@ -476,9 +461,11 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, struct req_args *arg)
{
const uint8_t zero = 0;
uint16_t interface = arg->index;
uint16_t alt = arg->value;
if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT;
@@ -495,36 +482,10 @@ int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
}
case USB_GET_INTERFACE:
usb_lld_write (ENDP0, &zero, 1);
usb_lld_set_data_to_send (NULL, 1);
return USB_SUCCESS;
return usb_lld_reply_request (&zero, 1, arg);
default:
case USB_QUERY_INTERFACE:
default:
return USB_SUCCESS;
}
}
#define INTR_REQ_USB 20
void *
usb_intr (void *arg)
{
chopstx_intr_t interrupt;
(void)arg;
usb_lld_init (USB_INITIAL_FEATURE);
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
usb_interrupt_handler ();
while (1)
{
chopstx_intr_wait (&interrupt);
/* Process interrupt. */
usb_interrupt_handler ();
}
return NULL;
}

View File

@@ -59,9 +59,9 @@ static const uint8_t hid_report_desc[] = {
#define USB_ICC_DATA_SIZE 64
/* USB Standard Device Descriptor */
static const uint8_t gnukDeviceDescriptor[] = {
static const uint8_t device_desc[] = {
18, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
DEVICE_DESCRIPTOR, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */
0x00, /* bDeviceClass: 0 means deferred to interface */
0x00, /* bDeviceSubClass */
@@ -99,11 +99,11 @@ static const uint8_t gnukDeviceDescriptor[] = {
/* Configuation Descriptor */
static const uint8_t gnukConfigDescriptor[] = {
static const uint8_t config_desc[] = {
9, /* bLength: Configuation Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */
NUM_INTERFACES, /* bNumInterfaces: */
CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */
NUM_INTERFACES, /* bNumInterfaces: */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
USB_INITIAL_FEATURE, /* bmAttributes*/
@@ -111,7 +111,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
ICC_INTERFACE, /* bInterfaceNumber: Index of this interface */
0, /* Alternate setting for this interface */
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
@@ -167,21 +167,21 @@ static const uint8_t gnukConfigDescriptor[] = {
1, /* bMaxCCIDBusySlots: 1 */
/*Endpoint IN1 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress: (IN1) */
0x02, /* bmAttributes: Bulk */
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval */
/*Endpoint OUT1 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x01, /* bEndpointAddress: (OUT1) */
0x02, /* bmAttributes: Bulk */
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval */
/*Endpoint IN2 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x82, /* bEndpointAddress: (IN2) */
0x03, /* bmAttributes: Interrupt */
0x04, 0x00, /* wMaxPacketSize: 4 */
@@ -190,7 +190,7 @@ static const uint8_t gnukConfigDescriptor[] = {
#ifdef HID_CARD_CHANGE_SUPPORT
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
HID_INTERFACE, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
@@ -209,7 +209,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/*Endpoint IN7 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x87, /* bEndpointAddress: (IN7) */
0x03, /* bmAttributes: Interrupt */
0x02, 0x00, /* wMaxPacketSize: 2 */
@@ -219,7 +219,7 @@ static const uint8_t gnukConfigDescriptor[] = {
#ifdef ENABLE_VIRTUAL_COM_PORT
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
VCOM_INTERFACE_0, /* bInterfaceNumber: Index of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
@@ -251,7 +251,7 @@ static const uint8_t gnukConfigDescriptor[] = {
VCOM_INTERFACE_1, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 4 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x84, /* bEndpointAddress: (IN4) */
0x03, /* bmAttributes: Interrupt */
VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
@@ -259,7 +259,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/*Data class interface descriptor*/
9, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
INTERFACE_DESCRIPTOR, /* bDescriptorType: */
VCOM_INTERFACE_1, /* bInterfaceNumber: Index of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
@@ -269,14 +269,14 @@ static const uint8_t gnukConfigDescriptor[] = {
0x00, /* iInterface: */
/*Endpoint 5 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x05, /* bEndpointAddress: (OUT5) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint 3 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x83, /* bEndpointAddress: (IN3) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
@@ -285,7 +285,7 @@ static const uint8_t gnukConfigDescriptor[] = {
#ifdef PINPAD_DND_SUPPORT
/* Interface Descriptor.*/
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
MSC_INTERFACE, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x02, /* bNumEndpoints. */
@@ -298,14 +298,14 @@ static const uint8_t gnukConfigDescriptor[] = {
0x00, /* iInterface. */
/* Endpoint Descriptor.*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x86, /* bEndpointAddress: (IN6) */
0x02, /* bmAttributes (Bulk). */
0x40, 0x00, /* wMaxPacketSize. */
0x00, /* bInterval (ignored for bulk). */
/* Endpoint Descriptor.*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
0x06, /* bEndpointAddress: (OUT6) */
0x02, /* bmAttributes (Bulk). */
0x40, 0x00, /* wMaxPacketSize. */
@@ -317,7 +317,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* USB String Descriptors */
static const uint8_t gnuk_string_lang_id[] = {
4, /* bLength */
USB_STRING_DESCRIPTOR_TYPE,
STRING_DESCRIPTOR,
0x09, 0x04 /* LangID = 0x0409: US-English */
};
@@ -346,30 +346,20 @@ static const struct desc string_descriptors[] = {
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index, uint16_t length)
struct req_args *arg)
{
if (rcp == DEVICE_RECIPIENT)
{
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (gnukDeviceDescriptor,
sizeof (gnukDeviceDescriptor));
return USB_SUCCESS;
}
return usb_lld_reply_request (device_desc, sizeof (device_desc), arg);
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (gnukConfigDescriptor,
sizeof (gnukConfigDescriptor));
return USB_SUCCESS;
}
return usb_lld_reply_request (config_desc, sizeof (config_desc), arg);
else if (desc_type == STRING_DESCRIPTOR)
{
if (desc_index < NUM_STRING_DESC)
{
usb_lld_set_data_to_send (string_descriptors[desc_index].desc,
string_descriptors[desc_index].size);
return USB_SUCCESS;
}
return usb_lld_reply_request (string_descriptors[desc_index].desc,
string_descriptors[desc_index].size,
arg);
else if (desc_index == NUM_STRING_DESC)
{
uint8_t usbbuf[64];
@@ -385,37 +375,25 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
usbbuf[i*2+3] = 0;
}
usbbuf[0] = len = i*2 + 2;
usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
if (len > length)
len = length;
usb_lld_write (ENDP0, usbbuf, len);
usb_lld_set_data_to_send (NULL, len);
return USB_SUCCESS;
usbbuf[1] = STRING_DESCRIPTOR;
return usb_lld_reply_request (usbbuf, len, arg);
}
}
}
#ifdef HID_CARD_CHANGE_SUPPORT
else if (rcp == INTERFACE_RECIPIENT)
{
#ifdef HID_CARD_CHANGE_SUPPORT
if (index == 1)
if (arg->index == HID_INTERFACE)
{
if (desc_type == USB_DT_HID)
{
usb_lld_set_data_to_send (gnukConfigDescriptor+ICC_TOTAL_LENGTH+9,
9);
return USB_SUCCESS;
}
return usb_lld_reply_request (config_desc+ICC_TOTAL_LENGTH+9, 9,
arg);
else if (desc_type == USB_DT_REPORT)
{
usb_lld_set_data_to_send (hid_report_desc, HID_REPORT_DESC_SIZE);
return USB_SUCCESS;
}
return usb_lld_reply_request (hid_report_desc, HID_REPORT_DESC_SIZE,
arg);
}
else
#else
(void)index;
#endif
}
#endif
return USB_UNSUPPORT;
}

View File

@@ -1,9 +1,3 @@
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
#define USB_STRING_DESCRIPTOR_TYPE 0x03
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
/* endpoints enumeration */
@@ -24,7 +18,7 @@
enum RECIPIENT_TYPE
{
DEVICE_RECIPIENT, /* Recipient device */
DEVICE_RECIPIENT = 0, /* Recipient device */
INTERFACE_RECIPIENT, /* Recipient interface */
ENDPOINT_RECIPIENT, /* Recipient endpoint */
OTHER_RECIPIENT
@@ -55,15 +49,22 @@ enum
USB_SUCCESS = 1,
};
struct req_args {
uint16_t value;
uint16_t index;
uint16_t len;
};
void usb_cb_device_reset (void);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int usb_cb_setup (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len);
int usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg);
int usb_cb_interface (uint8_t cmd, struct req_args *arg);
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index, uint16_t length);
struct req_args *arg);
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t value);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
struct req_args *arg);
void usb_cb_tx_done (uint8_t ep_num);
void usb_cb_rx_ready (uint8_t ep_num);
enum {
USB_EVENT_ADDRESS,
@@ -89,7 +90,6 @@ enum DEVICE_STATE
CONFIGURED
};
void usb_lld_init (uint8_t feature);
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
@@ -99,22 +99,18 @@ int usb_lld_tx_data_len (int ep_num);
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
void usb_lld_tx_enable (int ep_num, size_t len);
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
int usb_lld_reply_request (const void *buf, size_t buflen,
struct req_args *arg);
void usb_lld_rx_enable (int ep_num);
int usb_lld_rx_data_len (int ep_num);
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
void usb_lld_reset (void);
void usb_lld_reset (uint8_t feature);
void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
int ep_rx_addr, int ep_tx_addr,
int ep_rx_memory_size);
void usb_lld_set_configuration (uint8_t config);
uint8_t usb_lld_current_configuration (void);
void usb_lld_set_feature (uint8_t feature);
void usb_lld_set_data_to_send (const void *p, size_t len);
extern inline void usb_lld_set_data_to_recv (void *p, size_t len)
{
usb_lld_set_data_to_send ((const void *)p, len);
}
void usb_lld_set_data_to_recv (void *p, size_t len);
void usb_lld_prepare_shutdown (void);
void usb_lld_shutdown (void);

View File

@@ -1,9 +1,6 @@
#include <stdint.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#include "sys.h"
#include "usb_lld.h"
@@ -49,33 +46,29 @@ enum FEATURE_SELECTOR
struct DATA_INFO
{
uint16_t len;
uint16_t offset;
uint8_t *addr;
uint16_t len;
uint8_t require_zlp;
};
struct CONTROL_INFO
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
};
struct DEVICE_INFO
{
uint8_t current_configuration;
uint8_t current_feature;
uint8_t state;
/**/
uint8_t bmRequestType;
uint8_t bRequest;
/**/
uint16_t value;
uint16_t index;
uint16_t len;
};
static struct CONTROL_INFO control_info;
static struct DEVICE_INFO device_info;
static struct DATA_INFO data_info;
static struct CONTROL_INFO *const ctrl_p = &control_info;
static struct DEVICE_INFO *const dev_p = &device_info;
static struct DATA_INFO *const data_p = &data_info;
@@ -362,7 +355,7 @@ void usb_lld_init (uint8_t feature)
dev_p->state = IN_DATA;
usb_lld_set_configuration (0);
usb_lld_set_feature (feature);
dev_p->current_feature = feature;
/* Reset USB */
st103_set_cntr (CNTR_FRES);
@@ -412,16 +405,14 @@ static void handle_datastage_out (void)
{
if (data_p->addr && data_p->len)
{
uint8_t *buf;
uint32_t len = st103_get_rx_count (ENDP0);
if (len > data_p->len)
len = data_p->len;
buf = data_p->addr + data_p->offset;
usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len);
usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len);
data_p->len -= len;
data_p->offset += len;
data_p->addr += len;
}
if (data_p->len == 0)
@@ -440,13 +431,12 @@ static void handle_datastage_out (void)
static void handle_datastage_in (void)
{
uint32_t len = USB_MAX_PACKET_SIZE;;
const uint8_t *buf;
if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA))
{
if (data_p->require_zlp == TRUE)
if (data_p->require_zlp)
{
data_p->require_zlp = FALSE;
data_p->require_zlp = 0;
/* No more data to send. Send empty packet */
st103_set_tx_count (ENDP0, 0);
@@ -467,40 +457,33 @@ static void handle_datastage_in (void)
if (len > data_p->len)
len = data_p->len;
buf = (const uint8_t *)data_p->addr + data_p->offset;
usb_lld_to_pmabuf (buf, st103_get_tx_addr (ENDP0), len);
usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
data_p->len -= len;
data_p->offset += len;
data_p->addr += len;
st103_set_tx_count (ENDP0, len);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
}
typedef int (*HANDLER) (uint8_t req,
uint16_t value, uint16_t index, uint16_t length);
typedef int (*HANDLER) (uint8_t req, struct req_args *arg);
static int std_none (uint8_t req,
uint16_t value, uint16_t index, uint16_t length)
static int std_none (uint8_t req, struct req_args *arg)
{
(void)req; (void)value; (void)index; (void)length;
(void)req; (void)arg;
return USB_UNSUPPORT;
}
static int std_get_status (uint8_t req,
uint16_t value, uint16_t index, uint16_t length)
static int std_get_status (uint8_t req, struct req_args *arg)
{
static uint16_t status_info;
uint8_t rcp = req & RECIPIENT;
uint16_t status_info = 0;
status_info = 0; /* Reset Status Information */
data_p->addr = (uint8_t *)&status_info;
if (value != 0 || length != 2 || (index >> 8) != 0
|| (req & REQUEST_DIR) == 0)
if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0
|| USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (index == 0)
if (arg->index == 0)
{
/* Get Device Status */
uint8_t feature = dev_p->current_feature;
@@ -517,8 +500,7 @@ static int std_get_status (uint8_t req,
else /* Self-powered */
status_info &= ~1;
data_p->len = 2;
return USB_SUCCESS;
return usb_lld_reply_request (&status_info, 2, arg);
}
}
else if (rcp == INTERFACE_RECIPIENT)
@@ -528,22 +510,21 @@ static int std_get_status (uint8_t req,
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
r = usb_cb_interface (USB_QUERY_INTERFACE, index, 0);
r = usb_cb_interface (USB_QUERY_INTERFACE, arg);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
data_p->len = 2;
return USB_SUCCESS;
return usb_lld_reply_request (&status_info, 2, arg);
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t endpoint = (index & 0x0f);
uint8_t endpoint = (arg->index & 0x0f);
uint16_t status;
if ((index & 0x70) || endpoint == ENDP0)
if ((arg->index & 0x70) || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((arg->index & 0x80))
{
status = st103_ep_get_tx_status (endpoint);
if (status == 0) /* Disabled */
@@ -560,27 +541,25 @@ static int std_get_status (uint8_t req,
status_info |= 1; /* OUT Endpoint stalled */
}
data_p->len = 2;
return USB_SUCCESS;
return usb_lld_reply_request (&status_info, 2, arg);
}
return USB_UNSUPPORT;
}
static int std_clear_feature (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_clear_feature (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (length != 0 || index != 0)
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP)
if (arg->value == DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature &= ~(1 << 5);
return USB_SUCCESS;
@@ -588,17 +567,17 @@ static int std_clear_feature (uint8_t req, uint16_t value,
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t endpoint = (index & 0x0f);
uint8_t endpoint = (arg->index & 0x0f);
uint16_t status;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
if (length != 0 || (index >> 8) != 0 || value != ENDPOINT_STALL
|| endpoint == ENDP0)
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != ENDPOINT_STALL || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((arg->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
@@ -606,7 +585,7 @@ static int std_clear_feature (uint8_t req, uint16_t value,
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
if (index & 0x80) /* IN endpoint */
if (arg->index & 0x80) /* IN endpoint */
st103_ep_clear_dtog_tx (endpoint);
else /* OUT endpoint */
st103_ep_clear_dtog_rx (endpoint);
@@ -618,20 +597,19 @@ static int std_clear_feature (uint8_t req, uint16_t value,
return USB_UNSUPPORT;
}
static int std_set_feature (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_set_feature (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (length != 0 || index != 0)
if (arg->len != 0 || arg->index != 0)
return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP)
if (arg->value == DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature |= 1 << 5;
// event??
@@ -640,16 +618,17 @@ static int std_set_feature (uint8_t req, uint16_t value,
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t endpoint = (index & 0x0f);
uint8_t endpoint = (arg->index & 0x0f);
uint32_t status;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
if (length != 0 || (index >> 8) != 0 || value != 0 || endpoint == ENDP0)
if (arg->len != 0 || (arg->index >> 8) != 0
|| arg->value != 0 || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((arg->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
@@ -657,7 +636,7 @@ static int std_set_feature (uint8_t req, uint16_t value,
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
if (index & 0x80)
if (arg->index & 0x80)
/* IN endpoint */
st103_ep_set_tx_status (endpoint, EP_TX_STALL);
else
@@ -671,122 +650,88 @@ static int std_set_feature (uint8_t req, uint16_t value,
return USB_UNSUPPORT;
}
static int std_set_address (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_set_address (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127
&& arg->index == 0 && dev_p->current_configuration == 0)
return USB_SUCCESS;
return USB_UNSUPPORT;
}
static int std_get_descriptor (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
return usb_cb_get_descriptor (rcp, (arg->value >> 8),
(arg->value & 0xff), arg);
}
static int std_get_configuration (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (length == 0 && value <= 127 && index == 0
&& dev_p->current_configuration == 0)
return USB_SUCCESS;
}
return usb_lld_reply_request (&dev_p->current_configuration, 1, arg);
return USB_UNSUPPORT;
}
static int std_get_descriptor (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_set_configuration (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 0)
if (USB_SETUP_GET (req))
return USB_UNSUPPORT;
(void)length;
return usb_cb_get_descriptor (rcp, (value >> 8), (value & 0xff),
index, length);
}
static int std_get_configuration (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 0)
return USB_UNSUPPORT;
(void)value; (void)index; (void)length;
if (rcp == DEVICE_RECIPIENT)
{
data_p->addr = &dev_p->current_configuration;
data_p->len = 1;
return USB_SUCCESS;
}
if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0)
return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value);
return USB_UNSUPPORT;
}
static int std_set_configuration (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_get_interface (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0)
{
int r;
r = usb_cb_handle_event (USB_EVENT_CONFIG, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
static int std_get_interface (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 0)
if (USB_SETUP_SET (req))
return USB_UNSUPPORT;
if (rcp == INTERFACE_RECIPIENT)
{
if (value != 0 || (index >> 8) != 0 || length != 1)
if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1)
return USB_UNSUPPORT;
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
return usb_cb_interface (USB_GET_INTERFACE, index, 0);
return usb_cb_interface (USB_GET_INTERFACE, arg);
}
return USB_UNSUPPORT;
}
static int std_set_interface (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_set_interface (uint8_t req, struct req_args *arg)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT
|| arg->len != 0 || (arg->index >> 8) != 0
|| (arg->value >> 8) != 0 || dev_p->current_configuration == 0)
return USB_UNSUPPORT;
if (rcp == INTERFACE_RECIPIENT)
{
int r;
if (length != 0 || (index >> 8) != 0 || (value >> 8) != 0)
return USB_UNSUPPORT;
if (dev_p->current_configuration != 0)
return USB_UNSUPPORT;
r = usb_cb_interface (USB_SET_INTERFACE, index, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
return USB_UNSUPPORT;
return usb_cb_interface (USB_SET_INTERFACE, arg);
}
@@ -794,31 +739,31 @@ static void handle_setup0 (void)
{
const uint16_t *pw;
uint16_t w;
uint8_t req;
uint8_t req_no;
int r = USB_UNSUPPORT;
HANDLER handler;
pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2));
w = *pw++;
ctrl_p->bmRequestType = w & 0xff;
ctrl_p->bRequest = req = w >> 8;
dev_p->bmRequestType = w & 0xff;
dev_p->bRequest = req_no = w >> 8;
pw++;
ctrl_p->wValue = *pw++;
dev_p->value = *pw++;
pw++;
ctrl_p->wIndex = *pw++;
dev_p->index = *pw++;
pw++;
ctrl_p->wLength = *pw;
dev_p->len = *pw;
data_p->addr = NULL;
data_p->len = 0;
data_p->offset = 0;
data_p->require_zlp = 0;
if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
if ((dev_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST)
{
if (req < TOTAL_REQUEST)
if (req_no < TOTAL_REQUEST)
{
switch (req)
switch (req_no)
{
case 0: handler = std_get_status; break;
case 1: handler = std_clear_feature; break;
@@ -832,54 +777,32 @@ static void handle_setup0 (void)
default: handler = std_none; break;
}
r = (*handler) (ctrl_p->bmRequestType,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
r = (*handler) (dev_p->bmRequestType,
(struct req_args *)&dev_p->value);
}
}
else
r = usb_cb_setup (ctrl_p->bmRequestType, req,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
r = usb_cb_setup (dev_p->bmRequestType, req_no,
(struct req_args *)&dev_p->value);
if (r != USB_SUCCESS)
dev_p->state = STALLED;
else
{
if (USB_SETUP_GET (ctrl_p->bmRequestType))
if (USB_SETUP_SET (dev_p->bmRequestType))
{
uint32_t len = ctrl_p->wLength;
/* Restrict the data length to be the one host asks for */
if (data_p->len > len)
data_p->len = len;
if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
data_p->require_zlp = TRUE;
else
data_p->require_zlp = FALSE;
if (data_p->addr == NULL)
if (dev_p->len == 0)
{
/* usb_lld_wite was called already by the setup callback. */
dev_p->state = LAST_IN_DATA;
data_p->len = 0;
dev_p->state = WAIT_STATUS_IN;
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
}
else
{
dev_p->state = IN_DATA;
handle_datastage_in ();
dev_p->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
}
else if (ctrl_p->wLength == 0)
{
dev_p->state = WAIT_STATUS_IN;
st103_set_tx_count (ENDP0, 0);
st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID);
}
else
{
dev_p->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
}
}
@@ -889,17 +812,16 @@ static void handle_in0 (void)
handle_datastage_in ();
else if (dev_p->state == WAIT_STATUS_IN)
{
if ((ctrl_p->bRequest == SET_ADDRESS) &&
((ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
if ((dev_p->bRequest == SET_ADDRESS) &&
((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT))
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
st103_set_daddr (ctrl_p->wValue);
usb_cb_handle_event (USB_EVENT_ADDRESS, ctrl_p->wValue);
st103_set_daddr (dev_p->value);
usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value);
}
else
usb_cb_ctrl_write_finish (ctrl_p->bmRequestType,
ctrl_p->bRequest, ctrl_p->wValue,
ctrl_p->wIndex, ctrl_p->wLength);
usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest,
(struct req_args *)&dev_p->value);
dev_p->state = STALLED;
}
@@ -921,27 +843,6 @@ static void handle_out0 (void)
dev_p->state = STALLED;
}
static void nop_proc (void)
{
}
#define WEAK __attribute__ ((weak, alias ("nop_proc")))
void WEAK EP1_IN_Callback (void);
void WEAK EP2_IN_Callback (void);
void WEAK EP3_IN_Callback (void);
void WEAK EP4_IN_Callback (void);
void WEAK EP5_IN_Callback (void);
void WEAK EP6_IN_Callback (void);
void WEAK EP7_IN_Callback (void);
void WEAK EP1_OUT_Callback (void);
void WEAK EP2_OUT_Callback (void);
void WEAK EP3_OUT_Callback (void);
void WEAK EP4_OUT_Callback (void);
void WEAK EP5_OUT_Callback (void);
void WEAK EP6_OUT_Callback (void);
void WEAK EP7_OUT_Callback (void);
static void
usb_handle_transfer (uint16_t istr_value)
{
@@ -979,37 +880,21 @@ usb_handle_transfer (uint16_t istr_value)
if ((ep_value & EP_CTR_RX))
{
st103_ep_clear_ctr_rx (ep_index);
switch ((ep_index - 1))
{
case 0: EP1_OUT_Callback (); break;
case 1: EP2_OUT_Callback (); break;
case 2: EP3_OUT_Callback (); break;
case 3: EP4_OUT_Callback (); break;
case 4: EP5_OUT_Callback (); break;
case 5: EP6_OUT_Callback (); break;
case 6: EP7_OUT_Callback (); break;
}
usb_cb_rx_ready (ep_index);
}
if ((ep_value & EP_CTR_TX))
{
st103_ep_clear_ctr_tx (ep_index);
switch ((ep_index - 1))
{
case 0: EP1_IN_Callback (); break;
case 1: EP2_IN_Callback (); break;
case 2: EP3_IN_Callback (); break;
case 3: EP4_IN_Callback (); break;
case 4: EP5_IN_Callback (); break;
case 5: EP6_IN_Callback (); break;
case 6: EP7_IN_Callback (); break;
}
usb_cb_tx_done (ep_index);
}
}
}
void usb_lld_reset (void)
void usb_lld_reset (uint8_t feature)
{
usb_lld_set_configuration (0);
dev_p->current_feature = feature;
st103_set_btable ();
st103_set_daddr (0);
}
@@ -1116,14 +1001,9 @@ uint8_t usb_lld_current_configuration (void)
return dev_p->current_configuration;
}
void usb_lld_set_feature (uint8_t feature)
void usb_lld_set_data_to_recv (void *p, size_t len)
{
dev_p->current_feature = feature;
}
void usb_lld_set_data_to_send (const void *p, size_t len)
{
data_p->addr = (uint8_t *)p;
data_p->addr = p;
data_p->len = len;
}
@@ -1199,3 +1079,49 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n)
*d = (w & 0xff);
}
}
/*
* BUF: Pointer to data memory. Data memory should not be allocated
* on stack when BUFLEN > USB_MAX_PACKET_SIZE.
*
* BUFLEN: size of the data.
*/
int
usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl)
{
uint32_t len_asked = ctl->len;
uint32_t len;
data_p->addr = (void *)buf;
data_p->len = buflen;
/* Restrict the data length to be the one host asks for */
if (data_p->len > len_asked)
data_p->len = len_asked;
if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
data_p->require_zlp = 1;
if (data_p->len < USB_MAX_PACKET_SIZE)
{
len = data_p->len;
dev_p->state = LAST_IN_DATA;
}
else
{
len = USB_MAX_PACKET_SIZE;
dev_p->state = IN_DATA;
}
if (len)
{
usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
data_p->len -= len;
data_p->addr += len;
}
st103_set_tx_count (ENDP0, len);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
return USB_SUCCESS;
}

View File

@@ -7,6 +7,7 @@ import ast
import gnuk_token as gnuk
import rsa_keys
from array import array
@Before
def ini(sc):
@@ -26,7 +27,7 @@ def cmd_change_reference_data(who_str,pass_str):
@Given("cmd_put_data with (.*) and (\".*\")")
def cmd_put_data(tag_str,content_str_repr):
content_str = ast.literal_eval(content_str_repr)
content_str = ast.literal_eval("b" + content_str_repr + "")
tag = int(tag_str, 16)
tagh = tag >> 8
tagl = tag & 0xff
@@ -66,7 +67,7 @@ def cmd_put_data_with_result(tag_str):
@Given("a message (\".*\")")
def set_msg(content_str_repr):
msg = ast.literal_eval(content_str_repr)
msg = ast.literal_eval(content_str_repr).encode('UTF-8')
scc.digestinfo = rsa_keys.compute_digestinfo(msg)
@Given("a public key from token for OPENPGP.(.*)")
@@ -93,7 +94,7 @@ def compute_signature_on_host(keyno_str):
@Given("a plain text (\".*\")")
def set_plaintext(content_str_repr):
scc.plaintext = ast.literal_eval(content_str_repr)
scc.plaintext = ast.literal_eval("b" + content_str_repr + "")
@Given("encrypt it on host with RSA key pair (.*)$")
def encrypt_on_host(keyno_str):
@@ -106,7 +107,7 @@ def encrypt_on_host_public_key():
@Given("let a token decrypt encrypted data")
def decrypt():
scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext)
scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext).tostring()
@Given("USB version string of the token")
def usb_version_string():
@@ -129,7 +130,7 @@ def remove_key(openpgp_keyno_str):
def generate_key(openpgp_keyno_str):
openpgp_keyno = int(openpgp_keyno_str)
pubkey_info = ftc.token.cmd_genkey(openpgp_keyno)
scc.data = rsa_keys.calc_fpr(pubkey_info[0], pubkey_info[1])
scc.data = rsa_keys.calc_fpr(pubkey_info[0].tostring(), pubkey_info[1].tostring())
@When("put the first data to (.*)")
def cmd_put_data_first_with_result(tag_str):
@@ -148,8 +149,8 @@ def cmd_put_data_second_with_result(tag_str):
@Then("you should get: (.*)")
def check_result(v):
value = ast.literal_eval("'" + v + "'")
assert_equal(scc.result, value)
value = ast.literal_eval("b'" + v + "'")
assert_equal(scc.result, array('B', value))
@Then("it should get success")
def check_success():
@@ -157,7 +158,7 @@ def check_success():
@Then("you should get NULL")
def check_null():
assert_equal(scc.result, "")
assert_equal(scc.result, array('B'))
@Then("data should match: (.*)")
def check_regexp(re):

View File

@@ -14,10 +14,10 @@ def print_key_in_hex(k):
q_str = hexlify(q)
if int(p_str, 16)*int(q_str, 16) != int(n_str, 16):
raise ValueError("wrong key", k)
print n_str
print e_str
print p_str
print q_str
print(n_str)
print(e_str)
print(p_str)
print(q_str)
rng = Random.new().read
key = RSA.generate(2048, rng)

View File

@@ -24,7 +24,7 @@ def calc_fpr(n,e):
timestamp = int(time())
timestamp_data = pack('>I', timestamp)
m_len = 6 + 2 + 256 + 2 + 4
m = '\x99' + pack('>H', m_len) + '\x04' + timestamp_data + '\x01' + \
m = b'\x99' + pack('>H', m_len) + b'\x04' + timestamp_data + b'\x01' + \
pack('>H', 2048) + n + pack('>H', 17) + e
fpr = sha1(m).digest()
return (fpr, timestamp_data)
@@ -42,39 +42,39 @@ key[2] = read_key_from_file('rsa-aut.key')
(fpr[2], timestamp[2]) = calc_fpr(key[2][0], key[2][1])
def build_privkey_template(openpgp_keyno, keyno):
n_str = key[keyno][0]
e_str = '\x00' + key[keyno][1]
p_str = key[keyno][2]
q_str = key[keyno][3]
n_bytes = key[keyno][0]
e_bytes = b'\x00' + key[keyno][1]
p_bytes = key[keyno][2]
q_bytes = key[keyno][3]
if openpgp_keyno == 1:
keyspec = '\xb6'
keyspec = b'\xb6'
elif openpgp_keyno == 2:
keyspec = '\xb8'
keyspec = b'\xb8'
else:
keyspec = '\xa4'
keyspec = b'\xa4'
key_template = '\x91\x04'+ '\x92\x81\x80' + '\x93\x81\x80'
key_template = b'\x91\x04'+ b'\x92\x81\x80' + b'\x93\x81\x80'
exthdr = keyspec + '\x00' + '\x7f\x48' + '\x08' + key_template
exthdr = keyspec + b'\x00' + b'\x7f\x48' + b'\x08' + key_template
suffix = '\x5f\x48' + '\x82\x01\x04'
suffix = b'\x5f\x48' + b'\x82\x01\x04'
t = '\x4d' + '\x82\01\16' + exthdr + suffix + e_str + p_str + q_str
t = b'\x4d' + b'\x82\01\16' + exthdr + suffix + e_bytes + p_bytes + q_bytes
return t
def build_privkey_template_for_remove(openpgp_keyno):
if openpgp_keyno == 1:
keyspec = '\xb6'
keyspec = b'\xb6'
elif openpgp_keyno == 2:
keyspec = '\xb8'
keyspec = b'\xb8'
else:
keyspec = '\xa4'
return '\x4d\02' + keyspec + '\0x00'
keyspec = b'\xa4'
return b'\x4d\02' + keyspec + b'\0x00'
def compute_digestinfo(msg):
digest = sha256(msg).digest()
prefix = '\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
return prefix + digest
# egcd and modinv are from wikibooks
@@ -95,14 +95,14 @@ def modinv(a, m):
return x % m
def pkcs1_pad_for_sign(digestinfo):
byte_repr = '\x00' + '\x01' + string.ljust('', 256 - 19 - 32 - 3, '\xff') \
+ '\x00' + digestinfo
byte_repr = b'\x00' + b'\x01' + bytes.ljust(b'', 256 - 19 - 32 - 3, b'\xff') \
+ b'\x00' + digestinfo
return int(hexlify(byte_repr), 16)
def pkcs1_pad_for_crypt(msg):
padlen = 256 - 3 - len(msg)
byte_repr = '\x00' + '\x02' \
+ string.replace(urandom(padlen),'\x00','\x01') + '\x00' + msg
byte_repr = b'\x00' + b'\x02' \
+ bytes.replace(urandom(padlen), b'\x00', b'\x01') + b'\x00' + msg
return int(hexlify(byte_repr), 16)
def compute_signature(keyno, digestinfo):
@@ -136,13 +136,13 @@ def encrypt(keyno, plaintext):
e = key[keyno][4]
n = key[keyno][7]
m = pkcs1_pad_for_crypt(plaintext)
return '\x00' + integer_to_bytes_256(pow(m, e, n))
return b'\x00' + integer_to_bytes_256(pow(m, e, n))
def encrypt_with_pubkey(pubkey_info, plaintext):
n = int(hexlify(pubkey_info[0]), 16)
e = int(hexlify(pubkey_info[1]), 16)
m = pkcs1_pad_for_crypt(plaintext)
return '\x00' + integer_to_bytes_256(pow(m, e, n))
return b'\x00' + integer_to_bytes_256(pow(m, e, n))
def verify_signature(pubkey_info, digestinfo, sig):
n = int(hexlify(pubkey_info[0]), 16)

View File

@@ -1,202 +0,0 @@
#! /usr/bin/python
"""
gnuk_put_binary.py - a tool to put binary to Gnuk Token
This tool is for importing certificate, writing serial number, etc.
Copyright (C) 2011, 2012 Free Software Initiative of Japan
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/>.
"""
import sys, os, binascii, string
# INPUT: binary file
# Assume only single CCID device is attached to computer and it's Gnuk Token
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString
def s2l(s):
return [ ord(c) for c in s ]
class GnukToken(object):
def __init__(self):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
result = []
while True:
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
result += response
if sw1 == 0x90 and sw2 == 0x00:
return result
elif sw1 != 0x61:
raise ValueError, ("%02x%02x" % (sw1, sw2))
else:
expected_len = sw2
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_read_binary(self, fileid):
apdu = [0x00, 0xb0, 0x80+fileid, 0x00]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_write_binary(self, fileid, data, is_update):
count = 0
data_len = len(data)
if is_update:
ins = 0xd6
else:
ins = 0xd0
while count*256 < data_len:
if count == 0:
d = data[:256]
if len(d) <= 255:
apdu = [0x00, ins, 0x80+fileid, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
else:
d = data[256*count:256*(count+1)]
if len(d) <= 255:
apdu = [0x00, ins, count, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, count, 0x00, 255] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, count, 0x00, 1] + s2l(d[255:])
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if is_update:
raise ValueError, ("update failure: %02x%02x" % (sw1, sw2))
else:
raise ValueError, ("write failure: %02x%02x" % (sw1, sw2))
count += 1
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_get_data(self, tagh, tagl):
apdu = [0x00, 0xca, tagh, tagl]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def compare(data_original, data_in_device):
i = 0
for d in data_original:
if ord(d) != data_in_device[i]:
raise ValueError, "verify failed at %08x" % i
i += 1
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
def main(fileid, is_update, data, passwd):
gnuk = GnukToken()
gnuk.connection.connect()
print "Token:", gnuk.connection.getReader()
print "ATR:", toHexString( gnuk.connection.getATR() )
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_write_binary(fileid, data, is_update)
gnuk.cmd_select_openpgp()
if fileid == 0:
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
for d in data_in_device:
print "%02x" % d,
print
compare(data, data_in_device[8:])
elif fileid >= 1 and fileid <= 4:
data_in_device = gnuk.cmd_read_binary(fileid)
compare(data, data_in_device)
elif fileid == 5:
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
compare(data, data_in_device)
gnuk.connection.disconnect()
return 0
if __name__ == '__main__':
passwd = DEFAULT_PW3
if sys.argv[1] == '-p':
from getpass import getpass
passwd = getpass("Admin password: ")
sys.argv.pop(1)
if sys.argv[1] == '-u':
is_update = True
sys.argv.pop(1)
else:
is_update = False
if sys.argv[1] == '-s':
fileid = 0 # serial number
filename = sys.argv[2]
f = open(filename)
email = os.environ['EMAIL']
serial_data_hex = None
for line in f.readlines():
field = string.split(line)
if field[0] == email:
serial_data_hex = field[1].replace(':','')
f.close()
if not serial_data_hex:
print "No serial number"
exit(1)
print "Writing serial number"
data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-k': # firmware update key
keyno = sys.argv[2]
fileid = 1 + int(keyno)
filename = sys.argv[3]
f = open(filename)
data = f.read()
f.close()
else:
fileid = 5 # Card holder certificate
filename = sys.argv[1]
f = open(filename)
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
print "Updating card holder certificate"
main(fileid, is_update, data, passwd)

View File

@@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from struct import *
import sys, time, os, binascii, string
import sys, time, os, binascii
from gnuk_token import *
# INPUT: binary file
@@ -39,25 +39,23 @@ def main(fileid, is_update, data, passwd):
for (dev, config, intf) in gnuk_devices():
try:
gnuk = gnuk_token(dev, config, intf)
print "Device: ", dev.filename
print "Configuration: ", config.value
print "Interface: ", intf.interfaceNumber
print("Device: %s" % dev.filename)
print("Configuration: %d" % config.value)
print("Interface: %d" % intf.interfaceNumber)
break
except:
pass
if gnuk.icc_get_status() == 2:
raise ValueError, "No ICC present"
raise ValueError("No ICC present")
elif gnuk.icc_get_status() == 1:
gnuk.icc_power_on()
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_verify(BY_ADMIN, passwd.encode('UTF-8'))
gnuk.cmd_write_binary(fileid, data, is_update)
gnuk.cmd_select_openpgp()
if fileid == 0:
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
for d in data_in_device:
print "%02x" % ord(d),
print
compare(data + '\x00\x00', data_in_device[8:])
print(' '.join([ "%02x" % d for d in data_in_device ]))
compare(data + b'\x00\x00', data_in_device[8:].tostring())
elif fileid >= 1 and fileid <= 4:
data_in_device = gnuk.cmd_read_binary(fileid)
compare(data, data_in_device)
@@ -85,28 +83,28 @@ if __name__ == '__main__':
email = os.environ['EMAIL']
serial_data_hex = None
for line in f.readlines():
field = string.split(line)
field = str.split(line)
if field[0] == email:
serial_data_hex = field[1].replace(':','')
f.close()
if not serial_data_hex:
print "No serial number"
print("No serial number")
exit(1)
print "Writing serial number"
print("Writing serial number")
data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-k': # firmware update key
keyno = sys.argv[2]
fileid = 1 + int(keyno)
filename = sys.argv[3]
f = open(filename)
f = open(filename, "rb")
data = f.read()
f.close()
else:
fileid = 5 # Card holder certificate
filename = sys.argv[1]
f = open(filename)
f = open(filename, "rb")
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
print "Updating card holder certificate"
print("%s: %d" % (filename, len(data)))
print("Updating card holder certificate")
main(fileid, is_update, data, passwd)

View File

@@ -1,112 +0,0 @@
#! /usr/bin/python
"""
gnuk_remove_keys.py - a tool to remove keys in Gnuk Token
Copyright (C) 2012 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/>.
"""
import sys, os, string
# Assume only single CCID device is attached to computer and it's Gnuk Token
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString
def s2l(s):
return [ ord(c) for c in s ]
class GnukToken(object):
def __init__(self):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_put_data_remove(self, tagh, tagl):
apdu = [0x00, 0xda, tagh, tagl, 0]
response, sw1, sw2 = self.connection.transmit(apdu)
return response
def cmd_put_data_key_import_remove(self, keyno):
if keyno == 1:
keyspec = 0xb6 # SIG
elif keyno == 2:
keyspec = 0xb8 # DEC
else:
keyspec = 0xa4 # AUT
apdu = [0x00, 0xdb, 0x3f, 0xff, 4, 0x4d, 0x02, keyspec, 0x00]
response, sw1, sw2 = self.connection.transmit(apdu)
return response
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
def main(passwd):
gnuk = GnukToken()
gnuk.connection.connect()
print "Token:", gnuk.connection.getReader()
print "ATR:", toHexString( gnuk.connection.getATR() )
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_select_openpgp()
gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG
gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG
gnuk.cmd_put_data_key_import_remove(1)
gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC
gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_DEC
gnuk.cmd_put_data_key_import_remove(2)
gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT
gnuk.cmd_put_data_remove(0x00, 0xd0) # KGTIME_AUT
gnuk.cmd_put_data_key_import_remove(3)
gnuk.connection.disconnect()
return 0
if __name__ == '__main__':
passwd = DEFAULT_PW3
if len(sys.argv) > 1 and sys.argv[1] == '-p':
from getpass import getpass
passwd = getpass("Admin password: ")
sys.argv.pop(1)
main(passwd)

View File

@@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os, string
import sys, os
from gnuk_token import *
@@ -36,17 +36,17 @@ def main(passwd):
for (dev, config, intf) in gnuk_devices():
try:
gnuk = gnuk_token(dev, config, intf)
print "Device: ", dev.filename
print "Configuration: ", config.value
print "Interface: ", intf.interfaceNumber
print("Device: %s" % dev.filename)
print("Configuration: %d" % config.value)
print("Interface: %d" % intf.interfaceNumber)
break
except:
pass
if gnuk.icc_get_status() == 2:
raise ValueError, "No ICC present"
raise ValueError("No ICC present")
elif gnuk.icc_get_status() == 1:
gnuk.icc_power_on()
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_verify(BY_ADMIN, passwd.encode('UTF-8'))
gnuk.cmd_select_openpgp()
gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG
gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG

View File

@@ -1,7 +1,8 @@
"""
gnuk_token.py - a library for Gnuk Token
Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
Copyright (C) 2011, 2012, 2013, 2015
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -21,8 +22,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from struct import *
import string, binascii
import binascii
import usb, time
from array import array
# USB class, subclass, protocol
CCID_CLASS = 0x0B
@@ -50,9 +52,6 @@ def iso7816_compose(ins, p1, p2, data, cls=0x00, le=None):
return pack('>BBBBB', cls, ins, p1, p2, data_len) \
+ data + pack('>B', le)
def list_to_string(l):
return string.join([chr(c) for c in l], '')
# This class only supports Gnuk (for now)
class gnuk_token(object):
def __init__(self, device, configuration, interface):
@@ -68,10 +67,6 @@ class gnuk_token(object):
if interface.interfaceSubClass != CCID_SUBCLASS:
raise ValueError("Wrong interface sub class")
self.__devhandle = device.open()
try:
self.__devhandle.setConfiguration(configuration)
except:
pass
self.__devhandle.claimInterface(interface)
self.__devhandle.setAltInterface(0)
@@ -117,7 +112,7 @@ class gnuk_token(object):
def mem_info(self):
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
value = 0, index = 0, buffer = 8,
buffer = 8, value = 0, index = 0,
timeout = 10)
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
@@ -126,7 +121,7 @@ class gnuk_token(object):
def download(self, start, data, verbose=False):
addr = start
addr_end = (start + len(data)) & 0xffffff00
i = (addr - 0x20000000) / 0x100
i = int((addr - 0x20000000) / 0x100)
j = 0
print("start %08x" % addr)
print("end %08x" % addr_end)
@@ -134,9 +129,8 @@ class gnuk_token(object):
if verbose:
print("# %08x: %d : %d" % (addr, i, 256))
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
value = i, index = 0,
buffer = data[j*256:j*256+256],
timeout = 10)
value = i, index = 0, timeout = 10)
i = i+1
j = j+1
addr = addr + 256
@@ -145,22 +139,22 @@ class gnuk_token(object):
if verbose:
print("# %08x: %d : %d" % (addr, i, residue))
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
value = i, index = 0,
buffer = data[j*256:],
timeout = 10)
value = i, index = 0, timeout = 10)
def execute(self, last_addr):
i = (last_addr - 0x20000000) / 0x100
i = int((last_addr - 0x20000000) / 0x100)
o = (last_addr - 0x20000000) % 0x100
self.__devhandle.controlMsg(requestType = 0x40, request = 2,
value = i, index = o, buffer = None,
buffer = None, value = i, index = o,
timeout = 10)
def icc_get_result(self):
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
if len(msg) < 10:
print(msg)
usbmsg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
if len(usbmsg) < 10:
print(usbmsg)
raise ValueError("icc_get_result")
msg = array('B', usbmsg)
msg_type = msg[0]
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
slot = msg[5]
@@ -173,7 +167,7 @@ class gnuk_token(object):
return (status, chain, data)
def icc_get_status(self):
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
msg = icc_compose(0x65, 0, 0, self.__seq, 0, b"")
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
self.increment_seq()
status, chain, data = self.icc_get_result()
@@ -181,16 +175,16 @@ class gnuk_token(object):
return status
def icc_power_on(self):
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
msg = icc_compose(0x62, 0, 0, self.__seq, 0, b"")
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
self.increment_seq()
status, chain, data = self.icc_get_result()
# XXX: check status, chain
self.atr = list_to_string(data) # ATR
self.atr = data
return self.atr
def icc_power_off(self):
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
msg = icc_compose(0x63, 0, 0, self.__seq, 0, b"")
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
self.increment_seq()
status, chain, data = self.icc_get_result()
@@ -212,7 +206,7 @@ class gnuk_token(object):
elif chain == 1:
d = data_rcv
while True:
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, b"")
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
self.increment_seq()
status, chain, data_rcv = self.icc_get_result()
@@ -229,14 +223,14 @@ class gnuk_token(object):
raise ValueError("icc_send_cmd")
def cmd_get_response(self, expected_len):
result = []
result = array('B')
while True:
cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len)
cmd_data = iso7816_compose(0xc0, 0x00, 0x00, b'') + pack('>B', expected_len)
response = self.icc_send_cmd(cmd_data)
result += response[:-2]
sw = response[-2:]
if sw[0] == 0x90 and sw[1] == 0x00:
return list_to_string(result)
return result
elif sw[0] != 0x61:
raise ValueError("%02x%02x" % (sw[0], sw[1]))
else:
@@ -252,7 +246,7 @@ class gnuk_token(object):
return True
def cmd_read_binary(self, fileid):
cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '')
cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, b'')
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError(sw)
@@ -296,21 +290,21 @@ class gnuk_token(object):
count += 1
def cmd_select_openpgp(self):
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, b"\xD2\x76\x00\x01\x24\x01")
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError, sw
raise ValueError(sw)
if not (sw[0] == 0x90 and sw[1] == 0x00):
raise ValueError("%02x%02x" % (sw[0], sw[1]))
return True
def cmd_get_data(self, tagh, tagl):
cmd_data = iso7816_compose(0xca, tagh, tagl, "")
cmd_data = iso7816_compose(0xca, tagh, tagl, b"")
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError, sw
raise ValueError(sw)
if sw[0] == 0x90 and sw[1] == 0x00:
return ""
return array('B')
elif sw[0] != 0x61:
raise ValueError("%02x%02x" % (sw[0], sw[1]))
return self.cmd_get_response(sw[1])
@@ -363,7 +357,7 @@ class gnuk_token(object):
if len(sw) != 2:
raise ValueError(sw)
if sw[0] == 0x90 and sw[1] == 0x00:
return ""
return array('B')
elif sw[0] != 0x61:
raise ValueError("%02x%02x" % (sw[0], sw[1]))
return self.cmd_get_response(sw[1])
@@ -389,24 +383,24 @@ class gnuk_token(object):
if len(sw) != 2:
raise ValueError(sw)
if sw[0] == 0x90 and sw[1] == 0x00:
return ""
return array('B')
elif sw[0] != 0x61:
raise ValueError("%02x%02x" % (sw[0], sw[1]))
return self.cmd_get_response(sw[1])
def cmd_genkey(self, keyno):
if keyno == 1:
data = '\xb6\x00'
data = b'\xb6\x00'
elif keyno == 2:
data = '\xb8\x00'
data = b'\xb8\x00'
else:
data = '\xa4\x00'
data = b'\xa4\x00'
cmd_data = iso7816_compose(0x47, 0x80, 0, data)
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
raise ValueError(sw)
if sw[0] == 0x90 and sw[1] == 0x00:
return ""
return array('B')
elif sw[0] != 0x61:
raise ValueError("%02x%02x" % (sw[0], sw[1]))
pk = self.cmd_get_response(sw[1])
@@ -414,11 +408,11 @@ class gnuk_token(object):
def cmd_get_public_key(self, keyno):
if keyno == 1:
data = '\xb6\x00'
data = b'\xb6\x00'
elif keyno == 2:
data = '\xb8\x00'
data = b'\xb8\x00'
else:
data = '\xa4\x00'
data = b'\xa4\x00'
cmd_data = iso7816_compose(0x47, 0x81, 0, data)
sw = self.icc_send_cmd(cmd_data)
if len(sw) != 2:
@@ -429,22 +423,22 @@ class gnuk_token(object):
return (pk[9:9+256], pk[9+256+2:9+256+2+3])
def cmd_put_data_remove(self, tagh, tagl):
cmd_data = iso7816_compose(0xda, tagh, tagl, "")
cmd_data = iso7816_compose(0xda, tagh, tagl, b"")
sw = self.icc_send_cmd(cmd_data)
if sw[0] != 0x90 and sw[1] != 0x00:
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
raise ValueError("%02x%02x" % (sw[0], sw[1]))
def cmd_put_data_key_import_remove(self, keyno):
if keyno == 1:
keyspec = "\xb6\x00" # SIG
keyspec = b"\xb6\x00" # SIG
elif keyno == 2:
keyspec = "\xb8\x00" # DEC
keyspec = b"\xb8\x00" # DEC
else:
keyspec = "\xa4\x00" # AUT
cmd_data = iso7816_compose(0xdb, 0x3f, 0xff, "\x4d\x02" + keyspec)
keyspec = b"\xa4\x00" # AUT
cmd_data = iso7816_compose(0xdb, 0x3f, 0xff, b"\x4d\x02" + keyspec)
sw = self.icc_send_cmd(cmd_data)
if sw[0] != 0x90 and sw[1] != 0x00:
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
raise ValueError("%02x%02x" % (sw[0], sw[1]))
def cmd_get_challenge(self):
cmd_data = iso7816_compose(0x84, 0x00, 0x00, '')
@@ -478,16 +472,12 @@ class regnual(object):
if intf.interfaceClass != 0xff:
raise ValueError("Wrong interface class")
self.__devhandle = dev.open()
try:
self.__devhandle.setConfiguration(conf)
except:
pass
self.__devhandle.claimInterface(intf)
self.__devhandle.setAltInterface(0)
def mem_info(self):
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
value = 0, index = 0, buffer = 8,
buffer = 8, value = 0, index = 0,
timeout = 10000)
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
@@ -496,7 +486,7 @@ class regnual(object):
def download(self, start, data, verbose=False):
addr = start
addr_end = (start + len(data)) & 0xffffff00
i = (addr - 0x08000000) / 0x100
i = int((addr - 0x08000000) / 0x100)
j = 0
print("start %08x" % addr)
print("end %08x" % addr_end)
@@ -504,23 +494,21 @@ class regnual(object):
if verbose:
print("# %08x: %d: %d : %d" % (addr, i, j, 256))
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
value = 0, index = 0,
buffer = data[j*256:j*256+256],
timeout = 10000)
value = 0, index = 0, timeout = 10000)
crc32code = crc32(data[j*256:j*256+256])
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
value = 0, index = 0, buffer = 4,
buffer = 4, value = 0, index = 0,
timeout = 10000)
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
if (crc32code ^ r_value) != 0xffffffff:
print("failure")
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
value = i, index = 0,
buffer = None,
timeout = 10000)
value = i, index = 0, timeout = 10000)
time.sleep(0.010)
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
value = 0, index = 0, buffer = 4,
buffer = 4, value = 0, index = 0,
timeout = 10000)
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
if r_value == 0:
@@ -533,23 +521,21 @@ class regnual(object):
if verbose:
print("# %08x: %d : %d" % (addr, i, residue))
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
value = 0, index = 0,
buffer = data[j*256:],
timeout = 10000)
crc32code = crc32(data[j*256:].ljust(256,chr(255)))
value = 0, index = 0, timeout = 10000)
crc32code = crc32(data[j*256:].ljust(256,b'\xff'))
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
value = 0, index = 0, buffer = 4,
buffer = 4, value = 0, index = 0,
timeout = 10000)
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
if (crc32code ^ r_value) != 0xffffffff:
print("failure")
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
value = i, index = 0,
buffer = None,
timeout = 10000)
value = i, index = 0, timeout = 10000)
time.sleep(0.010)
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
value = 0, index = 0, buffer = 4,
buffer = 4, value = 0, index = 0,
timeout = 10000)
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
if r_value == 0:
@@ -557,11 +543,11 @@ class regnual(object):
def protect(self):
self.__devhandle.controlMsg(requestType = 0x40, request = 4,
value = 0, index = 0, buffer = None,
buffer = None, value = 0, index = 0,
timeout = 10000)
time.sleep(0.100)
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
value = 0, index = 0, buffer = 4,
buffer = 4, value = 0, index = 0,
timeout = 10000)
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
if r_value == 0:
@@ -569,7 +555,7 @@ class regnual(object):
def finish(self):
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
value = 0, index = 0, buffer = None,
buffer = None, value = 0, index = 0,
timeout = 10000)
def reset_device(self):

View File

@@ -3,7 +3,7 @@
"""
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
Copyright (C) 2012, 2015 Free Software Initiative of Japan
Copyright (C) 2012, 2015 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,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from struct import *
import sys, time, os, binascii, string
import sys, time, os, binascii
# INPUT: binary files (regnual_image, upgrade_firmware_image)
@@ -33,12 +33,6 @@ import usb
from gnuk_token import *
def to_string(t):
result = ""
for c in t:
result += chr(c)
return result
from subprocess import check_output
SHA256_OID_PREFIX="3031300d060960864801650304020105000420"
@@ -79,16 +73,16 @@ def gpg_sign(keygrip, hash):
def main(keyno,keygrip, data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), b'\x00')
crc32code = crc32(data_regnual)
print "CRC32: %04x\n" % crc32code
print("CRC32: %04x\n" % crc32code)
data_regnual += pack('<I', crc32code)
for (dev, config, intf) in gnuk_devices():
try:
icc = gnuk_token(dev, config, intf)
print "Device: ", dev.filename
print "Configuration: ", config.value
print "Interface: ", intf.interfaceNumber
print("Device: %s" % dev.filename)
print("Configuration: %d" % config.value)
print("Interface: %d" % intf.interfaceNumber)
break
except:
icc = None
@@ -97,15 +91,15 @@ def main(keyno,keygrip, data_regnual, data_upgrade):
elif icc.icc_get_status() == 1:
icc.icc_power_on()
icc.cmd_select_openpgp()
challenge = icc.cmd_get_challenge()
signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge)))
challenge = icc.cmd_get_challenge().tostring()
signed = gpg_sign(keygrip, binascii.hexlify(challenge))
icc.cmd_external_authenticate(keyno, signed)
icc.stop_gnuk()
mem_info = icc.mem_info()
print "%08x:%08x" % mem_info
print "Downloading flash upgrade program..."
print("%08x:%08x" % mem_info)
print("Downloading flash upgrade program...")
icc.download(mem_info[0], data_regnual)
print "Run flash upgrade program..."
print("Run flash upgrade program...")
icc.execute(mem_info[0] + len(data_regnual) - 4)
#
time.sleep(3)
@@ -113,20 +107,20 @@ def main(keyno,keygrip, data_regnual, data_upgrade):
del icc
icc = None
#
print "Wait 3 seconds..."
print("Wait 3 seconds...")
time.sleep(3)
# Then, send upgrade program...
reg = None
for dev in gnuk_devices_by_vidpid():
try:
reg = regnual(dev)
print "Device: ", dev.filename
print("Device: %d" % dev.filename)
break
except:
pass
mem_info = reg.mem_info()
print "%08x:%08x" % mem_info
print "Downloading the program"
print("%08x:%08x" % mem_info)
print("Downloading the program")
reg.download(mem_info[0], data_upgrade)
reg.protect()
reg.finish()
@@ -143,12 +137,12 @@ if __name__ == '__main__':
sys.argv.pop(1)
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
f = open(filename_regnual)
f = open(filename_regnual, "rb")
data_regnual = f.read()
f.close()
print "%s: %d" % (filename_regnual, len(data_regnual))
f = open(filename_upgrade)
print("%s: %d" % (filename_regnual, len(data_regnual)))
f = open(filename_upgrade, "rb")
data_upgrade = f.read()
f.close()
print "%s: %d" % (filename_upgrade, len(data_upgrade))
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
main(keyno, keygrip, data_regnual, data_upgrade[4096:])

View File

@@ -1,7 +1,7 @@
"""
gpg_agent.py - a library to connect gpg-agent
Copyright (C) 2013 Free Software Initiative of Japan
Copyright (C) 2013, 2015 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -34,7 +34,7 @@ class gpg_agent(object):
comm_port = os.path.join(home, "gnupg", "S.gpg-agent")
#
f = open(comm_port, "rb", 0)
infostr = f.read()
infostr = f.read().decode('UTF-8')
f.close()
#
info = infostr.split('\n', 1)
@@ -50,17 +50,17 @@ class gpg_agent(object):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(path)
self.sock = s
self.buf_remained = ""
self.buf_remained = b""
self.response = None
def read_line(self):
line = ""
if self.buf_remained != "":
line = b""
if self.buf_remained != b"":
chunk = self.buf_remained
else:
chunk = self.sock.recv(BUFLEN)
while True:
pos = chunk.find('\n')
pos = chunk.find(b'\n')
if pos >= 0:
self.buf_remained = chunk[pos+1:]
line = line + chunk[0:pos]
@@ -71,37 +71,40 @@ class gpg_agent(object):
def get_response(self):
r = self.response
result = ""
result = b""
while True:
i = r.find('%')
i = r.find(b'%')
if i < 0:
result += r
break
hex_str = r[i+1:i+3]
hex_str = r[i+1:i+3].decode('UTF-8')
result += r[0:i]
result += chr(int(hex_str,16))
if bytes == str:
result += chr(int(hex_str,16))
else:
result += bytes.fromhex(hex_str)
r = r[i+3:]
return result
def send_command(self, cmd):
self.sock.send(cmd)
self.response = ""
self.sock.send(cmd.encode('UTF-8'))
self.response = b""
while True:
while True:
l = self.read_line()
if l[0] != '#':
if l[0] != b'#'[0]:
break
if l[0] == 'D':
if l[0] == b'D'[0]:
self.response += l[2:]
elif l[0] == 'O' and l[1] == 'K':
elif l[0:2] == b'OK':
return True
elif l[0] == 'E' and l[1] == 'R' and l[2] == 'R':
elif l[0:3] == b'ERR':
return False
else: # XXX: S, INQUIRE, END
return False
def close(self):
self.sock.send('BYE\n')
self.sock.send(b'BYE\n')
bye = self.read_line()
self.sock.close()
return bye # "OK closing connection"
@@ -109,17 +112,17 @@ class gpg_agent(object):
# Test
if __name__ == '__main__':
g = gpg_agent()
print g.read_line()
print g.send_command("KEYINFO --list --data\n")
kl_str = g.get_response()
print(g.read_line().decode('UTF-8'))
print(g.send_command("KEYINFO --list --data\n"))
kl_str = g.get_response().decode('UTF-8')
kl_str = kl_str[0:-1]
kl = kl_str.split('\n')
import re
kl_o3 = [kg for kg in kl if re.search("OPENPGP\\.3", kg)]
print kl_o3
print(kl_o3)
kg = kl_o3[0].split(' ')[0]
print g.send_command("READKEY %s\n" % kg)
print(g.send_command("READKEY %s\n" % kg))
r = g.get_response()
import binascii
print binascii.hexlify(r)
print g.close()
print(binascii.hexlify(r).decode('UTF-8'))
print(g.close().decode('UTF-8'))

View File

@@ -36,7 +36,7 @@ class intel_hex(object):
memory[addr] = data
prev_addr = addr
prev_data_len = len(data)
self.memory = memory
self.memory = memory
def calc_checksum(self, byte_count, offset, type_code, data):
s = byte_count
@@ -57,19 +57,19 @@ class intel_hex(object):
except:
pass
else:
raise ValueError, "data overwritten (%d)" % self.lineno
raise ValueError("data overwritten (%d)" % self.lineno)
self.memory[address] = data
def parse_line(self, line):
if line[0] != ':':
raise ValueError, "invalid line (%d)" % self.lineno
raise ValueError("invalid line (%d)" % self.lineno)
count = int(line[1:3], 16)
offset = int(line[3:7], 16)
type_code = int(line[7:9], 16)
data = binascii.unhexlify(line[9:(9+count*2)])
check_sum = int(line[(9+count*2):], 16)
if check_sum != self.calc_checksum(count, offset, type_code, data):
raise ValueError, "invalid checksum (%d)" % self.lineno
raise ValueError("invalid checksum (%d)" % self.lineno)
if type_code == 0x00:
self.add_data(count, offset, data)
return 0
@@ -77,18 +77,18 @@ class intel_hex(object):
return 1
elif type_code == 0x04:
if count != 2:
raise ValueError, "invalid count (%d): (%d) Expected 2" \
% (self.lineno, count)
raise ValueError("invalid count (%d): (%d) Expected 2" \
% (self.lineno, count))
self.address = ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16)
return 0
elif type_code == 0x05:
if count != 4:
raise ValueError, "invalid count (%d): (%d) Expected 4" \
% (self.lineno, count)
raise ValueError("invalid count (%d): (%d) Expected 4" \
% (self.lineno, count))
self.start_address \
= ((ord(data[0])&0xff)<<24) + ((ord(data[1])&0xff)<<16) \
+ ((ord(data[2])&0xff)<<8) + ((ord(data[3])&0xff))
return 0
else:
raise ValueError, "invalid type code (%d): (%d)" \
% (self.lineno, type_code)
raise ValueError("invalid type code (%d): (%d)" \
% (self.lineno, type_code))

View File

@@ -434,3 +434,7 @@ if __name__ == '__main__':
# 076b:3821 OmniKey AG CardMan 3821
# OmniKey CardMan 3821 01 00
# Works well with --pinmax 31 --pinmin 1
# 046a:003e Cherry GmbH SmartTerminal ST-2xxx
# Cherry ST-2000
# Needs --add to function properly

View File

@@ -1,5 +1,4 @@
from binascii import hexlify, unhexlify
import string
from os import urandom
def read_key_from_file(file):
@@ -35,8 +34,9 @@ def modinv(a, m):
return x % m
def pkcs1_pad_for_sign(digestinfo):
byte_repr = '\x00' + '\x01' + string.ljust('', 256 - 19 - 32 - 3, '\xff') \
+ '\x00' + digestinfo
byte_repr = b'\x00' + b'\x01' \
+ bytes.ljust(b'', 256 - 19 - 32 - 3, b'\xff') \
+ b'\x00' + digestinfo
return int(hexlify(byte_repr), 16)
def compute_signature(key, digestinfo):
@@ -64,7 +64,7 @@ def integer_to_bytes_256(i):
s = s.rstrip('L')
if len(s) & 1:
s = '0' + s
return string.rjust(unhexlify(s), 256, '\x00')
return bytes.rjust(unhexlify(s), 256, b'\x00')
def get_raw_pubkey(key):
return key[0]

View File

@@ -3,7 +3,7 @@
"""
stlinkv2.py - a tool to control ST-Link/V2
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -26,6 +26,7 @@ from struct import *
import sys, time
import usb
from colorama import init as colorama_init, Fore, Back, Style
from array import array
# INPUT: binary file
@@ -75,12 +76,9 @@ SPI1= 0x40013000
def uint32(v):
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
prog_flash_write_body = "\x0D\x4A" + "\x0B\x48" + "\x0B\x49" + \
"\x09\x4C" + "\x01\x25" + "\x14\x26" + "\x00\x27" + "\x25\x61" + \
"\xC3\x5B" + "\xCB\x53" + "\xE3\x68" + "\x2B\x42" + "\xFC\xD1" + \
"\x33\x42" + "\x02\xD1" + "\x02\x37" + "\x97\x42" + "\xF5\xD1" + \
"\x00\x27" + "\x27\x61" + "\x00\xBE" + "\xC0\x46" + "\x00\x20\x02\x40" + \
"\x3C\x00\x00\x20"
prog_flash_write_body = b"\x0D\x4A\x0B\x48\x0B\x49\x09\x4C\x01\x25\x14\x26\x00\x27\x25\x61" + \
b"\xC3\x5B\xCB\x53\xE3\x68\x2B\x42\xFC\xD1\x33\x42\x02\xD1\x02\x37\x97\x42\xF5\xD1" + \
b"\x00\x27\x27\x61\x00\xBE\xC0\x46\x00\x20\x02\x40\x3C\x00\x00\x20"
# .SRC_ADDR: 0x2000003C
## HERE comes: target_addr in 4-byte
# .TARGET_ADDR
@@ -90,11 +88,9 @@ prog_flash_write_body = "\x0D\x4A" + "\x0B\x48" + "\x0B\x49" + \
def gen_prog_flash_write(addr,size):
return prog_flash_write_body + pack("<I", addr) + pack("<I", size)
prog_option_bytes_write_body = "\x0B\x48" + "\x0A\x49" + "\x08\x4A" + \
"\x10\x23" + "\x01\x24" + "\x13\x61" + "\x08\x80" + "\xD0\x68" + \
"\x20\x42" + "\xFC\xD1" + "\x02\x31" + "\xFF\x20" + "\x08\x80" + \
"\xD0\x68" + "\x20\x42" + "\xFC\xD1" + "\x00\x20" + "\x10\x61" + \
"\x00\xBE" + "\xC0\x46" + "\x00\x20\x02\x40"
prog_option_bytes_write_body = b"\x0B\x48\x0A\x49\x08\x4A\x10\x23\x01\x24\x13\x61\x08\x80\xD0\x68" + \
b"\x20\x42\xFC\xD1\x02\x31\xFF\x20\x08\x80\xD0\x68\x20\x42\xFC\xD1\x00\x20\x10\x61" + \
b"\x00\xBE\xC0\x46\x00\x20\x02\x40"
## HERE comes: target_addr in 4-byte
# .TARGET_ADDR
## HERE comes: option_bytes in 4-byte
@@ -103,9 +99,8 @@ prog_option_bytes_write_body = "\x0B\x48" + "\x0A\x49" + "\x08\x4A" + \
def gen_prog_option_bytes_write(addr,val):
return prog_option_bytes_write_body + pack("<I", addr) + pack("<I", val)
prog_blank_check_body = "\x04\x49" + "\x05\x4A" + "\x08\x68" + "\x01\x30" + \
"\x02\xD1" + "\x04\x31" + "\x91\x42" + "\xF9\xD1" + "\x00\xBE" + \
"\xC0\x46" + "\x00\x00\x00\x08"
prog_blank_check_body = b"\x04\x49\x05\x4A\x08\x68\x01\x30\x02\xD1\x04\x31\x91\x42\xF9\xD1\x00\xBE\xC0\x46" + \
b"\x00\x00\x00\x08"
## HERE comes: end_addr in 4-byte
# .END_ADDR
@@ -120,25 +115,28 @@ BLOCK_WRITE_TIMEOUT=80 # Increase this when you increase BLOCK_SIZE
class TimeOutError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
def __repr__(self):
return "TimeoutError(" + self.msg + ")"
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
def __repr__(self):
return "TimeoutError(" + self.msg + ")"
class OperationFailure(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
def __repr__(self):
return "OperationFailure(" + self.msg + ")"
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
def __repr__(self):
return "OperationFailure(" + self.msg + ")"
class stlinkv2(object):
def __init__(self, dev):
self.__bulkout = 2
if dev.idProduct == USB_VENDOR_STLINKV2:
self.__bulkout = 2
else:
self.__bulkout = 1
self.__bulkin = 0x81
self.__timeout = 1000 # 1 second
@@ -148,11 +146,14 @@ class stlinkv2(object):
if intf.interfaceClass != 0xff: # Vendor specific
raise ValueError("Wrong interface class.", intf.interfaceClass)
self.__devhandle = dev.open()
# ST-Link/V2-1 has other interfaces
# Some other processes or kernel would use it
# So, write access to configuration causes error
try:
self.__devhandle.setConfiguration(conf)
self.__devhandle.setConfiguration(conf.value)
except:
pass
self.__devhandle.claimInterface(intf)
self.__devhandle.claimInterface(intf.interfaceNumber)
# self.__devhandle.setAltInterface(0) # This was not good for libusb-win32 with wrong arg intf, new correct value 0 would be OK
def shutdown(self):
@@ -169,76 +170,76 @@ class stlinkv2(object):
self.__devhandle.bulkWrite(self.__bulkout, data, self.__timeout)
def stl_mode(self):
v = self.execute_get("\xf5\x00", 2)
v = self.execute_get(b"\xf5\x00", 2)
return (v[1] * 256 + v[0])
def exit_from_debug_swd(self):
self.execute_put("\xf2\x21\x00")
self.execute_put(b"\xf2\x21\x00")
time.sleep(1)
def exit_from_dfu(self):
self.execute_put("\xf3\x07\x00")
self.execute_put(b"\xf3\x07\x00")
time.sleep(1)
def exit_from_debug_swim(self):
self.execute_put("\xf4\x01\x00")
self.execute_put(b"\xf4\x01\x00")
time.sleep(1)
def enter_swd(self):
self.execute_put("\xf2\x20\xa3")
self.execute_put(b"\xf2\x20\xa3")
time.sleep(1)
def get_status(self):
v = self.execute_get("\xf2\x01\x00", 2)
v = self.execute_get(b"\xf2\x01\x00", 2)
return (v[1] << 8) + v[0]
# RUN:128, HALT:129
def enter_debug(self):
v = self.execute_get("\xf2\x02\x00", 2)
v = self.execute_get(b"\xf2\x02\x00", 2)
return (v[1] << 8) + v[0]
def exit_debug(self):
self.execute_put("\xf2\x21\x00")
self.execute_put(b"\xf2\x21\x00")
def reset_sys(self):
v = self.execute_get("\xf2\x03\x00", 2)
v = self.execute_get(b"\xf2\x03\x00", 2)
return (v[1] << 8) + v[0]
def read_memory(self, addr, length):
return self.execute_get("\xf2\x07" + pack('<IH', addr, length), length)
return self.execute_get(b"\xf2\x07" + pack('<IH', addr, length), length)
def read_memory_u32(self, addr):
return uint32(self.execute_get("\xf2\x07" + pack('<IH', addr, 4), 4))
return uint32(self.execute_get(b"\xf2\x07" + pack('<IH', addr, 4), 4))
def write_memory(self, addr, data):
return self.execute_put("\xf2\x08" + pack('<IH', addr, len(data)), data)
return self.execute_put(b"\xf2\x08" + pack('<IH', addr, len(data)), data)
def write_memory_u32(self, addr, data):
return self.execute_put("\xf2\x08" + pack('<IH', addr, 4),
return self.execute_put(b"\xf2\x08" + pack('<IH', addr, 4),
pack('<I', data))
def read_reg(self, regno):
return uint32(self.execute_get("\xf2\x05" + pack('<B', regno), 4))
return uint32(self.execute_get(b"\xf2\x05" + pack('<B', regno), 4))
def write_reg(self, regno, value):
return self.execute_get("\xf2\x06" + pack('<BI', regno, value), 2)
return self.execute_get(b"\xf2\x06" + pack('<BI', regno, value), 2)
def write_debug_reg(self, addr, value):
return self.execute_get("\xf2\x35" + pack('<II', addr, value), 2)
return self.execute_get(b"\xf2\x35" + pack('<II', addr, value), 2)
def control_nrst(self, value):
return self.execute_get("\xf2\x3c" + pack('<B', value), 2)
return self.execute_get(b"\xf2\x3c" + pack('<B', value), 2)
def run(self):
v = self.execute_get("\xf2\x09\x00", 2)
v = self.execute_get(b"\xf2\x09\x00", 2)
return (v[1] << 8) + v[0]
def get_core_id(self):
v = self.execute_get("\xf2\x22\x00", 4)
v = self.execute_get(b"\xf2\x22\x00", 4)
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
def version(self):
v = self.execute_get("\xf1", 6)
v = self.execute_get(b"\xf1", 6)
val = (v[0] << 8) + v[1]
return ((val >> 12) & 0x0f, (val >> 6) & 0x3f, val & 0x3f)
@@ -339,7 +340,7 @@ class stlinkv2(object):
def option_bytes_write(self,addr,val):
self.write_memory_u32(FLASH_KEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_KEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY2)
@@ -363,13 +364,13 @@ class stlinkv2(object):
def option_bytes_erase(self):
self.write_memory_u32(FLASH_KEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_KEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_CR, FLASH_CR_OPTER)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER)
self.write_memory_u32(FLASH_CR, FLASH_CR_OPTER)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER)
i = 0
while True:
@@ -381,7 +382,7 @@ class stlinkv2(object):
break
self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK)
if (status & FLASH_SR_EOP) == 0:
if (status & FLASH_SR_EOP) == 0:
raise OperationFailure("option bytes erase")
def flash_write_internal(self, addr, data, off, size):
@@ -404,7 +405,7 @@ class stlinkv2(object):
def flash_write(self, addr, data):
self.write_memory_u32(FLASH_KEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_KEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
off = 0
while True:
@@ -423,10 +424,10 @@ class stlinkv2(object):
def flash_erase_all(self):
self.write_memory_u32(FLASH_KEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_KEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_CR, FLASH_CR_MER)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER)
self.write_memory_u32(FLASH_CR, FLASH_CR_MER)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER)
i = 0
while True:
@@ -440,18 +441,18 @@ class stlinkv2(object):
self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK)
if (status & FLASH_SR_EOP) == 0:
if (status & FLASH_SR_EOP) == 0:
raise OperationFailure("flash erase all")
def flash_erase_page(self, addr):
self.write_memory_u32(FLASH_KEYR, FLASH_KEY1)
self.write_memory_u32(FLASH_KEYR, FLASH_KEY2)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR)
self.write_memory_u32(FLASH_CR, FLASH_CR_PER)
self.write_memory_u32(FLASH_AR, addr)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER)
self.write_memory_u32(FLASH_CR, FLASH_CR_PER)
self.write_memory_u32(FLASH_AR, addr)
self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER)
i = 0
while True:
@@ -464,7 +465,7 @@ class stlinkv2(object):
self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK)
if (status & FLASH_SR_EOP) == 0:
if (status & FLASH_SR_EOP) == 0:
raise OperationFailure("flash page erase")
def start(self):
@@ -543,6 +544,7 @@ class stlinkv2(object):
USB_VENDOR_ST=0x0483 # 0x0483 SGS Thomson Microelectronics
USB_VENDOR_STLINKV2=0x3748 # 0x3748 ST-LINK/V2
USB_VENDOR_STLINKV2_1=0x374b # 0x374b ST-LINK/V2_1
def stlinkv2_devices():
busses = usb.busses()
@@ -551,14 +553,14 @@ def stlinkv2_devices():
for dev in devices:
if dev.idVendor != USB_VENDOR_ST:
continue
if dev.idProduct != USB_VENDOR_STLINKV2:
if dev.idProduct != USB_VENDOR_STLINKV2 and dev.idProduct != USB_VENDOR_STLINKV2_1:
continue
yield dev
def compare(data_original, data_in_device):
i = 0
for d in data_original:
if ord(d) != data_in_device[i]:
if d != data_in_device[i]:
raise ValueError("Verify failed at:", i)
i += 1
@@ -689,7 +691,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
stl.flash_write(0x08000000, data)
print("VERIFY")
data_received = ()
data_received = array('B')
size = len(data)
off = 0
while size > 0:
@@ -697,10 +699,10 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
blk_size = 1024
else:
blk_size = size
data_received = data_received + stl.read_memory(0x08000000+off, blk_size)
data_received = data_received + array('B', stl.read_memory(0x08000000+off, blk_size))
size = size - blk_size
off = off + blk_size
compare(data, data_received)
compare(array('B', data), data_received)
if not no_protect and stl.has_protection():
print("PROTECT")

View File

@@ -32,7 +32,7 @@ BY_ADMIN = 3
KEYNO_FOR_AUTH=2
def main(keyno, passwd, data_regnual, data_upgrade):
def main(wait_e, keyno, passwd, data_regnual, data_upgrade):
l = len(data_regnual)
if (l & 0x03) != 0:
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
@@ -44,11 +44,11 @@ def main(keyno, passwd, data_regnual, data_upgrade):
rsa_raw_pubkey = rsa.get_raw_pubkey(rsa_key)
gnuk = get_gnuk_device()
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_verify(BY_ADMIN, passwd.encode('UTF-8'))
gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False)
gnuk.cmd_select_openpgp()
challenge = gnuk.cmd_get_challenge()
challenge = gnuk.cmd_get_challenge().tostring()
digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge
signed = rsa.compute_signature(rsa_key, digestinfo)
signed_bytes = rsa.integer_to_bytes_256(signed)
@@ -67,17 +67,18 @@ def main(keyno, passwd, data_regnual, data_upgrade):
del gnuk
gnuk = None
#
print("Wait 3 seconds...")
time.sleep(3)
# Then, send upgrade program...
reg = None
for dev in gnuk_devices_by_vidpid():
try:
reg = regnual(dev)
print("Device: %s" % dev.filename)
break
except:
pass
while reg == None:
print("Wait %d seconds..." % wait_e)
time.sleep(wait_e)
for dev in gnuk_devices_by_vidpid():
try:
reg = regnual(dev)
print("Device: %s" % dev.filename)
break
except:
pass
# Then, send upgrade program...
mem_info = reg.mem_info()
print("%08x:%08x" % mem_info)
print("Downloading the program")
@@ -89,6 +90,9 @@ def main(keyno, passwd, data_regnual, data_upgrade):
from getpass import getpass
# This should be event driven, not guessing some period, or polling.
DEFAULT_WAIT_FOR_REENUMERATION=1
if __name__ == '__main__':
if os.getcwd() != os.path.dirname(os.path.abspath(__file__)):
print("Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__)))
@@ -96,11 +100,15 @@ if __name__ == '__main__':
keyno = 0
passwd = None
wait_e = DEFAULT_WAIT_FOR_REENUMERATION
while len(sys.argv) > 3:
option = sys.argv[1]
sys.argv.pop(1)
if option == '-f': # F for Factory setting
passwd = DEFAULT_PW3
elif option == '-e': # E for Enumeration
wait_e = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-k': # K for Key number
keyno = int(sys.argv[1])
sys.argv.pop(1)
@@ -110,13 +118,13 @@ if __name__ == '__main__':
passwd = getpass("Admin password: ")
filename_regnual = sys.argv[1]
filename_upgrade = sys.argv[2]
f = open(filename_regnual)
f = open(filename_regnual,"rb")
data_regnual = f.read()
f.close()
print("%s: %d" % (filename_regnual, len(data_regnual)))
f = open(filename_upgrade)
f = open(filename_upgrade,"rb")
data_upgrade = f.read()
f.close()
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
# First 4096-byte in data_upgrade is SYS, so, skip it.
main(keyno, passwd, data_regnual, data_upgrade[4096:])
main(wait_e, keyno, passwd, data_regnual, data_upgrade[4096:])

View File

@@ -3,7 +3,7 @@
"""
usb_strings.py - a tool to dump USB string
Copyright (C) 2012 Free Software Initiative of Japan
Copyright (C) 2012, 2015 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -27,7 +27,7 @@ import usb, sys
USB_VENDOR_FSIJ=0x234b
USB_PRODUCT_GNUK=0x0000
def gnuk_devices():
def gnuk_devices_by_vidpid():
busses = usb.busses()
for bus in busses:
devices = bus.devices
@@ -41,13 +41,13 @@ def gnuk_devices():
field = ['', 'Vendor', 'Product', 'Serial', 'Revision', 'Config', 'Sys', 'Board']
def main(n):
for dev in gnuk_devices():
for dev in gnuk_devices_by_vidpid():
handle = dev.open()
print "Device: ", dev.filename
print("Device: %s" % dev.filename)
try:
for i in range(1,n):
str = handle.getString(i, 512)
print "%10s: %s" % (field[i], str)
s = handle.getString(i, 512)
print("%10s: %s" % (field[i], s.decode('UTF-8')))
except:
pass
del dev