Compare commits

...

19 Commits

Author SHA1 Message Date
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
NIIBE Yutaka
8bf1019df7 version 0.13 2011-06-15 08:52:02 +09:00
NIIBE Yutaka
e0b70894db more rsa tweak 2011-06-08 15:18:27 +09:00
NIIBE Yutaka
8c930952f2 more performance tweak 2011-05-31 10:17:38 +09:00
NIIBE Yutaka
09748fc046 bug fixes 2011-05-27 16:08:16 +09:00
NIIBE Yutaka
450807e8bf more rsa improvement 2011-05-27 11:11:41 +09:00
NIIBE Yutaka
ede8bdc2c0 rsa improvement 2011-05-26 12:04:45 +09:00
NIIBE Yutaka
4e1126f88c add tool/hub_ctrl.py, this is convenient for development if you have hub with the feature 2011-05-25 15:17:36 +09:00
NIIBE Yutaka
c620b73202 flash_unlock at the beginning 2011-05-16 10:14:09 +09:00
NIIBE Yutaka
2d07cd6f0d API change 2011-05-16 10:05:17 +09:00
25 changed files with 1135 additions and 183 deletions

109
ChangeLog
View File

@@ -1,3 +1,112 @@
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>
* Version 0.13.
* src/usb_desc.c (gnukStringSerial): Updated.
2011-06-08 NIIBE Yutaka <gniibe@fsij.org>
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
(MULADDC_1024_CORE, MULADDC_1024_LOOP): New.
* polarssl-0.14.0/library/bignum.c (mpi_mul_hlp): Use
MULADDC_1024_LOOP.
2011-05-31 NIIBE Yutaka <gniibe@fsij.org>
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
(MULADDC_HUIT, MULADDC_INIT, MULADDC_CORE, MULADDC_STOP): Tweak.
2011-05-27 NIIBE Yutaka <gniibe@fsij.org>
* tool/gnuk_put_binary.py (main): Confirm Serial ID is written
correctly.
* src/openpgp.c (cmd_write_binary): Fix FILE_EF_SERIAL comparison.
* src/gnuk.ld.in (.gnuk_random, .gnuk_ch_certificate): Put LONG to
have CONTENTS.
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
(MULADDC_HUIT): New.
2011-05-26 NIIBE Yutaka <gniibe@fsij.org>
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
(MULADDC_INIT): Add ADDS instruction to clear of carry flag.
(MULADDC_CORE): Tune to 6 instructions and less registers.
(MULADDC_STOP): Add ADC instruction to save carry flag.
2011-05-25 NIIBE Yutaka <gniibe@fsij.org>
* tool/hub_ctrl.py: New. Port of original C implementation.
2011-05-16 NIIBE Yutaka <gniibe@fsij.org>
* src/main.c (main): Call flash_unlock at the beginning.
(device_initialize_once): Don't call flash_unlock here.
* src/flash.c (flash_init): Likewise.
* src/openpgp.c (cmd_select_file): Don't use write_res_apdu.
(set_res_apdu): Rename from write_res_apdu. Just SW1 and SW2.
2011-05-13 NIIBE Yutaka <gniibe@fsij.org>
* Version 0.12.

View File

@@ -62,6 +62,20 @@
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
#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. */
/*===========================================================================*/
@@ -238,26 +252,51 @@ typedef struct {
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Number of channels in a conversion sequence.
*/
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
#define ADC_SQR3_SQ0_N(n) ((n) << 0)
#define ADC_SQR3_SQ1_N(n) ((n) << 5)
#define ADC_SQR3_SQ2_N(n) ((n) << 10)
#define ADC_SQR3_SQ3_N(n) ((n) << 15)
#define ADC_SQR3_SQ4_N(n) ((n) << 20)
#define ADC_SQR3_SQ5_N(n) ((n) << 25)
#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
#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) << 5)
#define ADC_SQR2_SQ8_N(n) ((n) << 10)
#define ADC_SQR2_SQ9_N(n) ((n) << 15)
#define ADC_SQR2_SQ10_N(n) ((n) << 20)
#define ADC_SQR2_SQ11_N(n) ((n) << 25)
#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
#define ADC_SQR1_SQ13_N(n) ((n) << 0)
#define ADC_SQR1_SQ14_N(n) ((n) << 5)
#define ADC_SQR1_SQ15_N(n) ((n) << 10)
#define ADC_SQR1_SQ16_N(n) ((n) << 15)
#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
#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. */

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) {
port_lock_from_isr();
if ((SCB_ICSR & ICSR_RETTOBASE) && chSchIsRescRequiredExI()) {
if ((SCB_ICSR & ICSR_RETTOBASE)) {
register struct extctx *ctxp;
/* 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.*/
return;
}
/* ISR exit without context switching.*/
port_unlock_from_isr();
}
@@ -139,7 +138,8 @@ __attribute__((naked))
#endif
void _port_switch_from_isr(void) {
chSchDoRescheduleI();
if (chSchIsRescRequiredExI())
chSchDoRescheduleI();
asm volatile ("svc #0");
}

23
NEWS
View File

@@ -1,5 +1,28 @@
Gnuk NEWS - User visible changes
* 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
Released 2011-06-15, by NIIBE Yutaka
** Improved RSA routine.
About 20% speed improvement.
** New tool: hub_ctrl.
It is a Python implementation ported from original C implementation.
It is useful for development of USB target if you have a good hub.
You can power off/on the port to reset Gnuk Token.
* Major changes in Gnuk 0.12
Released 2011-05-13, by NIIBE Yutaka

63
README
View File

@@ -1,7 +1,7 @@
Gnuk - software for GnuPG USB Token
Version 0.12
2011-05-13
Version 0.14
2011-10-07
Niibe Yutaka
Free Software Initiative of Japan
@@ -19,15 +19,15 @@ me to bring a card reader all the time. With Gnuk, this issue will be
solved by a USB token which is small enough.
Please look at the graphics of "gnuk.svg" for the software name. My
son used to be with his NUK(R), always, everywhere. I will be with a
USB Token by "Gnuk" everywhere.
son used to be with his NUK(R), always, everywhere. I am with a USB
Token by "Gnuk", always, everywhere.
FAQ
===
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.privacyfoundation.de/crypto_stick/
A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
@@ -44,16 +44,18 @@ A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
(GNU Toolchain, Python, etc.),
"for Free Software"; Gnuk supports GnuPG.
Q1: What's kind of key algorithm is supported?
Q1: What kind of key algorithm is supported?
A1: Gnuk only supports 2048-bit RSA.
Q2: How long does it take for digital signing?
A2: It takes two seconds or so.
A2: It takes a second and a half or so.
Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103.
If you have skill of electronics and like DIY, STM32 part of STM8S
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?
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
@@ -92,13 +94,9 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of
Release notes
=============
This is thirteenth release of Gnuk. While it works well for specific
This is fifteenth release of Gnuk. While it works well for specific
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:
* Personalization of the card
@@ -129,7 +127,7 @@ It is known not-working well:
Not supported feature(s):
* Overriding key import. You need to remove all keys first.
* Key generation
* Key generation on device side
Targets
@@ -179,8 +177,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
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
protections. Private keys, random bytes, and other information should
be protected properly.
protections. Private keys, and other information should be protected
properly.
External source code
@@ -200,6 +198,9 @@ Gnuk is distributed with external source code.
We use PolarSSL for RSA computation, AES encryption/decryption
and SHA-1 computation.
The file include/polarssl/bn_mul.h is heavily modified for ARM
Cortex-M3.
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
@@ -229,8 +230,8 @@ How to compile
You need GNU toolchain and newlib for 'arm-none-eabi' target.
See http://github.com/esden/summon-arm-toolchain/ for preparation of
GNU Toolchain for 'arm-none-eabi' target.
See http://github.com/uwehermann/summon-arm-toolchain/ for preparation
of GNU Toolchain for 'arm-none-eabi' target.
Change directory to `src':
@@ -338,19 +339,7 @@ How to configure
You need python and pyscard (python-pyscard package in Debian) or
PyUSB (python-usb package in Debian).
(1) In the 'src' directory, type
$ 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
(1) [pyscard] Stop scdaemon
[PyUSB] Stop the pcsc daemon.
If scdaemon is running, please kill it, or you will get "Smartcard
@@ -363,17 +352,7 @@ In case of PyUSB tool, you need to stop pcscd.
# /etc/init.d/pcscd stop
(3) Write the random bits to the device
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
(2) [Optional] Write fixed serial number
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
@@ -381,7 +360,7 @@ If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
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:

View File

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

View File

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

View File

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

View File

@@ -495,27 +495,130 @@
#endif /* TriCore */
#if defined(__arm__)
#define MULADDC_1024_CORE \
"ldmia %0!, { r5, r6, r7 } \n" \
"ldmia %1, { r8, r9, r10 } \n" \
"umull r11, r12, %2, r5 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r8, r8, r11 \n" \
"umull r11, r12, %2, r6 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r9, r9, r11 \n" \
"umull r11, r12, %2, r7 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r10, r10, r11 \n" \
"stmia %1!, { r8, r9, r10 } \n"
#define MULADDC_INIT \
asm( "ldr r0, %0 " :: "m" (s)); \
asm( "ldr r1, %0 " :: "m" (d)); \
asm( "ldr r2, %0 " :: "m" (c)); \
asm( "ldr r3, %0 " :: "m" (b));
#define MULADDC_1024_LOOP \
asm( "tst %4, #0xfe0 \n" \
"beq 0f \n" \
"1: sub %4, %4, #32 \n" \
"ldmia %0!, { r5, r6, r7 } \n" \
"ldmia %1, { r8, r9, r10 } \n" \
"umull r11, r12, %2, r5 \n" \
"adds r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r8, r8, r11 \n" \
"umull r11, r12, %2, r6 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r9, r9, r11 \n" \
"umull r11, r12, %2, r7 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r10, r10, r11 \n" \
"stmia %1!, { r8, r9, r10 } \n" \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE MULADDC_1024_CORE \
MULADDC_1024_CORE \
"ldmia %0!, { r5, r6 } \n" \
"ldmia %1, { r8, r9 } \n" \
"umull r11, r12, %2, r5 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r8, r8, r11 \n" \
"umull r11, r12, %2, r6 \n" \
"adcs r11, r11, %3 \n" \
"adc %3, r12, #0 \n" \
"adds r9, r9, r11 \n" \
"stmia %1!, { r8, r9 } \n" \
"adc %3, %3, #0 \n" \
"tst %4, #0xfe0 \n" \
"bne 1b \n" \
"0:" \
: "=r" (s), "=r" (d), "=r" (b), "=r" (c), "=r" (i) \
: "0" (s), "1" (d), "2" (b), "3" (c), "4" (i) \
: "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory", "cc" );
#define MULADDC_CORE \
asm( "ldr r4, [r0], #4 " ); \
asm( "mov r5, #0 " ); \
asm( "ldr r6, [r1] " ); \
asm( "umlal r2, r5, r3, r4 " ); \
asm( "adds r7, r6, r2 " ); \
asm( "adc r2, r5, #0 " ); \
asm( "str r7, [r1], #4 " );
/* Just for reference (dead code) */
#define MULADDC_HUIT \
"ldmia %0!, { r4, r5 } \n" \
"ldmia %1, { r8, r9 } \n" \
"umull r6, r7, %2, r4 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r8, r8, r6 \n" \
"umull r6, r7, %2, r5 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r9, r9, r6 \n" \
"stmia %1!, { r8, r9 } \n" \
"ldmia %0!, { r4, r5 } \n" \
"ldmia %1, { r8, r9 } \n" \
"umull r6, r7, %2, r4 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r8, r8, r6 \n" \
"umull r6, r7, %2, r5 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r9, r9, r6 \n" \
"stmia %1!, { r8, r9 } \n" \
"ldmia %0!, { r4, r5 } \n" \
"ldmia %1, { r8, r9 } \n" \
"umull r6, r7, %2, r4 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r8, r8, r6 \n" \
"umull r6, r7, %2, r5 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r9, r9, r6 \n" \
"stmia %1!, { r8, r9 } \n" \
"ldmia %0!, { r4, r5 } \n" \
"ldmia %1, { r8, r9 } \n" \
"umull r6, r7, %2, r4 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r8, r8, r6 \n" \
"umull r6, r7, %2, r5 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r9, r9, r6 \n" \
"stmia %1!, { r8, r9 } \n"
#define MULADDC_STOP \
asm( "str r2, %0 " : "=m" (c)); \
asm( "str r1, %0 " : "=m" (d)); \
asm( "str r0, %0 " : "=m" (s) :: \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
#define MULADDC_INIT \
asm( "adds %0, #0 \n"
#define MULADDC_CORE \
"ldr r5, [%1] \n" \
"ldr r4, [%0], #4 \n" \
"umull r6, r7, %2, r4 \n" \
"adcs r6, r6, %3 \n" \
"adc %3, r7, #0 \n" \
"adds r5, r5, r6 \n" \
"str r5, [%1], #4 \n"
#define MULADDC_STOP \
"adc %3, %3, #0 " \
: "=r" (s), "=r" (d), "=r" (b), "=r" (c) \
: "0" (s), "1" (d), "2" (b), "3" (c) \
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc" );
#endif /* ARMv3 */

View File

@@ -894,7 +894,16 @@ static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
{
t_int c = 0, t = 0;
#if defined(MULADDC_HUIT)
#if defined(MULADDC_1024_LOOP)
MULADDC_1024_LOOP
for( ; i > 0; i-- )
{
MULADDC_INIT
MULADDC_CORE
MULADDC_STOP
}
#elif defined(MULADDC_HUIT)
for( ; i >= 8; i -= 8 )
{
MULADDC_INIT

View File

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

View File

@@ -10,7 +10,7 @@
#define CH_OPTIMIZE_SPEED TRUE
#define CH_USE_REGISTRY 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_SEMSW FALSE
#define CH_USE_MUTEXES TRUE

View File

@@ -147,8 +147,6 @@ flash_erase_page (uint32_t addr)
* .bss
* _end
* <alignment to page>
* random_bits_start
* <one page>
* ch_certificate_startp
* <2048 bytes>
* _data_pool
@@ -206,7 +204,6 @@ flash_init (void)
keystore = p;
flash_unlock ();
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
}
@@ -614,15 +611,6 @@ flash_erase_binary (uint8_t file_id)
#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;
}
else
@@ -642,11 +630,6 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
maxsize = FLASH_CH_CERTIFICATE_SIZE;
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)
{
maxsize = 6;

View File

@@ -90,8 +90,7 @@ extern void ac_reset_admin (void);
extern void ac_fini (void);
extern void write_res_apdu (const uint8_t *p, int len,
uint8_t sw1, uint8_t sw2);
extern void set_res_apdu (uint8_t sw1, uint8_t sw2);
extern uint16_t data_objects_number_of_bytes;
extern void gpg_data_scan (const uint8_t *p);
@@ -108,6 +107,7 @@ enum kind_of_key {
GPG_KEY_FOR_AUTHENTICATION,
};
extern void flash_unlock (void);
extern const uint8_t *flash_init (void);
extern void flash_do_release (const uint8_t *);
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
@@ -292,6 +292,7 @@ extern uint8_t admin_authorized;
#define SIZE_PW_STATUS_BYTES 7
extern void random_init (void);
/* 16-byte random bytes */
extern const uint8_t *random_bytes_get (void);
extern void random_bytes_free (const uint8_t *);

View File

@@ -27,8 +27,9 @@
/*
* ST32F103 memory setup.
*/
__main_stack_size__ = 0x0400;
__stacks_total_size__ = __main_stack_size__;
__main_stack_size__ = 0x0200;
__process_stack_size__ = 0x0200;
__stacks_total_size__ = __main_stack_size__ + __process_stack_size__;
MEMORY
{
@@ -114,18 +115,11 @@ SECTIONS
PROVIDE(end = .);
_end = .;
.gnuk_random :
{
. = ALIGN (@FLASH_PAGE_SIZE@);
random_bits_start = .;
. += 1;
. = ALIGN (@FLASH_PAGE_SIZE@);
} > flash =0xffffffff
.gnuk_ch_certificate :
{
. = ALIGN (@FLASH_PAGE_SIZE@);
ch_certificate_start = .;
LONG(0xffffffff);
. += 1920;
. = ALIGN (@FLASH_PAGE_SIZE@);
} > flash =0xffffffff

View File

@@ -6,7 +6,7 @@
#include "mcuconf.h"
#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_MAC FALSE
#define CH_HAL_USE_PWM FALSE

View File

@@ -172,7 +172,6 @@ device_initialize_once (void)
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
{
extern void flash_unlock (void);
/*
* This is the first time invocation.
* Setup serial number by unique device ID.
@@ -180,7 +179,6 @@ device_initialize_once (void)
const uint8_t *u = unique_device_id ();
int i;
flash_unlock ();
for (i = 0; i < 4; i++)
{
uint8_t b = u[i];
@@ -212,9 +210,11 @@ main (int argc, char **argv)
(void)argc;
(void)argv;
flash_unlock ();
device_initialize_once ();
usb_lld_init ();
USB_Init();
USB_Init ();
random_init ();
#ifdef DEBUG
stdout_init ();

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

@@ -62,13 +62,11 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
};
void
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
set_res_apdu (uint8_t sw1, uint8_t sw2)
{
res_APDU_size = 2 + len;
if (len)
memcpy (res_APDU, p, len);
res_APDU[len] = sw1;
res_APDU[len+1] = sw2;
res_APDU_size = 2;
res_APDU[0] = sw1;
res_APDU[1] = sw2;
}
#define FILE_NONE 0
@@ -678,10 +676,14 @@ cmd_select_file (void)
}
else
{
write_res_apdu (select_file_TOP_result,
sizeof (select_file_TOP_result), 0x90, 0x00);
int len = sizeof (select_file_TOP_result);
res_APDU_size = 2 + len;
memcpy (res_APDU, select_file_TOP_result, len);
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
res_APDU[3] = (data_objects_number_of_bytes >> 8);
res_APDU[len] = 0x90;
res_APDU[len+1] = 0x00;
}
file_selection = FILE_MF;
@@ -946,7 +948,7 @@ cmd_write_binary (void)
{
if (file_selection != FILE_EF_CH_CERTIFICATE
&& file_selection != FILE_EF_RANDOM
&& file_selection != FILEID_SERIAL_NO)
&& file_selection != FILE_EF_SERIAL)
{
GPG_COMMAND_NOT_ALLOWED ();
return;
@@ -1026,12 +1028,9 @@ GPGthread (void *arg)
while (!chThdShouldTerminate ())
{
eventmask_t m;
m = chEvtWaitOne (ALL_EVENTS);
chEvtWaitOne (ALL_EVENTS);
DEBUG_INFO ("GPG!: ");
DEBUG_WORD ((uint32_t)&m);
res_APDU_pointer = NULL; /* default */

View File

@@ -1,10 +1,10 @@
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
#define GPG_COMMAND_NOT_ALLOWED() write_res_apdu (NULL, 0, 0x69, 0x86)
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
#define GPG_ERROR() write_res_apdu (NULL, 0, 0x6f, 0x00)
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 0x00)
#define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81)
#define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82)
#define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83)
#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86)
#define GPG_NO_FILE() set_res_apdu (0x6a, 0x82)
#define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88)
#define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00)
#define GPG_NO_INS() set_res_apdu (0x6d, 0x00)
#define GPG_ERROR() set_res_apdu (0x6f, 0x00)
#define GPG_SUCCESS() set_res_apdu (0x90, 0x00)

View File

@@ -24,6 +24,23 @@
#include "config.h"
#include "ch.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
@@ -31,25 +48,8 @@
const uint8_t *
random_bytes_get (void)
{
uint32_t addr, addr0;
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;
neug_wait_full ();
return (const uint8_t *)random_word;
}
/*
@@ -58,11 +58,8 @@ random_bytes_get (void)
void
random_bytes_free (const uint8_t *p)
{
int i;
uint32_t addr = (uint32_t)p;
for (i = 0; i < 8; i++)
flash_clear_halfword (addr+i*2);
(void)p;
neug_flush ();
}
/*
@@ -71,15 +68,5 @@ random_bytes_free (const uint8_t *p)
uint32_t
get_salt (void)
{
const uint8_t *u = unique_device_id (); /* 12-byte unique id */
uint32_t r = 0;
int i;
for (i = 0; i < 4; i++)
{
r <<= 8;
r |= u[hardclock () % 12];
}
return r;
return neug_get (NEUG_KICK_FILLING);
}

View File

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

View File

@@ -107,6 +107,13 @@ def main(fileid, is_update, data, passwd):
gnuk.cmd_select_openpgp()
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
compare(data[:-2], data_in_device)
elif fileid == 2:
gnuk.cmd_select_openpgp()
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
for d in data_in_device:
print "%02x" % d,
print
compare(data, data_in_device[8:])
gnuk.connection.disconnect()
return 0

256
tool/hub_ctrl.py Executable file
View File

@@ -0,0 +1,256 @@
#! /usr/bin/python
"""
hub_ctrl.py - a tool to control port power/led of USB hub
Copyright (C) 2006, 2011 Free Software Initiative of Japan
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import usb
USB_RT_HUB = (usb.TYPE_CLASS | usb.RECIP_DEVICE)
USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
USB_PORT_FEAT_RESET = 4
USB_PORT_FEAT_POWER = 8
USB_PORT_FEAT_INDICATOR = 22
USB_DIR_IN = 0x80 # device to host
COMMAND_SET_NONE = 0
COMMAND_SET_LED = 1
COMMAND_SET_POWER = 2
HUB_LED_GREEN = 2
def find_hubs(listing, verbose, busnum=None, devnum=None, hub=None):
number_of_hubs_with_feature = 0
hubs = []
busses = usb.busses()
if not busses:
raise ValueError, "can't access USB"
for bus in busses:
devices = bus.devices
for dev in devices:
if dev.deviceClass != usb.CLASS_HUB:
continue
printout_enable = 0
if (listing
or (verbose
and ((bus.dirname == busnum and dev.devnum == devnumd)
or hub == number_of_hubs_with_feature))):
printout_enable = 1
uh = dev.open()
desc = None
try:
# Get USB Hub descriptor
desc = uh.controlMsg(requestType = USB_DIR_IN | USB_RT_HUB,
request = usb.REQ_GET_DESCRIPTOR,
value = usb.DT_HUB << 8,
index = 0, buffer = 1024, timeout = 1000)
finally:
del uh
if not desc:
continue
# desc[3] is lower byte of wHubCharacteristics
if (desc[3] & 0x80) == 0 and (desc[3] & 0x03) >= 2:
# Hub doesn't have features of controling port power/indicator
continue
if printout_enable:
print "Hub #%d at %s:%03d" % (number_of_hubs_with_feature,
bus.dirname, dev.devnum)
if (desc[3] & 0x03) == 0:
print " INFO: ganged power switching."
elif (desc[3] & 0x03) == 1:
print " INFO: individual power switching."
elif (desc[3] & 0x03) == 2 or (desc[3] & 0x03) == 3:
print " WARN: no power switching."
if (desc[3] & 0x80) == 0:
print " WARN: Port indicators are NOT supported."
hubs.append({ 'busnum' : bus.dirname, 'devnum' : dev.devnum,
'indicator_support' : (desc[3] & 0x80) == 0x80,
'dev' : dev, 'num_ports' : desc[2] })
number_of_hubs_with_feature += 1
return hubs
def hub_port_status(handle, num_ports):
print " Hub Port Status:"
for i in range(num_ports):
port = i + 1
status = handle.controlMsg(requestType = USB_RT_PORT | usb.ENDPOINT_IN,
request = usb.REQ_GET_STATUS,
value = 0,
index = port, buffer = 4,
timeout = 1000)
print " Port %d: %02x%02x.%02x%02x" % (port, status[3], status[2],
status[1], status[0]),
if status[1] & 0x10:
print " indicator",
if status[1] & 0x08:
print " test" ,
if status[1] & 0x04:
print " highspeed",
if status[1] & 0x02:
print " lowspeed",
if status[1] & 0x01:
print " power",
if status[0] & 0x10:
print " RESET",
if status[0] & 0x08:
print " oc",
if status[0] & 0x04:
print " suspend",
if status[0] & 0x02:
print " enable",
if status[0] & 0x01:
print " connect",
print
import sys
COMMAND_SET_NONE = 0
COMMAND_SET_LED = 1
COMMAND_SET_POWER = 2
HUB_LED_GREEN = 2
def usage(progname):
print >> sys.stderr, """Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}]
[-P PORT] [{-p [VALUE]|-l [VALUE]}]
""" % progname
def exit_with_usage(progname):
usage(progname)
exit(1)
if __name__ == '__main__':
busnum = None
devnum = None
listing = False
verbose = False
hub = None
port = 1
cmd = COMMAND_SET_NONE
if len(sys.argv) == 1:
listing = True
else:
try:
while len(sys.argv) >= 2:
option = sys.argv[1]
sys.argv.pop(1)
if option == '-h':
if bunum != None or devnum != None:
exit_with_usage(sys.argv[0])
hub = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-b':
busnum = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-d':
devnum = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-P':
port = int(sys.argv[1])
sys.argv.pop(1)
elif option == '-l':
if cmd != COMMAND_SET_NONE:
exit_with_usage(sys.argv[0])
if len(sys.argv) > 1:
value = int(sys.argv[1])
sys.argv.pop(1)
else:
value = HUB_LED_GREEN
cmd = COMMAND_SET_LED
elif option == '-p':
if cmd != COMMAND_SET_NONE:
exit_with_usage(sys.argv[0])
if len(sys.argv) > 1:
value = int(sys.argv[1])
sys.argv.pop(1)
else:
value = 0
cmd = COMMAND_SET_POWER
elif option == '-v':
verbose = True
if len(sys.argv) == 1:
listing = True
else:
exit_with_usage(sys.argv[0])
except:
exit_with_usage(sys.argv[0])
if ((busnum != None and devnum == None)
or (busnum == None and devnum != None)):
exit_with_usage(sys.argv[0])
if hub == None and busnum == None:
hub = 0 # Default hub = 0
if cmd == COMMAND_SET_NONE:
cmd = COMMAND_SET_POWER
hubs = find_hubs(listing, verbose, busnum, devnum, hub)
if len(hubs) == 0:
print >> sys.stderr, "No hubs found."
exit(1)
if listing:
exit(0)
if hub == None:
for h in hubs:
if h['busnum'] == busnum and h['devnum'] == devnum:
dev_hub = h['dev']
nports = h['num_ports']
else:
dev_hub = hubs[hub]['dev']
nports = hubs[hub]['num_ports']
uh = dev_hub.open()
if cmd == COMMAND_SET_POWER:
feature = USB_PORT_FEAT_POWER
index = port
if value:
request = usb.REQ_SET_FEATURE
else:
request = usb.REQ_CLEAR_FEATURE
else:
request = usb.REQ_SET_FEATURE
feature = USB_PORT_FEAT_INDICATOR
index = (value << 8) | port
if verbose:
print "Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d) " % (request, feature, index)
uh.controlMsg(requestType = USB_RT_PORT, request = request, value = feature,
index = index, buffer = None, timeout = 1000)
if verbose:
hub_port_status(uh,nports)
del uh