Compare commits

..

26 Commits

Author SHA1 Message Date
NIIBE Yutaka
bc71c39ea4 version 0.15 2011-11-24 15:40:38 +09:00
NIIBE Yutaka
0232c0a595 dfuse.py: fix handling of unaligned page 2011-11-24 13:54:12 +09:00
NIIBE Yutaka
62520ed0f4 tool/dfuse.py: support unaligned write and hole 2011-11-22 16:17:37 +09:00
NIIBE Yutaka
2c91633f59 add FST-01 description 2011-11-14 14:34:51 +09:00
NIIBE Yutaka
1ac7e20fb0 add FST_01 2011-11-14 14:22:37 +09:00
NIIBE Yutaka
e790bb783c change README and NEWS 2011-11-01 15:58:48 +09:00
NIIBE Yutaka
f45b7a5439 minor change for pin-cir.c 2011-11-01 15:13:58 +09:00
NIIBE Yutaka
6337371016 PIN input DIAL support change 2011-11-01 15:01:32 +09:00
NIIBE Yutaka
ed7e904aef PIN input CIR support change 2011-11-01 14:57:11 +09:00
NIIBE Yutaka
de39c484d0 support FST-01 8MHz 2011-11-01 11:41:20 +09:00
NIIBE Yutaka
ec7a2db43a cosmetic fix of src/ac.c 2011-11-01 11:39:47 +09:00
NIIBE Yutaka
f3a3808608 merge call-rsa.c change in the branch of rsa_1024_support. 2011-11-01 11:21:25 +09:00
NIIBE Yutaka
b2856d162e added more DEBUG_XX 2011-11-01 11:02:22 +09:00
NIIBE Yutaka
447139f74d fixed the bug for user who keeps using initial PW1 2011-11-01 11:01:16 +09:00
NIIBE Yutaka
683253b2eb workaround for GCC (summon-arm-toolchain) 2011-11-01 10:59:44 +09:00
NIIBE Yutaka
4749062338 increase (decreased) main (interrupt) stack size 2011-10-14 15:50:08 +09:00
NIIBE Yutaka
2181c1a428 version 0.14 2011-10-07 11:01:21 +09:00
NIIBE Yutaka
48f552b69b random_bits are not needed any more 2011-10-06 17:02:37 +09:00
NIIBE Yutaka
6aca64b664 cleanup 2011-10-06 16:58:20 +09:00
NIIBE Yutaka
3ec2df97b9 add missing neug.h 2011-10-06 16:57:28 +09:00
NIIBE Yutaka
94f2c25c3b NeuG integrated 2011-10-06 16:56:08 +09:00
NIIBE Yutaka
b1bb1354f8 Change for NeuG RNG 2011-10-06 11:23:49 +09:00
NIIBE Yutaka
1ef7813a53 add neug.c from NeuG/src/random.c 2011-10-06 11:22:51 +09:00
NIIBE Yutaka
9528867c2a minor boards fixes 2011-07-22 15:48:00 +09:00
NIIBE Yutaka
241f62238d add fix of Chibios 2011-07-04 15:57:05 +09:00
NIIBE Yutaka
dee75314fc adc macro rename patch (external) 2011-07-04 10:05:56 +09:00
36 changed files with 2053 additions and 460 deletions

123
ChangeLog
View File

@@ -1,3 +1,126 @@
2011-11-24 Niibe Yutaka <gniibe@fsij.org>
* Version 0.15.
* src/usb_desc.c (gnukStringSerial): Updated.
2011-11-22 Niibe Yutaka <gniibe@fsij.org>
* tool/dfuse.py (DFU_STM32.download, DFU_STM32.verify): Support
unaligned write and hole.
2011-11-14 Niibe Yutaka <gniibe@fsij.org>
* boards/FST_01/{mcuconf.h,board.h,board.c}: New.
2011-11-01 Niibe Yutaka <gniibe@fsij.org>
* src/pin-dial.c (pinpad_getline): New.
(pin_main): Remove.
* boards/STBEE_MINI/board.h (TIMx): Define.
boards/STBEE/board.h (TIMx): Ditto.
boards/STM8S_DISCOVERY/board.h: Ditto.
* src/pin-cir.c (pinpad_getline): New.
(cir_timer_interrupt, cir_ext_interrupt): Use TIMx.
(cir_key_is_backspace, cir_key_is_enter, pin_main, pindisp):
Remove.
(cir_codetable_dell_mr425, cir_codetable_aquos)
(cir_codetable_regza, cir_codetable_bravia, ch_is_backspace)
(ch_is_enter, find_char_codetable, hex, cir_getchar): New.
(cir_timer_interrupt): Don't filter out ADDRESS.
* src/openpgp.c (get_pinpad_input): Don't invoke thread,
but just call pinpad_getline.
* src/main.c (display_interaction, display_fatal_code)
(display_status_code, led_blink): New.
(main): Call display_* routine.
(fatal): Notify main thread.
* src/usb_prop.c (gnuk_device_SetConfiguration): Notify main
thread.
* src/pin-cir.c (pindisp): Remove.
* boards/FST_01_00: New (for 8MHz FST-01).
* src/ac.c (calc_md): Fix comparison.
* src/call-rsa.c (RSA_SIGNATURE_LENGTH): Use KEY_CONTENT_LEN.
(rsa_sign, rsa_decrypt): Likewise.
(modulus_calc): Don't assume it's 2048-bit.
* src/ac.c (verify_user_0): Fix for non-initialized PW1.
* src/Makefile.in (MCFLAGS): Override MCFLAGS option for newer
GCC of summon-arm-toolchain to add -mfix-cortex-m3-ldrd.
NOTE: This should not be needed (as -mcpu=cortex-m3 defaults
to -mfix-cortex-m3-ldrd for GCC-proper), but it is needed
to select arm-none-eabi/lib/thumb2/libc.a correctly.
2011-10-14 NIIBE Yutaka <gniibe@fsij.org>
* src/gnuk.ld.in (__main_stack_size__): It's 1KB (was 512 byte).
2011-10-07 NIIBE Yutaka <gniibe@fsij.org>
* Version 0.14.
* src/usb_desc.c (gnukStringSerial): Updated.
* src/random.c (random_init): Call neug_prng_reseed.
2011-10-06 NIIBE Yutaka <gniibe@fsij.org>
* src/Makefile.in (random_bits): Remove.
* src/openpgp.c (GPGthread): Remove unused event message.
* src/main.c (main): Call random_init.
* src/gnuk.ld.in (__process_stack_size__): Fix.
(.gnuk_random): Removed.
* src/flash.c (flash_erase_binary, flash_write_binary): Remove
support of random_byte in flash ROM.
* src/neug.c (adccb): Use old API (was: chEvtSignalFlagsI).
(adccb_err): Remove.
(rng_gen, rng): Add the last argument adccb for adcStartConversion:
This is old API of ADC driver.
(adcgrpcfg): Remove callbacks, add CONT and SWSTART: This is old
API of ADC driver.
(adccb): Remove the first argument: This is old API of ADC driver.
(neug_wait_full): New.
* ChibiOS_2.0.8/os/hal/platforms/STM32/adc_lld.h (ADC_SAMPLE_1P5):
Add (from new API).
* src/random.c (random_init): New.
(random_bytes_get, random_bytes_free, get_salt): Use NeuG.
* src/Makefile.in (CSRC): Add neug.c.
* src/neug.c: New. Verbatim copy of NeuG/src/random.c.
* boards/common/mcuconf-common.h (USE_STM32_ADC1): TRUE for NewG RNG.
* src/chconf.h (CH_USE_SEMAPHORES): TRUE as ADC driver requires it.
* src/halconf.h (CH_HAL_USE_ADC); TRUE for NewG RNG.
2011-07-22 NIIBE Yutaka <gniibe@fsij.org>
* boards/OLIMEX_STM32_H103/board.h (BOARD_NAME): Fixed.
* boards/STBEE_MINI/mcuconf.h: Added missing include of
mcuconf-common.h.
2011-07-04 NIIBE Yutaka <gniibe@fsij.org>
* ChibiOS_2.0.8/os/ports/GCC/ARMCMx/chcore_v7m.c
(_port_irq_epilogue, _port_switch_from_isr): Apply a patch of 2.2.6.
* ChibiOS_2.0.8/os/hal/platforms/STM32/adc_lld.h: Apply a patch of
ADC from the branch of ChibiOS_2.0.X.
2011-06-15 NIIBE Yutaka <gniibe@fsij.org> 2011-06-15 NIIBE Yutaka <gniibe@fsij.org>
* Version 0.13. * Version 0.13.

View File

@@ -62,6 +62,20 @@
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/ #define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */ #define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
/**
* @name Sampling rates
* @{
*/
#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */
#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */
#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */
#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */
#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */
#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */
#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */
#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */
/** @} */
/*===========================================================================*/ /*===========================================================================*/
/* Driver pre-compile time settings. */ /* Driver pre-compile time settings. */
/*===========================================================================*/ /*===========================================================================*/
@@ -238,26 +252,51 @@ typedef struct {
/* Driver macros. */ /* Driver macros. */
/*===========================================================================*/ /*===========================================================================*/
/**
* @brief Number of channels in a conversion sequence.
*/
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20) #define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
#define ADC_SQR3_SQ0_N(n) ((n) << 0) #define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
#define ADC_SQR3_SQ1_N(n) ((n) << 5) #define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
#define ADC_SQR3_SQ2_N(n) ((n) << 10) #define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
#define ADC_SQR3_SQ3_N(n) ((n) << 15) #define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
#define ADC_SQR3_SQ4_N(n) ((n) << 20) #define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
#define ADC_SQR3_SQ5_N(n) ((n) << 25) #define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
#define ADC_SQR2_SQ6_N(n) ((n) << 0) #define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
#define ADC_SQR2_SQ7_N(n) ((n) << 5) #define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
#define ADC_SQR2_SQ8_N(n) ((n) << 10) #define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
#define ADC_SQR2_SQ9_N(n) ((n) << 15) #define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
#define ADC_SQR2_SQ10_N(n) ((n) << 20) #define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
#define ADC_SQR2_SQ11_N(n) ((n) << 25) #define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
#define ADC_SQR1_SQ13_N(n) ((n) << 0) #define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
#define ADC_SQR1_SQ14_N(n) ((n) << 5) #define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
#define ADC_SQR1_SQ15_N(n) ((n) << 10) #define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
#define ADC_SQR1_SQ16_N(n) ((n) << 15) #define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
sampling time. */
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
sampling time. */
/*===========================================================================*/ /*===========================================================================*/
/* External declarations. */ /* External declarations. */

View File

@@ -107,12 +107,12 @@ void SVCallVector(void) {
} }
/** /**
* @brief Reschedule verification and setup after an IRQ. * @brief Exception exit redirection to _port_switch_from_isr().
*/ */
void _port_irq_epilogue(void) { void _port_irq_epilogue(void) {
port_lock_from_isr(); port_lock_from_isr();
if ((SCB_ICSR & ICSR_RETTOBASE) && chSchIsRescRequiredExI()) { if ((SCB_ICSR & ICSR_RETTOBASE)) {
register struct extctx *ctxp; register struct extctx *ctxp;
/* Adding an artificial exception return context, there is no need to /* Adding an artificial exception return context, there is no need to
@@ -126,7 +126,6 @@ void _port_irq_epilogue(void) {
order to keep the rest of the context switching atomic.*/ order to keep the rest of the context switching atomic.*/
return; return;
} }
/* ISR exit without context switching.*/
port_unlock_from_isr(); port_unlock_from_isr();
} }
@@ -139,7 +138,8 @@ __attribute__((naked))
#endif #endif
void _port_switch_from_isr(void) { void _port_switch_from_isr(void) {
chSchDoRescheduleI(); if (chSchIsRescRequiredExI())
chSchDoRescheduleI();
asm volatile ("svc #0"); asm volatile ("svc #0");
} }

38
NEWS
View File

@@ -1,5 +1,43 @@
Gnuk NEWS - User visible changes Gnuk NEWS - User visible changes
* Major changes in Gnuk 0.15
Released 2011-11-24, by NIIBE Yutaka
** New targets: FST_01 and FST_01_00
Flying Stone Technology's open hardware, Flying Stone Tiny 01 is
supported.
** Flash writing tool for "DfuSe" is improved
Now, it support holes and unaligned blocks in hex file.
** Experimental PIN-pad support (by TV controller) change
Now, Gnuk has codetables for conversion from CIR code to ASCII code.
Note that only four controllers (of Dell, Sharp, Sony, and Toshiba)
are supported and tested.
** It is possible for users to keep using OPENPGP_CARD_INITIAL_PW1
With a bug fix of verify_user_0, it's now possible. Although it's not
recommended.
** Important bug fix and a workaround
In version 0.14, __main_stack_size__ (for interrupt handler) was too
small for some cases. This is fixed in 0.15.
In src/Makefile.in, added -mfix-cortex-m3-ldrd for correctly linking C
library for thumb2. This is needed for newer summon-arm-toolchain.
* Major changes in Gnuk 0.14
Released 2011-10-07, by NIIBE Yutaka
** Random number generator change
NeuG, Gniibe's True RNG implementation for STM32F103, has been
integrated to Gnuk. It is not needed to put random number bytes
(generated by host) to Token any more.
* Major changes in Gnuk 0.13 * Major changes in Gnuk 0.13
Released 2011-06-15, by NIIBE Yutaka Released 2011-06-15, by NIIBE Yutaka

125
README
View File

@@ -1,7 +1,7 @@
Gnuk - software for GnuPG USB Token Gnuk - software for GnuPG USB Token
Version 0.13 Version 0.15
2011-06-15 2011-11-24
Niibe Yutaka Niibe Yutaka
Free Software Initiative of Japan Free Software Initiative of Japan
@@ -27,7 +27,7 @@ FAQ
=== ===
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, GPF Crypto Stick, etc) ? card 2.0, GPF Crypto Stick, etc.) ?
http://www.g10code.de/p-card.html http://www.g10code.de/p-card.html
http://www.privacyfoundation.de/crypto_stick/ http://www.privacyfoundation.de/crypto_stick/
A0: IMRHO, not quite. There is no ready-to-use out-of-box product. A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
@@ -54,6 +54,8 @@ Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103. A3: Orthodox choice is Olimex STM32-H103.
If you have skill of electronics and like DIY, STM32 part of STM8S If you have skill of electronics and like DIY, STM32 part of STM8S
Discovery Kit might be the best choice. Discovery Kit might be the best choice.
Currently FST-01 (Flying Stone Tiny 01) is under development,
it will be the best choice, hopefully.
Q4: What's version of GnuPG are you using? Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
@@ -88,17 +90,27 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of
and confirm scdaemon doesn't exist, then, and confirm scdaemon doesn't exist, then,
$ gpg-connect-agent learn /bye $ gpg-connect-agent learn /bye
Qa: With GNOME, I can't use Gnuk Token for SSH. How can we use it for SSH?
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
gpg-agant for the role of ssh-agent. For gnome-keyring please do:
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
Qb: With GNOME 3, I can't use Gnuk Token at all. Why?
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
$ gnome-session-properties
and at the tab of "Startup Programs", disable check buttons for "GPG Password Agent" and "SSH Key Agent".
Release notes Release notes
============= =============
This is fourteenth release of Gnuk. While it works well for specific This is sixteenth release of Gnuk. While it works well for specific
usages and it is considered stable, it is still somewhat experimental. usages and it is considered stable, it is still somewhat experimental.
Note that you need to write random bits after installation of gnuk
executable to the chip. This procedure is required to share a single
executable among multiple devices.
Tested features are: Tested features are:
* Personalization of the card * Personalization of the card
@@ -121,22 +133,23 @@ It is known not-working well:
work well. Please disable DEBUG option if it doesn't work well. work well. Please disable DEBUG option if it doesn't work well.
* Card holder certificate * Card holder certificate
It is implemented in Gnuk side. But its size matters (> It is implemented in Gnuk side. But its large size matters
1KB). GnuPG cannot handle a data object of large size with (> 1KB). Some versions of GnuPG cannot handle a data object
PC/SC backend. Specifically, handle_transmit function in of large size with PC/SC backend. Specifically,
pcsc-wrapper.c uses the buffer of size 1024-byte. handle_transmit function in pcsc-wrapper.c uses the buffer
of size 1024-byte.
Not supported feature(s): Not supported feature(s):
* Overriding key import. You need to remove all keys first. * Overriding key import. You need to remove all keys first.
* Key generation * Key generation on device side
Targets Targets
======= =======
We use Olimex STM32-H103 board. We also use STM32 part of STM8S We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We
Discovery Kit. also use STM32 part of STM8S Discovery Kit.
With DfuSe support, CQ STARM, STBee, and STBee Mini are also our With DfuSe support, CQ STARM, STBee, and STBee Mini are also our
targets. But those targets with DfuSe are basically not for normal targets. But those targets with DfuSe are basically not for normal
@@ -179,8 +192,8 @@ The author(s) of Gnuk expect users of Gnuk will be able to access the
source code of Gnuk, so that users can study the code and can modify source code of Gnuk, so that users can study the code and can modify
if needed. This doesn't mean person who has a USB Token by Gnuk if needed. This doesn't mean person who has a USB Token by Gnuk
should be able to acess everything on the Token, regardless of its should be able to acess everything on the Token, regardless of its
protections. Private keys, random bytes, and other information should protections. Private keys, and other information should be protected
be protected properly. properly.
External source code External source code
@@ -232,8 +245,24 @@ How to compile
You need GNU toolchain and newlib for 'arm-none-eabi' target. You need GNU toolchain and newlib for 'arm-none-eabi' target.
See http://github.com/uwehermann/summon-arm-toolchain/ for preparation See http://github.com/esden/summon-arm-toolchain/ (which includes fix
of GNU Toolchain for 'arm-none-eabi' target. of binutils-2.21.1) for preparation of GNU Toolchain for
'arm-none-eabi' target.
# Note that we need to link correct C library (for string functions).
# For this purpose, Makefile.in contains following line:
#
# MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
#
# This should not be needed (as -mcpu=cortex-m3 means
# -mfix-cortex-m3-ldrd), but in practice it is needed for
# the configuration of patch-gcc-config-arm-t-arm-elf.diff in
# summon-arm-toolchain.
#
# In ChibiOS_2.0.8/os/ports/GCC/ARM/rules.mk, it specifies
# -mno-thumb-interwork option. This means that you should not
# link C library which contains ARM (not Thumb) code.
Change directory to `src': Change directory to `src':
@@ -270,6 +299,36 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ $
Flying Stone Tiny 01
--------------------
If you are using Flying Stone Tiny 01, you need a SWD writer. I am
using revision 946 of Simon Qian's Versaloon.
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
For OpenOCD, we need unofficial patch.
See the article of Versaloon Forum:
http://www.versaloon.com/bbs/viewtopic.php?p=16179
Type following to invoke OpenOCD:
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
STM8S Discovery Kit STM8S Discovery Kit
------------------- -------------------
@@ -341,19 +400,7 @@ How to configure
You need python and pyscard (python-pyscard package in Debian) or You need python and pyscard (python-pyscard package in Debian) or
PyUSB (python-usb package in Debian). PyUSB (python-usb package in Debian).
(1) In the 'src' directory, type (1) [pyscard] Stop scdaemon
$ make random_bits
In this process, it takes time for the command of
dd if=/dev/random bs=1 of=random_bits count=1024
Don't just wait, but do some other works on your PC.
/dev/random needs entropy to finish.
(2) [pyscard] Stop scdaemon
[PyUSB] Stop the pcsc daemon. [PyUSB] Stop the pcsc daemon.
If scdaemon is running, please kill it, or you will get "Smartcard If scdaemon is running, please kill it, or you will get "Smartcard
@@ -366,17 +413,7 @@ In case of PyUSB tool, you need to stop pcscd.
# /etc/init.d/pcscd stop # /etc/init.d/pcscd stop
(3) Write the random bits to the device (2) [Optional] Write fixed serial number
Connect your board to USB port of your PC. And invoke gnuk_put_binary.py:
$ ../tool/gnuk_put_binary.py -r random_bits
random_bits: 1024
Updating random bits
...
(4) [Optional] Write fixed serial number
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do: If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
@@ -384,7 +421,7 @@ If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
Writing serial number Writing serial number
... ...
(5) [Optional] Write card holder certificate (3) [Optional] Write card holder certificate
If you have card holder certificate binary file, you can do: If you have card holder certificate binary file, you can do:

107
boards/FST_01/board.c Normal file
View File

@@ -0,0 +1,107 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
#include "../common/hwinit.c"
void
hwinit0 (void)
{
hwinit0_common ();
}
void
hwinit1 (void)
{
hwinit1_common ();
#if defined(PINPAD_SUPPORT)
/* PA0/TIM2_CH1 = 1 (pull up) */
/* PA1/TIM2_CH2 = 0 (pull down) */
/* PA2/TIM2_CH3 <= Vout of CIR receiver module */
/* EXTI2 <= PA2 */
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI2_PA;
EXTI->IMR = 0;
EXTI->FTSR = EXTI_FTSR_TR2;
NVICEnableVector(EXTI2_IRQn,
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
/* TIM2 */
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
RCC->APB1RSTR = RCC_APB1RSTR_TIM2RST;
RCC->APB1RSTR = 0;
NVICEnableVector(TIM2_IRQn,
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
TIM2->CR1 = TIM_CR1_URS | TIM_CR1_ARPE;
TIM2->CR2 = TIM_CR2_TI1S;
TIM2->SMCR = TIM_SMCR_TS_0 | TIM_SMCR_TS_2 | TIM_SMCR_SMS_2;
TIM2->DIER = 0; /* Disable interrupt for now */
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_3
| TIM_CCMR1_CC2S_1 | TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_3;
TIM2->CCMR2 = 0;
TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
TIM2->PSC = 72 - 1; /* 1 MHz */
TIM2->ARR = 18000; /* 18 ms */
/* Generate UEV to upload PSC and ARR */
TIM2->EGR = TIM_EGR_UG;
#endif
}
void
USB_Cable_Config (int NewState)
{
if (NewState != DISABLE)
palSetPad (IOPORT1, GPIOA_USB_ENABLE);
else
palClearPad (IOPORT1, GPIOA_USB_ENABLE);
}
void
set_led (int value)
{
if (value)
palSetPad (IOPORT2, GPIOB_LED);
else
palClearPad (IOPORT2, GPIOB_LED);
}
#if defined(PINPAD_SUPPORT)
void
cir_ext_disable (void)
{
EXTI->PR = EXTI_PR_PR2;
EXTI->IMR &= ~EXTI_IMR_MR2;
}
void
cir_ext_enable (void)
{
EXTI->IMR |= EXTI_IMR_MR2;
}
extern void cir_ext_interrupt (void);
extern void cir_timer_interrupt (void);
CH_IRQ_HANDLER (EXTI2_IRQHandler)
{
CH_IRQ_PROLOGUE ();
chSysLockFromIsr ();
cir_ext_interrupt ();
chSysUnlockFromIsr ();
CH_IRQ_EPILOGUE ();
}
CH_IRQ_HANDLER (TIM2_IRQHandler)
{
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
cir_timer_interrupt ();
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
#endif

138
boards/FST_01/board.h Normal file
View File

@@ -0,0 +1,138 @@
/*
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 FST-01 board.
*/
/*
* Board identifier.
*/
#define BOARD_FST_01
#define BOARD_NAME "FST-01"
/*
* 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
#define CPU_WITH_NO_GPIOE 1
/*
* IO pins assignments.
*/
#define GPIOB_LED 0
#define GPIOA_USB_ENABLE 10
#define GPIOA_SPI1NSS 4
/*
* Timer assignment for CIR
*/
#define TIMx TIM2
/*
* 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.
* PA0 - input with pull-up (TIM2_CH1)
* PA1 - input with pull-down (TIM2_CH2)
* PA2 - input with pull-up (TIM2_CH3)
* PA11 - input with pull-up (USBDM)
* PA12 - input with pull-up (USBDP)
* Everything input with pull-up except:
* PA10 - Push pull output (USB 1:ON 0:OFF)
*/
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888388 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFD
/*
* Port B setup.
* Everything input with pull-up except:
* PB0 - Push pull output (LED 1:ON 0:OFF)
*/
#define VAL_GPIOBCRL 0x88888883 /* PB7...PB0 */
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* PD0 - Normal input (XTAL).
* PD1 - Normal input (XTAL).
*/
#define VAL_GPIODCRL 0x88888844 /* 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
#endif /* _BOARD_H_ */

15
boards/FST_01/mcuconf.h Normal file
View File

@@ -0,0 +1,15 @@
/*
* 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 6
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_ADCPRE STM32_ADCPRE_DIV4
#define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_MCO STM32_MCO_NOCLOCK
#include "mcuconf-common.h"

36
boards/FST_01_00/board.c Normal file
View File

@@ -0,0 +1,36 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
#include "../common/hwinit.c"
void
hwinit0 (void)
{
hwinit0_common ();
}
void
hwinit1 (void)
{
hwinit1_common ();
}
void
USB_Cable_Config (int NewState)
{
if (NewState != DISABLE)
palSetPad (IOPORT1, GPIOA_USB_ENABLE);
else
palClearPad (IOPORT1, GPIOA_USB_ENABLE);
}
void
set_led (int value)
{
if (value)
palSetPad (IOPORT1, GPIOA_LED);
else
palClearPad (IOPORT1, GPIOA_LED);
}

129
boards/FST_01_00/board.h Normal file
View File

@@ -0,0 +1,129 @@
/*
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 FST-01 board (experimental version 00).
*/
/*
* Board identifier.
*/
#define BOARD_FST_01
#define BOARD_NAME "FST-01-00"
/*
* 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
#define CPU_WITH_NO_GPIOE 1
/*
* IO pins assignments.
*/
#define GPIOA_LED 8
#define GPIOA_USB_ENABLE 10
/*
* 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.
* PA11 - input with pull-up (USBDM)
* PA12 - input with pull-up (USBDP)
* Everything input with pull-up except:
* PA8 - Push pull output (LED 1:ON 0:OFF)
* PA10 - Push pull output (USB 1:ON 0:OFF)
*/
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888383 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFF
/*
* Port B setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* PD0 - Normal input (XTAL).
* PD1 - Normal input (XTAL).
*/
#define VAL_GPIODCRL 0x88888844 /* 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
#endif /* _BOARD_H_ */

View File

@@ -0,0 +1,15 @@
/*
* 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_DIV2
#define STM32_ADCPRE STM32_ADCPRE_DIV4
#define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_MCO STM32_MCO_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -28,14 +28,14 @@
#define _BOARD_H_ #define _BOARD_H_
/* /*
* Setup for the Olimex STM32-P103 proto board. * Setup for the Olimex STM32-H103 proto board.
*/ */
/* /*
* Board identifier. * Board identifier.
*/ */
#define BOARD_OLIMEX_STM32_P103 #define BOARD_OLIMEX_STM32_H103
#define BOARD_NAME "Olimex STM32-P103" #define BOARD_NAME "Olimex STM32-H103"
/* /*
* Board frequencies. * Board frequencies.

View File

@@ -40,6 +40,10 @@
#if defined(PINPAD_SUPPORT) #if defined(PINPAD_SUPPORT)
#define HAVE_7SEGLED 1 #define HAVE_7SEGLED 1
/*
* Timer assignment for CIR
*/
#define TIMx TIM3
#endif #endif
/* /*

View File

@@ -41,6 +41,10 @@
#if defined(PINPAD_SUPPORT) #if defined(PINPAD_SUPPORT)
#define HAVE_7SEGLED 1 #define HAVE_7SEGLED 1
/*
* Timer assignment for CIR
*/
#define TIMx TIM3
#endif #endif
/* /*

View File

@@ -10,3 +10,5 @@
#define STM32_PPRE2 STM32_PPRE2_DIV2 #define STM32_PPRE2 STM32_PPRE2_DIV2
#define STM32_ADCPRE STM32_ADCPRE_DIV4 #define STM32_ADCPRE STM32_ADCPRE_DIV4
#define STM32_MCO STM32_MCO_NOCLOCK #define STM32_MCO STM32_MCO_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -56,6 +56,11 @@
*/ */
#define GPIOA_LED 8 #define GPIOA_LED 8
/*
* Timer assignment for CIR
*/
#define TIMx TIM3
/* /*
* I/O ports initial setup, this configuration is established soon after reset * I/O ports initial setup, this configuration is established soon after reset
* in the initialization code. * in the initialization code.

View File

@@ -41,7 +41,7 @@
/* /*
* ADC driver system settings. * ADC driver system settings.
*/ */
#define USE_STM32_ADC1 FALSE #define USE_STM32_ADC1 TRUE
#define STM32_ADC1_DMA_PRIORITY 3 #define STM32_ADC1_DMA_PRIORITY 3
#define STM32_ADC1_IRQ_PRIORITY 5 #define STM32_ADC1_IRQ_PRIORITY 5
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt() #define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()

View File

@@ -91,7 +91,7 @@ CSRC = $(PORTSRC) \
main.c usb_lld.c \ main.c usb_lld.c \
usb_desc.c usb_prop.c \ usb_desc.c usb_prop.c \
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \
random.c random.c neug.c
ifneq ($(ENABLE_DEBUG),) ifneq ($(ENABLE_DEBUG),)
CSRC += debug.c CSRC += debug.c
@@ -205,9 +205,7 @@ ifeq ($(USE_FWLIB),yes)
endif endif
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
random_bits:
dd if=/dev/random bs=1 of=random_bits count=1024
distclean: clean distclean: clean
-rm -f Makefile gnuk.ld config.h random_bits -rm -f Makefile gnuk.ld config.h

View File

@@ -75,7 +75,7 @@ verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len)) || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
goto failure; goto failure;
else else
goto success; goto success_one_step;
} }
else else
pw_len = ks_pw1[0]; pw_len = ks_pw1[0];
@@ -88,15 +88,15 @@ verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
return -1; return -1;
} }
success_one_step:
sha1 (pw, pw_len, keystring); sha1 (pw, pw_len, keystring);
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring)) if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring))
< 0) < 0)
goto failure; goto failure;
else if (r == 0) else if (r == 0)
if (memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 0) if (ks_pw1 != NULL && memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 0)
goto failure; goto failure;
success:
gpg_pw_reset_err_counter (PW_ERR_PW1); gpg_pw_reset_err_counter (PW_ERR_PW1);
return pw_len; return pw_len;
} }
@@ -172,7 +172,7 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
count -= pw_len + 8; count -= pw_len + 8;
} }
if (count < 8) if (count <= 8)
sha1_update (&sha1_ctx, salt, count); sha1_update (&sha1_ctx, salt, count);
else else
{ {

View File

@@ -1,7 +1,7 @@
/* /*
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
* *
* Copyright (C) 2010 Free Software Initiative of Japan * Copyright (C) 2010, 2011 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -28,7 +28,9 @@
#include "polarssl/config.h" #include "polarssl/config.h"
#include "polarssl/rsa.h" #include "polarssl/rsa.h"
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */ #define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
/* 256 byte == 2048-bit */
/* 128 byte == 1024-bit */
static rsa_context rsa_ctx; static rsa_context rsa_ctx;
@@ -43,10 +45,10 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
mpi_init (&P1, &Q1, &H, NULL); mpi_init (&P1, &Q1, &H, NULL);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = 2048 / 8; rsa_ctx.len = KEY_CONTENT_LEN;
mpi_read_string (&rsa_ctx.E, 16, "10001"); mpi_read_string (&rsa_ctx.E, 16, "10001");
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2); mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], rsa_ctx.len / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2);
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
@@ -90,23 +92,25 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
} }
} }
/*
* LEN: length in byte
*/
const uint8_t * const uint8_t *
modulus_calc (const uint8_t *p, int len) modulus_calc (const uint8_t *p, int len)
{ {
mpi P, Q, N; mpi P, Q, N;
uint8_t *modulus; uint8_t *modulus;
(void)len; /* 2048-bit assumed */ modulus = malloc (len);
modulus = malloc (2048 / 8);
if (modulus == NULL) if (modulus == NULL)
return NULL; return NULL;
mpi_init (&P, &Q, &N, NULL); mpi_init (&P, &Q, &N, NULL);
mpi_read_binary (&P, p, 2048 / 8 / 2); mpi_read_binary (&P, p, len / 2);
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2); mpi_read_binary (&Q, p + len / 2, len / 2);
mpi_mul_mpi (&N, &P, &Q); mpi_mul_mpi (&N, &P, &Q);
mpi_write_binary (&N, modulus, 2048 / 8); mpi_write_binary (&N, modulus, len);
mpi_free (&P, &Q, &N, NULL); mpi_free (&P, &Q, &N, NULL);
return modulus; return modulus;
} }
@@ -135,8 +139,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
DEBUG_WORD (msg_len); DEBUG_WORD (msg_len);
mpi_read_string (&rsa_ctx.E, 16, "10001"); mpi_read_string (&rsa_ctx.E, 16, "10001");
mpi_read_binary (&rsa_ctx.P, &kd->data[0], 2048 / 8 / 2); mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2);
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], 2048 / 8 / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
KEY_CONTENT_LEN / 2);
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1);

View File

@@ -10,7 +10,7 @@
#define CH_OPTIMIZE_SPEED TRUE #define CH_OPTIMIZE_SPEED TRUE
#define CH_USE_REGISTRY TRUE #define CH_USE_REGISTRY TRUE
#define CH_USE_WAITEXIT TRUE #define CH_USE_WAITEXIT TRUE
#define CH_USE_SEMAPHORES FALSE #define CH_USE_SEMAPHORES TRUE
#define CH_USE_SEMAPHORES_PRIORITY FALSE #define CH_USE_SEMAPHORES_PRIORITY FALSE
#define CH_USE_SEMSW FALSE #define CH_USE_SEMSW FALSE
#define CH_USE_MUTEXES TRUE #define CH_USE_MUTEXES TRUE

View File

@@ -147,8 +147,6 @@ flash_erase_page (uint32_t addr)
* .bss * .bss
* _end * _end
* <alignment to page> * <alignment to page>
* random_bits_start
* <one page>
* ch_certificate_startp * ch_certificate_startp
* <2048 bytes> * <2048 bytes>
* _data_pool * _data_pool
@@ -613,15 +611,6 @@ flash_erase_binary (uint8_t file_id)
#endif #endif
} }
return 0;
}
else if (file_id == FILEID_RANDOM)
{
p = &random_bits_start;
if (flash_check_blank (p, FLASH_PAGE_SIZE) == 0)
flash_erase_page ((uint32_t)p);
return 0; return 0;
} }
else else
@@ -641,11 +630,6 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
maxsize = FLASH_CH_CERTIFICATE_SIZE; maxsize = FLASH_CH_CERTIFICATE_SIZE;
p = &ch_certificate_start; p = &ch_certificate_start;
} }
else if (file_id == FILEID_RANDOM)
{
maxsize = FLASH_PAGE_SIZE;
p = &random_bits_start;
}
else if (file_id == FILEID_SERIAL_NO) else if (file_id == FILEID_SERIAL_NO)
{ {
maxsize = 6; maxsize = 6;

View File

@@ -292,6 +292,7 @@ extern uint8_t admin_authorized;
#define SIZE_PW_STATUS_BYTES 7 #define SIZE_PW_STATUS_BYTES 7
extern void random_init (void);
/* 16-byte random bytes */ /* 16-byte random bytes */
extern const uint8_t *random_bytes_get (void); extern const uint8_t *random_bytes_get (void);
extern void random_bytes_free (const uint8_t *); extern void random_bytes_free (const uint8_t *);
@@ -332,6 +333,15 @@ extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *da
extern const unsigned char *unique_device_id (void); extern const unsigned char *unique_device_id (void);
extern const uint8_t gnukStringSerial[]; extern const uint8_t gnukStringSerial[];
#define LED_ONESHOT_SHORT ((eventmask_t)1)
#define LED_ONESHOT_LONG ((eventmask_t)2)
#define LED_TWOSHOT ((eventmask_t)4)
#define LED_STATUS_MODE ((eventmask_t)8)
#define LED_INPUT_MODE ((eventmask_t)16)
#define LED_FATAL_MODE ((eventmask_t)32)
extern Thread *main_thread;
extern void led_blink (int spec);
#if defined(PINPAD_SUPPORT) #if defined(PINPAD_SUPPORT)
#if defined(PINPAD_CIR_SUPPORT) #if defined(PINPAD_CIR_SUPPORT)
extern void cir_ext_disable (void); extern void cir_ext_disable (void);
@@ -347,5 +357,6 @@ extern void dial_sw_enable (void);
extern uint8_t pin_input_buffer[MAX_PIN_CHARS]; extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
extern uint8_t pin_input_len; extern uint8_t pin_input_len;
extern msg_t pin_main (void *arg); extern int pinpad_getline (int msg_code, systime_t timeout);
#endif #endif

View File

@@ -28,7 +28,8 @@
* ST32F103 memory setup. * ST32F103 memory setup.
*/ */
__main_stack_size__ = 0x0400; __main_stack_size__ = 0x0400;
__stacks_total_size__ = __main_stack_size__; __process_stack_size__ = 0x0200;
__stacks_total_size__ = __main_stack_size__ + __process_stack_size__;
MEMORY MEMORY
{ {
@@ -114,14 +115,6 @@ SECTIONS
PROVIDE(end = .); PROVIDE(end = .);
_end = .; _end = .;
.gnuk_random :
{
. = ALIGN (@FLASH_PAGE_SIZE@);
random_bits_start = .;
LONG(0xffffffff);
. = ALIGN (@FLASH_PAGE_SIZE@);
} > flash =0xffffffff
.gnuk_ch_certificate : .gnuk_ch_certificate :
{ {
. = ALIGN (@FLASH_PAGE_SIZE@); . = ALIGN (@FLASH_PAGE_SIZE@);

View File

@@ -6,7 +6,7 @@
#include "mcuconf.h" #include "mcuconf.h"
#define CH_HAL_USE_PAL TRUE #define CH_HAL_USE_PAL TRUE
#define CH_HAL_USE_ADC FALSE #define CH_HAL_USE_ADC TRUE
#define CH_HAL_USE_CAN FALSE #define CH_HAL_USE_CAN FALSE
#define CH_HAL_USE_MAC FALSE #define CH_HAL_USE_MAC FALSE
#define CH_HAL_USE_PWM FALSE #define CH_HAL_USE_PWM FALSE

View File

@@ -1,7 +1,7 @@
/* /*
* main.c - main routine of Gnuk * main.c - main routine of Gnuk
* *
* Copyright (C) 2010 Free Software Initiative of Japan * Copyright (C) 2010, 2011 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -196,6 +196,161 @@ device_initialize_once (void)
static volatile uint8_t fatal_code; static volatile uint8_t fatal_code;
Thread *main_thread;
#define GNUK_INIT 0
#define GNUK_RUNNING 1
#define GNUK_INPUT_WAIT 2
#define GNUK_FATAL 255
/*
* 0 for initializing
* 1 for normal mode
* 2 for input waiting
* 255 for fatal
*/
static uint8_t main_mode;
static void display_interaction (void)
{
eventmask_t m;
while (1)
{
m = chEvtWaitOne (ALL_EVENTS);
set_led (1);
switch (m)
{
case LED_ONESHOT_SHORT:
chThdSleep (MS2ST (100));
break;
case LED_ONESHOT_LONG:
chThdSleep (MS2ST (400));
break;
case LED_TWOSHOT:
chThdSleep (MS2ST (50));
set_led (0);
chThdSleep (MS2ST (50));
set_led (1);
chThdSleep (MS2ST (50));
break;
case LED_STATUS_MODE:
chThdSleep (MS2ST (400));
set_led (0);
return;
case LED_FATAL_MODE:
main_mode = GNUK_FATAL;
set_led (0);
return;
default:
break;
}
set_led (0);
}
}
static void display_fatal_code (void)
{
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
set_led (1);
if (fatal_code & 1)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if (fatal_code & 2)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
}
static void display_status_code (void)
{
if (icc_state == ICC_STATE_START)
{
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 3);
}
else
/* GPGthread running */
{
set_led (1);
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
if (icc_state == ICC_STATE_WAIT)
{
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 2);
}
else if (icc_state == ICC_STATE_RECEIVE)
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
}
else
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
}
}
}
void
led_blink (int spec)
{
if (spec == 0)
chEvtSignal (main_thread, LED_ONESHOT_SHORT);
else if (spec == 1)
chEvtSignal (main_thread, LED_ONESHOT_LONG);
else
chEvtSignal (main_thread, LED_TWOSHOT);
}
/* /*
* Entry point. * Entry point.
* *
@@ -210,10 +365,13 @@ main (int argc, char **argv)
(void)argc; (void)argc;
(void)argv; (void)argv;
main_thread = chThdSelf ();
flash_unlock (); flash_unlock ();
device_initialize_once (); device_initialize_once ();
usb_lld_init (); usb_lld_init ();
USB_Init(); USB_Init ();
random_init ();
#ifdef DEBUG #ifdef DEBUG
stdout_init (); stdout_init ();
@@ -230,105 +388,47 @@ main (int argc, char **argv)
while (1) while (1)
{ {
count++; eventmask_t m;
if (fatal_code != 0) count++;
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL);
switch (m)
{ {
case LED_STATUS_MODE:
main_mode = GNUK_RUNNING;
break;
case LED_FATAL_MODE:
main_mode = GNUK_FATAL;
break;
case LED_INPUT_MODE:
main_mode = GNUK_INPUT_WAIT;
set_led (1); set_led (1);
chThdSleep (LED_TIMEOUT_ZERO); chThdSleep (MS2ST (400));
set_led (0); set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL); break;
set_led (1); default:
chThdSleep (LED_TIMEOUT_ZERO); break;
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
set_led (1);
if (fatal_code & 1)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if (fatal_code & 2)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
} }
if (bDeviceState != CONFIGURED) switch (main_mode)
{ {
case GNUK_FATAL:
display_fatal_code ();
break;
case GNUK_INIT:
set_led (1); set_led (1);
chThdSleep (LED_TIMEOUT_ZERO); chThdSleep (LED_TIMEOUT_ZERO);
set_led (0); set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 3); chThdSleep (LED_TIMEOUT_STOP * 3);
break;
case GNUK_INPUT_WAIT:
display_interaction ();
break;
case GNUK_RUNNING:
default:
display_status_code ();
break;
} }
else
/* Device configured */
if (icc_state == ICC_STATE_START)
{
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 3);
}
else
/* GPGthread running */
{
set_led (1);
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
if (icc_state == ICC_STATE_WAIT)
{
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 2);
}
else if (icc_state == ICC_STATE_RECEIVE)
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
}
else
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
}
}
#ifdef DEBUG_MORE #ifdef DEBUG_MORE
if (bDeviceState == CONFIGURED && (count % 10) == 0) if (bDeviceState == CONFIGURED && (count % 10) == 0)
@@ -348,6 +448,7 @@ void
fatal (uint8_t code) fatal (uint8_t code)
{ {
fatal_code = code; fatal_code = code;
chEvtSignal (main_thread, LED_FATAL_MODE);
_write ("fatal\r\n", 7); _write ("fatal\r\n", 7);
for (;;); for (;;);
} }

453
src/neug.c Normal file
View File

@@ -0,0 +1,453 @@
/*
* neug.c - random number generation (from NeuG/src/random.c)
*
* Copyright (C) 2011 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a Random Number Generator
* implementation (for STM32F103).
*
* NeuG is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "ch.h"
#include "hal.h"
static Thread *rng_thread;
#define ADC_DATA_AVAILABLE ((eventmask_t)1)
/* Total number of channels to be sampled by a single ADC operation.*/
#define ADC_GRP1_NUM_CHANNELS 2
/* Depth of the conversion buffer, channels are sampled one time each.*/
#define ADC_GRP1_BUF_DEPTH 4
/*
* ADC samples buffer.
*/
static adcsample_t samp[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
static void adccb (adcsample_t *buffer, size_t n);
/*
* ADC conversion group.
* Mode: Linear buffer, 4 samples of 2 channels, SW triggered.
* Channels: Vref (1.5 cycles sample time, violating the spec.)
* Sensor (1.5 cycles sample time, violating the spec.)
*/
static const ADCConversionGroup adcgrpcfg = {
FALSE,
ADC_GRP1_NUM_CHANNELS,
0,
ADC_CR2_EXTSEL_SWSTART | ADC_CR2_TSVREFE | ADC_CR2_CONT,
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_1P5) | ADC_SMPR1_SMP_VREF(ADC_SAMPLE_1P5),
0,
ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
0,
ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) | ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)
};
/*
* ADC end conversion callback.
*/
static void adccb (adcsample_t *buffer, size_t n)
{
ADCDriver *adcp = &ADCD1;
(void) buffer; (void) n;
if (adcp->ad_state == ADC_COMPLETE)
chEvtSignalI (rng_thread, ADC_DATA_AVAILABLE);
}
/*
* TinyMT routines.
*
* See
* "Tiny Mersenne Twister (TinyMT): A small-sized variant of Mersenne Twister"
* by Mutsuo Saito and Makoto Matsumoto
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/
*/
/* Use the first example of TinyMT */
#define TMT_MAT1 0x8f7011ee
#define TMT_MAT2 0xfc78ff1f
#define TMT_TMAT 0x3793fdff
static uint32_t tmt[4];
static void tmt_one_step (void);
#define TMT_INIT_MIN_LOOP 8
#define TMT_INIT_PRE_LOOP 8
/**
* @brief TinyMT initialize function.
*/
static void tmt_init (uint32_t seed)
{
int i;
tmt[0] = seed;
tmt[1] = TMT_MAT1;
tmt[2] = TMT_MAT2;
tmt[3] = TMT_TMAT;
for (i = 1; i < TMT_INIT_MIN_LOOP; i++)
tmt[i & 3] ^= i + UINT32_C(1812433253) * (tmt[(i - 1) & 3]
^ (tmt[(i - 1) & 3] >> 30));
if ((tmt[0] & 0x7fffffff) == 0 && tmt[1] == 0 && tmt[2] == 0 && tmt[3] == 0)
{ /* Prevent all zero */
tmt[0] = 'T';
tmt[1] = 'I';
tmt[2] = 'N';
tmt[3] = 'Y';
}
for (i = 0; i < TMT_INIT_PRE_LOOP; i++)
tmt_one_step ();
}
/**
* @brief TinyMT one step function, call this every time before tmt_value.
*/
static void tmt_one_step (void)
{
uint32_t x, y;
y = tmt[3];
x = (tmt[0] & 0x7fffffff) ^ tmt[1] ^ tmt[2];
x ^= (x << 1);
y ^= (y >> 1) ^ x;
tmt[0] = tmt[1];
tmt[1] = tmt[2];
tmt[2] = x ^ (y << 10);
tmt[3] = y;
if ((y & 1))
{
tmt[1] ^= TMT_MAT1;
tmt[2] ^= TMT_MAT2;
}
}
/**
* @brief Get a random word (32-bit).
*/
static uint32_t tmt_value (void)
{
uint32_t t0, t1;
t0 = tmt[3];
t1 = tmt[0] + (tmt[2] >> 8);
t0 ^= t1;
if ((t1 & 1))
t0 ^= TMT_TMAT;
return t0;
}
/* 8 parallel CRC-16 shift registers, with randomly rotated feedback */
#define EPOOL_SIZE 16
static uint8_t epool[EPOOL_SIZE]; /* Big-endian */
static uint8_t ep_count;
/*
* Magic number seven.
*
* We did an experiment of measuring entropy of ADC output with MUST.
* The entropy of a byte by raw sampling of LSBs has more than 6.0 bit/byte.
* So, it is considered OK to get 4-byte from 7-byte (6x7 = 42 > 32).
*/
#define NUM_NOISE_INPUTS 7
#define SHIFT_RIGHT(f) ((f)>>1)
static void ep_add (uint8_t entropy_bits, uint8_t another_random_bit)
{
uint8_t v = epool[ep_count];
/* CRC-16-CCITT's Polynomial is: x^16 + x^12 + x^5 + 1 */
epool[(ep_count - 12)& 0x0f] ^= v;
epool[(ep_count - 5)& 0x0f] ^= v;
epool[ep_count] = SHIFT_RIGHT (v) ^ entropy_bits;
if ((v&1) || another_random_bit)
epool[ep_count] ^= 0xff;
ep_count = (ep_count + 1) & 0x0f;
}
#define FNV_INIT 2166136261U
#define FNV_PRIME 16777619
static uint32_t fnv32_hash (const uint8_t *buf, int len)
{
uint32_t v = FNV_INIT;
int i;
for (i = 0; i < len; i++)
{
v ^= buf[i];
v *= FNV_PRIME;
}
return v;
}
#define PROBABILITY_50_BY_TICK() ((SysTick->VAL & 0x02) != 0)
static uint32_t ep_output (void)
{
int i;
uint8_t buf[NUM_NOISE_INPUTS];
uint8_t *p = buf;
/*
* NUM_NOISE_INPUTS is seven.
*
* There are sixteen bytes in the CRC-16 buffer. We use seven
* outputs of CRC-16 buffer for final output. There are two parts;
* former 4 outputs which will be used directly, and latter 3
* outputs which will be used with feedback loop.
*/
/* At some probability, use latter 3 outputs of CRC-16 buffer */
for (i = NUM_NOISE_INPUTS - 1; i >= 4; i--)
if (PROBABILITY_50_BY_TICK ())
*p++ = epool[(ep_count+i) & 0x0f] ^ epool[(ep_count+i-4) & 0x0f];
/* Use former 4 outputs of CRC-16 buffer */
for (i = 3; i >= 0; i--)
*p++ = epool[(ep_count+i) & 0x0f];
return fnv32_hash (buf, p - buf);
}
/*
* Ring buffer, filled by generator, consumed by neug_get routine.
*/
struct rng_rb {
uint32_t *buf;
Mutex m;
CondVar data_available;
CondVar space_available;
uint8_t head, tail;
uint8_t size;
unsigned int full :1;
unsigned int empty :1;
};
static void rb_init (struct rng_rb *rb, uint32_t *p, uint8_t size)
{
rb->buf = p;
rb->size = size;
chMtxInit (&rb->m);
chCondInit (&rb->data_available);
chCondInit (&rb->space_available);
rb->head = rb->tail = 0;
rb->full = 0;
rb->empty = 1;
}
static void rb_add (struct rng_rb *rb, uint32_t v)
{
rb->buf[rb->tail++] = v;
if (rb->tail == rb->size)
rb->tail = 0;
if (rb->tail == rb->head)
rb->full = 1;
rb->empty = 0;
}
static uint32_t rb_del (struct rng_rb *rb)
{
uint32_t v = rb->buf[rb->head++];
if (rb->head == rb->size)
rb->head = 0;
if (rb->head == rb->tail)
rb->empty = 1;
rb->full = 0;
return v;
}
/**
* @brief Random number generation from ADC sampling.
* @param RB: Pointer to ring buffer structure
* @return -1 when failure, 0 otherwise.
* @note Called holding the mutex, with RB->full == 0.
* Keep generating until RB->full == 1.
*/
static int rng_gen (struct rng_rb *rb)
{
static uint8_t round = 0;
uint8_t b;
while (1)
{
chEvtWaitOne (ADC_DATA_AVAILABLE);
/* Got, ADC sampling data */
round++;
b = (((samp[0] & 0x01) << 0) | ((samp[1] & 0x01) << 1)
| ((samp[2] & 0x01) << 2) | ((samp[3] & 0x01) << 3)
| ((samp[4] & 0x01) << 4) | ((samp[5] & 0x01) << 5)
| ((samp[6] & 0x01) << 6) | ((samp[7] & 0x01) << 7));
adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH, adccb);
/*
* Put a random byte to entropy pool.
*/
ep_add (b, PROBABILITY_50_BY_TICK ());
if ((round % NUM_NOISE_INPUTS) == 0)
{ /* We have enough entropy in the pool. */
uint32_t v = ep_output (); /* Get the random bits from the pool. */
/* Mix the random bits from the pool with the output of PRNG. */
tmt_one_step ();
v ^= tmt_value ();
/* We got the final random bits, add it to the ring buffer. */
rb_add (rb, v);
round = 0;
if (rb->full)
/* fully generated */
break;
}
}
return 0; /* success */
}
/**
* @brief Random number generation thread.
*/
static msg_t rng (void *arg)
{
struct rng_rb *rb = (struct rng_rb *)arg;
rng_thread = chThdSelf ();
adcStart (&ADCD1, NULL);
adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH, adccb);
while (1)
{
chMtxLock (&rb->m);
while (rb->full)
chCondWait (&rb->space_available);
rng_gen (rb);
chCondSignal (&rb->data_available);
chMtxUnlock ();
}
return 0;
}
static struct rng_rb the_ring_buffer;
static WORKING_AREA(wa_rng, 128);
/**
* @brief Initialize NeuG.
*/
void
neug_init (uint32_t *buf, uint8_t size)
{
struct rng_rb *rb = &the_ring_buffer;
tmt_init (0);
rb_init (rb, buf, size);
chThdCreateStatic (wa_rng, sizeof (wa_rng), NORMALPRIO, rng, rb);
}
/**
* @breif Flush random bytes.
*/
void
neug_flush (void)
{
struct rng_rb *rb = &the_ring_buffer;
chMtxLock (&rb->m);
while (!rb->empty)
(void)rb_del (rb);
chCondSignal (&rb->space_available);
chMtxUnlock ();
}
/**
* @breif Set seed to PRNG
*/
void
neug_prng_reseed (void)
{
uint32_t seed = ep_output ();
tmt_init (seed);
neug_flush ();
}
/**
* @brief Wakes up RNG thread to generate random numbers.
*/
void
neug_kick_filling (void)
{
struct rng_rb *rb = &the_ring_buffer;
chMtxLock (&rb->m);
if (!rb->full)
chCondSignal (&rb->space_available);
chMtxUnlock ();
}
/**
* @brief Get random word (32-bit) from NeuG.
* @detail With NEUG_KICK_FILLING, it wakes up RNG thread.
* With NEUG_NO_KICK, it doesn't wake up RNG thread automatically,
* it is needed to call neug_kick_filling later.
*/
uint32_t
neug_get (int kick)
{
struct rng_rb *rb = &the_ring_buffer;
uint32_t v;
chMtxLock (&rb->m);
while (rb->empty)
chCondWait (&rb->data_available);
v = rb_del (rb);
if (kick)
chCondSignal (&rb->space_available);
chMtxUnlock ();
return v;
}
void
neug_wait_full (void)
{
struct rng_rb *rb = &the_ring_buffer;
chMtxLock (&rb->m);
while (!rb->full)
chCondWait (&rb->data_available);
chMtxUnlock ();
}

11
src/neug.h Normal file
View File

@@ -0,0 +1,11 @@
#define NEUG_NO_KICK 0
#define NEUG_KICK_FILLING 1
#define NEUG_PRE_LOOP 16
void neug_init (uint32_t *buf, uint8_t size);
void neug_prng_reseed (void);
uint32_t neug_get (int kick);
void neug_kick_filling (void);
void neug_flush (void);
void neug_wait_full (void);

View File

@@ -627,6 +627,9 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE]; uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
struct key_data_internal kdi; struct key_data_internal kdi;
DEBUG_INFO ("Loading private key: ");
DEBUG_BYTE (kk);
if (do_data == NULL) if (do_data == NULL)
return 0; return 0;
@@ -646,6 +649,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
/* more sanity check??? */ /* more sanity check??? */
memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN); memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN);
DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN);
return 1; return 1;
} }

View File

@@ -97,24 +97,19 @@ gpg_fini (void)
#if defined(PINPAD_SUPPORT) #if defined(PINPAD_SUPPORT)
/* /*
* Invoke the thread PIN_MAIN, and let user input PIN string. * Let user input PIN string.
* Return length of the string. * Return length of the string.
* The string itself is in PIN_INPUT_BUFFER. * The string itself is in PIN_INPUT_BUFFER.
*/ */
static int static int
get_pinpad_input (int msg_code) get_pinpad_input (int msg_code)
{ {
Thread *t; int r;
t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128), chEvtSignal (main_thread, LED_INPUT_MODE);
NORMALPRIO, pin_main, (void *)msg_code); r = pinpad_getline (msg_code, MS2ST (8000));
if (t == NULL) chEvtSignal (main_thread, LED_STATUS_MODE);
return -1; return r;
else
{
chThdWait (t);
return pin_input_len;
}
} }
#endif #endif
@@ -726,6 +721,7 @@ cmd_pso (void)
DEBUG_INFO (" - PSO: "); DEBUG_INFO (" - PSO: ");
DEBUG_WORD ((uint32_t)&r); DEBUG_WORD ((uint32_t)&r);
DEBUG_BINARY (cmd_APDU, cmd_APDU_size);
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a) if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
{ {
@@ -751,6 +747,7 @@ cmd_pso (void)
else else
{ {
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */ DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len, r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
&kd[GPG_KEY_FOR_SIGNING]); &kd[GPG_KEY_FOR_SIGNING]);
@@ -767,6 +764,7 @@ cmd_pso (void)
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86) else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
{ {
DEBUG_SHORT (len); DEBUG_SHORT (len);
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
if (!ac_check_status (AC_OTHER_AUTHORIZED)) if (!ac_check_status (AC_OTHER_AUTHORIZED))
{ {
@@ -1028,12 +1026,9 @@ GPGthread (void *arg)
while (!chThdShouldTerminate ()) while (!chThdShouldTerminate ())
{ {
eventmask_t m; chEvtWaitOne (ALL_EVENTS);
m = chEvtWaitOne (ALL_EVENTS);
DEBUG_INFO ("GPG!: "); DEBUG_INFO ("GPG!: ");
DEBUG_WORD ((uint32_t)&m);
res_APDU_pointer = NULL; /* default */ res_APDU_pointer = NULL; /* default */

View File

@@ -27,13 +27,41 @@
#include "board.h" #include "board.h"
#include "gnuk.h" #include "gnuk.h"
#if 0 #ifdef DEBUG
#define DEBUG_CIR 1 #define DEBUG_CIR 1
#endif #endif
uint8_t pin_input_buffer[MAX_PIN_CHARS]; uint8_t pin_input_buffer[MAX_PIN_CHARS];
uint8_t pin_input_len; uint8_t pin_input_len;
/*
* Supported/tested TV controllers:
*
* Controller of Toshiba REGZA
* Controller of Sony BRAVIA
* Controller of Sharp AQUOS
* Dell Wireless Travel Remote MR425
*
* The code supports RC-5 protocol in fact, but I don't have any
* controller at hand which I can test with, so I don't have any data
* for controller of RC-5.
*
* Current code assumes following mapping:
*
* --------------------------------------
* Protocol Controller
* --------------------------------------
* RC-6 Dell MR425
* NEC Toshiba REGZA
* Sharp Sharp AQUOS
* Sony Sony BRAVIA
* --------------------------------------
*
* In future, when I will have other controllers, this mapping will be
* (should be) configurable, at compile time at least, preferably at
* runtime.
*/
/* /*
* Philips RC-5 Protocol: 14-bit (MSB first) * Philips RC-5 Protocol: 14-bit (MSB first)
* *
@@ -69,18 +97,26 @@ uint8_t pin_input_len;
*/ */
/* /*
* PB0 / TIM3_CH3 * The implementation note of CIR signal decoding (on STM32).
*
* (1) Use EXTI interrupt to detect the first edge of signal.
* (2) Use Timer (with PWM input mode) to measure timings of square wave.
*
*/
/*
* Timer settings.
*
* See THE reference manual (RM0008) section 15.3.6 PWM input mode.
* *
* 72MHz * 72MHz
*
* Prescaler = 72 * Prescaler = 72
* *
* 1us * 1us
* *
* * TIMx_CR1
* TIM3_CR1 * CKD = 00 (tDTS = tCK_INT)
* CKD = 10 (sampling x4) * ARPE = 1 (buffered)
* ARPE = 0 (not buffered)
* CMS = 00 (up counter) * CMS = 00 (up counter)
* DIR = 0 (up counter) * DIR = 0 (up counter)
* OPM = 0 (up counter) * OPM = 0 (up counter)
@@ -88,13 +124,13 @@ uint8_t pin_input_len;
* UDIS = 0 (UEV (update event) enabled) * UDIS = 0 (UEV (update event) enabled)
* CEN = 1 (counter enable) * CEN = 1 (counter enable)
* *
* TIM3_CR2 * TIMx_CR2
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3) * TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
* MMS = 000 (TRGO at Reset) * MMS = 000 (TRGO at Reset)
* CCDS = 0 (DMA on capture) * CCDS = 0 (DMA on capture)
* RSVD = 000 * RSVD = 000
* *
* TIM3_SMCR * TIMx_SMCR
* ETP = 0 * ETP = 0
* ECE = 0 * ECE = 0
* ETPS = 00 * ETPS = 00
@@ -104,61 +140,37 @@ uint8_t pin_input_len;
* RSVD = 0 * RSVD = 0
* SMS = 100 (Reset-mode) * SMS = 100 (Reset-mode)
* *
* TIM3_DIER * TIMx_DIER
* *
* TIM3_SR * TIMx_SR
* *
* TIM3_EGR * TIMx_EGR
* *
* TIM3_CCMR1 * TIMx_CCMR1
* CC1S = 01 (TI1 selected) * CC1S = 01 (TI1 selected)
* CC2S = 10 (TI1 selected) * CC2S = 10 (TI1 selected)
* IC1F = 1001 (fSAMPLING=fDTS/8, N=8)
* IC2F = 1001 (fSAMPLING=fDTS/8, N=8)
* *
* TIM3_CCMR2 * TIMx_CCMR2
* *
* TIM3_CCER * TIMx_CCER
* CC2P = 1 (polarity = falling edge: TI1FP1) * CC2P = 1 (polarity = falling edge: TI1FP1)
* CC2E = 1 * CC2E = 1
* CC1P = 0 (polarity = rising edge: TI1FP1) * CC1P = 0 (polarity = rising edge: TI1FP1)
* CC1E = 1 * CC1E = 1
* *
* TIM3_CNT * TIMx_CNT
* TIM3_PSC = 71 * TIMx_PSC = 71
* TIM3_ARR = 18000 * TIMx_ARR = 18000
* *
* TIM3_CCR1 period * TIMx_CCR1 period
* TIM3_CCR2 duty * TIMx_CCR2 duty
* *
* TIM3_DCR * TIMx_DCR
* TIM3_DMAR * TIMx_DMAR
*/ */
#define PINDISP_TIMEOUT_INTERVAL0 MS2ST(25)
#define PINDISP_TIMEOUT_INTERVAL1 MS2ST(300)
static void
pindisp (uint8_t c)
{
#if defined(HAVE_7SEGLED)
switch (c)
{
case 'G':
palWritePort (IOPORT2, 0xa1ff);
break;
case 'P':
palWritePort (IOPORT2, 0x98ff);
break;
case '.':
palWritePort (IOPORT2, 0x7fff);
break;
default:
palWritePort (IOPORT2, 0xffff);
}
#else
(void)c;
#endif
}
#if defined(DEBUG_CIR) #if defined(DEBUG_CIR)
static uint16_t intr_ext; static uint16_t intr_ext;
static uint16_t intr_trg; static uint16_t intr_trg;
@@ -179,14 +191,6 @@ static uint8_t cir_proto;
#define CIR_PROTO_NEC 5 #define CIR_PROTO_NEC 5
#define CIR_PROTO_SHARP 6 #define CIR_PROTO_SHARP 6
#define CIR_KEY_RC6_ENTER 0x0d /* Mute */
#define CIR_KEY_RC6_BACKSPACE 0xa4 /* <= */
#define CIR_KEY_NEC_ENTER 0x3d /* 'kettei' */
#define CIR_KEY_NEC_BACKSPACE 0x3b /* 'modoru' */
#define CIR_KEY_SONY_ENTER 0x65 /* 'kettei' */
#define CIR_KEY_SONY_BACKSPACE 0xa3 /* 'modoru' */
#define CIR_KEY_SHARP_ENTER 0x0252 /* 'kettei' */
#define CIR_KEY_SHARP_BACKSPACE 0xe4 /* 'modoru' */
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */ /* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
static uint8_t cir_data_zero; static uint8_t cir_data_zero;
@@ -196,6 +200,388 @@ static uint8_t cir_seq;
static systime_t cir_input_last; static systime_t cir_input_last;
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */ #define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
static void
cir_init (void)
{
cir_data = 0;
cir_seq = 0;
/* Don't touch cir_proto here */
cir_ext_enable ();
}
#define CH_RETURN 0x0d
#define CH_BACKSPACE 0x08
struct codetable {
uint16_t cir_code;
uint8_t char_code;
};
/* NOTE: no way to input '0' */
static const struct codetable
cir_codetable_dell_mr425[] = {
{0x10, '7' }, /* Speaker Louder */
{0x11, '8' }, /* Speaker Quieter */
{0x0d, '9' }, /* Speaker Mute */
{0xce, 'a' }, /* Black triangle UP */
{0xcf, 'b' }, /* Black triangle DOWN */
{0x58, 'c' }, /* White triangle UP */
{0x5a, 'd' }, /* White triangle LEFT */
{0x5c, CH_RETURN }, /* Check */
{0x5b, 'e' }, /* White triangle RIGHT */
{0xa4, CH_BACKSPACE }, /* Back */
{0x59, 'f' }, /* White triangle DOWN */
{0x2f, '1' }, /* Rewind */
{0x2c, '2' }, /* Play / Pause */
{0x2e, '3' }, /* Forward */
{0x21, '4' }, /* Skip backward */
{0x31, '5' }, /* Stop */
{0x20, '6' }, /* Skip forward */
{0, 0} /* <<END>> */
};
#define CIR_ADDR_SHARP_AQUOS 0x028f
static const struct codetable
cir_codetable_aquos[] = {
{ 0x0116, ' ' }, /* Power */
{ 0x025e, '0' }, /* d */
{ 0x024e, '1' }, /* 1 */
{ 0x024f, '2' }, /* 2 */
{ 0x0250, '3' }, /* 3 */
{ 0x0251, '4' }, /* 4 */
{ 0x0252, '5' }, /* 5 */
{ 0x0253, '6' }, /* 6 */
{ 0x0254, '7' }, /* 7 */
{ 0x0255, '8' }, /* 8 */
{ 0x0256, '9' }, /* 9 */
{ 0x0257, 'a' }, /* 10/0 */
{ 0x0258, 'b' }, /* 11 */
{ 0x0259, 'c' }, /* 12 */
{ 0x0111, 'd' }, /* Ch ^ */
{ 0x0112, 'e' }, /* Ch v */
{ 0x0114, 'f' }, /* Vol + */
{ 0x0115, 'g' }, /* Vol - */
{ 0x0117, 'h' }, /* Mute */
{ 0x0280, 'i' }, /* BLUE */
{ 0x0281, 'j' }, /* RED */
{ 0x0282, 'k' }, /* GREEN */
{ 0x0283, 'l' }, /* YELLOW */
{ 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */
{ 0x01d5, 'n' }, /* DISPLAY SIZE */
{ 0x0157, 'o' }, /* UP */
{ 0x01d7, 'p' }, /* LEFT */
{ 0x01d8, 'q' }, /* RIGHT */
{ 0x0120, 'r' }, /* DOWN */
{ 0x0152, CH_RETURN }, /* Commit (kettei) */
{ 0x01e4, CH_BACKSPACE }, /* Back (modoru) */
{ 0x01f5, 's' }, /* Quit (shuuryou) */
{ 0x0b03, 't' }, /* Rewind (hayamodoshi) */
{ 0x0b01, 'u' }, /* Play (saisei) */
{ 0x0b04, 'v' }, /* Forward (hayaokuri) */
{ 0x0b02, 'w' }, /* Stop (teishi) */
{ 0x028a, 'x' }, /* BS */
{ 0x028b, 'y' }, /* CS */
{ 0x025f, 'z' }, /* Program information (bangumi jouhou) */
{ 0x0260, '\\' }, /* Program table (bangumi hyou) */
{ 0x0118, '|' }, /* Sound channel (onsei kirikae) */
{ 0x028e, '[' }, /* Ground Analog (chijou A) */
{ 0x0289, ']' }, /* Ground Digital (chijou D) */
{ 0x0b07, '\"' }, /* Feature select (kinou sentaku) */
{ 0x026b, '.' }, /* TV/Radio/Data (terebi/rajio/data) */
{ 0x025a, ',' }, /* 3 code input (3 keta nyuuryoku) */
{ 0x0267, ':' }, /* subtitle (jimaku) */
{ 0x0159, ';' }, /* hold (seishi) */
{ 0x01c4, 'A' }, /* Menu */
{ 0x011a, 'B' }, /* Off timer */
{ 0x0121, 'C' }, /* CATV */
{ 0x0b05, 'D' }, /* Record */
{ 0x0b06, 'E' }, /* Recording stop */
{ 0x0113, 'F' }, /* Inputs (nyuuryoku kirikae) */
{ 0x0275, 'G' }, /* other programs (ura bangumi) */
{ 0x0266, 'H' }, /* signal control (eizou kirikae) */
{ 0x01e7, 'I' }, /* AV position */
{ 0x027f, 'J' }, /* i.LINK */
{ 0x0b00, 'K' }, /* Recorder power */
{ 0x028f, 'L' }, /* as you like it (okonomi senkyoku) */
{0, 0} /* <<END>> */
};
#define CIR_ADDR_TOSHIBA_REGZA 0xbf40
static const struct codetable
cir_codetable_regza[] = {
{ 0x12, ' ' }, /* Power */
{ 0x14, '0' }, /* d (data) */
{ 0x01, '1' }, /* 1 */
{ 0x02, '2' }, /* 2 */
{ 0x03, '3' }, /* 3 */
{ 0x04, '4' }, /* 4 */
{ 0x05, '5' }, /* 5 */
{ 0x06, '6' }, /* 6 */
{ 0x07, '7' }, /* 7 */
{ 0x08, '8' }, /* 8 */
{ 0x09, '9' }, /* 9 */
{ 0x0a, 'a' }, /* 10 */
{ 0x0b, 'b' }, /* 11 */
{ 0x0c, 'c' }, /* 12 */
{ 0x1b, 'd' }, /* Ch ^ */
{ 0x1f, 'e' }, /* Ch v */
{ 0x1a, 'f' }, /* Vol + */
{ 0x1e, 'g' }, /* Vol - */
{ 0x10, 'h' }, /* Mute */
{ 0x73, 'i' }, /* BLUE */
{ 0x74, 'j' }, /* RED */
{ 0x75, 'k' }, /* GREEN */
{ 0x76, 'l' }, /* YELLOW */
{ 0x1c, 'm' }, /* Display control */
{ 0x2b, 'n' }, /* Display size */
{ 0x3e, 'o' }, /* UP */
{ 0x5f, 'p' }, /* LEFT */
{ 0x5b, 'q' }, /* RIGHT */
{ 0x3f, 'r' }, /* DOWN */
{ 0x3d, CH_RETURN }, /* Commit (kettei) */
{ 0x3b, CH_BACKSPACE }, /* Back (modoru) */
{ 0x3c, 's' }, /* Quit (shuuryou) */
{ 0x2c, 't' }, /* << (Rewind) */
{ 0x2d, 'u' }, /* >/|| (Play/Stop) */
{ 0x2e, 'v' }, /* >> (Forward) */
{ 0x2b, 'w' }, /* Stop (teishi) */
{ 0x7c, 'x' }, /* BS */
{ 0x7d, 'y' }, /* CS */
{ 0x71, 'z' }, /* Program information (bangumi setsumei) */
{ 0x77, '\\' }, /* Mini program table (mini bangumihyou) */
{ 0x13, '|' }, /* Sound (onta kirikae) */
{ 0x7a, '[' }, /* Ground Digital (chideji) */
{ 0x7b, ']' }, /* Ground Analog (chiana) */
{ 0xd0, '\"' }, /* Settings Menu (settei menu) */
{ 0x6d, '.' }, /* Radio/Data (rajio/data) */
{ 0x60, ',' }, /* CH 10-key input (search) */
{ 0x52, ':' }, /* subtitle (jimaku) */
{ 0x50, ';' }, /* hold (seishi) */
{ 0x3a, 'A' }, /* Input- (nyuuryokukirikae-) */
{ 0x0f, 'B' }, /* Input+ (nyuuryokukirikae+) */
{ 0x29, 'C' }, /* Two screens (nigamen) */
{ 0x25, 'D' }, /* Broadband */
{ 0x27, 'E' }, /* |<< Skip backward */
{ 0x26, 'F' }, /* >>| Skip forward */
{ 0x61, '!' }, /* 1 NHK1 */
{ 0x62, '@' }, /* 2 NHK2 */
{ 0x63, '#' }, /* 3 NHKh */
{ 0x64, '$' }, /* 4 BS Nihon TV */
{ 0x65, '%' }, /* 5 BS Asahi */
{ 0x66, '^' }, /* 6 BS-i */
{ 0x67, '&' }, /* 7 BSJ */
{ 0x68, '*' }, /* 8 BS Fuji */
{ 0x69, '(' }, /* 9 WOW */
{ 0x6a, ')' }, /* 10 Star */
{ 0x6b, '-' }, /* 11 BS11 */
{ 0x6c, '+' }, /* 12 TwellV */
{ 0x27, '=' }, /* Quick (Delete) */
{ 0x34, '<' }, /* REGZA link */
{ 0x6e, '>' }, /* Program Table */
{ 0x20, '/' }, /* ^^ */
{ 0x22, '\'' }, /* << */
{ 0x23, '?' }, /* >> */
{ 0x21, '_' }, /* vv */
{0, 0} /* <<END>> */
};
static const struct codetable
cir_codetable_bravia[] = {
{ 0x15, ' ' }, /* Power */
{ 0x95, '0' }, /* d (16-bit: 0x4b) */
{ 0x00, '1' }, /* 1 */
{ 0x01, '2' }, /* 2 */
{ 0x02, '3' }, /* 3 */
{ 0x03, '4' }, /* 4 */
{ 0x04, '5' }, /* 5 */
{ 0x05, '6' }, /* 6 */
{ 0x06, '7' }, /* 7 */
{ 0x07, '8' }, /* 8 */
{ 0x08, '9' }, /* 9 */
{ 0x09, 'a' }, /* 10 */
{ 0x0a, 'b' }, /* 11 */
{ 0x0b, 'c' }, /* 12 */
{ 0x10, 'd' }, /* CH+ */
{ 0x11, 'd' }, /* CH- */
{ 0x12, 'f' }, /* Vol+ */
{ 0x13, 'g' }, /* Vol- */
{ 0x14, 'h' }, /* Mute */
{ 0xa4, 'i' }, /* BLUE (16-bit: 0x4b) */
{ 0xa5, 'j' }, /* RED (16-bit: 0x4b) */
{ 0xa6, 'k' }, /* GREEN (16-bit: 0x4b) */
{ 0xa7, 'l' }, /* YELLOW (16-bit: 0x4b) */
{ 0x3a, 'm' }, /* DISPLAY control (gamen hyouji) */
{ 0x3d, 'n' }, /* Display Wide (waido kirikae) */
{ 0x74, 'o' }, /* UP */
{ 0x75, 'p' }, /* DOWN */
{ 0x33, 'q' }, /* RIGHT */
{ 0x34, 'r' }, /* LEFT */
{ 0x65, CH_RETURN }, /* Commit (kettei) */
{ 0xa3, CH_BACKSPACE }, /* Back (modoru) (16-bit: 0x4b) */
{ 0xac, 's' }, /* BS (16-bit: 0x4b) */
{ 0xab, 't' }, /* CS (16-bit: 0x4b) */
{ 0x5b, 'u' }, /* Program table (bangumi hyou) (16-bit: 0x52) */
{ 0x17, 'v' }, /* Sound channel (onsei kirikae) */
{ 0xa8, 'w' }, /* subtitle (jimaku) (16-bit: 0x4b) */
{ 0x5c, 'x' }, /* hold (memo) */
{ 0xb6, 'y' }, /* Tool (16-bit: 0x4b) */
{ 0x8c, 'z' }, /* 10 key input (10ki-) (16-bit: 0x4b) */
{ 0x60, '!' }, /* Menu */
{ 0xae, '@' }, /* Analog (16-bit: 0x4b) */
{ 0xb2, '#' }, /* Digital (16-bit: 0x4b) */
{ 0x25, '$' }, /* Input (nyuuryoku kirikae) */
{0, 0} /* <<END>> */,
};
static int
ch_is_backspace (int ch)
{
return ch == CH_BACKSPACE;
}
static int
ch_is_enter (int ch)
{
return ch == CH_RETURN;
}
/* liner search is good enough for this small amount of data */
static uint8_t
find_char_codetable (uint32_t cir_code, const struct codetable *ctp)
{
while (ctp->cir_code != 0x0000 || ctp->char_code != 0x00)
if (ctp->cir_code == cir_code)
return ctp->char_code;
else
ctp++;
/* Not found */
return cir_code & 0xff;
}
static int
hex (int x)
{
if (x < 10)
return x + '0';
else
return (x - 10) + 'a';
}
static int
cir_getchar (systime_t timeout)
{
uint16_t cir_addr;
eventmask_t m;
#if defined(DEBUG_CIR)
uint16_t *p;
#endif
#if defined(DEBUG_CIR)
cirinput_p = cirinput;
#endif
chEvtClear (ALL_EVENTS);
cir_init ();
m = chEvtWaitOneTimeout (ALL_EVENTS, timeout);
if (m == 0)
return -1;
#if defined(DEBUG_CIR)
DEBUG_INFO ("****\r\n");
DEBUG_SHORT (intr_ext);
DEBUG_SHORT (intr_trg);
DEBUG_SHORT (intr_ovf);
DEBUG_INFO ("----\r\n");
for (p = cirinput; p < cirinput_p; p++)
DEBUG_SHORT (*p);
DEBUG_INFO ("====\r\n");
cirinput_p = cirinput;
DEBUG_INFO ("**** CIR data:");
DEBUG_WORD (cir_data);
if (cir_seq > 48)
DEBUG_SHORT (cir_data_more);
DEBUG_BYTE (cir_seq);
#endif
switch (cir_proto)
{
case CIR_PROTO_RC5:
cir_data &= 0x003f;
goto err;
case CIR_PROTO_RC6:
cir_addr = cir_data >> 8; /* in case of cir_seq == 16. 32??? */
cir_data &= 0x00ff;
return find_char_codetable (cir_data, cir_codetable_dell_mr425);
case CIR_PROTO_NEC:
cir_addr = cir_data&0xffff;
if (cir_addr == CIR_ADDR_TOSHIBA_REGZA)
{
cir_data = (cir_data >> 16) & 0x00ff;
return find_char_codetable (cir_data, cir_codetable_regza);
}
else
goto err;
case CIR_PROTO_SHARP:
cir_addr = cir_data&0x0fff;
if (cir_addr == CIR_ADDR_SHARP_AQUOS)
{
cir_data = (cir_data>>16)&0x0fff;
return find_char_codetable (cir_data, cir_codetable_aquos);
}
else
goto err;
case CIR_PROTO_SONY:
/* Remove ADDRESS bits and filter COMMAND bits */
if (cir_seq == 1 + 12)
{
cir_addr = cir_data >> 7;
cir_data = cir_data & 0x007f;
/* ADDRESS = 0x01 (5-bit) */
}
else
{
cir_addr = cir_data >> 8;
cir_data = cir_data & 0x00ff;
/* ADDRESS = 0x4b or 0x52 (7-bit) */
}
return find_char_codetable (cir_data, cir_codetable_bravia);
err:
default:
/* encode debug information */
pin_input_len = 16;
pin_input_buffer[0] = hex (cir_proto >> 4);
pin_input_buffer[1] = hex (cir_proto & 0x0f);
pin_input_buffer[2] = ':';
pin_input_buffer[3] = hex ((cir_data >> 28) & 0x0f);
pin_input_buffer[4] = hex ((cir_data >> 24) & 0x0f);
pin_input_buffer[5] = hex ((cir_data >> 20) & 0x0f);
pin_input_buffer[6] = hex ((cir_data >> 16) & 0x0f);
pin_input_buffer[7] = hex ((cir_data >> 12) & 0x0f);
pin_input_buffer[8] = hex ((cir_data >> 8) & 0x0f);
pin_input_buffer[9] = hex ((cir_data >> 4) & 0x0f);
pin_input_buffer[10] = hex (cir_data & 0x0f);
pin_input_buffer[11] = ':';
pin_input_buffer[12] = hex ((cir_data_more >> 12) & 0x0f);
pin_input_buffer[13] = hex ((cir_data_more >> 8) & 0x0f);
pin_input_buffer[14] = hex ((cir_data_more >> 4) & 0x0f);
pin_input_buffer[15] = hex (cir_data_more & 0x0f);
return CH_RETURN;
}
}
/* /*
* RC-5 protocol doesn't have a start bit, while any other protocols * RC-5 protocol doesn't have a start bit, while any other protocols
* have the one. * have the one.
@@ -207,125 +593,56 @@ static systime_t cir_input_last;
#define CIR_BIT_PERIOD 1500 #define CIR_BIT_PERIOD 1500
#define CIR_BIT_SIRC_PERIOD_ON 1000 #define CIR_BIT_SIRC_PERIOD_ON 1000
static void
cir_init (void)
{
cir_data = 0;
cir_seq = 0;
/* Don't touch cir_proto here */
cir_ext_enable ();
}
static Thread *pin_thread; static Thread *pin_thread;
static int /*
cir_key_is_backspace (void) * Let user input PIN string.
* Return length of the string.
* The string itself is in PIN_INPUT_BUFFER.
*/
int
pinpad_getline (int msg_code, systime_t timeout)
{ {
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_BACKSPACE)
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_BACKSPACE)
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_BACKSPACE)
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_BACKSPACE);
}
static int
cir_key_is_enter (void)
{
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_ENTER)
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_ENTER)
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_ENTER)
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_ENTER);
}
msg_t
pin_main (void *arg)
{
uint8_t s = 0;
int msg_code = (int)arg;
(void)msg_code; (void)msg_code;
pin_thread = chThdSelf (); pin_thread = chThdSelf ();
#if defined(DEBUG_CIR) DEBUG_INFO (">>>\r\n");
cirinput_p = cirinput;
#endif
pin_input_len = 0; pin_input_len = 0;
chEvtClear (ALL_EVENTS); while (1)
cir_init ();
while (!chThdShouldTerminate ())
{ {
eventmask_t m; int ch;
m = chEvtWaitOneTimeout (ALL_EVENTS, PINDISP_TIMEOUT_INTERVAL1); ch = cir_getchar (timeout);
if (ch < 0)
return 0; /* timeout */
if (m) if (ch_is_backspace (ch))
{ {
#if defined(DEBUG_CIR) led_blink (2);
uint16_t *p; if (pin_input_len > 0)
pin_input_len--;
DEBUG_INFO ("****\r\n");
DEBUG_SHORT (intr_ext);
DEBUG_SHORT (intr_trg);
DEBUG_SHORT (intr_ovf);
DEBUG_INFO ("----\r\n");
for (p = cirinput; p < cirinput_p; p++)
DEBUG_SHORT (*p);
DEBUG_INFO ("====\r\n");
cirinput_p = cirinput;
#endif
DEBUG_INFO ("**** CIR data:");
DEBUG_WORD (cir_data);
if (cir_seq > 48)
{
DEBUG_SHORT (cir_data_more);
}
DEBUG_BYTE (cir_seq);
if (cir_key_is_backspace ())
{
if (pin_input_len > 0)
pin_input_len--;
}
else if (cir_key_is_enter ())
{
pindisp (' ');
chThdExit (0);
}
else if (pin_input_len < MAX_PIN_CHARS)
pin_input_buffer[pin_input_len++] = (uint8_t)cir_data;
cir_init ();
} }
else if (ch_is_enter (ch))
switch (s++) break;
else if (pin_input_len < MAX_PIN_CHARS)
{ {
case 0: led_blink (0);
pindisp ('G'); pin_input_buffer[pin_input_len++] = ch;
break;
case 1:
pindisp ('P');
break;
case 2:
pindisp ('G');
break;
case 3:
pindisp ('.');
break;
default:
pindisp (' ');
s = 0;
break;
} }
chThdSleep (PINDISP_TIMEOUT_INTERVAL0);
} }
cir_ext_disable (); cir_ext_disable ();
return 0;
return pin_input_len;
} }
/**
* @brief Interrupt handler of EXTI.
* @note This handler will be invoked at the beginning of signal.
* Setup timer to measure period and duty using PWM input mode.
*/
void void
cir_ext_interrupt (void) cir_ext_interrupt (void)
{ {
@@ -340,29 +657,33 @@ cir_ext_interrupt (void)
} }
#endif #endif
TIM3->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */ TIMx->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
/* Enable Timer */ /* Enable Timer */
TIM3->SR &= ~(TIM_SR_UIF TIMx->SR &= ~(TIM_SR_UIF
| TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC1IF | TIM_SR_CC2IF
| TIM_SR_TIF | TIM_SR_TIF
| TIM_SR_CC1OF | TIM_SR_CC2OF); | TIM_SR_CC1OF | TIM_SR_CC2OF);
TIM3->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/; TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
TIM3->CR1 |= TIM_CR1_CEN; TIMx->CR1 |= TIM_CR1_CEN;
} }
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \ #define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
* CIR_BIT_PERIOD_RC6 * 3 / 2) * CIR_BIT_PERIOD_RC6 * 3 / 2)
/**
* @brief Interrupt handler of timer.
* @note Timer is PWM input mode, this handler will be invoked on each cycle
*/
void void
cir_timer_interrupt (void) cir_timer_interrupt (void)
{ {
uint16_t period, on, off; uint16_t period, on, off;
period = TIM3->CCR1; period = TIMx->CCR1;
on = TIM3->CCR2; on = TIMx->CCR2;
off = period - on; off = period - on;
if ((TIM3->SR & TIM_SR_TIF)) if ((TIMx->SR & TIM_SR_TIF))
{ {
if (cir_seq == 0) if (cir_seq == 0)
{ {
@@ -477,23 +798,23 @@ cir_timer_interrupt (void)
intr_trg++; intr_trg++;
#endif #endif
TIM3->EGR = TIM_EGR_UG; /* Generate UEV */ TIMx->EGR = TIM_EGR_UG; /* Generate UEV */
TIM3->SR &= ~TIM_SR_TIF; TIMx->SR &= ~TIM_SR_TIF;
} }
else else
/* overflow occurred */ /* overflow occurred */
{ {
systime_t now = chTimeNow (); systime_t now = chTimeNow ();
TIM3->SR &= ~TIM_SR_UIF; TIMx->SR &= ~TIM_SR_UIF;
if (on > 0) if (on > 0)
{ {
uint8_t ignore_input = 0; uint8_t ignore_input = 0;
/* Disable the timer */ /* Disable the timer */
TIM3->CR1 &= ~TIM_CR1_CEN; TIMx->CR1 &= ~TIM_CR1_CEN;
TIM3->DIER = 0; TIMx->DIER = 0;
if (cir_seq == 12 || cir_seq == 15) if (cir_seq == 12 || cir_seq == 15)
{ {
@@ -536,14 +857,9 @@ cir_timer_interrupt (void)
cir_input_last = now; cir_input_last = now;
ignore_input = 1; ignore_input = 1;
} }
/* Remove ADDRESS bits and filter COMMAND bits */
else if (cir_proto == CIR_PROTO_SONY) else if (cir_proto == CIR_PROTO_SONY)
{ {
if (cir_seq == 1 + 12) if (cir_seq != 1 + 12 && cir_seq != 1 + 15)
cir_data = cir_data & 0x007f;
else if (cir_seq == 1 + 15)
cir_data = cir_data & 0x00ff;
else
ignore_input = 1; ignore_input = 1;
} }
else if (cir_proto == CIR_PROTO_OTHER) else if (cir_proto == CIR_PROTO_OTHER)
@@ -551,10 +867,7 @@ cir_timer_interrupt (void)
if (cir_seq == 1 + 32) if (cir_seq == 1 + 32)
{ {
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff)) if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
{ cir_proto = CIR_PROTO_NEC;
cir_proto = CIR_PROTO_NEC;
cir_data = (cir_data >> 16) & 0x00ff;
}
else else
ignore_input = 1; ignore_input = 1;
} }
@@ -569,10 +882,7 @@ cir_timer_interrupt (void)
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f) ^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f) ^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f))) ^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
{ cir_proto = CIR_PROTO_SHARP;
cir_proto = CIR_PROTO_SHARP;
cir_data = (cir_data >> 16) & 0x0fff;
}
else else
ignore_input = 1; ignore_input = 1;
} }
@@ -581,16 +891,12 @@ cir_timer_interrupt (void)
} }
else if (cir_proto == CIR_PROTO_RC6) else if (cir_proto == CIR_PROTO_RC6)
{ {
if (cir_seq == 16 || cir_seq == 32) if (cir_seq != 16 && cir_seq != 32)
cir_data &= 0x00ff;
else
ignore_input = 1; ignore_input = 1;
} }
else if (cir_proto == CIR_PROTO_RC5) else if (cir_proto == CIR_PROTO_RC5)
{ {
if (cir_seq == 14) if (cir_seq != 14)
cir_data &= 0x003f;
else
ignore_input = 1; ignore_input = 1;
} }
else else
@@ -603,7 +909,8 @@ cir_timer_interrupt (void)
{ {
cir_input_last = now; cir_input_last = now;
/* Notify thread */ /* Notify thread */
chEvtSignal (pin_thread, (eventmask_t)1); if (pin_thread)
chEvtSignalI (pin_thread, (eventmask_t)1);
} }
#if defined(DEBUG_CIR) #if defined(DEBUG_CIR)

View File

@@ -128,10 +128,9 @@ dial_sw_interrupt (void)
} }
msg_t int
pin_main (void *arg) pinpad_getline (int msg_code, systime_t timeout)
{ {
int msg_code = (int)arg;
uint16_t count, count_prev; uint16_t count, count_prev;
uint8_t input_mode; uint8_t input_mode;
uint8_t sw_push_count; uint8_t sw_push_count;
@@ -150,7 +149,7 @@ pin_main (void *arg)
sw_push_count = 0; sw_push_count = 0;
sw_event = 0; sw_event = 0;
while (!chThdShouldTerminate ()) while (1)
{ {
eventmask_t m; eventmask_t m;
@@ -218,5 +217,5 @@ pin_main (void *arg)
led_disp (OFF); led_disp (OFF);
TIM4->CR1 &= ~TIM_CR1_CEN; TIM4->CR1 &= ~TIM_CR1_CEN;
dial_sw_disable (); dial_sw_disable ();
return 0; return pin_input_len;
} }

View File

@@ -24,6 +24,23 @@
#include "config.h" #include "config.h"
#include "ch.h" #include "ch.h"
#include "gnuk.h" #include "gnuk.h"
#include "neug.h"
#define RANDOM_BYTES_LENGTH 16
static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
void
random_init (void)
{
int i;
neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
for (i = 0; i < NEUG_PRE_LOOP; i++)
(void)neug_get (NEUG_KICK_FILLING);
neug_prng_reseed ();
}
/* /*
* Return pointer to random 16-byte * Return pointer to random 16-byte
@@ -31,25 +48,8 @@
const uint8_t * const uint8_t *
random_bytes_get (void) random_bytes_get (void)
{ {
uint32_t addr, addr0; neug_wait_full ();
return (const uint8_t *)random_word;
addr = (uint32_t)&random_bits_start + ((hardclock () << 4) & 0x3f0);
addr0 = addr;
while (1)
{
if (*(uint32_t *)addr != 0 && *(uint32_t *)addr != 0xffffffff)
break;
addr += 16;
if (addr >= ((uint32_t)&random_bits_start) + 1024)
addr = ((uint32_t)&random_bits_start);
if (addr == addr0)
fatal (FATAL_RANDOM);
}
return (const uint8_t *)addr;
} }
/* /*
@@ -58,11 +58,8 @@ random_bytes_get (void)
void void
random_bytes_free (const uint8_t *p) random_bytes_free (const uint8_t *p)
{ {
int i; (void)p;
uint32_t addr = (uint32_t)p; neug_flush ();
for (i = 0; i < 8; i++)
flash_clear_halfword (addr+i*2);
} }
/* /*
@@ -71,15 +68,5 @@ random_bytes_free (const uint8_t *p)
uint32_t uint32_t
get_salt (void) get_salt (void)
{ {
const uint8_t *u = unique_device_id (); /* 12-byte unique id */ return neug_get (NEUG_KICK_FILLING);
uint32_t r = 0;
int i;
for (i = 0; i < 4; i++)
{
r <<= 8;
r |= u[hardclock () % 12];
}
return r;
} }

View File

@@ -227,7 +227,7 @@ static const uint8_t gnukStringProduct[] = {
const uint8_t gnukStringSerial[] = { const uint8_t gnukStringSerial[] = {
13*2+2, /* bLength */ 13*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0', 0, '.', 0, '1', 0, '3', 0, /* Version number of Gnuk */ '0', 0, '.', 0, '1', 0, '5', 0, /* Version number of Gnuk */
'-', 0, '-', 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

View File

@@ -120,8 +120,14 @@ gnuk_device_SetConfiguration (void)
DEVICE_INFO *pInfo = &Device_Info; DEVICE_INFO *pInfo = &Device_Info;
if (pInfo->Current_Configuration != 0) if (pInfo->Current_Configuration != 0)
/* Device configured */ { /* Device configured */
bDeviceState = CONFIGURED; extern void *main_thread;
extern void chEvtSignalI (void *, unsigned long);
#define LED_STATUS_MODE (8)
bDeviceState = CONFIGURED;
chEvtSignalI (main_thread, LED_STATUS_MODE);
}
} }
static void static void

View File

@@ -4,7 +4,7 @@
dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor. dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor.
"SE" in DfuSe stands for "STmicroelectronics Extention". "SE" in DfuSe stands for "STmicroelectronics Extention".
Copyright (C) 2010 Free Software Initiative of Japan Copyright (C) 2010, 2011 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org> Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation. This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -208,10 +208,23 @@ class DFU_STM32:
# First, erase pages # First, erase pages
sys.stdout.write("Erasing: ") sys.stdout.write("Erasing: ")
sys.stdout.flush() sys.stdout.flush()
last_addr = 0
for start_addr in sorted(ih.memory.keys()): for start_addr in sorted(ih.memory.keys()):
data = ih.memory[start_addr] data = ih.memory[start_addr]
end_addr = start_addr + len(data) end_addr = start_addr + len(data)
addr = start_addr & 0xfffffc00 addr = start_addr & 0xfffffc00
if not last_addr == 0:
i = 0
if last_addr > addr:
addr = last_addr
else:
while last_addr < addr:
self.dfuse_erase(last_addr)
if i & 0x03 == 0x03:
sys.stdout.write(".")
sys.stdout.flush()
last_addr += 1024
i += 1
i = 0 i = 0
while addr < end_addr: while addr < end_addr:
self.dfuse_erase(addr) self.dfuse_erase(addr)
@@ -220,20 +233,32 @@ class DFU_STM32:
sys.stdout.flush() sys.stdout.flush()
addr += 1024 addr += 1024
i += 1 i += 1
last_addr = addr
sys.stdout.write("\n") sys.stdout.write("\n")
sys.stdout.flush() sys.stdout.flush()
# Then, write pages # Then, write pages
sys.stdout.write("Writing: ") sys.stdout.write("Writing: ")
sys.stdout.flush() sys.stdout.flush()
last_addr = 0
for start_addr in sorted(ih.memory.keys()): for start_addr in sorted(ih.memory.keys()):
data = ih.memory[start_addr] data = ih.memory[start_addr]
end_addr = start_addr + len(data) end_addr = start_addr + len(data)
addr = start_addr & 0xfffffc00 addr = start_addr & 0xfffffc00
# XXX: data should be 1-KiB aligned if not last_addr == 0:
if addr != start_addr: i = 0
raise ValueError, "padding is not supported yet" while last_addr < addr:
self.dfuse_set_address_pointer(addr) if i & 0x03 == 0x03:
sys.stdout.write(".")
sys.stdout.flush()
last_addr += 1024
i += 1
i = 0 i = 0
if addr != start_addr:
self.dfuse_set_address_pointer(start_addr)
self.dfuse_write_memory(data[0:(addr + 1024 - start_addr)])
data = data[(addr + 1024 - start_addr):]
addr += 1024
self.dfuse_set_address_pointer(addr)
while addr < end_addr: while addr < end_addr:
self.dfuse_write_memory(data[i*1024:(i+1)*1024]) self.dfuse_write_memory(data[i*1024:(i+1)*1024])
if i & 0x03 == 0x03: if i & 0x03 == 0x03:
@@ -241,6 +266,7 @@ class DFU_STM32:
sys.stdout.flush() sys.stdout.flush()
addr += 1024 addr += 1024
i += 1 i += 1
last_addr = addr
if self.__protocol == DFU_STM32PROTOCOL_0: if self.__protocol == DFU_STM32PROTOCOL_0:
# 0-length write at the end # 0-length write at the end
self.ll_download_block(self.__blocknum, None) self.ll_download_block(self.__blocknum, None)
@@ -268,13 +294,33 @@ class DFU_STM32:
# Read pages # Read pages
sys.stdout.write("Reading: ") sys.stdout.write("Reading: ")
sys.stdout.flush() sys.stdout.flush()
last_addr = 0
for start_addr in sorted(ih.memory.keys()): for start_addr in sorted(ih.memory.keys()):
data = ih.memory[start_addr] data = ih.memory[start_addr]
end_addr = start_addr + len(data) end_addr = start_addr + len(data)
addr = start_addr & 0xfffffc00 addr = start_addr & 0xfffffc00
# XXX: data should be 1-KiB aligned if not last_addr == 0:
i = 0
while last_addr < addr:
if i & 0x03 == 0x03:
sys.stdout.write(".")
sys.stdout.flush()
last_addr += 1024
i += 1
if addr != start_addr: if addr != start_addr:
raise ValueError, "padding is not supported yet" self.dfuse_set_address_pointer(addr)
self.ll_clear_status()
self.ll_clear_status()
block = self.dfuse_read_memory()
j = 0
for c in data[0:(addr + 1024 - start_addr)]:
if (ord(c)&0xff) != block[j + start_addr - addr]:
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
j += 1
data = data[(addr + 1024 - start_addr):]
addr += 1024
self.ll_clear_status()
self.ll_clear_status()
self.dfuse_set_address_pointer(addr) self.dfuse_set_address_pointer(addr)
self.ll_clear_status() self.ll_clear_status()
self.ll_clear_status() self.ll_clear_status()
@@ -291,6 +337,7 @@ class DFU_STM32:
sys.stdout.flush() sys.stdout.flush()
addr += 1024 addr += 1024
i += 1 i += 1
last_addr = addr
self.ll_clear_status() self.ll_clear_status()
self.ll_clear_status() self.ll_clear_status()
self.ll_clear_status() self.ll_clear_status()