Compare commits

...

37 Commits

Author SHA1 Message Date
NIIBE Yutaka
61e4551b76 Version 1.1.7 2015-08-05 09:56:20 +09:00
NIIBE Yutaka
254742bc6d more change for Python 2015-08-04 12:32:56 +09:00
NIIBE Yutaka
a6fd40d4fd update Chopstx and ADC driver 2015-08-04 11:11:20 +09:00
NIIBE Yutaka
9a11e954d8 More PythonUSB change 2015-08-04 11:11:03 +09:00
NIIBE Yutaka
b2ca03dc19 Python3 fixes 2015-08-03 19:51:50 +09:00
NIIBE Yutaka
0fb6853fc7 more python3 fix 2015-08-03 19:22:02 +09:00
NIIBE Yutaka
94d6208542 More python3 fixes 2015-08-03 16:44:38 +09:00
NIIBE Yutaka
eb62609c86 Add pinpadtest info from Thomas Jarosch 2015-07-31 23:12:01 +09:00
NIIBE Yutaka
d596493831 fix sed script in configure 2015-07-31 23:00:34 +09:00
NIIBE Yutaka
70463566bf update regnual 2015-07-31 16:13:06 +09:00
NIIBE Yutaka
99c55fce60 support ST-Link/V2-1 2015-07-31 16:10:47 +09:00
NIIBE Yutaka
ec2a2e049f stlinkv2.py now works with newer PyUSB 2015-07-28 23:02:33 +09:00
NIIBE Yutaka
43331cbeaf fix for python3 2015-07-28 14:45:18 +09:00
NIIBE Yutaka
fbdac6a96a More USB driver change 2015-07-28 10:18:39 +09:00
NIIBE Yutaka
9e3af06141 USB driver update 2015-07-27 21:16:28 +09:00
NIIBE Yutaka
1de2f33d23 remove PC/SC tools 2015-07-27 18:55:10 +09:00
NIIBE Yutaka
06b364b1ac fix quote in sed scripts 2015-07-23 12:14:18 +09:00
NIIBE Yutaka
9786da7009 Use for \n 2015-07-23 11:18:50 +09:00
NIIBE Yutaka
55ee1cd30f version 1.1.6 2015-07-21 09:25:06 +09:00
NIIBE Yutaka
5f21a44058 ECC keygen 2015-07-20 18:01:21 +09:00
NIIBE Yutaka
edf1a0cdd7 always enable keygen 2015-07-18 13:55:28 +09:00
NIIBE Yutaka
be5c052531 cleanup USB string things 2015-07-16 10:35:08 +09:00
NIIBE Yutaka
e041a2aa7d configure update 2015-07-16 10:19:12 +09:00
NIIBE Yutaka
31c7a42c73 common binary support fix 2015-07-16 09:31:44 +09:00
NIIBE Yutaka
8ddcc1e896 support Board 2015-07-15 16:37:19 +09:00
NIIBE Yutaka
6a8f8dffcb common binary support 2015-07-15 14:29:37 +09:00
NIIBE Yutaka
f2744bec30 upgrade to chopstx 0.07 2015-07-15 14:09:36 +09:00
NIIBE Yutaka
074f479962 update 2015-07-15 14:02:49 +09:00
NIIBE Yutaka
a60fe371a4 improve stlinkv2.py 2015-07-15 14:01:40 +09:00
NIIBE Yutaka
3ea5e54eb9 Add debug test files 2015-07-15 14:01:22 +09:00
NIIBE Yutaka
ed8c41a0ca Support STM32 Primer 2 2015-07-11 17:49:52 +09:00
NIIBE Yutaka
9ed3bb5353 Fix stlinkv2 for STM32F103xE 2015-07-11 17:46:50 +09:00
NIIBE Yutaka
9bbca07033 Curve25519 support 2015-07-08 08:49:05 +09:00
NIIBE Yutaka
9ba59de212 stlinkv2.py: merge Cortex-M0 support for FSM-55 2015-07-06 15:52:04 +09:00
NIIBE Yutaka
35c880fc0c remove boards/ since we have now STM32 Primer2 and CQ STARM 2015-07-06 12:46:45 +09:00
NIIBE Yutaka
7b116d614e update chopstx 2015-06-30 16:07:46 +09:00
NIIBE Yutaka
a73d04cf82 serial number change 2015-06-30 16:03:00 +09:00
68 changed files with 1821 additions and 2105 deletions

31
AUTHORS
View File

@@ -1,35 +1,10 @@
Kaz Kojima:
Added STM32 Primer2 support:
boards/STM32_PRIMER2/board.c
boards/STM32_PRIMER2/board.h
boards/STM32_PRIMER2/mcuconf.h
Added STM32 Primer2 support.
NIIBE Yutaka:
Founder of the project.
Added FST_01 support:
boards/FST_01/board.c
boards/FST_01/board.h
boards/FST_01/mcuconf.h
Added FST_01_00 support:
boards/FST_01_00/board.c
boards/FST_01_00/board.h
boards/FST_01_00/mcuconf.h
Added STBee support:
boards/STBEE/board.c
boards/STBEE/board.h
boards/STBEE/mcuconf.h
Added STM8S Discovery Kit support:
boards/STM8S_DISCOVERY/board.c
boards/STM8S_DISCOVERY/board.h
boards/STM8S_DISCOVERY/mcuconf.h
Added STBee Mini support:
boards/STBEE_MINI/board.c
boards/STBEE_MINI/board.h
boards/STBEE_MINI/mcuconf.h
Added CQ STARM support:
boards/CQ_STARM/board.c
boards/CQ_STARM/board.h
boards/CQ_STARM/mcuconf.h
Wrote tools for STLink/V2:
tool/stlinkv2.py
Wrote tools for DfuSe:
tool/dfuse.py
tool/dump_mem.py

174
ChangeLog
View File

@@ -1,3 +1,177 @@
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.
2015-07-20 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_keygen): Support ECC.
* src/call-ec.c (ecc_check_secret): New.
* src/ecc.c (check_secret): New.
2015-07-18 Niibe Yutaka <gniibe@fsij.org>
* src/configure (keygen): It's always enabled.
* src/openpgp-do.c (gpg_do_keygen): Support key generation.
* src/openpgp.c (cmd_pgp_gakp): Likewise.
* src/call-rsa.c (rsa_genkey): Likewise.
* src/random.c (random_gen): Likewise.
* src/Makefile.in (KEYGEN_SUPPORT): Remove.
* polarssl/include/polarssl/config.h (POLARSSL_GENPRIME): Define.
2015-07-16 Niibe Yutaka <gniibe@fsij.org>
* src/configure (FLASH_PAGE_SIZE, FLASH_SIZE, MEMORY_SIZE)
[sys1_compat]: Use safe values for common binary.
(TARGET_DEFINE): Remove.
2015-07-15 Niibe Yutaka <gniibe@fsij.org>
* tool/usb_strings.py (field): Add 'Board'.
* regnual/regnual.c (usb_cb_get_descriptor): Update.
* src/usb_ctrl.c (usb_cb_interface): Call usb_lld_write.
* src/usb_desc.c (usb_cb_get_descriptor): Support sys_board_name,
using usb_lld_write.
* src/usb_lld.h (usb_cb_get_descriptor): Add last argument length
for asked length.
* src/usb_stm32f103.c (handle_setup0): Allow setup callback to
call usb_lld_write with ENDP0.
* src/usb_conf.h (NUM_STRING_DESC): Remove.
* src/configure [!sys1_compat] (CONFIG): Don't include target
board name.
* src/flash.c: Detect flash_page_size at runtime.
* src/main.c: Remove dependency to board.h.
* src/neug.c: Update from NeuG 1.0.2.
* src/adc_stm32f103.c: Update.
* chopstx: Update to 0.07.
* src/sys.c: Update.
* src/sys.h: Update.
* src/gnuk.ld.in: Update.
* tool/stlinkv2.py (stlinkv2.get_chip_id): New. Detect flash
size, too.
(main): Call stlinkv2.get_chip_id after MCU reset and stop.
Verify read out fix.
2015-07-11 Niibe Yutaka <gniibe@fsij.org>
* src/configure (help): Add STM32_PRIMER2 and CQ_STARM.
* chopstx: Update to 0.06.
* tool/stlinkv2.py: Support 512kB version of STM32F103.
The size of executable file should be even.
2015-07-07 Niibe Yutaka <gniibe@fsij.org>
* src/Makefile.in (CSRC): Add ecc-mont.c.
* src/ecc-mont.c (mod25638_mul_121665): Fix.
(ecdh_compute_public_25519, ecdh_decrypt_curve25519): New.
* src/openpgp.c (cmd_pso): Support ALGO_CURVE25519.
* src/openpgp-do.c (algorithm_attr_cv25519): New.
(rw_algorithm_attr, get_algo_attr_data_object)
(gpg_get_algo_attr_key_size, gpg_do_write_prvkey)
(proc_key_import, gpg_do_public_key): Support ALGO_CURVE25519.
* src/gnuk.h (ALGO_CURVE25519): New.
2015-07-06 Niibe Yutaka <gniibe@fsij.org>
Enhancement for FSM-55.
* tool/stlinkv2.py (stlinkv2.control_nrst): New.
(stlinkv2.get_rdp_key,has_spi_flash,has_protection): New.
(stlinkv2.get_core_id): Rename.
(stlinkv2.blank_check): Use self.flash_size.
(stlinkv2.start): Call control_nrst. Call get_core_id.
Distinguishing chip, and set rdp_key, flash_size and require_nrst.
(stlinkv2.flash_write): Use self.flash_block_size.
(main): Call control_nrst.
(prog_flash_write_body, prog_option_bytes_write_body)
(prog_blank_check_body): Support Cortex-M0.
(main): Call API V2 halt twice.
* tool/asm-thumb/*.S: Updated for Cortex-M0.
2015-06-30 Niibe Yutaka <gniibe@fsij.org>
* src/sys.c: Update from chopstx/example-cdc/sys.c.
* src/main.c (device_initialize_once): Apply change of NeuG.
2015-06-03 Niibe Yutaka <gniibe@fsij.org>
* VERSION: 1.1.5.

34
NEWS
View File

@@ -1,5 +1,37 @@
Gnuk NEWS - User visible changes
* 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, by NIIBE Yutaka
** USB SerialNumber String
The way to determine a serial number of Gnuk Token has been changed.
It uses the 96-bit unique bits of MCU, but the portion for use is
changed.
** Upgrade of Chopstx
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
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.
** No --enable-keygen option
It is now standard feature included always. Note that it doesn't mean
this feature is stable now. It is becoming stable, hopefully.
* Major changes in Gnuk 1.1.5
Released 2015-06-03, by NIIBE Yutaka
@@ -8,7 +40,7 @@ Gnuk NEWS - User visible changes
Since it's getting stable, no debug output any more.
** Maple mini support.
Although it's random number generation is not tested, Maple mini
Although its random number generation is not tested, Maple mini
support is added.
** Windows interoperability fix.

86
README
View File

@@ -1,24 +1,29 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.1.5
2015-06-03
Version 1.1.7
2015-08-05
Niibe Yutaka
Free Software Initiative of Japan
Warning
=======
This is another experimental release of Gnuk, version 1.1.5, which has
This is another experimental release of Gnuk, version 1.1.7, which has
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) and EdDSA with
EdDSA, but this feature is pretty much experimental, and it requires
development version of GnuPG with newest version of libgcrypt. You
will not able to keep using EdDSA keys, as the key format is subject
to change. It also support RSA-4096 experimentally, but users should
know that it takes more than 8 second to sign/decrypt.
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).
It also support RSA-4096 experimentally, but users should know that it
takes more than 8 second to sign/decrypt.
You will not able to keep using Curve25519 keys, as the key format is
subject to change.
What's Gnuk?
@@ -114,31 +119,37 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
and at the tab of "Startup Programs", disable check buttons for
"GPG Password Agent" and "SSH Key Agent".
Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
Qc: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
disable the invocation of gnome-keyring-daemon. In Debian
wheezy, it's in the files /etc/xdg/autostart/gnome-keyring-ssh.desktop
and /etc/xdg/autostart/gnome-keyring-gpg.desktop.
We have a line something like:
OnlyShowIn=GNOME;Unity;MATE;
Please edit this line to:
OnlyShowIn=
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.
Qd: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
Ad: Please set the configration variable OnlyShowIn as none. Like:
OnlyShowIn=
In the files of /etc/xdg/autostart/gnome-keyring-gpg.desktop and
/etc/xdg/autostart/gnome-keyring-ssh.desktop
Release notes
=============
This is third experimental release in version 1.1 series of Gnuk.
This is seventh experimental release in version 1.1 series of Gnuk.
While it is daily use by its developer, some newly introduced features
(including ECDSA/EdDSA, key generation and firmware upgrade) should be
considered experimental. ECDSA/EdDSA is really experimental.
Further, EdDSA is much experimental. You won't be able to keep using
the EdDSA key, as the key format of GnuPG is subject to change.
(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:
@@ -197,6 +208,19 @@ 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
==========
@@ -229,14 +253,14 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 0.04
* chopstx/ -- Chopstx 0.07
We use Chopstx as the kernel for Gnuk.
Chopstx is distributed under GPLv3+ (with a special exception).
* polarssl/ -- PolarSSL 1.2.10
* polarssl/ -- based on PolarSSL 1.2.10 (now mbedTLS)
Souce code taken from: http://polarssl.org/
@@ -356,7 +380,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
@@ -388,11 +413,10 @@ Flying Stone Tiny 01
If you are using Flying Stone Tiny 01, you need a SWD writer.
OpenOCD 0.6.1 now supports ST-Link/V2. We can use it:
OpenOCD 0.9 now supports ST-Link/V2. We can use it:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg
But it doesn't support option bytes handling (protection) yet.
STBee
@@ -449,7 +473,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
...
@@ -457,7 +481,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
...

1
THANKS
View File

@@ -10,6 +10,7 @@ improvements, or fixing bugs. Here is a list of those people.
Achim Pietig achim@pietig.com
Aidan Thornton
Andre Zepezauer andre.zepezauer@student.uni-halle.de
Bertrand Jacquin bertrand@jacquin.bzh
Hironobu SUZUKI hironobu@h2np.net
Jan Suhr jan@suhr.info
Kaz Kojima kkojima@rr.iij4u.or.jp

View File

@@ -1 +1 @@
release/1.1.5
release/1.1.7

View File

@@ -1,10 +0,0 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
/*
* Board-specific initialization code.
*/
void boardInit(void)
{
}

View File

@@ -1,163 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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.
ChibiOS/RT 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/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for the CQ STARM board.
*/
#undef SET_USB_CONDITION /* No functionality to disconnect USB */
#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */
#define GPIO_LED GPIOC_LED
#define IOPORT_LED GPIOC
/*
* Board identifier.
*/
#define BOARD_CQ_STARM
#define BOARD_NAME "CQ STARM"
/*
* Board frequencies.
*/
#define STM32_LSECLK 32768
#define STM32_HSECLK 8000000
/*
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
* native STM32 HAL.
*/
#define STM32F10X_MD
/*
* IO pins assignments.
*/
#define GPIOC_LED 6
#if 0
#define GPIOA_BUTTON 0
#define GPIOA_SPI1NSS 4
#define GPIOB_SPI2NSS 12
#define GPIOC_MMCWP 6
#define GPIOC_MMCCP 7
#define GPIOC_CANCNTL 10
#define GPIOC_DISC 11
#endif
/*
* I/O ports initial setup, this configuration is established soon after reset
* in the initialization code.
*
* The digits have the following meaning:
* 0 - Analog input.
* 1 - Push Pull output 10MHz.
* 2 - Push Pull output 2MHz.
* 3 - Push Pull output 50MHz.
* 4 - Digital input.
* 5 - Open Drain output 10MHz.
* 6 - Open Drain output 2MHz.
* 7 - Open Drain output 50MHz.
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
* 9 - Alternate Push Pull output 10MHz.
* A - Alternate Push Pull output 2MHz.
* B - Alternate Push Pull output 50MHz.
* C - Reserved.
* D - Alternate Open Drain output 10MHz.
* E - Alternate Open Drain output 2MHz.
* F - Alternate Open Drain output 50MHz.
* Please refer to the STM32 Reference Manual for details.
*/
/*
* Port A setup.
* Everything input with pull-up except:
* PA4 - Normal input (ADC_IN4 : VoutX of LIS344ALH).
* PA5 - Alternate output (MMC SPI1 SCK).
* PA6 - Normal input (MMC SPI1 MISO).
* PA7 - Alternate output (MMC SPI1 MOSI).
* PA11 - (USBDM)
* PA12 - (USBDP)
*/
#define VAL_GPIOACRL 0xB4B48888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFF
/*
* Port B setup.
* Everything input with pull-up except:
* PB13 - Alternate output (MMC SPI2 SCK).
* PB14 - Normal input (MMC SPI2 MISO).
* PB15 - Alternate output (MMC SPI2 MOSI).
*/
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0xB4B88888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
* PC4 - Normal input (ADC_IN14 : VoutY of LIS344ALH).
* PC5 - Normal input (ADC_IN15 : VoutZ of LIS344ALH).
* PC6 - Push Pull output (LED).
* (PC9 - SDCard CD)
* (PC12 - SDCard CS)
* PC14 - Normal input (XTAL).
* PC15 - Normal input (XTAL).
*/
#define VAL_GPIOCCRL 0x83448888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x44888888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* (PD9 - USB_DC)
*/
#define VAL_GPIODCRL 0x88888888 /* PD7...PD0 */
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
#define VAL_GPIODODR 0xFFFFFFFF
/*
* Port E setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
#define VAL_GPIOEODR 0xFFFFFFFF
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@@ -1,14 +0,0 @@
/*
* HAL driver system settings.
*/
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 9
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -1,15 +0,0 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
/*
* Board-specific initialization code.
*/
void boardInit(void)
{
/*
* Clear LED and SHUTDOWN output.
*/
palClearPad (IOPORT5, GPIOE_LED);
palClearPad (IOPORT3, GPIOC_SHUTDOWN);
}

View File

@@ -1,175 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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.
ChibiOS/RT 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/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for the STM32 Primer2.
*/
#define SET_USB_CONDITION(en) (!en) /* To connect USB, call palClearPad */
#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */
#define GPIO_USB GPIOD_DISC
#define IOPORT_USB GPIOD
#define GPIO_LED GPIOE_LEDR
#define IOPORT_LED GPIOE
/* NeuG settings for ADC2. */
/*
* Board identifier.
*/
#define BOARD_STM32_PRIMER2
#define BOARD_NAME "STM32 Primer2"
/*
* Board frequencies.
*/
#define STM32_LSECLK 32768
#define STM32_HSECLK 12000000
/*
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
* native STM32 HAL.
*/
#define STM32F10X_MD
/*
* IO pins assignments.
*/
#define GPIOA_BUTTON 8
#define GPIOC_SHUTDOWN 13
#define GPIOD_DISC 3
#define GPIOE_LED 0
#define GPIOE_LEDR 1
/*
* I/O ports initial setup, this configuration is established soon after reset
* in the initialization code.
*
* The digits have the following meaning:
* 0 - Analog input.
* 1 - Push Pull output 10MHz.
* 2 - Push Pull output 2MHz.
* 3 - Push Pull output 50MHz.
* 4 - Digital input.
* 5 - Open Drain output 10MHz.
* 6 - Open Drain output 2MHz.
* 7 - Open Drain output 50MHz.
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
* 9 - Alternate Push Pull output 10MHz.
* A - Alternate Push Pull output 2MHz.
* B - Alternate Push Pull output 50MHz.
* C - Reserved.
* D - Alternate Open Drain output 10MHz.
* E - Alternate Open Drain output 2MHz.
* F - Alternate Open Drain output 50MHz.
* Please refer to the STM32 Reference Manual for details.
*/
/*
* Port A setup.
* Everything input with pull-up except:
* PA0 - Digital input with PullUp. AN0
* PA1 - Digital input with PullUp. AN1
* PA2 - Alternate output (USART2 TX).
* PA3 - Normal input (USART2 RX).
* PA8 - Input with pull-down (PBUTTON).
*/
#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFEFF
/*
* Port B setup.
* Everything input with pull-up except:
* PB13 - Alternate output (AUDIO SPI2 SCK).
* PB14 - Normal input (AUDIO SPI2 MISO).
* PB15 - Alternate output (AUDIO SPI2 MOSI).
*/
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0xB4B88888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
* PC6 - Normal input because there is an external resistor.
* PC7 - Normal input because there is an external resistor.
* PC13 - Push Pull output (SHUTDOWN)
*/
#define VAL_GPIOCCRL 0x44888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* PD3 - Push Pull output (USB_DISCONNECT)
*/
#define VAL_GPIODCRL 0x88883888 /* PD7...PD0 */
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
#define VAL_GPIODODR 0xFFFFFFFF
/*
* Port E setup.
* Everything input with pull-up except:
* PE0 - Push Pull output (LED0).
* PD1 - Push Pull output (LED1).
*/
#define VAL_GPIOECRL 0x88888833 /* PE7...PE0 */
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
#define VAL_GPIOEODR 0xFFFFFFFF
#if 0
/*
* Port F setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOFCRL 0x88888888 /* PF7...PF0 */
#define VAL_GPIOFCRH 0x88888888 /* PF15...PF8 */
#define VAL_GPIOFODR 0xFFFFFFFF
/*
* Port G setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOGCRL 0x88888888 /* PG7...PG0 */
#define VAL_GPIOGCRH 0x88888888 /* PG15...PG8 */
#define VAL_GPIOGODR 0xFFFFFFFF
#endif
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@@ -1,14 +0,0 @@
/*
* HAL driver system settings.
*/
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV2
#define STM32_PLLMUL_VALUE 12
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -1,69 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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.
ChibiOS/RT 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/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#include "ch.h"
#include "hal.h"
#include "config.h"
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
#if HAL_USE_PAL || defined(__DOXYGEN__)
const PALConfig pal_default_config =
{
{VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH},
{VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH},
{VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH},
{VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH},
{VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH},
#if defined(STM32F10X_HD)
{VAL_GPIOFODR, VAL_GPIOFCRL, VAL_GPIOFCRH},
{VAL_GPIOGODR, VAL_GPIOGCRL, VAL_GPIOGCRH},
#endif
};
#endif
/*
* Early initialization code.
* This initialization must be performed just after stack setup and before
* any other initialization.
*/
void
__early_init(void)
{
stm32_clock_init();
}
const uint8_t *
unique_device_id (void)
{
/* STM32F103 has 96-bit unique device identifier */
const uint8_t *addr = (const uint8_t *)0x1ffff7e8;
return addr;
}

View File

@@ -1,116 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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.
ChibiOS/RT 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/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/*
* STM32 drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the driver
* is enabled in halconf.h.
*
* IRQ priorities:
* 15...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED FALSE
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_USB_CLOCK_REQUIRED TRUE
#define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
/*
* ADC driver system settings.
*/
#define USE_STM32_ADC1 TRUE
#define STM32_ADC1_DMA_PRIORITY 3
#define STM32_ADC1_IRQ_PRIORITY 5
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
/*
* CAN driver system settings.
*/
#define USE_STM32_CAN1 FALSE
#define STM32_CAN1_IRQ_PRIORITY 11
/*
* PWM driver system settings.
*/
#define USE_STM32_PWM1 FALSE
#define USE_STM32_PWM2 FALSE
#define USE_STM32_PWM3 FALSE
#define USE_STM32_PWM4 FALSE
#define STM32_PWM1_IRQ_PRIORITY 7
#define STM32_PWM2_IRQ_PRIORITY 7
#define STM32_PWM3_IRQ_PRIORITY 7
#define STM32_PWM4_IRQ_PRIORITY 7
/*
* SERIAL driver system settings.
*/
#define USE_STM32_USART1 FALSE
#define USE_STM32_USART2 FALSE
#define USE_STM32_USART3 FALSE
#if defined(STM32F10X_HD) || defined(STM32F10X_CL)
#define USE_STM32_UART4 FALSE
#define USE_STM32_UART5 FALSE
#endif
#define STM32_USART1_PRIORITY 12
#define STM32_USART2_PRIORITY 12
#define STM32_USART3_PRIORITY 12
#if defined(STM32F10X_HD) || defined(STM32F10X_CL)
#define STM32_UART4_PRIORITY 12
#define STM32_UART5_PRIORITY 12
#endif
/*
* SPI driver system settings.
*/
#define USE_STM32_SPI1 FALSE
#define USE_STM32_SPI2 FALSE
#define STM32_SPI1_DMA_PRIORITY 2
#define STM32_SPI2_DMA_PRIORITY 2
#define STM32_SPI1_IRQ_PRIORITY 10
#define STM32_SPI2_IRQ_PRIORITY 10
#define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt()
/*
* USB driver system settings.
*/
#define STM32_USB_USE_USB1 TRUE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY 6
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14

Submodule chopstx updated: fc26cf0889...218102c5c4

View File

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

220
misc/debug-bn.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* debug-bn.c - Debug Bignum
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "bn.h"
void
print_le_bn256 (const bn256 *X)
{
int i;
const uint8_t *p = (const uint8_t *)X;
for (i = 0; i < 32; i++)
printf ("%02x", p[i]);
puts ("");
}
void
print_be_bn256 (const bn256 *X)
{
int i;
for (i = 7; i >= 0; i--)
printf ("%08x", X->word[i]);
puts ("");
}
#define MAXLINE 4096
static int lineno;
static int test_no;
static bn256 sk[1];
static bn256 pk[1];
static unsigned char msg[MAXLINE];
static size_t msglen;
static bn512 sig[1];
const char *
skip_white_space (const char *l)
{
while (*l != '\n' && isspace (*l))
l++;
return l;
}
static int
read_hex_4bit (char c)
{
int r;
if (c >= '0' && c <= '9')
r = c - '0';
else if (c >= 'a' && c <= 'f')
r = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
r = c - 'A' + 10;
else
r = -1;
return r;
}
static int
read_hex_8bit (const char **l_p)
{
const char *l = *l_p;
int r, v;
r = read_hex_4bit (*l++);
if (r < 0)
return -1;
v = r*16;
r = read_hex_4bit (*l++);
if (r < 0)
return -1;
v += r;
*l_p = l;
return v;
}
static int
read_msg (unsigned char *msg, const char *l, int len)
{
int i, r;
for (i = 0; i < len; i++)
{
r = read_hex_8bit (&l);
if (r < 0)
return -1;
msg[i] = r;
}
return 0;
}
static int
read_le_bn256 (bn256 *sk, const char *l)
{
int i;
uint8_t *p = (uint8_t *)sk;
for (i = 0; i < sizeof (bn256); i++)
{
int r;
if (*l == '\n')
{
/* should support small input??? */
return -1;
}
r = read_hex_8bit (&l);
if (r < 0)
return -1;
p[i] = r;
}
return 0;
}
static int
read_be_bn256 (bn256 *sk, const char *l)
{
int i;
uint8_t *p = (uint8_t *)sk;
for (i = 0; i < sizeof (bn256); i++)
{
int r;
if (*l == '\n')
{
/* should support small input??? */
return -1;
}
r = read_hex_8bit (&l);
if (r < 0)
return -1;
p[31 - i] = r;
}
return 0;
}
static int
read_pk (bn256 *pk, const char *l, int len)
{
int r;
if (len == 64) /* 64 chars == 32-byte */
{ /* compressed form */
r = read_le_bn256 (pk, l);
if (r < 0)
return -1;
return 0;
}
else
{
bn256 x[1];
r = read_hex_8bit (&l);
if (r < 0)
return -1;
if (r != 4)
return -1;
r = read_be_bn256 (x, l);
if (r < 0)
return -1;
r = read_be_bn256 (pk, l+64);
if (r < 0)
return -1;
pk->word[7] ^= (x->word[0] & 1) * 0x80000000;
return 0;
}
}
static int
read_le_bn512 (bn512 *sig, const char *l)
{
int i;
uint8_t *p = (uint8_t *)sig;
for (i = 0; i < sizeof (bn512); i++)
{
int r;
if (*l == '\n')
{
/* should support small input??? */
return -1;
}
r = read_hex_8bit (&l);
if (r < 0)
return -1;
p[i] = r;
}
return 0;
}

92
misc/t-mont.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* t-eddsa.c - testing EdDSA
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* Run following commands. The file t-ed25519.inp is available in GNU
* libgcrypt source code under 'tests' directory.
gcc -Wall -c -DBN256_C_IMPLEMENTATION ecc-mont.c
gcc -Wall -c -DBN256_NO_RANDOM -DBN256_C_IMPLEMENTATION bn.c
gcc -Wall -c mod.c
gcc -Wall -c -DBN256_C_IMPLEMENTATION mod25638.c
gcc -Wall -c t-mont.c
gcc -Wall -c debug-bn.c
gcc -o t-mont t-mont.o ecc-mont.o bn.o mod.o mod25638.o debug-bn.o
*
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "bn.h"
const uint8_t k[32] = {
0x30, 0x01, 0x33, 0xE7, 0xDC, 0x52, 0xAD, 0x9F,
0x89, 0xFE, 0xC0, 0x59, 0x4A, 0x6D, 0x65, 0xE5,
0xF8, 0x7A, 0xD6, 0xA9, 0xA4, 0x89, 0x00, 0xB1,
0x93, 0x7E, 0xD3, 0x6F, 0x09, 0x1E, 0xB7, 0x76,
};
int
main (int argc, char *argv[])
{
int all_good = 1;
int r;
bn256 *pk;
bn256 a[1];
uint8_t out[32];
extern void ecdh_decrypt_curve25519 (const uint8_t *input,
uint8_t *output,
const bn256 *k);
extern uint8_t *ecdh_compute_public_25519 (const uint8_t*k);
extern void print_le_bn256 (const bn256 *X);
while (1)
{
#if 0
hash[0] &= 248;
hash[31] &= 127;
hash[31] |= 64;
memcpy (a, hash, sizeof (bn256)); /* Lower half of hash */
#endif
pk = ecdh_compute_public_25519 (k);
print_le_bn256 (pk);
return 0;
#if 0
if (memcmp (pk, pk_calculated, sizeof (bn256)) != 0)
{
printf ("ERR PK: %d\n", test_no);
print_be_bn256 (sk);
print_be_bn256 (pk);
print_be_bn256 (pk_calculated);
all_good = 0;
continue;
}
ecdh_decrypt_25519 (msg, out, a);
if (memcmp (sig, R, sizeof (bn256)) != 0
|| memcmp (((const uint8_t *)sig)+32, S, sizeof (bn256)) != 0)
{
printf ("ERR SIG: %d\n", test_no);
print_le_bn256 (R);
print_le_bn256 (S);
print_le_bn256 ((const bn256 *)sig);
print_le_bn256 ((const bn256 *)(((const uint8_t *)sig)+32));
all_good = 0;
continue;
}
printf ("%d\n", test_no);
#endif
}
return all_good == 1?0:1;
}

View File

@@ -209,9 +209,7 @@
*
* Enable the RSA prime-number generation code.
*/
#ifdef KEYGEN_SUPPORT
#define POLARSSL_GENPRIME
#endif
/**
* \def POLARSSL_FS_IO

View File

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

View File

@@ -1,7 +1,8 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2012, 2013, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -32,12 +33,18 @@
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)
@@ -166,8 +173,7 @@ 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, uint16_t value)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -175,24 +181,21 @@ void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
{
if (req_no == USB_REGNUAL_SEND && 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);
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 && 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 && 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 control_info *detail)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -202,45 +205,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), detail);
}
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), detail);
}
else /* SETUP_SET */
{
if (req_no == USB_REGNUAL_SEND)
{
if (value != 0 || index + len > 256)
if (detail->value != 0 || detail->index + detail->len > 256)
return USB_UNSUPPORT;
if (index + len < 256)
memset ((uint8_t *)mem + index + len, 0xff,
256 - (index + len));
if (detail->index + detail->len < 256)
memset ((uint8_t *)mem + detail->index + detail->len, 0xff,
256 - (detail->index + detail->len));
usb_lld_set_data_to_recv (mem + index, len);
usb_lld_set_data_to_recv (mem + detail->index, detail->len);
return USB_SUCCESS;
}
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
else if (req_no == USB_REGNUAL_FLASH && detail->len == 0
&& detail->index == 0)
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
uint32_t dst_addr = (0x08000000 + detail->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 && detail->len == 0
&& detail->value == 0 && detail->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 && detail->len == 0
&& detail->value == 0 && detail->index == 0)
return USB_SUCCESS;
}
}
@@ -250,24 +250,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)
struct control_info *detail)
{
(void)index;
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), detail);
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), detail);
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -280,12 +273,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;
@@ -295,8 +288,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, detail);
}
return USB_UNSUPPORT;
@@ -318,9 +310,9 @@ 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 control_info *detail)
{
(void)cmd; (void)interface; (void)alt;
(void)cmd; (void)detail;
return USB_UNSUPPORT;
}
@@ -342,6 +334,7 @@ main (int argc, char *argv[])
set_led (0);
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
usb_lld_init (regnual_config_desc[7]);
while (1)

View File

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

View File

@@ -15,7 +15,7 @@ CSRC = main.c usb_stm32f103.c adc_stm32f103.c \
bn.c mod.c \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
mod25638.c ecc-edwards.c sha512.c \
mod25638.c ecc-edwards.c ecc-mont.c sha512.c \
random.c neug.c sha256.c sys.c
INCDIR =
@@ -55,7 +55,7 @@ OBJCOPY = $(CROSS)objcopy
MCU = cortex-m3
CWARN = -Wall -Wextra -Wstrict-prototypes
# DEFS: Add
DEFS = @KEYGEN_SUPPORT@ @HAVE_SYS_H@
DEFS = @HAVE_SYS_H@
OPT = -O3 -Os -g
LIBS =

View File

@@ -3,7 +3,8 @@
* In this ADC driver, there are NeuG specific parts.
* You need to modify to use this as generic ADC driver.
*
* 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 NeuG, a True Random Number Generator
@@ -92,15 +93,6 @@
| ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
#define NEUG_ADC_SETTING1_NUM_CHANNELS 4
#if !defined(NEUG_ADC_SETTING2_SMPR1)
#define NEUG_ADC_SETTING2_SMPR1 0
#define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5) \
| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0) \
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1)
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
#endif
/*
* Do calibration for both of ADCs.
@@ -133,9 +125,69 @@ void adc_init (void)
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
}
#include "sys.h"
#if defined(HAVE_SYS_H)
# define SYS_BOARD_ID sys_board_id
#else
# include "board.h"
# define SYS_BOARD_ID BOARD_ID
#endif
static void
get_adc_config (uint32_t config[4])
{
config[2] = ADC_SQR1_NUM_CH(2);
switch (SYS_BOARD_ID)
{
case BOARD_ID_FST_01:
config[0] = 0;
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
break;
case BOARD_ID_OLIMEX_STM32_H103:
case BOARD_ID_STBEE:
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)
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11);
break;
case BOARD_ID_STBEE_MINI:
config[0] = 0;
config[1] = ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5);
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1)
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
break;
case BOARD_ID_CQ_STARM:
case BOARD_ID_FST_01_00:
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:
default:
config[0] = 0;
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5);
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1);
break;
}
}
void adc_start (void)
{
uint32_t config[4];
get_adc_config (config);
/* Use DMA channel 1. */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
@@ -156,11 +208,11 @@ void adc_start (void)
ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
| ADC_CR1_SCAN);
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC2->SMPR1 = NEUG_ADC_SETTING2_SMPR1;
ADC2->SMPR2 = NEUG_ADC_SETTING2_SMPR2;
ADC2->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING2_NUM_CHANNELS);
ADC2->SMPR1 = config[0];
ADC2->SMPR2 = config[1];
ADC2->SQR1 = config[2];
ADC2->SQR2 = 0;
ADC2->SQR3 = NEUG_ADC_SETTING2_SQR3;
ADC2->SQR3 = config[3];
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
/*

View File

@@ -124,3 +124,20 @@ FUNC(ecdh_decrypt) (const uint8_t *input, uint8_t *output,
return r;
}
/**
* @brief Check if a secret d0 is valid or not
*
* @param D0 scalar D0: secret
* @param D1 scalar D1: secret candidate N-D0
*
* Return 0 on error.
* Return -1 when D1 should be used as the secret
* Return 1 when D0 should be used as the secret
*/
int
FUNC(ecc_check_secret) (const uint8_t *d0, uint8_t *d1)
{
return FUNC(check_secret) ((const bn256 *)d0, (bn256 *)d1);
}

View File

@@ -204,7 +204,6 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
#define RSA_EXPONENT 0x10001
#ifdef KEYGEN_SUPPORT
uint8_t *
rsa_genkey (int pubkey_len)
{
@@ -245,4 +244,3 @@ rsa_genkey (int pubkey_len)
else
return p_q_modulus;
}
#endif

View File

@@ -7,4 +7,4 @@
@PINPAD_MORE_DEFINE@
@CERTDO_DEFINE@
@HID_CARD_CHANGE_DEFINE@
@SERIALNO_STR_LEN@
@SERIALNO_STR_LEN_DEFINE@

165
src/configure vendored
View File

@@ -1,5 +1,8 @@
#! /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
#
@@ -27,12 +30,18 @@ target=FST_01
verbose=no
with_dfu=default
debug=no
sys1_compat=yes
pinpad=no
certdo=no
keygen=no
sys1_compat=yes
hid_card_change=no
# Revision number
if test -d ../.git; then
REVISION=`git describe --dirty="-modified"`
else
REVISION=`cat ../VERSION`
fi
# Process each option
for option; do
case $option in
@@ -61,18 +70,14 @@ for option; do
certdo=yes ;;
--disable-certdo)
certdo=no ;;
--enable-keygen)
keygen=yes ;;
--disable-keygen)
keygen=no ;;
--enable-sys1-compat)
sys1_compat=yes ;;
--disable-sys1-compat)
sys1_compat=no ;;
--enable-hid-card-change)
hid_card_change=yes ;;
--disable-hid-card-change)
hid_card_change=no ;;
--enable-sys1-compat)
sys1_compat=yes ;;
--disable-sys1-compat)
sys1_compat=no ;;
--with-dfu)
with_dfu=yes ;;
--without-dfu)
@@ -98,15 +103,16 @@ Configuration:
supported targets are:
FST_01
OLIMEX_STM32_H103
STM32_PRIMER2
STBEE
STBEE_MINI
MAPLE_MINI
CQ_STARM
FST_01_00 (unreleased version with 8MHz XTAL)
--enable-debug debug with virtual COM port [no]
--enable-pinpad=cir
PIN entry support [no]
--enable-certdo support CERT.3 data object [no]
--enable-keygen support key generation [no]
--enable-sys1-compat enable SYS 1.0 compatibility [yes]
executable is target dependent
--disable-sys1-compat disable SYS 1.0 compatibility [no]
@@ -122,14 +128,13 @@ if test "$vidpid" = "none"; then
exit 1
fi
TARGET_DEFINE="#define BOARD_$target 1"
BOARD_HEADER_FILE=board-`echo $target | tr '_[:upper:]' '-[:lower:]'`.h
echo Header file is: $BOARD_HEADER_FILE
ln -sf ../chopstx/board/$BOARD_HEADER_FILE board.h
# Flash page size in byte
FLASH_PAGE_SIZE=1024
# Flash memory size in KB
# Flash memory size in KiB
FLASH_SIZE=128
# Memory size in KiB
MEMORY_SIZE=20
@@ -173,7 +178,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 enable this."
echo "FST-01 doesn't have DFU loader, you should not use --with-dfu."
exit 1
fi
echo "Configured for DFU"
@@ -220,15 +225,6 @@ else
echo "CERT.3 Data Object is NOT supported"
fi
# --enable-keygen option
if test "$keygen" = "yes"; then
KEYGEN_SUPPORT="-DKEYGEN_SUPPORT"
echo "Key generation on device is supported"
else
KEYGEN_SUPPORT=""
echo "Key generation on device is NOT supported"
fi
# --enable-hid-card-change option
if test "$hid_card_change" = "yes"; then
HID_CARD_CHANGE_DEFINE="#define HID_CARD_CHANGE_SUPPORT 1"
@@ -238,65 +234,82 @@ else
echo "Card insert/removal by HID device is NOT supported"
fi
if test -d ../.git; then
REVISION=`git describe --dirty="-modified"`
else
REVISION=`cat ../VERSION`
fi
### !!! Replace following string of "FSIJ" to yours !!! ####
SERIALNO="FSIJ-`cat ../VERSION | sed -e 's%^[^/]*/%%'`-"
SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:keygen=$keygen"
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."
exit 1
fi
# Override settings for common binary. Safer side.
FLASH_PAGE_SIZE=2048
FLASH_SIZE=128
MEMORY_SIZE=20
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo"
fi
output_vid_pid_version () {
echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\\${nl} 0x\4, 0x\3, /* idProduct */%p"
echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
}
output_vendor_product_serial_strings () {
prefix=$1
echo "static const uint8_t ${prefix}string_vendor[] = {"
echo " ${#VENDOR}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Manufacturer: \"$VENDOR\" */"
echo $VENDOR | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
if test -n "$prefix"; then
echo
echo "uint8_t ${prefix}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo '};'
echo
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 " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo '#endif'
fi
}
if !(IFS=" "
while read VIDPID VERSION PRODUCT VENDOR; do
if test "$vidpid" = "$VIDPID"; then
(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 $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
) > usb-vid-pid-ver.c.inc
(echo 'static const uint8_t gnukStringVendor[] = {'
echo " ${#VENDOR}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* 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 '};'
echo
echo 'static const uint8_t gnukStringProduct[] = {'
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* 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 '};'
echo
echo 'const uint8_t gnukStringSerial[] = {'
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* 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 " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo '};'
echo
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo 'static const uint8_t gnuk_revision_detail[] = {'
echo " ${#REVISION}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* 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 '};'
echo
echo 'static const uint8_t gnuk_config_options[] = {'
echo " ${#CONFIG}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* 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 '};'
echo '#endif'
) >usb-strings.c.inc
output_vid_pid_version > usb-vid-pid-ver.c.inc
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
exit 0
fi
done; exit 1) < ../GNUK_USB_DEVICE_ID
@@ -307,8 +320,8 @@ then
fi
if test "$sys1_compat" = "no"; then
# Disable when you are sure that it's sys version 2.0.
# Note that Gnuk 1.0 and Neug (until 0.06) uses sys version 1.0.
# Disable when you are sure that it's sys version 2.1.
# Note that Gnuk 1.0 and NeuG (until 0.06) uses sys version 1.0.
# Disabling the compatibility, executable will be target independent,
# assuming the clock initialization will be done by SYS (before entry).
have_sys_h="-DHAVE_SYS_H"
@@ -316,10 +329,10 @@ else
have_sys_h=""
fi
sed -e "s%@HAVE_SYS_H@%$have_sys_h%" \
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
-e "s%@KEYGEN_SUPPORT@%$KEYGEN_SUPPORT%" \
-e "s%@HEXOUTPUT_MAKE_OPTION@%$HEXOUTPUT_MAKE_OPTION%" \
< Makefile.in > Makefile
if test "$certdo" = "yes"; then
@@ -347,6 +360,6 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_DEFINE/" \
-e "s/@SERIALNO_STR_LEN@/$SERIALNO_STR_LEN_DEFINE/" \
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
< config.h.in > config.h
exit 0

View File

@@ -1,4 +1,4 @@
int compute_kP_p256k1 (ac *X, const bn256 *K, const ac *P);
int compute_kG_p256k1 (ac *X, const bn256 *K);
void ecdsa_p256k1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
int check_secret_p256k1 (const bn256 *q, bn256 *d1);

View File

@@ -1,5 +1,4 @@
int compute_kP_p256r1 (ac *X, const bn256 *K, const ac *P);
int compute_kG_p256r1 (ac *X, const bn256 *K);
void ecdsa_p256r1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
int check_secret_p256r1 (const bn256 *q, bn256 *d1);

View File

@@ -2,7 +2,7 @@
* ecc-mont.c - Elliptic curve computation for
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Copyright (C) 2014, 2015 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "bn.h"
#include "mod25638.h"
#include "mod.h"
@@ -78,6 +79,7 @@ mod25638_mul_121665 (bn256 *x, const bn256 *a)
s = a->word;
d = x->word;
memset (d, 0, sizeof (bn256));
w = 121665;
MULADD_256_ASM (s, d, w, c);
#else
@@ -143,7 +145,7 @@ mont_d_and_a (pt *prd, pt *sum, pt *q0, pt *q1, const bn256 *dif_x)
* @param Q_X x-coordinate of Q
*
*/
void
static void
compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
{
int i, j;
@@ -194,3 +196,37 @@ compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
mod25638_mul (res, res, p0->x);
mod25519_reduce (res);
}
uint8_t *
ecdh_compute_public_25519 (const uint8_t *key_data)
{
uint8_t *p;
bn256 gx[1];
bn256 k[1];
memset (gx, 0, sizeof (bn256));
gx[0].word[0] = 9; /* Gx = 9 */
memcpy (k, key_data, sizeof (bn256));
p = (uint8_t *)malloc (sizeof (bn256));
if (p == NULL)
return NULL;
compute_nQ ((bn256 *)p, k, gx);
return p;
}
int
ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data)
{
bn256 q_x[1];
bn256 k[1];
bn256 shared[1];
memcpy (q_x, input, sizeof (bn256));
memcpy (k, key_data, sizeof (bn256));
compute_nQ (shared, k, q_x);
memcpy (output, shared, sizeof (bn256));
return 0;
}

View File

@@ -1,7 +1,8 @@
/* -*- coding: utf-8 -*-
* ecc.c - Elliptic curve over GF(prime)
*
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
* Copyright (C) 2011, 2013, 2014, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -366,3 +367,32 @@ FUNC(ecdsa) (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
#undef tmp_k
#undef borrow
}
/**
* @brief Check if a secret d0 is valid or not
*
* @param D0 scalar D0: secret
* @param D1 scalar D1: secret candidate N-D0
*
* Return 0 on error.
* Return -1 when D1 should be used as the secret
* Return 1 when D0 should be used as the secret
*/
int
FUNC(check_secret) (const bn256 *d0, bn256 *d1)
{
ac Q0[1], Q1[1];
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) <= 0)
/* == 0 or >= N, it's not valid. */
return 0;
FUNC(compute_kG) (Q0, d0);
FUNC(compute_kG) (Q1, d1);
/*
* Jivsov compliant key check
*/
return bn256_cmp (Q1[0].y, Q0[0].y);
}

View File

@@ -1,7 +1,7 @@
/*
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -35,7 +35,6 @@
#include "config.h"
#include "board.h"
#include "sys.h"
#include "gnuk.h"
@@ -65,7 +64,9 @@
*/
#define FLASH_DATA_POOL_HEADER_SIZE 2
#define FLASH_DATA_POOL_SIZE (FLASH_PAGE_SIZE*2)
#define FLASH_DATA_POOL_SIZE (flash_page_size*2)
static uint16_t flash_page_size;
static const uint8_t *data_pool;
extern uint8_t _keystore_pool;
@@ -99,22 +100,30 @@ static int key_available_at (const uint8_t *k, int key_size)
return 1;
}
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
const uint8_t *
flash_init (void)
{
uint16_t gen0, gen1;
uint16_t *gen0_p = (uint16_t *)&_data_pool;
uint16_t *gen1_p = (uint16_t *)(&_data_pool + FLASH_PAGE_SIZE);
uint16_t *gen1_p;
flash_page_size = 1024;
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
flash_page_size = 2048;
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
/* Check data pool generation and choose the page */
gen0 = *gen0_p;
gen1 = *gen1_p;
if (gen0 == 0xffff)
data_pool = &_data_pool + FLASH_PAGE_SIZE;
data_pool = &_data_pool + flash_page_size;
else if (gen1 == 0xffff)
data_pool = &_data_pool;
else if (gen1 > gen0)
data_pool = &_data_pool + FLASH_PAGE_SIZE;
data_pool = &_data_pool + flash_page_size;
else
data_pool = &_data_pool;
@@ -135,7 +144,7 @@ flash_init_keys (void)
int key_size = gpg_get_algo_attr_key_size (i, GPG_KEY_STORAGE);
kd[i].pubkey = NULL;
for (k = p; k < p + FLASH_PAGE_SIZE; k += key_size)
for (k = p; k < p + flash_page_size; k += key_size)
if (key_available_at (k, key_size))
{
int prv_len = gpg_get_algo_attr_key_size (i, GPG_KEY_PRIVATE);
@@ -144,7 +153,7 @@ flash_init_keys (void)
break;
}
p += FLASH_PAGE_SIZE;
p += flash_page_size;
}
}
@@ -189,11 +198,11 @@ flash_copying_gc (void)
if (data_pool == &_data_pool)
{
src = &_data_pool;
dst = &_data_pool + FLASH_PAGE_SIZE;
dst = &_data_pool + flash_page_size;
}
else
{
src = &_data_pool + FLASH_PAGE_SIZE;
src = &_data_pool + flash_page_size;
dst = &_data_pool;
}
@@ -208,7 +217,7 @@ flash_copying_gc (void)
static int
is_data_pool_full (size_t size)
{
return last_p + size > data_pool + FLASH_PAGE_SIZE;
return last_p + size > data_pool + flash_page_size;
}
static uint8_t *
@@ -322,7 +331,7 @@ static uint8_t *
flash_key_getpage (enum kind_of_key kk)
{
/* There is a page for each KK. */
return &_keystore_pool + (FLASH_PAGE_SIZE * kk);
return &_keystore_pool + (flash_page_size * kk);
}
uint8_t *
@@ -333,7 +342,7 @@ flash_key_alloc (enum kind_of_key kk)
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
/* Seek free space in the page. */
for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += key_size)
for (k = k0; k < k0 + flash_page_size; k += key_size)
{
const uint32_t *p = (const uint32_t *)k;
@@ -382,10 +391,10 @@ flash_key_write (uint8_t *key_addr,
static int
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
{
uint32_t start = (uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1);
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
const uint32_t *p = (const uint32_t *)start;
while (p < (const uint32_t *)(start + FLASH_PAGE_SIZE))
while (p < (const uint32_t *)(start + flash_page_size))
if (p == (const uint32_t *)key_addr)
p += key_size/4;
else
@@ -411,7 +420,7 @@ void
flash_key_release (uint8_t *key_addr, int key_size)
{
if (flash_check_all_other_keys_released (key_addr, key_size))
flash_erase_page (((uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1)));
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
else
flash_key_fill_zero_as_released (key_addr, key_size);
}
@@ -619,9 +628,8 @@ flash_erase_binary (uint8_t file_id)
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
{
flash_erase_page ((uint32_t)p);
#if FLASH_CH_CERTIFICATE_SIZE > FLASH_PAGE_SIZE
flash_erase_page ((uint32_t)p + FLASH_PAGE_SIZE);
#endif
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uint32_t)p + flash_page_size);
}
return 0;

View File

@@ -116,6 +116,7 @@ const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
#define ALGO_NISTP256R1 1
#define ALGO_SECP256K1 2
#define ALGO_ED25519 3
#define ALGO_CURVE25519 4
#define ALGO_RSA2K 255
enum kind_of_key {
@@ -162,7 +163,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) */
@@ -266,12 +266,14 @@ uint8_t *rsa_genkey (int);
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
@@ -279,6 +281,9 @@ int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
const uint8_t *sk_a, const uint8_t *seed,
const uint8_t *pk);
uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
const uint8_t *gpg_do_read_simple (uint8_t);
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
@@ -409,7 +414,7 @@ void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
void flash_do_write_internal (const uint8_t *p, int nr,
const uint8_t *data, int len);
extern const uint8_t gnukStringSerial[];
extern const uint8_t gnuk_string_serial[];
#define LED_ONESHOT (1)
#define LED_TWOSHOTS (2)

View File

@@ -18,10 +18,6 @@ MEMORY
ram : org = 0x20000000, len = @MEMORY_SIZE@k
}
/* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */
__flash_start__ = 0x08001000;
__flash_end__ = ORIGIN(flash) + LENGTH(flash);
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
@@ -32,18 +28,20 @@ SECTIONS
.sys : ALIGN(4) SUBALIGN(4)
{
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
*(.sys.version)
build/sys.o(.text)
build/sys.o(.text.*)
build/sys.o(.rodata)
build/sys.o(.rodata.*)
. = ALIGN(1024);
*(.sys.0)
*(.sys.1)
*(.sys.2)
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
KEEP(*(.sys.version))
KEEP(*(.sys.board_id))
KEEP(*(.sys.board_name))
build/sys.o(.text)
build/sys.o(.text.*)
build/sys.o(.rodata)
build/sys.o(.rodata.*)
. = ALIGN(1024);
*(.sys.0)
*(.sys.1)
*(.sys.2)
} > flash0
_text = .;
@@ -64,6 +62,7 @@ SECTIONS
*(.glue_7t)
*(.glue_7)
*(.gcc*)
. = ALIGN(8);
} > flash
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash

View File

@@ -28,7 +28,6 @@
#include <eventflag.h>
#include "config.h"
#include "board.h"
#include "sys.h"
#include "adc.h"
@@ -127,7 +126,7 @@ extern void *USBthread (void *arg);
static void
device_initialize_once (void)
{
const uint8_t *p = &gnukStringSerial[ID_OFFSET];
const uint8_t *p = &gnuk_string_serial[ID_OFFSET];
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
{
@@ -135,12 +134,12 @@ device_initialize_once (void)
* This is the first time invocation.
* Setup serial number by unique device ID.
*/
const uint8_t *u = unique_device_id ();
const uint8_t *u = unique_device_id () + 8;
int i;
for (i = 0; i < 4; i++)
{
uint8_t b = u[i];
uint8_t b = u[3-i];
uint8_t nibble;
nibble = (b >> 4);
@@ -426,15 +425,20 @@ main (int argc, char *argv[])
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
{
extern uint8_t _sys;
uint32_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
uint32_t flash_page_size = 1024; /* 1KiB default */
if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
flash_page_size = 2048; /* It's 2KiB. */
/* Kill DFU */
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
addr += FLASH_PAGE_SIZE)
addr += flash_page_size)
flash_erase_page (addr);
/* copy system service routines */

View File

@@ -215,7 +215,7 @@ static int ep_process (int mode)
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR & 0xff;
v = CRC->DR & 0xff; /* First byte of CRC->DR is used here. */
noise_source_continuous_test (v);
sha256_ctx_data.wbuf[i] = v;
ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
@@ -280,8 +280,6 @@ uint16_t neug_rc_max;
uint16_t neug_p64_max;
uint16_t neug_p4k_max;
#include "board.h"
static void noise_source_cnt_max_reset (void)
{
neug_err_cnt = neug_err_cnt_rc = neug_err_cnt_p64 = neug_err_cnt_p4k = 0;

View File

@@ -3,9 +3,9 @@
#define NEUG_PRE_LOOP 32
#define NEUG_MODE_CONDITIONED 0
#define NEUG_MODE_RAW 1
#define NEUG_MODE_RAW_DATA 2
#define NEUG_MODE_CONDITIONED 0 /* Conditioned data. */
#define NEUG_MODE_RAW 1 /* CRC-32 filtered sample data. */
#define NEUG_MODE_RAW_DATA 2 /* Sample data directly. */
extern uint8_t neug_mode;
extern uint16_t neug_err_cnt;

View File

@@ -1,7 +1,7 @@
/*
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* 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>
*
@@ -170,6 +170,13 @@ static const uint8_t algorithm_attr_ed25519[] __attribute__ ((aligned (1))) = {
0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01
};
static const uint8_t algorithm_attr_cv25519[] __attribute__ ((aligned (1))) = {
11,
OPENPGP_ALGO_ECDH,
/* OID of the curve Curve25519 */
0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01
};
/*
* Representation of PW1_LIFETIME:
@@ -246,16 +253,21 @@ get_algo_attr_data_object (enum kind_of_key kk)
if (algo_attr_p == NULL)
return algorithm_attr_rsa2k;
if (algo_attr_p[1] == ALGO_RSA4K)
return algorithm_attr_rsa4k;
else if (algo_attr_p[1] == ALGO_NISTP256R1)
return algorithm_attr_p256r1;
else if (algo_attr_p[1] == ALGO_SECP256K1)
return algorithm_attr_p256k1;
else if (algo_attr_p[1] == ALGO_ED25519)
return algorithm_attr_ed25519;
return algorithm_attr_rsa2k;
switch (algo_attr_p[1])
{
case ALGO_RSA4K:
return algorithm_attr_rsa4k;
case ALGO_NISTP256R1:
return algorithm_attr_p256r1;
case ALGO_SECP256K1:
return algorithm_attr_p256k1;
case ALGO_ED25519:
return algorithm_attr_ed25519;
case ALGO_CURVE25519:
return algorithm_attr_cv25519;
default:
return algorithm_attr_rsa2k;
}
}
int
@@ -263,30 +275,43 @@ gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s)
{
const uint8_t *algo_attr_p = *get_algo_attr_pointer (kk);
if (algo_attr_p == NULL)
if (s == GPG_KEY_STORAGE)
return 512;
else
return 256;
else if (algo_attr_p[1] == ALGO_RSA4K)
if (s == GPG_KEY_STORAGE)
return 1024;
else
return 512;
else if (algo_attr_p[1] == ALGO_NISTP256R1 || algo_attr_p[1] == ALGO_SECP256K1)
if (s == GPG_KEY_STORAGE)
return 128;
else if (s == GPG_KEY_PUBLIC)
return 64;
else
return 32;
else /* ED25519 */
if (s == GPG_KEY_STORAGE)
return 128;
else if (s == GPG_KEY_PUBLIC)
return 32;
else
return 64;
if (algo_attr_p == NULL) /* RSA-2048 */
goto rsa2k;
switch (algo_attr_p[1])
{
case ALGO_RSA4K:
if (s == GPG_KEY_STORAGE)
return 1024;
else
return 512;
case ALGO_NISTP256R1:
case ALGO_SECP256K1:
if (s == GPG_KEY_STORAGE)
return 128;
else if (s == GPG_KEY_PUBLIC)
return 64;
else
return 32;
case ALGO_ED25519:
if (s == GPG_KEY_STORAGE)
return 128;
else if (s == GPG_KEY_PUBLIC)
return 32;
else
return 64;
case ALGO_CURVE25519:
if (s == GPG_KEY_STORAGE)
return 64;
else
return 32;
default:
rsa2k:
if (s == GPG_KEY_STORAGE)
return 512;
else
return 256;
}
}
@@ -464,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.
*/
@@ -724,6 +751,8 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
algo = ALGO_NISTP256R1;
else if (len == 10 && memcmp (data, algorithm_attr_ed25519+1, 10) == 0)
algo = ALGO_ED25519;
else if (len == 11 && memcmp (data, algorithm_attr_cv25519+1, 11) == 0)
algo = ALGO_CURVE25519;
if (algo < 0)
return 0; /* Error */
@@ -1049,6 +1078,12 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
if (prvkey_len != 64)
return -1;
}
else if (attr == ALGO_CURVE25519)
{
pubkey_len = prvkey_len;
if (prvkey_len != 32)
return -1;
}
else /* RSA */
{
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
@@ -1066,6 +1101,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
else if (attr == ALGO_ED25519)
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
else if (attr == ALGO_CURVE25519)
pubkey_allocated_here = ecdh_compute_public_25519 (key_data);
else /* RSA */
pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
@@ -1292,7 +1329,7 @@ kkb_to_kk (uint8_t kk_byte)
static int
proc_key_import (const uint8_t *data, int len)
{
int r;
int r = -1;
enum kind_of_key kk;
const uint8_t *keystring_admin;
int attr;
@@ -1328,7 +1365,7 @@ proc_key_import (const uint8_t *data, int len)
attr = gpg_get_algo_attr (kk);
if ((len <= 12 && (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1
|| attr == ALGO_ED25519))
|| attr == ALGO_ED25519 || attr == ALGO_CURVE25519))
|| (len <= 22 && attr == ALGO_RSA2K) || (len <= 24 && attr == ALGO_RSA4K))
{ /* Deletion of the key */
gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
@@ -1343,7 +1380,7 @@ proc_key_import (const uint8_t *data, int len)
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, NULL);
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
else /* if (attr == ALGO_ED25519) */
else if (attr == ALGO_ED25519)
{
uint8_t hash[64];
@@ -1356,6 +1393,18 @@ proc_key_import (const uint8_t *data, int len)
hash[31] |= 64;
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
}
else if (attr == ALGO_CURVE25519)
{
uint8_t priv[32];
int i;
if (len - 12 != 32)
return 1; /* Error. */
for (i = 0; i < 32; i++)
priv[31-i] = data[12+i];
r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, NULL);
}
if (r < 0)
return 0;
@@ -1910,14 +1959,14 @@ gpg_do_public_key (uint8_t kk_byte)
res_p += 64;
}
}
else if (attr == ALGO_ED25519)
{ /* EdDSA */
else if (attr == ALGO_ED25519 || attr == ALGO_CURVE25519)
{ /* EdDSA or ECDH on curve25519 */
/* LEN */
*res_p++ = 2 + 32;
{
/*TAG*/ /* LEN = 32 */
*res_p++ = 0x86; *res_p++ = 0x20;
/* 32-byte binary (little endian): Y with parity */
/* 32-byte binary (little endian): Y with parity or X*/
memcpy (res_p, pubkey, 32);
res_p += 32;
}
@@ -1983,16 +2032,18 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
*do_data_p = NULL;
}
#ifdef KEYGEN_SUPPORT
void
gpg_do_keygen (uint8_t kk_byte)
{
enum kind_of_key kk = kkb_to_kk (kk_byte);
int pubkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PUBLIC);
int attr = gpg_get_algo_attr (kk);;
int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE);
const uint8_t *keystring_admin;
uint8_t *p_q_modulus;
const uint8_t *p_q;
const uint8_t *modulus;
uint8_t *p_q_modulus = NULL;
uint8_t d[64];
const uint8_t *rnd;
const uint8_t *prv;
const uint8_t *pubkey;
int r;
DEBUG_INFO ("Keygen\r\n");
@@ -2003,19 +2054,85 @@ gpg_do_keygen (uint8_t kk_byte)
else
keystring_admin = NULL;
p_q_modulus = rsa_genkey (pubkey_len);
if (p_q_modulus == NULL)
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
{
GPG_MEMORY_FAILURE ();
p_q_modulus = rsa_genkey (prvkey_len);
if (p_q_modulus == NULL)
{
GPG_MEMORY_FAILURE ();
return;
}
prv = p_q_modulus;
pubkey = p_q_modulus + prvkey_len;
}
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
uint8_t d1[32];
const uint8_t *p;
int i, r;
rnd = NULL;
do
{
if (rnd)
random_bytes_free (rnd);
rnd = random_bytes_get ();
if (attr == ALGO_NISTP256R1)
r = ecc_check_secret_p256r1 (rnd, d1);
else
r = ecc_check_secret_p256k1 (rnd, d1);
}
while (r == 0);
/* Convert it to big endian */
if (r < 0)
p = (const uint8_t *)d1;
else
p = rnd;
for (i = 0; i < 32; i++)
d[32 - i - 1] = p[i];
random_bytes_free (rnd);
prv = d;
pubkey = NULL;
}
else if (attr == ALGO_ED25519)
{
rnd = random_bytes_get ();
sha512 (rnd, 32, d);
random_bytes_free (rnd);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
}
else if (attr == ALGO_CURVE25519)
{
rnd = random_bytes_get ();
memcpy (d, rnd, 32);
random_bytes_free (rnd);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
prv = d;
pubkey = NULL;
}
else
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
p_q = p_q_modulus;
modulus = p_q_modulus + pubkey_len;
r = gpg_do_write_prvkey (kk, p_q, pubkey_len, keystring_admin, modulus);
memset (p_q_modulus, 0, pubkey_len * 2);
free (p_q_modulus);
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
if (p_q_modulus)
{
memset (p_q_modulus, 0, prvkey_len * 2);
free (p_q_modulus);
}
if (r < 0)
{
GPG_ERROR ();
@@ -2041,4 +2158,3 @@ gpg_do_keygen (uint8_t kk_byte)
gpg_do_public_key (kk_byte);
}
#endif

View File

@@ -620,12 +620,7 @@ cmd_pgp_gakp (void)
{
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
GPG_SECURITY_FAILURE ();
#ifdef KEYGEN_SUPPORT
/* Generate key pair */
gpg_do_keygen (apdu.cmd_apdu_data[0]);
#else
GPG_FUNCTION_NOT_SUPPORTED ();
#endif
}
}
@@ -942,15 +937,11 @@ cmd_pso (void)
}
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
{
int header_size = -1;
if (len == 65)
header_size = 0;
else if (len == 65 + ECC_CIPHER_DO_HEADER_SIZE)
header_size = ECC_CIPHER_DO_HEADER_SIZE;
int header = ECC_CIPHER_DO_HEADER_SIZE;
/* Format is in big endian MPI: 04 || x || y */
if (header_size < 0 || apdu.cmd_apdu_data[header_size] != 4)
if (len != 65 + ECC_CIPHER_DO_HEADER_SIZE
|| apdu.cmd_apdu_data[header] != 0x04)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
@@ -958,12 +949,26 @@ cmd_pso (void)
result_len = 65;
if (attr == ALGO_NISTP256R1)
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header_size, res_APDU,
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header, res_APDU,
kd[GPG_KEY_FOR_DECRYPTION].data);
else
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header_size, res_APDU,
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header, res_APDU,
kd[GPG_KEY_FOR_DECRYPTION].data);
}
else if (attr == ALGO_CURVE25519)
{
int header = ECC_CIPHER_DO_HEADER_SIZE;
if (len != 32 + ECC_CIPHER_DO_HEADER_SIZE)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
result_len = 32;
r = ecdh_decrypt_curve25519 (apdu.cmd_apdu_data + header, res_APDU,
kd[GPG_KEY_FOR_DECRYPTION].data);
}
else
{
DEBUG_INFO ("unknown algo.");

View File

@@ -1,7 +1,8 @@
/*
* random.c -- get random bytes
*
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 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.
@@ -24,8 +25,6 @@
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "gnuk.h"
#include "neug.h"
@@ -85,7 +84,6 @@ random_get_salt (uint8_t *p)
}
#ifdef KEYGEN_SUPPORT
/*
* Random byte iterator
*/
@@ -120,4 +118,3 @@ random_gen (void *arg, unsigned char *out, size_t out_len)
return 0;
}
#endif

262
src/sys.c
View File

@@ -1,7 +1,7 @@
/*
* sys.c - system routines for the initial page for STM32F103.
*
* Copyright (C) 2013, 2014 Flying Stone Technology
* Copyright (C) 2013, 2014, 2015 Flying Stone Technology
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* Copying and distribution of this file, with or without modification,
@@ -17,53 +17,13 @@
#include <stdlib.h>
#include "board.h"
#include "clk_gpio_init.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
#define STM32_SW_HSI (0 << 0)
#define STM32_SW_PLL (2 << 0)
#define STM32_PLLSRC_HSI (0 << 16)
#define STM32_PLLSRC_HSE (1 << 16)
#define STM32_PLLXTPRE_DIV1 (0 << 17)
#define STM32_PLLXTPRE_DIV2 (1 << 17)
#define STM32_HPRE_DIV1 (0 << 4)
#define STM32_PPRE1_DIV1 (0 << 8)
#define STM32_PPRE1_DIV2 (4 << 8)
#define STM32_PPRE2_DIV1 (0 << 11)
#define STM32_PPRE2_DIV2 (4 << 11)
#define STM32_ADCPRE_DIV4 (1 << 14)
#define STM32_ADCPRE_DIV6 (2 << 14)
#define STM32_USBPRE_DIV1P5 (0 << 22)
#define STM32_MCO_NOCLOCK (0 << 24)
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_FLASHBITS 0x00000012
#define STM32_PLLCLKIN (STM32_HSECLK / 1)
#define STM32_SW STM32_SW_PLL
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_MCOSEL STM32_MCO_NOCLOCK
#define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
#define STM32_SYSCLK STM32_PLLCLKOUT
#define STM32_HCLK (STM32_SYSCLK / 1)
struct NVIC {
uint32_t ISER[8];
uint32_t unused1[24];
@@ -93,191 +53,6 @@ nvic_enable_vector (uint32_t n, uint32_t prio)
NVIC_ISER (n) = 1 << (n & 0x1F);
}
#define PERIPH_BASE 0x40000000
#define APBPERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
struct RCC {
volatile uint32_t CR;
volatile uint32_t CFGR;
volatile uint32_t CIR;
volatile uint32_t APB2RSTR;
volatile uint32_t APB1RSTR;
volatile uint32_t AHBENR;
volatile uint32_t APB2ENR;
volatile uint32_t APB1ENR;
volatile uint32_t BDCR;
volatile uint32_t CSR;
};
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
static struct RCC *const RCC = ((struct RCC *const)RCC_BASE);
#define RCC_APB1ENR_USBEN 0x00800000
#define RCC_APB1RSTR_USBRST 0x00800000
#define RCC_CR_HSION 0x00000001
#define RCC_CR_HSIRDY 0x00000002
#define RCC_CR_HSITRIM 0x000000F8
#define RCC_CR_HSEON 0x00010000
#define RCC_CR_HSERDY 0x00020000
#define RCC_CR_PLLON 0x01000000
#define RCC_CR_PLLRDY 0x02000000
#define RCC_CFGR_SWS 0x0000000C
#define RCC_CFGR_SWS_HSI 0x00000000
#define RCC_AHBENR_CRCEN 0x0040
#define RCC_APB2RSTR_AFIORST 0x00000001
#define RCC_APB2RSTR_IOPARST 0x00000004
#define RCC_APB2RSTR_IOPBRST 0x00000008
#define RCC_APB2RSTR_IOPCRST 0x00000010
#define RCC_APB2RSTR_IOPDRST 0x00000020
#define RCC_APB2ENR_AFIOEN 0x00000001
#define RCC_APB2ENR_IOPAEN 0x00000004
#define RCC_APB2ENR_IOPBEN 0x00000008
#define RCC_APB2ENR_IOPCEN 0x00000010
#define RCC_APB2ENR_IOPDEN 0x00000020
struct FLASH {
volatile uint32_t ACR;
volatile uint32_t KEYR;
volatile uint32_t OPTKEYR;
volatile uint32_t SR;
volatile uint32_t CR;
volatile uint32_t AR;
volatile uint32_t RESERVED;
volatile uint32_t OBR;
volatile uint32_t WRPR;
};
#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000)
static struct FLASH *const FLASH = ((struct FLASH *const) FLASH_R_BASE);
static void
clock_init (void)
{
/* HSI setup */
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY))
;
/* Reset HSEON, HSEBYP, CSSON, and PLLON, not touching RCC_CR_HSITRIM */
RCC->CR &= (RCC_CR_HSITRIM | RCC_CR_HSION);
RCC->CFGR = 0;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
;
/* HSE setup */
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY))
;
/* PLL setup */
RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY))
;
/* Clock settings */
RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE
| STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
/*
* We don't touch RCC->CR2, RCC->CFGR2, RCC->CFGR3, and RCC->CIR.
*/
/* Flash setup */
FLASH->ACR = STM32_FLASHBITS;
/* CRC */
RCC->AHBENR |= RCC_AHBENR_CRCEN;
/* Switching on the configured clock source. */
RCC->CFGR |= STM32_SW;
while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2))
;
}
struct AFIO
{
volatile uint32_t EVCR;
volatile uint32_t MAPR;
volatile uint32_t EXTICR[4];
uint32_t RESERVED0;
volatile uint32_t MAPR2;
};
#define AFIO_BASE 0x40010000
static struct AFIO *const AFIO = (struct AFIO *const)AFIO_BASE;
#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP 0x00000800
#define AFIO_MAPR_SWJ_CFG_DISABLE 0x04000000
struct GPIO {
volatile uint32_t CRL;
volatile uint32_t CRH;
volatile uint32_t IDR;
volatile uint32_t ODR;
volatile uint32_t BSRR;
volatile uint32_t BRR;
volatile uint32_t LCKR;
};
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#define GPIOA ((struct GPIO *) GPIOA_BASE)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define GPIOB ((struct GPIO *) GPIOB_BASE)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define GPIOC ((struct GPIO *) GPIOC_BASE)
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
#define GPIOD ((struct GPIO *) GPIOD_BASE)
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define GPIOE ((struct GPIO *) GPIOE_BASE)
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
#ifdef GPIO_USB_BASE
static struct GPIO *const GPIO_USB = ((struct GPIO *const) GPIO_USB_BASE);
#endif
#ifdef GPIO_OTHER_BASE
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
#endif
static void
gpio_init (void)
{
/* Enable GPIO clock. */
RCC->APB2ENR |= RCC_ENR_IOP_EN;
RCC->APB2RSTR = RCC_RSTR_IOP_RST;
RCC->APB2RSTR = 0;
#ifdef AFIO_MAPR_SOMETHING
AFIO->MAPR |= AFIO_MAPR_SOMETHING;
#endif
GPIO_USB->ODR = VAL_GPIO_ODR;
GPIO_USB->CRH = VAL_GPIO_CRH;
GPIO_USB->CRL = VAL_GPIO_CRL;
#if GPIO_USB_BASE != GPIO_LED_BASE
GPIO_LED->ODR = VAL_GPIO_LED_ODR;
GPIO_LED->CRH = VAL_GPIO_LED_CRH;
GPIO_LED->CRL = VAL_GPIO_LED_CRL;
#endif
#ifdef GPIO_OTHER_BASE
GPIO_OTHER->ODR = VAL_GPIO_OTHER_ODR;
GPIO_OTHER->CRH = VAL_GPIO_OTHER_CRH;
GPIO_OTHER->CRL = VAL_GPIO_OTHER_CRL;
#endif
}
static void
usb_cable_config (int enable)
{
@@ -468,16 +243,19 @@ flash_check_blank (const uint8_t *p_start, size_t size)
return 1;
}
extern uint8_t __flash_start__, __flash_end__;
#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 CHIP_ID_REG ((uint32_t *)0xe0042000)
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
static int
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
{
int status;
uint32_t flash_start = (uint32_t)&__flash_start__;
uint32_t flash_end = (uint32_t)&__flash_end__;
uint32_t flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
if (dst_addr < flash_start || dst_addr + len > flash_end)
if (dst_addr < FLASH_START || dst_addr + len > flash_end)
return 0;
while (len)
@@ -530,17 +308,21 @@ flash_protect (void)
static void __attribute__((naked))
flash_erase_all_and_exec (void (*entry)(void))
{
uint32_t addr = (uint32_t)&__flash_start__;
uint32_t end = (uint32_t)&__flash_end__;
uint32_t addr = FLASH_START;
uint32_t end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
uint32_t page_size = 1024;
int r;
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
page_size = 2048;
while (addr < end)
{
r = flash_erase_page (addr);
if (r != 0)
break;
addr += FLASH_PAGE_SIZE;
addr += page_size;
}
if (addr >= end)
@@ -640,7 +422,13 @@ 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.0" */
'2', 0, '.', 0, '0', 0,
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
/* sys version: "2.1" */
'2', 0, '.', 0, '1', 0,
};
const uint32_t __attribute__((section(".sys.board_id")))
sys_board_id = BOARD_ID;
const uint8_t __attribute__((section(".sys.board_name")))
sys_board_name[] = BOARD_NAME;

View File

@@ -1,4 +1,18 @@
#define BOARD_ID_CQ_STARM 0xc5480875
#define BOARD_ID_FST_01_00 0x613870a9
#define BOARD_ID_FST_01 0x696886af
#define BOARD_ID_MAPLE_MINI 0x7a445272
#define BOARD_ID_OLIMEX_STM32_H103 0xf92bb594
#define BOARD_ID_STBEE_MINI 0x1f341961
#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
extern const uint8_t sys_version[8];
extern const uint32_t sys_board_id;
extern const uint8_t sys_board_name[];
typedef void (*handler)(void);
extern handler vector[16];

View File

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

View File

@@ -3,7 +3,6 @@
#ifndef __USB_CONF_H
#define __USB_CONF_H
#define NUM_STRING_DESC 7
#define ICC_NUM_INTERFACES 1
#define ICC_INTERFACE 0
#ifdef HID_CARD_CHANGE_SUPPORT

View File

@@ -58,15 +58,12 @@ static struct line_coding line_coding = {
};
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 control_info *detail)
{
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), detail);
}
else /* USB_SETUP_SET (req) */
{
@@ -79,7 +76,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 (detail->value != 0)
{
if (stdout.connected == 0)
/* It's Open call */
@@ -262,8 +259,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 control_info *detail)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -272,30 +268,27 @@ 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), detail);
}
else /* SETUP_SET */
{
uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
uint8_t *addr = (uint8_t *)(0x20000000 + detail->value * 0x100 + detail->index);
if (req_no == USB_FSIJ_GNUK_DOWNLOAD)
{
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT;
if (addr < &_regnual_start || addr + len > __heap_end__)
if (addr < &_regnual_start || addr + detail->len > __heap_end__)
return USB_UNSUPPORT;
if (index + len < 256)
memset (addr + index + len, 0, 256 - (index + len));
if (detail->index + detail->len < 256)
memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
usb_lld_set_data_to_recv (addr, len);
usb_lld_set_data_to_recv (addr, detail->len);
return USB_SUCCESS;
}
else if (req_no == USB_FSIJ_GNUK_EXEC && len == 0)
else if (req_no == USB_FSIJ_GNUK_EXEC && detail->len == 0)
{
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
return USB_UNSUPPORT;
@@ -305,33 +298,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 && detail->len == 0)
{
if (value != 0 && value != 1 && value != 2)
if (detail->value != 0 && detail->value != 1 && detail->value != 2)
return USB_UNSUPPORT;
ccid_card_change_signal (value);
ccid_card_change_signal (detail->value);
return USB_SUCCESS;
}
}
}
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
if (index == ICC_INTERFACE)
if (detail->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),
detail);
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), detail);
}
else
{
@@ -347,21 +335,19 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
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, detail);
case USB_HID_REQ_SET_IDLE:
usb_lld_set_data_to_recv (&hid_idle_rate, 1);
usb_lld_set_data_to_recv (&hid_idle_rate, 1, detail);
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, detail);
case USB_HID_REQ_SET_REPORT:
/* Received LED set request */
if (len == 1)
usb_lld_set_data_to_recv (&hid_report, len);
if (detail->len == 1)
usb_lld_set_data_to_recv (&hid_report, detail->len);
return USB_SUCCESS;
case USB_HID_REQ_GET_PROTOCOL:
@@ -376,7 +362,7 @@ 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);
return vcom_port_data_setup (req, req_no, detail);
#endif
#ifdef PINPAD_DND_SUPPORT
else if (index == MSC_INTERFACE)
@@ -384,10 +370,8 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
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),
detail);
}
else
if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
@@ -402,14 +386,13 @@ 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, uint16_t value)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
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)
return;
@@ -476,9 +459,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 control_info *detail)
{
static const uint8_t zero = 0;
const uint8_t zero = 0;
uint16_t interface = detail->index;
uint16_t alt = detail->value;
if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT;
@@ -495,11 +480,10 @@ int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
}
case USB_GET_INTERFACE:
usb_lld_set_data_to_send (&zero, 1);
return USB_SUCCESS;
return usb_lld_reply_request (&zero, 1, detail);
default:
case USB_QUERY_INTERFACE:
default:
return USB_SUCCESS;
}
}

View File

@@ -59,7 +59,7 @@ 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 */
0x10, 0x01, /* bcdUSB = 1.1 */
@@ -99,7 +99,7 @@ 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 */
@@ -315,7 +315,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* USB String Descriptors */
static const uint8_t gnukStringLangID[] = {
static const uint8_t gnuk_string_lang_id[] = {
4, /* bLength */
USB_STRING_DESCRIPTOR_TYPE,
0x09, 0x04 /* LangID = 0x0409: US-English */
@@ -330,78 +330,70 @@ struct desc
uint16_t size;
};
static const struct desc String_Descriptors[NUM_STRING_DESC] = {
{gnukStringLangID, sizeof (gnukStringLangID)},
{gnukStringVendor, sizeof (gnukStringVendor)},
{gnukStringProduct, sizeof (gnukStringProduct)},
{gnukStringSerial, sizeof (gnukStringSerial)},
static const struct desc string_descriptors[] = {
{gnuk_string_lang_id, sizeof (gnuk_string_lang_id)},
{gnuk_string_vendor, sizeof (gnuk_string_vendor)},
{gnuk_string_product, sizeof (gnuk_string_product)},
{gnuk_string_serial, sizeof (gnuk_string_serial)},
{gnuk_revision_detail, sizeof (gnuk_revision_detail)},
{gnuk_config_options, sizeof (gnuk_config_options)},
{sys_version, sizeof (sys_version)},
};
#define NUM_STRING_DESC (sizeof (string_descriptors) / sizeof (struct desc))
#define USB_DT_HID 0x21
#define USB_DT_REPORT 0x22
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index)
struct control_info *detail)
{
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), detail);
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), detail);
else if (desc_type == STRING_DESCRIPTOR)
{
if (desc_index < NUM_STRING_DESC)
return usb_lld_reply_request (string_descriptors[desc_index].desc,
string_descriptors[desc_index].size,
detail);
else 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;
uint8_t usbbuf[64];
int i;
size_t len;
for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
{
if (sys_board_name[i] == 0)
break;
usbbuf[i*2+2] = sys_board_name[i];
usbbuf[i*2+3] = 0;
}
usbbuf[0] = len = i*2 + 2;
usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
return usb_lld_reply_request (usbbuf, len, detail);
}
}
}
#ifdef HID_CARD_CHANGE_SUPPORT
else if (rcp == INTERFACE_RECIPIENT)
{
#ifdef HID_CARD_CHANGE_SUPPORT
if (index == 1)
if (detail->index == 1)
{
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,
detail);
else if (desc_type == USB_DT_REPORT)
{
usb_lld_set_data_to_send (hid_report_desc, HID_REPORT_DESC_SIZE);
return USB_SUCCESS;
}
}
else
#else
(void)index;
#endif
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 (hid_report_desc, HID_REPORT_DESC_SIZE,
detail);
}
}
#endif
return USB_UNSUPPORT;
}

View File

@@ -55,15 +55,19 @@ enum
USB_SUCCESS = 1,
};
struct control_info {
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 control_info *detail);
int usb_cb_interface (uint8_t cmd, struct control_info *detail);
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index);
struct control_info *detail);
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, uint16_t value);
enum {
USB_EVENT_ADDRESS,
@@ -89,7 +93,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,6 +102,8 @@ 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 control_info *ctrl);
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);
@@ -109,12 +114,7 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
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 (const void *p, size_t len);
void usb_lld_prepare_shutdown (void);
void usb_lld_shutdown (void);

View File

@@ -1,9 +1,6 @@
#include <stdint.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#include "sys.h"
#include "usb_lld.h"
@@ -49,33 +46,27 @@ 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;
};
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;
@@ -412,16 +403,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 +429,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 +455,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 control_info *detail);
static int std_none (uint8_t req,
uint16_t value, uint16_t index, uint16_t length)
static int std_none (uint8_t req, struct control_info *detail)
{
(void)req; (void)value; (void)index; (void)length;
(void)req; (void)detail;
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 control_info *detail)
{
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
if (detail->value != 0 || detail->len != 2 || (detail->index >> 8) != 0
|| (req & REQUEST_DIR) == 0)
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (index == 0)
if (detail->index == 0)
{
/* Get Device Status */
uint8_t feature = dev_p->current_feature;
@@ -517,8 +498,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, detail);
}
}
else if (rcp == INTERFACE_RECIPIENT)
@@ -528,22 +508,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, detail);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
data_p->len = 2;
return USB_SUCCESS;
return usb_lld_reply_request (&status_info, 2, detail);
}
else if (rcp == ENDPOINT_RECIPIENT)
{
uint8_t endpoint = (index & 0x0f);
uint8_t endpoint = (detail->index & 0x0f);
uint16_t status;
if ((index & 0x70) || endpoint == ENDP0)
if ((detail->index & 0x70) || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((detail->index & 0x80))
{
status = st103_ep_get_tx_status (endpoint);
if (status == 0) /* Disabled */
@@ -560,15 +539,13 @@ 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, detail);
}
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 control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
@@ -577,10 +554,10 @@ static int std_clear_feature (uint8_t req, uint16_t value,
if (rcp == DEVICE_RECIPIENT)
{
if (length != 0 || index != 0)
if (detail->len != 0 || detail->index != 0)
return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP)
if (detail->value == DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature &= ~(1 << 5);
return USB_SUCCESS;
@@ -588,17 +565,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 = (detail->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 (detail->len != 0 || (detail->index >> 8) != 0
|| detail->value != ENDPOINT_STALL || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((detail->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
@@ -606,7 +583,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 (detail->index & 0x80) /* IN endpoint */
st103_ep_clear_dtog_tx (endpoint);
else /* OUT endpoint */
st103_ep_clear_dtog_rx (endpoint);
@@ -618,8 +595,7 @@ 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 control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
@@ -628,10 +604,10 @@ static int std_set_feature (uint8_t req, uint16_t value,
if (rcp == DEVICE_RECIPIENT)
{
if (length != 0 || index != 0)
if (detail->len != 0 || detail->index != 0)
return USB_UNSUPPORT;
if (value == DEVICE_REMOTE_WAKEUP)
if (detail->value == DEVICE_REMOTE_WAKEUP)
{
dev_p->current_feature |= 1 << 5;
// event??
@@ -640,16 +616,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 = (detail->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 (detail->len != 0 || (detail->index >> 8) != 0
|| detail->value != 0 || endpoint == ENDP0)
return USB_UNSUPPORT;
if ((index & 0x80))
if ((detail->index & 0x80))
status = st103_ep_get_tx_status (endpoint);
else
status = st103_ep_get_rx_status (endpoint);
@@ -657,7 +634,7 @@ static int std_set_feature (uint8_t req, uint16_t value,
if (status == 0) /* Disabled */
return USB_UNSUPPORT;
if (index & 0x80)
if (detail->index & 0x80)
/* IN endpoint */
st103_ep_set_tx_status (endpoint, EP_TX_STALL);
else
@@ -671,77 +648,59 @@ 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 control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
return USB_UNSUPPORT;
if (rcp == DEVICE_RECIPIENT)
{
if (length == 0 && value <= 127 && index == 0
&& dev_p->current_configuration == 0)
return USB_SUCCESS;
}
if (rcp == DEVICE_RECIPIENT && detail->len == 0 && detail->value <= 127
&& detail->index == 0 && dev_p->current_configuration == 0)
return USB_SUCCESS;
return USB_UNSUPPORT;
}
static int std_get_descriptor (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_get_descriptor (uint8_t req, struct control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 0)
return USB_UNSUPPORT;
(void)length;
return usb_cb_get_descriptor (rcp, (value >> 8), (value & 0xff), index);
return usb_cb_get_descriptor (rcp, (detail->value >> 8),
(detail->value & 0xff), detail);
}
static int std_get_configuration (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_get_configuration (uint8_t req, struct control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
(void)detail;
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;
}
return usb_lld_reply_request (&dev_p->current_configuration, 1, detail);
return USB_UNSUPPORT;
}
static int std_set_configuration (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_set_configuration (uint8_t req, struct control_info *detail)
{
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;
}
if (rcp == DEVICE_RECIPIENT && detail->index == 0 && detail->len == 0)
return usb_cb_handle_event (USB_EVENT_CONFIG, detail->value);
return USB_UNSUPPORT;
}
static int std_get_interface (uint8_t req, uint16_t value,
uint16_t index, uint16_t length)
static int std_get_interface (uint8_t req, struct control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
@@ -750,74 +709,61 @@ static int std_get_interface (uint8_t req, uint16_t value,
if (rcp == INTERFACE_RECIPIENT)
{
if (value != 0 || (index >> 8) != 0 || length != 1)
if (detail->value != 0 || (detail->index >> 8) != 0 || detail->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, detail);
}
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 control_info *detail)
{
uint8_t rcp = req & RECIPIENT;
if ((req & REQUEST_DIR) == 1)
if ((req & REQUEST_DIR) == 1 || rcp != INTERFACE_RECIPIENT
|| detail->len != 0 || (detail->index >> 8) != 0
|| (detail->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, detail);
}
static void handle_setup0 (void)
{
const uint16_t *pw;
struct control_info ctrl;
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++;
ctrl.value = *pw++;
pw++;
ctrl_p->wIndex = *pw++;
ctrl.index = *pw++;
pw++;
ctrl_p->wLength = *pw;
ctrl.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;
@@ -831,44 +777,30 @@ 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, &ctrl);
}
}
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, &ctrl);
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 % USB_MAX_PACKET_SIZE) == 0)
data_p->require_zlp = TRUE;
dev_p->value = ctrl.value;
if (ctrl.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
data_p->require_zlp = FALSE;
dev_p->state = IN_DATA;
handle_datastage_in ();
}
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);
{
dev_p->state = OUT_DATA;
st103_ep_set_rx_status (ENDP0, EP_RX_VALID);
}
}
}
}
@@ -879,17 +811,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,
dev_p->value);
dev_p->state = STALLED;
}
@@ -1111,7 +1042,7 @@ void usb_lld_set_feature (uint8_t feature)
dev_p->current_feature = feature;
}
void usb_lld_set_data_to_send (const void *p, size_t len)
void usb_lld_set_data_to_recv (const void *p, size_t len)
{
data_p->addr = (uint8_t *)p;
data_p->len = len;
@@ -1189,3 +1120,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 control_info *ctl)
{
uint32_t len_asked = ctl->len;
uint32_t len;
data_p->addr = (void *)buf;
data_p->len = buflen;
/* Restrict the data length to be the one host asks for */
if (data_p->len > len_asked)
data_p->len = len_asked;
if (data_p->len != 0 && (data_p->len % USB_MAX_PACKET_SIZE) == 0)
data_p->require_zlp = 1;
if (data_p->len < USB_MAX_PACKET_SIZE)
{
len = data_p->len;
dev_p->state = LAST_IN_DATA;
}
else
{
len = USB_MAX_PACKET_SIZE;
dev_p->state = IN_DATA;
}
if (len)
{
usb_lld_to_pmabuf (data_p->addr, st103_get_tx_addr (ENDP0), len);
data_p->len -= len;
data_p->addr += len;
}
st103_set_tx_count (ENDP0, len);
st103_ep_set_tx_status (ENDP0, EP_TX_VALID);
return USB_SUCCESS;
}

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/* ARM Thumb Assembler code */
// arm-none-eabi-gcc -Wa,-amhls=blank_check.lst -c blank_check.S
.cpu cortex-m3
.cpu cortex-m0
.thumb
ldr r1, .START_ADDR
ldr r2, .END_ADDR

View File

@@ -8,11 +8,9 @@
#define FLASH_SR_OFFSET 0x0c
#define FLASH_CR_OFFSET 0x10
#define COUNT 0x1000
.cpu cortex-m3
.cpu cortex-m0
.thumb
movw r2, #COUNT
ldr r2, .SIZE
ldr r0, .SRC_ADDR
ldr r1, .TARGET_ADDR
ldr r4, .FLASH_BASE_ADDR
@@ -35,5 +33,6 @@
bkpt #0x00
.align 2
.FLASH_BASE_ADDR: .word 0x40022000
.SRC_ADDR: .word 0x20000038
.SRC_ADDR: .word 0x2000003C
.TARGET_ADDR: .word 0x08000000
.SIZE: .word 0x00000000

View File

@@ -7,11 +7,9 @@
#define FLASH_SR_OFFSET 0x0c
#define FLASH_CR_OFFSET 0x10
#define OB_RDP_UNLOCK 0x00a5
.cpu cortex-m3
.cpu cortex-m0
.thumb
movw r0, #OB_RDP_UNLOCK
ldr r0, .OPTION_BYTES
ldr r1, .TARGET_ADDR
ldr r2, .FLASH_BASE_ADDR
mov r3, #FLASH_CR_OPTPG
@@ -21,9 +19,16 @@
1: ldr r0, [r2, #FLASH_SR_OFFSET]
tst r0, r4
bne 1b
add r1, #2
mov r0, #255
strh r0, [r1]
2: ldr r0, [r2, #FLASH_SR_OFFSET]
tst r0, r4
bne 2b
mov r0, #0
str r0, [r2, #FLASH_CR_OFFSET]
bkpt #0x00
.align 2
.FLASH_BASE_ADDR: .word 0x40022000
.TARGET_ADDR: .word 0x1FFFF800
.OPTION_BYTES: .word 0x00000000

View File

@@ -1,202 +0,0 @@
#! /usr/bin/python
"""
gnuk_put_binary.py - a tool to put binary to Gnuk Token
This tool is for importing certificate, writing serial number, etc.
Copyright (C) 2011, 2012 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os, binascii, string
# INPUT: binary file
# Assume only single CCID device is attached to computer and it's Gnuk Token
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString
def s2l(s):
return [ ord(c) for c in s ]
class GnukToken(object):
def __init__(self):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
result = []
while True:
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
result += response
if sw1 == 0x90 and sw2 == 0x00:
return result
elif sw1 != 0x61:
raise ValueError, ("%02x%02x" % (sw1, sw2))
else:
expected_len = sw2
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_read_binary(self, fileid):
apdu = [0x00, 0xb0, 0x80+fileid, 0x00]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_write_binary(self, fileid, data, is_update):
count = 0
data_len = len(data)
if is_update:
ins = 0xd6
else:
ins = 0xd0
while count*256 < data_len:
if count == 0:
d = data[:256]
if len(d) <= 255:
apdu = [0x00, ins, 0x80+fileid, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
else:
d = data[256*count:256*(count+1)]
if len(d) <= 255:
apdu = [0x00, ins, count, 0x00, len(d)] + s2l(d)
else:
apdu0 = [0x10, ins, count, 0x00, 255] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, count, 0x00, 1] + s2l(d[255:])
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if is_update:
raise ValueError, ("update failure: %02x%02x" % (sw1, sw2))
else:
raise ValueError, ("write failure: %02x%02x" % (sw1, sw2))
count += 1
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_get_data(self, tagh, tagl):
apdu = [0x00, 0xca, tagh, tagl]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def compare(data_original, data_in_device):
i = 0
for d in data_original:
if ord(d) != data_in_device[i]:
raise ValueError, "verify failed at %08x" % i
i += 1
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
def main(fileid, is_update, data, passwd):
gnuk = GnukToken()
gnuk.connection.connect()
print "Token:", gnuk.connection.getReader()
print "ATR:", toHexString( gnuk.connection.getATR() )
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_write_binary(fileid, data, is_update)
gnuk.cmd_select_openpgp()
if fileid == 0:
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
for d in data_in_device:
print "%02x" % d,
print
compare(data, data_in_device[8:])
elif fileid >= 1 and fileid <= 4:
data_in_device = gnuk.cmd_read_binary(fileid)
compare(data, data_in_device)
elif fileid == 5:
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
compare(data, data_in_device)
gnuk.connection.disconnect()
return 0
if __name__ == '__main__':
passwd = DEFAULT_PW3
if sys.argv[1] == '-p':
from getpass import getpass
passwd = getpass("Admin password: ")
sys.argv.pop(1)
if sys.argv[1] == '-u':
is_update = True
sys.argv.pop(1)
else:
is_update = False
if sys.argv[1] == '-s':
fileid = 0 # serial number
filename = sys.argv[2]
f = open(filename)
email = os.environ['EMAIL']
serial_data_hex = None
for line in f.readlines():
field = string.split(line)
if field[0] == email:
serial_data_hex = field[1].replace(':','')
f.close()
if not serial_data_hex:
print "No serial number"
exit(1)
print "Writing serial number"
data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-k': # firmware update key
keyno = sys.argv[2]
fileid = 1 + int(keyno)
filename = sys.argv[3]
f = open(filename)
data = f.read()
f.close()
else:
fileid = 5 # Card holder certificate
filename = sys.argv[1]
f = open(filename)
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
print "Updating card holder certificate"
main(fileid, is_update, data, passwd)

View File

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

View File

@@ -1,112 +0,0 @@
#! /usr/bin/python
"""
gnuk_remove_keys.py - a tool to remove keys in Gnuk Token
Copyright (C) 2012 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os, string
# Assume only single CCID device is attached to computer and it's Gnuk Token
from smartcard.CardType import AnyCardType
from smartcard.CardRequest import CardRequest
from smartcard.util import toHexString
def s2l(s):
return [ ord(c) for c in s ]
class GnukToken(object):
def __init__(self):
cardtype = AnyCardType()
cardrequest = CardRequest(timeout=1, cardType=cardtype)
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01]
response, sw1, sw2 = self.connection.transmit(apdu)
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_put_data_remove(self, tagh, tagl):
apdu = [0x00, 0xda, tagh, tagl, 0]
response, sw1, sw2 = self.connection.transmit(apdu)
return response
def cmd_put_data_key_import_remove(self, keyno):
if keyno == 1:
keyspec = 0xb6 # SIG
elif keyno == 2:
keyspec = 0xb8 # DEC
else:
keyspec = 0xa4 # AUT
apdu = [0x00, 0xdb, 0x3f, 0xff, 4, 0x4d, 0x02, keyspec, 0x00]
response, sw1, sw2 = self.connection.transmit(apdu)
return response
DEFAULT_PW3 = "12345678"
BY_ADMIN = 3
def main(passwd):
gnuk = GnukToken()
gnuk.connection.connect()
print "Token:", gnuk.connection.getReader()
print "ATR:", toHexString( gnuk.connection.getATR() )
gnuk.cmd_verify(BY_ADMIN, passwd)
gnuk.cmd_select_openpgp()
gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG
gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG
gnuk.cmd_put_data_key_import_remove(1)
gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC
gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_DEC
gnuk.cmd_put_data_key_import_remove(2)
gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT
gnuk.cmd_put_data_remove(0x00, 0xd0) # KGTIME_AUT
gnuk.cmd_put_data_key_import_remove(3)
gnuk.connection.disconnect()
return 0
if __name__ == '__main__':
passwd = DEFAULT_PW3
if len(sys.argv) > 1 and sys.argv[1] == '-p':
from getpass import getpass
passwd = getpass("Admin password: ")
sys.argv.pop(1)
main(passwd)

View File

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

View File

@@ -1,7 +1,8 @@
"""
gnuk_token.py - a library for Gnuk Token
Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
Copyright (C) 2011, 2012, 2013, 2015
Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -21,8 +22,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from struct import *
import string, binascii
import binascii
import usb, time
from array import array
# USB class, subclass, protocol
CCID_CLASS = 0x0B
@@ -50,9 +52,6 @@ def iso7816_compose(ins, p1, p2, data, cls=0x00, le=None):
return pack('>BBBBB', cls, ins, p1, p2, data_len) \
+ data + pack('>B', le)
def list_to_string(l):
return string.join([chr(c) for c in l], '')
# This class only supports Gnuk (for now)
class gnuk_token(object):
def __init__(self, device, configuration, interface):
@@ -68,10 +67,7 @@ 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.setConfiguration(configuration.value)
self.__devhandle.claimInterface(interface)
self.__devhandle.setAltInterface(0)
@@ -117,7 +113,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 +122,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 +130,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 +140,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 +168,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 +176,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 +207,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 +224,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 +247,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 +291,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 +358,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 +384,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 +409,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 +424,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, '')
@@ -487,7 +482,7 @@ class regnual(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 = 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 +491,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 +499,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 +526,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 +548,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 +560,7 @@ class regnual(object):
def finish(self):
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
value = 0, index = 0, buffer = None,
buffer = None, value = 0, index = 0,
timeout = 10000)
def reset_device(self):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
"""
stlinkv2.py - a tool to control ST-Link/V2
Copyright (C) 2012, 2013 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,16 +26,25 @@ 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
# Assumes only single ST-Link/V2 device is attached to computer.
CORE_ID_CORTEX_M3=0x1ba01477
CORE_ID_CORTEX_M0=0x0bb11477
CHIP_ID_STM32F103xB=0x20036410
CHIP_ID_STM32F103xE=0x10016414
# CHIP_ID_STM32F0 0x20006440
# CHIP_ID_STM32F030?? 0x10006444; FSM-55
GPIOA=0x40010800
GPIOB=0x40010C00
OPTION_BYTES_ADDR=0x1ffff800
RDP_KEY=0x00a5 # Unlock readprotection
RDP_KEY_F1=0x00a5 # Unlock readprotection
RDP_KEY_F0=0x00aa # Unlock readprotection
FLASH_BASE_ADDR=0x40022000
FLASH_KEYR= FLASH_BASE_ADDR+0x04
@@ -62,44 +71,36 @@ FLASH_CR_STRT= 0x0040
FLASH_CR_LOCK= 0x0080
FLASH_CR_OPTWRE= 0x0200
SPI1= 0x40013000
def uint32(v):
return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24)
## HERE comes: "movw r2,#SIZE" instruction
prog_flash_write_body = "\x0A\x48" + "\x0B\x49" + \
"\x08\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" + "\x00\x20\x02\x40" + \
"\x38\x00\x00\x20"
# .SRC_ADDR: 0x20000038
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
## HERE comes: size in 4-byte
# .SIZE
def gen_prog_flash_write(addr,size):
return pack("<BBBB", (0x40 | (size&0xf000)>>12), (0xf2 | (size&0x0800)>>9),
(size & 0x00ff), (0x02 | ((size&0x0700) >> 4))) + \
prog_flash_write_body + pack("<I", addr)
return prog_flash_write_body + pack("<I", addr) + pack("<I", size)
## HERE comes: "movw r0,#VAL" instruction
prog_option_bytes_write_body = "\x06\x49" + "\x05\x4A" + "\x10\x23" + \
"\x01\x24" + "\x13\x61" + "\x08\x80" + "\xD0\x68" + "\x20\x42" + \
"\xFC\xD1" + "\x00\x20" + "\x10\x61" + "\x00\xBE" + "\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
# .OPTION_BYTES
def gen_prog_option_bytes_write(addr,val):
return pack("<BBBB", (0x40 | (val&0xf000)>>12), (0xf2 | (val&0x0800)>>9),
(val & 0x00ff), (0x00 | ((val&0x0700) >> 4))) + \
prog_option_bytes_write_body + pack("<I", addr)
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" + \
"\x00\xBF" + "\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
@@ -108,30 +109,34 @@ def gen_prog_blank_check(size):
SRAM_ADDRESS=0x20000000
BLOCK_SIZE=16384 # Should be less than (20KiB - 0x0038)
FLASH_BLOCK_SIZE_F1=16384 # Should be less than (20KiB - 0x0038)
FLASH_BLOCK_SIZE_F0=2048 # Should be less than (4KiB - 0x0038)
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
@@ -141,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):
@@ -162,73 +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(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 core_id(self):
v = self.execute_get("\xf2\x22\x00", 4)
def get_core_id(self):
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)
@@ -309,7 +320,7 @@ class stlinkv2(object):
return (self.read_memory_u32(FLASH_OBR) & 0x0002) != 0
def blank_check(self):
prog = gen_prog_blank_check(0x20000) # 128KiB XXX: table lookup???
prog = gen_prog_blank_check(self.flash_size)
self.write_memory(SRAM_ADDRESS, prog)
self.write_reg(15, SRAM_ADDRESS)
self.run()
@@ -329,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)
@@ -353,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:
@@ -371,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):
@@ -394,12 +405,12 @@ 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:
if len(data[off:]) > BLOCK_SIZE:
size = BLOCK_SIZE
if len(data[off:]) > self.flash_block_size:
size = self.flash_block_size
self.flash_write_internal(addr, data, off, size)
off = off + size
addr = addr + size
@@ -413,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:
@@ -430,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:
@@ -454,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):
@@ -466,11 +477,12 @@ class stlinkv2(object):
elif mode != 1 and mode != 4:
self.exit_from_dfu()
new_mode = self.stl_mode()
print "Change ST-Link/V2 mode %04x -> %04x" % (mode, new_mode)
print("Change ST-Link/V2 mode %04x -> %04x" % (mode, new_mode))
self.control_nrst(2)
self.enter_swd()
s = self.get_status()
if s != 0x0080:
print "Status is %04x" % s
print("Status is %04x" % s)
self.run()
s = self.get_status()
if s != 0x0080:
@@ -483,9 +495,56 @@ class stlinkv2(object):
if mode != 2:
raise ValueError("Failed to switch debug mode.", mode)
self.core_id = self.get_core_id()
if self.core_id == CORE_ID_CORTEX_M3:
self.chip_stm32 = True
elif self.core_id == CORE_ID_CORTEX_M0:
self.chip_stm32 = False
else:
raise ValueError("Unknown core ID", self.core_id)
if self.chip_stm32:
self.rdp_key = RDP_KEY_F1
self.flash_block_size = FLASH_BLOCK_SIZE_F1
self.require_nrst = False
self.external_spi_flash = True
self.protection_feature = True
else:
self.rdp_key = RDP_KEY_F0
self.flash_block_size = FLASH_BLOCK_SIZE_F0
self.require_nrst = True
self.external_spi_flash = False
self.protection_feature = False
return self.core_id
def get_chip_id(self):
if self.chip_stm32:
self.chip_id = self.read_memory_u32(0xE0042000)
self.flash_size = (self.read_memory_u32(0x1ffff7e0) & 0xffff)*1024
if self.chip_id == CHIP_ID_STM32F103xB:
pass
elif self.chip_id == CHIP_ID_STM32F103xE:
pass
else:
raise ValueError("Unknown chip ID", self.chip_id)
else:
self.chip_id = self.read_memory_u32(0x40015800)
self.flash_size = (self.read_memory_u32(0x1ffff7cc) & 0xffff)*1024
print("Flash size: %dKiB" % (self.flash_size/1024))
return self.chip_id
def get_rdp_key(self):
return self.rdp_key
def has_spi_flash(self):
return self.external_spi_flash
def has_protection(self):
return self.protection_feature
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()
@@ -494,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
@@ -515,15 +574,15 @@ def open_stlinkv2():
return None
def help():
print "stlinkv2.py [-h]: Show this help message"
print "stlinkv2.py [-e]: Erase flash ROM"
print "stlinkv2.py [-u]: Unlock flash ROM"
print "stlinkv2.py [-s]: Show status"
print "stlinkv2.py [-b] [-n] [-r] [-i] FILE: Write content of FILE to flash ROM"
print " -b: Blank check before write (auto erase when not blank)"
print " -n: Don't enable read protection after write"
print " -r: Don't reset after write"
print " -i: Don't test SPI flash"
print("stlinkv2.py [-h]: Show this help message")
print("stlinkv2.py [-e]: Erase flash ROM")
print("stlinkv2.py [-u]: Unlock flash ROM")
print("stlinkv2.py [-s]: Show status")
print("stlinkv2.py [-b] [-n] [-r] [-i] FILE: Write content of FILE to flash ROM")
print(" -b: Blank check before write (auto erase when not blank)")
print(" -n: Don't enable read protection after write")
print(" -r: Don't reset after write")
print(" -i: Don't test SPI flash")
def main(show_help, erase_only, no_protect, spi_flash_check,
@@ -537,40 +596,39 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
if not stl:
raise ValueError("No ST-Link/V2 device found.", None)
print "ST-Link/V2 version info: %d %d %d" % stl.version()
stl.start()
core_id = stl.core_id()
chip_id = stl.read_memory_u32(0xE0042000)
# FST-01 chip id: 0x20036410
print "CORE: %08x, CHIP_ID: %08x" % (core_id, chip_id)
print "Flash ROM read protection:",
protection = stl.protection()
if protection:
print "ON"
else:
print "off"
option_bytes = stl.option_bytes_read()
print "Option bytes: %08x" % option_bytes
if (option_bytes & 0xff) == RDP_KEY:
ob_protection_enable = False
else:
ob_protection_enable = True
print("ST-Link/V2 version info: %d %d %d" % stl.version())
core_id = stl.start()
stl.control_nrst(2)
stl.enter_debug()
status = stl.get_status()
if status != 0x0081:
print "Core does not halt, try API V2 halt."
print("Core does not halt, try API V2 halt.")
# DCB_DHCSR DBGKEY|C_HALT|C_DEBUGEN
stl.write_debug_reg(0xE000EDF0, 0xA05F0003)
status = stl.get_status()
stl.write_debug_reg(0xE000EDF0, 0xA05F0003)
status = stl.get_status()
if status != 0x0081:
raise ValueError("Status of core is not halt.", status)
chip_id = stl.get_chip_id()
# FST-01 chip id: 0x20036410
print("CORE: %08x, CHIP_ID: %08x" % (core_id, chip_id))
protection = stl.protection()
print("Flash ROM read protection: " + ("ON" if protection else "off"))
option_bytes = stl.option_bytes_read()
print("Option bytes: %08x" % option_bytes)
rdp_key = stl.get_rdp_key()
if (option_bytes & 0xff) == rdp_key:
ob_protection_enable = False
else:
ob_protection_enable = True
if protection:
if status_only:
print "The MCU is now stopped."
print("The MCU is now stopped.")
return 0
elif not unlock:
raise OperationFailure("Flash ROM is protected")
@@ -578,7 +636,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
if not skip_blank_check:
stl.reset_sys()
blank = stl.blank_check()
print "Flash ROM blank check: %s" % blank
print("Flash ROM blank check: %s" % blank)
else:
blank = True
if status_only:
@@ -587,12 +645,12 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
stl.exit_debug()
return 0
elif unlock and not ob_protection_enable:
print "No need to unlock. Protection is not enabled."
print("No need to unlock. Protection is not enabled.")
return 1
if erase_only:
if blank:
print "No need to erase"
print("No need to erase")
return 0
stl.setup_gpio()
@@ -602,22 +660,22 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
stl.reset_sys()
stl.option_bytes_erase()
stl.reset_sys()
stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY)
stl.option_bytes_write(OPTION_BYTES_ADDR,rdp_key)
stl.usb_disconnect()
time.sleep(0.100)
stl.finish_gpio()
print "Flash ROM read protection disabled. Reset the board, now."
print("Flash ROM read protection disabled. Reset the board, now.")
return 0
if spi_flash_check:
if spi_flash_check and stl.has_spi_flash():
stl.spi_flash_init()
id = stl.spi_flash_read_id()
print "SPI Flash ROM ID: %06x" % id
print("SPI Flash ROM ID: %06x" % id)
if id != 0xbf254a:
raise ValueError("bad spi flash ROM ID")
if not blank:
print "ERASE ALL"
print("ERASE ALL")
stl.reset_sys()
stl.flash_erase_all()
@@ -629,11 +687,11 @@ def main(show_help, erase_only, no_protect, spi_flash_check,
time.sleep(0.100)
print "WRITE"
print("WRITE")
stl.flash_write(0x08000000, data)
print "VERIFY"
data_received = ()
print("VERIFY")
data_received = array('B')
size = len(data)
off = 0
while size > 0:
@@ -641,17 +699,18 @@ 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, 1024)
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:
print "PROTECT"
if not no_protect and stl.has_protection():
print("PROTECT")
stl.option_bytes_erase()
print "Flash ROM read protection enabled. Reset the board to enable protection."
print("Flash ROM read protection enabled. Reset the board to enable protection.")
if reset_after_successful_write:
stl.control_nrst(2)
stl.usb_disconnect()
stl.reset_sys()
stl.run()
@@ -705,6 +764,8 @@ if __name__ == '__main__':
f = open(filename,'rb')
data = f.read()
f.close()
if len(data) % 1:
raise ValueError("The size of file should be even")
sys.argv.pop(1)
colorama_init()
@@ -714,7 +775,7 @@ if __name__ == '__main__':
reset_after_successful_write,
skip_blank_check, status_only, unlock, data)
if r == 0:
print Fore.WHITE + Back.BLUE + Style.BRIGHT + "SUCCESS" + Style.RESET_ALL
print(Fore.WHITE + Back.BLUE + Style.BRIGHT + "SUCCESS" + Style.RESET_ALL)
sys.exit(r)
except Exception as e:
print Back.RED + Style.BRIGHT + repr(e) + Style.RESET_ALL
print(Back.RED + Style.BRIGHT + repr(e) + Style.RESET_ALL)

View File

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

View File

@@ -3,7 +3,7 @@
"""
usb_strings.py - a tool to dump USB string
Copyright (C) 2012 Free Software Initiative of Japan
Copyright (C) 2012, 2015 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -27,7 +27,7 @@ import usb, sys
USB_VENDOR_FSIJ=0x234b
USB_PRODUCT_GNUK=0x0000
def gnuk_devices():
def gnuk_devices_by_vidpid():
busses = usb.busses()
for bus in busses:
devices = bus.devices
@@ -38,16 +38,16 @@ def gnuk_devices():
continue
yield dev
title = [ '', 'Vendor', 'Product', 'Serial', 'Revision', 'Config', 'Sys' ]
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" % (title[i], str)
s = handle.getString(i, 512)
print("%10s: %s" % (field[i], s.decode('UTF-8')))
except:
pass
del dev
@@ -56,5 +56,5 @@ if __name__ == '__main__':
if len(sys.argv) > 1:
n = int(sys.argv[1])
else:
n = 7 # Gnuk has seven strings
n = 8 # Gnuk has eight strings
main(n)