Compare commits
65 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f86f97cdbe | ||
|
|
1e004bec78 | ||
|
|
d68bee21e5 | ||
|
|
2903e88986 | ||
|
|
25fed157e1 | ||
|
|
d5c5571423 | ||
|
|
51d4b754e6 | ||
|
|
48905155c5 | ||
|
|
772071d1ba | ||
|
|
1fa45e3273 | ||
|
|
1a5eb0ec3b | ||
|
|
106b042e75 | ||
|
|
eebd40d946 | ||
|
|
5e37c7722a | ||
|
|
b1a582e87c | ||
|
|
3f1ee534fe | ||
|
|
522ec3299e | ||
|
|
34e2099b23 | ||
|
|
baf09ecac9 | ||
|
|
db23a1d051 | ||
|
|
3f8c4d1f17 | ||
|
|
1648a538df | ||
|
|
3ffac57509 | ||
|
|
1654a83366 | ||
|
|
022bb44f12 | ||
|
|
03c024f8f6 | ||
|
|
9b7d400550 | ||
|
|
c53bd96eb8 | ||
|
|
1f9e8ca77f | ||
|
|
deeb8aad1c | ||
|
|
f02d7d8565 | ||
|
|
a5f7072a64 | ||
|
|
2c79280441 | ||
|
|
d4d36bebab | ||
|
|
d423678f59 | ||
|
|
4b7cfd04af | ||
|
|
115a7ba67a | ||
|
|
d0e7aad11e | ||
|
|
645f42a890 | ||
|
|
f505dea314 | ||
|
|
748c3cac6c | ||
|
|
fa8bc533a3 | ||
|
|
00062a0ac7 | ||
|
|
c9f88bb9f1 | ||
|
|
482742394d | ||
|
|
05867d84f6 | ||
|
|
92cbb5364a | ||
|
|
61e4551b76 | ||
|
|
254742bc6d | ||
|
|
a6fd40d4fd | ||
|
|
9a11e954d8 | ||
|
|
b2ca03dc19 | ||
|
|
0fb6853fc7 | ||
|
|
94d6208542 | ||
|
|
eb62609c86 | ||
|
|
d596493831 | ||
|
|
70463566bf | ||
|
|
99c55fce60 | ||
|
|
ec2a2e049f | ||
|
|
43331cbeaf | ||
|
|
fbdac6a96a | ||
|
|
9e3af06141 | ||
|
|
1de2f33d23 | ||
|
|
06b364b1ac | ||
|
|
9786da7009 |
260
ChangeLog
260
ChangeLog
@@ -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.
|
||||
|
||||
@@ -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
62
NEWS
@@ -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
151
README
@@ -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
10
THANKS
@@ -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
|
||||
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: bdaae5661d...5458b77d36
@@ -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
131
doc/note/firmware-update-2
Normal 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.
|
||||
--
|
||||
@@ -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 ) );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -12,8 +12,6 @@ MEMORY
|
||||
}
|
||||
|
||||
vector = 0x08000000;
|
||||
_flash_start = 0x08001000;
|
||||
_flash_end = 0x08020000;
|
||||
|
||||
__ram_start__ = ORIGIN(ram0);
|
||||
__ram_size__ = 20k;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
2
src/ac.c
2
src/ac.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
49
src/configure
vendored
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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. */
|
||||
|
||||
34
src/gnuk.h
34
src/gnuk.h
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
204
src/main.c
204
src/main.c
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
48
src/sys.c
48
src/sys.c
@@ -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")))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
145
src/usb_ctrl.c
145
src/usb_ctrl.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:])
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
142
tool/stlinkv2.py
142
tool/stlinkv2.py
@@ -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")
|
||||
|
||||
@@ -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:])
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user