From 4749062338f5b6f9fa994a376d2d564fbbec0477 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 14 Oct 2011 15:50:08 +0900 Subject: [PATCH 001/300] increase (decreased) main (interrupt) stack size --- ChangeLog | 4 ++++ src/gnuk.ld.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2e649c1..74f2e3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-14 NIIBE Yutaka + + * src/gnuk.ld.in (__main_stack_size__): It's 1KB (was 512 byte). + 2011-10-07 NIIBE Yutaka * Version 0.14. diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index cefb008..121f47c 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -27,7 +27,7 @@ /* * ST32F103 memory setup. */ -__main_stack_size__ = 0x0200; +__main_stack_size__ = 0x0400; __process_stack_size__ = 0x0200; __stacks_total_size__ = __main_stack_size__ + __process_stack_size__; From 683253b2ebc1ec488ee9a059fcbfc2961c4351ce Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 10:59:44 +0900 Subject: [PATCH 002/300] workaround for GCC (summon-arm-toolchain) --- ChangeLog | 8 ++++++++ src/Makefile.in | 1 + 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 74f2e3d..f640cc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-01 Niibe Yutaka + + * 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 * src/gnuk.ld.in (__main_stack_size__): It's 1KB (was 512 byte). diff --git a/src/Makefile.in b/src/Makefile.in index cc77479..929654e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -205,6 +205,7 @@ ifeq ($(USE_FWLIB),yes) endif include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk +MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd distclean: clean -rm -f Makefile gnuk.ld config.h From 447139f74d8d28a7eb78d30c907dba85a5a62801 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 11:01:16 +0900 Subject: [PATCH 003/300] fixed the bug for user who keeps using initial PW1 --- ChangeLog | 2 ++ src/ac.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f640cc0..8601a02 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2011-11-01 Niibe Yutaka + * 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 diff --git a/src/ac.c b/src/ac.c index f6300d5..4d29ef7 100644 --- a/src/ac.c +++ b/src/ac.c @@ -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)) goto failure; else - goto success; + goto success_one_step; } else 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; } + success_one_step: sha1 (pw, pw_len, keystring); if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring)) < 0) goto failure; 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; - success: gpg_pw_reset_err_counter (PW_ERR_PW1); return pw_len; } From b2856d162e0a3c0b349a8490a281f66b27ac67d3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 11:02:22 +0900 Subject: [PATCH 004/300] added more DEBUG_XX --- src/openpgp-do.c | 4 ++++ src/openpgp.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/openpgp-do.c b/src/openpgp-do.c index aa36a7b..13cc88c 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -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]; struct key_data_internal kdi; + DEBUG_INFO ("Loading private key: "); + DEBUG_BYTE (kk); + if (do_data == NULL) return 0; @@ -646,6 +649,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring) /* more sanity check??? */ memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN); + DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN); return 1; } diff --git a/src/openpgp.c b/src/openpgp.c index 253de43..172bf22 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -726,6 +726,7 @@ cmd_pso (void) DEBUG_INFO (" - PSO: "); DEBUG_WORD ((uint32_t)&r); + DEBUG_BINARY (cmd_APDU, cmd_APDU_size); if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a) { @@ -751,6 +752,7 @@ cmd_pso (void) else { 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, &kd[GPG_KEY_FOR_SIGNING]); @@ -767,6 +769,7 @@ cmd_pso (void) else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86) { DEBUG_SHORT (len); + DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN); if (!ac_check_status (AC_OTHER_AUTHORIZED)) { From f3a3808608b68087040d04334e101823132c8fb5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 11:10:09 +0900 Subject: [PATCH 005/300] merge call-rsa.c change in the branch of rsa_1024_support. --- ChangeLog | 4 ++++ src/call-rsa.c | 27 ++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8601a02..1442404 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-11-01 Niibe Yutaka + * 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 diff --git a/src/call-rsa.c b/src/call-rsa.c index 7769ee8..8705d04 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -1,7 +1,7 @@ /* * 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 * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -28,7 +28,9 @@ #include "polarssl/config.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; @@ -43,10 +45,10 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, mpi_init (&P1, &Q1, &H, NULL); 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_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_sub_int (&P1, &rsa_ctx.P, 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 * modulus_calc (const uint8_t *p, int len) { mpi P, Q, N; uint8_t *modulus; - (void)len; /* 2048-bit assumed */ - modulus = malloc (2048 / 8); + modulus = malloc (len); if (modulus == NULL) return NULL; mpi_init (&P, &Q, &N, NULL); - mpi_read_binary (&P, p, 2048 / 8 / 2); - mpi_read_binary (&Q, p + 128, 2048 / 8 / 2); + mpi_read_binary (&P, p, len / 2); + mpi_read_binary (&Q, p + len / 2, len / 2); 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); return modulus; } @@ -135,8 +139,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, DEBUG_WORD (msg_len); 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.Q, &kd->data[128], 2048 / 8 / 2); + mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 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_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); From ec7a2db43a6cfe17d6d391e2eba3b13585c8d778 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 11:39:47 +0900 Subject: [PATCH 006/300] cosmetic fix of src/ac.c --- ChangeLog | 2 ++ src/ac.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1442404..10057a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2011-11-01 Niibe Yutaka + * 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. diff --git a/src/ac.c b/src/ac.c index 4d29ef7..9994ff9 100644 --- a/src/ac.c +++ b/src/ac.c @@ -172,7 +172,7 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len, count -= pw_len + 8; } - if (count < 8) + if (count <= 8) sha1_update (&sha1_ctx, salt, count); else { From de39c484d06ee6436746caea8a6afbcca68d182f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 11:41:20 +0900 Subject: [PATCH 007/300] support FST-01 8MHz --- ChangeLog | 2 + boards/FST_01_00/board.c | 36 +++++++++++ boards/FST_01_00/board.h | 129 +++++++++++++++++++++++++++++++++++++ boards/FST_01_00/mcuconf.h | 15 +++++ 4 files changed, 182 insertions(+) create mode 100644 boards/FST_01_00/board.c create mode 100644 boards/FST_01_00/board.h create mode 100644 boards/FST_01_00/mcuconf.h diff --git a/ChangeLog b/ChangeLog index 10057a9..93136de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2011-11-01 Niibe Yutaka + * 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. diff --git a/boards/FST_01_00/board.c b/boards/FST_01_00/board.c new file mode 100644 index 0000000..2425ffe --- /dev/null +++ b/boards/FST_01_00/board.c @@ -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); +} diff --git a/boards/FST_01_00/board.h b/boards/FST_01_00/board.h new file mode 100644 index 0000000..a938218 --- /dev/null +++ b/boards/FST_01_00/board.h @@ -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 . + + --- + + 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_ */ diff --git a/boards/FST_01_00/mcuconf.h b/boards/FST_01_00/mcuconf.h new file mode 100644 index 0000000..acfb005 --- /dev/null +++ b/boards/FST_01_00/mcuconf.h @@ -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" From ed7e904aef1fef43d133b0748983eb2bac968be2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 14:57:11 +0900 Subject: [PATCH 008/300] PIN input CIR support change --- ChangeLog | 25 ++ boards/STBEE/board.h | 4 + boards/STBEE_MINI/board.h | 4 + boards/STM8S_DISCOVERY/board.h | 5 + src/gnuk.h | 13 +- src/main.c | 280 +++++++++----- src/openpgp.c | 17 +- src/pin-cir.c | 682 ++++++++++++++++++++++++--------- src/usb_prop.c | 10 +- 9 files changed, 749 insertions(+), 291 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93136de..71de366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,30 @@ 2011-11-01 Niibe Yutaka + * 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. diff --git a/boards/STBEE/board.h b/boards/STBEE/board.h index 6e2e74d..a947f06 100644 --- a/boards/STBEE/board.h +++ b/boards/STBEE/board.h @@ -40,6 +40,10 @@ #if defined(PINPAD_SUPPORT) #define HAVE_7SEGLED 1 +/* + * Timer assignment for CIR + */ +#define TIMx TIM3 #endif /* diff --git a/boards/STBEE_MINI/board.h b/boards/STBEE_MINI/board.h index 8238c91..a256510 100644 --- a/boards/STBEE_MINI/board.h +++ b/boards/STBEE_MINI/board.h @@ -41,6 +41,10 @@ #if defined(PINPAD_SUPPORT) #define HAVE_7SEGLED 1 +/* + * Timer assignment for CIR + */ +#define TIMx TIM3 #endif /* diff --git a/boards/STM8S_DISCOVERY/board.h b/boards/STM8S_DISCOVERY/board.h index e0a2a5e..562dd55 100644 --- a/boards/STM8S_DISCOVERY/board.h +++ b/boards/STM8S_DISCOVERY/board.h @@ -56,6 +56,11 @@ */ #define GPIOA_LED 8 +/* + * Timer assignment for CIR + */ +#define TIMx TIM3 + /* * I/O ports initial setup, this configuration is established soon after reset * in the initialization code. diff --git a/src/gnuk.h b/src/gnuk.h index 196e4ed..5e3d4f7 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -348,5 +348,16 @@ extern void dial_sw_enable (void); extern uint8_t pin_input_buffer[MAX_PIN_CHARS]; extern uint8_t pin_input_len; -extern msg_t pin_main (void *arg); +extern int pinpad_getline (int msg_code, systime_t timeout); + +#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); + + #endif diff --git a/src/main.c b/src/main.c index 9344ee2..655aa59 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* * 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 * * 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; +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. * @@ -210,6 +365,8 @@ main (int argc, char **argv) (void)argc; (void)argv; + main_thread = chThdSelf (); + flash_unlock (); device_initialize_once (); usb_lld_init (); @@ -231,105 +388,47 @@ main (int argc, char **argv) while (1) { + eventmask_t m; + count++; - - if (fatal_code != 0) + 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); - chThdSleep (LED_TIMEOUT_ZERO); + chThdSleep (MS2ST (400)); 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); - } + break; + default: + break; + } - if (bDeviceState != CONFIGURED) + switch (main_mode) { + case GNUK_FATAL: + display_fatal_code (); + break; + case GNUK_INIT: set_led (1); chThdSleep (LED_TIMEOUT_ZERO); set_led (0); chThdSleep (LED_TIMEOUT_STOP * 3); - } - 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); - } - } + break; + case GNUK_INPUT_WAIT: + display_interaction (); + break; + case GNUK_RUNNING: + default: + display_status_code (); + break; + } #ifdef DEBUG_MORE if (bDeviceState == CONFIGURED && (count % 10) == 0) @@ -349,6 +448,7 @@ void fatal (uint8_t code) { fatal_code = code; + chEvtSignal (main_thread, LED_FATAL_MODE); _write ("fatal\r\n", 7); for (;;); } diff --git a/src/openpgp.c b/src/openpgp.c index 172bf22..1738363 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -97,24 +97,19 @@ gpg_fini (void) #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. * The string itself is in PIN_INPUT_BUFFER. */ static int get_pinpad_input (int msg_code) { - Thread *t; + int r; - t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128), - NORMALPRIO, pin_main, (void *)msg_code); - if (t == NULL) - return -1; - else - { - chThdWait (t); - return pin_input_len; - } + chEvtSignal (main_thread, LED_INPUT_MODE); + r = pinpad_getline (msg_code, MS2ST (8000)); + chEvtSignal (main_thread, LED_STATUS_MODE); + return r; } #endif diff --git a/src/pin-cir.c b/src/pin-cir.c index f512b94..75e84ef 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -27,13 +27,41 @@ #include "board.h" #include "gnuk.h" -#if 0 +#ifdef DEBUG #define DEBUG_CIR 1 #endif uint8_t pin_input_buffer[MAX_PIN_CHARS]; 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) * @@ -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 - * * Prescaler = 72 * * 1us * - * - * TIM3_CR1 - * CKD = 10 (sampling x4) - * ARPE = 0 (not buffered) + * TIMx_CR1 + * CKD = 00 (tDTS = tCK_INT) + * ARPE = 1 (buffered) * CMS = 00 (up counter) * DIR = 0 (up counter) * OPM = 0 (up counter) @@ -88,13 +124,13 @@ uint8_t pin_input_len; * UDIS = 0 (UEV (update event) enabled) * CEN = 1 (counter enable) * - * TIM3_CR2 + * TIMx_CR2 * TI1S = 1 (TI1 is XOR of ch1, ch2, ch3) * MMS = 000 (TRGO at Reset) * CCDS = 0 (DMA on capture) * RSVD = 000 * - * TIM3_SMCR + * TIMx_SMCR * ETP = 0 * ECE = 0 * ETPS = 00 @@ -104,60 +140,37 @@ uint8_t pin_input_len; * RSVD = 0 * SMS = 100 (Reset-mode) * - * TIM3_DIER + * TIMx_DIER * - * TIM3_SR + * TIMx_SR * - * TIM3_EGR + * TIMx_EGR * - * TIM3_CCMR1 + * TIMx_CCMR1 * CC1S = 01 (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) * CC2E = 1 * CC1P = 0 (polarity = rising edge: TI1FP1) * CC1E = 1 * - * TIM3_CNT - * TIM3_PSC = 71 - * TIM3_ARR = 18000 + * TIMx_CNT + * TIMx_PSC = 71 + * TIMx_ARR = 18000 * - * TIM3_CCR1 period - * TIM3_CCR2 duty + * TIMx_CCR1 period + * TIMx_CCR2 duty * - * TIM3_DCR - * TIM3_DMAR + * TIMx_DCR + * 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) static uint16_t intr_ext; @@ -179,14 +192,6 @@ static uint8_t cir_proto; #define CIR_PROTO_NEC 5 #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 */ static uint8_t cir_data_zero; @@ -196,6 +201,388 @@ static uint8_t cir_seq; static systime_t cir_input_last; #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} /* <> */ +}; + +#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} /* <> */ +}; + +#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 Asashi */ + { 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} /* <> */ +}; + +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} /* <> */, +}; + +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 * have the one. @@ -207,125 +594,56 @@ static systime_t cir_input_last; #define CIR_BIT_PERIOD 1500 #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 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; + pin_thread = chThdSelf (); -#if defined(DEBUG_CIR) - cirinput_p = cirinput; -#endif + DEBUG_INFO (">>>\r\n"); pin_input_len = 0; - chEvtClear (ALL_EVENTS); - cir_init (); - - while (!chThdShouldTerminate ()) + while (1) { - 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) - uint16_t *p; - - 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 (); + led_blink (2); + if (pin_input_len > 0) + pin_input_len--; } - - switch (s++) + else if (ch_is_enter (ch)) + break; + else if (pin_input_len < MAX_PIN_CHARS) { - case 0: - pindisp ('G'); - break; - case 1: - pindisp ('P'); - break; - case 2: - pindisp ('G'); - break; - case 3: - pindisp ('.'); - break; - default: - pindisp (' '); - s = 0; - break; + led_blink (0); + pin_input_buffer[pin_input_len++] = ch; } - - chThdSleep (PINDISP_TIMEOUT_INTERVAL0); } 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 cir_ext_interrupt (void) { @@ -340,29 +658,33 @@ cir_ext_interrupt (void) } #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 */ - TIM3->SR &= ~(TIM_SR_UIF + TIMx->SR &= ~(TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_TIF | TIM_SR_CC1OF | TIM_SR_CC2OF); - TIM3->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/; - TIM3->CR1 |= TIM_CR1_CEN; + TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/; + TIMx->CR1 |= TIM_CR1_CEN; } #define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \ * 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 cir_timer_interrupt (void) { uint16_t period, on, off; - period = TIM3->CCR1; - on = TIM3->CCR2; + period = TIMx->CCR1; + on = TIMx->CCR2; off = period - on; - if ((TIM3->SR & TIM_SR_TIF)) + if ((TIMx->SR & TIM_SR_TIF)) { if (cir_seq == 0) { @@ -477,23 +799,23 @@ cir_timer_interrupt (void) intr_trg++; #endif - TIM3->EGR = TIM_EGR_UG; /* Generate UEV */ - TIM3->SR &= ~TIM_SR_TIF; + TIMx->EGR = TIM_EGR_UG; /* Generate UEV */ + TIMx->SR &= ~TIM_SR_TIF; } else /* overflow occurred */ { systime_t now = chTimeNow (); - TIM3->SR &= ~TIM_SR_UIF; + TIMx->SR &= ~TIM_SR_UIF; if (on > 0) { uint8_t ignore_input = 0; /* Disable the timer */ - TIM3->CR1 &= ~TIM_CR1_CEN; - TIM3->DIER = 0; + TIMx->CR1 &= ~TIM_CR1_CEN; + TIMx->DIER = 0; if (cir_seq == 12 || cir_seq == 15) { @@ -536,14 +858,9 @@ cir_timer_interrupt (void) cir_input_last = now; ignore_input = 1; } - /* Remove ADDRESS bits and filter COMMAND bits */ else if (cir_proto == CIR_PROTO_SONY) { - if (cir_seq == 1 + 12) - cir_data = cir_data & 0x007f; - else if (cir_seq == 1 + 15) - cir_data = cir_data & 0x00ff; - else + if (cir_seq != 1 + 12 && cir_seq != 1 + 15) ignore_input = 1; } else if (cir_proto == CIR_PROTO_OTHER) @@ -551,10 +868,7 @@ cir_timer_interrupt (void) if (cir_seq == 1 + 32) { if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff)) - { - cir_proto = CIR_PROTO_NEC; - cir_data = (cir_data >> 16) & 0x00ff; - } + cir_proto = CIR_PROTO_NEC; else ignore_input = 1; } @@ -569,10 +883,7 @@ cir_timer_interrupt (void) ^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f) ^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f) ^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f))) - { - cir_proto = CIR_PROTO_SHARP; - cir_data = (cir_data >> 16) & 0x0fff; - } + cir_proto = CIR_PROTO_SHARP; else ignore_input = 1; } @@ -581,16 +892,12 @@ cir_timer_interrupt (void) } else if (cir_proto == CIR_PROTO_RC6) { - if (cir_seq == 16 || cir_seq == 32) - cir_data &= 0x00ff; - else + if (cir_seq != 16 && cir_seq != 32) ignore_input = 1; } else if (cir_proto == CIR_PROTO_RC5) { - if (cir_seq == 14) - cir_data &= 0x003f; - else + if (cir_seq != 14) ignore_input = 1; } else @@ -603,7 +910,8 @@ cir_timer_interrupt (void) { cir_input_last = now; /* Notify thread */ - chEvtSignal (pin_thread, (eventmask_t)1); + if (pin_thread) + chEvtSignalI (pin_thread, (eventmask_t)1); } #if defined(DEBUG_CIR) diff --git a/src/usb_prop.c b/src/usb_prop.c index 1abef3e..f9b06ef 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -120,8 +120,14 @@ gnuk_device_SetConfiguration (void) DEVICE_INFO *pInfo = &Device_Info; if (pInfo->Current_Configuration != 0) - /* Device configured */ - bDeviceState = CONFIGURED; + { /* Device 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 From 6337371016915fe11a1fd9e66542636bd9942d70 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 15:01:32 +0900 Subject: [PATCH 009/300] PIN input DIAL support change --- ChangeLog | 3 +++ src/pin-dial.c | 9 ++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71de366..4f03cba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-11-01 Niibe Yutaka + * 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. diff --git a/src/pin-dial.c b/src/pin-dial.c index d18ff65..67758bc 100644 --- a/src/pin-dial.c +++ b/src/pin-dial.c @@ -128,10 +128,9 @@ dial_sw_interrupt (void) } -msg_t -pin_main (void *arg) +int +pinpad_getline (int msg_code, systime_t timeout) { - int msg_code = (int)arg; uint16_t count, count_prev; uint8_t input_mode; uint8_t sw_push_count; @@ -150,7 +149,7 @@ pin_main (void *arg) sw_push_count = 0; sw_event = 0; - while (!chThdShouldTerminate ()) + while (1) { eventmask_t m; @@ -218,5 +217,5 @@ pin_main (void *arg) led_disp (OFF); TIM4->CR1 &= ~TIM_CR1_CEN; dial_sw_disable (); - return 0; + return pin_input_len; } From f45b7a5439b2b629a00aade351b174e64c08f525 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 15:13:58 +0900 Subject: [PATCH 010/300] minor change for pin-cir.c --- src/pin-cir.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pin-cir.c b/src/pin-cir.c index 75e84ef..7093e6a 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -171,7 +171,6 @@ uint8_t pin_input_len; * TIMx_DMAR */ - #if defined(DEBUG_CIR) static uint16_t intr_ext; static uint16_t intr_trg; @@ -269,7 +268,7 @@ cir_codetable_aquos[] = { { 0x0281, 'j' }, /* RED */ { 0x0282, 'k' }, /* GREEN */ { 0x0283, 'l' }, /* YELLOW */ - { 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */ + { 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */ { 0x01d5, 'n' }, /* DISPLAY SIZE */ { 0x0157, 'o' }, /* UP */ { 0x01d7, 'p' }, /* LEFT */ @@ -304,7 +303,7 @@ cir_codetable_aquos[] = { { 0x0113, 'F' }, /* Inputs (nyuuryoku kirikae) */ { 0x0275, 'G' }, /* other programs (ura bangumi) */ { 0x0266, 'H' }, /* signal control (eizou kirikae) */ - { 0x01e7, 'I' }, /* AV position */ + { 0x01e7, 'I' }, /* AV position */ { 0x027f, 'J' }, /* i.LINK */ { 0x0b00, 'K' }, /* Recorder power */ { 0x028f, 'L' }, /* as you like it (okonomi senkyoku) */ @@ -375,7 +374,7 @@ cir_codetable_regza[] = { { 0x62, '@' }, /* 2 NHK2 */ { 0x63, '#' }, /* 3 NHKh */ { 0x64, '$' }, /* 4 BS Nihon TV */ - { 0x65, '%' }, /* 5 BS Asashi */ + { 0x65, '%' }, /* 5 BS Asahi */ { 0x66, '^' }, /* 6 BS-i */ { 0x67, '&' }, /* 7 BSJ */ { 0x68, '*' }, /* 8 BS Fuji */ From e790bb783cbf8cb1dffabd723f7cf5a4665ce265 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 1 Nov 2011 15:58:48 +0900 Subject: [PATCH 011/300] change README and NEWS --- NEWS | 21 +++++++++++++++++++++ README | 35 ++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 8644738..f8944fd 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,26 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 0.15 + + Released 2011-11-XX, by NIIBE Yutaka + +** 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 diff --git a/README b/README index a974551..29620ad 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token - Version 0.14 - 2011-10-07 + Version 0.15 + 2011-11-XX Niibe Yutaka Free Software Initiative of Japan @@ -94,7 +94,7 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of Release notes ============= -This is fifteenth 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. Tested features are: @@ -119,10 +119,11 @@ It is known not-working well: work well. Please disable DEBUG option if it doesn't work well. * Card holder certificate - It is implemented in Gnuk side. But its size matters (> - 1KB). GnuPG cannot handle a data object of large size with - PC/SC backend. Specifically, handle_transmit function in - pcsc-wrapper.c uses the buffer of size 1024-byte. + It is implemented in Gnuk side. But its large size matters + (> 1KB). Some versions of GnuPG cannot handle a data object + of large size with PC/SC backend. Specifically, + handle_transmit function in pcsc-wrapper.c uses the buffer + of size 1024-byte. Not supported feature(s): @@ -230,8 +231,24 @@ How to compile You need GNU toolchain and newlib for 'arm-none-eabi' target. -See http://github.com/uwehermann/summon-arm-toolchain/ for preparation -of GNU Toolchain for 'arm-none-eabi' target. +See http://github.com/esden/summon-arm-toolchain/ (which includes fix +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': From 1ac7e20fb028597f0d5b8f30406792276811243a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 Nov 2011 14:22:37 +0900 Subject: [PATCH 012/300] add FST_01 --- ChangeLog | 4 ++ boards/FST_01/board.c | 107 +++++++++++++++++++++++++++++++ boards/FST_01/board.h | 138 ++++++++++++++++++++++++++++++++++++++++ boards/FST_01/mcuconf.h | 15 +++++ src/gnuk.h | 19 +++--- 5 files changed, 273 insertions(+), 10 deletions(-) create mode 100644 boards/FST_01/board.c create mode 100644 boards/FST_01/board.h create mode 100644 boards/FST_01/mcuconf.h diff --git a/ChangeLog b/ChangeLog index 4f03cba..4d1cf0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-14 Niibe Yutaka + + * boards/FST_01/{mcuconf.h,board.h,board.c}: New. + 2011-11-01 Niibe Yutaka * src/pin-dial.c (pinpad_getline): New. diff --git a/boards/FST_01/board.c b/boards/FST_01/board.c new file mode 100644 index 0000000..1172c27 --- /dev/null +++ b/boards/FST_01/board.c @@ -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 diff --git a/boards/FST_01/board.h b/boards/FST_01/board.h new file mode 100644 index 0000000..df3f3bf --- /dev/null +++ b/boards/FST_01/board.h @@ -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 . + + --- + + 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_ */ diff --git a/boards/FST_01/mcuconf.h b/boards/FST_01/mcuconf.h new file mode 100644 index 0000000..56235c0 --- /dev/null +++ b/boards/FST_01/mcuconf.h @@ -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" diff --git a/src/gnuk.h b/src/gnuk.h index 5e3d4f7..994e789 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -333,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 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_CIR_SUPPORT) extern void cir_ext_disable (void); @@ -350,14 +359,4 @@ extern uint8_t pin_input_len; extern int pinpad_getline (int msg_code, systime_t timeout); -#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); - - #endif From 2c91633f597c35582ee9b97342105f7ffa2b6f77 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 Nov 2011 14:34:51 +0900 Subject: [PATCH 013/300] add FST-01 description --- README | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/README b/README index 29620ad..4e63114 100644 --- a/README +++ b/README @@ -134,8 +134,8 @@ Not supported feature(s): Targets ======= -We use Olimex STM32-H103 board. We also use STM32 part of STM8S -Discovery Kit. +We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We +also use STM32 part of STM8S Discovery Kit. With DfuSe support, CQ STARM, STBee, and STBee Mini are also our targets. But those targets with DfuSe are basically not for normal @@ -285,6 +285,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 ------------------- From 62520ed0f47d7bf117d78bf00178c9c1eac5d67c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 Nov 2011 16:17:37 +0900 Subject: [PATCH 014/300] tool/dfuse.py: support unaligned write and hole --- ChangeLog | 5 +++++ tool/dfuse.py | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4d1cf0f..eb1c2e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-22 Niibe Yutaka + + * tool/dfuse.py (DFU_STM32.download, DFU_STM32.verify): Support + unaligned write and hole. + 2011-11-14 Niibe Yutaka * boards/FST_01/{mcuconf.h,board.h,board.c}: New. diff --git a/tool/dfuse.py b/tool/dfuse.py index 722f217..0dcf619 100755 --- a/tool/dfuse.py +++ b/tool/dfuse.py @@ -4,7 +4,7 @@ dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor. "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 This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -208,10 +208,20 @@ class DFU_STM32: # First, erase pages sys.stdout.write("Erasing: ") sys.stdout.flush() + last_addr = 0 for start_addr in sorted(ih.memory.keys()): data = ih.memory[start_addr] end_addr = start_addr + len(data) addr = start_addr & 0xfffffc00 + if not last_addr == 0: + i = 0 + 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 while addr < end_addr: self.dfuse_erase(addr) @@ -220,18 +230,28 @@ class DFU_STM32: sys.stdout.flush() addr += 1024 i += 1 + last_addr = addr sys.stdout.write("\n") sys.stdout.flush() # Then, write pages sys.stdout.write("Writing: ") sys.stdout.flush() + last_addr = 0 for start_addr in sorted(ih.memory.keys()): data = ih.memory[start_addr] end_addr = start_addr + len(data) 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: - raise ValueError, "padding is not supported yet" + # fill by 0xff + data = '\xff' * (start_addr & 0x3ff) + data self.dfuse_set_address_pointer(addr) i = 0 while addr < end_addr: @@ -241,6 +261,7 @@ class DFU_STM32: sys.stdout.flush() addr += 1024 i += 1 + last_addr = addr if self.__protocol == DFU_STM32PROTOCOL_0: # 0-length write at the end self.ll_download_block(self.__blocknum, None) @@ -268,13 +289,22 @@ class DFU_STM32: # Read pages sys.stdout.write("Reading: ") sys.stdout.flush() + last_addr = 0 for start_addr in sorted(ih.memory.keys()): data = ih.memory[start_addr] end_addr = start_addr + len(data) 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: - raise ValueError, "padding is not supported yet" + # fill by 0xff + data = '\xff' * (start_addr & 0x3ff) + data self.dfuse_set_address_pointer(addr) self.ll_clear_status() self.ll_clear_status() @@ -291,6 +321,7 @@ class DFU_STM32: sys.stdout.flush() addr += 1024 i += 1 + last_addr = addr self.ll_clear_status() self.ll_clear_status() self.ll_clear_status() From 0232c0a595c4a6b53e3f9060b7c3995998460140 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 Nov 2011 13:54:12 +0900 Subject: [PATCH 015/300] dfuse.py: fix handling of unaligned page --- tool/dfuse.py | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/tool/dfuse.py b/tool/dfuse.py index 0dcf619..8239f6f 100755 --- a/tool/dfuse.py +++ b/tool/dfuse.py @@ -215,13 +215,16 @@ class DFU_STM32: addr = start_addr & 0xfffffc00 if not last_addr == 0: i = 0 - while last_addr < addr: - self.dfuse_erase(last_addr) - if i & 0x03 == 0x03: - sys.stdout.write(".") - sys.stdout.flush() - last_addr += 1024 - i += 1 + 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 while addr < end_addr: self.dfuse_erase(addr) @@ -249,11 +252,13 @@ class DFU_STM32: sys.stdout.flush() last_addr += 1024 i += 1 - if addr != start_addr: - # fill by 0xff - data = '\xff' * (start_addr & 0x3ff) + data - self.dfuse_set_address_pointer(addr) 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: self.dfuse_write_memory(data[i*1024:(i+1)*1024]) if i & 0x03 == 0x03: @@ -303,8 +308,19 @@ class DFU_STM32: last_addr += 1024 i += 1 if addr != start_addr: - # fill by 0xff - data = '\xff' * (start_addr & 0x3ff) + data + 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.ll_clear_status() self.ll_clear_status() From bc71c39ea4962e62ff0b0d350cbb8d769aa67109 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 Nov 2011 15:40:38 +0900 Subject: [PATCH 016/300] version 0.15 --- ChangeLog | 5 +++++ NEWS | 9 ++++++++- README | 16 +++++++++++++++- src/usb_desc.c | 2 +- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index eb1c2e3..f8ab93d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-24 Niibe Yutaka + + * Version 0.15. + * src/usb_desc.c (gnukStringSerial): Updated. + 2011-11-22 Niibe Yutaka * tool/dfuse.py (DFU_STM32.download, DFU_STM32.verify): Support diff --git a/NEWS b/NEWS index f8944fd..6608be8 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,14 @@ Gnuk NEWS - User visible changes * Major changes in Gnuk 0.15 - Released 2011-11-XX, by NIIBE Yutaka + 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. diff --git a/README b/README index 4e63114..87d0e86 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token Version 0.15 - 2011-11-XX + 2011-11-24 Niibe Yutaka Free Software Initiative of Japan @@ -90,6 +90,20 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of and confirm scdaemon doesn't exist, then, $ 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 ============= diff --git a/src/usb_desc.c b/src/usb_desc.c index 47565e9..05a08d8 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -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, '4', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '1', 0, '5', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From 268c41634a8f6a37c70e11dd38764f5f1f2a71d4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 Nov 2011 15:18:25 +0900 Subject: [PATCH 017/300] pinpad input for reset code --- ChangeLog | 5 +++++ src/openpgp.c | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8ab93d..04800c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-29 Niibe Yutaka + + * src/openpgp.c (cmd_put_data) [PINPAD_SUPPORT]: Support pinpad + input (for reset code). + 2011-11-24 Niibe Yutaka * Version 0.15. diff --git a/src/openpgp.c b/src/openpgp.c index 1738363..646f9be 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -572,13 +572,44 @@ cmd_put_data (void) GPG_NO_RECORD(); tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]); - len = cmd_APDU_size - 5; data = &cmd_APDU[5]; - if (len >= 256) - /* extended Lc */ + +#if defined(PINPAD_SUPPORT) + if (cmd_APDU_size == 4) /* For 0xD3: reset code */ { - data += 2; - len -= 2; + len = get_pinpad_input (PIN_INPUT_NEW); + if (len < 0) + { + GPG_ERROR (); + return; + } + + cmd_APDU[4] = len; + memcpy (data, pin_input_buffer, len); + + len = get_pinpad_input (PIN_INPUT_CONFIRM); + if (len < 0) + { + GPG_ERROR (); + return; + } + + if (len != cmd_APDU[4] || memcmp (data, pin_input_buffer, len) !=0) + { + GPG_SECURITY_FAILURE (); + return; + } + } + else +#endif + { + len = cmd_APDU_size - 5; + if (len >= 256) + /* extended Lc */ + { + data += 2; + len -= 2; + } } gpg_do_put_data (tag, data, len); From 1e94b262af40e787f8640af7074e83a6a1ed4aed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 1 Dec 2011 18:23:10 +0900 Subject: [PATCH 018/300] pinpad support change --- ChangeLog | 18 ++++ src/gnuk.h | 7 ++ src/openpgp.c | 262 +++++++++++++++++++------------------------------ src/openpgp.h | 2 + src/pin-cir.c | 2 +- src/pin-dial.c | 5 +- src/usb-icc.c | 10 +- 7 files changed, 138 insertions(+), 168 deletions(-) diff --git a/ChangeLog b/ChangeLog index 04800c6..9e57599 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-12-01 Niibe Yutaka + + * src/gnuk.h (EV_PINPAD_INPUT_DONE, EV_NOP, EV_CMD_AVAILABLE) + (EV_VERIFY_CMD_AVAILABLE, EV_MODIFY_CMD_AVAILABLE): New. + * src/usb-icc.c (icc_power_off, icc_handle_data): Use EV_NOP, + EV_CMD_AVAILABLE, EV_VERIFY_CMD_AVAILABLE, and EV_MODIFY_CMD_AVAILABLE. + * src/pin-cir.c (cir_timer_interrupt): Use EV_PINPAD_INPUT_DONE. + * src/pin-dial.c (dial_sw_interrupt, pinpad_getline): Ditto. + (EV_SW_PUSH): Remove. + + * src/openpgp.h (GPG_FUNCTION_NOT_SUPPORTED): New. + (GPG_CONDITION_NOT_SATISFIED): New. + * src/openpgp.c (cmd_change_password): Use GPG_FUNCTION_NOT_SUPPORTED. + + * src/openpgp.c (cmd_verify, cmd_change_password) + (cmd_reset_user_password, cmd_put_data): Remove pinpad handling... + (GPGthread): ... and implement pinpad handling here. + 2011-11-29 Niibe Yutaka * src/openpgp.c (cmd_put_data) [PINPAD_SUPPORT]: Support pinpad diff --git a/src/gnuk.h b/src/gnuk.h index 994e789..2df1def 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -24,6 +24,13 @@ extern void *memmove(void *dest, const void *src, size_t n); #define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */ +/* GPG thread */ +#define EV_PINPAD_INPUT_DONE ((eventmask_t)1) +#define EV_NOP ((eventmask_t)2) +#define EV_CMD_AVAILABLE ((eventmask_t)4) +#define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8) +#define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16) + /* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */ #define MAX_CMD_APDU_SIZE (7+282) /* header + data */ /* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */ diff --git a/src/openpgp.c b/src/openpgp.c index 646f9be..19377d7 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -125,32 +125,14 @@ cmd_verify (void) DEBUG_INFO (" - VERIFY\r\n"); DEBUG_BYTE (p2); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Verification with pinpad */ + len = cmd_APDU[4]; + if (len == 0) /* extended length */ { - len = get_pinpad_input (PIN_INPUT_CURRENT); - if (len < 0) - { - GPG_ERROR (); - return; - } - - pw = pin_input_buffer; - } - else -#endif - { - len = cmd_APDU[4]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - - pw = &cmd_APDU[data_start]; + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + data_start = 7; } + pw = &cmd_APDU[data_start]; if (p2 == 0x81) r = verify_pso_cds (pw, len); @@ -231,6 +213,7 @@ cmd_change_password (void) uint8_t old_ks[KEYSTRING_MD_SIZE]; uint8_t new_ks0[KEYSTRING_MD_SIZE+1]; uint8_t *new_ks = &new_ks0[1]; + uint8_t p1 = cmd_APDU[2]; /* 0: change (old+new), 1: exchange (new) */ uint8_t p2 = cmd_APDU[3]; int len; const uint8_t *pw; @@ -242,55 +225,18 @@ cmd_change_password (void) DEBUG_INFO ("Change PW\r\n"); DEBUG_BYTE (who); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Modification with pinpad */ + len = cmd_APDU[4]; + pw = &cmd_APDU[5]; + if (len == 0) /* extended length */ { - pw_len = get_pinpad_input (PIN_INPUT_CURRENT); - if (pw_len < 0) - { - GPG_ERROR (); - return; - } - - pw = &cmd_APDU[5]; - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); - newpw = pw + pw_len; - - newpw_len = get_pinpad_input (PIN_INPUT_NEW); - if (newpw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0) - { - GPG_SECURITY_FAILURE (); - return; - } - - len = cmd_APDU[4] = pw_len + newpw_len; + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + pw += 2; } - else -#endif + + if (p1 != 0) { - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + GPG_FUNCTION_NOT_SUPPORTED(); + return; } if (who == BY_USER) /* PW1 */ @@ -395,60 +341,12 @@ cmd_reset_user_password (void) DEBUG_INFO ("Reset PW1\r\n"); DEBUG_BYTE (p1); -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) - /* Modification with pinpad */ + len = cmd_APDU[4]; + pw = &cmd_APDU[5]; + if (len == 0) /* extended length */ { - if (p1 == 0x00) /* by User with Reseting Code */ - { - pw_len = get_pinpad_input (PIN_INPUT_CURRENT); - if (pw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); - } - else - pw_len = 0; - - pw = &cmd_APDU[5]; - newpw = pw + pw_len; - newpw_len = get_pinpad_input (PIN_INPUT_NEW); - if (newpw_len < 0) - { - GPG_ERROR (); - return; - } - - memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0) - { - GPG_SECURITY_FAILURE (); - return; - } - - len = cmd_APDU[4] = pw_len + newpw_len; - } - else -#endif - { - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; + pw += 2; } if (p1 == 0x00) /* by User with Reseting Code */ @@ -574,42 +472,12 @@ cmd_put_data (void) tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]); data = &cmd_APDU[5]; -#if defined(PINPAD_SUPPORT) - if (cmd_APDU_size == 4) /* For 0xD3: reset code */ + len = cmd_APDU_size - 5; + if (len >= 256) + /* extended Lc */ { - len = get_pinpad_input (PIN_INPUT_NEW); - if (len < 0) - { - GPG_ERROR (); - return; - } - - cmd_APDU[4] = len; - memcpy (data, pin_input_buffer, len); - - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) - { - GPG_ERROR (); - return; - } - - if (len != cmd_APDU[4] || memcmp (data, pin_input_buffer, len) !=0) - { - GPG_SECURITY_FAILURE (); - return; - } - } - else -#endif - { - len = cmd_APDU_size - 5; - if (len >= 256) - /* extended Lc */ - { - data += 2; - len -= 2; - } + data += 2; + len -= 2; } gpg_do_put_data (tag, data, len); @@ -1057,15 +925,91 @@ GPGthread (void *arg) while (!chThdShouldTerminate ()) { - chEvtWaitOne (ALL_EVENTS); + eventmask_t m = chEvtWaitOne (ALL_EVENTS); +#if defined(PINPAD_SUPPORT) + int len, pw_len, newpw_len; +#endif DEBUG_INFO ("GPG!: "); - res_APDU_pointer = NULL; /* default */ + res_APDU_pointer = NULL; + + if (m == EV_VERIFY_CMD_AVAILABLE) + { +#if defined(PINPAD_SUPPORT) + if (cmd_APDU[1] != INS_VERIFY) + { + GPG_CONDITION_NOT_SATISFIED (); + goto done; + } + + pw_len = get_pinpad_input (PIN_INPUT_CURRENT); + if (pw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); + cmd_APDU[4] = pw_len; + icc_data_size = 5 + pw_len; +#else + GPG_ERROR (); + goto done; +#endif + } + else if (m == EV_MODIFY_CMD_AVAILABLE) + { +#if defined(PINPAD_SUPPORT) + if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA) + { + GPG_CONDITION_NOT_SATISFIED (); + goto done; + } + + pw_len = get_pinpad_input (PIN_INPUT_CURRENT); + if (pw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); + + newpw_len = get_pinpad_input (PIN_INPUT_NEW); + if (newpw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); + + len = get_pinpad_input (PIN_INPUT_CONFIRM); + if (len < 0) + { + GPG_ERROR (); + goto done; + } + + if (len != newpw_len + || memcmp (&cmd_APDU[5]+pw_len, pin_input_buffer, len) != 0) + { + GPG_SECURITY_FAILURE (); + goto done; + } + + len = cmd_APDU[4] = pw_len + newpw_len; + icc_data_size = 5 + len; +#else + GPG_ERROR (); + goto done; +#endif + } + else if (m == EV_NOP) + continue; if (icc_data_size != 0) { process_command_apdu (); + done: chEvtSignal (icc_thread, EV_EXEC_FINISHED); } } diff --git a/src/openpgp.h b/src/openpgp.h index 0d039c9..8cd3f8c 100644 --- a/src/openpgp.h +++ b/src/openpgp.h @@ -1,7 +1,9 @@ #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_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85) #define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86) +#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81) #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) diff --git a/src/pin-cir.c b/src/pin-cir.c index 7093e6a..4bf1052 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -910,7 +910,7 @@ cir_timer_interrupt (void) cir_input_last = now; /* Notify thread */ if (pin_thread) - chEvtSignalI (pin_thread, (eventmask_t)1); + chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE); } #if defined(DEBUG_CIR) diff --git a/src/pin-dial.c b/src/pin-dial.c index 67758bc..5fd471e 100644 --- a/src/pin-dial.c +++ b/src/pin-dial.c @@ -117,13 +117,12 @@ blink_dp (void) } static Thread *pin_thread; -#define EV_SW_PUSH (eventmask_t)1 void dial_sw_interrupt (void) { dial_sw_disable (); - chEvtSignalI (pin_thread, EV_SW_PUSH); + chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE); palClearPad (IOPORT1, GPIOA_LED2); } @@ -157,7 +156,7 @@ pinpad_getline (int msg_code, systime_t timeout) dial_sw_enable (); m = chEvtWaitOneTimeout (ALL_EVENTS, LED_DISP_BLINK_INTERVAL0); - if (m == EV_SW_PUSH || sw_push_count) + if (m == EV_PINPAD_INPUT_DONE || sw_push_count) { if (palReadPad (IOPORT2, GPIOB_BUTTON) == 0) sw_push_count++; diff --git a/src/usb-icc.c b/src/usb-icc.c index d526513..156d19a 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -374,7 +374,7 @@ icc_power_off (void) if (gpg_thread) { chThdTerminate (gpg_thread); - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_NOP); chThdWait (gpg_thread); gpg_thread = NULL; } @@ -497,7 +497,7 @@ icc_handle_data (void) { if (icc_header->param == 0) { /* Give this message to GPG thread */ - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (icc_header->param == 1) @@ -524,7 +524,7 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[27]; cmd_APDU[3] = icc_buffer[28]; icc_data_size = 4; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (icc_buffer[10] == 0x01) /* PIN Modification */ @@ -540,7 +540,7 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[29 + num_msgs]; cmd_APDU[3] = icc_buffer[30 + num_msgs]; icc_data_size = 4; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else @@ -572,7 +572,7 @@ icc_handle_data (void) icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE; icc_chain_p = NULL; next_state = ICC_STATE_EXECUTE; - chEvtSignal (gpg_thread, (eventmask_t)1); + chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); } else /* icc_header->param == 3 is not supported. */ { From 142dbabfd8c56d00f2a9d9ce0586eefbc4d6a0b9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 7 Dec 2011 09:38:48 +0900 Subject: [PATCH 019/300] pinpad entry parameter handling --- ChangeLog | 7 +++++++ src/openpgp.c | 43 +++++++++++++++++++++++++++---------------- src/usb-icc.c | 19 +++++++++++++++++++ 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e57599..2f0e1e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-07 Niibe Yutaka + + * src/openpgp.c (GPGthread): Handle bConfirmPIN parameter. + + * src/usb-icc.c (icc_handle_data): Pass PC_to_RDR_Secure + information to gpg_thread using memory of cmd_APDU. + 2011-12-01 Niibe Yutaka * src/gnuk.h (EV_PINPAD_INPUT_DONE, EV_NOP, EV_CMD_AVAILABLE) diff --git a/src/openpgp.c b/src/openpgp.c index 19377d7..2ea4519 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -960,19 +960,28 @@ GPGthread (void *arg) else if (m == EV_MODIFY_CMD_AVAILABLE) { #if defined(PINPAD_SUPPORT) + uint8_t bConfirmPIN = cmd_APDU[4]; + uint8_t *p = &cmd_APDU[5]; + if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA) { GPG_CONDITION_NOT_SATISFIED (); goto done; } - pw_len = get_pinpad_input (PIN_INPUT_CURRENT); - if (pw_len < 0) + if ((bConfirmPIN & 2)) /* Require old PIN */ { - GPG_ERROR (); - goto done; + pw_len = get_pinpad_input (PIN_INPUT_CURRENT); + if (pw_len < 0) + { + GPG_ERROR (); + goto done; + } + memcpy (p, pin_input_buffer, pw_len); + p += pw_len; } - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); + else + pw_len = 0; newpw_len = get_pinpad_input (PIN_INPUT_NEW); if (newpw_len < 0) @@ -980,20 +989,22 @@ GPGthread (void *arg) GPG_ERROR (); goto done; } - memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len); + memcpy (p, pin_input_buffer, newpw_len); - len = get_pinpad_input (PIN_INPUT_CONFIRM); - if (len < 0) + if ((bConfirmPIN & 1)) /* New PIN twice */ { - GPG_ERROR (); - goto done; - } + len = get_pinpad_input (PIN_INPUT_CONFIRM); + if (len < 0) + { + GPG_ERROR (); + goto done; + } - if (len != newpw_len - || memcmp (&cmd_APDU[5]+pw_len, pin_input_buffer, len) != 0) - { - GPG_SECURITY_FAILURE (); - goto done; + if (len != newpw_len || memcmp (p, pin_input_buffer, len) != 0) + { + GPG_SECURITY_FAILURE (); + goto done; + } } len = cmd_APDU[4] = pw_len + newpw_len; diff --git a/src/usb-icc.c b/src/usb-icc.c index 156d19a..5c1e33b 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -524,6 +524,14 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[27]; cmd_APDU[3] = icc_buffer[28]; icc_data_size = 4; + cmd_APDU[4] = 0; /* bConfirmPIN */ + cmd_APDU[5] = icc_buffer[17]; /* bEntryValidationCondition */ + cmd_APDU[6] = icc_buffer[18]; /* bNumberMessage */ + cmd_APDU[7] = icc_buffer[19]; /* wLangId L */ + cmd_APDU[8] = icc_buffer[20]; /* wLangId H */ + cmd_APDU[9] = icc_buffer[21]; /* bMsgIndex, bMsgIndex1 */ + cmd_APDU[10] = 0; /* bMsgIndex2 */ + cmd_APDU[11] = 0; /* bMsgIndex3 */ chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } @@ -540,6 +548,17 @@ icc_handle_data (void) cmd_APDU[2] = icc_buffer[29 + num_msgs]; cmd_APDU[3] = icc_buffer[30 + num_msgs]; icc_data_size = 4; + cmd_APDU[4] = icc_buffer[19]; /* bConfirmPIN */ + cmd_APDU[5] = icc_buffer[20]; /* bEntryValidationCondition */ + cmd_APDU[6] = icc_buffer[21]; /* bNumberMessage */ + cmd_APDU[7] = icc_buffer[22]; /* wLangId L */ + cmd_APDU[8] = icc_buffer[23]; /* wLangId H */ + cmd_APDU[9] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */ + cmd_APDU[10] = cmd_APDU[11] = 0; + if (num_msgs >= 2) + cmd_APDU[10] = icc_buffer[25]; /* bMsgIndex2 */ + if (num_msgs == 3) + cmd_APDU[11] = icc_buffer[26]; /* bMsgIndex3 */ chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } From 351ce68729ee6eb8aa2c8c54c9fbe0d6afc86014 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 7 Dec 2011 10:16:02 +0900 Subject: [PATCH 020/300] better USB interoperability --- ChangeLog | 6 ++++++ src/usb_desc.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2f0e1e3..5800fca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2011-12-07 Niibe Yutaka + * src/usb_desc.c (gnukDeviceDescriptor): Changed bcdUSB = 1.1. + Gnuk device conforms to USB 2.0 full speed device, but when it was + 2.0, some OS informs users, "you can connect the device to 2.0 + compliant hub so that it can have better bandwidth", which is not + the case for full speed device. + * src/openpgp.c (GPGthread): Handle bConfirmPIN parameter. * src/usb-icc.c (icc_handle_data): Pass PC_to_RDR_Secure diff --git a/src/usb_desc.c b/src/usb_desc.c index 05a08d8..50ab1c3 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -15,7 +15,7 @@ static const uint8_t gnukDeviceDescriptor[] = { 18, /* bLength */ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ - 0x00, 0x02, /* bcdUSB = 2.00 */ + 0x10, 0x01, /* bcdUSB = 1.1 */ 0x00, /* bDeviceClass: 0 means deferred to interface */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ From 9dcb59f6aa78b1e6261bfc853a270df739a83f63 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 8 Dec 2011 10:56:48 +0900 Subject: [PATCH 021/300] minor cleanup --- ChangeLog | 6 ++++++ src/usb-icc.c | 1 - src/usb_endp.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5800fca..bf4f16a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-08 Niibe Yutaka + + * src/usb-icc.c: Not include "usb_desc.h". + + * src/usb_endp.c (EP5_OUT_Callback): Fix minor bug. + 2011-12-07 Niibe Yutaka * src/usb_desc.c (gnukDeviceDescriptor): Changed bcdUSB = 1.1. diff --git a/src/usb-icc.c b/src/usb-icc.c index 5c1e33b..0258930 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -26,7 +26,6 @@ #include "hal.h" #include "gnuk.h" #include "usb_lib.h" -#include "usb_desc.h" #include "usb_mem.h" #include "hw_config.h" #include "usb_istr.h" diff --git a/src/usb_endp.c b/src/usb_endp.c index cdf675c..42a3aaf 100644 --- a/src/usb_endp.c +++ b/src/usb_endp.c @@ -18,5 +18,5 @@ EP3_IN_Callback(void) void EP5_OUT_Callback(void) { - SetEPRxValid (ENDP3); + SetEPRxValid (ENDP5); } From b113e6fa7bc39eec7add6f6bb88ab4259285faed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 13 Dec 2011 11:21:45 +0900 Subject: [PATCH 022/300] verify_other should not fail with no keys, but really checks PW1 --- ChangeLog | 7 +++++++ src/ac.c | 57 ++++++++++++++++++++++++++------------------------- src/gnuk.h | 4 ++-- src/openpgp.c | 2 +- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf4f16a..67b57f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Niibe Yutaka + + * src/ac.c (verify_user_0): Add access argument. + (verify_pso_cds, verify_other, verify_admin_0): Follow the change. + + * src/openpgp.c (cmd_change_password): Likewise. + 2011-12-08 Niibe Yutaka * src/usb-icc.c: Not include "usb_desc.h". diff --git a/src/ac.c b/src/ac.c index 9994ff9..87e09ba 100644 --- a/src/ac.c +++ b/src/ac.c @@ -57,11 +57,11 @@ ac_reset_other (void) } int -verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known, +verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known, const uint8_t *ks_pw1) { int pw_len; - int r; + int r1, r2; uint8_t keystring[KEYSTRING_MD_SIZE]; if (gpg_pw_locked (PW_ERR_PW1)) @@ -90,10 +90,23 @@ verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known, success_one_step: sha1 (pw, pw_len, keystring); - if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring)) - < 0) - goto failure; - else if (r == 0) + if (access == AC_PSO_CDS_AUTHORIZED) + { + r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); + r2 = 0; + } + else + { + r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring); + r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring); + } + + if (r1 < 0 || r2 < 0) + { + gpg_pw_increment_err_counter (PW_ERR_PW1); + return -1; + } + else if (r1 == 0 && r2 == 0) if (ks_pw1 != NULL && memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 0) goto failure; @@ -113,7 +126,7 @@ verify_pso_cds (const uint8_t *pw, int pw_len) DEBUG_INFO ("verify_pso_cds\r\n"); DEBUG_BYTE (pw_len); - r = verify_user_0 (pw, pw_len, pw_len, ks_pw1); + r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, pw_len, pw_len, ks_pw1); if (r > 0) auth_status |= AC_PSO_CDS_AUTHORIZED; return r; @@ -122,29 +135,16 @@ verify_pso_cds (const uint8_t *pw, int pw_len) int verify_other (const uint8_t *pw, int pw_len) { - int r1, r2; - uint8_t keystring[KEYSTRING_MD_SIZE]; + const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); + int r; DEBUG_INFO ("verify_other\r\n"); + DEBUG_BYTE (pw_len); - if (gpg_pw_locked (PW_ERR_PW1)) - return 0; - - sha1 (pw, pw_len, keystring); - if ((r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring)) < 0 - || (r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, - keystring)) < 0) - { - gpg_pw_increment_err_counter (PW_ERR_PW1); - return -1; - } - else if (r1 == 0 && r2 == 0) - /* No key is available. Fail even if password can match. */ - return -1; - - gpg_pw_reset_err_counter (PW_ERR_PW1); - auth_status |= AC_OTHER_AUTHORIZED; - return 1; + r = verify_user_0 (AC_OTHER_AUTHORIZED, pw, pw_len, pw_len, ks_pw1); + if (r > 0) + auth_status |= AC_OTHER_AUTHORIZED; + return r; } /* @@ -230,7 +230,8 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known) if (ks_pw1 != NULL) { /* empty PW3, but PW1 exists */ - int r = verify_user_0 (pw, buf_len, pw_len_known, ks_pw1); + int r = verify_user_0 (AC_PSO_CDS_AUTHORIZED, + pw, buf_len, pw_len_known, ks_pw1); if (r > 0) admin_authorized = BY_USER; diff --git a/src/gnuk.h b/src/gnuk.h index 2df1def..3d8940f 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -86,8 +86,8 @@ extern void gpg_pw_increment_err_counter (uint8_t which); extern int ac_check_status (uint8_t ac_flag); extern int verify_pso_cds (const uint8_t *pw, int pw_len); extern int verify_other (const uint8_t *pw, int pw_len); -extern int verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known, - const uint8_t *ks_pw1); +extern int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, + int pw_len_known, const uint8_t *ks_pw1); extern int verify_admin (const uint8_t *pw, int pw_len); extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known); diff --git a/src/openpgp.c b/src/openpgp.c index 2ea4519..9eb7f94 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -243,7 +243,7 @@ cmd_change_password (void) { const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - pw_len = verify_user_0 (pw, len, -1, ks_pw1); + pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1); if (pw_len < 0) { From 696de23b521f696e77d912076d81491b564dd577 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 8 Dec 2011 11:00:26 +0900 Subject: [PATCH 023/300] usb mass storage class --- Virtual_COM_Port/usb_desc.h | 2 +- src/main.c | 7 + src/usb_conf.h | 9 +- src/usb_desc.c | 60 ++++- src/usb_msc.c | 491 ++++++++++++++++++++++++++++++++++++ src/usb_msc.h | 45 ++++ src/virtual_block_device.c | 271 ++++++++++++++++++++ 7 files changed, 876 insertions(+), 9 deletions(-) create mode 100644 src/usb_msc.c create mode 100644 src/usb_msc.h create mode 100644 src/virtual_block_device.c diff --git a/Virtual_COM_Port/usb_desc.h b/Virtual_COM_Port/usb_desc.h index df0476a..bc3cc57 100644 --- a/Virtual_COM_Port/usb_desc.h +++ b/Virtual_COM_Port/usb_desc.h @@ -28,7 +28,7 @@ #define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 #define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 -#define VIRTUAL_COM_PORT_DATA_SIZE 64 +#define VIRTUAL_COM_PORT_DATA_SIZE 16 #define VIRTUAL_COM_PORT_INT_SIZE 8 #define VIRTUAL_COM_PORT_SIZ_DEVICE_DESC 18 diff --git a/src/main.c b/src/main.c index 655aa59..edd62d7 100644 --- a/src/main.c +++ b/src/main.c @@ -439,6 +439,13 @@ main (int argc, char **argv) "Hello world\r\n\r\n", 35+21+15); } #endif + if (msc_recv_cbw () == 0) + { + int r = msc_handle_cbw (); + + if (r != 1) + msc_handle_err (r); + } } return 0; diff --git a/src/usb_conf.h b/src/usb_conf.h index 34a9b36..17d738d 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -28,9 +28,14 @@ /* EP3 */ #define ENDP3_TXADDR (0x140) /* EP4 */ -#define ENDP4_TXADDR (0x180) +#define ENDP4_TXADDR (0x150) /* EP5 */ -#define ENDP5_RXADDR (0x190) +#define ENDP5_RXADDR (0x160) + +/* EP6 */ +#define ENDP6_TXADDR (0x180) +/* EP7 */ +#define ENDP7_RXADDR (0x1c0) #define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM ) diff --git a/src/usb_desc.c b/src/usb_desc.c index 50ab1c3..00b0f17 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -29,14 +29,29 @@ static const uint8_t gnukDeviceDescriptor[] = { 0x01 /* bNumConfigurations */ }; +#define ICC_TOTAL_LENGTH (9+9+54+7+7) +#define ICC_NUM_INTERFACES 1 + #ifdef ENABLE_VIRTUAL_COM_PORT -#define W_TOTAL_LENGTH (9+9+54+7+7+9+5+5+4+5+7+9+7+7) -#define NUM_INTERFACES 3 /* two for CDC, one for GPG */ +#define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7) +#define VCOM_NUM_INTERFACES 2 #else -#define W_TOTAL_LENGTH (9+9+54+7+7) -#define NUM_INTERFACES 1 /* GPG only */ +#define VCOM_TOTAL_LENGTH 0 +#define VCOM_NUM_INTERFACES 0 #endif +#ifdef PINPAD_DND_SUPPORT +#define MSC_TOTAL_LENGTH (9+7+7) +#define MSC_NUM_INTERFACES 1 +#else +#define MSC_TOTAL_LENGTH 0 +#define MSC_NUM_INTERFACES 0 +#endif + +#define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH+VCOM_TOTAL_LENGTH+MSC_TOTAL_LENGTH) +#define NUM_INTERFACES (ICC_NUM_INTERFACES+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES) + + /* Configuation Descriptor */ static const uint8_t gnukConfigDescriptor[] = { 9, /* bLength: Configuation Descriptor size */ @@ -105,7 +120,7 @@ static const uint8_t gnukConfigDescriptor[] = { 0xff, /* bClassEnvelope: */ 0, 0, /* wLCDLayout: FIXED VALUE */ #if defined(PINPAD_SUPPORT) -#if defined(PINPAD_CIR_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT) 1, /* bPinSupport: with PIN pad (verify) */ #elif defined(PINPAD_DIAL_SUPPORT) 3, /* bPinSupport: with PIN pad (verify, modify) */ @@ -193,7 +208,40 @@ static const uint8_t gnukConfigDescriptor[] = { 0x83, /* bEndpointAddress: (IN3) */ 0x02, /* bmAttributes: Bulk */ VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */ - 0x00 /* bInterval */ + 0x00, /* bInterval */ +#endif +#ifdef PINPAD_DND_SUPPORT + /* Interface Descriptor.*/ + 9, /* bLength: Interface Descriptor size */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ +#ifdef ENABLE_VIRTUAL_COM_PORT + 0x03, /* bInterfaceNumber. */ +#else + 0x01, /* bInterfaceNumber. */ +#endif + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x08, /* bInterfaceClass (Mass Stprage). */ + 0x06, /* bInterfaceSubClass (SCSI + transparent command set, MSCO + chapter 2). */ + 0x50, /* bInterfaceProtocol (Bulk-Only + Mass Storage, MSCO chapter 3). */ + 0x00, /* iInterface. */ + /* Endpoint Descriptor.*/ + 7, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + 0x86, /* bEndpointAddress: (IN6) */ + 0x02, /* bmAttributes (Bulk). */ + 0x40, 0x00, /* wMaxPacketSize. */ + 0x00, /* bInterval (ignored for bulk). */ + /* Endpoint Descriptor.*/ + 7, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + 0x07, /* bEndpointAddress: (OUT7) */ + 0x02, /* bmAttributes (Bulk). */ + 0x40, 0x00, /* wMaxPacketSize. */ + 0x00, /* bInterval (ignored for bulk). */ #endif }; diff --git a/src/usb_msc.c b/src/usb_msc.c new file mode 100644 index 0000000..cd8cac7 --- /dev/null +++ b/src/usb_msc.c @@ -0,0 +1,491 @@ +#include "usb_lib.h" + +#include "config.h" +#include "ch.h" +#include "gnuk.h" +#include "usb_msc.h" + +struct usb_endp_in { + const uint8_t *txbuf; /* Pointer to the transmission buffer. */ + size_t txsize; /* Transmit transfer size remained. */ + size_t txcnt; /* Transmitted bytes so far. */ +}; + +struct usb_endp_out { + uint8_t *rxbuf; /* Pointer to the receive buffer. */ + size_t rxsize; /* Requested receive transfer size. */ + size_t rxcnt; /* Received bytes so far. */ +}; + +static struct usb_endp_in ep6_in; +static struct usb_endp_out ep7_out; + +static Thread *the_thread; + +#define ENDP_MAX_SIZE 64 + +static uint8_t msc_state; + + +static void usb_stall_transmit (void) +{ + SetEPTxStatus (ENDP6, EP_TX_STALL); +} + +static void usb_start_transmit (const uint8_t *p, size_t n) +{ + size_t pkt_len = n > ENDP_MAX_SIZE ? ENDP_MAX_SIZE : n; + + ep6_in.txbuf = p; + ep6_in.txsize = n; + ep6_in.txcnt = 0; + + USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, pkt_len); + SetEPTxValid (ENDP6); +} + +/* "Data Transmitted" callback */ +void EP6_IN_Callback (void) +{ + size_t n = (size_t)GetEPTxCount (ENDP6); + + ep6_in.txbuf += n; + ep6_in.txcnt += n; + ep6_in.txsize -= n; + + if (ep6_in.txsize > 0) /* More data to be sent */ + { + if (ep6_in.txsize > ENDP_MAX_SIZE) + n = ENDP_MAX_SIZE; + else + n = ep6_in.txsize; + USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, n); + SetEPTxValid (ENDP6); + return; + } + + /* Transmit has been completed, notify the waiting thread */ + switch (msc_state) + { + case MSC_SENDING_CSW: + case MSC_DATA_IN: + if (the_thread != NULL) { + Thread *tp; + chSysLockFromIsr (); + tp = the_thread; + the_thread = NULL; + tp->p_u.rdymsg = RDY_OK; + chSchReadyI (tp); + chSysUnlockFromIsr (); + } + break; + default: + break; + } +} + + +static void usb_stall_receive (void) +{ + SetEPRxStatus (ENDP7, EP_RX_STALL); +} + +static void usb_start_receive (uint8_t *p, size_t n) +{ + ep7_out.rxbuf = p; + ep7_out.rxsize = n; + ep7_out.rxcnt = 0; + SetEPRxValid (ENDP7); +} + +/* "Data Received" call back */ +void EP7_OUT_Callback (void) +{ + size_t n = (size_t)GetEPRxCount (ENDP7); + int err = 0; + + if (n > ep7_out.rxsize) + { /* buffer overflow */ + err = 1; + SetEPRxCount (ENDP7, ep7_out.rxsize); + } + + n = USB_SIL_Read (EP7_OUT, ep7_out.rxbuf); + ep7_out.rxbuf += n; + ep7_out.rxcnt += n; + ep7_out.rxsize -= n; + + if (n == ENDP_MAX_SIZE && ep7_out.rxsize != 0) + { /* More data to be received */ + SetEPRxValid (ENDP7); + return; + } + + /* Receiving has been completed, notify the waiting thread */ + switch (msc_state) + { + case MSC_IDLE: + case MSC_DATA_OUT: + if (the_thread != NULL) { + Thread *tp; + chSysLockFromIsr (); + tp = the_thread; + the_thread = NULL; + tp->p_u.rdymsg = err? RDY_OK : RDY_RESET; + chSchReadyI (tp); + chSysUnlockFromIsr (); + } + break; + default: + break; + } +} + +static const uint8_t lun_buf[4] = {0, 0, 0, 0}; /* One drives: 0 */ + +static const uint8_t scsi_inquiry_data_00[] = { 0, 0, 0, 0, 0 }; + +static const uint8_t scsi_inquiry_data[] = { + 0x00, /* Direct Access Device. */ + 0x80, /* RMB = 1: Removable Medium. */ + 0x05, /* Version: SPC-3. */ + 0x02, /* Response format: SPC-3. */ + 36 - 4, /* Additional Length. */ + 0x00, + 0x00, + 0x00, + /* Vendor Identification */ + 'F', 'S', 'I', 'J', ' ', ' ', ' ', ' ', + /* Product Identification */ + 'V', 'i', 'r', 't', 'u', 'a', 'l', ' ', + 'D', 'i', 's', 'k', ' ', ' ', ' ', ' ', + /* Product Revision Level */ + '1', '.', '0', ' ' +}; + +static uint8_t scsi_sense_data_desc[] = { + 0x72, /* Response Code: descriptor, current */ + 0x02, /* Sense Key */ + 0x3a, /* ASC (additional sense code) */ + 0x00, /* ASCQ (additional sense code qualifier) */ + 0x00, 0x00, 0x00, + 0x00, /* Additional Sense Length */ +}; + +static uint8_t scsi_sense_data_fixed[] = { + 0x70, /* Response Code: fixed, current */ + 0x00, + 0x02, /* Sense Key */ + 0x00, 0x00, 0x00, 0x00, + 0x0a, /* Additional Sense Length */ + 0x00, 0x00, 0x00, 0x00, + 0x3a, /* ASC (additional sense code) */ + 0x00, /* ASCQ (additional sense code qualifier) */ + 0x00, + 0x00, 0x00, 0x00, +}; + +static void set_scsi_sense_data(uint8_t sense_key, uint8_t asc) { + scsi_sense_data_desc[1] = scsi_sense_data_fixed[2] = sense_key; + scsi_sense_data_desc[2] = scsi_sense_data_fixed[12] = asc; +} + + +static uint8_t buf[512]; + +static uint8_t media_available; +static uint8_t media_changed; + +void msc_media_insert_change (int available) +{ + media_available = available; + media_changed = 1; + if (available) + set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */ + else + set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */ +} + + +static uint8_t scsi_read_format_capacities (uint32_t *nblocks, + uint32_t *secsize) +{ + *nblocks = 68; + *secsize = 512; + if (media_available) + return 2; /* Formatted Media.*/ + else + return 3; /* No Media.*/ +} + +static struct CBW CBW; + +static struct CSW CSW; + +int msc_recv_cbw (void) +{ + msg_t msg; + + chSysLock(); + msc_state = MSC_IDLE; + the_thread = chThdSelf (); + usb_start_receive ((uint8_t *)&CBW, sizeof CBW); + chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000)); + msg = chThdSelf ()->p_u.rdymsg; + chSysUnlock (); + if (msg == RDY_OK) + return 0; + else + return -1; +} + +static int msc_recv_data (void) +{ + msg_t msg; + + chSysLock (); + msc_state = MSC_DATA_OUT; + the_thread = chThdSelf (); + usb_start_receive (buf, 512); + chSchGoSleepS (THD_STATE_SUSPENDED); + msg = chThdSelf ()->p_u.rdymsg; + chSysUnlock (); + return 0; +} + +static void msc_send_data (const uint8_t *p, size_t n) +{ + msg_t msg; + + chSysLock (); + msc_state = MSC_DATA_IN; + the_thread = chThdSelf (); + usb_start_transmit (p, n); + chSchGoSleepS (THD_STATE_SUSPENDED); + msg = chThdSelf ()->p_u.rdymsg; + CSW.dCSWDataResidue -= (uint32_t)n; + chSysUnlock(); +} + +static void msc_send_result (const uint8_t *p, size_t n) +{ + msg_t msg; + + if (p != NULL) + { + if (n > CBW.dCBWDataTransferLength) + n = CBW.dCBWDataTransferLength; + + CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; + msc_send_data (p, n); + CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; + } + + chSysLock (); + msc_state = MSC_SENDING_CSW; + the_thread = chThdSelf (); + usb_start_transmit ((uint8_t *)&CSW, sizeof CSW); + chSchGoSleepS (THD_STATE_SUSPENDED); + msg = chThdSelf ()->p_u.rdymsg; + chSysUnlock (); +} + + +void msc_handle_err (int err) +{ + if (err == 0) + { + msc_state = MSC_ERROR; + chSysLock (); + usb_stall_receive (); + chSysUnlock (); + } + else + { + msc_state = MSC_ERROR; + chSysLock (); + usb_stall_transmit (); + usb_stall_receive (); + chSysUnlock (); + } +} + +int msc_handle_cbw (void) +{ + size_t n; + uint32_t nblocks, secsize; + uint8_t lun; + uint32_t lba; + + n = ep7_out.rxcnt; + + if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE)) + return 0; + + CSW.dCSWTag = CBW.dCBWTag; + switch (CBW.CBWCB[0]) { + case SCSI_REQUEST_SENSE: + if (CBW.CBWCB[1] & 0x01) /* DESC */ + msc_send_result ((uint8_t *)&scsi_sense_data_desc, + sizeof scsi_sense_data_desc); + else + msc_send_result ((uint8_t *)&scsi_sense_data_fixed, + sizeof scsi_sense_data_fixed); + if (media_changed && media_available) + { + media_changed = 0; + set_scsi_sense_data (0x00, 0x00); + } + return 1; + case SCSI_INQUIRY: + if (CBW.CBWCB[1] & 0x01) /* EVPD */ + /* assume page 00 */ + msc_send_result ((uint8_t *)&scsi_inquiry_data_00, + sizeof scsi_inquiry_data_00); + else + msc_send_result ((uint8_t *)&scsi_inquiry_data, + sizeof scsi_inquiry_data); + return 1; + case SCSI_READ_FORMAT_CAPACITIES: + buf[8] = scsi_read_format_capacities (&nblocks, &secsize); + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 8; + buf[4] = (uint8_t)(nblocks >> 24); + buf[5] = (uint8_t)(nblocks >> 16); + buf[6] = (uint8_t)(nblocks >> 8); + buf[7] = (uint8_t)(nblocks >> 0); + buf[9] = (uint8_t)(secsize >> 16); + buf[10] = (uint8_t)(secsize >> 8); + buf[11] = (uint8_t)(secsize >> 0); + msc_send_result (buf, 12); + return 1; + case SCSI_TEST_UNIT_READY: + if (media_available == 0 || media_changed) + { + CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + CSW.dCSWDataResidue = 0; + msc_send_result (NULL, 0); + return 1; + } + /* fall through */ + case SCSI_SYNCHRONIZE_CACHE: + case SCSI_VERIFY10: + case SCSI_START_STOP_UNIT: + case SCSI_ALLOW_MEDIUM_REMOVAL: + CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; + CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; + msc_send_result (NULL, 0); + return 1; + case SCSI_MODE_SENSE6: + buf[0] = 0x03; + buf[1] = buf[2] = buf[3] = 0; + msc_send_result (buf, 4); + return 1; + case SCSI_READ_CAPACITY10: + scsi_read_format_capacities (&nblocks, &secsize); + buf[0] = (uint8_t)((nblocks - 1) >> 24); + buf[1] = (uint8_t)((nblocks - 1) >> 16); + buf[2] = (uint8_t)((nblocks - 1) >> 8); + buf[3] = (uint8_t)((nblocks - 1) >> 0); + buf[4] = (uint8_t)(secsize >> 24); + buf[5] = (uint8_t)(secsize >> 16); + buf[6] = (uint8_t)(secsize >> 8); + buf[7] = (uint8_t)(secsize >> 0); + msc_send_result (buf, 8); + return 1; + case SCSI_READ10: + case SCSI_WRITE10: + break; + default: + if (CBW.dCBWDataTransferLength == 0) + { + CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + CSW.dCSWDataResidue = 0; + msc_send_result (NULL, 0); + return 1; + } + return -1; + } + + lun = CBW.bCBWLUN; + lba = (CBW.CBWCB[2] << 24) | (CBW.CBWCB[3] << 16) + | (CBW.CBWCB[4] << 8) | CBW.CBWCB[5]; + + /* Transfer direction.*/ + if (CBW.bmCBWFlags & 0x80) + { + /* IN, Device to Host.*/ + msc_state = MSC_DATA_IN; + if (CBW.CBWCB[0] == SCSI_READ10) + { + const uint8_t *p; + + CSW.dCSWDataResidue = 0; + while (1) + { + if (CBW.CBWCB[7] == 0 && CBW.CBWCB[8] == 0) + { + CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; + break; + } + + if ((p = msc_scsi_read (lun, lba))) + { + msc_send_data (p, 512); + if (++CBW.CBWCB[5] == 0) + if (++CBW.CBWCB[4] == 0) + if (++CBW.CBWCB[3] == 0) + ++CBW.CBWCB[2]; + if (CBW.CBWCB[8]-- == 0) + CBW.CBWCB[7]--; + CSW.dCSWDataResidue += 512; + } + else + { + CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + break; + } + } + + msc_send_result (NULL, 0); + } + } + else + { + /* OUT, Host to Device.*/ + if (CBW.CBWCB[0] == SCSI_WRITE10) + { + CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; + + while (1) + { + if (CBW.CBWCB[8] == 0 && CBW.CBWCB[7] == 0) + { + CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; + break; + } + + msc_recv_data (); + if (msc_scsi_write (lun, lba, buf, 512)) + { + if (++CBW.CBWCB[5] == 0) + if (++CBW.CBWCB[4] == 0) + if (++CBW.CBWCB[3] == 0) + ++CBW.CBWCB[2]; + if (CBW.CBWCB[8]-- == 0) + CBW.CBWCB[7]--; + CSW.dCSWDataResidue -= 512; + } + else + { + CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + break; + } + } + + msc_send_result (NULL, 0); + } + } + + return 1; +} diff --git a/src/usb_msc.h b/src/usb_msc.h new file mode 100644 index 0000000..3a117e0 --- /dev/null +++ b/src/usb_msc.h @@ -0,0 +1,45 @@ +#define MSC_CBW_SIGNATURE 0x43425355 +#define MSC_CSW_SIGNATURE 0x53425355 + +#define MSC_GET_MAX_LUN_COMMAND 0xFE +#define MSC_MASS_STORAGE_RESET_COMMAND 0xFF + +#define MSC_CSW_STATUS_PASSED 0 +#define MSC_CSW_STATUS_FAILED 1 + +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E +#define SCSI_READ10 0x28 +#define SCSI_READ_CAPACITY10 0x25 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_WRITE10 0x2A +#define SCSI_VERIFY10 0x2F +#define SCSI_READ_FORMAT_CAPACITIES 0x23 + +#define SCSI_SYNCHRONIZE_CACHE 0x35 + +#define MSC_IDLE 0 +#define MSC_DATA_OUT 1 +#define MSC_DATA_IN 2 +#define MSC_SENDING_CSW 3 +#define MSC_ERROR 4 + +struct CBW { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +} __attribute__((packed)); + +struct CSW { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +} __attribute__((packed)); diff --git a/src/virtual_block_device.c b/src/virtual_block_device.c new file mode 100644 index 0000000..51cadca --- /dev/null +++ b/src/virtual_block_device.c @@ -0,0 +1,271 @@ +#include + +#include "config.h" +#include "ch.h" +#include "board.h" + +extern Thread *main_thread; + +/* + +blk=0: master boot record sector +blk=1: fat0 +blk=2: fat1 +blk=3: root directory +blk=4: fat cluster #2 +... +blk=4+63: fat cluster #2+63 +*/ + +static const uint8_t d0_0_sector[512] = { + 0xeb, 0x3c, /* Jump instruction */ + 0x90, /* NOP */ + + 0x6d, 0x6b, 0x64, 0x6f, 0x73, 0x66, 0x73, 0x20, /* "mkdosfs " */ + + 0x00, 0x02, /* Bytes per sector: 512 */ + + 0x01, /* sectors per cluster: 1 */ + 0x01, 0x00, /* reserved sector count: 1 */ + 0x02, /* Number of FATs: 2 */ + 0x10, 0x00, /* Max. root directory entries: 16 (1 sector) */ + 0x44, 0x00, /* total sectors: 68 */ + 0xf8, /* media descriptor: fixed disk */ + 0x01, 0x00, /* sectors per FAT: 1 */ + 0x04, 0x00, /* sectors per track: 4 */ + 0x01, 0x00, /* number of heads: 1 */ + 0x00, 0x00, 0x00, 0x00, /* hidden sectors: 0 */ + 0x00, 0x00, 0x00, 0x00, /* total sectors (long) */ + 0x00, /* drive number */ + 0x00, /* reserved */ + 0x29, /* extended boot signature */ + 0xbf, 0x86, 0x75, 0xea, /* Volume ID (serial number) (Little endian) */ + + /* Volume label */ + 'G', 'O', 'N', 'E', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + + 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */ + + 0x0e, 0x1f, + 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, + 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, + 0x5e, 0xeb, 0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, + 0x19, + 0xeb, 0xfe, /* loop: jmp loop */ + + /* "Thisis not a bootable disk... \r\n" */ + 0x54, 0x68, 0x69, 0x73, 0x20, + 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, + 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2e, 0x20, + 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, + 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, + 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, + 0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, + 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa +}; + +static const uint8_t d0_fat0_sector[512] = { + 0xf8, 0xff, 0xff, /* Media descriptor: fixed disk */ /* EOC */ + 0xff, 0xff, 0xff, /* cluster 2: used */ /* cluster 3: used */ + 0xff, 0xff, 0xff, /* cluster 4: used */ /* cluster 5: used */ + 0xff, 0xff, 0xff, /* cluster 6: used */ /* cluster 7: used */ + 0xff, 0x0f, 0x00, /* cluster 8: used */ /* cluster 9: free */ + 0x00, +}; + +static const uint8_t zero_sector[512] = { + 0x00, +}; + +static uint8_t the_sector[512]; + +struct folder { + uint8_t parent; + uint8_t children[7]; +}; + +static struct folder folders[8] = { { 0, { 1, 2, 3, 4, 5, 6, 7 } }, }; +#define FOLDER_INDEX_TO_CLUSTER_NO(i) (i+1) +#define CLUSTER_NO_TO_FOLDER_INDEX(n) (n-1) +#define FOLDER_INDEX_TO_LBA(i) (i+3) +#define LBA_TO_FOLDER_INDEX(lba) (lba-3) +#define FOLDER_INDEX_TO_DIRCHAR(i) ('A'+i-1) +#define DIRCHAR_TO_FOLDER_INDEX(c) (c - 'A' + 1) + +static uint8_t *fill_file_entry (uint8_t *p, const uint8_t *filename, + uint16_t cluster_no) +{ + memcpy (p, filename, 8+3); + p += 11; + *p++ = 0x10; /* directory */ + *p++ = 0x00; /* reserved */ + memcpy (p, "\x64\x3b\xa7\x61\x3f", 5); /* create time */ + p += 5; + memcpy (p, "\x61\x3f", 2); /* last access */ + p += 2; + *p++ = 0x00; *p++ = 0x00; /* ea-index */ + memcpy (p, "\x3b\xa7\x61\x3f", 4); /* last modified */ + p += 4; + memcpy (p, &cluster_no, 2); /* cluster # */ + p += 2; + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; /* file size */ + return p; +} + +static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index) +{ + uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index); + int i; + uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20 }; + uint8_t child; + uint8_t *p_orig = p; + + memset (p, 0, 512); + + if (index != 0) + { + p = fill_file_entry (p, filename, cluster_no); + filename[1] = 0x2e; + p = fill_file_entry (p, filename, 0); + filename[1] = 0x20; + } + + for (i = 0; i < 7; i++) + if ((child = folders[index].children[i]) != 0) + { + filename[0] = FOLDER_INDEX_TO_DIRCHAR (child); + p = fill_file_entry (p, filename, FOLDER_INDEX_TO_CLUSTER_NO (child)); + } + else + break; + + return p_orig; +} + +const uint8_t * +msc_scsi_read (uint8_t lun, uint32_t lba) +{ + switch (lba) + { + case 0: + return d0_0_sector; + case 1: + case 2: + return d0_fat0_sector; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + return build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba)); + default: + return zero_sector; + } +} + +uint8_t datetime_string[29]; +static uint8_t *dts = datetime_string; + +static void parse_directory_sector (const uint8_t *p, uint8_t index) +{ + uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index); + int i; + uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20 }; + uint8_t child; + uint8_t *p_orig = p; + + if (index != 0) + { + uint16_t cluster_no; + uint8_t dest_index; + + p += 32; /* skip "." */ + + /* ".." */ + cluster_no = p[26] | (p[27] << 8); + dest_index = CLUSTER_NO_TO_FOLDER_INDEX (cluster_no); + + if (dest_index >= 1 && dest_index <= 7) + dts += sprintf (dts, "%c%c ", FOLDER_INDEX_TO_DIRCHAR (index), + FOLDER_INDEX_TO_DIRCHAR (dest_index)); + else + ; /* can be 255 : root_dir */ + + p += 32; + } + + for (i = 0; i < 7; i++) + if (*p) + { + child = DIRCHAR_TO_FOLDER_INDEX (*p); + folders[index].children[i] = child; + p += 32; + } + else + break; +} + +int +msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size) +{ + if (lba <= 2) + return 1; /* error */ + else + { + uint8_t index = LBA_TO_FOLDER_INDEX (lba); + + parse_directory_sector (buf, index); + } + + return 1; +} From 231c50d9b5c3856296078912774ff7968cb16b75 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 9 Dec 2011 15:05:34 +0900 Subject: [PATCH 024/300] cleanup --- src/usb_msc.c | 129 ++++++++++++++++++++----------------- src/usb_msc.h | 7 ++ src/virtual_block_device.c | 126 ++++++++++++++++-------------------- 3 files changed, 134 insertions(+), 128 deletions(-) diff --git a/src/usb_msc.c b/src/usb_msc.c index cd8cac7..4665484 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -193,17 +193,22 @@ static void set_scsi_sense_data(uint8_t sense_key, uint8_t asc) { static uint8_t buf[512]; -static uint8_t media_available; -static uint8_t media_changed; +static uint8_t contingent_allegiance; +static uint8_t keep_contingent_allegiance; + +uint8_t media_available; void msc_media_insert_change (int available) { + contingent_allegiance = 1; media_available = available; - media_changed = 1; if (available) set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */ else - set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */ + { + set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */ + keep_contingent_allegiance = 1; + } } @@ -222,22 +227,6 @@ static struct CBW CBW; static struct CSW CSW; -int msc_recv_cbw (void) -{ - msg_t msg; - - chSysLock(); - msc_state = MSC_IDLE; - the_thread = chThdSelf (); - usb_start_receive ((uint8_t *)&CBW, sizeof CBW); - chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000)); - msg = chThdSelf ()->p_u.rdymsg; - chSysUnlock (); - if (msg == RDY_OK) - return 0; - else - return -1; -} static int msc_recv_data (void) { @@ -291,36 +280,42 @@ static void msc_send_result (const uint8_t *p, size_t n) } -void msc_handle_err (int err) -{ - if (err == 0) - { - msc_state = MSC_ERROR; - chSysLock (); - usb_stall_receive (); - chSysUnlock (); - } - else - { - msc_state = MSC_ERROR; - chSysLock (); - usb_stall_transmit (); - usb_stall_receive (); - chSysUnlock (); - } -} - -int msc_handle_cbw (void) +void msc_handle_command (void) { size_t n; uint32_t nblocks, secsize; - uint8_t lun; uint32_t lba; + int r; + msg_t msg; + + chSysLock(); + msc_state = MSC_IDLE; + the_thread = chThdSelf (); + usb_start_receive ((uint8_t *)&CBW, sizeof CBW); + chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000)); + msg = chThdSelf ()->p_u.rdymsg; + chSysUnlock (); + + if (msg != RDY_OK) + { + /* Error occured, ignore the request and go into error state */ + msc_state = MSC_ERROR; + chSysLock (); + usb_stall_receive (); + chSysUnlock (); + return; + } n = ep7_out.rxcnt; if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE)) - return 0; + { + msc_state = MSC_ERROR; + chSysLock (); + usb_stall_receive (); + chSysUnlock (); + return; + } CSW.dCSWTag = CBW.dCBWTag; switch (CBW.CBWCB[0]) { @@ -331,12 +326,13 @@ int msc_handle_cbw (void) else msc_send_result ((uint8_t *)&scsi_sense_data_fixed, sizeof scsi_sense_data_fixed); - if (media_changed && media_available) + /* After the error is reported, clear it, if it's . */ + if (!keep_contingent_allegiance) { - media_changed = 0; + contingent_allegiance = 0; set_scsi_sense_data (0x00, 0x00); } - return 1; + return; case SCSI_INQUIRY: if (CBW.CBWCB[1] & 0x01) /* EVPD */ /* assume page 00 */ @@ -345,7 +341,7 @@ int msc_handle_cbw (void) else msc_send_result ((uint8_t *)&scsi_inquiry_data, sizeof scsi_inquiry_data); - return 1; + return; case SCSI_READ_FORMAT_CAPACITIES: buf[8] = scsi_read_format_capacities (&nblocks, &secsize); buf[0] = buf[1] = buf[2] = 0; @@ -358,14 +354,14 @@ int msc_handle_cbw (void) buf[10] = (uint8_t)(secsize >> 8); buf[11] = (uint8_t)(secsize >> 0); msc_send_result (buf, 12); - return 1; + return; case SCSI_TEST_UNIT_READY: - if (media_available == 0 || media_changed) + if (contingent_allegiance) { CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.dCSWDataResidue = 0; msc_send_result (NULL, 0); - return 1; + return; } /* fall through */ case SCSI_SYNCHRONIZE_CACHE: @@ -375,12 +371,12 @@ int msc_handle_cbw (void) CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; msc_send_result (NULL, 0); - return 1; + return; case SCSI_MODE_SENSE6: buf[0] = 0x03; buf[1] = buf[2] = buf[3] = 0; msc_send_result (buf, 4); - return 1; + return; case SCSI_READ_CAPACITY10: scsi_read_format_capacities (&nblocks, &secsize); buf[0] = (uint8_t)((nblocks - 1) >> 24); @@ -392,7 +388,7 @@ int msc_handle_cbw (void) buf[6] = (uint8_t)(secsize >> 8); buf[7] = (uint8_t)(secsize >> 0); msc_send_result (buf, 8); - return 1; + return; case SCSI_READ10: case SCSI_WRITE10: break; @@ -402,12 +398,19 @@ int msc_handle_cbw (void) CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; CSW.dCSWDataResidue = 0; msc_send_result (NULL, 0); - return 1; + return; + } + else + { + msc_state = MSC_ERROR; + chSysLock (); + usb_stall_transmit (); + usb_stall_receive (); + chSysUnlock (); + return; } - return -1; } - lun = CBW.bCBWLUN; lba = (CBW.CBWCB[2] << 24) | (CBW.CBWCB[3] << 16) | (CBW.CBWCB[4] << 8) | CBW.CBWCB[5]; @@ -429,7 +432,7 @@ int msc_handle_cbw (void) break; } - if ((p = msc_scsi_read (lun, lba))) + if ((r = msc_scsi_read (lba, &p)) == 0) { msc_send_data (p, 512); if (++CBW.CBWCB[5] == 0) @@ -443,6 +446,11 @@ int msc_handle_cbw (void) else { CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + contingent_allegiance = 1; + if (r == SCSI_ERROR_NOT_READY) + set_scsi_sense_data (SCSI_ERROR_NOT_READY, 0x3a); + else + set_scsi_sense_data (r, 0x00); break; } } @@ -466,7 +474,7 @@ int msc_handle_cbw (void) } msc_recv_data (); - if (msc_scsi_write (lun, lba, buf, 512)) + if ((r = msc_scsi_write (lba, buf, 512)) == 0) { if (++CBW.CBWCB[5] == 0) if (++CBW.CBWCB[4] == 0) @@ -479,6 +487,11 @@ int msc_handle_cbw (void) else { CSW.bCSWStatus = MSC_CSW_STATUS_FAILED; + contingent_allegiance = 1; + if (r == SCSI_ERROR_NOT_READY) + set_scsi_sense_data (SCSI_ERROR_NOT_READY, 0x3a); + else + set_scsi_sense_data (r, 0x00); break; } } @@ -486,6 +499,4 @@ int msc_handle_cbw (void) msc_send_result (NULL, 0); } } - - return 1; } diff --git a/src/usb_msc.h b/src/usb_msc.h index 3a117e0..567e4dc 100644 --- a/src/usb_msc.h +++ b/src/usb_msc.h @@ -43,3 +43,10 @@ struct CSW { uint32_t dCSWDataResidue; uint8_t bCSWStatus; } __attribute__((packed)); + +#define SCSI_ERROR_NOT_READY 2 +#define SCSI_ERROR_ILLEAGAL_REQUEST 5 +#define SCSI_ERROR_UNIT_ATTENTION 6 +#define SCSI_ERROR_DATA_PROTECT 7 + +extern uint8_t media_available; diff --git a/src/virtual_block_device.c b/src/virtual_block_device.c index 51cadca..27e0b8c 100644 --- a/src/virtual_block_device.c +++ b/src/virtual_block_device.c @@ -6,6 +6,8 @@ extern Thread *main_thread; +#define TOTAL_SECTOR 68 + /* blk=0: master boot record sector @@ -17,7 +19,7 @@ blk=4: fat cluster #2 blk=4+63: fat cluster #2+63 */ -static const uint8_t d0_0_sector[512] = { +static const uint8_t d0_0_sector[] = { 0xeb, 0x3c, /* Jump instruction */ 0x90, /* NOP */ @@ -29,7 +31,7 @@ static const uint8_t d0_0_sector[512] = { 0x01, 0x00, /* reserved sector count: 1 */ 0x02, /* Number of FATs: 2 */ 0x10, 0x00, /* Max. root directory entries: 16 (1 sector) */ - 0x44, 0x00, /* total sectors: 68 */ + TOTAL_SECTOR, 0x00, /* total sectors: 68 */ 0xf8, /* media descriptor: fixed disk */ 0x01, 0x00, /* sectors per FAT: 1 */ 0x04, 0x00, /* sectors per track: 4 */ @@ -46,14 +48,24 @@ static const uint8_t d0_0_sector[512] = { 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */ - 0x0e, 0x1f, - 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b, - 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, - 0x5e, 0xeb, 0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, - 0x19, - 0xeb, 0xfe, /* loop: jmp loop */ + 0x0e, /* push cs */ + 0x1f, /* pop ds */ + 0xbe, 0x5b, 0x7c, /* mov si, offset message_txt */ + 0xac, /* 1: lodsb */ + 0x22, 0xc0, /* and al, al */ + 0x74, 0x0b, /* jz 2f */ + 0x56, /* push si */ + 0xb4, 0x0e, /* mov ah, 0eh */ + 0xbb, 0x07, 0x00, /* mov bx, 0007h */ + 0xcd, 0x10, /* int 10h ; output char color=white */ + 0x5e, /* pop si */ + 0xeb, 0xf0, /* jmp 1b */ + 0x32, 0xe4, /* 2: xor ah, ah */ + 0xcd, 0x16, /* int 16h; key input */ + 0xcd, 0x19, /* int 19h; load OS */ + 0xeb, 0xfe, /* 3: jmp 3b */ - /* "Thisis not a bootable disk... \r\n" */ + /* "This is not a bootable disk... \r\n" */ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, @@ -67,61 +79,16 @@ static const uint8_t d0_0_sector[512] = { 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa }; -static const uint8_t d0_fat0_sector[512] = { +static const uint8_t d0_fat0_sector[] = { 0xf8, 0xff, 0xff, /* Media descriptor: fixed disk */ /* EOC */ 0xff, 0xff, 0xff, /* cluster 2: used */ /* cluster 3: used */ 0xff, 0xff, 0xff, /* cluster 4: used */ /* cluster 5: used */ 0xff, 0xff, 0xff, /* cluster 6: used */ /* cluster 7: used */ 0xff, 0x0f, 0x00, /* cluster 8: used */ /* cluster 9: free */ - 0x00, }; -static const uint8_t zero_sector[512] = { - 0x00, -}; - static uint8_t the_sector[512]; struct folder { @@ -157,14 +124,13 @@ static uint8_t *fill_file_entry (uint8_t *p, const uint8_t *filename, return p; } -static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index) +static void build_directory_sector (uint8_t *p, uint8_t index) { uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index); int i; uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; uint8_t child; - uint8_t *p_orig = p; memset (p, 0, 512); @@ -184,20 +150,33 @@ static const uint8_t *build_directory_sector (uint8_t *p, uint8_t index) } else break; - - return p_orig; } -const uint8_t * -msc_scsi_read (uint8_t lun, uint32_t lba) +int +msc_scsi_read (uint32_t lba, const uint8_t **sector_p) { + if (!media_available) + return SCSI_ERROR_NOT_READY; + + if (lba >= TOTAL_SECTOR) + return SCSI_ERROR_ILLEAGAL_REQUEST; + switch (lba) { case 0: - return d0_0_sector; + *sector_p = the_sector; + memcpy (the_sector, d0_0_sector, sizeof d0_0_sector); + memset (the_sector + sizeof d0_0_sector, 0, 512 - sizeof d0_0_sector); + the_sector[510] = 0x55; + the_sector[511] = 0xaa; + return 0; case 1: case 2: - return d0_fat0_sector; + *sector_p = the_sector; + memcpy (the_sector, d0_fat0_sector, sizeof d0_fat0_sector); + memset (the_sector + sizeof d0_fat0_sector, 0, + 512 - sizeof d0_fat0_sector); + return 0; case 3: case 4: case 5: @@ -206,9 +185,13 @@ msc_scsi_read (uint8_t lun, uint32_t lba) case 8: case 9: case 10: - return build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba)); + *sector_p = the_sector; + build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba)); + return 0; default: - return zero_sector; + *sector_p = the_sector; + memset (the_sector, 0, 512); + return 0; } } @@ -258,14 +241,19 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) int msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size) { - if (lba <= 2) - return 1; /* error */ + if (!media_available) + return SCSI_ERROR_NOT_READY; + + if (lba >= TOTAL_SECTOR) + return SCSI_ERROR_ILLEAGAL_REQUEST; + + if (lba <= 2 || lba >= 11) + return SCSI_ERROR_DATA_PROTECT; else { uint8_t index = LBA_TO_FOLDER_INDEX (lba); parse_directory_sector (buf, index); + return 0; } - - return 1; } From ec409fe8a410d447bc62ec5f7e7a9362d4858916 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 9 Dec 2011 15:06:43 +0900 Subject: [PATCH 025/300] rename --- src/{virtual_block_device.c => pin-dnd.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{virtual_block_device.c => pin-dnd.c} (100%) diff --git a/src/virtual_block_device.c b/src/pin-dnd.c similarity index 100% rename from src/virtual_block_device.c rename to src/pin-dnd.c From f58233aa5dbe51e9fb1a5303e2cd3924043761e7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 9 Dec 2011 17:53:45 +0900 Subject: [PATCH 026/300] more --- src/Makefile.in | 4 ++ src/configure | 10 ++--- src/main.c | 7 ---- src/pin-dnd.c | 103 ++++++++++++++++++++++++++++++++++++++++-------- src/usb_msc.c | 22 ++++++++++- src/usb_prop.c | 82 ++++++++++++++++++++++++++++++-------- 6 files changed, 181 insertions(+), 47 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 929654e..e6d5271 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -101,6 +101,10 @@ ifneq ($(ENABLE_PINPAD),) CSRC += pin-$(ENABLE_PINPAD).c endif +ifeq ($(ENABLE_PINPAD),dnd) +CSRC += usb_msc.c +endif + # List ASM source files here ASMSRC = $(PORTASM) \ $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s diff --git a/src/configure b/src/configure index dea3fa4..8b7cd8a 100755 --- a/src/configure +++ b/src/configure @@ -86,8 +86,8 @@ Configuration: STM8S_DISCOVERY STBEE --enable-debug debug with virtual COM port [no] - --enable-pinpad={cir,dial} - PIN input device support [no] + --enable-pinpad={dnd,cir,dial} + PIN entry support [no] --with-dfu build image for DFU [] EOF exit 0 @@ -159,10 +159,10 @@ if test "$pinpad" = "no"; then PINPAD_MORE_DEFINE="" echo "PIN pad option disabled" elif test "$pinpad" = "yes"; then - PINPAD_MAKE_OPTION="ENABLE_PINPAD=cir" + PINPAD_MAKE_OPTION="ENABLE_PINPAD=dnd" PINPAD_DEFINE="#define PINPAD_SUPPORT 1" - PINPAD_MORE_DEFINE="#define PINPAD_CIR_SUPPORT 1" - echo "PIN pad option enabled (cir)" + PINPAD_MORE_DEFINE="#define PINPAD_DND_SUPPORT 1" + echo "PIN pad option enabled (dnd)" else PINPAD_MAKE_OPTION="ENABLE_PINPAD=$pinpad" PINPAD_DEFINE="#define PINPAD_SUPPORT 1" diff --git a/src/main.c b/src/main.c index edd62d7..655aa59 100644 --- a/src/main.c +++ b/src/main.c @@ -439,13 +439,6 @@ main (int argc, char **argv) "Hello world\r\n\r\n", 35+21+15); } #endif - if (msc_recv_cbw () == 0) - { - int r = msc_handle_cbw (); - - if (r != 1) - msc_handle_err (r); - } } return 0; diff --git a/src/pin-dnd.c b/src/pin-dnd.c index 27e0b8c..b3b1c76 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -1,10 +1,65 @@ -#include - #include "config.h" #include "ch.h" #include "board.h" +#include "gnuk.h" +#include "usb_msc.h" -extern Thread *main_thread; +uint8_t pin_input_buffer[MAX_PIN_CHARS]; +uint8_t pin_input_len; + +static Thread *pin_thread; + +/* + * 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) +{ + msg_t msg; + + (void)msg_code; + + + DEBUG_INFO (">>>\r\n"); + + pin_input_len = 0; + + while (1) + { + chSysLock (); + msc_media_insert_change (1); + pin_thread = chThdSelf (); + chSchGoSleepS (THD_STATE_SUSPENDED); + msg = chThdSelf ()->p_u.rdymsg; + chSysUnlock (); + + led_blink (0); + if (msg == 1) + break; + } + + msc_media_insert_change (0); + + return pin_input_len; +} + +static void pinpad_input (void) +{ + chSysLock (); + pin_thread->p_u.rdymsg = 0; + chSchReadyI (pin_thread); + chSysUnlock (); +} + +static void pinpad_finish_entry (void) +{ + chSysLock (); + pin_thread->p_u.rdymsg = 1; + chSchReadyI (pin_thread); + chSysUnlock (); +} #define TOTAL_SECTOR 68 @@ -195,8 +250,6 @@ msc_scsi_read (uint32_t lba, const uint8_t **sector_p) } } -uint8_t datetime_string[29]; -static uint8_t *dts = datetime_string; static void parse_directory_sector (const uint8_t *p, uint8_t index) { @@ -206,6 +259,8 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) 0x20, 0x20, 0x20 }; uint8_t child; uint8_t *p_orig = p; + int input = 0; + int num_children = 0; if (index != 0) { @@ -218,24 +273,38 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) cluster_no = p[26] | (p[27] << 8); dest_index = CLUSTER_NO_TO_FOLDER_INDEX (cluster_no); - if (dest_index >= 1 && dest_index <= 7) - dts += sprintf (dts, "%c%c ", FOLDER_INDEX_TO_DIRCHAR (index), - FOLDER_INDEX_TO_DIRCHAR (dest_index)); + if (dest_index < 1 || dest_index > 7) + ; /* it can be 255 : root_dir */ else - ; /* can be 255 : root_dir */ + if (pin_input_len < MAX_PIN_CHARS - 2) + { + pin_input_buffer[pin_input_len++] + = FOLDER_INDEX_TO_DIRCHAR (index); + pin_input_buffer[pin_input_len++] + = FOLDER_INDEX_TO_DIRCHAR (dest_index); + input = 1; + } p += 32; } for (i = 0; i < 7; i++) - if (*p) - { - child = DIRCHAR_TO_FOLDER_INDEX (*p); - folders[index].children[i] = child; - p += 32; - } - else - break; + { + if (*p) + { + child = DIRCHAR_TO_FOLDER_INDEX (*p); + folders[index].children[i] = child; + num_children++; + } + else + folders[index].children[i] = 0; + p += 32; + } + + if (index == 0 && num_children == 1) + pinpad_finish_entry (); + else if (input) + pinpad_input (); } int diff --git a/src/usb_msc.c b/src/usb_msc.c index 4665484..86c66e6 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -141,8 +141,6 @@ void EP7_OUT_Callback (void) } } -static const uint8_t lun_buf[4] = {0, 0, 0, 0}; /* One drives: 0 */ - static const uint8_t scsi_inquiry_data_00[] = { 0, 0, 0, 0, 0 }; static const uint8_t scsi_inquiry_data[] = { @@ -280,6 +278,7 @@ static void msc_send_result (const uint8_t *p, size_t n) } + void msc_handle_command (void) { size_t n; @@ -500,3 +499,22 @@ void msc_handle_command (void) } } } + +static msg_t +msc_main (void *arg) +{ + (void)arg; + + while (1) + msc_handle_command (); + + return 0; +} + +static WORKING_AREA(wa_msc_thread, 128); + +void msc_init (void) +{ + chThdCreateStatic (wa_msc_thread, sizeof (wa_msc_thread), + NORMALPRIO, msc_main, NULL); +} diff --git a/src/usb_prop.c b/src/usb_prop.c index f9b06ef..8416681 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -36,6 +36,10 @@ #include "usb-cdc-vport.c" #endif +#ifdef PINPAD_DND_SUPPORT +#include "usb_msc.h" +#endif + static void gnuk_device_init (void) @@ -247,11 +251,24 @@ gnuk_data_rates (uint16_t len) return (uint8_t *)data_rate_table; } +static const uint8_t lun_table[] = { 0, 0, 0, 0, }; +static uint8_t * +msc_lun_info (uint16_t len) +{ + if (len == 0) + { + pInformation->Ctrl_Info.Usb_wLength = sizeof (lun_table); + return NULL; + } + + return (uint8_t *)lun_table; +} + static RESULT gnuk_setup_with_data (uint8_t RequestNo) { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - if (pInformation->USBwIndex0 == 0) /* Interface */ + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + if (pInformation->USBwIndex0 == 0) { if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) { @@ -270,23 +287,41 @@ gnuk_setup_with_data (uint8_t RequestNo) else return USB_UNSUPPORT; } - else +#if defined(PINPAD_DND_SUPPORT) +# if defined(ENABLE_VIRTUAL_COM_PORT) + else if (pInformation->USBwIndex0 == 2) + return Virtual_Com_Port_Data_Setup (RequestNo); + else if (pInformation->USBwIndex0 == 3) +# else + else if (pInformation->USBwIndex0 == 1) +# endif { -#if defined(ENABLE_VIRTUAL_COM_PORT) - return Virtual_Com_Port_Data_Setup (RequestNo); -#else - return USB_UNSUPPORT; -#endif + if (RequestNo == MSC_GET_MAX_LUN_COMMAND) + { + pInformation->Ctrl_Info.CopyData = msc_lun_info; + pInformation->Ctrl_Info.Usb_wOffset = 0; + msc_lun_info (0); + return USB_SUCCESS; + } + else + return USB_UNSUPPORT; } +#elif defined(ENABLE_VIRTUAL_COM_PORT) + else if (pInformation->USBwIndex0 == 2) + return Virtual_Com_Port_Data_Setup (RequestNo); +#endif + else + return USB_UNSUPPORT; else return USB_UNSUPPORT; } + static RESULT gnuk_setup_with_nodata (uint8_t RequestNo) { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - if (pInformation->USBwIndex0 == 0) /* Interface */ + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + if (pInformation->USBwIndex0 == 0) { if (RequestNo == USB_CCID_REQ_ABORT) /* wValue: bSeq, bSlot */ @@ -295,14 +330,29 @@ gnuk_setup_with_nodata (uint8_t RequestNo) else return USB_UNSUPPORT; } - else +#if defined(PINPAD_DND_SUPPORT) +# if defined(ENABLE_VIRTUAL_COM_PORT) + else if (pInformation->USBwIndex0 == 2) + return Virtual_Com_Port_NoData_Setup (RequestNo); + else if (pInformation->USBwIndex0 == 3) +# else + else if (pInformation->USBwIndex0 == 1) +# endif { -#if defined(ENABLE_VIRTUAL_COM_PORT) - return Virtual_Com_Port_NoData_Setup (RequestNo); -#else - return USB_UNSUPPORT; -#endif + if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND) + { + /* Should call resetting MSC thread, something like msc_reset() */ + return USB_SUCCESS; + } + else + return USB_UNSUPPORT; } +#elif defined(ENABLE_VIRTUAL_COM_PORT) + else if (pInformation->USBwIndex0 == 2) + return Virtual_Com_Port_NoData_Setup (RequestNo); +#endif + else + return USB_UNSUPPORT; else return USB_UNSUPPORT; } From 5a9194d136233d8ac2c937d09a33e5440ecdb5eb Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 12 Dec 2011 18:12:43 +0900 Subject: [PATCH 027/300] working now --- src/gnuk.h | 8 +++++--- src/main.c | 5 +++++ src/pin-dnd.c | 14 +++++++------- src/usb_conf.h | 10 +++++++--- src/usb_msc.c | 15 +++++++++++---- src/usb_prop.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/gnuk.h b/src/gnuk.h index 3d8940f..b4a6b8d 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -350,13 +350,15 @@ extern Thread *main_thread; extern void led_blink (int spec); #if defined(PINPAD_SUPPORT) -#if defined(PINPAD_CIR_SUPPORT) +# if defined(PINPAD_CIR_SUPPORT) extern void cir_ext_disable (void); extern void cir_ext_enable (void); -#elif defined(PINPAD_DIAL_SUPPORT) +# elif defined(PINPAD_DIAL_SUPPORT) extern void dial_sw_disable (void); extern void dial_sw_enable (void); -#endif +# elif defined(PINPAD_DND_SUPPORT) +extern void msc_init (void); +# endif #define PIN_INPUT_CURRENT 1 #define PIN_INPUT_NEW 2 #define PIN_INPUT_CONFIRM 3 diff --git a/src/main.c b/src/main.c index 655aa59..eae07e8 100644 --- a/src/main.c +++ b/src/main.c @@ -386,12 +386,17 @@ main (int argc, char **argv) chThdCreateStatic (waUSBthread, sizeof(waUSBthread), NORMALPRIO, USBthread, NULL); +#ifdef PINPAD_DND_SUPPORT + msc_init (); +#endif + while (1) { eventmask_t m; count++; m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL); +continue; switch (m) { case LED_STATUS_MODE: diff --git a/src/pin-dnd.c b/src/pin-dnd.c index b3b1c76..ea3f063 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -26,10 +26,11 @@ pinpad_getline (int msg_code, systime_t timeout) pin_input_len = 0; + msc_media_insert_change (1); + while (1) { chSysLock (); - msc_media_insert_change (1); pin_thread = chThdSelf (); chSchGoSleepS (THD_STATE_SUSPENDED); msg = chThdSelf ()->p_u.rdymsg; @@ -253,12 +254,8 @@ msc_scsi_read (uint32_t lba, const uint8_t **sector_p) static void parse_directory_sector (const uint8_t *p, uint8_t index) { - uint16_t cluster_no = FOLDER_INDEX_TO_CLUSTER_NO (index); int i; - uint8_t filename[11] = { 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20 }; uint8_t child; - uint8_t *p_orig = p; int input = 0; int num_children = 0; @@ -290,7 +287,7 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) for (i = 0; i < 7; i++) { - if (*p) + if (*p >= 'A' && *p <= 'G') { child = DIRCHAR_TO_FOLDER_INDEX (*p); folders[index].children[i] = child; @@ -308,7 +305,7 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) } int -msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size) +msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size) { if (!media_available) return SCSI_ERROR_NOT_READY; @@ -316,6 +313,9 @@ msc_scsi_write (uint8_t lun, uint32_t lba, const uint8_t *buf, size_t size) if (lba >= TOTAL_SECTOR) return SCSI_ERROR_ILLEAGAL_REQUEST; + if (lba == 1) + return 0; /* ??? */ + if (lba <= 2 || lba >= 11) return SCSI_ERROR_DATA_PROTECT; else diff --git a/src/usb_conf.h b/src/usb_conf.h index 17d738d..4416def 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -8,10 +8,14 @@ #ifndef __USB_CONF_H #define __USB_CONF_H -#ifdef ENABLE_VIRTUAL_COM_PORT -#define EP_NUM (6) +#ifdef PINPAD_DND_SUPPORT +# define EP_NUM (8) #else -#define EP_NUM (3) +# ifdef ENABLE_VIRTUAL_COM_PORT +# define EP_NUM (6) +# else +# define EP_NUM (3) +# endif #endif #define BTABLE_ADDRESS (0x00) diff --git a/src/usb_msc.c b/src/usb_msc.c index 86c66e6..40efb35 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -95,6 +95,10 @@ static void usb_start_receive (uint8_t *p, size_t n) ep7_out.rxbuf = p; ep7_out.rxsize = n; ep7_out.rxcnt = 0; + if (n < ENDP_MAX_SIZE) + SetEPRxCount (ENDP7, n); + else + SetEPRxCount (ENDP7, ENDP_MAX_SIZE); SetEPRxValid (ENDP7); } @@ -131,7 +135,7 @@ void EP7_OUT_Callback (void) chSysLockFromIsr (); tp = the_thread; the_thread = NULL; - tp->p_u.rdymsg = err? RDY_OK : RDY_RESET; + tp->p_u.rdymsg = err? RDY_RESET : RDY_OK; chSchReadyI (tp); chSysUnlockFromIsr (); } @@ -299,9 +303,12 @@ void msc_handle_command (void) { /* Error occured, ignore the request and go into error state */ msc_state = MSC_ERROR; - chSysLock (); - usb_stall_receive (); - chSysUnlock (); + if (msg != RDY_TIMEOUT) + { + chSysLock (); + usb_stall_receive (); + chSysUnlock (); + } return; } diff --git a/src/usb_prop.c b/src/usb_prop.c index 8416681..ebde6d0 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -112,6 +112,20 @@ gnuk_device_reset (void) SetEPTxStatus (ENDP5, EP_TX_DIS); #endif +#ifdef PINPAD_DND_SUPPORT + /* Initialize Endpoint 6 */ + SetEPType (ENDP6, EP_BULK); + SetEPTxAddr (ENDP6, ENDP6_TXADDR); + SetEPTxStatus (ENDP6, EP_TX_NAK); + SetEPRxStatus (ENDP6, EP_RX_DIS); + + /* Initialize Endpoint 7 */ + SetEPType (ENDP7, EP_BULK); + SetEPRxAddr (ENDP7, ENDP7_RXADDR); + SetEPRxStatus (ENDP7, EP_RX_STALL); + SetEPTxStatus (ENDP7, EP_TX_DIS); +#endif + /* Set this device to response on default address */ SetDeviceAddress (0); @@ -157,6 +171,21 @@ gnuk_device_SetInterface (void) ClearDTOG_TX (ENDP3); } #endif +#ifdef PINPAD_DND_SUPPORT +# ifdef ENABLE_VIRTUAL_COM_PORT + else if (intf == 3) + { + ClearDTOG_TX (ENDP6); + ClearDTOG_RX (ENDP7); + } +# else + else if (intf == 1) + { + ClearDTOG_TX (ENDP6); + ClearDTOG_RX (ENDP7); + } +# endif +#endif } static void @@ -204,10 +233,18 @@ gnuk_device_GetStringDescriptor (uint16_t Length) (PONE_DESCRIPTOR)&String_Descriptor[wValue0]); } -#ifdef ENABLE_VIRTUAL_COM_PORT -#define NUM_INTERFACES 3 /* two for CDC, one for CCID */ +#ifdef PINPAD_DND_SUPPORT +# ifdef ENABLE_VIRTUAL_COM_PORT +# define NUM_INTERFACES 4 /* two for CDC, one for CCID, and MSC */ +# else +# define NUM_INTERFACES 2 /* CCID and MSC */ +# endif #else -#define NUM_INTERFACES 1 /* CCID only */ +# ifdef ENABLE_VIRTUAL_COM_PORT +# define NUM_INTERFACES 3 /* two for CDC, one for CCID */ +# else +# define NUM_INTERFACES 1 /* CCID only */ +# endif #endif static RESULT From d9be456fedc585d7545fb6b28d4ae09c41500bff Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 13 Dec 2011 10:51:51 +0900 Subject: [PATCH 028/300] fix --- src/usb_msc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/usb_msc.c b/src/usb_msc.c index 40efb35..62dd321 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -205,7 +205,10 @@ void msc_media_insert_change (int available) contingent_allegiance = 1; media_available = available; if (available) - set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */ + { + set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */ + keep_contingent_allegiance = 0; + } else { set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */ @@ -272,6 +275,7 @@ static void msc_send_result (const uint8_t *p, size_t n) CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; } + CSW.dCSWSignature = MSC_CSW_SIGNATURE; chSysLock (); msc_state = MSC_SENDING_CSW; the_thread = chThdSelf (); @@ -512,6 +516,8 @@ msc_main (void *arg) { (void)arg; + /* Initially, it starts with no media */ + msc_media_insert_change (0); while (1) msc_handle_command (); From 828b8f57687e36cb1c197e61caa65dcda2143d6b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 13 Dec 2011 13:12:00 +0900 Subject: [PATCH 029/300] merge dnd-support branch fix vcom, change volume label --- ChangeLog | 22 +++++++++++++++++++++- src/gnuk.h | 4 ++++ src/main.c | 7 +++++-- src/pin-dnd.c | 51 ++++++++++++++++++++++++++++++++++++++++---------- src/usb_msc.c | 23 +++++++++++++++++++++++ src/usb_prop.c | 8 ++++---- 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67b57f2..f8f8745 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,28 @@ 2011-12-13 Niibe Yutaka + Add pinpad DND support. + * src/Makefile.in (CSRC) [ENABLE_PINPAD]: Add usb_msc.c. + * src/configure (pinpad): Add dnd support. + * src/gnuk.h [PINPAD_DND_SUPPORT]: Add declarations. + * src/main.c (STDOUTthread): Add PUSH packet. + (main) [PINPAD_DND_SUPPORT]: Call msc_init. + * src/usb_conf.h (EP_NUM): Add the case of PINPAD_DND_SUPPORT. + (ENDP6_TXADDR, ENDP7_RXADDR): New. + (ENDP4_TXADDR, ENDP5_RXADDR): Changed for smaller buffer. + * src/usb_desc.c (gnukConfigDescriptor): Add Mass storage device. + * src/usb_msc.c, src/usb_msc.h, src/pin-dnd.c: New. + * src/usb_prop.c: Include "usb_msc.h". + (gnuk_device_reset): Add initialization of ENDP6 and ENDP7. + (gnuk_device_SetInterface): Add initialization of ENDP6 and ENDP7. + (NUM_INTERFACES): Handle cases for PINPAD_DND_SUPPORT. + (msc_lun_info): New. + (gnuk_setup_with_data, gnuk_setup_with_nodata): Handle standard + request for Mass storage device. + * Virtual_COM_Port/usb_desc.h (VIRTUAL_COM_PORT_DATA_SIZE): Since + there isn't enough hardware buffer, smaller value (was: 64). + * src/ac.c (verify_user_0): Add access argument. (verify_pso_cds, verify_other, verify_admin_0): Follow the change. - * src/openpgp.c (cmd_change_password): Likewise. 2011-12-08 Niibe Yutaka diff --git a/src/gnuk.h b/src/gnuk.h index b4a6b8d..6bf3493 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -357,7 +357,11 @@ extern void cir_ext_enable (void); extern void dial_sw_disable (void); extern void dial_sw_enable (void); # elif defined(PINPAD_DND_SUPPORT) +extern uint8_t media_available; extern void msc_init (void); +extern void msc_media_insert_change (int available); +extern int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size); +extern int msc_scsi_read (uint32_t lba, const uint8_t **sector_p); # endif #define PIN_INPUT_CURRENT 1 #define PIN_INPUT_NEW 2 diff --git a/src/main.c b/src/main.c index eae07e8..4b9ef8a 100644 --- a/src/main.c +++ b/src/main.c @@ -106,10 +106,14 @@ STDOUTthread (void *arg) p = stdout.str; len = stdout.size; - while (len > 0) + while (1) { int i; + if (len == 0) + if (count_in != VIRTUAL_COM_PORT_DATA_SIZE) + break; + if (len < VIRTUAL_COM_PORT_DATA_SIZE) { for (i = 0; i < len; i++) @@ -396,7 +400,6 @@ main (int argc, char **argv) count++; m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL); -continue; switch (m) { case LED_STATUS_MODE: diff --git a/src/pin-dnd.c b/src/pin-dnd.c index ea3f063..3cd1c8d 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -1,9 +1,41 @@ +/* + * pin-dnd.c -- PIN input support (Drag and Drop with File Manager) + * + * Copyright (C) 2011 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + #include "config.h" #include "ch.h" #include "board.h" #include "gnuk.h" #include "usb_msc.h" +struct folder { + uint8_t parent; + uint8_t children[7]; +}; + +static struct folder folders[8]; +static const struct folder folder_ini = { 0, { 1, 2, 3, 4, 5, 6, 7 } }; + + uint8_t pin_input_buffer[MAX_PIN_CHARS]; uint8_t pin_input_len; @@ -20,7 +52,7 @@ pinpad_getline (int msg_code, systime_t timeout) msg_t msg; (void)msg_code; - + (void)timeout; DEBUG_INFO (">>>\r\n"); @@ -28,6 +60,9 @@ pinpad_getline (int msg_code, systime_t timeout) msc_media_insert_change (1); + memset (folders, 0, sizeof folders); + memcpy (folders, &folder_ini, sizeof folder_ini); + while (1) { chSysLock (); @@ -99,8 +134,8 @@ static const uint8_t d0_0_sector[] = { 0x29, /* extended boot signature */ 0xbf, 0x86, 0x75, 0xea, /* Volume ID (serial number) (Little endian) */ - /* Volume label */ - 'G', 'O', 'N', 'E', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + /* Volume label: DNDpinentry */ + 'D', 'n', 'D', 'p', 'i', 'n', 'e', 'n', 't', 'r', 'y', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */ @@ -147,12 +182,6 @@ static const uint8_t d0_fat0_sector[] = { static uint8_t the_sector[512]; -struct folder { - uint8_t parent; - uint8_t children[7]; -}; - -static struct folder folders[8] = { { 0, { 1, 2, 3, 4, 5, 6, 7 } }, }; #define FOLDER_INDEX_TO_CLUSTER_NO(i) (i+1) #define CLUSTER_NO_TO_FOLDER_INDEX(n) (n-1) #define FOLDER_INDEX_TO_LBA(i) (i+3) @@ -307,6 +336,8 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size) { + (void)size; + if (!media_available) return SCSI_ERROR_NOT_READY; @@ -314,7 +345,7 @@ msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size) return SCSI_ERROR_ILLEAGAL_REQUEST; if (lba == 1) - return 0; /* ??? */ + return 0; /* updating FAT, just ignore */ if (lba <= 2 || lba >= 11) return SCSI_ERROR_DATA_PROTECT; diff --git a/src/usb_msc.c b/src/usb_msc.c index 62dd321..4262825 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -1,3 +1,26 @@ +/* + * usb_msc.c -- USB Mass Storage Class protocol handling + * + * Copyright (C) 2011 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + #include "usb_lib.h" #include "config.h" diff --git a/src/usb_prop.c b/src/usb_prop.c index ebde6d0..c063a28 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -326,7 +326,7 @@ gnuk_setup_with_data (uint8_t RequestNo) } #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 2) + else if (pInformation->USBwIndex0 == 1) return Virtual_Com_Port_Data_Setup (RequestNo); else if (pInformation->USBwIndex0 == 3) # else @@ -344,7 +344,7 @@ gnuk_setup_with_data (uint8_t RequestNo) return USB_UNSUPPORT; } #elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 2) + else if (pInformation->USBwIndex0 == 1) return Virtual_Com_Port_Data_Setup (RequestNo); #endif else @@ -369,7 +369,7 @@ gnuk_setup_with_nodata (uint8_t RequestNo) } #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 2) + else if (pInformation->USBwIndex0 == 1) return Virtual_Com_Port_NoData_Setup (RequestNo); else if (pInformation->USBwIndex0 == 3) # else @@ -385,7 +385,7 @@ gnuk_setup_with_nodata (uint8_t RequestNo) return USB_UNSUPPORT; } #elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 2) + else if (pInformation->USBwIndex0 == 1) return Virtual_Com_Port_NoData_Setup (RequestNo); #endif else From a955cbec2fa8b8f00ef71dd2c99212d362051ec5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 13 Dec 2011 14:25:07 +0900 Subject: [PATCH 030/300] doc changes --- AUTHORS | 15 +++++++++++++++ NEWS | 19 ++++++++++++++++++- README | 22 ++++++++++++++-------- doc/settings-for-DnDpinentry | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 doc/settings-for-DnDpinentry diff --git a/AUTHORS b/AUTHORS index f9cb335..4b44825 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,6 +6,14 @@ Kaz Kojima: NIIBE Yutaka: Founder of the project. + Added FST_01 support: + boards/FST_01/board.c + boards/FST_01/board.h + boards/FST_01/mcuconf.h + Added FST_01_00 support: + boards/FST_01_00/board.c + boards/FST_01_00/board.h + boards/FST_01_00/mcuconf.h Added STBee support: boards/STBEE/board.c boards/STBEE/board.h @@ -28,6 +36,9 @@ NIIBE Yutaka: tool/intel_hex.py Wrote a tool for Gnuk: tool/gnuk_put_binary.py + tool/gnuk_put_binary_libusb.py + Wrote a tool for USB Hub: + tool/hub_ctrl.py Wrote: gnuk.svg src/configure @@ -49,5 +60,9 @@ NIIBE Yutaka: src/random.c src/pin-cir.c src/pin-dial.c + src/pin-dnd.c + src/usb_msc.c + src/usb_msc.h + src/neug.c * and others. diff --git a/NEWS b/NEWS index 6608be8..8d95654 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,22 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 0.16 + + Released 2011-12-1x, by NIIBE Yutaka + +** DnD pinentry support is added and it's default to pinentry support +DnD pinentry support doesn't require any hardware extension, but +emulates mass storage class device of USB. User inputs pass phrase +by "drag and drop"-ing folders using file manager or something. + +** Bug fix for VERIFY for CHV2 +With no keys, VERIFY command for CHV2 used to fail even if pass phrase +is correct. It was intentional, because CHV2 verification would be +useless with no keys. But there is a corner case for PRIVATE-DOs, +which may requires CHV2 verification. Even though Gnuk doesn't +support any PRIVATE-DOs, it is good to be fixed. + + * Major changes in Gnuk 0.15 Released 2011-11-24, by NIIBE Yutaka @@ -9,7 +26,7 @@ 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. +Now, it supports 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. diff --git a/README b/README index 87d0e86..34b9d77 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token - Version 0.15 - 2011-11-24 + Version 0.16 + 2011-12-1x Niibe Yutaka Free Software Initiative of Japan @@ -9,8 +9,8 @@ What's Gnuk? ============ Gnuk is software implementation of a USB token for GNU Privacy Guard. -Gnuk supports OpenPGP card protocol version 2, and it runs on STM32 -processor. +Gnuk supports OpenPGP card protocol version 2, and it runs on +STM32F103 processor. I wish that Gnuk will be a developer's soother who uses GnuPG. I have been nervous of storing secret key(s) on usual secondary storage. @@ -94,21 +94,22 @@ 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 + $ 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 + $ gnome-session-properties -and at the tab of "Startup Programs", disable check buttons for "GPG Password Agent" and "SSH Key Agent". + and at the tab of "Startup Programs", disable check buttons for + "GPG Password Agent" and "SSH Key Agent". Release notes ============= -This is sixteenth release of Gnuk. While it works well for specific +This is seventeenth release of Gnuk. While it works well for specific usages and it is considered stable, it is still somewhat experimental. Tested features are: @@ -172,6 +173,11 @@ Another PIN-pad support is connecting rotary encoder, push switch and 7-segment LED display. Both of PIN verification and PIN modification are supported for this circuit extension. +Recently, "DnDpinentry" qsupport is added. This is using normal file +manager for pinentry. User does "drag and drop" folders and it will +be pin entry. This feature doesn't require any additional hardware. +See doc/settings-for-DnDpinentry for your desktop configuration. + Souce code ========== diff --git a/doc/settings-for-DnDpinentry b/doc/settings-for-DnDpinentry new file mode 100644 index 0000000..c0c52ad --- /dev/null +++ b/doc/settings-for-DnDpinentry @@ -0,0 +1,34 @@ +On GNU/Linux Desktop, I use udisks-glue so that DnDpinentry folder can +be mounted with sync and noatime options. + +After installing udisks-glue, I invoke gnome-session-properties to +add udisks-glue to "Startup Program". + +Then, I have two files to configure udisks (disable udisks for +DnDpinentry) and udisks-glue (enable and specify options for DnDpinentry). + +/etc/udev/rules.d/88-udisks.rules +--------------- +ENV{ID_VENDOR}=="FSIJ", ENV{DEVTYPE}=="disk", ENV{ID_FS_LABEL}=="DnDpinentry", ENV{UDISKS_PRESENTATION_NOPOLICY}="1" +--------------- + +~/.udisks-glue.conf +--------------- +filter gone { + label = "DnDpinentry" + optical = false +} + +match gone { + automount = true + automount_options = { sync, noatime } +} +--------------- + +We need following setting for pinentry. Or else, you can't do +anything when pinentry grabs mouse focus. + +~/.gnupg/gpg-agent.conf +--------------- +no-grab +--------------- From b4d36a429fa7237e2c28a14787fee2a0738a2226 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 14 Dec 2011 12:45:20 +0900 Subject: [PATCH 031/300] Fixes for PINPAD_SUPPORT --- ChangeLog | 7 +++++++ boards/FST_01/board.c | 4 ++-- boards/STBEE/board.c | 4 ---- boards/STBEE/board.h | 4 ++-- boards/STBEE_MINI/board.c | 6 ++---- boards/STBEE_MINI/board.h | 4 ++-- boards/STM8S_DISCOVERY/board.c | 4 ++-- boards/STM8S_DISCOVERY/board.h | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8f8745..b10f59d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-14 Niibe Yutaka + + * boards/STM8S_DISCOVERY/board.h, board.c: Fix for PINPAD_SUPPORT. + * boards/STBEE_MINI/board.h, board.c: Likewise. + * boards/STBEE/board.h, board.c: Likewise. + * boards/FST_01/board.c: Likewise. + 2011-12-13 Niibe Yutaka Add pinpad DND support. diff --git a/boards/FST_01/board.c b/boards/FST_01/board.c index 1172c27..cdd64bd 100644 --- a/boards/FST_01/board.c +++ b/boards/FST_01/board.c @@ -15,7 +15,7 @@ hwinit1 (void) { hwinit1_common (); -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) /* PA0/TIM2_CH1 = 1 (pull up) */ /* PA1/TIM2_CH2 = 0 (pull down) */ /* PA2/TIM2_CH3 <= Vout of CIR receiver module */ @@ -66,7 +66,7 @@ set_led (int value) palClearPad (IOPORT2, GPIOB_LED); } -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) { diff --git a/boards/STBEE/board.c b/boards/STBEE/board.c index 882d79e..391165d 100644 --- a/boards/STBEE/board.c +++ b/boards/STBEE/board.c @@ -15,7 +15,6 @@ hwinit1 (void) { hwinit1_common (); -#if defined(PINPAD_SUPPORT) #if defined(PINPAD_CIR_SUPPORT) /* EXTI0 <= PB0 */ AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB; @@ -69,7 +68,6 @@ hwinit1 (void) /* Generate UEV to upload PSC and ARR */ TIM4->EGR = TIM_EGR_UG; #endif -#endif } void @@ -90,7 +88,6 @@ set_led (int value) palSetPad (IOPORT4, GPIOD_LED1); } -#if defined(PINPAD_SUPPORT) #if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) @@ -156,4 +153,3 @@ CH_IRQ_HANDLER (EXTI2_IRQHandler) CH_IRQ_EPILOGUE (); } #endif -#endif diff --git a/boards/STBEE/board.h b/boards/STBEE/board.h index a947f06..b31f5e5 100644 --- a/boards/STBEE/board.h +++ b/boards/STBEE/board.h @@ -38,7 +38,7 @@ #define BOARD_STBEE #define BOARD_NAME "STBee" -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT) #define HAVE_7SEGLED 1 /* * Timer assignment for CIR @@ -89,7 +89,7 @@ * Please refer to the STM32 Reference Manual for details. */ -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT) /* * Port A setup. * PA6 - (TIM3_CH1) input with pull-up diff --git a/boards/STBEE_MINI/board.c b/boards/STBEE_MINI/board.c index edc53f7..c65d3d9 100644 --- a/boards/STBEE_MINI/board.c +++ b/boards/STBEE_MINI/board.c @@ -15,11 +15,12 @@ hwinit1 (void) { hwinit1_common (); -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT) palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */ while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0) ; /* Wait for JTAG debugger connection */ palWritePort(IOPORT2, 0xffff); /* All set */ +#endif #if defined(PINPAD_CIR_SUPPORT) /* EXTI0 <= PB0 */ @@ -73,7 +74,6 @@ hwinit1 (void) TIM4->ARR = 31; /* Generate UEV to upload PSC and ARR */ TIM4->EGR = TIM_EGR_UG; -#endif #endif /* * Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO @@ -101,7 +101,6 @@ set_led (int value) palSetPad (IOPORT1, GPIOA_LED1); } -#if defined(PINPAD_SUPPORT) #if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) @@ -167,4 +166,3 @@ CH_IRQ_HANDLER (EXTI2_IRQHandler) CH_IRQ_EPILOGUE (); } #endif -#endif diff --git a/boards/STBEE_MINI/board.h b/boards/STBEE_MINI/board.h index a256510..cdd7527 100644 --- a/boards/STBEE_MINI/board.h +++ b/boards/STBEE_MINI/board.h @@ -39,7 +39,7 @@ #define BOARD_NAME "STBee Mini" #define CPU_WITH_NO_GPIOE 1 -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT) #define HAVE_7SEGLED 1 /* * Timer assignment for CIR @@ -92,7 +92,7 @@ * Please refer to the STM32 Reference Manual for details. */ -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT) /* * Port A setup. * PA6 - (TIM3_CH1) input with pull-up diff --git a/boards/STM8S_DISCOVERY/board.c b/boards/STM8S_DISCOVERY/board.c index 88f4032..355efc9 100644 --- a/boards/STM8S_DISCOVERY/board.c +++ b/boards/STM8S_DISCOVERY/board.c @@ -15,7 +15,7 @@ hwinit1 (void) { hwinit1_common (); -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) /* EXTI5 <= PB5 */ AFIO->EXTICR[1] = AFIO_EXTICR2_EXTI5_PB; EXTI->IMR = 0; @@ -62,7 +62,7 @@ set_led (int value) palClearPad (IOPORT1, GPIOA_LED); } -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) { diff --git a/boards/STM8S_DISCOVERY/board.h b/boards/STM8S_DISCOVERY/board.h index 562dd55..71ad5f2 100644 --- a/boards/STM8S_DISCOVERY/board.h +++ b/boards/STM8S_DISCOVERY/board.h @@ -96,7 +96,7 @@ #define VAL_GPIOACRH 0x88888883 /* PA15...PA8 */ #define VAL_GPIOAODR 0xFFFFFFFF -#if defined(PINPAD_SUPPORT) +#if defined(PINPAD_CIR_SUPPORT) /* * Port B setup. * Everything input with pull-up except: From e2a4be1444f2bc03d66802277ff81810c2116a6d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 14 Dec 2011 12:50:54 +0900 Subject: [PATCH 032/300] version 0.16 --- ChangeLog | 4 ++++ NEWS | 8 +++++++- README | 9 +++++++-- src/usb_desc.c | 2 +- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index b10f59d..a06beae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-12-14 Niibe Yutaka + * Version 0.16. + + * src/usb_desc.c (gnukStringSerial): Updated. + * boards/STM8S_DISCOVERY/board.h, board.c: Fix for PINPAD_SUPPORT. * boards/STBEE_MINI/board.h, board.c: Likewise. * boards/STBEE/board.h, board.c: Likewise. diff --git a/NEWS b/NEWS index 8d95654..bdc1a4c 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,7 @@ Gnuk NEWS - User visible changes * Major changes in Gnuk 0.16 - Released 2011-12-1x, by NIIBE Yutaka + Released 2011-12-14, by NIIBE Yutaka ** DnD pinentry support is added and it's default to pinentry support DnD pinentry support doesn't require any hardware extension, but @@ -16,6 +16,12 @@ useless with no keys. But there is a corner case for PRIVATE-DOs, which may requires CHV2 verification. Even though Gnuk doesn't support any PRIVATE-DOs, it is good to be fixed. +** Changed bcdUSB = 1.1 +Gnuk device conforms to USB 2.0 full speed device, but when it was +2.0, some OS informs users, "you can connect the device to 2.0 +compliant hub so that it can have better bandwidth", which is not +the case for full speed device. + * Major changes in Gnuk 0.15 diff --git a/README b/README index 34b9d77..c3aa877 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token Version 0.16 - 2011-12-1x + 2011-12-14 Niibe Yutaka Free Software Initiative of Japan @@ -173,11 +173,16 @@ Another PIN-pad support is connecting rotary encoder, push switch and 7-segment LED display. Both of PIN verification and PIN modification are supported for this circuit extension. -Recently, "DnDpinentry" qsupport is added. This is using normal file +Recently, "DnDpinentry" support is added. This is using usual file manager for pinentry. User does "drag and drop" folders and it will be pin entry. This feature doesn't require any additional hardware. See doc/settings-for-DnDpinentry for your desktop configuration. +Note that you need pinpad support for GnuPG, it's currently in the +master branch of GnuPG git repository at git.gnupg.org, and it's under +evaluation. When it will be considered stable, it will be put onto +stable branch. + Souce code ========== diff --git a/src/usb_desc.c b/src/usb_desc.c index 00b0f17..43c09eb 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -275,7 +275,7 @@ static const uint8_t gnukStringProduct[] = { const uint8_t gnukStringSerial[] = { 13*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - '0', 0, '.', 0, '1', 0, '5', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '1', 0, '6', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From 1145fe0ad8013b5a3f273386ec44a048d8baf1de Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 16 Dec 2011 16:42:09 +0900 Subject: [PATCH 033/300] add new tool pinpad-test.py --- ChangeLog | 9 ++ tool/gnuk_put_binary.py | 2 +- tool/gnuk_put_binary_libusb.py | 2 +- tool/pinpad-test.py | 187 +++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 2 deletions(-) create mode 100755 tool/pinpad-test.py diff --git a/ChangeLog b/ChangeLog index a06beae..06e3b04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-16 Niibe Yutaka + + * tool/gnuk_put_binary_libusb.py (gnuk_token.cmd_select_openpgp): + Fix apdu parameter. + + * tool/gnuk_put_binary.py (GnukToken.cmd_select_openpgp): Ditto. + + * tool/pinpad-test.py: New. + 2011-12-14 Niibe Yutaka * Version 0.16. diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 07a86e9..f0e83cc 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -72,7 +72,7 @@ class GnukToken(object): count += 1 def cmd_select_openpgp(self): - apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, "cmd_select_openpgp" diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index d4a1e87..4d7afef 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -189,7 +189,7 @@ class gnuk_token: count += 1 def cmd_select_openpgp(self): - cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") + cmd_data = iso7816_compose(0xa4, 0x04, 0x00, "\xD2\x76\x00\x01\x24\x01") sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: raise ValueError, "cmd_select_openpgp" diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py new file mode 100755 index 0000000..f50fa76 --- /dev/null +++ b/tool/pinpad-test.py @@ -0,0 +1,187 @@ +#! /usr/bin/python + +""" +pinpad-test.py - a tool to test pinpad support by card reader. + +Copyright (C) 2011 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +import sys + +# Assume only single CCID device is attached to computer with card + +from smartcard.CardType import AnyCardType +from smartcard.CardRequest import CardRequest +from smartcard.util import toHexString + +CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400) +FEATURE_VERIFY_PIN_DIRECT = 0x06 +FEATURE_MODIFY_PIN_DIRECT = 0x07 + +class Card(object): + def __init__(self, add_a_byte): + cardtype = AnyCardType() + cardrequest = CardRequest(timeout=1, cardType=cardtype) + cardservice = cardrequest.waitforcard() + self.connection = cardservice.connection + self.verify_ioctl = -1 + self.modify_ioctl = -1 + self.another_byte = add_a_byte + + def get_features(self): + p = self.connection.control(CM_IOCTL_GET_FEATURE_REQUEST, []) + i = 0 + while i < len(p): + code = p[i] + l = p[i+1] + i = i + 2 + if l == 4: + ioctl = (p[i] << 24) | (p[i+1] << 16) | (p[i+2] << 8) | p[i+3] + i = i + l + else: + i = i + l + continue + if code == FEATURE_VERIFY_PIN_DIRECT: + self.verify_ioctl = ioctl + elif code == FEATURE_MODIFY_PIN_DIRECT: + self.modify_ioctl = ioctl + if self.verify_ioctl == -1: + raise ValueError, "Not supported" + + def cmd_select_openpgp(self): + apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, "cmd_select_openpgp" + + def possibly_add_dummy_byte(self): + if self.another_byte: + return [ 0 ] + else: + return [] + + def cmd_verify_pinpad(self, who): + apdu = [0x00, 0x20, 0x00, 0x80+who ] + pin_verify = [ 0x00, # bTimeOut + 0x00, # bTimeOut2 + 0x82, # bmFormatString: Byte, pos=0, left, ASCII. + 0x00, # bmPINBlockString + 0x00, # bmPINLengthFormat + 15, # wPINMaxExtraDigit Low (PINmax) + 1, # wPINMaxExtraDigit High (PINmin) + 0x02, # bEntryValidationCondition + 0x01, # bNumberMessage + 0x00, # wLangId Low + 0x00, # wLangId High + 0x00, # bMsgIndex + 0x00, # bTeoPrologue[0] + 0x00, # bTeoPrologue[1] + 0x00 # bTeoPrologue[2] + ] + pin_verify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte() + data = self.connection.control(self.verify_ioctl,pin_verify) + sw1 = data[0] + sw2 = data[1] + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("cmd_verify_pinpad %02x %02x" % (sw1, sw2)) + + def send_modify_pinpad(self, adpu, command): + if self.modify_ioctl == -1: + raise ValueError, "Not supported" + pin_modify = [ 0x00, # bTimerOut + 0x00, # bTimerOut2 + 0x82, # bmFormatString: Byte, pos=0, left, ASCII. + 0x00, # bmPINBlockString + 0x00, # bmPINLengthFormat + 0x00, # bInsertionOffsetOld + 0x00, # bInsertionOffsetNew + 15, # wPINMaxExtraDigit Low (PINmax) + 1, # wPINMaxExtraDigit High (PINmin) + 0x03, # bConfirmPIN: old PIN and new PIN twice + 0x02, # bEntryValidationCondition + 0x03, # bNumberMessage + 0x00, # wLangId Low + 0x00, # wLangId High + 0x00, # bMsgIndex1 + 0x01, # bMsgIndex2 + 0x02, # bMsgIndex3 + 0x00, # bTeoPrologue[0] + 0x00, # bTeoPrologue[1] + 0x00 # bTeoPrologue[2] + ] + pin_modify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte() + data = self.connection.control(self.modify_ioctl,pin_modify) + sw1 = data[0] + sw2 = data[1] + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%s %02x %02x" % (command, sw1, sw2)) + + def cmd_reset_retry_counter_pinpad(self, who): + apdu = [0x00, 0x2c, 0x02, 0x80+who ] + self.send_modify_pinpad(apdu, "cmd_reset_retry_counter_pinpad") + + def cmd_change_reference_data(self, who): + apdu = [0x00, 0x24, 0x00, 0x80+who ] + self.send_modify_pinpad(apdu, "cmd_change_reference_data") + + +def main(who, method, add_a_byte): + card = Card(add_a_byte) + + card.connection.connect() + print "Reader/Token:", card.connection.getReader() + print "ATR:", toHexString( card.connection.getATR() ) + + card.get_features() + card.cmd_select_openpgp() + if method == "verify" + card.cmd_verify_pinpad(who) + elif method == "change" + card.cmd_change_reference_data(self, who): + elif method == "unblock" + card.cmd_reset_retry_counter_pinpad(who) + else: + raise ValueError, method + card.connection.disconnect() + + print "OK." + return 0 + +BY_ADMIN = 3 +BY_USER = 1 + +if __name__ == '__main__': + who = BY_USER + method = "verify" + add_a_byte = False + while len(sys.argv) >= 2: + option = sys.argv[1] + sys.argv.pop(1) + if option == '--admin': + who = BY_ADMIN + elif option == '--unblock': + who = BY_ADMIN + method = "unblock" + elif option == '--change': + method = "change" + elif option == '--add': + add_a_byte = True + else: + raise ValueError, option + main(who, method, add_a_byte) From 4a75aa47dfa3d938998629ddae88e9482aef303d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 19 Dec 2011 12:17:22 +0900 Subject: [PATCH 034/300] improve pinpad-test.py --- tool/pinpad-test.py | 111 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index f50fa76..71edc21 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -34,8 +34,18 @@ CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400) FEATURE_VERIFY_PIN_DIRECT = 0x06 FEATURE_MODIFY_PIN_DIRECT = 0x07 +BY_ADMIN = 3 +BY_USER = 1 +PIN_MAX_DEFAULT = 15 # max of VASCO DIGIPASS 920 + +def confirm_pin_setting(single_step): + if single_step: + return 0x01 # bConfirmPIN: new PIN twice + else: + return 0x03 # bConfirmPIN: old PIN and new PIN twice + class Card(object): - def __init__(self, add_a_byte): + def __init__(self, add_a_byte, pinmax): cardtype = AnyCardType() cardrequest = CardRequest(timeout=1, cardType=cardtype) cardservice = cardrequest.waitforcard() @@ -43,6 +53,7 @@ class Card(object): self.verify_ioctl = -1 self.modify_ioctl = -1 self.another_byte = add_a_byte + self.pinmax = pinmax def get_features(self): p = self.connection.control(CM_IOCTL_GET_FEATURE_REQUEST, []) @@ -83,7 +94,7 @@ class Card(object): 0x82, # bmFormatString: Byte, pos=0, left, ASCII. 0x00, # bmPINBlockString 0x00, # bmPINLengthFormat - 15, # wPINMaxExtraDigit Low (PINmax) + self.pinmax, # wPINMaxExtraDigit Low (PINmax) 1, # wPINMaxExtraDigit High (PINmin) 0x02, # bEntryValidationCondition 0x01, # bNumberMessage @@ -101,7 +112,7 @@ class Card(object): if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("cmd_verify_pinpad %02x %02x" % (sw1, sw2)) - def send_modify_pinpad(self, adpu, command): + def send_modify_pinpad(self, adpu, single_step, command): if self.modify_ioctl == -1: raise ValueError, "Not supported" pin_modify = [ 0x00, # bTimerOut @@ -111,9 +122,9 @@ class Card(object): 0x00, # bmPINLengthFormat 0x00, # bInsertionOffsetOld 0x00, # bInsertionOffsetNew - 15, # wPINMaxExtraDigit Low (PINmax) + self.pinmax, # wPINMaxExtraDigit Low (PINmax) 1, # wPINMaxExtraDigit High (PINmin) - 0x03, # bConfirmPIN: old PIN and new PIN twice + confirm_pin_setting(single_step), 0x02, # bEntryValidationCondition 0x03, # bNumberMessage 0x00, # wLangId Low @@ -132,30 +143,55 @@ class Card(object): if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%s %02x %02x" % (command, sw1, sw2)) + # Note: CCID specification doesn't permit this (only 0x20 and 0x24) def cmd_reset_retry_counter_pinpad(self, who): - apdu = [0x00, 0x2c, 0x02, 0x80+who ] - self.send_modify_pinpad(apdu, "cmd_reset_retry_counter_pinpad") + if who == BY_ADMIN: + apdu = [0x00, 0x2c, 0x02, 0x81] # BY_ADMIN + else: + apdu = [0x00, 0x2c, 0x00, 0x81] # BY_USER with resetcode + self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad") - def cmd_change_reference_data(self, who): - apdu = [0x00, 0x24, 0x00, 0x80+who ] - self.send_modify_pinpad(apdu, "cmd_change_reference_data") + # Note: CCID specification doesn't permit this (only 0x20 and 0x24) + def cmd_put_resetcode_pinpad(self): + apdu = [0x00, 0xda, 0x00, 0xd3] + self.send_modify_pinpad(apdu, True, "cmd_put_resetcode_pinpad") + def cmd_change_reference_data_pinpad(self, who, is_exchange): + if is_exchange: + apdu = [0x00, 0x24, 1, 0x80+who] + else: + apdu = [0x00, 0x24, 0x00, 0x80+who] + self.send_modify_pinpad(apdu, is_exchange, + "cmd_change_reference_data_pinpad") -def main(who, method, add_a_byte): - card = Card(add_a_byte) +# "Vasco DIGIPASS 920 [CCID] 00 00" +# "FSIJ Gnuk (0.16-34006F06) 00 00" +def main(who, method, add_a_byte, pinmax, change_by_two_steps): + card = Card(add_a_byte, pinmax) card.connection.connect() + print "Reader/Token:", card.connection.getReader() print "ATR:", toHexString( card.connection.getATR() ) card.get_features() + card.cmd_select_openpgp() - if method == "verify" + if method == "verify": card.cmd_verify_pinpad(who) - elif method == "change" - card.cmd_change_reference_data(self, who): - elif method == "unblock" + elif method == "change": + if change_by_two_steps: + card.cmd_verify_pinpad(who) + card.cmd_change_reference_data_pinpad(self, who, True) + else: + card.cmd_change_reference_data_pinpad(self, who, False) + elif method == "unblock": + # It's always by single step card.cmd_reset_retry_counter_pinpad(who) + elif method == "put": + # It's always by two steps + card.cmd_verify_pinpad(BY_ADMIN) + card.cmd_put_resetcode_pinpad() else: raise ValueError, method card.connection.disconnect() @@ -163,25 +199,56 @@ def main(who, method, add_a_byte): print "OK." return 0 -BY_ADMIN = 3 -BY_USER = 1 +def print_usage(): + print "pinpad-test: testing pinentry of PC/SC card reader" + print "\thelp:" + print "\t\t--help:\t\tthis message" + print "\tmethod:\t\t\t\t\t\t\t\t[verify]" + print "\t\t--verify:\tverify PIN" + print "\t\t--change:\tchange PIN (old PIN, new PIN twice)" + print "\t\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)" + print "\t\t--unblock:\tunblock PIN (admin PIN or resetcode, new PIN twice)" + print "\t\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)" + print "\toptions:" + print "\t\t--admin:\tby administrator\t\t\t[False]" + print "\t\t--add:\t\tadd a dummy byte at the end of APDU\t[False]" + print "\t\t--pinmax:\tspecify maximum length of PIN\t\t[15]" + print "EXAMPLES:" + print " $ pinpad-test # verify user's PIN " + print " $ pinpad-test --admin --change # change admin's PIN " + print " $ pinpad-test --admin --unblock # change user's PIN by admin's PIN" + print " $ pinpad-test --unblock # change user's PIN by reset code" if __name__ == '__main__': who = BY_USER method = "verify" add_a_byte = False + pinmax = PIN_MAX_DEFAULT + change_by_two_steps = False while len(sys.argv) >= 2: option = sys.argv[1] sys.argv.pop(1) if option == '--admin': who = BY_ADMIN - elif option == '--unblock': - who = BY_ADMIN - method = "unblock" elif option == '--change': method = "change" + elif option == '--change2': + method = "change" + change_by_two_steps = True + elif option == '--unblock': + method = "unblock" elif option == '--add': add_a_byte = True + elif option == '--pinmax': + pinmax = int(sys.argv[1]) + sys.argv.pop(1) + elif option == '--put': + method = "put" + elif option == "verify": + method = "verify" + elif option == '--help': + print_usage() + exit(0) else: raise ValueError, option - main(who, method, add_a_byte) + main(who, method, add_a_byte, pinmax, change_by_two_steps) From a08669dfcd9eacdc839730a946743960b0284bf5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 19 Dec 2011 12:28:01 +0900 Subject: [PATCH 035/300] add messages to pinpad-test.py --- tool/pinpad-test.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 71edc21..88f65dd 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -178,19 +178,45 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps): card.cmd_select_openpgp() if method == "verify": + if who == BY_USER: + print "Please input User's PIN" + else: + print "Please input Admin's PIN" card.cmd_verify_pinpad(who) elif method == "change": if change_by_two_steps: + if who == BY_USER: + print "Please input User's PIN" + else: + print "Please input Admin's PIN" card.cmd_verify_pinpad(who) + if who == BY_USER: + print "Please input New User's PIN twice" + else: + print "Please input New Admin's PIN twice" card.cmd_change_reference_data_pinpad(self, who, True) else: + if who == BY_USER: + print "Please input User's PIN" + print "and New User's PIN twice" + else: + print "Please input Admin's PIN" + print "and New Admin's PIN twice" card.cmd_change_reference_data_pinpad(self, who, False) elif method == "unblock": # It's always by single step + if who == BY_USER: + print "Please input reset code" + print "and New User's PIN twice" + else: + print "Please input Admin's PIN" + print "and New User's PIN twice" card.cmd_reset_retry_counter_pinpad(who) elif method == "put": # It's always by two steps + print "Please input Admin's PIN" card.cmd_verify_pinpad(BY_ADMIN) + print "Please input New Reset Code twice" card.cmd_put_resetcode_pinpad() else: raise ValueError, method @@ -215,9 +241,14 @@ def print_usage(): print "\t\t--pinmax:\tspecify maximum length of PIN\t\t[15]" print "EXAMPLES:" print " $ pinpad-test # verify user's PIN " - print " $ pinpad-test --admin --change # change admin's PIN " - print " $ pinpad-test --admin --unblock # change user's PIN by admin's PIN" + print " $ pinpad-test --admin # verify admin's PIN " + print " $ pinpad-test --change # change user's PIN " + print " $ pinpad-test --change --admin # change admin's PIN " + print " $ pinpad-test --change2 # change user's PIN by two steps" + print " $ pinpad-test --change2 --admin # change admin's PIN by two steps" print " $ pinpad-test --unblock # change user's PIN by reset code" + print " $ pinpad-test --unblock --admin # change user's PIN by admin's PIN" + print " $ pinpad-test --put # setup resetcode " if __name__ == '__main__': who = BY_USER @@ -252,3 +283,5 @@ if __name__ == '__main__': else: raise ValueError, option main(who, method, add_a_byte, pinmax, change_by_two_steps) + +# 69 82: security error: pin doesn't match From c0ab2ae830a2401cfa0bc45e3acc56c175f7bad8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 20 Dec 2011 10:39:47 +0900 Subject: [PATCH 036/300] DnDpinentry: cancellation --- ChangeLog | 10 ++++++++++ NEWS | 13 +++++++++++++ src/gnuk.h | 1 + src/pin-dnd.c | 23 ++++++++++++++++++----- src/usb_msc.c | 13 ++++++++++++- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 06e3b04..17dedf1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-12-20 Niibe Yutaka + + * src/usb_msc.c (msc_handle_command): SCSI_START_STOP_UNIT command + with stop/eject/close means cancelling pinentry. + + * src/pin-dnd.c (pinpad_finish_entry, parse_directory_sector): + Implement "cancel". + (pinpad_getline): Likewise. + (msc_scsi_stop): New. + 2011-12-16 Niibe Yutaka * tool/gnuk_put_binary_libusb.py (gnuk_token.cmd_select_openpgp): diff --git a/NEWS b/NEWS index bdc1a4c..3b60b77 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,18 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 0.17 + + Released 2012-01-XX, by NIIBE Yutaka + +** With DnD pinentry, user can cancel pin input +Now, user can cancel pin input by unmounting device before finishing +DnD. + +** New tool: pinpad-test.py +The tool pinpad-test.py is PC/SC test tool for pinentry of pinpad with +OpenPGP card v2. + + * Major changes in Gnuk 0.16 Released 2011-12-14, by NIIBE Yutaka diff --git a/src/gnuk.h b/src/gnuk.h index 6bf3493..e0d72d6 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -362,6 +362,7 @@ extern void msc_init (void); extern void msc_media_insert_change (int available); extern int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size); extern int msc_scsi_read (uint32_t lba, const uint8_t **sector_p); +extern void msc_scsi_stop (uint8_t code); # endif #define PIN_INPUT_CURRENT 1 #define PIN_INPUT_NEW 2 diff --git a/src/pin-dnd.c b/src/pin-dnd.c index 3cd1c8d..70d1de9 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -72,13 +72,16 @@ pinpad_getline (int msg_code, systime_t timeout) chSysUnlock (); led_blink (0); - if (msg == 1) + if (msg != 0) break; } msc_media_insert_change (0); - return pin_input_len; + if (msg == 1) + return pin_input_len; + else + return -1; /* cancel */ } static void pinpad_input (void) @@ -89,10 +92,13 @@ static void pinpad_input (void) chSysUnlock (); } -static void pinpad_finish_entry (void) +static void pinpad_finish_entry (int cancel) { chSysLock (); - pin_thread->p_u.rdymsg = 1; + if (cancel) + pin_thread->p_u.rdymsg = 2; + else + pin_thread->p_u.rdymsg = 1; chSchReadyI (pin_thread); chSysUnlock (); } @@ -328,7 +334,7 @@ static void parse_directory_sector (const uint8_t *p, uint8_t index) } if (index == 0 && num_children == 1) - pinpad_finish_entry (); + pinpad_finish_entry (0); else if (input) pinpad_input (); } @@ -357,3 +363,10 @@ msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size) return 0; } } + +void +msc_scsi_stop (uint8_t code) +{ + (void)code; + pinpad_finish_entry (1); +} diff --git a/src/usb_msc.c b/src/usb_msc.c index 4262825..77836b9 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -388,6 +388,17 @@ void msc_handle_command (void) buf[11] = (uint8_t)(secsize >> 0); msc_send_result (buf, 12); return; + case SCSI_START_STOP_UNIT: + if (CBW.CBWCB[4] == 0x00 /* stop */ + || CBW.CBWCB[4] == 0x02 /* eject */ || CBW.CBWCB[4] == 0x03 /* close */) + { + msc_scsi_stop (CBW.CBWCB[4]); + set_scsi_sense_data (0x05, 0x24); /* ILLEGAL_REQUEST */ + contingent_allegiance = 1; + keep_contingent_allegiance = 1; + } + /* CBW.CBWCB[4] == 0x01 *//* start */ + goto success; case SCSI_TEST_UNIT_READY: if (contingent_allegiance) { @@ -397,9 +408,9 @@ void msc_handle_command (void) return; } /* fall through */ + success: case SCSI_SYNCHRONIZE_CACHE: case SCSI_VERIFY10: - case SCSI_START_STOP_UNIT: case SCSI_ALLOW_MEDIUM_REMOVAL: CSW.bCSWStatus = MSC_CSW_STATUS_PASSED; CSW.dCSWDataResidue = CBW.dCBWDataTransferLength; From a0c8cf2ff4c637bfa46c864bd27fa921577ba902 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 21 Dec 2011 14:14:28 +0900 Subject: [PATCH 037/300] Data Object 0x7f21 is now optional --- ChangeLog | 17 +++++++++++++++++ NEWS | 6 ++++++ src/config.h.in | 1 + src/configure | 36 +++++++++++++++++++++++++++--------- src/flash.c | 16 +++++++++++----- src/gnuk.ld.in | 2 ++ src/openpgp-do.c | 2 ++ 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17dedf1..5d6704b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-12-21 Niibe Yutaka + + * src/openpgp-do.c (gpg_do_get_data) [CERTDO_SUPPORT]: ifdef out. + + * src/gnuk.ld.in (.gnuk_ch_certificate): Only valid + when --enable-certdo. + + * src/flash.c (flash_check_blank) [CERTDO_SUPPORT]: ifdef out. + (flash_erase_binary) [CERTDO_SUPPORT]: Likewise. + (flash_write_binary) [CERTDO_SUPPORT]: Likewise. + + * src/configure (certdo): New. + (--enable-certdo, --disable-certdo): New options. + Remove cheking for /dev/random. + + * src/config.h.in (@CERTDO_DEFINE@): New. + 2011-12-20 Niibe Yutaka * src/usb_msc.c (msc_handle_command): SCSI_START_STOP_UNIT command diff --git a/NEWS b/NEWS index 3b60b77..8928329 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,12 @@ Gnuk NEWS - User visible changes Released 2012-01-XX, by NIIBE Yutaka +** CERT.3 Data Object (0x7f21) is now optional +As there's no valid use case for this data object and it does not +work as current version of GnuPG, this is now optional feature. +You can enable this data object by specifying --enable-certdo at +configure time. + ** With DnD pinentry, user can cancel pin input Now, user can cancel pin input by unmounting device before finishing DnD. diff --git a/src/config.h.in b/src/config.h.in index 23fe05d..37fbb30 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -5,3 +5,4 @@ @DFU_DEFINE@ @PINPAD_DEFINE@ @PINPAD_MORE_DEFINE@ +@CERTDO_DEFINE@ diff --git a/src/configure b/src/configure index 8b7cd8a..fb86998 100755 --- a/src/configure +++ b/src/configure @@ -26,12 +26,7 @@ verbose=no with_dfu=default debug=no pinpad=no - -# check /dev/random -if test ! -e /dev/random; then - echo "/dev/random is required." >&2 - exit 1 -fi +certdo=no # Process each option for option; do @@ -57,6 +52,10 @@ for option; do pinpad=$optarg ;; --disable-pinpad) pinpad=no ;; + --enable-certdo) + certdo=yes ;; + --disable-certdo) + certdo=no ;; --with-dfu) with_dfu=yes ;; --without-dfu) @@ -88,6 +87,7 @@ Configuration: --enable-debug debug with virtual COM port [no] --enable-pinpad={dnd,cir,dial} PIN entry support [no] + --enable-certdo support CERT.3 data object [no] --with-dfu build image for DFU [] EOF exit 0 @@ -170,16 +170,34 @@ else echo "PIN pad option enabled ($pinpad)" fi +# --enable-certdo option +if test "$certdo" = "yes"; then + CERTDO_DEFINE="#define CERTDO_SUPPORT 1" + echo "CERT.3 Data Object is supported (Note: it is not supported by GnuPG)" +else + CERTDO_DEFINE="#undef CERTDO_SUPPORT" + echo "CERT.3 Data Object is not supported" +fi + sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ < Makefile.in > Makefile -sed -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \ - -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ +if test "$certdo" = "yes"; then + sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \ + -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \ + -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ < gnuk.ld.in > gnuk.ld +else + sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \ + -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \ + -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ + < gnuk.ld.in > gnuk.ld +fi sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \ + -e "s/@DFU_DEFINE@/$DFU_DEFINE/" \ -e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \ -e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \ - -e "s/@DFU_DEFINE@/$DFU_DEFINE/" \ + -e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \ < config.h.in > config.h exit 0 diff --git a/src/flash.c b/src/flash.c index 2e1720a..31b2c1a 100644 --- a/src/flash.c +++ b/src/flash.c @@ -581,6 +581,7 @@ flash_cnt123_clear (const uint8_t **addr_p) } +#if defined(CERTDO_SUPPORT) static int flash_check_blank (const uint8_t *page, int size) { @@ -592,17 +593,16 @@ flash_check_blank (const uint8_t *page, int size) return 1; } - +#endif #define FLASH_CH_CERTIFICATE_SIZE 2048 int flash_erase_binary (uint8_t file_id) { - const uint8_t *p; - +#if defined(CERTDO_SUPPORT) if (file_id == FILEID_CH_CERTIFICATE) { - p = &ch_certificate_start; + const uint8_t *p = &ch_certificate_start; if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0) { flash_erase_page ((uint32_t)p); @@ -614,6 +614,9 @@ flash_erase_binary (uint8_t file_id) return 0; } else +#else + (void)file_id; +#endif return -1; } @@ -625,12 +628,15 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t maxsize; const uint8_t *p; +#if defined(CERTDO_SUPPORT) if (file_id == FILEID_CH_CERTIFICATE) { maxsize = FLASH_CH_CERTIFICATE_SIZE; p = &ch_certificate_start; } - else if (file_id == FILEID_SERIAL_NO) + else +#endif + if (file_id == FILEID_SERIAL_NO) { maxsize = 6; p = &openpgpcard_aid[8]; diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 121f47c..7bc613a 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -115,6 +115,7 @@ SECTIONS PROVIDE(end = .); _end = .; +@CERTDO_SUPPORT_START@ .gnuk_ch_certificate : { . = ALIGN (@FLASH_PAGE_SIZE@); @@ -123,6 +124,7 @@ SECTIONS . += 1920; . = ALIGN (@FLASH_PAGE_SIZE@); } > flash =0xffffffff +@CERTDO_SUPPORT_END@ .gnuk_flash : { diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 13cc88c..cd9ab77 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1241,6 +1241,7 @@ copy_do (const struct do_table_entry *do_p, int with_tag) void gpg_do_get_data (uint16_t tag, int with_tag) { +#if defined(CERTDO_SUPPORT) if (tag == GPG_DO_CH_CERTIFICATE) { res_APDU_pointer = &ch_certificate_start; @@ -1255,6 +1256,7 @@ gpg_do_get_data (uint16_t tag, int with_tag) res_APDU_size += 4 + 2; } else +#endif { const struct do_table_entry *do_p = get_do_entry (tag); From 3074058ff7736c45a22f255d83b4e39cafaa0960 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 22 Dec 2011 17:10:41 +0900 Subject: [PATCH 038/300] more fix to CERTDO_SUPPORT --- ChangeLog | 5 +++++ src/openpgp-do.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d6704b..f5cf0b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-22 Niibe Yutaka + + * src/openpgp-do.c (extended_capabilities) [CERTDO_SUPPORT]: + conditionalize. + 2011-12-21 Niibe Yutaka * src/openpgp-do.c (gpg_do_get_data) [CERTDO_SUPPORT]: ifdef out. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index cd9ab77..c297939 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -98,14 +98,18 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ 0x00, 0x00, /* Max get challenge */ +#ifdef CERTDO_SUPPORT 0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/ +#else + 0x00, 0x00, +#endif /* Max. length of command data */ (MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff), /* Max. length of response data */ -#if 0 - (MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff), -#else +#ifdef CERTDO_SUPPORT 0x08, 0x00, /* the case of cardholder ceritificate */ +#else + (MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff), #endif }; From c53afe1f96c4d8fa28a5c29aa01c4bd06ac66f80 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 27 Dec 2011 10:34:24 +0900 Subject: [PATCH 039/300] fix pinpad-test.py --- tool/pinpad-test.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 88f65dd..4492cc4 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -78,8 +78,10 @@ class Card(object): def cmd_select_openpgp(self): apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] response, sw1, sw2 = self.connection.transmit(apdu) - if not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, "cmd_select_openpgp" + if sw1 == 0x61: # More data + response, sw1, sw2 = self.connection.transmit([0x00, 0xc0, 0, 0, sw2]) + elif not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("cmd_select_openpgp %02x %02x" % (sw1, sw2)) def possibly_add_dummy_byte(self): if self.another_byte: @@ -112,7 +114,7 @@ class Card(object): if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("cmd_verify_pinpad %02x %02x" % (sw1, sw2)) - def send_modify_pinpad(self, adpu, single_step, command): + def send_modify_pinpad(self, apdu, single_step, command): if self.modify_ioctl == -1: raise ValueError, "Not supported" pin_modify = [ 0x00, # bTimerOut @@ -194,7 +196,7 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps): print "Please input New User's PIN twice" else: print "Please input New Admin's PIN twice" - card.cmd_change_reference_data_pinpad(self, who, True) + card.cmd_change_reference_data_pinpad(who, True) else: if who == BY_USER: print "Please input User's PIN" @@ -202,7 +204,7 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps): else: print "Please input Admin's PIN" print "and New Admin's PIN twice" - card.cmd_change_reference_data_pinpad(self, who, False) + card.cmd_change_reference_data_pinpad(who, False) elif method == "unblock": # It's always by single step if who == BY_USER: @@ -227,18 +229,18 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps): def print_usage(): print "pinpad-test: testing pinentry of PC/SC card reader" - print "\thelp:" - print "\t\t--help:\t\tthis message" - print "\tmethod:\t\t\t\t\t\t\t\t[verify]" - print "\t\t--verify:\tverify PIN" - print "\t\t--change:\tchange PIN (old PIN, new PIN twice)" - print "\t\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)" - print "\t\t--unblock:\tunblock PIN (admin PIN or resetcode, new PIN twice)" - print "\t\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)" - print "\toptions:" - print "\t\t--admin:\tby administrator\t\t\t[False]" - print "\t\t--add:\t\tadd a dummy byte at the end of APDU\t[False]" - print "\t\t--pinmax:\tspecify maximum length of PIN\t\t[15]" + print " help:" + print "\t--help:\t\tthis message" + print " method:\t\t\t\t\t\t\t[verify]" + print "\t--verify:\tverify PIN" + print "\t--change:\tchange PIN (old PIN, new PIN twice)" + print "\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)" + print "\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)" + print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)" + print " options:" + print "\t--admin:\tby administrator\t\t\t[False]" + print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]" + print "\t--pinmax:\tspecify maximum length of PIN\t\t[15]" print "EXAMPLES:" print " $ pinpad-test # verify user's PIN " print " $ pinpad-test --admin # verify admin's PIN " From 60c1fe47ce111a388d10b8ad0c672239b9fc5cb1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 27 Dec 2011 14:10:39 +0900 Subject: [PATCH 040/300] fix pinpad-test.py --- tool/pinpad-test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 4492cc4..592e10b 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -286,4 +286,6 @@ if __name__ == '__main__': raise ValueError, option main(who, method, add_a_byte, pinmax, change_by_two_steps) -# 69 82: security error: pin doesn't match +# 69 82: Security status not satisfied: pin doesn't match +# 69 85: Conditions of use not satisfied +# 6b 00: Wrong parameters P1-P2 From 48d89973c64b7cde5c35f1fe2428766d1080ae41 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 28 Dec 2011 12:27:16 +0900 Subject: [PATCH 041/300] fixed long standing bug of ZLP --- ChangeLog | 7 +++++++ NEWS | 8 ++++++++ src/usb-icc.c | 50 ++++++++++++++++++++++++++++++-------------------- src/usb_prop.c | 2 ++ 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index f5cf0b6..2a5d7f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-28 Niibe Yutaka + + * src/usb_prop.c (msc_lun_info) [PINPAD_DND_SUPPORT]: ifdef-out. + + * src/usb-icc.c (EP2_OUT_Callback): Fix apdu size == 49 bug, + we don't assume host sends ZLP (But accepts ZLP, just in case). + 2011-12-22 Niibe Yutaka * src/openpgp-do.c (extended_capabilities) [CERTDO_SUPPORT]: diff --git a/NEWS b/NEWS index 8928329..dd38543 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,14 @@ Gnuk NEWS - User visible changes Released 2012-01-XX, by NIIBE Yutaka +** USB CCID/ICCD low level bug is fixed +When the size of command APDU data is just 49, the lower level packet +size is 64. This is maximum size of BULK-OUT transfer packet, and +caused trouble in the past implementations. Example is setting url +(0x5f50) as: http://www.gniibe.org/adpu-string-size-is-just-49 +This is because the past implementations expect ZLP (zero size +packet). Now, it has been fixed. You can use any size. + ** CERT.3 Data Object (0x7f21) is now optional As there's no valid use case for this data object and it does not work as current version of GnuPG, this is now optional feature. diff --git a/src/usb-icc.c b/src/usb-icc.c index 0258930..a027bab 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -169,12 +169,31 @@ void EP2_OUT_Callback (void) { int len; + struct icc_header *icc_header; + int data_len_so_far; + int data_len; len = USB_SIL_Read (EP2_OUT, icc_next_p); + if (len == 0) + { /* Just ignore Zero Length Packet (ZLP), if any */ + SetEPRxValid (ENDP2); + return; + } - if (len == USB_LL_BUF_SIZE) /* The sequence of transactions continues */ + icc_next_p += len; + + if (icc_chain_p) + icc_header = (struct icc_header *)icc_chain_p; + else + icc_header = (struct icc_header *)icc_buffer; + + data_len = icc_header->data_len; /* NOTE: We're little endian */ + data_len_so_far = (icc_next_p - (uint8_t *)icc_header) - ICC_MSG_HEADER_SIZE; + + if (len == USB_LL_BUF_SIZE + && data_len != data_len_so_far) + /* The sequence of transactions continues */ { - icc_next_p += USB_LL_BUF_SIZE; SetEPRxValid (ENDP2); if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE) /* No room to receive any more */ @@ -186,27 +205,18 @@ EP2_OUT_Callback (void) * (and discard the whole block) */ } + + /* + * NOTE: It is possible a transaction may stall when the size of + * BULK_OUT transaction it's bigger than USB_BUF_SIZE and stops + * with just USB_LL_BUF_SIZE packet. Device will remain waiting + * another packet. + */ } else /* Finished */ { - struct icc_header *icc_header; - int data_len; - - icc_next_p += len; - if (icc_chain_p) - { - icc_header = (struct icc_header *)icc_chain_p; - icc_data_size = (icc_next_p - icc_chain_p) - ICC_MSG_HEADER_SIZE; - } - else - { - icc_header = (struct icc_header *)icc_buffer; - icc_data_size = (icc_next_p - icc_buffer) - ICC_MSG_HEADER_SIZE; - } - - /* NOTE: We're little endian, nothing to convert */ - data_len = icc_header->data_len; - icc_seq = icc_header->seq; + icc_data_size = data_len_so_far; + icc_seq = icc_header->seq; /* NOTE: We're little endian */ if (icc_data_size != data_len) { diff --git a/src/usb_prop.c b/src/usb_prop.c index c063a28..454ee0b 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -288,6 +288,7 @@ gnuk_data_rates (uint16_t len) return (uint8_t *)data_rate_table; } +#if defined(PINPAD_DND_SUPPORT) static const uint8_t lun_table[] = { 0, 0, 0, 0, }; static uint8_t * msc_lun_info (uint16_t len) @@ -300,6 +301,7 @@ msc_lun_info (uint16_t len) return (uint8_t *)lun_table; } +#endif static RESULT gnuk_setup_with_data (uint8_t RequestNo) From 121df700447fe16cec4445749a37511cbd609408 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 28 Dec 2011 22:16:14 +0900 Subject: [PATCH 042/300] fix long standing bug of RxCount setting for buffer bound (was bug in STmicro's software) --- ChangeLog | 7 +++++++ STM32_USB-FS-Device_Driver/src/usb_core.c | 3 --- src/usb_msc.c | 4 ---- src/usb_prop.c | 20 +++++++++++++++++--- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a5d7f3..f01793c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2011-12-28 Niibe Yutaka + * src/usb_prop.c (SetEPRxCount_allocated_size): New. + (gnuk_device_reset): Use SetEPRxCount_allocated_size. + * src/usb_msc.c (usb_start_receive): Don't set RxCount register + here. + * STM32_USB-FS-Device_Driver/src/usb_core.c (Standard_ClearFeature) + (Post0_Process): Don't need to set RxCount register. + * src/usb_prop.c (msc_lun_info) [PINPAD_DND_SUPPORT]: ifdef-out. * src/usb-icc.c (EP2_OUT_Callback): Fix apdu size == 49 bug, diff --git a/STM32_USB-FS-Device_Driver/src/usb_core.c b/STM32_USB-FS-Device_Driver/src/usb_core.c index 8fc2963..8220ef3 100644 --- a/STM32_USB-FS-Device_Driver/src/usb_core.c +++ b/STM32_USB-FS-Device_Driver/src/usb_core.c @@ -308,7 +308,6 @@ RESULT Standard_ClearFeature(void) if (Related_Endpoint == ENDP0) { /* After clear the STALL, enable the default endpoint receiver */ - SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize); _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); } else @@ -1019,8 +1018,6 @@ uint8_t Post0_Process(void) USB_OTG_EP *ep; #endif /* STM32F10X_CL */ - SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); - if (pInformation->ControlState == STALLED) { vSetEPRxStatus(EP_RX_STALL); diff --git a/src/usb_msc.c b/src/usb_msc.c index 77836b9..1e8bded 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -118,10 +118,6 @@ static void usb_start_receive (uint8_t *p, size_t n) ep7_out.rxbuf = p; ep7_out.rxsize = n; ep7_out.rxcnt = 0; - if (n < ENDP_MAX_SIZE) - SetEPRxCount (ENDP7, n); - else - SetEPRxCount (ENDP7, ENDP_MAX_SIZE); SetEPRxValid (ENDP7); } diff --git a/src/usb_prop.c b/src/usb_prop.c index 454ee0b..a0067bb 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -41,6 +41,19 @@ #endif +void +SetEPRxCount_allocated_size (uint8_t bEpNum, uint16_t wCount) +{ /* Assume wCount is even */ + uint16_t value; + + if (wCount < 62) + value = (wCount & 0x3e) << 9; + else + value = 0x8000 | (((wCount >> 5) - 1) << 10); + + SetEPRxCount (bEpNum, value); +} + static void gnuk_device_init (void) { @@ -75,7 +88,7 @@ gnuk_device_reset (void) SetEPRxAddr (ENDP0, ENDP0_RXADDR); SetEPTxAddr (ENDP0, ENDP0_TXADDR); Clear_Status_Out (ENDP0); - SetEPRxCount (ENDP0, GNUK_MAX_PACKET_SIZE); + SetEPRxCount_allocated_size (ENDP0, GNUK_MAX_PACKET_SIZE); SetEPRxValid (ENDP0); /* Initialize Endpoint 1 */ @@ -87,7 +100,7 @@ gnuk_device_reset (void) /* Initialize Endpoint 2 */ SetEPType (ENDP2, EP_BULK); SetEPRxAddr (ENDP2, ENDP2_RXADDR); - SetEPRxCount (ENDP2, GNUK_MAX_PACKET_SIZE); + SetEPRxCount_allocated_size (ENDP2, GNUK_MAX_PACKET_SIZE); SetEPRxStatus (ENDP2, EP_RX_VALID); SetEPTxStatus (ENDP2, EP_TX_DIS); @@ -107,7 +120,7 @@ gnuk_device_reset (void) /* Initialize Endpoint 5 */ SetEPType (ENDP5, EP_BULK); SetEPRxAddr (ENDP5, ENDP5_RXADDR); - SetEPRxCount (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE); + SetEPRxCount_allocated_size (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE); SetEPRxStatus (ENDP5, EP_RX_VALID); SetEPTxStatus (ENDP5, EP_TX_DIS); #endif @@ -122,6 +135,7 @@ gnuk_device_reset (void) /* Initialize Endpoint 7 */ SetEPType (ENDP7, EP_BULK); SetEPRxAddr (ENDP7, ENDP7_RXADDR); + SetEPRxCount_allocated_size (ENDP7, 64); SetEPRxStatus (ENDP7, EP_RX_STALL); SetEPTxStatus (ENDP7, EP_TX_DIS); #endif From 18f3e72c32c29b20357fe4df9178bfa77bb4fcba Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 4 Jan 2012 09:32:41 +0900 Subject: [PATCH 043/300] fix pinpad-test.py for --add --- tool/pinpad-test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 592e10b..b99aacb 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -107,7 +107,8 @@ class Card(object): 0x00, # bTeoPrologue[1] 0x00 # bTeoPrologue[2] ] - pin_verify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte() + apdu += self.possibly_add_dummy_byte() + pin_verify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.verify_ioctl,pin_verify) sw1 = data[0] sw2 = data[1] @@ -138,7 +139,8 @@ class Card(object): 0x00, # bTeoPrologue[1] 0x00 # bTeoPrologue[2] ] - pin_modify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte() + apdu += self.possibly_add_dummy_byte() + pin_modify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.modify_ioctl,pin_modify) sw1 = data[0] sw2 = data[1] @@ -286,6 +288,9 @@ if __name__ == '__main__': raise ValueError, option main(who, method, add_a_byte, pinmax, change_by_two_steps) +# Failure +# 67 00: Wrong length; no further indication # 69 82: Security status not satisfied: pin doesn't match # 69 85: Conditions of use not satisfied # 6b 00: Wrong parameters P1-P2 + From 35a62354aef7b63f3ea60d559b4642b36b407a40 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 4 Jan 2012 11:57:19 +0900 Subject: [PATCH 044/300] pinpad-test.py: add --pinmin, --unblock2, and --put2 --- tool/pinpad-test.py | 117 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 22 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index b99aacb..ca808e2 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -30,14 +30,20 @@ from smartcard.CardType import AnyCardType from smartcard.CardRequest import CardRequest from smartcard.util import toHexString +from getpass import getpass + CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400) FEATURE_VERIFY_PIN_DIRECT = 0x06 FEATURE_MODIFY_PIN_DIRECT = 0x07 BY_ADMIN = 3 BY_USER = 1 +PIN_MIN_DEFAULT = 6 # min of OpenPGP card PIN_MAX_DEFAULT = 15 # max of VASCO DIGIPASS 920 +def s2l(s): + return [ ord(c) for c in s ] + def confirm_pin_setting(single_step): if single_step: return 0x01 # bConfirmPIN: new PIN twice @@ -45,7 +51,7 @@ def confirm_pin_setting(single_step): return 0x03 # bConfirmPIN: old PIN and new PIN twice class Card(object): - def __init__(self, add_a_byte, pinmax): + def __init__(self, add_a_byte, pinmin, pinmax): cardtype = AnyCardType() cardrequest = CardRequest(timeout=1, cardType=cardtype) cardservice = cardrequest.waitforcard() @@ -53,6 +59,7 @@ class Card(object): self.verify_ioctl = -1 self.modify_ioctl = -1 self.another_byte = add_a_byte + self.pinmin = pinmin self.pinmax = pinmax def get_features(self): @@ -97,7 +104,7 @@ class Card(object): 0x00, # bmPINBlockString 0x00, # bmPINLengthFormat self.pinmax, # wPINMaxExtraDigit Low (PINmax) - 1, # wPINMaxExtraDigit High (PINmin) + self.pinmin, # wPINMaxExtraDigit High (PINmin) 0x02, # bEntryValidationCondition 0x01, # bNumberMessage 0x00, # wLangId Low @@ -126,7 +133,7 @@ class Card(object): 0x00, # bInsertionOffsetOld 0x00, # bInsertionOffsetNew self.pinmax, # wPINMaxExtraDigit Low (PINmax) - 1, # wPINMaxExtraDigit High (PINmin) + self.pinmin, # wPINMaxExtraDigit High (PINmin) confirm_pin_setting(single_step), 0x02, # bEntryValidationCondition 0x03, # bNumberMessage @@ -147,13 +154,29 @@ class Card(object): if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%s %02x %02x" % (command, sw1, sw2)) + def cmd_reset_retry_counter(self, who, data): + if who == BY_ADMIN: + apdu = [0x00, 0x2c, 0x02, 0x81, len(data) ] + data # BY_ADMIN + else: + apdu = [0x00, 0x2c, 0x00, 0x81, len(data) ] + data # BY_USER with resetcode + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("cmd_reset_retry_counter %02x %02x" % (sw1, sw2)) + # Note: CCID specification doesn't permit this (only 0x20 and 0x24) def cmd_reset_retry_counter_pinpad(self, who): if who == BY_ADMIN: apdu = [0x00, 0x2c, 0x02, 0x81] # BY_ADMIN + self.send_modify_pinpad(apdu, True, "cmd_reset_retry_counter_pinpad") else: apdu = [0x00, 0x2c, 0x00, 0x81] # BY_USER with resetcode - self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad") + self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad") + + def cmd_put_resetcode(self, data): + apdu = [0x00, 0xda, 0x00, 0xd3, len(data) ] + data # BY_ADMIN + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("cmd_put_resetcode %02x %02x" % (sw1, sw2)) # Note: CCID specification doesn't permit this (only 0x20 and 0x24) def cmd_put_resetcode_pinpad(self): @@ -168,11 +191,8 @@ class Card(object): self.send_modify_pinpad(apdu, is_exchange, "cmd_change_reference_data_pinpad") -# "Vasco DIGIPASS 920 [CCID] 00 00" -# "FSIJ Gnuk (0.16-34006F06) 00 00" - -def main(who, method, add_a_byte, pinmax, change_by_two_steps): - card = Card(add_a_byte, pinmax) +def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps): + card = Card(add_a_byte, pinmin, pinmax) card.connection.connect() print "Reader/Token:", card.connection.getReader() @@ -208,20 +228,38 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps): print "and New Admin's PIN twice" card.cmd_change_reference_data_pinpad(who, False) elif method == "unblock": - # It's always by single step - if who == BY_USER: - print "Please input reset code" - print "and New User's PIN twice" + if change_by_two_steps: + # It means using keyboard for new PIN + if who == BY_USER: + resetcode=s2l(getpass("Please input reset code from keyboard: ")) + newpin=s2l(getpass("Please input New User's PIN from keyboard: ")) + card.cmd_reset_retry_counter(who,resetcode+newpin) + else: + print "Please input Admin's PIN" + card.cmd_verify_pinpad(BY_ADMIN) + newpin=s2l(getpass("Please input New User's PIN from keyboard: ")) + card.cmd_reset_retry_counter(who,newpin) + else: + if who == BY_USER: + print "Please input reset code" + print "and New User's PIN twice" + else: + print "Please input Admin's PIN" + card.cmd_verify_pinpad(BY_ADMIN) + print "Please input New User's PIN twice" + card.cmd_reset_retry_counter_pinpad(who) + elif method == "put": + if change_by_two_steps: + # It means using keyboard for new PIN + print "Please input Admin's PIN" + card.cmd_verify_pinpad(BY_ADMIN) + resetcode=s2l(getpass("Please input New Reset Code from keyboard: ")) + card.cmd_put_resetcode(resetcode) else: print "Please input Admin's PIN" - print "and New User's PIN twice" - card.cmd_reset_retry_counter_pinpad(who) - elif method == "put": - # It's always by two steps - print "Please input Admin's PIN" - card.cmd_verify_pinpad(BY_ADMIN) - print "Please input New Reset Code twice" - card.cmd_put_resetcode_pinpad() + card.cmd_verify_pinpad(BY_ADMIN) + print "Please input New Reset Code twice" + card.cmd_put_resetcode_pinpad() else: raise ValueError, method card.connection.disconnect() @@ -238,10 +276,13 @@ def print_usage(): print "\t--change:\tchange PIN (old PIN, new PIN twice)" print "\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)" print "\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)" + print "\t--unblock2:\tunblock PIN (admin PIN:pinpad, new PIN:kbd)" print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)" + print "\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)" print " options:" print "\t--admin:\tby administrator\t\t\t[False]" print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]" + print "\t--pinmin:\tspecify minimum length of PIN\t\t[6]" print "\t--pinmax:\tspecify maximum length of PIN\t\t[15]" print "EXAMPLES:" print " $ pinpad-test # verify user's PIN " @@ -258,6 +299,7 @@ if __name__ == '__main__': who = BY_USER method = "verify" add_a_byte = False + pinmin = PIN_MIN_DEFAULT pinmax = PIN_MAX_DEFAULT change_by_two_steps = False while len(sys.argv) >= 2: @@ -272,13 +314,22 @@ if __name__ == '__main__': change_by_two_steps = True elif option == '--unblock': method = "unblock" + elif option == '--unblock2': + method = "unblock" + change_by_two_steps = True elif option == '--add': add_a_byte = True + elif option == '--pinmin': + pinmin = int(sys.argv[1]) + sys.argv.pop(1) elif option == '--pinmax': pinmax = int(sys.argv[1]) sys.argv.pop(1) elif option == '--put': method = "put" + elif option == '--put2': + method = "put" + change_by_two_steps = True elif option == "verify": method = "verify" elif option == '--help': @@ -286,11 +337,33 @@ if __name__ == '__main__': exit(0) else: raise ValueError, option - main(who, method, add_a_byte, pinmax, change_by_two_steps) + main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps) # Failure # 67 00: Wrong length; no further indication # 69 82: Security status not satisfied: pin doesn't match # 69 85: Conditions of use not satisfied # 6b 00: Wrong parameters P1-P2 +# 6b 80 +# 64 02: PIN different +# "FSIJ Gnuk (0.16-34006F06) 00 00" +# Works well except --change2 + +# "Vasco DIGIPASS 920 [CCID] 00 00" +# OK: --verify +# OK: --verify --admin +# OK: --change +# OK: --change --admin +# FAIL: --change2 fails with 6b 00 +# FAIL: --change2 --admin fails with 6b 00 +# FAIL: --put fails with 6b 80 +# OK: --put2 +# OK: --unblock +# FAIL: --unblock --admin fails with 69 85 +# FAIL: --unblock2 fails with 69 85 +# FAIL: --unblock2 --admin fails with 69 85 + +# Gemalto GemPC Pinpad 00 00 +# It asks users PIN with --add but it results 67 00 +# It seems that it doesn't support variable length PIN From 2c111d0b206059e568ae90cd89d71bf9a3ad1643 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 4 Jan 2012 17:33:34 +0900 Subject: [PATCH 045/300] add result for pinpad-test --- tool/pinpad-test.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index ca808e2..586994e 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -355,15 +355,16 @@ if __name__ == '__main__': # OK: --verify --admin # OK: --change # OK: --change --admin -# FAIL: --change2 fails with 6b 00 -# FAIL: --change2 --admin fails with 6b 00 -# FAIL: --put fails with 6b 80 +# FAIL: --change2 fails with 6b 00 (after input of PIN) +# FAIL: --change2 --admin fails with 6b 00 (after input of PIN) +# FAIL: --put fails with 6b 80 (before input of resetcode) # OK: --put2 # OK: --unblock -# FAIL: --unblock --admin fails with 69 85 +# FAIL: --unblock --admin fails with 69 85 (after input of PIN) # FAIL: --unblock2 fails with 69 85 -# FAIL: --unblock2 --admin fails with 69 85 +# FAIL: --unblock2 --admin fails with 69 85 (after input of PIN) # Gemalto GemPC Pinpad 00 00 # It asks users PIN with --add but it results 67 00 # It seems that it doesn't support variable length PIN +# Firmware version: GemTwRC2-V2.10-GL04 From 885e1c4ecb5a957b05f31ddefefb35049844fc4c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jan 2012 10:12:24 +0900 Subject: [PATCH 046/300] pinpad-test.py: add comment --- tool/pinpad-test.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 586994e..8fc8930 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -347,20 +347,25 @@ if __name__ == '__main__': # 6b 80 # 64 02: PIN different +# General +# OpenPGP card v2 doesn't support CHANGE REFERENCE DATA in exchanging +# mode (with P1 == 01, replacing PIN). +# FAIL: --change2 fails with 6b 00 (after input of PIN) +# FAIL: --change2 --admin fails with 6b 00 (after input of PIN) + # "FSIJ Gnuk (0.16-34006F06) 00 00" # Works well except --change2 +# It could support --put and --unblock, but currently it's disabled. # "Vasco DIGIPASS 920 [CCID] 00 00" # OK: --verify # OK: --verify --admin # OK: --change # OK: --change --admin -# FAIL: --change2 fails with 6b 00 (after input of PIN) -# FAIL: --change2 --admin fails with 6b 00 (after input of PIN) -# FAIL: --put fails with 6b 80 (before input of resetcode) -# OK: --put2 # OK: --unblock # FAIL: --unblock --admin fails with 69 85 (after input of PIN) +# FAIL: --put fails with 6b 80 (before input of resetcode) +# OK: --put2 # FAIL: --unblock2 fails with 69 85 # FAIL: --unblock2 --admin fails with 69 85 (after input of PIN) From 58f8470446880d9e51c845d7cc94be4767a9f6d1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jan 2012 10:13:42 +0900 Subject: [PATCH 047/300] pinpad-test.py: comment change --- tool/pinpad-test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/pinpad-test.py b/tool/pinpad-test.py index 8fc8930..307ad32 100755 --- a/tool/pinpad-test.py +++ b/tool/pinpad-test.py @@ -1,7 +1,7 @@ #! /usr/bin/python """ -pinpad-test.py - a tool to test pinpad support by card reader. +pinpadtest.py - a tool to test variable length pin entry with pinpad Copyright (C) 2011 Free Software Initiative of Japan Author: NIIBE Yutaka From a4e0e673404ae6b003c2445b817149c6f278ce37 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jan 2012 10:14:10 +0900 Subject: [PATCH 048/300] pinpadtest.py: name change --- ChangeLog | 4 ++++ tool/{pinpad-test.py => pinpadtest.py} | 0 2 files changed, 4 insertions(+) rename tool/{pinpad-test.py => pinpadtest.py} (100%) diff --git a/ChangeLog b/ChangeLog index f01793c..ca30a90 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-01-05 Niibe Yutaka + + * tool/pinpadtest.py: Rename from pinpad-test.py. + 2011-12-28 Niibe Yutaka * src/usb_prop.c (SetEPRxCount_allocated_size): New. diff --git a/tool/pinpad-test.py b/tool/pinpadtest.py similarity index 100% rename from tool/pinpad-test.py rename to tool/pinpadtest.py From 41537cc827340f2fa1bcc41cb29ca46b9dc7af76 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jan 2012 15:14:35 +0900 Subject: [PATCH 049/300] check DF name on SELECT command --- ChangeLog | 2 ++ src/openpgp-do.c | 8 +++++--- src/openpgp.c | 13 ++++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca30a90..185631e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-01-05 Niibe Yutaka + * src/openpgp.c (cmd_select_file): Check DF name. + * tool/pinpadtest.py: Rename from pinpad-test.py. 2011-12-28 Niibe Yutaka diff --git a/src/openpgp-do.c b/src/openpgp-do.c index c297939..714a0d0 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -417,10 +417,12 @@ do_kgtime_all (uint16_t tag, int with_tag) } const uint8_t openpgpcard_aid[] = { - 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01, - 0x02, 0x00, /* Version 2.0 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */ + 0xd2, 0x76, /* D: National, 276: DEU ISO 3166-1 */ + 0x00, 0x01, 0x24, /* Registered Application Provider Identifier */ + 0x01, /* Application: OpenPGPcard */ + 0x02, 0x00, /* Version 2.0 */ /* v. id */ /* serial number */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */ }; static int diff --git a/src/openpgp.c b/src/openpgp.c index 9eb7f94..527503e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -529,16 +529,19 @@ cmd_read_binary (void) static void cmd_select_file (void) { - if (cmd_APDU[2] == 4) /* Selection by DF name: it must be OpenPGP card */ + if (cmd_APDU[2] == 4) /* Selection by DF name */ { DEBUG_INFO (" - select DF by name\r\n"); - /* - * P2 == 0, LC=6, name = D2 76 00 01 24 01 - */ + /* name = D2 76 00 01 24 01 */ + if (cmd_APDU[4] != 6 || memcmp (openpgpcard_aid, &cmd_APDU[5], 6) != 0) + { + GPG_NO_FILE() + return; + } file_selection = FILE_DF_OPENPGP; - if (cmd_APDU[3] == 0x0c) /* No FCI */ + if ((cmd_APDU[3] & 0x0c) == 0x0c) /* No FCI */ GPG_SUCCESS (); else { From 6abac73354e84a6a5bd888e5048a531863f40b98 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jan 2012 17:04:00 +0900 Subject: [PATCH 050/300] add an entry for NEWS --- NEWS | 13 +++++++++---- src/openpgp.c | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index dd38543..73df182 100644 --- a/NEWS +++ b/NEWS @@ -4,13 +4,18 @@ Gnuk NEWS - User visible changes Released 2012-01-XX, by NIIBE Yutaka +** ISO 7816 SELECT command behavior is strict now +Old implementations do not check DF name for SELECT command. +This causes some trouble when Gnuk Token is identified as if it were +different card/token. Now, DF name of OpenPGP card is checked. + ** USB CCID/ICCD low level bug is fixed When the size of command APDU data is just 49, the lower level packet size is 64. This is maximum size of BULK-OUT transfer packet, and caused trouble in the past implementations. Example is setting url (0x5f50) as: http://www.gniibe.org/adpu-string-size-is-just-49 -This is because the past implementations expect ZLP (zero size -packet). Now, it has been fixed. You can use any size. +This is because the past implementations expect ZLP (zero length +packet). Now, it has been fixed. You can use any size of string. ** CERT.3 Data Object (0x7f21) is now optional As there's no valid use case for this data object and it does not @@ -22,8 +27,8 @@ configure time. Now, user can cancel pin input by unmounting device before finishing DnD. -** New tool: pinpad-test.py -The tool pinpad-test.py is PC/SC test tool for pinentry of pinpad with +** New tool: pinpadtest.py +The tool pinpadtest.py is PC/SC test tool for pinentry of pinpad with OpenPGP card v2. diff --git a/src/openpgp.c b/src/openpgp.c index 527503e..76d2cf5 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -536,7 +536,7 @@ cmd_select_file (void) /* name = D2 76 00 01 24 01 */ if (cmd_APDU[4] != 6 || memcmp (openpgpcard_aid, &cmd_APDU[5], 6) != 0) { - GPG_NO_FILE() + GPG_NO_FILE () return; } From 11351c8caedb94a0b800eea039ade58f19a4d98d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jan 2012 16:02:53 +0900 Subject: [PATCH 051/300] pinmodify is OK for unblock and put resetcode --- ChangeLog | 5 +++++ src/openpgp.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 185631e..c7f1f61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-01-10 Niibe Yutaka + + * src/openpgp.c (GPGthread): Allow INS_RESET_RETRY_COUNTER and + INS_PUT_DATA for pinentry targets. + 2012-01-05 Niibe Yutaka * src/openpgp.c (cmd_select_file): Check DF name. diff --git a/src/openpgp.c b/src/openpgp.c index 76d2cf5..0974d20 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -966,7 +966,9 @@ GPGthread (void *arg) uint8_t bConfirmPIN = cmd_APDU[4]; uint8_t *p = &cmd_APDU[5]; - if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA) + if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA + && cmd_APDU[1] != INS_RESET_RETRY_COUNTER + && cmd_APDU[1] != INS_PUT_DATA) { GPG_CONDITION_NOT_SATISFIED (); goto done; From 4ee4417fb5e99aac070e6c79f9e66cfd10ce67b3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jan 2012 16:47:48 +0900 Subject: [PATCH 052/300] fix adding semicolon --- src/openpgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openpgp.c b/src/openpgp.c index 0974d20..763b481 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -536,7 +536,7 @@ cmd_select_file (void) /* name = D2 76 00 01 24 01 */ if (cmd_APDU[4] != 6 || memcmp (openpgpcard_aid, &cmd_APDU[5], 6) != 0) { - GPG_NO_FILE () + GPG_NO_FILE (); return; } From 27277e56ee7b75971210b8543d51530a1933ddc0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 12 Jan 2012 10:39:16 +0900 Subject: [PATCH 053/300] update pinpadtest.py --- tool/pinpadtest.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tool/pinpadtest.py b/tool/pinpadtest.py index 307ad32..1993d69 100755 --- a/tool/pinpadtest.py +++ b/tool/pinpadtest.py @@ -3,7 +3,7 @@ """ pinpadtest.py - a tool to test variable length pin entry with pinpad -Copyright (C) 2011 Free Software Initiative of Japan +Copyright (C) 2011, 2012 Free Software Initiative of Japan Author: NIIBE Yutaka This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -53,7 +53,7 @@ def confirm_pin_setting(single_step): class Card(object): def __init__(self, add_a_byte, pinmin, pinmax): cardtype = AnyCardType() - cardrequest = CardRequest(timeout=1, cardType=cardtype) + cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() self.connection = cardservice.connection self.verify_ioctl = -1 @@ -369,7 +369,30 @@ if __name__ == '__main__': # FAIL: --unblock2 fails with 69 85 # FAIL: --unblock2 --admin fails with 69 85 (after input of PIN) +# 0c4b:0500 Reiner SCT Kartensysteme GmbH +# "REINER SCT cyberJack RFID standard (7592671050) 00 00" +# OK: --verify +# OK: --verify --admin +# OK: --change +# OK: --change --admin +# OK: --unblock +# OK: --unblock --admin +# FAIL: --put fails with 69 85 + # Gemalto GemPC Pinpad 00 00 # It asks users PIN with --add but it results 67 00 # It seems that it doesn't support variable length PIN # Firmware version: GemTwRC2-V2.10-GL04 + +# 072f:90d2 Advanced Card Systems, Ltd +# ACS ACR83U 01 00 +# --verify failed with 6b 80 + +# 08e6:34c2 Gemplus +# Gemalto Ezio Shield PinPad 01 00 +# works well +# FAIL: --unblock2 fails with 6d 00 + +# 076b:3821 OmniKey AG CardMan 3821 +# OmniKey CardMan 3821 01 00 +# Works well with --pinmax 31 --pinmin 1 From 00541d7627526e10e754909fe77c873e75c4b550 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 16 Jan 2012 12:17:45 +0900 Subject: [PATCH 054/300] clean up USB API --- ChangeLog | 21 +++++++++++++++++++++ src/stmusb.mk | 2 +- src/usb-icc.c | 31 +++++++++++++------------------ src/usb_lld.c | 1 + src/usb_lld.h | 35 +++++++++++++++++++++++++++++++++++ src/usb_prop.c | 11 +++++++---- 6 files changed, 78 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7f1f61..d62b31f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2012-01-16 Niibe Yutaka + + Adopt new API. + * src/usb-icc.c (EP1_IN_Callback, icc_error, icc_power_on) + (icc_send_status, icc_send_data_block, icc_send_params): Use + usb_lld_write (was: USB_SIL_Write). + (EP2_OUT_Callback): Use usb_lld_get_data_len, usb_lld_rxcpy, + and usb_lld_rx_enable (was: USB_SIL_Read and SetEPRxValid). + (icc_prepare_receive): Use usb_lld_rx_enable. + + * src/stmusb.mk (STMUSBSRC): Dont' include usb_sil.c. + + * src/usb_lld.h (usb_lld_txcpy, usb_lld_tx_enable) + (usb_lld_write, usb_lld_rx_enable, usb_lld_get_data_len) + (usb_lld_rxcpy): New. + + * src/usb_prop.c (SetEPRxCount_allocated_size): Fix the + implementation. (ST's SetEPRxCount is actually meant to + setup allocated size, which is confusing). + (gnuk_device_init): Don't call USB_SIL_Init. + 2012-01-10 Niibe Yutaka * src/openpgp.c (GPGthread): Allow INS_RESET_RETRY_COUNTER and diff --git a/src/stmusb.mk b/src/stmusb.mk index 3d7c954..f0b1b5e 100644 --- a/src/stmusb.mk +++ b/src/stmusb.mk @@ -1,7 +1,7 @@ STMUSBDIR = ../STM32_USB-FS-Device_Driver STMUSBSRCDIR = $(STMUSBDIR)/src STMUSBINCDIR = $(STMUSBDIR)/inc -STMUSBSRC= $(STMUSBSRCDIR)/usb_sil.c \ +STMUSBSRC= \ $(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \ $(STMUSBSRCDIR)/usb_mem.c $(STMUSBSRCDIR)/usb_core.c \ $(STMUSBSRCDIR)/usb_regs.c diff --git a/src/usb-icc.c b/src/usb-icc.c index a027bab..0f8db9c 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -29,6 +29,7 @@ #include "usb_mem.h" #include "hw_config.h" #include "usb_istr.h" +#include "usb_lld.h" #define ICC_SET_PARAMS 0x61 /* non-ICCD command */ #define ICC_POWER_ON 0x62 @@ -131,8 +132,7 @@ EP1_IN_Callback (void) { /* Send the last 0-DATA transcation of Bulk-IN in the transactions */ icc_next_p = NULL; - USB_SIL_Write (EP1_IN, icc_buffer, 0); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, icc_buffer, 0); } else { @@ -146,8 +146,7 @@ EP1_IN_Callback (void) tx_size = &icc_buffer[icc_tx_size] - p; } - USB_SIL_Write (EP1_IN, p, tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, p, tx_size); } } @@ -159,7 +158,7 @@ icc_prepare_receive (int chain) else icc_next_p = icc_buffer; - SetEPRxValid (ENDP2); + usb_lld_rx_enable (ENDP2); } /* @@ -173,10 +172,11 @@ EP2_OUT_Callback (void) int data_len_so_far; int data_len; - len = USB_SIL_Read (EP2_OUT, icc_next_p); + len = usb_lld_get_data_len (ENDP2); + usb_lld_rxcpy (icc_next_p, ENDP2, 0, len); if (len == 0) { /* Just ignore Zero Length Packet (ZLP), if any */ - SetEPRxValid (ENDP2); + usb_lld_rx_enable (ENDP2); return; } @@ -194,7 +194,7 @@ EP2_OUT_Callback (void) && data_len != data_len_so_far) /* The sequence of transactions continues */ { - SetEPRxValid (ENDP2); + usb_lld_rx_enable (ENDP2); if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE) /* No room to receive any more */ { @@ -298,8 +298,7 @@ icc_error (int offset) icc_next_p = NULL; /* This is a single transaction Bulk-IN */ icc_tx_size = ICC_MSG_HEADER_SIZE; - USB_SIL_Write (EP1_IN, icc_reply, icc_tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, icc_reply, icc_tx_size); } static Thread *gpg_thread; @@ -332,8 +331,7 @@ icc_power_on (void) icc_next_p = NULL; /* This is a single transaction Bulk-IN */ icc_tx_size = ICC_MSG_HEADER_SIZE + size_atr; - USB_SIL_Write (EP1_IN, icc_buffer, icc_tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, icc_buffer, icc_tx_size); DEBUG_INFO ("ON\r\n"); return ICC_STATE_WAIT; @@ -367,8 +365,7 @@ icc_send_status (void) icc_next_p = NULL; /* This is a single transaction Bulk-IN */ icc_tx_size = ICC_MSG_HEADER_SIZE; - USB_SIL_Write (EP1_IN, icc_reply, icc_tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, icc_reply, icc_tx_size); #ifdef DEBUG_MORE DEBUG_INFO ("St\r\n"); @@ -428,8 +425,7 @@ icc_send_data_block (int len, uint8_t status, uint8_t chain) else icc_next_p = p + USB_LL_BUF_SIZE; - USB_SIL_Write (EP1_IN, p, tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, p, tx_size); #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif @@ -458,8 +454,7 @@ icc_send_params (void) icc_next_p = NULL; /* This is a single transaction Bulk-IN */ icc_tx_size = ICC_MSG_HEADER_SIZE + 7; - USB_SIL_Write (EP1_IN, icc_buffer, icc_tx_size); - SetEPTxValid (ENDP1); + usb_lld_write (ENDP1, icc_buffer, icc_tx_size); #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif diff --git a/src/usb_lld.c b/src/usb_lld.c index 9429712..97c9f8d 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -1,5 +1,6 @@ #include "ch.h" #include "hal.h" +#include "usb_lib.h" #include "usb_lld.h" extern void USB_Istr (void); diff --git a/src/usb_lld.h b/src/usb_lld.h index 9e0ecfd..58bcbda 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -1,2 +1,37 @@ #define STM32_USB_IRQ_PRIORITY 11 void usb_lld_init (void); + +extern inline void usb_lld_txcpy (const uint8_t *src, + int ep_num, int offset, size_t len) +{ + UserToPMABufferCopy ((uint8_t *)src, GetEPTxAddr (ep_num) + offset, len); +} + +extern inline void usb_lld_tx_enable (int ep_num, size_t len) +{ + SetEPTxCount (ep_num, len); + SetEPTxValid (ep_num); +} + +extern inline void usb_lld_write (uint8_t ep_num, void *buf, size_t len) +{ + UserToPMABufferCopy (buf, GetEPTxAddr (ep_num), len); + SetEPTxCount (ep_num, len); + SetEPTxValid (ep_num); +} + +extern inline void usb_lld_rx_enable (int ep_num) +{ + SetEPRxValid (ep_num); +} + +extern inline int usb_lld_get_data_len (int ep_num) +{ + return GetEPRxCount (ep_num); +} + +extern inline void usb_lld_rxcpy (uint8_t *dst, + int ep_num, int offset, size_t len) +{ + PMAToUserBufferCopy (dst, GetEPRxAddr (ep_num) + offset, len); +} diff --git a/src/usb_prop.c b/src/usb_prop.c index a0067bb..56c0cb3 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -41,17 +41,18 @@ #endif -void +static void SetEPRxCount_allocated_size (uint8_t bEpNum, uint16_t wCount) { /* Assume wCount is even */ + uint32_t *pdwReg = _pEPRxCount (bEpNum); uint16_t value; - if (wCount < 62) + if (wCount <= 62) value = (wCount & 0x3e) << 9; else value = 0x8000 | (((wCount >> 5) - 1) << 10); - SetEPRxCount (bEpNum, value); + *pdwReg = (uint32_t)value; } static void @@ -63,7 +64,9 @@ gnuk_device_init (void) PowerOn (); /* Perform basic device initialization operations */ - USB_SIL_Init (); + _SetISTR (0); + wInterrupt_Mask = IMR_MSK; + _SetCNTR (wInterrupt_Mask); bDeviceState = UNCONNECTED; } From cbb2c6aab536e65dbc607da51dff4791acd76fd0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 16 Jan 2012 13:24:31 +0900 Subject: [PATCH 055/300] clean up USB API 2 --- ChangeLog | 18 +++++++++++++++--- src/main.c | 3 +-- src/usb-icc.c | 4 ++-- src/usb_lld.h | 17 ++++++++++++++++- src/usb_msc.c | 39 ++++++++++++++------------------------- 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index d62b31f..97bf755 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,17 +1,29 @@ 2012-01-16 Niibe Yutaka - Adopt new API. + Adopt new USB API. + * src/usb_msc.c (usb_start_transmit): Use usb_lld_write. + (EP6_IN_Callback): Use usb_lld_tx_data_len and usb_lld_write. + (usb_start_receive): Use usb_lld_rx_enable. + (EP7_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy + and usb_lld_rx_enable + (msc_handle_command): Use usb_lld_stall_rx and usb_lld_stall_tx. + + * src/usb_lld.h (usb_lld_stall_tx, usb_lld_stall_rx) + (usb_lld_tx_data_len): New. + + * src/main.c (STDOUTthread): Use usb_lld_write. + * src/usb-icc.c (EP1_IN_Callback, icc_error, icc_power_on) (icc_send_status, icc_send_data_block, icc_send_params): Use usb_lld_write (was: USB_SIL_Write). - (EP2_OUT_Callback): Use usb_lld_get_data_len, usb_lld_rxcpy, + (EP2_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy, and usb_lld_rx_enable (was: USB_SIL_Read and SetEPRxValid). (icc_prepare_receive): Use usb_lld_rx_enable. * src/stmusb.mk (STMUSBSRC): Dont' include usb_sil.c. * src/usb_lld.h (usb_lld_txcpy, usb_lld_tx_enable) - (usb_lld_write, usb_lld_rx_enable, usb_lld_get_data_len) + (usb_lld_write, usb_lld_rx_enable, usb_lld_rx_data_len) (usb_lld_rxcpy): New. * src/usb_prop.c (SetEPRxCount_allocated_size): Fix the diff --git a/src/main.c b/src/main.c index 4b9ef8a..c7460a8 100644 --- a/src/main.c +++ b/src/main.c @@ -132,8 +132,7 @@ STDOUTthread (void *arg) chEvtClear (EV_TX_READY); - USB_SIL_Write (EP3_IN, buffer_in, count_in); - SetEPTxValid (ENDP3); + usb_lld_write (ENDP3, buffer_in, count_in); chEvtWaitOne (EV_TX_READY); } diff --git a/src/usb-icc.c b/src/usb-icc.c index 0f8db9c..daa8752 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -1,7 +1,7 @@ /* * usb-icc.c -- USB CCID/ICCD protocol handling * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -172,7 +172,7 @@ EP2_OUT_Callback (void) int data_len_so_far; int data_len; - len = usb_lld_get_data_len (ENDP2); + len = usb_lld_rx_data_len (ENDP2); usb_lld_rxcpy (icc_next_p, ENDP2, 0, len); if (len == 0) { /* Just ignore Zero Length Packet (ZLP), if any */ diff --git a/src/usb_lld.h b/src/usb_lld.h index 58bcbda..0ec00d3 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -1,6 +1,21 @@ #define STM32_USB_IRQ_PRIORITY 11 void usb_lld_init (void); +extern inline void usb_lld_stall_tx (int ep_num) +{ + SetEPTxStatus (ep_num, EP_TX_STALL); +} + +extern inline void usb_lld_stall_rx (int ep_num) +{ + SetEPRxStatus (ep_num, EP_RX_STALL); +} + +extern inline int usb_lld_tx_data_len (int ep_num) +{ + return GetEPTxCount (ep_num); +} + extern inline void usb_lld_txcpy (const uint8_t *src, int ep_num, int offset, size_t len) { @@ -25,7 +40,7 @@ extern inline void usb_lld_rx_enable (int ep_num) SetEPRxValid (ep_num); } -extern inline int usb_lld_get_data_len (int ep_num) +extern inline int usb_lld_rx_data_len (int ep_num) { return GetEPRxCount (ep_num); } diff --git a/src/usb_msc.c b/src/usb_msc.c index 1e8bded..4147ec6 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -1,7 +1,7 @@ /* * usb_msc.c -- USB Mass Storage Class protocol handling * - * Copyright (C) 2011 Free Software Initiative of Japan + * Copyright (C) 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -26,6 +26,7 @@ #include "config.h" #include "ch.h" #include "gnuk.h" +#include "usb_lld.h" #include "usb_msc.h" struct usb_endp_in { @@ -50,11 +51,6 @@ static Thread *the_thread; static uint8_t msc_state; -static void usb_stall_transmit (void) -{ - SetEPTxStatus (ENDP6, EP_TX_STALL); -} - static void usb_start_transmit (const uint8_t *p, size_t n) { size_t pkt_len = n > ENDP_MAX_SIZE ? ENDP_MAX_SIZE : n; @@ -63,14 +59,13 @@ static void usb_start_transmit (const uint8_t *p, size_t n) ep6_in.txsize = n; ep6_in.txcnt = 0; - USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, pkt_len); - SetEPTxValid (ENDP6); + usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, pkt_len); } /* "Data Transmitted" callback */ void EP6_IN_Callback (void) { - size_t n = (size_t)GetEPTxCount (ENDP6); + size_t n = (size_t)usb_lld_tx_data_len (ENDP6); ep6_in.txbuf += n; ep6_in.txcnt += n; @@ -82,8 +77,7 @@ void EP6_IN_Callback (void) n = ENDP_MAX_SIZE; else n = ep6_in.txsize; - USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, n); - SetEPTxValid (ENDP6); + usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, n); return; } @@ -108,39 +102,34 @@ void EP6_IN_Callback (void) } -static void usb_stall_receive (void) -{ - SetEPRxStatus (ENDP7, EP_RX_STALL); -} - static void usb_start_receive (uint8_t *p, size_t n) { ep7_out.rxbuf = p; ep7_out.rxsize = n; ep7_out.rxcnt = 0; - SetEPRxValid (ENDP7); + usb_lld_rx_enable (ENDP7); } /* "Data Received" call back */ void EP7_OUT_Callback (void) { - size_t n = (size_t)GetEPRxCount (ENDP7); + size_t n = (size_t)usb_lld_rx_data_len (ENDP7); int err = 0; if (n > ep7_out.rxsize) { /* buffer overflow */ err = 1; - SetEPRxCount (ENDP7, ep7_out.rxsize); + n = ep7_out.rxsize; } - n = USB_SIL_Read (EP7_OUT, ep7_out.rxbuf); + usb_lld_rxcpy (ep7_out.rxbuf, ENDP7, 0, n); ep7_out.rxbuf += n; ep7_out.rxcnt += n; ep7_out.rxsize -= n; if (n == ENDP_MAX_SIZE && ep7_out.rxsize != 0) { /* More data to be received */ - SetEPRxValid (ENDP7); + usb_lld_rx_enable (ENDP7); return; } @@ -329,7 +318,7 @@ void msc_handle_command (void) if (msg != RDY_TIMEOUT) { chSysLock (); - usb_stall_receive (); + usb_lld_stall_rx (ENDP7); chSysUnlock (); } return; @@ -341,7 +330,7 @@ void msc_handle_command (void) { msc_state = MSC_ERROR; chSysLock (); - usb_stall_receive (); + usb_lld_stall_rx (ENDP7); chSysUnlock (); return; } @@ -444,8 +433,8 @@ void msc_handle_command (void) { msc_state = MSC_ERROR; chSysLock (); - usb_stall_transmit (); - usb_stall_receive (); + usb_lld_stall_tx (ENDP6); + usb_lld_stall_rx (ENDP7); chSysUnlock (); return; } From 87e4fd50c110538b2a2a50161a5acd03fd01ac66 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 18 Jan 2012 18:59:16 +0900 Subject: [PATCH 056/300] New API between gpg and ccid layer --- ChangeLog | 22 +++ src/call-rsa.c | 11 +- src/gnuk.h | 49 +++++-- src/openpgp-do.c | 20 ++- src/openpgp.c | 230 ++++++++++++------------------- src/usb-icc.c | 244 ++++++++++++++++++++++++++------- tool/gnuk_put_binary.py | 11 +- tool/gnuk_put_binary_libusb.py | 1 - 8 files changed, 352 insertions(+), 236 deletions(-) diff --git a/ChangeLog b/ChangeLog index 97bf755..b18c49b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2012-01-18 Niibe Yutaka + + Clean up API between application layer and CCID layer. + * tool/gnuk_put_binary.py, gnuk_put_binary_libusb.py: Don't append + 0x9000 at the data, any more. + * src/usb-icc.c (icc_data_size, icc_buffer, icc_seq): Make them + internal. + (res_APDU_size, res_APDU_pointer): Removed. + (icc_handle_data, USBthread): Follow new API of struct apdu. + * src/call-rsa.c (rsa_sign, rsa_decrypt): Likewise. + * src/openpgp.c (CLS, INS, P1, P2): New. + (set_res_apdu, cmd_verify, cmd_change_password) + (cmd_reset_user_password, cmd_put_data, cmd_pgp_gakp) + (cmd_read_binary, cmd_select_file, cmd_pso) + (cmd_internal_authenticate, cmd_update_binary, cmd_write_binary) + (process_command_apdu, GPGthread): Follow new API of struct apdu. + * src/openpgp-do.c (gpg_do_get_data, gpg_do_public_key): Follow + new API of struct apdu. + * src/gnuk.h (struct apdu, apdu): New. + (cmd_APDU, icc_data_size, cmd_APDU_size, icc_buffer): Removed. + (res_APDU, res_APDU_size): Use members of struct apdu. + 2012-01-16 Niibe Yutaka Adopt new USB API. diff --git a/src/call-rsa.c b/src/call-rsa.c index 8705d04..cf7530b 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -25,6 +25,7 @@ #include "config.h" #include "ch.h" #include "gnuk.h" +#include "openpgp.h" #include "polarssl/config.h" #include "polarssl/rsa.h" @@ -84,10 +85,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, } else { - res_APDU[RSA_SIGNATURE_LENGTH] = 0x90; - res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00; - res_APDU_size = RSA_SIGNATURE_LENGTH + 2; + res_APDU_size = RSA_SIGNATURE_LENGTH; DEBUG_INFO ("done.\r\n"); + GPG_SUCCESS (); return 0; } } @@ -177,10 +177,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, } else { - res_APDU[output_len] = 0x90; - res_APDU[output_len+1] = 0x00; - res_APDU_size = output_len + 2; + res_APDU_size = output_len; DEBUG_INFO ("done.\r\n"); + GPG_SUCCESS (); return 0; } } diff --git a/src/gnuk.h b/src/gnuk.h index e0d72d6..464e036 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -1,3 +1,17 @@ +/* + * We declare some of libc functions here, because we will + * remove dependency on libc in future, possibly. + */ +extern size_t strlen (const char *s); +extern int strncmp(const char *s1, const char *s2, size_t n); +extern void *memcpy (void *dest, const void *src, size_t n); +extern void *memset (void *s, int c, size_t n); +extern int memcmp (const void *s1, const void *s2, size_t n); +extern void *memmove(void *dest, const void *src, size_t n); + +/* + * Debug functions + */ extern Thread *stdout_thread; #define EV_TX_READY ((eventmask_t)1) @@ -11,16 +25,26 @@ extern void put_binary (const char *s, int len); extern void _write (const char *, int); + /* - * We declare some of libc functions here, because we will - * remove dependency on libc in future. + * Application layer <-> CCID layer data structure */ -extern size_t strlen (const char *s); -extern int strncmp(const char *s1, const char *s2, size_t n); -extern void *memcpy (void *dest, const void *src, size_t n); -extern void *memset (void *s, int c, size_t n); -extern int memcmp (const void *s1, const void *s2, size_t n); -extern void *memmove(void *dest, const void *src, size_t n); +struct apdu { + uint8_t seq; + + /* command APDU */ + uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */ + uint8_t *cmd_apdu_data; + uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */ + uint32_t expected_res_size; /* Ne, calculated by Le field */ + + /* response APDU */ + uint16_t sw; + uint8_t *res_apdu_data; + uint16_t res_apdu_data_len; +}; + +extern struct apdu apdu; #define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */ @@ -38,12 +62,8 @@ extern void *memmove(void *dest, const void *src, size_t n); #define ICC_MSG_HEADER_SIZE 10 -#define cmd_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE]) -#define res_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE]) -extern int icc_data_size; -#define cmd_APDU_size icc_data_size -extern int res_APDU_size; -extern const uint8_t *res_APDU_pointer; +#define res_APDU apdu.res_apdu_data +#define res_APDU_size apdu.res_apdu_data_len /* USB buffer size of LL (Low-level): size of single Bulk transaction */ #define USB_LL_BUF_SIZE 64 @@ -54,7 +74,6 @@ extern const uint8_t *res_APDU_pointer; */ #define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \ / USB_LL_BUF_SIZE * USB_LL_BUF_SIZE) -extern uint8_t icc_buffer[USB_BUF_SIZE]; enum icc_state { diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 714a0d0..47cec3b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1250,16 +1250,13 @@ gpg_do_get_data (uint16_t tag, int with_tag) #if defined(CERTDO_SUPPORT) if (tag == GPG_DO_CH_CERTIFICATE) { - res_APDU_pointer = &ch_certificate_start; - res_APDU_size = ((res_APDU_pointer[2] << 8) | res_APDU_pointer[3]); - if (res_APDU_size == 0xffff) - { - res_APDU_pointer = NULL; - GPG_NO_RECORD (); - } + apdu.res_apdu_data = &ch_certificate_start; + apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]); + if (apdu.res_apdu_data_len == 0xffff) + GPG_NO_RECORD (); else - /* Add length of (tag+len) and status word (0x9000) at the end */ - res_APDU_size += 4 + 2; + /* Add length of (tag+len) */ + apdu.res_apdu_data_len += 4; } else #endif @@ -1278,9 +1275,8 @@ gpg_do_get_data (uint16_t tag, int with_tag) GPG_SECURITY_FAILURE (); else { - *res_p++ = 0x90; - *res_p++ = 0x00; res_APDU_size = res_p - res_APDU; + GPG_SUCCESS (); } } else @@ -1414,8 +1410,8 @@ gpg_do_public_key (uint8_t kk_byte) *res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01; /* Success */ - *res_p++ = 0x90; *res_p++ = 0x00; res_APDU_size = res_p - res_APDU; + GPG_SUCCESS (); } DEBUG_INFO ("done.\r\n"); diff --git a/src/openpgp.c b/src/openpgp.c index 763b481..d73d773 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -29,6 +29,11 @@ #include "polarssl/config.h" #include "polarssl/sha1.h" +#define CLS(a) a.cmd_apdu_head[0] +#define INS(a) a.cmd_apdu_head[1] +#define P1(a) a.cmd_apdu_head[2] +#define P2(a) a.cmd_apdu_head[3] + #define INS_VERIFY 0x20 #define INS_CHANGE_REFERENCE_DATA 0x24 #define INS_PSO 0x2a @@ -64,9 +69,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = { void set_res_apdu (uint8_t sw1, uint8_t sw2) { - res_APDU_size = 2; - res_APDU[0] = sw1; - res_APDU[1] = sw2; + apdu.sw = (sw1 << 8) | sw2; } #define FILE_NONE 0 @@ -117,22 +120,15 @@ static void cmd_verify (void) { int len; - uint8_t p2 = cmd_APDU[3]; + uint8_t p2 = P2 (apdu); int r; - int data_start = 5; const uint8_t *pw; DEBUG_INFO (" - VERIFY\r\n"); DEBUG_BYTE (p2); - len = cmd_APDU[4]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - - pw = &cmd_APDU[data_start]; + len = apdu.cmd_apdu_data_len; + pw = apdu.cmd_apdu_data; if (p2 == 0x81) r = verify_pso_cds (pw, len); @@ -213,8 +209,8 @@ cmd_change_password (void) uint8_t old_ks[KEYSTRING_MD_SIZE]; uint8_t new_ks0[KEYSTRING_MD_SIZE+1]; uint8_t *new_ks = &new_ks0[1]; - uint8_t p1 = cmd_APDU[2]; /* 0: change (old+new), 1: exchange (new) */ - uint8_t p2 = cmd_APDU[3]; + uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */ + uint8_t p2 = P2 (apdu); int len; const uint8_t *pw; const uint8_t *newpw; @@ -225,13 +221,8 @@ cmd_change_password (void) DEBUG_INFO ("Change PW\r\n"); DEBUG_BYTE (who); - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + len = apdu.cmd_apdu_data_len; + pw = apdu.cmd_apdu_data; if (p1 != 0) { @@ -329,7 +320,7 @@ cmd_change_password (void) static void cmd_reset_user_password (void) { - uint8_t p1 = cmd_APDU[2]; + uint8_t p1 = P1 (apdu); int len; const uint8_t *pw; const uint8_t *newpw; @@ -341,13 +332,8 @@ cmd_reset_user_password (void) DEBUG_INFO ("Reset PW1\r\n"); DEBUG_BYTE (p1); - len = cmd_APDU[4]; - pw = &cmd_APDU[5]; - if (len == 0) /* extended length */ - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - pw += 2; - } + len = apdu.cmd_apdu_data_len; + pw = apdu.cmd_apdu_data; if (p1 == 0x00) /* by User with Reseting Code */ { @@ -469,17 +455,9 @@ cmd_put_data (void) if (file_selection != FILE_DF_OPENPGP) GPG_NO_RECORD(); - tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]); - data = &cmd_APDU[5]; - - len = cmd_APDU_size - 5; - if (len >= 256) - /* extended Lc */ - { - data += 2; - len -= 2; - } - + tag = ((P1 (apdu)<<8) | P2 (apdu)); + len = apdu.cmd_apdu_data_len; + data = apdu.cmd_apdu_data; gpg_do_put_data (tag, data, len); } @@ -487,16 +465,11 @@ static void cmd_pgp_gakp (void) { DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n"); - DEBUG_BYTE (cmd_APDU[2]); + DEBUG_BYTE (P1 (apdu)); - if (cmd_APDU[2] == 0x81) + if (P1 (apdu) == 0x81) /* Get public key */ - { - if (cmd_APDU[4] == 0) - gpg_do_public_key (cmd_APDU[7]); - else - gpg_do_public_key (cmd_APDU[5]); - } + gpg_do_public_key (apdu.cmd_apdu_data[0]); else { /* Generate key pair */ if (!ac_check_status (AC_ADMIN_AUTHORIZED)) @@ -514,7 +487,7 @@ cmd_read_binary (void) if (file_selection == FILE_EF_SERIAL) { - if (cmd_APDU[3] >= 6) + if (P2 (apdu) >= 6) GPG_BAD_P0_P1 (); else { @@ -529,19 +502,23 @@ cmd_read_binary (void) static void cmd_select_file (void) { - if (cmd_APDU[2] == 4) /* Selection by DF name */ + if (P1 (apdu) == 4) /* Selection by DF name */ { DEBUG_INFO (" - select DF by name\r\n"); /* name = D2 76 00 01 24 01 */ - if (cmd_APDU[4] != 6 || memcmp (openpgpcard_aid, &cmd_APDU[5], 6) != 0) + if (apdu.cmd_apdu_data_len != 6 + || memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0) { + DEBUG_WORD (apdu.cmd_apdu_data_len); + DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); + GPG_NO_FILE (); return; } file_selection = FILE_DF_OPENPGP; - if ((cmd_APDU[3] & 0x0c) == 0x0c) /* No FCI */ + if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */ GPG_SUCCESS (); else { @@ -553,8 +530,8 @@ cmd_select_file (void) res_APDU_size += 2; } } - else if (cmd_APDU[4] == 2 - && cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02) + else if (apdu.cmd_apdu_data_len == 2 + && apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02) { DEBUG_INFO (" - select 0x2f02 EF\r\n"); /* @@ -563,11 +540,11 @@ cmd_select_file (void) GPG_SUCCESS (); file_selection = FILE_EF_SERIAL; } - else if (cmd_APDU[4] == 2 - && cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00) + else if (apdu.cmd_apdu_data_len == 2 + && apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00) { DEBUG_INFO (" - select ROOT MF\r\n"); - if (cmd_APDU[3] == 0x0c) + if (P2 (apdu) == 0x0c) { GPG_SUCCESS (); } @@ -575,12 +552,11 @@ cmd_select_file (void) { int len = sizeof (select_file_TOP_result); - res_APDU_size = 2 + len; + res_APDU_size = 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; + GPG_SUCCESS (); } file_selection = FILE_MF; @@ -598,7 +574,7 @@ cmd_select_file (void) static void cmd_get_data (void) { - uint16_t tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]); + uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu)); DEBUG_INFO (" - Get Data\r\n"); @@ -611,21 +587,14 @@ cmd_get_data (void) static void cmd_pso (void) { - int len = cmd_APDU[4]; - int data_start = 5; + int len = apdu.cmd_apdu_data_len; int r; - if (len == 0) - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - DEBUG_INFO (" - PSO: "); DEBUG_WORD ((uint32_t)&r); - DEBUG_BINARY (cmd_APDU, cmd_APDU_size); + DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); - if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a) + if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a) { if (!ac_check_status (AC_PSO_CDS_AUTHORIZED)) { @@ -634,24 +603,24 @@ cmd_pso (void) return; } - if (cmd_APDU_size != 7 + 34 + 2 /* MD5 */ - /* Header (with Extended Lc)=7, size of digestInfo, and Le=2-byte */ - && cmd_APDU_size != 7 + 35 + 2 /* SHA1 / RIPEMD-160 */ - && cmd_APDU_size != 7 + 47 + 2 /* SHA224 */ - && cmd_APDU_size != 7 + 51 + 2 /* SHA256 */ - && cmd_APDU_size != 7 + 67 + 2 /* SHA384 */ - && cmd_APDU_size != 7 + 83 + 2) /* SHA512 */ + /* Check size of digestInfo */ + if (len != 34 /* MD5 */ + && len != 35 /* SHA1 / RIPEMD-160 */ + && len != 47 /* SHA224 */ + && len != 51 /* SHA256 */ + && len != 67 /* SHA384 */ + && len != 83) /* SHA512 */ { DEBUG_INFO (" wrong length: "); - DEBUG_SHORT (cmd_APDU_size); + DEBUG_SHORT (len); GPG_ERROR (); } else { - DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */ + DEBUG_SHORT (len); DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN); - r = rsa_sign (&cmd_APDU[data_start], res_APDU, len, + r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_SIGNING]); if (r < 0) { @@ -663,7 +632,7 @@ cmd_pso (void) gpg_increment_digital_signature_counter (); } } - else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86) + else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86) { DEBUG_SHORT (len); DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN); @@ -676,9 +645,8 @@ cmd_pso (void) } /* Skip padding 0x00 */ - data_start++; len--; - r = rsa_decrypt (&cmd_APDU[data_start], res_APDU, len, + r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, &kd[GPG_KEY_FOR_DECRYPTION]); if (r < 0) GPG_ERROR (); @@ -686,9 +654,9 @@ cmd_pso (void) else { DEBUG_INFO (" - ??"); - DEBUG_BYTE (cmd_APDU[2]); + DEBUG_BYTE (P1 (apdu)); DEBUG_INFO (" - ??"); - DEBUG_BYTE (cmd_APDU[3]); + DEBUG_BYTE (P2 (apdu)); GPG_ERROR (); } @@ -698,19 +666,12 @@ cmd_pso (void) static void cmd_internal_authenticate (void) { - int len = cmd_APDU[4]; - int data_start = 5; + int len = apdu.cmd_apdu_data_len; int r; - if (len == 0) - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n"); - if (cmd_APDU[2] == 0x00 && cmd_APDU[3] == 0x00) + if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00) { DEBUG_SHORT (len); @@ -721,7 +682,7 @@ cmd_internal_authenticate (void) return; } - r = rsa_sign (&cmd_APDU[data_start], res_APDU, len, + r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_AUTHENTICATION]); if (r < 0) GPG_ERROR (); @@ -729,9 +690,9 @@ cmd_internal_authenticate (void) else { DEBUG_INFO (" - ??"); - DEBUG_BYTE (cmd_APDU[2]); + DEBUG_BYTE (P1 (apdu)); DEBUG_INFO (" - ??"); - DEBUG_BYTE (cmd_APDU[3]); + DEBUG_BYTE (P2 (apdu)); GPG_ERROR (); } @@ -742,17 +703,10 @@ cmd_internal_authenticate (void) static void cmd_update_binary (void) { - int len = cmd_APDU[4]; - int data_start = 5; + int len = apdu.cmd_apdu_data_len; uint16_t offset; int r; - if (len == 0) - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - DEBUG_INFO (" - UPDATE BINARY\r\n"); if (!ac_check_status (AC_ADMIN_AUTHORIZED)) @@ -762,10 +716,10 @@ cmd_update_binary (void) return; } - if ((cmd_APDU[2] & 0x80)) - if ((cmd_APDU[2] & 0x7f) <= FILEID_RANDOM) + if ((P1 (apdu) & 0x80)) + if ((P1 (apdu) & 0x7f) <= FILEID_RANDOM) { - file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f); + file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f); r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE); if (r < 0) { @@ -790,14 +744,14 @@ cmd_update_binary (void) return; } - offset = (cmd_APDU[2] << 8) | cmd_APDU[3]; + offset = (P1 (apdu) << 8) | P2 (apdu); } DEBUG_SHORT (len); DEBUG_SHORT (offset); r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE, - &cmd_APDU[data_start], len, offset); + apdu.cmd_apdu_data, len, offset); if (r < 0) { DEBUG_INFO ("memory error.\r\n"); @@ -813,17 +767,10 @@ cmd_update_binary (void) static void cmd_write_binary (void) { - int len = cmd_APDU[4]; - int data_start = 5; + int len = apdu.cmd_apdu_data_len; uint16_t offset; int r; - if (len == 0) - { - len = (cmd_APDU[5]<<8) | cmd_APDU[6]; - data_start = 7; - } - DEBUG_INFO (" - WRITE BINARY\r\n"); if (!ac_check_status (AC_ADMIN_AUTHORIZED)) @@ -833,10 +780,10 @@ cmd_write_binary (void) return; } - if ((cmd_APDU[2] & 0x80)) - if ((cmd_APDU[2] & 0x7f) <= FILEID_SERIAL_NO) + if ((P1 (apdu) & 0x80)) + if ((P1 (apdu) & 0x7f) <= FILEID_SERIAL_NO) { - file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f); + file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f); offset = 0; } else @@ -854,14 +801,14 @@ cmd_write_binary (void) return; } - offset = (cmd_APDU[2] << 8) | cmd_APDU[3]; + offset = (P1 (apdu) << 8) | P2 (apdu); } DEBUG_SHORT (len); DEBUG_SHORT (offset); r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE, - &cmd_APDU[data_start], len, offset); + apdu.cmd_apdu_data, len, offset); if (r < 0) { DEBUG_INFO ("memory error.\r\n"); @@ -901,7 +848,7 @@ static void process_command_apdu (void) { int i; - uint8_t cmd = cmd_APDU[1]; + uint8_t cmd = INS (apdu); for (i = 0; i < NUM_CMDS; i++) if (cmds[i].command == cmd) @@ -935,12 +882,10 @@ GPGthread (void *arg) DEBUG_INFO ("GPG!: "); - res_APDU_pointer = NULL; - if (m == EV_VERIFY_CMD_AVAILABLE) { #if defined(PINPAD_SUPPORT) - if (cmd_APDU[1] != INS_VERIFY) + if (INS (apdu) != INS_VERIFY) { GPG_CONDITION_NOT_SATISFIED (); goto done; @@ -952,9 +897,8 @@ GPGthread (void *arg) GPG_ERROR (); goto done; } - memcpy (&cmd_APDU[5], pin_input_buffer, pw_len); - cmd_APDU[4] = pw_len; - icc_data_size = 5 + pw_len; + memcpy (apdu.cmd_apdu_data, pin_input_buffer, pw_len); + apdu.cmd_apdu_data_len = pw_len; #else GPG_ERROR (); goto done; @@ -963,12 +907,12 @@ GPGthread (void *arg) else if (m == EV_MODIFY_CMD_AVAILABLE) { #if defined(PINPAD_SUPPORT) - uint8_t bConfirmPIN = cmd_APDU[4]; - uint8_t *p = &cmd_APDU[5]; + uint8_t bConfirmPIN = apdu.cmd_apdu_data[5]; + uint8_t *p = apdu.cmd_apdu_data; - if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA - && cmd_APDU[1] != INS_RESET_RETRY_COUNTER - && cmd_APDU[1] != INS_PUT_DATA) + if (INS (apdu) != INS_CHANGE_REFERENCE_DATA + && INS (apdu) != INS_RESET_RETRY_COUNTER + && INS (apdu) != INS_PUT_DATA) { GPG_CONDITION_NOT_SATISFIED (); goto done; @@ -1012,8 +956,7 @@ GPGthread (void *arg) } } - len = cmd_APDU[4] = pw_len + newpw_len; - icc_data_size = 5 + len; + apdu.cmd_apdu_data_len = pw_len + newpw_len; #else GPG_ERROR (); goto done; @@ -1022,12 +965,9 @@ GPGthread (void *arg) else if (m == EV_NOP) continue; - if (icc_data_size != 0) - { - process_command_apdu (); - done: - chEvtSignal (icc_thread, EV_EXEC_FINISHED); - } + process_command_apdu (); + done: + chEvtSignal (icc_thread, EV_EXEC_FINISHED); } gpg_fini (); diff --git a/src/usb-icc.c b/src/usb-icc.c index daa8752..3d442cb 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -31,6 +31,8 @@ #include "usb_istr.h" #include "usb_lld.h" +struct apdu apdu; + #define ICC_SET_PARAMS 0x61 /* non-ICCD command */ #define ICC_POWER_ON 0x62 #define ICC_POWER_OFF 0x63 @@ -74,7 +76,7 @@ struct icc_header { uint16_t param; } __attribute__((packed)); -int icc_data_size; +static int icc_data_size; /* * USB-ICC communication could be considered "half duplex". @@ -94,8 +96,8 @@ int icc_data_size; * The buffer will be filled by multiple RX transactions (Bulk-OUT) * or will be used for multiple TX transactions (Bulk-IN) */ -uint8_t icc_buffer[USB_BUF_SIZE]; -uint8_t icc_seq; +static uint8_t icc_buffer[USB_BUF_SIZE]; +static uint8_t icc_seq; /* * Pointer to ICC_BUFFER @@ -391,9 +393,6 @@ icc_power_off (void) return ICC_STATE_START; } -int res_APDU_size; -const uint8_t *res_APDU_pointer; - static void icc_send_data_block (int len, uint8_t status, uint8_t chain) { @@ -501,6 +500,87 @@ icc_handle_data (void) { if (icc_header->param == 0) { /* Give this message to GPG thread */ + run_gpg_thread: + apdu.seq = icc_seq; + apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE]; + + apdu.sw = 0x9000; + apdu.res_apdu_data_len = 0; + apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; + + if (icc_data_size < 4) + { + icc_error (ICC_MSG_HEADER_SIZE + icc_data_size); + next_state = ICC_STATE_WAIT; + break; + } + else if (icc_data_size == 4) + { /* No Lc and No Le */ + apdu.cmd_apdu_data = NULL; + apdu.cmd_apdu_data_len = 0; + apdu.expected_res_size = 0; + apdu.cmd_apdu_head[4] = 0; + } + else if (icc_data_size == 5) + { /* No Lc but Le */ + apdu.cmd_apdu_data = NULL; + apdu.cmd_apdu_data_len = 0; + apdu.expected_res_size = apdu.cmd_apdu_head[4]; + if (apdu.expected_res_size == 0) + apdu.expected_res_size = 256; + apdu.cmd_apdu_head[4] = 0; + } + else if (apdu.cmd_apdu_head[4] == 0) + { /* extended Lc or extended Le */ + apdu.cmd_apdu_data = apdu.cmd_apdu_head + 7; + apdu.cmd_apdu_data_len + = (apdu.cmd_apdu_head[5] << 8) + apdu.cmd_apdu_head[6]; + if (icc_data_size == 7) + { /* No Lc but extended Le */ + apdu.expected_res_size = apdu.cmd_apdu_data_len; + apdu.cmd_apdu_data_len = 0; + } + else if (icc_data_size == apdu.cmd_apdu_data_len + 7) + apdu.expected_res_size = 0; + else if (icc_data_size == apdu.cmd_apdu_data_len + 7 + 2) + { + apdu.expected_res_size + = (icc_buffer[ICC_MSG_HEADER_SIZE + 7 + + apdu.cmd_apdu_data_len] << 8) + | icc_buffer[ICC_MSG_HEADER_SIZE + 7 + + apdu.cmd_apdu_data_len + 1]; + if (apdu.expected_res_size == 0) + apdu.expected_res_size = 65536; + } + else + { + icc_error (ICC_MSG_HEADER_SIZE + 5); + next_state = ICC_STATE_WAIT; + break; + } + } + else /* short Lc */ + { + apdu.cmd_apdu_data = apdu.cmd_apdu_head + 5; + apdu.cmd_apdu_data_len = apdu.cmd_apdu_head[4]; + if (icc_data_size == apdu.cmd_apdu_data_len + 5) + apdu.expected_res_size = 0; + else if (icc_data_size == apdu.cmd_apdu_data_len + 5 + 1) + { + apdu.expected_res_size + = icc_buffer[ICC_MSG_HEADER_SIZE + 5 + + apdu.cmd_apdu_data_len]; + if (apdu.expected_res_size == 0) + apdu.expected_res_size = 256; + } + else + { + icc_error (ICC_MSG_HEADER_SIZE + 5); + next_state = ICC_STATE_WAIT; + break; + } + } + chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } @@ -523,19 +603,28 @@ icc_handle_data (void) { if (icc_buffer[10] == 0x00) /* PIN verification */ { - cmd_APDU[0] = icc_buffer[25]; - cmd_APDU[1] = icc_buffer[26]; - cmd_APDU[2] = icc_buffer[27]; - cmd_APDU[3] = icc_buffer[28]; - icc_data_size = 4; - cmd_APDU[4] = 0; /* bConfirmPIN */ - cmd_APDU[5] = icc_buffer[17]; /* bEntryValidationCondition */ - cmd_APDU[6] = icc_buffer[18]; /* bNumberMessage */ - cmd_APDU[7] = icc_buffer[19]; /* wLangId L */ - cmd_APDU[8] = icc_buffer[20]; /* wLangId H */ - cmd_APDU[9] = icc_buffer[21]; /* bMsgIndex, bMsgIndex1 */ - cmd_APDU[10] = 0; /* bMsgIndex2 */ - cmd_APDU[11] = 0; /* bMsgIndex3 */ + icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[25]; + icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[26]; + icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[27]; + icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[28]; + /**/ + icc_buffer[ICC_MSG_HEADER_SIZE+5] = 0; /* bConfirmPIN */ + icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[17]; /* bEntryValidationCondition */ + icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[18]; /* bNumberMessage */ + icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[19]; /* wLangId L */ + icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[20]; /* wLangId H */ + icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[21]; /* bMsgIndex */ + + apdu.seq = icc_seq; + apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0]; + apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5]; + apdu.cmd_apdu_data_len = 6; + apdu.expected_res_size = 0; + + apdu.sw = 0x9000; + apdu.res_apdu_data_len = 0; + apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; + chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } @@ -547,22 +636,32 @@ icc_handle_data (void) num_msgs = 1; else if (num_msgs == 0xff) num_msgs = 3; - cmd_APDU[0] = icc_buffer[27 + num_msgs]; - cmd_APDU[1] = icc_buffer[28 + num_msgs]; - cmd_APDU[2] = icc_buffer[29 + num_msgs]; - cmd_APDU[3] = icc_buffer[30 + num_msgs]; - icc_data_size = 4; - cmd_APDU[4] = icc_buffer[19]; /* bConfirmPIN */ - cmd_APDU[5] = icc_buffer[20]; /* bEntryValidationCondition */ - cmd_APDU[6] = icc_buffer[21]; /* bNumberMessage */ - cmd_APDU[7] = icc_buffer[22]; /* wLangId L */ - cmd_APDU[8] = icc_buffer[23]; /* wLangId H */ - cmd_APDU[9] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */ - cmd_APDU[10] = cmd_APDU[11] = 0; + icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[27 + num_msgs]; + icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[28 + num_msgs]; + icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[29 + num_msgs]; + icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[30 + num_msgs]; + /**/ + icc_buffer[ICC_MSG_HEADER_SIZE+5] = icc_buffer[19]; /* bConfirmPIN */ + icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[20]; /* bEntryValidationCondition */ + icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[21]; /* bNumberMessage */ + icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[22]; /* wLangId L */ + icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[23]; /* wLangId H */ + icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */ if (num_msgs >= 2) - cmd_APDU[10] = icc_buffer[25]; /* bMsgIndex2 */ + icc_buffer[ICC_MSG_HEADER_SIZE+11] = icc_buffer[25]; /* bMsgIndex2 */ if (num_msgs == 3) - cmd_APDU[11] = icc_buffer[26]; /* bMsgIndex3 */ + icc_buffer[ICC_MSG_HEADER_SIZE+12] = icc_buffer[26]; /* bMsgIndex3 */ + + apdu.seq = icc_seq; + apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0]; + apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5]; + apdu.cmd_apdu_data_len = 5 + num_msgs; + apdu.expected_res_size = 0; + + apdu.sw = 0x9000; + apdu.res_apdu_data_len = 0; + apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; + chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } @@ -594,8 +693,7 @@ icc_handle_data (void) icc_next_p -= ICC_MSG_HEADER_SIZE; icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE; icc_chain_p = NULL; - next_state = ICC_STATE_EXECUTE; - chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); + goto run_gpg_thread; } else /* icc_header->param == 3 is not supported. */ { @@ -633,25 +731,59 @@ icc_handle_data (void) { if (icc_header->param == 0x10) { - if (res_APDU_pointer != NULL) + int len = apdu.res_apdu_data_len; + + if (apdu.res_apdu_data == NULL) + { /* send last byte of 0x9000 */ + icc_buffer[ICC_MSG_HEADER_SIZE] = 0x00; + len = 1; + } + else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) { - memcpy (res_APDU, res_APDU_pointer, - ICC_RESPONSE_MSG_DATA_SIZE); - res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE; + if (apdu.res_apdu_data_len >= ICC_RESPONSE_MSG_DATA_SIZE) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); + apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; + } + else if (apdu.res_apdu_data_len + <= ICC_RESPONSE_MSG_DATA_SIZE - 2) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, apdu.res_apdu_data_len); + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] + = 0x90; + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] + = 0x00; + apdu.res_apdu_data = NULL; + len += 2; + } + else if (apdu.res_apdu_data_len + == ICC_RESPONSE_MSG_DATA_SIZE - 1) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, apdu.res_apdu_data_len); + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] + = 0x90; + apdu.res_apdu_data = NULL; + len += 1; + } } else - memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE, - res_APDU_size); + memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], + &icc_buffer[ICC_MSG_HEADER_SIZE] + +ICC_RESPONSE_MSG_DATA_SIZE, + apdu.res_apdu_data_len); - if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE) + if (len <= ICC_RESPONSE_MSG_DATA_SIZE) { - icc_send_data_block (res_APDU_size, 0, 0x02); + icc_send_data_block (len, 0, 0x02); next_state = ICC_STATE_WAIT; } else { icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); - res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE; + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; } } else @@ -721,26 +853,36 @@ USBthread (void *arg) else if (m == EV_EXEC_FINISHED) if (icc_state == ICC_STATE_EXECUTE) { - if (res_APDU_pointer != NULL) + if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) { - memcpy (res_APDU, res_APDU_pointer, ICC_RESPONSE_MSG_DATA_SIZE); - res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE; + /* Assume that + * apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE + */ + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); + apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; + } + else + { + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] = (apdu.sw >> 8); + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = (apdu.sw & 0xff); + apdu.res_apdu_data_len += 2; } - if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE) + if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE) { - icc_send_data_block (res_APDU_size, 0, 0); + icc_send_data_block (apdu.res_apdu_data_len, 0, 0); icc_state = ICC_STATE_WAIT; } else { icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01); - res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE; + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; icc_state = ICC_STATE_SEND; } } else - { /* XXX: error */ + { /* error */ DEBUG_INFO ("ERR07\r\n"); } else if (m == EV_TX_FINISHED) diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index f0e83cc..d3de957 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -47,7 +47,7 @@ class GnukToken(object): apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd) response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, "cmd_verify" + raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_write_binary(self, fileid, data, is_update): count = 0 @@ -66,22 +66,22 @@ class GnukToken(object): response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): if is_update: - raise ValueError, "cmd_update_binary" + raise ValueError, ("%02x%02x" % (sw1, sw2)) else: - raise ValueError, "cmd_write_binary" + raise ValueError, ("%02x%02x" % (sw1, sw2)) count += 1 def cmd_select_openpgp(self): apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, "cmd_select_openpgp" + raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_get_data(self, tagh, tagl): apdu = [0x00, 0xca, tagh, tagl] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, "cmd_get_data" + raise ValueError, ("%02x%02x" % (sw1, sw2)) return response def compare(data_original, data_in_device): @@ -165,6 +165,5 @@ if __name__ == '__main__': data = f.read() f.close() print "%s: %d" % (filename, len(data)) - data += "\x90\x00" print "Updating card holder certificate" main(fileid, is_update, data, passwd) diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 4d7afef..ae47ba9 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -289,6 +289,5 @@ if __name__ == '__main__': data = f.read() f.close() print "%s: %d" % (filename, len(data)) - data += "\x90\x00" print "Updating card holder certificate" main(fileid, is_update, data) From f92ee76db569320129da7109a0867eb0bc742548 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 19 Jan 2012 14:23:01 +0900 Subject: [PATCH 057/300] fixes two bugs --- ChangeLog | 7 ++++++ src/openpgp-do.c | 5 +++- src/usb-icc.c | 62 +++++++++++++++++++++++++++++++----------------- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index b18c49b..93a69d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-01-19 Niibe Yutaka + + * src/usb-icc.c (icc_handle_data): Handle the case when it only + sends 0x90 and 0x00 correctly. + + * src/openpgp-do.c (gpg_do_get_data): Fix res_apdu_data_len. + 2012-01-18 Niibe Yutaka Clean up API between application layer and CCID layer. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 47cec3b..b91b10b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1253,7 +1253,10 @@ gpg_do_get_data (uint16_t tag, int with_tag) apdu.res_apdu_data = &ch_certificate_start; apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]); if (apdu.res_apdu_data_len == 0xffff) - GPG_NO_RECORD (); + { + apdu.res_apdu_data_len = 0; + GPG_NO_RECORD (); + } else /* Add length of (tag+len) */ apdu.res_apdu_data_len += 4; diff --git a/src/usb-icc.c b/src/usb-icc.c index 3d442cb..db21ae8 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -734,17 +734,44 @@ icc_handle_data (void) int len = apdu.res_apdu_data_len; if (apdu.res_apdu_data == NULL) - { /* send last byte of 0x9000 */ - icc_buffer[ICC_MSG_HEADER_SIZE] = 0x00; - len = 1; + { /* send status word(s) of 0x9000 */ + len = 0; + + if (apdu.res_apdu_data_len == 2) + { + icc_buffer[ICC_MSG_HEADER_SIZE] = 0x90; + len++; + } + + icc_buffer[ICC_MSG_HEADER_SIZE+len] = 0x00; + len++; } else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) { - if (apdu.res_apdu_data_len >= ICC_RESPONSE_MSG_DATA_SIZE) + if (apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE) { memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; + } + else if (apdu.res_apdu_data_len == ICC_RESPONSE_MSG_DATA_SIZE) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); + apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 2; + } + else if (apdu.res_apdu_data_len + == ICC_RESPONSE_MSG_DATA_SIZE - 1) + { + memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], + apdu.res_apdu_data, apdu.res_apdu_data_len); + icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] + = 0x90; + apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 1; + len += 1; } else if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE - 2) @@ -756,24 +783,18 @@ icc_handle_data (void) icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = 0x00; apdu.res_apdu_data = NULL; + apdu.res_apdu_data_len = 0; len += 2; } - else if (apdu.res_apdu_data_len - == ICC_RESPONSE_MSG_DATA_SIZE - 1) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, apdu.res_apdu_data_len); - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] - = 0x90; - apdu.res_apdu_data = NULL; - len += 1; - } } else - memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], - &icc_buffer[ICC_MSG_HEADER_SIZE] - +ICC_RESPONSE_MSG_DATA_SIZE, - apdu.res_apdu_data_len); + { + memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], + &icc_buffer[ICC_MSG_HEADER_SIZE] + +ICC_RESPONSE_MSG_DATA_SIZE, + apdu.res_apdu_data_len); + apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; + } if (len <= ICC_RESPONSE_MSG_DATA_SIZE) { @@ -781,10 +802,7 @@ icc_handle_data (void) next_state = ICC_STATE_WAIT; } else - { - icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); - apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; - } + icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); } else { From 21debc056763d766249626d704e1f9ba7e8d0b48 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jan 2012 18:18:23 +0900 Subject: [PATCH 058/300] no ext lc and le but short APDU only --- STM32_USB-FS-Device_Driver/src/usb_core.c | 7 +- src/call-rsa.c | 2 +- src/gnuk.h | 21 +- src/main.c | 7 + src/openpgp-do.c | 24 +- src/openpgp.c | 5 +- src/openpgp.h | 24 +- src/stmusb.mk | 2 +- src/usb-icc.c | 1476 +++++++++++++-------- src/usb_desc.c | 4 +- src/usb_lld.c | 73 + src/usb_lld.h | 13 +- tool/gnuk_put_binary.py | 32 +- 13 files changed, 1064 insertions(+), 626 deletions(-) diff --git a/STM32_USB-FS-Device_Driver/src/usb_core.c b/STM32_USB-FS-Device_Driver/src/usb_core.c index 8220ef3..24ee765 100644 --- a/STM32_USB-FS-Device_Driver/src/usb_core.c +++ b/STM32_USB-FS-Device_Driver/src/usb_core.c @@ -15,6 +15,9 @@ /* Includes ------------------------------------------------------------------*/ #include "usb_lib.h" +extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, uint32_t n); +extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, uint32_t n); + /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define ValBit(VAR,Place) (VAR & (1 << Place)) @@ -460,7 +463,7 @@ void DataStageOut(void) #ifdef STM32F10X_CL OTGD_FS_PCD_EP_Read(ENDP0, Buffer, Length); #else - PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); + usb_lld_from_pmabuf (Buffer, GetEPRxAddr(ENDP0), Length); #endif /* STM32F10X_CL */ } @@ -544,7 +547,7 @@ void DataStageIn(void) #ifdef STM32F10X_CL OTGD_FS_PCD_EP_Write (ENDP0, DataBuffer, Length); #else - UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); + usb_lld_to_pmabuf (DataBuffer, GetEPTxAddr(ENDP0), Length); #endif /* STM32F10X_CL */ SetEPTxCount(ENDP0, Length); diff --git a/src/call-rsa.c b/src/call-rsa.c index cf7530b..f9a90ef 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -167,7 +167,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, #endif r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len, - input, output, MAX_RES_APDU_SIZE - 2); + input, output, MAX_RES_APDU_DATA_SIZE); rsa_free (&rsa_ctx); if (r < 0) { diff --git a/src/gnuk.h b/src/gnuk.h index 464e036..f5a2f43 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -36,7 +36,7 @@ struct apdu { uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */ uint8_t *cmd_apdu_data; uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */ - uint32_t expected_res_size; /* Ne, calculated by Le field */ + uint16_t expected_res_size; /* Ne, calculated by Le field */ /* response APDU */ uint16_t sw; @@ -55,10 +55,10 @@ extern struct apdu apdu; #define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8) #define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16) -/* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */ -#define MAX_CMD_APDU_SIZE (7+282) /* header + data */ -/* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */ -#define MAX_RES_APDU_SIZE ((5+9+256)+2) /* Data + status */ +/* Maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */ +#define MAX_CMD_APDU_DATA_SIZE (22+4+128+128) /* without header */ +/* Maximum res apdu data is public key 5+9+256 (gpg_do_public_key) */ +#define MAX_RES_APDU_DATA_SIZE (5+9+256) /* without trailer */ #define ICC_MSG_HEADER_SIZE 10 @@ -68,13 +68,6 @@ extern struct apdu apdu; /* USB buffer size of LL (Low-level): size of single Bulk transaction */ #define USB_LL_BUF_SIZE 64 -/* - * USB buffer size of USB-ICC driver - * (Changing this, dwMaxCCIDMessageLength too !!) - */ -#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \ - / USB_LL_BUF_SIZE * USB_LL_BUF_SIZE) - enum icc_state { ICC_STATE_START, /* Initial */ @@ -85,7 +78,7 @@ enum icc_state ICC_STATE_SEND, /* APDU Sent Partially */ }; -extern volatile enum icc_state icc_state; +extern enum icc_state *icc_state_p; extern volatile uint8_t auth_status; #define AC_NONE_AUTHORIZED 0x00 @@ -116,7 +109,7 @@ extern void ac_reset_admin (void); extern void ac_fini (void); -extern void set_res_apdu (uint8_t sw1, uint8_t sw2); +extern void set_res_sw (uint8_t sw1, uint8_t sw2); extern uint16_t data_objects_number_of_bytes; extern void gpg_data_scan (const uint8_t *p); diff --git a/src/main.c b/src/main.c index c7460a8..5f62801 100644 --- a/src/main.c +++ b/src/main.c @@ -287,6 +287,13 @@ static void display_fatal_code (void) static void display_status_code (void) { + enum icc_state icc_state; + + if (icc_state_p == NULL) + icc_state = ICC_STATE_START; + else + icc_state = *icc_state_p; + if (icc_state == ICC_STATE_START) { set_led (1); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index b91b10b..f0cd355 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -77,12 +77,11 @@ uint16_t data_objects_number_of_bytes; static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { 10, 0x00, - 0x31, 0x80, /* Full DF name */ + 0x31, 0x84, /* Full DF name, GET DATA, MF */ 0x73, - 0x80, 0x01, 0x40, /* Full DF name */ + 0x80, 0x01, 0x80, /* Full DF name */ /* 1-byte */ - /* No command chaining */ - /* Extended Lc and Le */ + /* Command chaining, No extended Lc and Le */ 0x00, 0x90, 0x00 /* Status info (no life cycle management) */ }; @@ -90,27 +89,24 @@ static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = { static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { 10, 0x30, /* - * No SM, No get challenge, + * No SM, + * No get challenge, * Key import supported, * PW status byte can be put, * No private_use_DO, * No algo change allowed */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ - 0x00, 0x00, /* Max get challenge */ + 0x00, 0x00, /* Max get challenge (0: Get challenge not supported) */ #ifdef CERTDO_SUPPORT - 0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/ + 0x08, 0x00, /* max. length of cardholder certificate (2KiB) */ #else 0x00, 0x00, #endif - /* Max. length of command data */ - (MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff), + /* Max. length of command APDU */ + 0x00, 0xff, /* Max. length of response data */ -#ifdef CERTDO_SUPPORT - 0x08, 0x00, /* the case of cardholder ceritificate */ -#else - (MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff), -#endif + 0x00, 0xff, }; /* Algorithm Attributes */ diff --git a/src/openpgp.c b/src/openpgp.c index d73d773..eec46ee 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -67,7 +67,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = { }; void -set_res_apdu (uint8_t sw1, uint8_t sw2) +set_res_sw (uint8_t sw1, uint8_t sw2) { apdu.sw = (sw1 << 8) | sw2; } @@ -510,7 +510,7 @@ cmd_select_file (void) if (apdu.cmd_apdu_data_len != 6 || memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0) { - DEBUG_WORD (apdu.cmd_apdu_data_len); + DEBUG_SHORT (apdu.cmd_apdu_data_len); DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); GPG_NO_FILE (); @@ -528,6 +528,7 @@ cmd_select_file (void) res_APDU[1] = 0x12; res_APDU[2] = 0x84; /* overwrite: DF name */ res_APDU_size += 2; + GPG_SUCCESS (); } } else if (apdu.cmd_apdu_data_len == 2 diff --git a/src/openpgp.h b/src/openpgp.h index 8cd3f8c..b92c2c8 100644 --- a/src/openpgp.h +++ b/src/openpgp.h @@ -1,12 +1,12 @@ -#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_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85) -#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86) -#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81) -#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) +#define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81) +#define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82) +#define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83) +#define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85) +#define GPG_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86) +#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81) +#define GPG_NO_FILE() set_res_sw (0x6a, 0x82) +#define GPG_NO_RECORD() set_res_sw (0x6a, 0x88) +#define GPG_BAD_P0_P1() set_res_sw (0x6b, 0x00) +#define GPG_NO_INS() set_res_sw (0x6d, 0x00) +#define GPG_ERROR() set_res_sw (0x6f, 0x00) +#define GPG_SUCCESS() set_res_sw (0x90, 0x00) diff --git a/src/stmusb.mk b/src/stmusb.mk index f0b1b5e..b459268 100644 --- a/src/stmusb.mk +++ b/src/stmusb.mk @@ -3,5 +3,5 @@ STMUSBSRCDIR = $(STMUSBDIR)/src STMUSBINCDIR = $(STMUSBDIR)/inc STMUSBSRC= \ $(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \ - $(STMUSBSRCDIR)/usb_mem.c $(STMUSBSRCDIR)/usb_core.c \ + $(STMUSBSRCDIR)/usb_core.c \ $(STMUSBSRCDIR)/usb_regs.c diff --git a/src/usb-icc.c b/src/usb-icc.c index db21ae8..f392fd8 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -31,8 +31,107 @@ #include "usb_istr.h" #include "usb_lld.h" +/* + * USB buffer size of USB-ICC driver + */ +#if MAX_RES_APDU_DATA_SIZE > MAX_CMD_APDU_DATA_SIZE +#define USB_BUF_SIZE (MAX_RES_APDU_DATA_SIZE+5) +#else +#define USB_BUF_SIZE (MAX_CMD_APDU_DATA_SIZE+5) +#endif + struct apdu apdu; +/* + * There are three layers in USB CCID implementation + * + * +-------------------+ + * | Application Layer | + * +-------------------+ + * ^ command APDU | + * | v response APDU + * +-------------------+ + * | CCID Layer | + * +-------------------+ + * ^ CCID PC_to_RDR | CCID RDR_to_PC + * | Message v Message + * +-------------------+ + * | USB Layer | + * +-------------------+ + * ^ USB | USB + * | Bulk-OUT Packet v Bulk-IN Packet + * + */ + +/* + * USB layer data structures + */ + +struct ep_in { + uint8_t ep_num; + uint8_t tx_done; + void (*notify) (struct ep_in *epi); + const uint8_t *buf; + size_t cnt; + size_t buf_len; + void *priv; + void (*next_buf) (struct ep_in *epi, size_t len); +}; + +static void epi_init (struct ep_in *epi, int ep_num, + void (*notify) (struct ep_in *epi), void *priv) +{ + epi->ep_num = ep_num; + epi->tx_done = 0; + epi->notify = notify; + epi->buf = NULL; + epi->cnt = 0; + epi->buf_len = 0; + epi->priv = priv; + epi->next_buf = NULL; +} + +struct ep_out { + uint8_t ep_num; + uint8_t err; + void (*notify) (struct ep_out *epo); + uint8_t *buf; + size_t cnt; + size_t buf_len; + void *priv; + void (*next_buf) (struct ep_out *epo, size_t len); + int (*end_rx) (struct ep_out *epo, size_t orig_len); +}; + +static struct ep_out endpoint_out; +static struct ep_in endpoint_in; + +static void epo_init (struct ep_out *epo, int ep_num, + void (*notify) (struct ep_out *epo), void *priv) +{ + epo->ep_num = ep_num; + epo->err = 0; + epo->notify = notify; + epo->buf = NULL; + epo->cnt = 0; + epo->buf_len = 0; + epo->priv = priv; + epo->next_buf = NULL; + epo->end_rx = NULL; +} + +/* + * CCID Layer + */ + +/* + * Buffer of USB communication: for both of RX and TX + * + * The buffer will be filled by multiple RX packets (Bulk-OUT) + * or will be used for multiple TX packets (Bulk-IN) + */ +static uint8_t icc_buffer[USB_BUF_SIZE]; + #define ICC_SET_PARAMS 0x61 /* non-ICCD command */ #define ICC_POWER_ON 0x62 #define ICC_POWER_OFF 0x63 @@ -49,7 +148,7 @@ struct apdu apdu; #define ICC_MSG_ERROR_OFFSET 8 #define ICC_MSG_CHAIN_OFFSET 9 #define ICC_MSG_DATA_OFFSET 10 /* == ICC_MSG_HEADER_SIZE */ -#define ICC_MAX_MSG_DATA_SIZE (USB_BUF_SIZE - ICC_MSG_HEADER_SIZE) +#define ICC_MAX_MSG_DATA_SIZE USB_BUF_SIZE #define ICC_STATUS_RUN 0x00 #define ICC_STATUS_PRESENT 0x01 @@ -65,21 +164,105 @@ struct apdu apdu; * error with offset 0 means "command not supported". */ #define ICC_OFFSET_CMD_NOT_SUPPORTED 0 +#define ICC_OFFSET_DATA_LEN 1 #define ICC_OFFSET_PARAM 8 struct icc_header { uint8_t msg_type; - int32_t data_len; + uint32_t data_len; uint8_t slot; uint8_t seq; uint8_t rsvd; uint16_t param; } __attribute__((packed)); -static int icc_data_size; + +enum icc_state *icc_state_p; + +/* Data structure handled by CCID layer */ +struct ccid { + enum icc_state icc_state; + uint8_t state; + uint8_t *p; + size_t len; + + uint8_t err; + + struct icc_header icc_header; + + uint8_t sw1sw2[2]; + + Thread *icc_thread; + Thread *application; + + /* lower layer */ + struct ep_out *epo; + struct ep_in *epi; + + /* upper layer */ + struct apdu *a; +}; /* - * USB-ICC communication could be considered "half duplex". + * APDU_STATE_WAIT_COMMAND +---------+ + * | | | | + * | v v | + * | APDU_STATE_COMMAND_CHAINING --+ + * | | + * v v + * APDU_STATE_COMMAND_RECEIVED + * | + * v + * =================== + * | Process COMMAND | + * =================== + * | + * v + * +-----+----------+ +---------+ + * | | | | + * v v v | + * APDU_STATE_RESULT <---- APDU_STATE_RESULT_GET_RESPONSE --+ + * | + * | + * v + * APDU_STATE_WAIT_COMMAND + */ + +#define APDU_STATE_WAIT_COMMAND 0 +#define APDU_STATE_COMMAND_CHAINING 1 +#define APDU_STATE_COMMAND_RECEIVED 2 +#define APDU_STATE_RESULT 3 +#define APDU_STATE_RESULT_GET_RESPONSE 4 + +static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, + struct apdu *a, Thread *t) +{ + icc_state_p = &c->icc_state; + + c->icc_state = ICC_STATE_START; + c->state = APDU_STATE_WAIT_COMMAND; + /* + * Note: a is not yet initialized yet, we can't use c->a->cmd_apdu_data here. + */ + c->p = &icc_buffer[5]; + c->len = MAX_CMD_APDU_DATA_SIZE; + c->err = 0; + memset (&c->icc_header, 0, sizeof (struct icc_header)); + c->sw1sw2[0] = 0x90; + c->sw1sw2[1] = 0x00; + c->icc_thread = t; + c->application = NULL; + c->epi = epi; + c->epo = epo; + c->a = a; +} + +/* + * Application layer + */ + +/* + * USB-CCID communication could be considered "half duplex". * * While the device is sending something, there is no possibility for * the device to receive anything. @@ -88,152 +271,350 @@ static int icc_data_size; * for the device to send anything. * * Thus, the buffer can be shared for RX and TX. - */ - -/* - * Buffer of USB communication: for both of RX and TX * - * The buffer will be filled by multiple RX transactions (Bulk-OUT) - * or will be used for multiple TX transactions (Bulk-IN) + * Exception: When we support ABORT of CCID, it is possible to receive + * ABORT Class Specific Request to control pipe while we are + * receiving/sending something at OUT/IN endpoint. + * */ -static uint8_t icc_buffer[USB_BUF_SIZE]; -static uint8_t icc_seq; -/* - * Pointer to ICC_BUFFER - */ -static uint8_t *icc_next_p; +#define CMD_APDU_HEAD_SIZE 5 -/* - * Chain pointer: This implementation support two packets in chain (not more) - */ -static uint8_t *icc_chain_p; +static void apdu_init (struct apdu *a) +{ + a->seq = 0; /* will be set by lower layer */ + a->cmd_apdu_head = &icc_buffer[0]; + a->cmd_apdu_data = &icc_buffer[5]; + a->cmd_apdu_data_len = 0; /* will be set by lower layer */ + a->expected_res_size = 0; /* will be set by lower layer */ -/* - * Whole size of TX transfer (Bulk-IN transactions) - */ -static int icc_tx_size; - -static Thread *icc_thread; + a->sw = 0x9000; /* will be set by upper layer */ + a->res_apdu_data = &icc_buffer[5]; /* will be set by upper layer */ + a->res_apdu_data_len = 0; /* will be set by upper layer */ +} #define EV_RX_DATA_READY (eventmask_t)1 /* USB Rx data available */ /* EV_EXEC_FINISHED == 2 */ #define EV_TX_FINISHED (eventmask_t)4 /* USB Tx finished */ + +static void notify_tx (struct ep_in *epi) +{ + struct ccid *c = (struct ccid *)epi->priv; + + /* The sequence of Bulk-IN transactions finished */ + chEvtSignalI (c->icc_thread, EV_TX_FINISHED); +} + +static void no_buf (struct ep_in *epi, size_t len) +{ + (void)len; + epi->buf = NULL; + epi->cnt = 0; + epi->buf_len = 0; +} + +static void set_sw1sw2 (struct ep_in *epi) +{ + struct ccid *c = (struct ccid *)epi->priv; + + if (c->a->expected_res_size >= c->len) + { + c->sw1sw2[0] = 0x90; + c->sw1sw2[1] = 0x00; + } + else + { + c->sw1sw2[0] = 0x61; + if (c->len >= 256) + c->sw1sw2[1] = 0; + else + c->sw1sw2[1] = (uint8_t)c->len; + } +} + +static void get_sw1sw2 (struct ep_in *epi, size_t len) +{ + struct ccid *c = (struct ccid *)epi->priv; + + (void)len; + epi->buf = c->sw1sw2; + epi->cnt = 0; + epi->buf_len = 2; + epi->next_buf = no_buf; +} + + /* * Tx done callback */ void EP1_IN_Callback (void) { - if (icc_next_p == NULL) - /* The sequence of Bulk-IN transactions finished */ - chEvtSignalI (icc_thread, EV_TX_FINISHED); - else if (icc_next_p == &icc_buffer[icc_tx_size]) - /* It was multiple of USB_LL_BUF_SIZE */ - { - /* Send the last 0-DATA transcation of Bulk-IN in the transactions */ - icc_next_p = NULL; - usb_lld_write (ENDP1, icc_buffer, 0); - } + struct ep_in *epi = &endpoint_in; + + if (epi->buf == NULL) + if (epi->tx_done) + epi->notify (epi); + else + { + epi->tx_done = 1; + usb_lld_tx_enable (epi->ep_num, 0); /* send ZLP */ + } else { - int tx_size = USB_LL_BUF_SIZE; - uint8_t *p = icc_next_p; + int tx_size = 0; + size_t remain = USB_LL_BUF_SIZE; + int offset = 0; - icc_next_p += USB_LL_BUF_SIZE; - if (icc_next_p > &icc_buffer[icc_tx_size]) - { - icc_next_p = NULL; - tx_size = &icc_buffer[icc_tx_size] - p; - } + while (epi->buf) + if (epi->buf_len < remain) + { + usb_lld_txcpy (epi->buf, epi->ep_num, offset, epi->buf_len); + offset += epi->buf_len; + remain -= epi->buf_len; + tx_size += epi->buf_len; + epi->next_buf (epi, remain); /* Update epi->buf, cnt, buf_len */ + } + else + { + usb_lld_txcpy (epi->buf, epi->ep_num, offset, remain); + epi->buf += remain; + epi->cnt += remain; + epi->buf_len -= remain; + tx_size += remain; + break; + } - usb_lld_write (ENDP1, p, tx_size); + if (tx_size < USB_LL_BUF_SIZE) + epi->tx_done = 1; + usb_lld_tx_enable (epi->ep_num, tx_size); } } -static void -icc_prepare_receive (int chain) -{ - if (chain) - icc_next_p = icc_chain_p; - else - icc_next_p = icc_buffer; - usb_lld_rx_enable (ENDP2); +static void notify_icc (struct ep_out *epo) +{ + struct ccid *c = (struct ccid *)epo->priv; + + c->err = epo->err; + chEvtSignalI (c->icc_thread, EV_RX_DATA_READY); +} + +static int end_icc_rx (struct ep_out *epo, size_t orig_len) +{ + (void)orig_len; + if (epo->cnt < sizeof (struct icc_header)) + /* short packet, just ignore */ + return 1; + + /* icc message with no abdata */ + return 0; +} + +static int end_notify (struct ep_out *epo, size_t orig_len) +{ + (void)epo; + (void)orig_len; + return 0; +} + +static int end_cmd_apdu_head (struct ep_out *epo, size_t orig_len) +{ + struct ccid *c = (struct ccid *)epo->priv; + + (void)orig_len; + + if (epo->cnt < 4 || epo->cnt != c->icc_header.data_len) + epo->err = 1; + + if (epo->cnt == 4) + { + /* No Lc and Le */ + c->a->cmd_apdu_data_len = 0; + c->a->expected_res_size = 0; + } + else if (epo->cnt == 5) + { + /* No Lc but Le */ + c->a->cmd_apdu_data_len = 0; + c->a->expected_res_size = c->a->cmd_apdu_head[4]; + if (c->a->expected_res_size == 0) + c->a->expected_res_size = 256; + c->a->cmd_apdu_head[4] = 0; + } + + return 0; +} + + +static int end_nomore_data (struct ep_out *epo, size_t orig_len) +{ + (void)epo; + if (orig_len == USB_LL_BUF_SIZE) + return 1; + else + return 0; +} + + +static int end_cmd_apdu_data (struct ep_out *epo, size_t orig_len) +{ + struct ccid *c = (struct ccid *)epo->priv; + size_t len = epo->cnt; + + if (orig_len == USB_LL_BUF_SIZE + && CMD_APDU_HEAD_SIZE + len < c->icc_header.data_len) + /* more packet comes */ + return 1; + + if (CMD_APDU_HEAD_SIZE + len != c->icc_header.data_len) + goto error; + + if (len == c->a->cmd_apdu_head[4]) + /* No Le field*/ + c->a->expected_res_size = 0; + else if (len == (size_t)c->a->cmd_apdu_head[4] + 1) + { + /* it has Le field*/ + c->a->expected_res_size = epo->buf[-1]; + len--; + } + else + { + error: + epo->err = 1; + return 0; + } + + c->a->cmd_apdu_data_len += len; + return 0; +} + + +static void nomore_data (struct ep_out *epo, size_t len) +{ + (void)len; + epo->err = 1; + epo->end_rx = end_nomore_data; + epo->buf = NULL; + epo->buf_len = 0; + epo->cnt = 0; + epo->next_buf = nomore_data; +} + +#define INS_GET_RESPONSE 0xc0 + +static void icc_cmd_apdu_data (struct ep_out *epo, size_t len) +{ + struct ccid *c = (struct ccid *)epo->priv; + + (void)len; + if (c->state == APDU_STATE_RESULT_GET_RESPONSE + && c->a->cmd_apdu_head[1] != INS_GET_RESPONSE) + { + /* + * Handling exceptional request. + * + * Host didn't finish receiving the whole response APDU by GET RESPONSE, + * but initiates another command. + */ + + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + } + + epo->end_rx = end_cmd_apdu_data; + epo->buf = c->p; + epo->buf_len = c->len; + epo->cnt = 0; + epo->next_buf = nomore_data; +} + +static void icc_abdata (struct ep_out *epo, size_t len) +{ + struct ccid *c = (struct ccid *)epo->priv; + + (void)len; + if (c->icc_header.msg_type == ICC_XFR_BLOCK) + { + c->a->seq = c->icc_header.seq; + epo->end_rx = end_cmd_apdu_head; + epo->buf = c->a->cmd_apdu_head; + epo->buf_len = 5; + epo->cnt = 0; + epo->next_buf = icc_cmd_apdu_data; + } + else + { + epo->end_rx = end_notify; + epo->buf = c->p; + epo->buf_len = c->len; + epo->cnt = 0; + epo->next_buf = nomore_data; + } +} + + +static void +icc_prepare_receive (struct ccid *c) +{ + DEBUG_INFO ("Rx ready\r\n"); + + c->epo->err = 0; + c->epo->buf = (uint8_t *)&c->icc_header; + c->epo->buf_len = sizeof (struct icc_header); + c->epo->cnt = 0; + c->epo->next_buf = icc_abdata; + c->epo->end_rx = end_icc_rx; + usb_lld_rx_enable (c->epo->ep_num); } /* * Rx ready callback */ + void EP2_OUT_Callback (void) { - int len; - struct icc_header *icc_header; - int data_len_so_far; - int data_len; + struct ep_out *epo = &endpoint_out; + size_t len = usb_lld_rx_data_len (epo->ep_num); + int offset = 0; + int cont; + size_t orig_len = len; - len = usb_lld_rx_data_len (ENDP2); - usb_lld_rxcpy (icc_next_p, ENDP2, 0, len); - if (len == 0) - { /* Just ignore Zero Length Packet (ZLP), if any */ - usb_lld_rx_enable (ENDP2); - return; - } + while (epo->err == 0) + if (len == 0) + break; + else if (len <= epo->buf_len) + { + usb_lld_rxcpy (epo->buf, epo->ep_num, offset, len); + epo->buf += len; + epo->cnt += len; + epo->buf_len -= len; + break; + } + else /* len > buf_len */ + { + usb_lld_rxcpy (epo->buf, epo->ep_num, offset, epo->buf_len); + len -= epo->buf_len; + offset += epo->buf_len; + epo->next_buf (epo, len); /* Update epo->buf, cnt, buf_len */ + } - icc_next_p += len; + /* + * ORIG_LEN to distingush ZLP and the end of transaction + * (ORIG_LEN != USB_LL_BUF_SIZE) + */ + cont = epo->end_rx (epo, orig_len); - if (icc_chain_p) - icc_header = (struct icc_header *)icc_chain_p; + if (cont) + usb_lld_rx_enable (epo->ep_num); else - icc_header = (struct icc_header *)icc_buffer; - - data_len = icc_header->data_len; /* NOTE: We're little endian */ - data_len_so_far = (icc_next_p - (uint8_t *)icc_header) - ICC_MSG_HEADER_SIZE; - - if (len == USB_LL_BUF_SIZE - && data_len != data_len_so_far) - /* The sequence of transactions continues */ - { - usb_lld_rx_enable (ENDP2); - if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE) - /* No room to receive any more */ - { - DEBUG_INFO ("ERR0F\r\n"); - icc_next_p -= USB_LL_BUF_SIZE; /* Just for not overrun the buffer */ - /* - * Receive until the end of the sequence - * (and discard the whole block) - */ - } - - /* - * NOTE: It is possible a transaction may stall when the size of - * BULK_OUT transaction it's bigger than USB_BUF_SIZE and stops - * with just USB_LL_BUF_SIZE packet. Device will remain waiting - * another packet. - */ - } - else /* Finished */ - { - icc_data_size = data_len_so_far; - icc_seq = icc_header->seq; /* NOTE: We're little endian */ - - if (icc_data_size != data_len) - { - DEBUG_INFO ("ERR0E\r\n"); - /* Ignore the whole block */ - icc_chain_p = NULL; - icc_prepare_receive (0); - } - else - /* Notify myself */ - chEvtSignalI (icc_thread, EV_RX_DATA_READY); - } + epo->notify (epo); } -volatile enum icc_state icc_state; /* * ATR (Answer To Reset) string @@ -254,32 +635,26 @@ volatile enum icc_state icc_state; * Minimum: 0x3b, 0x8a, 0x80, 0x01, + historical bytes, xor check * */ -static const char ATR[] = { +static const uint8_t ATR[] = { 0x3b, 0xda, 0x11, 0xff, 0x81, 0xb1, 0xfe, 0x55, 0x1f, 0x03, 0x00, 0x31, 0x84, /* full DF name, GET DATA, MF */ 0x73, - 0x80, /* DF full name */ - 0x01, /* 1-byte */ - 0x40, /* Extended Lc and extended Le */ + 0x80, /* DF full name */ + 0x01, /* 1-byte */ + 0x80, /* Command chaining, No extended Lc and extended Le */ 0x00, 0x90, 0x00, (0xda^0x11^0xff^0x81^0xb1^0xfe^0x55^0x1f^0x03 - ^0x00^0x31^0x84^0x73^0x80^0x01^0x40^0x00^0x90^0x00) + ^0x00^0x31^0x84^0x73^0x80^0x01^0x80^0x00^0x90^0x00) }; /* * Send back error */ -void -icc_error (int offset) +static void icc_error (struct ccid *c, int offset) { - uint8_t *icc_reply; - - if (icc_chain_p) - icc_reply = icc_chain_p; - else - icc_reply = icc_buffer; + uint8_t icc_reply[ICC_MSG_HEADER_SIZE]; icc_reply[0] = ICC_SLOT_STATUS_RET; /* Any value should be OK */ icc_reply[1] = 0x00; @@ -287,8 +662,8 @@ icc_error (int offset) icc_reply[3] = 0x00; icc_reply[4] = 0x00; icc_reply[5] = 0x00; /* Slot */ - icc_reply[ICC_MSG_SEQ_OFFSET] = icc_seq; - if (icc_state == ICC_STATE_START) + icc_reply[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; + if (c->icc_state == ICC_STATE_START) /* 1: ICC present but not activated 2: No ICC present */ icc_reply[ICC_MSG_STATUS_OFFSET] = 1; else @@ -298,56 +673,55 @@ icc_error (int offset) icc_reply[ICC_MSG_ERROR_OFFSET] = offset; icc_reply[ICC_MSG_CHAIN_OFFSET] = 0x00; - icc_next_p = NULL; /* This is a single transaction Bulk-IN */ - icc_tx_size = ICC_MSG_HEADER_SIZE; - usb_lld_write (ENDP1, icc_reply, icc_tx_size); + /* This is a single packet Bulk-IN transaction */ + c->epi->buf = NULL; + c->epi->tx_done = 1; + usb_lld_write (c->epi->ep_num, icc_reply, ICC_MSG_HEADER_SIZE); } -static Thread *gpg_thread; static WORKING_AREA(waGPGthread, 128*16); extern msg_t GPGthread (void *arg); /* Send back ATR (Answer To Reset) */ enum icc_state -icc_power_on (void) +icc_power_on (struct ccid *c) { - int size_atr; + size_t size_atr = sizeof (ATR); + uint8_t p[ICC_MSG_HEADER_SIZE]; - if (gpg_thread == NULL) - gpg_thread = chThdCreateStatic (waGPGthread, sizeof(waGPGthread), - NORMALPRIO, GPGthread, (void *)icc_thread); + if (c->application == NULL) + c->application = chThdCreateStatic (waGPGthread, sizeof(waGPGthread), + NORMALPRIO, GPGthread, + (void *)c->icc_thread); - size_atr = sizeof (ATR); - icc_buffer[0] = ICC_DATA_BLOCK_RET; - icc_buffer[1] = size_atr; - icc_buffer[2] = 0x00; - icc_buffer[3] = 0x00; - icc_buffer[4] = 0x00; - icc_buffer[5] = 0x00; /* Slot */ - icc_buffer[ICC_MSG_SEQ_OFFSET] = icc_seq; - icc_buffer[ICC_MSG_STATUS_OFFSET] = 0x00; - icc_buffer[ICC_MSG_ERROR_OFFSET] = 0x00; - icc_buffer[ICC_MSG_CHAIN_OFFSET] = 0x00; - memcpy (&icc_buffer[ICC_MSG_DATA_OFFSET], ATR, size_atr); + p[0] = ICC_DATA_BLOCK_RET; + p[1] = size_atr; + p[2] = 0x00; + p[3] = 0x00; + p[4] = 0x00; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; + p[ICC_MSG_STATUS_OFFSET] = 0x00; + p[ICC_MSG_ERROR_OFFSET] = 0x00; + p[ICC_MSG_CHAIN_OFFSET] = 0x00; - icc_next_p = NULL; /* This is a single transaction Bulk-IN */ - icc_tx_size = ICC_MSG_HEADER_SIZE + size_atr; - usb_lld_write (ENDP1, icc_buffer, icc_tx_size); + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE); + usb_lld_txcpy (ATR, c->epi->ep_num, ICC_MSG_HEADER_SIZE, size_atr); + + /* This is a single packet Bulk-IN transaction */ + c->epi->buf = NULL; + c->epi->tx_done = 1; + usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + size_atr); DEBUG_INFO ("ON\r\n"); return ICC_STATE_WAIT; } static void -icc_send_status (void) +icc_send_status (struct ccid *c) { - uint8_t *icc_reply; - - if (icc_chain_p) - icc_reply = icc_chain_p; - else - icc_reply = icc_buffer; + uint8_t icc_reply[ICC_MSG_HEADER_SIZE]; icc_reply[0] = ICC_SLOT_STATUS_RET; icc_reply[1] = 0x00; @@ -355,8 +729,8 @@ icc_send_status (void) icc_reply[3] = 0x00; icc_reply[4] = 0x00; icc_reply[5] = 0x00; /* Slot */ - icc_reply[ICC_MSG_SEQ_OFFSET] = icc_seq; - if (icc_state == ICC_STATE_START) + icc_reply[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; + if (c->icc_state == ICC_STATE_START) /* 1: ICC present but not activated 2: No ICC present */ icc_reply[ICC_MSG_STATUS_OFFSET] = 1; else @@ -365,9 +739,10 @@ icc_send_status (void) icc_reply[ICC_MSG_ERROR_OFFSET] = 0x00; icc_reply[ICC_MSG_CHAIN_OFFSET] = 0x00; - icc_next_p = NULL; /* This is a single transaction Bulk-IN */ - icc_tx_size = ICC_MSG_HEADER_SIZE; - usb_lld_write (ENDP1, icc_reply, icc_tx_size); + /* This is a single packet Bulk-IN transaction */ + c->epi->buf = NULL; + c->epi->tx_done = 1; + usb_lld_write (c->epi->ep_num, icc_reply, ICC_MSG_HEADER_SIZE); #ifdef DEBUG_MORE DEBUG_INFO ("St\r\n"); @@ -375,34 +750,27 @@ icc_send_status (void) } enum icc_state -icc_power_off (void) +icc_power_off (struct ccid *c) { - icc_data_size = 0; - - if (gpg_thread) + if (c->application) { - chThdTerminate (gpg_thread); - chEvtSignal (gpg_thread, EV_NOP); - chThdWait (gpg_thread); - gpg_thread = NULL; + chThdTerminate (c->application); + chEvtSignal (c->application, EV_NOP); + chThdWait (c->application); + c->application = NULL; } - icc_state = ICC_STATE_START; /* This status change should be here */ - icc_send_status (); + c->icc_state = ICC_STATE_START; /* This status change should be here */ + icc_send_status (c); DEBUG_INFO ("OFF\r\n"); return ICC_STATE_START; } static void -icc_send_data_block (int len, uint8_t status, uint8_t chain) +icc_send_data_block_0x9000 (struct ccid *c) { - int tx_size = USB_LL_BUF_SIZE; - uint8_t *p; - - if (icc_chain_p) - p = icc_chain_p; - else - p = icc_buffer; + uint8_t p[ICC_MSG_HEADER_SIZE+2]; + size_t len = 2; p[0] = ICC_DATA_BLOCK_RET; p[1] = len & 0xFF; @@ -410,415 +778,400 @@ icc_send_data_block (int len, uint8_t status, uint8_t chain) p[3] = (len >> 16)& 0xFF; p[4] = (len >> 24)& 0xFF; p[5] = 0x00; /* Slot */ - p[ICC_MSG_SEQ_OFFSET] = icc_seq; - p[ICC_MSG_STATUS_OFFSET] = status; + p[ICC_MSG_SEQ_OFFSET] = c->a->seq; + p[ICC_MSG_STATUS_OFFSET] = 0; p[ICC_MSG_ERROR_OFFSET] = 0; - p[ICC_MSG_CHAIN_OFFSET] = chain; + p[ICC_MSG_CHAIN_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET+1] = 0x90; + p[ICC_MSG_CHAIN_OFFSET+2] = 0x00; - icc_tx_size = ICC_MSG_HEADER_SIZE + len; - if (icc_tx_size < USB_LL_BUF_SIZE) - { - icc_next_p = NULL; - tx_size = icc_tx_size; - } - else - icc_next_p = p + USB_LL_BUF_SIZE; + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len); + c->epi->buf = NULL; + c->epi->tx_done = 1; - usb_lld_write (ENDP1, p, tx_size); + usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len); #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif } static void -icc_send_params (void) +icc_send_data_block (struct ccid *c, uint8_t status) { - icc_buffer[0] = ICC_PARAMS_RET; - icc_buffer[1] = 0x07; /* Length = 0x00000007 */ - icc_buffer[2] = 0; - icc_buffer[3] = 0; - icc_buffer[4] = 0; - icc_buffer[5] = 0x00; /* Slot */ - icc_buffer[ICC_MSG_SEQ_OFFSET] = icc_seq; - icc_buffer[ICC_MSG_STATUS_OFFSET] = 0; - icc_buffer[ICC_MSG_ERROR_OFFSET] = 0; - icc_buffer[ICC_MSG_CHAIN_OFFSET] = 0x01; /* ProtocolNum: T=1 */ - icc_buffer[ICC_MSG_DATA_OFFSET] = 0x11; /* bmFindexDindex */ - icc_buffer[ICC_MSG_DATA_OFFSET+1] = 0x11; /* bmTCCKST1 */ - icc_buffer[ICC_MSG_DATA_OFFSET+2] = 0xFE; /* bGuardTimeT1 */ - icc_buffer[ICC_MSG_DATA_OFFSET+3] = 0x55; /* bmWaitingIntegersT1 */ - icc_buffer[ICC_MSG_DATA_OFFSET+4] = 0x03; /* bClockStop */ - icc_buffer[ICC_MSG_DATA_OFFSET+5] = 0xFE; /* bIFSC */ - icc_buffer[ICC_MSG_DATA_OFFSET+6] = 0; /* bNadValue */ + int tx_size = USB_LL_BUF_SIZE; + uint8_t p[ICC_MSG_HEADER_SIZE]; + size_t len; - icc_next_p = NULL; /* This is a single transaction Bulk-IN */ - icc_tx_size = ICC_MSG_HEADER_SIZE + 7; - usb_lld_write (ENDP1, icc_buffer, icc_tx_size); + if (status == 0) + len = c->a->res_apdu_data_len + 2; + else + len = 0; + + p[0] = ICC_DATA_BLOCK_RET; + p[1] = len & 0xFF; + p[2] = (len >> 8)& 0xFF; + p[3] = (len >> 16)& 0xFF; + p[4] = (len >> 24)& 0xFF; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = c->a->seq; + p[ICC_MSG_STATUS_OFFSET] = status; + p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET] = 0; + + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE); + if (len == 0) + { + usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE); + return; + } + + if (ICC_MSG_HEADER_SIZE + len <= USB_LL_BUF_SIZE) + { + usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num, + ICC_MSG_HEADER_SIZE, c->a->res_apdu_data_len); + usb_lld_txcpy (c->sw1sw2, c->epi->ep_num, + ICC_MSG_HEADER_SIZE + c->a->res_apdu_data_len, 2); + c->epi->buf = NULL; + if (ICC_MSG_HEADER_SIZE + len < USB_LL_BUF_SIZE) + c->epi->tx_done = 1; + tx_size = ICC_MSG_HEADER_SIZE + len; + } + else if (ICC_MSG_HEADER_SIZE + len - 1 == USB_LL_BUF_SIZE) + { + usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num, + ICC_MSG_HEADER_SIZE, c->a->res_apdu_data_len); + usb_lld_txcpy (c->sw1sw2, c->epi->ep_num, + ICC_MSG_HEADER_SIZE + c->a->res_apdu_data_len, 1); + c->epi->buf = &c->sw1sw2[1]; + c->epi->cnt = 1; + c->epi->buf_len = 1; + c->epi->next_buf = no_buf; + } + else if (ICC_MSG_HEADER_SIZE + len - 2 == USB_LL_BUF_SIZE) + { + usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num, + ICC_MSG_HEADER_SIZE, c->a->res_apdu_data_len); + c->epi->buf = &c->sw1sw2[0]; + c->epi->cnt = 0; + c->epi->buf_len = 2; + c->epi->next_buf = no_buf; + } + else + { + usb_lld_txcpy (c->a->res_apdu_data, c->epi->ep_num, ICC_MSG_HEADER_SIZE, + USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE); + c->epi->buf = c->a->res_apdu_data + USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE; + c->epi->cnt = USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE; + c->epi->buf_len = c->a->res_apdu_data_len + - (USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE); + c->epi->next_buf = get_sw1sw2; + } + + usb_lld_tx_enable (c->epi->ep_num, tx_size); #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif } -/* Supporting smaller buffer of libccid (<= 1.3.11) */ -#define ICC_RESPONSE_MSG_DATA_SIZE 262 +static void +icc_send_data_block_gr (struct ccid *c, size_t chunk_len) +{ + int tx_size = USB_LL_BUF_SIZE; + uint8_t p[ICC_MSG_HEADER_SIZE]; + size_t len = chunk_len + 2; + + p[0] = ICC_DATA_BLOCK_RET; + p[1] = len & 0xFF; + p[2] = (len >> 8)& 0xFF; + p[3] = (len >> 16)& 0xFF; + p[4] = (len >> 24)& 0xFF; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = c->a->seq; + p[ICC_MSG_STATUS_OFFSET] = 0; + p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET] = 0; + + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE); + + set_sw1sw2 (c->epi); + + if (chunk_len <= USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE) + { + int size_for_sw; + + if (chunk_len <= USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE - 2) + size_for_sw = 2; + else if (chunk_len == USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE - 1) + size_for_sw = 1; + else + size_for_sw = 0; + + usb_lld_txcpy (c->p, c->epi->ep_num, ICC_MSG_HEADER_SIZE, chunk_len); + if (size_for_sw) + usb_lld_txcpy (c->sw1sw2, c->epi->ep_num, + ICC_MSG_HEADER_SIZE + chunk_len, size_for_sw); + tx_size = ICC_MSG_HEADER_SIZE + chunk_len + size_for_sw; + if (size_for_sw == 2) + { + c->epi->buf = NULL; + if (tx_size < USB_LL_BUF_SIZE) + c->epi->tx_done = 1; + /* Don't set epi->tx_done = 1, when it requires ZLP */ + } + else + { + c->epi->buf = c->sw1sw2 + size_for_sw; + c->epi->cnt = size_for_sw; + c->epi->buf_len = 2 - size_for_sw; + c->epi->next_buf = no_buf; + } + } + else + { + usb_lld_txcpy (c->p, c->epi->ep_num, ICC_MSG_HEADER_SIZE, + USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE); + c->epi->buf = c->p + USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE; + c->epi->cnt = 0; + c->epi->buf_len = chunk_len - (USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE); + c->epi->next_buf = get_sw1sw2; + } + + c->p += chunk_len; + c->len -= chunk_len; + usb_lld_tx_enable (c->epi->ep_num, tx_size); +#ifdef DEBUG_MORE + DEBUG_INFO ("DATA\r\n"); +#endif +} + + +static void +icc_send_params (struct ccid *c) +{ + uint8_t p[ICC_MSG_HEADER_SIZE]; + const uint8_t params[] = { + 0x11, /* bmFindexDindex */ + 0x11, /* bmTCCKST1 */ + 0xFE, /* bGuardTimeT1 */ + 0x55, /* bmWaitingIntegersT1 */ + 0x03, /* bClockStop */ + 0xFE, /* bIFSC */ + 0 /* bNadValue */ + }; + + p[0] = ICC_PARAMS_RET; + p[1] = 0x07; /* Length = 0x00000007 */ + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; + p[ICC_MSG_STATUS_OFFSET] = 0; + p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET] = 0x01; /* ProtocolNum: T=1 */ + + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE); + usb_lld_txcpy (params, c->epi->ep_num, ICC_MSG_HEADER_SIZE, sizeof params); + + /* This is a single packet Bulk-IN transaction */ + c->epi->buf = NULL; + c->epi->tx_done = 1; + usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + sizeof params); +#ifdef DEBUG_MORE + DEBUG_INFO ("PARAMS\r\n"); +#endif +} + static enum icc_state -icc_handle_data (void) +icc_handle_data (struct ccid *c) { - enum icc_state next_state = icc_state; - struct icc_header *icc_header; + enum icc_state next_state = c->icc_state; - if (icc_chain_p) - icc_header = (struct icc_header *)icc_chain_p; - else - icc_header = (struct icc_header *)icc_buffer; + if (c->err != 0) + { + c->err = 0; + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + c->a->cmd_apdu_data_len = 0; + c->a->expected_res_size = 0; + icc_error (c, ICC_OFFSET_DATA_LEN); + return next_state; + } - switch (icc_state) + switch (c->icc_state) { case ICC_STATE_START: - if (icc_header->msg_type == ICC_POWER_ON) - next_state = icc_power_on (); - else if (icc_header->msg_type == ICC_POWER_OFF) - next_state = icc_power_off (); - else if (icc_header->msg_type == ICC_SLOT_STATUS) - icc_send_status (); + if (c->icc_header.msg_type == ICC_POWER_ON) + next_state = icc_power_on (c); + else if (c->icc_header.msg_type == ICC_POWER_OFF) + next_state = icc_power_off (c); + else if (c->icc_header.msg_type == ICC_SLOT_STATUS) + icc_send_status (c); else { DEBUG_INFO ("ERR01\r\n"); - icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); + icc_error (c, ICC_OFFSET_CMD_NOT_SUPPORTED); } break; case ICC_STATE_WAIT: - if (icc_header->msg_type == ICC_POWER_ON) + if (c->icc_header.msg_type == ICC_POWER_ON) /* Not in the spec., but pcscd/libccid */ - next_state = icc_power_on (); - else if (icc_header->msg_type == ICC_POWER_OFF) - next_state = icc_power_off (); - else if (icc_header->msg_type == ICC_SLOT_STATUS) - icc_send_status (); - else if (icc_header->msg_type == ICC_XFR_BLOCK) + next_state = icc_power_on (c); + else if (c->icc_header.msg_type == ICC_POWER_OFF) + next_state = icc_power_off (c); + else if (c->icc_header.msg_type == ICC_SLOT_STATUS) + icc_send_status (c); + else if (c->icc_header.msg_type == ICC_XFR_BLOCK) { - if (icc_header->param == 0) - { /* Give this message to GPG thread */ - run_gpg_thread: - apdu.seq = icc_seq; - apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE]; - - apdu.sw = 0x9000; - apdu.res_apdu_data_len = 0; - apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; - - if (icc_data_size < 4) - { - icc_error (ICC_MSG_HEADER_SIZE + icc_data_size); - next_state = ICC_STATE_WAIT; - break; - } - else if (icc_data_size == 4) - { /* No Lc and No Le */ - apdu.cmd_apdu_data = NULL; - apdu.cmd_apdu_data_len = 0; - apdu.expected_res_size = 0; - apdu.cmd_apdu_head[4] = 0; - } - else if (icc_data_size == 5) - { /* No Lc but Le */ - apdu.cmd_apdu_data = NULL; - apdu.cmd_apdu_data_len = 0; - apdu.expected_res_size = apdu.cmd_apdu_head[4]; - if (apdu.expected_res_size == 0) - apdu.expected_res_size = 256; - apdu.cmd_apdu_head[4] = 0; - } - else if (apdu.cmd_apdu_head[4] == 0) - { /* extended Lc or extended Le */ - apdu.cmd_apdu_data = apdu.cmd_apdu_head + 7; - apdu.cmd_apdu_data_len - = (apdu.cmd_apdu_head[5] << 8) + apdu.cmd_apdu_head[6]; - if (icc_data_size == 7) - { /* No Lc but extended Le */ - apdu.expected_res_size = apdu.cmd_apdu_data_len; - apdu.cmd_apdu_data_len = 0; - } - else if (icc_data_size == apdu.cmd_apdu_data_len + 7) - apdu.expected_res_size = 0; - else if (icc_data_size == apdu.cmd_apdu_data_len + 7 + 2) - { - apdu.expected_res_size - = (icc_buffer[ICC_MSG_HEADER_SIZE + 7 - + apdu.cmd_apdu_data_len] << 8) - | icc_buffer[ICC_MSG_HEADER_SIZE + 7 - + apdu.cmd_apdu_data_len + 1]; - if (apdu.expected_res_size == 0) - apdu.expected_res_size = 65536; - } - else - { - icc_error (ICC_MSG_HEADER_SIZE + 5); - next_state = ICC_STATE_WAIT; - break; - } - } - else /* short Lc */ - { - apdu.cmd_apdu_data = apdu.cmd_apdu_head + 5; - apdu.cmd_apdu_data_len = apdu.cmd_apdu_head[4]; - if (icc_data_size == apdu.cmd_apdu_data_len + 5) - apdu.expected_res_size = 0; - else if (icc_data_size == apdu.cmd_apdu_data_len + 5 + 1) - { - apdu.expected_res_size - = icc_buffer[ICC_MSG_HEADER_SIZE + 5 - + apdu.cmd_apdu_data_len]; - if (apdu.expected_res_size == 0) - apdu.expected_res_size = 256; - } - else - { - icc_error (ICC_MSG_HEADER_SIZE + 5); - next_state = ICC_STATE_WAIT; - break; - } - } - - chEvtSignal (gpg_thread, EV_CMD_AVAILABLE); - next_state = ICC_STATE_EXECUTE; - } - else if (icc_header->param == 1) + if (c->icc_header.param == 0) { - icc_chain_p = icc_next_p; - icc_send_data_block (0, 0, 0x10); - next_state = ICC_STATE_RECEIVE; + DEBUG_INFO ("DUMP C\r\n"); + DEBUG_SHORT (c->icc_state); + DEBUG_BYTE (c->state); + DEBUG_WORD (c->p); + DEBUG_WORD (c->len); + DEBUG_BYTE (c->err); + DEBUG_WORD (c->epo->buf); + DEBUG_WORD (c->epo->cnt); + DEBUG_WORD (c->epo->buf_len); + DEBUG_WORD (c->a->cmd_apdu_data); + DEBUG_BINARY (c->a->cmd_apdu_data, c->a->cmd_apdu_data_len); + + if ((c->a->cmd_apdu_head[0] & 0x10) == 0) + { + if (c->state == APDU_STATE_COMMAND_CHAINING) + { /* command chaining finished */ + c->p += c->a->cmd_apdu_head[4]; + c->a->cmd_apdu_head[4] = 0; + c->a->cmd_apdu_data_len = c->p - c->a->cmd_apdu_data; + DEBUG_INFO ("CMD chaning finished.\r\n"); + } + + if (c->a->cmd_apdu_head[1] == INS_GET_RESPONSE + && c->state == APDU_STATE_RESULT_GET_RESPONSE) + { + size_t len = c->a->expected_res_size; + + if (c->len <= c->a->expected_res_size) + len = c->len; + + icc_send_data_block_gr (c, len); + if (c->len == 0) + c->state = APDU_STATE_RESULT; + c->icc_state = ICC_STATE_WAIT; + } + else + { /* Give this message to GPG thread */ + c->state = APDU_STATE_COMMAND_RECEIVED; + + c->a->sw = 0x9000; + c->a->res_apdu_data_len = 0; + c->a->res_apdu_data = &icc_buffer[5]; + + chEvtSignal (c->application, EV_CMD_AVAILABLE); + next_state = ICC_STATE_EXECUTE; + } + } + else /* command chaining is ongoing*/ + { + c->state = APDU_STATE_COMMAND_CHAINING; + c->p += c->a->cmd_apdu_head[4]; + c->len -= c->a->cmd_apdu_head[4]; + icc_send_data_block_0x9000 (c); + DEBUG_INFO ("CMD chaning...\r\n"); + } } else - { + { /* ICC block chaining is not supported. */ DEBUG_INFO ("ERR02\r\n"); - icc_error (ICC_OFFSET_PARAM); + icc_error (c, ICC_OFFSET_PARAM); } } - else if (icc_header->msg_type == ICC_SET_PARAMS - || icc_header->msg_type == ICC_GET_PARAMS) - icc_send_params (); - else if (icc_header->msg_type == ICC_SECURE) + else if (c->icc_header.msg_type == ICC_SET_PARAMS + || c->icc_header.msg_type == ICC_GET_PARAMS) + icc_send_params (c); + else if (c->icc_header.msg_type == ICC_SECURE) { if (icc_buffer[10] == 0x00) /* PIN verification */ { - icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[25]; - icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[26]; - icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[27]; - icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[28]; + icc_buffer[0] = icc_buffer[25-10]; + icc_buffer[1] = icc_buffer[26-10]; + icc_buffer[2] = icc_buffer[27-10]; + icc_buffer[3] = icc_buffer[28-10]; /**/ - icc_buffer[ICC_MSG_HEADER_SIZE+5] = 0; /* bConfirmPIN */ - icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[17]; /* bEntryValidationCondition */ - icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[18]; /* bNumberMessage */ - icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[19]; /* wLangId L */ - icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[20]; /* wLangId H */ - icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[21]; /* bMsgIndex */ + icc_buffer[5] = 0; /* bConfirmPIN */ + icc_buffer[6] = icc_buffer[17-10]; /* bEntryValidationCondition */ + icc_buffer[7] = icc_buffer[18-10]; /* bNumberMessage */ + icc_buffer[8] = icc_buffer[19-10]; /* wLangId L */ + icc_buffer[9] = icc_buffer[20-10]; /* wLangId H */ + icc_buffer[10] = icc_buffer[21-10]; /* bMsgIndex */ - apdu.seq = icc_seq; - apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0]; - apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5]; - apdu.cmd_apdu_data_len = 6; - apdu.expected_res_size = 0; + c->a->cmd_apdu_data_len = 6; + c->a->expected_res_size = 0; - apdu.sw = 0x9000; - apdu.res_apdu_data_len = 0; - apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; + c->a->sw = 0x9000; + c->a->res_apdu_data_len = 0; + c->a->res_apdu_data = &icc_buffer[5]; - chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE); + chEvtSignal (c->application, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else if (icc_buffer[10] == 0x01) /* PIN Modification */ { - uint8_t num_msgs = icc_buffer[21]; + uint8_t num_msgs = icc_buffer[21-10]; if (num_msgs == 0x00) num_msgs = 1; else if (num_msgs == 0xff) num_msgs = 3; - icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[27 + num_msgs]; - icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[28 + num_msgs]; - icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[29 + num_msgs]; - icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[30 + num_msgs]; + icc_buffer[0] = icc_buffer[27 + num_msgs-10]; + icc_buffer[1] = icc_buffer[28 + num_msgs-10]; + icc_buffer[2] = icc_buffer[29 + num_msgs-10]; + icc_buffer[3] = icc_buffer[30 + num_msgs-10]; /**/ - icc_buffer[ICC_MSG_HEADER_SIZE+5] = icc_buffer[19]; /* bConfirmPIN */ - icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[20]; /* bEntryValidationCondition */ - icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[21]; /* bNumberMessage */ - icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[22]; /* wLangId L */ - icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[23]; /* wLangId H */ - icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */ + icc_buffer[5] = icc_buffer[19-10]; /* bConfirmPIN */ + icc_buffer[6] = icc_buffer[20-10]; /* bEntryValidationCondition */ + icc_buffer[7] = icc_buffer[21-10]; /* bNumberMessage */ + icc_buffer[8] = icc_buffer[22-10]; /* wLangId L */ + icc_buffer[9] = icc_buffer[23-10]; /* wLangId H */ + icc_buffer[10] = icc_buffer[24-10]; /* bMsgIndex, bMsgIndex1 */ if (num_msgs >= 2) - icc_buffer[ICC_MSG_HEADER_SIZE+11] = icc_buffer[25]; /* bMsgIndex2 */ + icc_buffer[11] = icc_buffer[25-10]; /* bMsgIndex2 */ if (num_msgs == 3) - icc_buffer[ICC_MSG_HEADER_SIZE+12] = icc_buffer[26]; /* bMsgIndex3 */ + icc_buffer[12] = icc_buffer[26-10]; /* bMsgIndex3 */ - apdu.seq = icc_seq; - apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0]; - apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5]; - apdu.cmd_apdu_data_len = 5 + num_msgs; - apdu.expected_res_size = 0; + c->a->cmd_apdu_data_len = 5 + num_msgs; + c->a->expected_res_size = 0; - apdu.sw = 0x9000; - apdu.res_apdu_data_len = 0; - apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE]; + c->a->sw = 0x9000; + c->a->res_apdu_data_len = 0; + c->a->res_apdu_data = &icc_buffer[5]; - chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE); + chEvtSignal (c->application, EV_MODIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } else - icc_error (ICC_MSG_DATA_OFFSET); + icc_error (c, ICC_MSG_DATA_OFFSET); } else { DEBUG_INFO ("ERR03\r\n"); - DEBUG_BYTE (icc_header->msg_type); - icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); - } - break; - case ICC_STATE_RECEIVE: - if (icc_header->msg_type == ICC_POWER_OFF) - { - icc_chain_p = NULL; - next_state = icc_power_off (); - } - else if (icc_header->msg_type == ICC_SLOT_STATUS) - icc_send_status (); - else if (icc_header->msg_type == ICC_XFR_BLOCK) - { - if (icc_header->param == 2) /* Got the final block */ - { /* Give this message to GPG thread */ - int len = icc_next_p - icc_chain_p - ICC_MSG_HEADER_SIZE; - - memmove (icc_chain_p, icc_chain_p + ICC_MSG_HEADER_SIZE, len); - icc_next_p -= ICC_MSG_HEADER_SIZE; - icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE; - icc_chain_p = NULL; - goto run_gpg_thread; - } - else /* icc_header->param == 3 is not supported. */ - { - DEBUG_INFO ("ERR08\r\n"); - icc_error (ICC_OFFSET_PARAM); - } - } - else - { - DEBUG_INFO ("ERR05\r\n"); - DEBUG_BYTE (icc_header->msg_type); - icc_chain_p = NULL; - icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); - next_state = ICC_STATE_WAIT; + DEBUG_BYTE (c->icc_header.msg_type); + icc_error (c, ICC_OFFSET_CMD_NOT_SUPPORTED); } break; case ICC_STATE_EXECUTE: - if (icc_header->msg_type == ICC_POWER_OFF) - next_state = icc_power_off (); - else if (icc_header->msg_type == ICC_SLOT_STATUS) - icc_send_status (); + if (c->icc_header.msg_type == ICC_POWER_OFF) + next_state = icc_power_off (c); + else if (c->icc_header.msg_type == ICC_SLOT_STATUS) + icc_send_status (c); else { DEBUG_INFO ("ERR04\r\n"); - DEBUG_BYTE (icc_header->msg_type); - icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); - } - break; - case ICC_STATE_SEND: - if (icc_header->msg_type == ICC_POWER_OFF) - next_state = icc_power_off (); - else if (icc_header->msg_type == ICC_SLOT_STATUS) - icc_send_status (); - else if (icc_header->msg_type == ICC_XFR_BLOCK) - { - if (icc_header->param == 0x10) - { - int len = apdu.res_apdu_data_len; - - if (apdu.res_apdu_data == NULL) - { /* send status word(s) of 0x9000 */ - len = 0; - - if (apdu.res_apdu_data_len == 2) - { - icc_buffer[ICC_MSG_HEADER_SIZE] = 0x90; - len++; - } - - icc_buffer[ICC_MSG_HEADER_SIZE+len] = 0x00; - len++; - } - else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) - { - if (apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); - apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; - apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; - } - else if (apdu.res_apdu_data_len == ICC_RESPONSE_MSG_DATA_SIZE) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); - apdu.res_apdu_data = NULL; - apdu.res_apdu_data_len = 2; - } - else if (apdu.res_apdu_data_len - == ICC_RESPONSE_MSG_DATA_SIZE - 1) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, apdu.res_apdu_data_len); - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] - = 0x90; - apdu.res_apdu_data = NULL; - apdu.res_apdu_data_len = 1; - len += 1; - } - else if (apdu.res_apdu_data_len - <= ICC_RESPONSE_MSG_DATA_SIZE - 2) - { - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, apdu.res_apdu_data_len); - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] - = 0x90; - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] - = 0x00; - apdu.res_apdu_data = NULL; - apdu.res_apdu_data_len = 0; - len += 2; - } - } - else - { - memmove (&icc_buffer[ICC_MSG_HEADER_SIZE], - &icc_buffer[ICC_MSG_HEADER_SIZE] - +ICC_RESPONSE_MSG_DATA_SIZE, - apdu.res_apdu_data_len); - apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; - } - - if (len <= ICC_RESPONSE_MSG_DATA_SIZE) - { - icc_send_data_block (len, 0, 0x02); - next_state = ICC_STATE_WAIT; - } - else - icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03); - } - else - { - DEBUG_INFO ("ERR0A\r\n"); - DEBUG_BYTE (icc_header->param >> 8); - DEBUG_BYTE (icc_header->param & 0xff); - icc_error (ICC_OFFSET_PARAM); - next_state = ICC_STATE_WAIT; - } - } - else - { - DEBUG_INFO ("ERR06\r\n"); - DEBUG_BYTE (icc_header->msg_type); - icc_error (ICC_OFFSET_CMD_NOT_SUPPORTED); - next_state = ICC_STATE_WAIT; + DEBUG_BYTE (c->icc_header.msg_type); + icc_error (c, ICC_OFFSET_CMD_NOT_SUPPORTED); } break; default: @@ -831,14 +1184,14 @@ icc_handle_data (void) } static enum icc_state -icc_handle_timeout (void) +icc_handle_timeout (struct ccid *c) { - enum icc_state next_state = icc_state; + enum icc_state next_state = c->icc_state; - switch (icc_state) + switch (c->icc_state) { case ICC_STATE_EXECUTE: - icc_send_data_block (0, ICC_CMD_STATUS_TIMEEXT, 0); + icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT); break; default: break; @@ -849,17 +1202,28 @@ icc_handle_timeout (void) #define USB_ICC_TIMEOUT MS2ST(1950) + +static struct ccid ccid; + + msg_t USBthread (void *arg) { + struct ep_in *epi = &endpoint_in; + struct ep_out *epo = &endpoint_out; + struct ccid *c = &ccid; + struct apdu *a = &apdu; + (void)arg; - icc_thread = chThdSelf (); + epi_init (epi, ENDP1, notify_tx, c); + epo_init (epo, ENDP2, notify_icc, c); + ccid_init (c, epi, epo, a, chThdSelf ()); + apdu_init (a); + chEvtClear (ALL_EVENTS); - icc_state = ICC_STATE_START; - - icc_prepare_receive (0); + icc_prepare_receive (c); while (1) { eventmask_t m; @@ -867,52 +1231,52 @@ USBthread (void *arg) m = chEvtWaitOneTimeout (ALL_EVENTS, USB_ICC_TIMEOUT); if (m == EV_RX_DATA_READY) - icc_state = icc_handle_data (); + c->icc_state = icc_handle_data (c); else if (m == EV_EXEC_FINISHED) - if (icc_state == ICC_STATE_EXECUTE) + if (c->icc_state == ICC_STATE_EXECUTE) { - if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE]) - { - /* Assume that - * apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE - */ - memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE], - apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE); - apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE; - } - else - { - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] = (apdu.sw >> 8); - icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = (apdu.sw & 0xff); - apdu.res_apdu_data_len += 2; - } + c->a->cmd_apdu_data_len = 0; + c->sw1sw2[0] = c->a->sw >> 8; + c->sw1sw2[1] = c->a->sw & 0xff; - if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE) + if (c->a->res_apdu_data_len <= c->a->expected_res_size) { - icc_send_data_block (apdu.res_apdu_data_len, 0, 0); - icc_state = ICC_STATE_WAIT; + c->state = APDU_STATE_RESULT; + icc_send_data_block (c, 0); + c->icc_state = ICC_STATE_WAIT; } else { - icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01); - apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE; - icc_state = ICC_STATE_SEND; + c->state = APDU_STATE_RESULT_GET_RESPONSE; + c->p = c->a->res_apdu_data; + c->len = c->a->res_apdu_data_len; + icc_send_data_block_gr (c, c->a->expected_res_size); + c->icc_state = ICC_STATE_WAIT; } } else - { /* error */ + { DEBUG_INFO ("ERR07\r\n"); } else if (m == EV_TX_FINISHED) { - if (icc_state == ICC_STATE_START || icc_state == ICC_STATE_WAIT - || icc_state == ICC_STATE_SEND) - icc_prepare_receive (0); - else if (icc_state == ICC_STATE_RECEIVE) - icc_prepare_receive (1); + if (c->state == APDU_STATE_RESULT) + { + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + c->err = 0; + c->a->cmd_apdu_data_len = 0; + c->a->expected_res_size = 0; + } + + if (c->state == APDU_STATE_WAIT_COMMAND + || c->state == APDU_STATE_COMMAND_CHAINING + || c->state == APDU_STATE_RESULT_GET_RESPONSE) + icc_prepare_receive (c); } else /* Timeout */ - icc_state = icc_handle_timeout (); + c->icc_state = icc_handle_timeout (c); } return 0; diff --git a/src/usb_desc.c b/src/usb_desc.c index 43c09eb..fdb2f37 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -102,7 +102,7 @@ static const uint8_t gnukConfigDescriptor[] = { * ccid-driver. */ 0x42, 0x08, 0x04, 0x00, /* dwFeatures (not ICCD): - * Short and extended APDU level: 0x40000 * + * Short APDU level : 0x20000 * * (what? means ICCD?) : 0x00800 * * Automatic IFSD : 0x00400 * NAD value other than 0x00 : 0x00200 @@ -115,7 +115,7 @@ static const uint8_t gnukConfigDescriptor[] = { * Auto activaction of ICC : 0x00004 * Automatic conf. based on ATR : 0x00002 g */ - 0x40, 0x01, 0, 0, /* dwMaxCCIDMessageLength */ + 0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */ 0xff, /* bClassGetResponse: */ 0xff, /* bClassEnvelope: */ 0, 0, /* wLCDLayout: FIXED VALUE */ diff --git a/src/usb_lld.c b/src/usb_lld.c index 97c9f8d..4af51fe 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -27,3 +27,76 @@ void usb_lld_init (void) { RCC->APB1RSTR = RCC_APB1RSTR_USBRST; RCC->APB1RSTR = 0; } + +void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n) +{ + const uint8_t *s = (const uint8_t *)src; + uint16_t *p; + uint16_t w; + + if (n == 0) + return; + + if ((wPMABufAddr & 1)) + { + p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2); + w = *p; + w = (w & 0xff) | (*s++) << 8; + *p = w; + p += 2; + n--; + } + else + p = (uint16_t *)(PMAAddr + wPMABufAddr * 2); + + while (n >= 2) + { + w = *s++; + w |= (*s++) << 8; + *p = w; + p += 2; + n -= 2; + } + + if (n > 0) + { + w = *s; + *p = w; + } +} + +void usb_lld_from_pmabuf (void *dst, uint16_t wPMABufAddr, size_t n) +{ + uint8_t *d = (uint8_t *)dst; + uint16_t *p; + uint16_t w; + + if (n == 0) + return; + + if ((wPMABufAddr & 1)) + { + p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2); + w = *p; + *d++ = (w >> 8); + p += 2; + n--; + } + else + p = (uint16_t *)(PMAAddr + wPMABufAddr * 2); + + while (n >= 2) + { + w = *p; + *d++ = (w & 0xff); + *d++ = (w >> 8); + p += 2; + n -= 2; + } + + if (n > 0) + { + w = *p; + *d = (w & 0xff); + } +} diff --git a/src/usb_lld.h b/src/usb_lld.h index 0ec00d3..a74dcd7 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -1,6 +1,9 @@ #define STM32_USB_IRQ_PRIORITY 11 void usb_lld_init (void); +extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n); +extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n); + extern inline void usb_lld_stall_tx (int ep_num) { SetEPTxStatus (ep_num, EP_TX_STALL); @@ -16,10 +19,10 @@ extern inline int usb_lld_tx_data_len (int ep_num) return GetEPTxCount (ep_num); } -extern inline void usb_lld_txcpy (const uint8_t *src, +extern inline void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len) { - UserToPMABufferCopy ((uint8_t *)src, GetEPTxAddr (ep_num) + offset, len); + usb_lld_to_pmabuf (src, GetEPTxAddr (ep_num) + offset, len); } extern inline void usb_lld_tx_enable (int ep_num, size_t len) @@ -28,9 +31,9 @@ extern inline void usb_lld_tx_enable (int ep_num, size_t len) SetEPTxValid (ep_num); } -extern inline void usb_lld_write (uint8_t ep_num, void *buf, size_t len) +extern inline void usb_lld_write (uint8_t ep_num, const void *buf, size_t len) { - UserToPMABufferCopy (buf, GetEPTxAddr (ep_num), len); + usb_lld_to_pmabuf (buf, GetEPTxAddr (ep_num), len); SetEPTxCount (ep_num, len); SetEPTxValid (ep_num); } @@ -48,5 +51,5 @@ extern inline int usb_lld_rx_data_len (int ep_num) extern inline void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len) { - PMAToUserBufferCopy (dst, GetEPRxAddr (ep_num) + offset, len); + usb_lld_from_pmabuf (dst, GetEPRxAddr (ep_num) + offset, len); } diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index d3de957..0b81194 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -44,7 +44,7 @@ class GnukToken(object): self.connection = cardservice.connection def cmd_verify(self, who, passwd): - apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd) + apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd) response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) @@ -59,10 +59,20 @@ class GnukToken(object): while count*256 < data_len: if count == 0: d = data[:256] - apdu = [0x00, ins, 0x80+fileid, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d) + if len(d) <= 255: + apdu = [0x00, ins, 0x80+fileid, 0x00, len(d) ] + s2l(d) + else: + apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255 ] + s2l(d[:255]) + response, sw1, sw2 = self.connection.transmit(apdu0) + apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:]) else: d = data[256*count:256*(count+1)] - apdu = [0x00, ins, count, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d) + if len(d) <= 255: + apdu = [0x00, ins, count, 0x00, len(d) ] + s2l(d) + else: + apdu0 = [0x10, ins, count, 0x00, 255 ] + s2l(d[:255]) + response, sw1, sw2 = self.connection.transmit(apdu0) + apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:]) response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): if is_update: @@ -72,13 +82,13 @@ class GnukToken(object): count += 1 def cmd_select_openpgp(self): - apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_get_data(self, tagh, tagl): - apdu = [0x00, 0xca, tagh, tagl] + apdu = [0x00, 0xca, tagh, tagl ] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) @@ -146,18 +156,6 @@ if __name__ == '__main__': exit(1) print "Writing serial number" data = binascii.unhexlify(serial_data_hex) - elif sys.argv[1] == '-r': - fileid = 1 # Random number bits - if len(sys.argv) == 3: - filename = sys.argv[2] - f = open(filename) - else: - filename = stdin - f = sys.stdin - data = f.read() - f.close() - print "%s: %d" % (filename, len(data)) - print "Updating random bits" else: fileid = 0 # Card holder certificate filename = sys.argv[1] From aff9080b357638946901e6642feadfe090daecb8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jan 2012 23:57:23 +0900 Subject: [PATCH 059/300] add alignment for gnuk.ld.in, add ChangeLog entries. --- ChangeLog | 64 ++++++++++++++++++++ src/configure | 2 +- src/gnuk.ld.in | 1 + src/openpgp-do.c | 6 +- src/usb-icc.c | 130 +++++++++++++++++++++++----------------- tool/gnuk_put_binary.py | 2 +- 6 files changed, 146 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93a69d3..3394576 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,67 @@ +2012-01-20 Niibe Yutaka + + Short APDU only CCID driver. + * STM32_USB-FS-Device_Driver/src/usb_core.c (DataStageOut) + (DataStageIn): Use usb_lld_to_pmabuf and usb_lld_from_pmabuf. + + * src/configure (CERTDO_SUPPORT): Comment fix. + + * src/gnuk.h (struct adpu): expected_res_size has type uint16_t. + (MAX_CMD_APDU_DATA_SIZE, MAX_RES_APDU_DATA_SIZE): New. + (MAX_CMD_APDU_SIZE, MAX_RES_APDU_SIZE, USB_BUF_SIZE): Remove. + (icc_state_p): New. + (set_res_sw): Rename from set_res_apdu. + + * src/call-rsa.c (rsa_decrypt): Use MAX_RES_APDU_DATA_SIZE. + + * src/openpgp.c (set_res_sw): Rename from set_res_apdu. + * src/openpgp.h: Use set_res_sw. + + * src/main.c: Handle icc_state_p. + + * src/openpgp-do.c (historical_bytes): command chaining but short + APDU only. + (extended_capabilities): Change for short APDU only. + + * src/usb-icc.c (USB_BUF_SIZE): Define here (was in gnuk.h). + (struct ep_in, epi_init, struct ep_out, epo_init, endpoint_out) + (endpoint_in, icc_state_p, struct ccid, APDU_STATE_WAIT_COMMAND) + (APDU_STATE_COMMAND_CHAINING, APDU_STATE_COMMAND_RECEIVED) + (APDU_STATE_RESULT, APDU_STATE_RESULT_GET_RESPONSE, ccid_reset) + (ccid_init, CMD_APDU_HEAD_SIZE, apdu_init, notify_tx, no_buf) + (set_sw1sw2, get_sw1sw2, notify_icc, end_icc_rx, end_abdata) + (end_cmd_apdu_head, end_nomore_data, end_cmd_apdu_data) + (nomore_data, INS_GET_RESPONSE, icc_cmd_apdu_data, icc_abdata) + (icc_send_data_block_0x9000, icc_send_data_block_gr, ccid): New. + (icc_data_size, icc_seq, icc_next_p, icc_chain_p, icc_tx_size) + (icc_thread, icc_state, gpg_thread, ICC_RESPONSE_MSG_DATA_SIZE): + Remove. + (EP1_IN_Callback): Rewrite using epi. + (EP2_OUT_Callback): Rewrite using epo. + (icc_prepare_receive): Rewrite using epo and struct ccid. + (ATR): Change ofr short APDU only. + (icc_error, icc_power_on, icc_send_status, icc_power_off) + (icc_send_data_block, icc_send_params, icc_handle_data) + (icc_handle_timeout, USBthread): Rewrite using struct ccid. + + * src/usb_desc.c (gnukConfigDescriptor): dwFeatures: Short APDU + level, dwMaxCCIDMessageLength: 271. + + * src/usb_lld.c (usb_lld_to_pmabuf, usb_lld_from_pmabuf): New. + * src/usb_lld.h (usb_lld_txcpy, void usb_lld_write) Use + usb_lld_to_pmabuf. + (usb_lld_rxcpy): Use usb_lld_from_pmabuf. + + * src/stmusb.mk (usb_mem.c): Remove. + + * gnuk_put_binary.py (cmd_select_openpgp): No response APDU data. + (cmd_verify, cmd_write_binary): Send short APDU. + (__main__): Remove RANDOM_NUMBER_BITS support. + + Bug fix for CERTDO_SUPPORT. + * src/gnuk.ld.in: Add missing alignment for _data_pool (when no + CERTDO_SUPPORT). + 2012-01-19 Niibe Yutaka * src/usb-icc.c (icc_handle_data): Handle the case when it only diff --git a/src/configure b/src/configure index fb86998..d357cdb 100755 --- a/src/configure +++ b/src/configure @@ -173,7 +173,7 @@ fi # --enable-certdo option if test "$certdo" = "yes"; then CERTDO_DEFINE="#define CERTDO_SUPPORT 1" - echo "CERT.3 Data Object is supported (Note: it is not supported by GnuPG)" + echo "CERT.3 Data Object is supported" else CERTDO_DEFINE="#undef CERTDO_SUPPORT" echo "CERT.3 Data Object is not supported" diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 7bc613a..31f0387 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -128,6 +128,7 @@ SECTIONS .gnuk_flash : { + . = ALIGN (@FLASH_PAGE_SIZE@); _data_pool = .; KEEP(*(.gnuk_data)) . = ALIGN(@FLASH_PAGE_SIZE@); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index f0cd355..d263663 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -103,10 +103,10 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = { #else 0x00, 0x00, #endif - /* Max. length of command APDU */ - 0x00, 0xff, - /* Max. length of response data */ + /* Max. length of command APDU data */ 0x00, 0xff, + /* Max. length of response APDU data */ + 0x01, 0x00, }; /* Algorithm Attributes */ diff --git a/src/usb-icc.c b/src/usb-icc.c index f392fd8..239fcbd 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -234,6 +234,16 @@ struct ccid { #define APDU_STATE_RESULT 3 #define APDU_STATE_RESULT_GET_RESPONSE 4 +static void ccid_reset (struct ccid *c) +{ + c->err = 0; + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + c->a->cmd_apdu_data_len = 0; + c->a->expected_res_size = 0; +} + static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, struct apdu *a, Thread *t) { @@ -412,10 +422,18 @@ static int end_icc_rx (struct ep_out *epo, size_t orig_len) return 0; } -static int end_notify (struct ep_out *epo, size_t orig_len) +static int end_abdata (struct ep_out *epo, size_t orig_len) { - (void)epo; - (void)orig_len; + struct ccid *c = (struct ccid *)epo->priv; + size_t len = epo->cnt; + + if (orig_len == USB_LL_BUF_SIZE && len < c->icc_header.data_len) + /* more packet comes */ + return 1; + + if (len != c->icc_header.data_len) + epo->err = 1; + return 0; } @@ -537,6 +555,7 @@ static void icc_abdata (struct ep_out *epo, size_t len) struct ccid *c = (struct ccid *)epo->priv; (void)len; + c->a->seq = c->icc_header.seq; if (c->icc_header.msg_type == ICC_XFR_BLOCK) { c->a->seq = c->icc_header.seq; @@ -548,7 +567,7 @@ static void icc_abdata (struct ep_out *epo, size_t len) } else { - epo->end_rx = end_notify; + epo->end_rx = end_abdata; epo->buf = c->p; epo->buf_len = c->len; epo->cnt = 0; @@ -990,12 +1009,7 @@ icc_handle_data (struct ccid *c) if (c->err != 0) { - c->err = 0; - c->state = APDU_STATE_WAIT_COMMAND; - c->p = c->a->cmd_apdu_data; - c->len = MAX_CMD_APDU_DATA_SIZE; - c->a->cmd_apdu_data_len = 0; - c->a->expected_res_size = 0; + ccid_reset (c); icc_error (c, ICC_OFFSET_DATA_LEN); return next_state; } @@ -1004,9 +1018,15 @@ icc_handle_data (struct ccid *c) { case ICC_STATE_START: if (c->icc_header.msg_type == ICC_POWER_ON) - next_state = icc_power_on (c); + { + ccid_reset (c); + next_state = icc_power_on (c); + } else if (c->icc_header.msg_type == ICC_POWER_OFF) - next_state = icc_power_off (c); + { + ccid_reset (c); + next_state = icc_power_off (c); + } else if (c->icc_header.msg_type == ICC_SLOT_STATUS) icc_send_status (c); else @@ -1017,35 +1037,28 @@ icc_handle_data (struct ccid *c) break; case ICC_STATE_WAIT: if (c->icc_header.msg_type == ICC_POWER_ON) - /* Not in the spec., but pcscd/libccid */ - next_state = icc_power_on (c); + { + /* Not in the spec., but pcscd/libccid */ + ccid_reset (c); + next_state = icc_power_on (c); + } else if (c->icc_header.msg_type == ICC_POWER_OFF) - next_state = icc_power_off (c); + { + ccid_reset (c); + next_state = icc_power_off (c); + } else if (c->icc_header.msg_type == ICC_SLOT_STATUS) icc_send_status (c); else if (c->icc_header.msg_type == ICC_XFR_BLOCK) { if (c->icc_header.param == 0) { - DEBUG_INFO ("DUMP C\r\n"); - DEBUG_SHORT (c->icc_state); - DEBUG_BYTE (c->state); - DEBUG_WORD (c->p); - DEBUG_WORD (c->len); - DEBUG_BYTE (c->err); - DEBUG_WORD (c->epo->buf); - DEBUG_WORD (c->epo->cnt); - DEBUG_WORD (c->epo->buf_len); - DEBUG_WORD (c->a->cmd_apdu_data); - DEBUG_BINARY (c->a->cmd_apdu_data, c->a->cmd_apdu_data_len); - if ((c->a->cmd_apdu_head[0] & 0x10) == 0) { if (c->state == APDU_STATE_COMMAND_CHAINING) { /* command chaining finished */ c->p += c->a->cmd_apdu_head[4]; c->a->cmd_apdu_head[4] = 0; - c->a->cmd_apdu_data_len = c->p - c->a->cmd_apdu_data; DEBUG_INFO ("CMD chaning finished.\r\n"); } @@ -1061,6 +1074,7 @@ icc_handle_data (struct ccid *c) if (c->len == 0) c->state = APDU_STATE_RESULT; c->icc_state = ICC_STATE_WAIT; + DEBUG_INFO ("GET Response.\r\n"); } else { /* Give this message to GPG thread */ @@ -1094,53 +1108,61 @@ icc_handle_data (struct ccid *c) icc_send_params (c); else if (c->icc_header.msg_type == ICC_SECURE) { - if (icc_buffer[10] == 0x00) /* PIN verification */ + if (c->p != c->a->cmd_apdu_data) { - icc_buffer[0] = icc_buffer[25-10]; - icc_buffer[1] = icc_buffer[26-10]; - icc_buffer[2] = icc_buffer[27-10]; - icc_buffer[3] = icc_buffer[28-10]; + /* SECURE received in the middle of command chaining */ + ccid_reset (c); + icc_error (c, ICC_OFFSET_DATA_LEN); + return next_state; + } + + if (c->p[10-10] == 0x00) /* PIN verification */ + { + c->a->cmd_apdu_head[0] = c->p[25-10]; + c->a->cmd_apdu_head[1] = c->p[26-10]; + c->a->cmd_apdu_head[2] = c->p[27-10]; + c->a->cmd_apdu_head[3] = c->p[28-10]; /**/ - icc_buffer[5] = 0; /* bConfirmPIN */ - icc_buffer[6] = icc_buffer[17-10]; /* bEntryValidationCondition */ - icc_buffer[7] = icc_buffer[18-10]; /* bNumberMessage */ - icc_buffer[8] = icc_buffer[19-10]; /* wLangId L */ - icc_buffer[9] = icc_buffer[20-10]; /* wLangId H */ - icc_buffer[10] = icc_buffer[21-10]; /* bMsgIndex */ + c->a->cmd_apdu_data[0] = 0; /* bConfirmPIN */ + c->a->cmd_apdu_data[1] = c->p[17-10]; /* bEntryValidationCondition */ + c->a->cmd_apdu_data[2] = c->p[18-10]; /* bNumberMessage */ + c->a->cmd_apdu_data[3] = c->p[19-10]; /* wLangId L */ + c->a->cmd_apdu_data[4] = c->p[20-10]; /* wLangId H */ + c->a->cmd_apdu_data[5] = c->p[21-10]; /* bMsgIndex */ c->a->cmd_apdu_data_len = 6; c->a->expected_res_size = 0; c->a->sw = 0x9000; c->a->res_apdu_data_len = 0; - c->a->res_apdu_data = &icc_buffer[5]; + c->a->res_apdu_data = &c->p[5]; chEvtSignal (c->application, EV_VERIFY_CMD_AVAILABLE); next_state = ICC_STATE_EXECUTE; } - else if (icc_buffer[10] == 0x01) /* PIN Modification */ + else if (c->p[10-10] == 0x01) /* PIN Modification */ { - uint8_t num_msgs = icc_buffer[21-10]; + uint8_t num_msgs = c->p[21-10]; if (num_msgs == 0x00) num_msgs = 1; else if (num_msgs == 0xff) num_msgs = 3; - icc_buffer[0] = icc_buffer[27 + num_msgs-10]; - icc_buffer[1] = icc_buffer[28 + num_msgs-10]; - icc_buffer[2] = icc_buffer[29 + num_msgs-10]; - icc_buffer[3] = icc_buffer[30 + num_msgs-10]; + c->a->cmd_apdu_head[0] = c->p[27 + num_msgs-10]; + c->a->cmd_apdu_head[1] = c->p[28 + num_msgs-10]; + c->a->cmd_apdu_head[2] = c->p[29 + num_msgs-10]; + c->a->cmd_apdu_head[3] = c->p[30 + num_msgs-10]; /**/ - icc_buffer[5] = icc_buffer[19-10]; /* bConfirmPIN */ - icc_buffer[6] = icc_buffer[20-10]; /* bEntryValidationCondition */ - icc_buffer[7] = icc_buffer[21-10]; /* bNumberMessage */ - icc_buffer[8] = icc_buffer[22-10]; /* wLangId L */ - icc_buffer[9] = icc_buffer[23-10]; /* wLangId H */ - icc_buffer[10] = icc_buffer[24-10]; /* bMsgIndex, bMsgIndex1 */ + c->a->cmd_apdu_data[0] = c->p[19-10]; /* bConfirmPIN */ + c->a->cmd_apdu_data[1] = c->p[20-10]; /* bEntryValidationCondition */ + c->a->cmd_apdu_data[2] = c->p[21-10]; /* bNumberMessage */ + c->a->cmd_apdu_data[3] = c->p[22-10]; /* wLangId L */ + c->a->cmd_apdu_data[4] = c->p[23-10]; /* wLangId H */ + c->a->cmd_apdu_data[5] = c->p[24-10]; /* bMsgIndex, bMsgIndex1 */ if (num_msgs >= 2) - icc_buffer[11] = icc_buffer[25-10]; /* bMsgIndex2 */ + c->a->cmd_apdu_data[6] = c->p[25-10]; /* bMsgIndex2 */ if (num_msgs == 3) - icc_buffer[12] = icc_buffer[26-10]; /* bMsgIndex3 */ + c->a->cmd_apdu_data[7] = c->p[26-10]; /* bMsgIndex3 */ c->a->cmd_apdu_data_len = 5 + num_msgs; c->a->expected_res_size = 0; diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 0b81194..d43ea4c 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -88,7 +88,7 @@ class GnukToken(object): raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_get_data(self, tagh, tagl): - apdu = [0x00, 0xca, tagh, tagl ] + apdu = [0x00, 0xca, tagh, tagl] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) From 3d732a7c2d951a7fd312daea9a4115741e188845 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Feb 2012 12:18:47 +0900 Subject: [PATCH 060/300] command chaining change --- ChangeLog | 6 ++++++ src/usb-icc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3394576..c25214c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-01-30 Niibe Yutaka + + * src/usb-icc.c (struct ccid): Add chained_cls_ins_p1_p2. + (end_cmd_apdu_head, icc_cmd_apdu_data, icc_handle_data): Add checking + CMD APDU head for command chaining. + 2012-01-20 Niibe Yutaka Short APDU only CCID driver. diff --git a/src/usb-icc.c b/src/usb-icc.c index 239fcbd..47b7bef 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -191,6 +191,7 @@ struct ccid { struct icc_header icc_header; uint8_t sw1sw2[2]; + uint8_t chained_cls_ins_p1_p2[4]; Thread *icc_thread; Thread *application; @@ -444,7 +445,29 @@ static int end_cmd_apdu_head (struct ep_out *epo, size_t orig_len) (void)orig_len; if (epo->cnt < 4 || epo->cnt != c->icc_header.data_len) - epo->err = 1; + { + epo->err = 1; + return 0; + } + + if ((c->state == APDU_STATE_COMMAND_CHAINING) + && (c->chained_cls_ins_p1_p2[0] != (c->a->cmd_apdu_head[0] & ~0x10) + || c->chained_cls_ins_p1_p2[1] != c->a->cmd_apdu_head[1] + || c->chained_cls_ins_p1_p2[2] != c->a->cmd_apdu_head[2] + || c->chained_cls_ins_p1_p2[3] != c->a->cmd_apdu_head[3])) + /* + * Handling exceptional request. + * + * Host stops sending command APDU using command chaining, + * and start another command APDU. + * + * Discard old one, and start handling new one. + */ + { + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + } if (epo->cnt == 4) { @@ -542,6 +565,27 @@ static void icc_cmd_apdu_data (struct ep_out *epo, size_t len) c->p = c->a->cmd_apdu_data; c->len = MAX_CMD_APDU_DATA_SIZE; } + else if (c->state == APDU_STATE_COMMAND_CHAINING) + { + if (c->chained_cls_ins_p1_p2[0] != (c->a->cmd_apdu_head[0] & ~0x10) + || c->chained_cls_ins_p1_p2[1] != c->a->cmd_apdu_head[1] + || c->chained_cls_ins_p1_p2[2] != c->a->cmd_apdu_head[2] + || c->chained_cls_ins_p1_p2[3] != c->a->cmd_apdu_head[3]) + /* + * Handling exceptional request. + * + * Host stops sending command APDU using command chaining, + * and start another command APDU. + * + * Discard old one, and start handling new one. + */ + { + c->state = APDU_STATE_WAIT_COMMAND; + c->p = c->a->cmd_apdu_data; + c->len = MAX_CMD_APDU_DATA_SIZE; + c->a->cmd_apdu_data_len = 0; + } + } epo->end_rx = end_cmd_apdu_data; epo->buf = c->p; @@ -1088,9 +1132,15 @@ icc_handle_data (struct ccid *c) next_state = ICC_STATE_EXECUTE; } } - else /* command chaining is ongoing*/ + else { - c->state = APDU_STATE_COMMAND_CHAINING; + if (c->state == APDU_STATE_WAIT_COMMAND) + { /* command chaining is started */ + c->a->cmd_apdu_head[0] &= ~0x10; + memcpy (c->chained_cls_ins_p1_p2, c->a->cmd_apdu_head, 4); + c->state = APDU_STATE_COMMAND_CHAINING; + } + c->p += c->a->cmd_apdu_head[4]; c->len -= c->a->cmd_apdu_head[4]; icc_send_data_block_0x9000 (c); From 6550dd5353bacc7dc0774de78bdf931909750d4f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Feb 2012 13:15:23 +0900 Subject: [PATCH 061/300] space removal --- src/usb-icc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/usb-icc.c b/src/usb-icc.c index 47b7bef..7766bcf 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -280,7 +280,7 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, * * While the device is receiving something, there is no possibility * for the device to send anything. - * + * * Thus, the buffer can be shared for RX and TX. * * Exception: When we support ABORT of CCID, it is possible to receive @@ -970,7 +970,7 @@ icc_send_data_block_gr (struct ccid *c, size_t chunk_len) size_for_sw = 0; usb_lld_txcpy (c->p, c->epi->ep_num, ICC_MSG_HEADER_SIZE, chunk_len); - if (size_for_sw) + if (size_for_sw) usb_lld_txcpy (c->sw1sw2, c->epi->ep_num, ICC_MSG_HEADER_SIZE + chunk_len, size_for_sw); tx_size = ICC_MSG_HEADER_SIZE + chunk_len + size_for_sw; @@ -1161,7 +1161,7 @@ icc_handle_data (struct ccid *c) if (c->p != c->a->cmd_apdu_data) { /* SECURE received in the middle of command chaining */ - ccid_reset (c); + ccid_reset (c); icc_error (c, ICC_OFFSET_DATA_LEN); return next_state; } From 14673b825b9b40b826cac7d2804a0417c3f1ceb4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Feb 2012 14:09:38 +0900 Subject: [PATCH 062/300] version 0.17 --- ChangeLog | 9 +++++++++ NEWS | 11 ++++++++--- README | 23 ++++++++++------------- src/usb_desc.c | 2 +- tool/gnuk_put_binary.py | 15 +++++++++++++-- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index c25214c..6ef6448 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-02-02 Niibe Yutaka + + * Version 0.17. + + * src/usb_desc.c (gnukStringSerial): Updated. + + * tool/gnuk_put_binary.py (cmd_get_response): New. + (cmd_select_openpgp, cmd_get_data): Call cmd_get_response. + 2012-01-30 Niibe Yutaka * src/usb-icc.c (struct ccid): Add chained_cls_ins_p1_p2. diff --git a/NEWS b/NEWS index 73df182..8293239 100644 --- a/NEWS +++ b/NEWS @@ -2,14 +2,19 @@ Gnuk NEWS - User visible changes * Major changes in Gnuk 0.17 - Released 2012-01-XX, by NIIBE Yutaka + Released 2012-02-02, by NIIBE Yutaka -** ISO 7816 SELECT command behavior is strict now +** USB CCID/ICCD protocol implementation change +Gnuk now only supports short APDU level exchange, not support. +extended APDU level exchange. Thus, Gnuk could be compatible to older +host side software implementation. + +** ISO 7816 SELECT command behavior is somewhat strict now Old implementations do not check DF name for SELECT command. This causes some trouble when Gnuk Token is identified as if it were different card/token. Now, DF name of OpenPGP card is checked. -** USB CCID/ICCD low level bug is fixed +** USB CCID/ICCD low-level bug is fixed When the size of command APDU data is just 49, the lower level packet size is 64. This is maximum size of BULK-OUT transfer packet, and caused trouble in the past implementations. Example is setting url diff --git a/README b/README index c3aa877..25ad9c5 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token - Version 0.16 - 2011-12-14 + Version 0.17 + 2012-02-02 Niibe Yutaka Free Software Initiative of Japan @@ -104,12 +104,15 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: and at the tab of "Startup Programs", disable check buttons for "GPG Password Agent" and "SSH Key Agent". +Qc: Do you know a good SWD debugger to connect FST-01 or something? +Ac: Perhaps, you can use a part of STM32F4 Discovery Kit as SWD + debugger. It seems that there is a free software tool for that. Release notes ============= -This is seventeenth release of Gnuk. While it works well for specific +This is eighteenth release of Gnuk. While it works well for specific usages and it is considered stable, it is still somewhat experimental. Tested features are: @@ -127,18 +130,13 @@ Tested features are: * Changing value of password status bytes (0x00C4): forcesig * Verify with pin pad * Modify with pin pad + * Card holder certificate It is known not-working well: * For some version of kernel and libccid, --enable-debug can't - work well. Please disable DEBUG option if it doesn't work well. - - * Card holder certificate - It is implemented in Gnuk side. But its large size matters - (> 1KB). Some versions of GnuPG cannot handle a data object - of large size with PC/SC backend. Specifically, - handle_transmit function in pcsc-wrapper.c uses the buffer - of size 1024-byte. + work well. Please make sure to disable DEBUG option if it + doesn't work well. Not supported feature(s): @@ -241,8 +239,7 @@ Gnuk is distributed with external source code. Host Requirements ================= -For GNU/Linux, libccid version >= 1.3.11 is required. -libccid version == 1.3.9 is known not working well by the issue [r4235]. +For GNU/Linux, libccid version >= 1.3.11 is recommended. I think that it should not be requirment but the kernel version of my use is: Linux version 2.6.32-5-686 (Debian 2.6.32-18) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-2) ) #1 SMP Sat Jul 24 02:27:10 UTC 2010 diff --git a/src/usb_desc.c b/src/usb_desc.c index fdb2f37..887cbee 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -275,7 +275,7 @@ static const uint8_t gnukStringProduct[] = { const uint8_t gnukStringSerial[] = { 13*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - '0', 0, '.', 0, '1', 0, '6', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '1', 0, '7', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index d43ea4c..f29f763 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -43,6 +43,13 @@ class GnukToken(object): cardservice = cardrequest.waitforcard() self.connection = cardservice.connection + def cmd_get_response(self, expected_len): + apdu = [0x00, 0xc0, 0x00, 0x00, expected_len ] + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + return response + def cmd_verify(self, who, passwd): apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd) response, sw1, sw2 = self.connection.transmit(apdu) @@ -84,13 +91,17 @@ class GnukToken(object): def cmd_select_openpgp(self): apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] response, sw1, sw2 = self.connection.transmit(apdu) - if not (sw1 == 0x90 and sw2 == 0x00): + if sw1 == 0x61: + response = self.cmd_get_response(sw2) + elif not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_get_data(self, tagh, tagl): apdu = [0x00, 0xca, tagh, tagl] response, sw1, sw2 = self.connection.transmit(apdu) - if not (sw1 == 0x90 and sw2 == 0x00): + if sw1 == 0x61: + response = self.cmd_get_response(sw2) + elif not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) return response From c98f1fe8c60402dcd4924ef7dbd27db23cd9ef7e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Feb 2012 14:17:51 +0900 Subject: [PATCH 063/300] fix usb config --- ChangeLog | 1 + src/usb_desc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6ef6448..98f0f26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ * Version 0.17. * src/usb_desc.c (gnukStringSerial): Updated. + (gnukConfigDescriptor): Short APDU only. * tool/gnuk_put_binary.py (cmd_get_response): New. (cmd_select_openpgp, cmd_get_data): Call cmd_get_response. diff --git a/src/usb_desc.c b/src/usb_desc.c index 887cbee..eec9bc6 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -101,7 +101,7 @@ static const uint8_t gnukConfigDescriptor[] = { * It is different now for better interaction to GPG's in-stock * ccid-driver. */ - 0x42, 0x08, 0x04, 0x00, /* dwFeatures (not ICCD): + 0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD): * Short APDU level : 0x20000 * * (what? means ICCD?) : 0x00800 * * Automatic IFSD : 0x00400 From b56c3b81ec26106462c0e8350d5c8a8b78f24b15 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 10 May 2012 19:01:01 +0900 Subject: [PATCH 064/300] New USB stack --- ChangeLog | 136 ++ NEWS | 9 + README | 10 - STM32_USB-FS-Device_Driver/inc/otgd_fs_cal.h | 258 --- STM32_USB-FS-Device_Driver/inc/otgd_fs_dev.h | 121 -- STM32_USB-FS-Device_Driver/inc/otgd_fs_int.h | 54 - STM32_USB-FS-Device_Driver/inc/otgd_fs_pcd.h | 87 - STM32_USB-FS-Device_Driver/inc/otgd_fs_regs.h | 1592 ----------------- STM32_USB-FS-Device_Driver/inc/usb_core.h | 243 --- STM32_USB-FS-Device_Driver/inc/usb_def.h | 80 - STM32_USB-FS-Device_Driver/inc/usb_init.h | 49 - STM32_USB-FS-Device_Driver/inc/usb_int.h | 33 - STM32_USB-FS-Device_Driver/inc/usb_lib.h | 50 - STM32_USB-FS-Device_Driver/inc/usb_mem.h | 32 - STM32_USB-FS-Device_Driver/inc/usb_regs.h | 670 ------- STM32_USB-FS-Device_Driver/inc/usb_sil.h | 34 - STM32_USB-FS-Device_Driver/inc/usb_type.h | 74 - STM32_USB-FS-Device_Driver/src/otgd_fs_cal.c | 1334 -------------- STM32_USB-FS-Device_Driver/src/otgd_fs_dev.c | 386 ---- STM32_USB-FS-Device_Driver/src/otgd_fs_int.c | 874 --------- STM32_USB-FS-Device_Driver/src/otgd_fs_pcd.c | 454 ----- STM32_USB-FS-Device_Driver/src/usb_core.c | 1088 ----------- STM32_USB-FS-Device_Driver/src/usb_init.c | 63 - STM32_USB-FS-Device_Driver/src/usb_int.c | 188 -- STM32_USB-FS-Device_Driver/src/usb_mem.c | 75 - STM32_USB-FS-Device_Driver/src/usb_regs.c | 750 -------- STM32_USB-FS-Device_Driver/src/usb_sil.c | 126 -- Virtual_COM_Port/hw_config.c | 113 -- Virtual_COM_Port/hw_config.h | 41 - Virtual_COM_Port/platform.h | 57 - Virtual_COM_Port/platform_config.h | 52 - Virtual_COM_Port/usb_conf.h | 197 -- Virtual_COM_Port/usb_desc.c | 161 -- Virtual_COM_Port/usb_desc.h | 53 - Virtual_COM_Port/usb_endp.c | 67 - Virtual_COM_Port/usb_istr.c | 419 ----- Virtual_COM_Port/usb_istr.h | 104 -- Virtual_COM_Port/usb_prop.c | 419 ----- Virtual_COM_Port/usb_prop.h | 74 - Virtual_COM_Port/usb_pwr.c | 251 --- Virtual_COM_Port/usb_pwr.h | 59 - boards/common/hw_config.c | 30 +- src/Makefile.in | 9 +- src/main.c | 8 - src/stmusb.mk | 7 - src/usb-cdc-vport.c | 93 - src/usb-icc.c | 4 - src/usb_conf.h | 21 +- src/usb_desc.c | 23 +- src/usb_endp.c | 8 +- src/usb_lld.c | 1143 +++++++++++- src/usb_lld.h | 172 +- src/usb_msc.c | 2 - src/usb_prop.c | 522 +++--- src/usb_prop.h | 7 - src/vcomport.mk | 5 - 56 files changed, 1648 insertions(+), 11343 deletions(-) delete mode 100644 STM32_USB-FS-Device_Driver/inc/otgd_fs_cal.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/otgd_fs_dev.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/otgd_fs_int.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/otgd_fs_pcd.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/otgd_fs_regs.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_core.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_def.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_init.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_int.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_lib.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_mem.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_regs.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_sil.h delete mode 100644 STM32_USB-FS-Device_Driver/inc/usb_type.h delete mode 100644 STM32_USB-FS-Device_Driver/src/otgd_fs_cal.c delete mode 100644 STM32_USB-FS-Device_Driver/src/otgd_fs_dev.c delete mode 100644 STM32_USB-FS-Device_Driver/src/otgd_fs_int.c delete mode 100644 STM32_USB-FS-Device_Driver/src/otgd_fs_pcd.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_core.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_init.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_int.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_mem.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_regs.c delete mode 100644 STM32_USB-FS-Device_Driver/src/usb_sil.c delete mode 100644 Virtual_COM_Port/hw_config.c delete mode 100644 Virtual_COM_Port/hw_config.h delete mode 100644 Virtual_COM_Port/platform.h delete mode 100644 Virtual_COM_Port/platform_config.h delete mode 100644 Virtual_COM_Port/usb_conf.h delete mode 100644 Virtual_COM_Port/usb_desc.c delete mode 100644 Virtual_COM_Port/usb_desc.h delete mode 100644 Virtual_COM_Port/usb_endp.c delete mode 100644 Virtual_COM_Port/usb_istr.c delete mode 100644 Virtual_COM_Port/usb_istr.h delete mode 100644 Virtual_COM_Port/usb_prop.c delete mode 100644 Virtual_COM_Port/usb_prop.h delete mode 100644 Virtual_COM_Port/usb_pwr.c delete mode 100644 Virtual_COM_Port/usb_pwr.h delete mode 100644 src/stmusb.mk delete mode 100644 src/usb-cdc-vport.c delete mode 100644 src/usb_prop.h delete mode 100644 src/vcomport.mk diff --git a/ChangeLog b/ChangeLog index 98f0f26..239f3c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,139 @@ +2012-05-10 Niibe Yutaka + + * STM32_USB-FS-Device_Driver, Virtual_COM_Port: Remove. + + * src/usb_lld.c (#include): Don't include usb_lib.h. + (RECIPIENT, REG_BASE PMA_ADDR, CNTR, ISTR, FNR, DADDR, BTABLE) + (ISTR_CTR, ISTR_DOVR, ISTR_ERR, ISTR_WKUP, ISTR_SUSP, ISTR_RESET) + (ISTR_SOF, ISTR_ESOF, ISTR_DIR, ISTR_EP_ID, CLR_CTR, CLR_DOVR) + (CLR_ERR, CLR_WKUP, CLR_SUSP, CLR_RESET, CLR_SOF, CLR_ESOF) + (CNTR_CTRM, CNTR_DOVRM, CNTR_ERRM, CNTR_WKUPM, CNTR_SUSPM) + (CNTR_RESETM, CNTR_SOFM, CNTR_ESOFM, CNTR_RESUME, CNTR_FSUSP) + (CNTR_LPMODE, CNTR_PDWN, CNTR_FRES, DADDR_EF, DADDR_ADD) + (EP_CTR_RX, EP_DTOG_RX, EPRX_STAT, EP_SETUP, EP_T_FIELD, EP_KIND) + (EP_CTR_TX, EP_DTOG_TX, EPTX_STAT, EPADDR_FIELD, EPREG_MASK) + (EP_TX_DIS, EP_TX_STALL, EP_TX_NAK, EP_TX_VALID, EPTX_DTOG1) + (EPTX_DTOG2, EP_RX_DIS, EP_RX_STALL, EP_RX_NAK, EP_RX_VALID) + (EPRX_DTOG1, EPRX_DTOG2): New. Compatible to ST's USB-FS-Device_Lib. + (CH_IRQ_HANDLER): Call usb_interrupt_handler (was: USB_Istr). + (EP1_IN_Callback, EP2_IN_Callback, EP3_IN_Callback) + (EP4_IN_Callback, EP5_IN_Callback, EP6_IN_Callback) + (EP7_IN_Callback, EP1_OUT_Callback, EP2_OUT_Callback) + (EP3_OUT_Callback, EP4_OUT_Callback, EP5_OUT_Callback) + (EP6_OUT_Callback, EP7_OUT_Callback): New. Implement here. + Compatible to ST's USB-FS-Device_Lib. + (USB_MAX_PACKET_SIZE): New. + (GET_STATUS, CLEAR_FEATURE, RESERVED1, SET_FEATURE, RESERVED2) + (SET_ADDRESS, GET_DESCRIPTOR, SET_DESCRIPTOR, GET_CONFIGURATION) + (SET_CONFIGURATION, GET_INTERFACE, SET_INTERFACE) + (SYNCH_FRAME,TOTAL_REQUEST): New for USB control transfer. + (enum CONTROL_STATE): New for state machine of control pipe. + (enum FEATURE_SELECTOR): New. + (struct DATA_INFO, struct CONTROL_INFO, struct DEVICE_INFO): New. + (ctrl_p, dev_p, data_p, Control_Info, Device_Info, Data_Info): + New. + (usb_lld_stall_tx, usb_lld_stall_rx) + (usb_lld_tx_data_len, usb_lld_txcpy, usb_lld_tx_enable) + (usb_lld_write, usb_lld_rx_enable, usb_lld_rx_data_len) + (usb_lld_rxcpy): Move from usb_lld.h and not inline. + (usb_lld_reset, usb_lld_setup_endpoint) + (usb_lld_set_configuration, usb_lld_current_configuration) + (usb_lld_set_feature, usb_lld_set_data_to_send): New. + (usb_lld_to_pmabuf, usb_lld_from_pmabuf): Clean up. + (usb_lld_init): New implementation. + (st103_set_btable, st103_get_istr, st103_set_istr, st103_set_cntr) + (st103_set_daddr, st103_set_epreg, st103_get_epreg) + (st103_set_tx_addr, st103_get_tx_addr, st103_set_tx_count) + (st103_get_tx_count, st103_set_rx_addr, st103_get_rx_addr) + (st103_set_rx_buf_size, st103_get_rx_count, st103_ep_clear_ctr_rx) + (st103_ep_clear_ctr_tx, st103_ep_set_rxtx_status) + (st103_ep_set_rx_status, st103_ep_get_rx_status) + (st103_ep_set_tx_status, st103_ep_get_tx_status) + (st103_ep_clear_dtog_rx, st103_ep_clear_dtog_tx): New lower-level + functions for USB related registers access. + (usb_interrupt_handler, usb_handle_transfer) + (handle_datastage_out, handle_datastage_in, handle_setup0) + (handle_in0, handle_out0) + (std_none, std_get_status, std_clear_feature, std_set_feature, + std_set_address, std_get_descriptor, std_get_configuration, + std_set_configuration, std_get_interface, std_set_interface) + (std_request_handler): New USB stack implementation. + + * src/usb_lld.h (usb_lld_stall_tx, usb_lld_stall_rx) + (usb_lld_tx_data_len, usb_lld_txcpy, usb_lld_tx_enable) + (usb_lld_write, usb_lld_rx_enable, usb_lld_rx_data_len) + (usb_lld_rxcpy): Those are not inline functions anymore. + (USB_DEVICE_DESCRIPTOR_TYPE, USB_CONFIGURATION_DESCRIPTOR_TYPE) + (USB_STRING_DESCRIPTOR_TYPE, USB_INTERFACE_DESCRIPTOR_TYPE) + (USB_ENDPOINT_DESCRIPTOR_TYPE, STANDARD_ENDPOINT_DESC_SIZE) + (ENDP0, ENDP1, ENDP2, ENDP3, ENDP4, ENDP5, ENDP6, ENDP7) + (EP_BULK, EP_CONTROL, EP_ISOCHRONOUS, EP_INTERRUPT) + (DEVICE_RECIPIENT, INTERFACE_RECIPIENT, ENDPOINT_RECIPIENT) + (ENDPOINT_RECIPIENT, OTHER_RECIPIENT) + (DEVICE_DESCRIPTOR, CONFIG_DESCRIPTOR, STRING_DESCRIPTOR) + (INTERFACE_DESCRIPTOR, ENDPOINT_DESCRIPTOR) + (REQUEST_TYPE, STANDARD_REQUEST, CLASS_REQUEST, VENDOR_REQUEST) + (USB_UNSUPPORT, USB_SUCCESS) + (USB_EVENT_RESET, USB_EVENT_ADDRESS, USB_EVENT_CONFIG) + (USB_EVENT_SUSPEND, USB_EVENT_WAKEUP, USB_EVENT_STALL) + (USB_SET_INTERFACE, USB_GET_INTERFACE, USB_QUERY_INTERFACE) + (UNCONNECTED, ATTACHED, POWERED, SUSPENDED, ADDRESSED) + (CONFIGURED, USB_Cable_Config): New. Compatible to ST's + USB-FS-Device_Lib. + (struct Descriptor, struct usb_device_method) + (Device_Descriptor, Config_Descriptor, String_Descriptors) + (STM32_USB_IRQ_PRIORITY, bDeviceState, Device_Method) + (usb_lld_init, usb_lld_reset, usb_lld_setup_endpoint) + (usb_lld_set_configuration, usb_lld_current_configuration) + (usb_lld_set_feature, usb_lld_set_data_to_send): New API. + + * src/usb_prop.c(#include): Only include usb_lld.h for USB. + (SetEPRxCount_allocated_size): Remove. + (struct line_coding, line_coding, Virtual_Com_Port_Data_Setup) + (Virtual_Com_Port_NoData_Setup): Add from usb-cdc-vport.c. + (gnuk_device_init, gnuk_device_reset, gnuk_setup_with_data) + (gnuk_setup_with_nodata): Follow the API change of USB stack. + (gnuk_setup_endpoints_for_interface, gnuk_get_descriptor) + (gnuk_usb_event, gnuk_interface): New. + (gnuk_device_SetConfiguration, gnuk_device_SetInterface) + (gnuk_device_SetDeviceAddress, gnuk_device_Status_In) + (gnuk_device_Status_Out, gnuk_device_GetDeviceDescriptor) + (gnuk_device_GetConfigDescriptor, gnuk_device_GetStringDescriptor) + (gnuk_device_Get_Interface_Setting, gnuk_clock_frequencies) + (gnuk_data_rates, msc_lun_info, Device_Table) + (User_Standard_Requests): Remove. + (Device_Method): Replace Device_Property. + + * src/usb_msc.c (#include): Only include usb_lld.h for USB. + + * src/usb_endp.c (#include): Only include usb_lld.h for USB. + (EP5_OUT_Callback): Follow the API change of USB stack. + + * src/usb_desc.c (#include): Only include usb_lld.h for USB. + Add usb_conf.h. + (Device_Descriptor, Config_Descriptor): Follow the API change + of USB stack. + (String_Descriptors): New, rename from String_Descriptor. + + * src/usb_conf.h (EP_NUM, BTABLE_ADDRESS, IMR_MSK): Remove. + (NUM_STRING_DESC): Add. + + * src/usb-icc.c (#include): Only include usb_lld.h for USB. + + * src/usb-cdc-vport.c, src/usb_prop.h: Remove. + + * src/stmusb.mk, src/vcomport.mk: Remove. + + * src/main.c (#include): Only include usb_lld.h for USB. + (main): Remove call to USB_Init. + + * src/Makefile.in (include): Remove stmusb.mk, vcomport.mk. + (VCOMSRC) [ENABLE_VCOMPORT]: Add. + (INCDIR): Remove STMUSBINCDIR and VCOMDIR. + + * boards/common/hw_config.c (Enter_LowPowerMode) + (Leave_LowPowerMode): Remove. + 2012-02-02 Niibe Yutaka * Version 0.17. diff --git a/NEWS b/NEWS index 8293239..8c055cd 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,14 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 0.18 + + Released 2012-05-XX, by NIIBE Yutaka + +** New USB stack +Gnuk used to use USB stack of USB-FS-Device_Lib by ST. Now, it has +original implementation. Hopefully, size and quality are improved. + + * Major changes in Gnuk 0.17 Released 2012-02-02, by NIIBE Yutaka diff --git a/README b/README index 25ad9c5..227bd52 100644 --- a/README +++ b/README @@ -225,16 +225,6 @@ Gnuk is distributed with external source code. 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 - - STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib) - is a STM32F10x library for USB functionality. - - I took Libraries/STM32_USB-FS-Device_Driver and - Project/Virtual_COM_Port in STM32_USB-FS-Device_Lib distribution. - See http://www.st.com/ for detail. - Host Requirements ================= diff --git a/STM32_USB-FS-Device_Driver/inc/otgd_fs_cal.h b/STM32_USB-FS-Device_Driver/inc/otgd_fs_cal.h deleted file mode 100644 index 17761d4..0000000 --- a/STM32_USB-FS-Device_Driver/inc/otgd_fs_cal.h +++ /dev/null @@ -1,258 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_cal.h -* Author : STMicroelectronics -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Header of OTG FS Device Core Access Layer interface. -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ -#ifndef __OTG_CORE_H__ -#define __OTG_CORE_H__ - -#ifdef STM32F10X_CL - -#include "stm32f10x.h" -#include "usb_type.h" - -#if defined ( __CC_ARM ) - #define __packed __packed /*!< packing keyword for ARM Compiler */ -#elif defined ( __ICCARM__ ) - #define __packed __packed /*!< packing keyword for IAR Compiler */ -#elif defined ( __GNUC__ ) - #define __packed __attribute__ ((__packed__)) /*!< packing keyword for GNU Compiler */ -#elif defined ( __TASKING__ ) /*!< packing keyword for TASKING Compiler */ - #define __packed -#endif /* __CC_ARM */ - -/******************************************************************************* - define and types -*******************************************************************************/ - -#define DEVICE_MODE_ENABLED - -#ifndef NULL -#define NULL ((void *)0) -#endif - - -#define DEV_EP_TX_DIS 0x0000 -#define DEV_EP_TX_STALL 0x0010 -#define DEV_EP_TX_NAK 0x0020 -#define DEV_EP_TX_VALID 0x0030 - -#define DEV_EP_RX_DIS 0x0000 -#define DEV_EP_RX_STALL 0x1000 -#define DEV_EP_RX_NAK 0x2000 -#define DEV_EP_RX_VALID 0x3000 - -/***************** GLOBAL DEFINES ***************************/ - -#define GAHBCFG_TXFEMPTYLVL_EMPTY 1 -#define GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 - -#define GAHBCFG_GLBINT_ENABLE 1 -#define GAHBCFG_INT_DMA_BURST_SINGLE 0 -#define GAHBCFG_INT_DMA_BURST_INCR 1 -#define GAHBCFG_INT_DMA_BURST_INCR4 3 -#define GAHBCFG_INT_DMA_BURST_INCR8 5 -#define GAHBCFG_INT_DMA_BURST_INCR16 7 -#define GAHBCFG_DMAENABLE 1 -#define GAHBCFG_TXFEMPTYLVL_EMPTY 1 -#define GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 - -#define GRXSTS_PKTSTS_IN 2 -#define GRXSTS_PKTSTS_IN_XFER_COMP 3 -#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5 -#define GRXSTS_PKTSTS_CH_HALTED 7 - -#define DEVICE_MODE 0 -#define HOST_MODE 1 - -/***************** DEVICE DEFINES ***************************/ - -#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 -#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 -#define DSTS_ENUMSPD_LS_PHY_6MHZ 2 -#define DSTS_ENUMSPD_FS_PHY_48MHZ 3 - -#define DCFG_FRAME_INTERVAL_80 0 -#define DCFG_FRAME_INTERVAL_85 1 -#define DCFG_FRAME_INTERVAL_90 2 -#define DCFG_FRAME_INTERVAL_95 3 - -#define DEP0CTL_MPS_64 0 -#define DEP0CTL_MPS_32 1 -#define DEP0CTL_MPS_16 2 -#define DEP0CTL_MPS_8 3 - -#define EP_SPEED_LOW 0 -#define EP_SPEED_FULL 1 -#define EP_SPEED_HIGH 2 - -#define EP_TYPE_CTRL 0 -#define EP_TYPE_ISOC 1 -#define EP_TYPE_BULK 2 -#define EP_TYPE_INTR 3 - -#define STS_GOUT_NAK 1 -#define STS_DATA_UPDT 2 -#define STS_XFER_COMP 3 -#define STS_SETUP_COMP 4 -#define STS_SETUP_UPDT 6 - - - - -typedef enum { - - USB_OTG_OK, - USB_OTG_FAIL - -}USB_OTG_Status; - -typedef struct USB_OTG_hc -{ - uint8_t hc_num; - uint8_t dev_addr ; - uint8_t ep_num; - uint8_t ep_is_in; - uint8_t speed; - uint8_t ep_type; - uint16_t max_packet; - uint8_t data_pid; - uint16_t multi_count; - uint8_t *xfer_buff; - uint32_t xfer_len; -} -USB_OTG_HC , *PUSB_OTG_HC; - -typedef struct USB_OTG_ep -{ - uint8_t num; - uint8_t is_in; - uint32_t tx_fifo_num; - uint32_t type; - uint8_t data_pid_start; - uint8_t even_odd_frame; - uint32_t maxpacket; - uint8_t *xfer_buff; - uint32_t xfer_len; - uint32_t xfer_count; -} - -USB_OTG_EP , *PUSB_OTG_EP; - -/******************************************************************************** - MACRO'S -********************************************************************************/ - -#define CLEAR_IN_EP_INTR(epnum,intr) \ - diepint.d32=0; \ - diepint.b.intr = 1; \ - WRITE_REG32(&core_regs.inep_regs[epnum]->dev_in_ep_int,diepint.d32); - -#define CLEAR_OUT_EP_INTR(epnum,intr) \ - doepint.d32=0; \ - doepint.b.intr = 1; \ - WRITE_REG32(&core_regs.outep_regs[epnum]->dev_out_ep_int,doepint.d32); - - -#define READ_REG32(reg) (*(__IO uint32_t *)reg) - -#define WRITE_REG32(reg,value) (*(__IO uint32_t *)reg = value) - -#define MODIFY_REG32(reg,clear_mask,set_mask) \ - WRITE_REG32(reg, (((READ_REG32(reg)) & ~clear_mask) | set_mask ) ) - - -#define uDELAY(usec) udelay(usec) -#define mDELAY(msec) uDELAY(msec * 1000) - -#define _OTGD_FS_GATE_PHYCLK *(__IO uint32_t*)(0x50000E00) = 0x03 -#define _OTGD_FS_UNGATE_PHYCLK *(__IO uint32_t*)(0x50000E00) = 0x00 - -/******************************************************************************* - this can be changed for real time base -*******************************************************************************/ -static void udelay (const uint32_t usec) -{ - uint32_t count = 0; - const uint32_t utime = usec * 10; - do - { - if ( ++count > utime ) - { - return ; - } - } - while (1); -} -/******************************************************************************** - EXPORTED FUNCTIONS FROM THE OTGD_FS_CAL LAYER -********************************************************************************/ -USB_OTG_Status OTGD_FS_CoreInit(void); -USB_OTG_Status OTGD_FS_SetAddress(uint32_t BaseAddress); -USB_OTG_Status OTGD_FS_EnableGlobalInt(void); -USB_OTG_Status OTGD_FS_DisableGlobalInt(void); - -USB_OTG_Status USB_OTG_CoreInitHost(void); -USB_OTG_Status USB_OTG_EnableHostInt(void); -USB_OTG_Status USB_OTG_DisableHostInt(void); - -void* OTGD_FS_ReadPacket(uint8_t *dest, uint16_t bytes); -USB_OTG_Status OTGD_FS_WritePacket(uint8_t *src, uint8_t ch_ep_num, uint16_t bytes); - -USB_OTG_Status USB_OTG_HcInit(USB_OTG_HC *hc); -USB_OTG_Status USB_OTG_StartXfer(USB_OTG_HC *hc); - -uint32_t USB_OTG_ResetPort( void); - -uint32_t USB_OTG_ReadHPRT0(void); -uint32_t OTGD_FS_ReadDevAllInEPItr(void); -uint32_t OTGD_FS_ReadCoreItr(void); -uint32_t OTGD_FS_ReadOtgItr (void); -uint32_t USB_OTG_ReadHostAllChannels_intr (void); -uint8_t IsHostMode(void); -uint8_t IsDeviceMode(void); -USB_OTG_Status USB_OTG_HcInit(USB_OTG_HC *hc); -USB_OTG_Status USB_OTG_HcHalt(uint8_t hc_num); - -USB_OTG_Status OTGD_FS_FlushTxFifo (uint32_t num); -USB_OTG_Status OTGD_FS_FlushRxFifo (void); -USB_OTG_Status OTGD_FS_SetHostMode (void); - -USB_OTG_Status OTGD_FS_PhyInit(void); -USB_OTG_Status USB_OTG_HcStartXfer(USB_OTG_HC *hc); - -USB_OTG_Status OTGD_FS_CoreInitDev (void); -USB_OTG_Status OTGD_FS_EnableDevInt(void); -USB_OTG_Status OTGD_FS_EP0Activate(void); -USB_OTG_Status OTGD_FS_EPActivate(USB_OTG_EP *ep); -USB_OTG_Status OTGD_FS_EPDeactivate(USB_OTG_EP *ep); - -USB_OTG_Status OTGD_FS_EPStartXfer(USB_OTG_EP *ep); -USB_OTG_Status OTGD_FS_EP0StartXfer(USB_OTG_EP *ep); - -USB_OTG_Status OTGD_FS_EPSetStall(USB_OTG_EP *ep); -USB_OTG_Status OTGD_FS_EPClearStall(USB_OTG_EP *ep); -uint32_t OTGD_FS_ReadDevAllOutEp_itr(void); -uint32_t OTGD_FS_ReadDevOutEP_itr(USB_OTG_EP *ep); -uint32_t OTGD_FS_ReadDevAllInEPItr(void); - - -uint32_t OTGD_FS_Dev_GetEPStatus(USB_OTG_EP *ep); -void OTGD_FS_Dev_SetEPStatus(USB_OTG_EP *ep, uint32_t Status); -void OTGD_FS_Dev_SetRemoteWakeup(void); -void OTGD_FS_Dev_ResetRemoteWakeup(void); - -#endif /* STM32F10X_CL */ - -#endif -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/STM32_USB-FS-Device_Driver/inc/otgd_fs_dev.h b/STM32_USB-FS-Device_Driver/inc/otgd_fs_dev.h deleted file mode 100644 index d0c7554..0000000 --- a/STM32_USB-FS-Device_Driver/inc/otgd_fs_dev.h +++ /dev/null @@ -1,121 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otg_dev.h -* Author : STMicroelectronics -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : linking defines -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __OTG_DEV_H__ -#define __OTG_DEV_H__ - -#ifdef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f10x.h" -#include "usb_type.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* Endpoint types */ -#define OTG_DEV_EP_TYPE_CONTROL 0 -#define OTG_DEV_EP_TYPE_ISOC 1 -#define OTG_DEV_EP_TYPE_BULK 2 -#define OTG_DEV_EP_TYPE_INT 3 - -/* Endpoint Addresses (w/direction) */ -#define EP0_OUT 0x00 -#define EP0_IN 0x80 -#define EP1_OUT 0x01 -#define EP1_IN 0x81 -#define EP2_OUT 0x02 -#define EP2_IN 0x82 -#define EP3_OUT 0x03 -#define EP3_IN 0x83 - - -/*-*-*-*-*-*-*-*-*-* Replace the usb_regs.h defines -*-*-*-*-*-*-*-*-*-*-*-*-*/ -/* endpoints enumeration */ -#define ENDP0 ((uint8_t)0) -#define ENDP1 ((uint8_t)1) -#define ENDP2 ((uint8_t)2) -#define ENDP3 ((uint8_t)3) -#define ENDP4 ((uint8_t)4) -#define ENDP5 ((uint8_t)5) -#define ENDP6 ((uint8_t)6) -#define ENDP7 ((uint8_t)7) - -/* EP Transmit status defines */ -#define EP_TX_DIS DEV_EP_TX_DIS) /* EndPoint TX DISabled */ -#define EP_TX_STALL DEV_EP_TX_STALL /* EndPoint TX STALLed */ -#define EP_TX_NAK DEV_EP_TX_NAK /* EndPoint TX NAKed */ -#define EP_TX_VALID DEV_EP_TX_VALID /* EndPoint TX VALID */ - -/* EP Transmit status defines */ -#define EP_RX_DIS DEV_EP_RX_DIS /* EndPoint RX DISabled */ -#define EP_RX_STALL DEV_EP_RX_STALL /* EndPoint RX STALLed */ -#define EP_RX_NAK DEV_EP_RX_NAK /* EndPoint RX NAKed */ -#define EP_RX_VALID DEV_EP_RX_VALID /* EndPoint RX VALID */ -/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - -/* Exported macro ------------------------------------------------------------*/ -#define _GetEPTxStatus(bEpNum) ((uint16_t)OTG_DEV_GetEPTxStatus(bEpNum)) -#define _GetEPRxStatus(bEpNum) ((uint16_t)OTG_DEV_GetEPRxStatus(bEpNum)) - -#define _SetEPTxStatus(bEpNum,wState) (OTG_DEV_SetEPTxStatus(bEpNum, wState)) -#define _SetEPRxStatus(bEpNum,wState) (OTG_DEV_SetEPRxStatus(bEpNum, wState)) - -#define _SetEPTxValid(bEpNum) (OTG_DEV_SetEPTxStatus(bEpNum, EP_TX_VALID)) -#define _SetEPRxValid(bEpNum) (OTG_DEV_SetEPRxStatus(bEpNum, EP_RX_VALID)) - -#define _GetTxStallStatus(bEpNum) (OTG_DEV_GetEPTxStatus(bEpNum) == EP_TX_STALL) -#define _GetRxStallStatus(bEpNum) (OTG_DEV_GetEPRxStatus(bEpNum) == EP_RX_STALL) - -/* Define the callbacks for updating the USB state machine */ -#define OTGD_FS_DEVICE_RESET Device_Property.Reset() - -/* Exported define -----------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -void OTG_DEV_Init(void); -void OTG_DEV_EP_Init(uint8_t bEpAdd, uint8_t bEpType, uint16_t wEpMaxPackSize); - -void OTG_DEV_SetEPRxStatus(uint8_t bEpnum, uint32_t status); -void OTG_DEV_SetEPTxStatus(uint8_t bEpnum, uint32_t status); -uint32_t OTG_DEV_GetEPRxStatus(uint8_t bEpnum); -uint32_t OTG_DEV_GetEPTxStatus(uint8_t bEpnum); - -void USB_DevDisconnect(void); -void USB_DevConnect(void); - - -/*-*-*-*-*-*-*-*-*-* Replace the usb_regs.h prototypes *-*-*-*-*-*-*-*-*-*-*-*/ -void SetEPTxStatus(uint8_t bEpNum, uint16_t wState); -void SetEPRxStatus(uint8_t bEpNum, uint16_t wState); -uint16_t GetEPTxStatus(uint8_t bEpNum); -uint16_t GetEPRxStatus(uint8_t bEpNum); -void SetEPTxValid(uint8_t bEpNum); -void SetEPRxValid(uint8_t bEpNum); -uint16_t GetTxStallStatus(uint8_t bEpNum); -uint16_t GetRxStallStatus(uint8_t bEpNum); -void SetEPTxCount(uint8_t bEpNum, uint16_t wCount); -void SetEPRxCount(uint8_t bEpNum, uint16_t wCount); - -uint16_t ToWord(uint8_t, uint8_t); -uint16_t ByteSwap(uint16_t); -/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - -#endif /* STM32F10X_CL */ - -#endif /* __OTG_DEV_H__ */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/STM32_USB-FS-Device_Driver/inc/otgd_fs_int.h b/STM32_USB-FS-Device_Driver/inc/otgd_fs_int.h deleted file mode 100644 index b0b1281..0000000 --- a/STM32_USB-FS-Device_Driver/inc/otgd_fs_int.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_int.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Endpoint interrupt's service routines prototypes. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_INT_H -#define __USB_INT_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#ifdef STM32F10X_CL - -/* Interrupt Handlers functions */ -uint32_t OTGD_FS_Handle_ModeMismatch_ISR(void); -uint32_t OTGD_FS_Handle_Sof_ISR(void); -uint32_t OTGD_FS_Handle_RxStatusQueueLevel_ISR(void); -uint32_t OTGD_FS_Handle_NPTxFE_ISR(void); -uint32_t OTGD_FS_Handle_GInNakEff_ISR(void); -uint32_t OTGD_FS_Handle_GOutNakEff_ISR(void); -uint32_t OTGD_FS_Handle_EarlySuspend_ISR(void); -uint32_t OTGD_FS_Handle_USBSuspend_ISR(void); -uint32_t OTGD_FS_Handle_UsbReset_ISR(void); -uint32_t OTGD_FS_Handle_EnumDone_ISR(void); -uint32_t OTGD_FS_Handle_IsoOutDrop_ISR(void); -uint32_t OTGD_FS_Handle_EOPF_ISR(void); -uint32_t OTGD_FS_Handle_EPMismatch_ISR(void); -uint32_t OTGD_FS_Handle_InEP_ISR(void); -uint32_t OTGD_FS_Handle_OutEP_ISR(void); -uint32_t OTGD_FS_Handle_IncomplIsoIn_ISR(void); -uint32_t OTGD_FS_Handle_IncomplIsoOut_ISR(void); -uint32_t OTGD_FS_Handle_Wakeup_ISR(void); - -#endif /* STM32F10X_CL */ - -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_INT_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/otgd_fs_pcd.h b/STM32_USB-FS-Device_Driver/inc/otgd_fs_pcd.h deleted file mode 100644 index 5255737..0000000 --- a/STM32_USB-FS-Device_Driver/inc/otgd_fs_pcd.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_pcd.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Header file of the High Layer device mode interface and -* wrapping layer -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifndef __USB_OTG_PCD_H__ -#define __USB_OTG_PCD_H__ - -#include "otgd_fs_regs.h" - -#define MAX_EP0_SIZE 0x40 -#define MAX_PACKET_SIZE 0x400 - - -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 -#define USB_ENDPOINT_XFERTYPE_MASK 3 - - -/******************************************************************************** - ENUMERATION TYPE -********************************************************************************/ -enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, - USB_SPEED_LOW, USB_SPEED_FULL, - USB_SPEED_HIGH -}; -/******************************************************************************** - Data structure type -********************************************************************************/ -typedef struct usb_ep_descriptor -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; -} -EP_DESCRIPTOR , *PEP_DESCRIPTOR; -/******************************************************************************** - USBF LAYER UNION AND STRUCTURES -********************************************************************************/ -typedef struct USB_OTG_USBF -{ - - USB_OTG_EP ep0; - uint8_t ep0state; - USB_OTG_EP in_ep[ MAX_TX_FIFOS - 1]; - USB_OTG_EP out_ep[ MAX_TX_FIFOS - 1]; -} -USB_OTG_PCD_DEV , *USB_OTG_PCD_PDEV; -/******************************************************************************** - EXPORTED FUNCTION FROM THE USB_OTG LAYER -********************************************************************************/ -void OTGD_FS_PCD_Init(void); -void OTGD_FS_PCD_DevConnect (void); -void OTGD_FS_PCD_DevDisconnect (void); -void OTGD_FS_PCD_EP_SetAddress (uint8_t address); -uint32_t OTGD_FS_PCD_EP_Open(EP_DESCRIPTOR *epdesc); -uint32_t OTGD_FS_PCD_EP_Close ( uint8_t ep_addr); -uint32_t OTGD_FS_PCD_EP_Read ( uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len); -uint32_t OTGD_FS_PCD_EP_Write ( uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len); -uint32_t OTGD_FS_PCD_EP_Stall (uint8_t epnum); -uint32_t OTGD_FS_PCD_EP_ClrStall (uint8_t epnum); -uint32_t OTGD_FS_PCD_EP_Flush (uint8_t epnum); -uint32_t OTGD_FS_PCD_Handle_ISR(void); - -USB_OTG_EP* OTGD_FS_PCD_GetOutEP(uint32_t ep_num) ; -USB_OTG_EP* OTGD_FS_PCD_GetInEP(uint32_t ep_num); -void OTGD_FS_PCD_EP0_OutStart(void); - -#endif -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/otgd_fs_regs.h b/STM32_USB-FS-Device_Driver/inc/otgd_fs_regs.h deleted file mode 100644 index d98bae0..0000000 --- a/STM32_USB-FS-Device_Driver/inc/otgd_fs_regs.h +++ /dev/null @@ -1,1592 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_regs.h -* Author : STMicroelectronics -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : USB OTG IP hardware registers. -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifndef __USB_OTG_REGS_H__ -#define __USB_OTG_REGS_H__ - -#ifdef STM32F10X_CL - -#include "stm32f10x.h" -#include "usb_type.h" - -#define USB_OTG_FS1_BASE_ADDR 0x50000000 - -#define USB_OTG_CORE_GLOBAL_REGS_OFFSET 0x000 -#define USB_OTG_DEV_GLOBAL_REG_OFFSET 0x800 -#define USB_OTG_DEV_IN_EP_REG_OFFSET 0x900 -#define USB_OTG_EP_REG_OFFSET 0x20 -#define USB_OTG_DEV_OUT_EP_REG_OFFSET 0xB00 -#define USB_OTG_HOST_GLOBAL_REG_OFFSET 0x400 -#define USB_OTG_HOST_PORT_REGS_OFFSET 0x440 -#define USB_OTG_HOST_CHAN_REGS_OFFSET 0x500 -#define USB_OTG_CHAN_REGS_OFFSET 0x20 -#define USB_OTG_PCGCCTL_OFFSET 0xE00 -#define USB_OTG_DATA_FIFO_OFFSET 0x1000 -#define USB_OTG_DATA_FIFO_SIZE 0x1000 - -#define MAX_PERIO_FIFOS 8 -#define MAX_TX_FIFOS 4 -#define MAX_EPS_CHANNELS 8 -/******************************************************************************* - * USB_OTG Core registers . - * The USB_OTG_core_regs structure defines the size - * and relative field offsets for the Core Global registers. - ******************************************************************************/ -typedef struct _USB_OTG_common_regs //000h -{ - - __IO uint32_t otg_ctl; /* USB_OTG Control and Status Register 000h*/ - __IO uint32_t otg_int; /* USB_OTG Interrupt Register 004h*/ - __IO uint32_t ahb_cfg; /* Core AHB Configuration Register 008h*/ - __IO uint32_t usb_cfg; /* Core USB Configuration Register 00Ch*/ - __IO uint32_t rst_ctl; /* Core Reset Register 010h*/ - __IO uint32_t int_sts; /* Core Interrupt Register 014h*/ - __IO uint32_t int_msk; /* Core Interrupt Mask Register 018h*/ - __IO uint32_t rx_stsr; /* Receive Sts Q Read Register 01Ch*/ - __IO uint32_t rx_stsp; /* Receive Sts Q Read & POP Register 020h*/ - __IO uint32_t rx_fifo_siz; /* Receive FIFO Size Register 024h*/ - __IO uint32_t np_tx_fifo_siz; /* Non Periodic Tx FIFO Size Register 028h*/ - __IO uint32_t np_tx_sts; /* Non Periodic Tx FIFO/Queue Sts reg 02Ch*/ - __IO uint32_t i2c_ctl; /* I2C Access Register 030h*/ - __IO uint32_t phy_vnd_ctl; /* PHY Vendor Control Register 034h*/ - __IO uint32_t gpio; /* General Purpose IO Register 038h*/ - __IO uint32_t usr_id; /* User ID Register 03Ch*/ - __IO uint32_t snps_id; /* Synopsys ID Register 040h*/ - __IO uint32_t hw_cfg1; /* User HW Config1 Register (RO) 044h*/ - __IO uint32_t hw_cfg2; /* User HW Config2 Register (RO) 048h*/ - __IO uint32_t hw_cfg3; /* User HW Config3 Register (RO) 04Ch*/ - __IO uint32_t hw_cfg4; /* User HW Config4 Register (RO) 050h*/ - uint32_t reserved[43]; /* Reserved 054h-0FFh*/ - __IO uint32_t host_p_tx_fifo_siz; /* Host Periodic Tx FIFO Size Reg 100h*/ - __IO uint32_t dev_p_tx_fsiz_dieptxf[15];/* dev Periodic Transmit FIFO */ - -} -USB_OTG_common_regs; - -/******************************************************************************* - * dev Registers - * dev Global Registers : Offsets 800h-BFFh - * The following structures define the size and relative field offsets - * for the dev Mode Registers. - * These registers are visible only in dev mode and must not be - * accessed in Host mode, as the results are unknown - ******************************************************************************/ -typedef struct _USB_OTG_dev_regs // 800h -{ - - __IO uint32_t dev_cfg; /* dev Configuration Register 800h*/ - __IO uint32_t dev_ctl; /* dev Control Register 804h*/ - __IO uint32_t dev_sts; /* dev Status Register (RO) 808h*/ - uint32_t reserved3; /* Reserved 80Ch*/ - __IO uint32_t dev_in_ep_msk; /* dev IN Endpoint Mask 810h*/ - __IO uint32_t dev_out_ep_msk; /* dev OUT Endpoint Mask 814h*/ - __IO uint32_t dev_all_int; /* dev All Endpoints Itr Reg 818h*/ - __IO uint32_t dev_all_int_msk; /* dev All Endpoints Itr Mask 81Ch*/ - uint32_t Reserved8; /* Reserved 820h*/ - __IO uint32_t Reserved9; /* Reserved 824h*/ - __IO uint32_t dev_vbus_dis; /* dev VBUS discharge Register 828h*/ - __IO uint32_t dev_vbus_pulse; /* dev VBUS Pulse Register 82Ch*/ - __IO uint32_t dev_thr_ctl; /* dev thr 830h*/ - __IO uint32_t dev_fifo_empty_msk; /* dev empty msk 834h*/ - -} -USB_OTG_dev_regs; -/******************************************************************************* - * dev Logical IN Endpoint-Specific Registers: Offsets 900h-AFCh - * There will be one set of endpoint registers per logical endpointimplemented. - * These registers are visible only in dev mode and must not be - * accessed in Host mode, as the results are unknown -*******************************************************************************/ -typedef struct _USB_OTG_dev_in_ep_regs -{ - __IO uint32_t dev_in_ep_ctl; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ - uint32_t reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ - __IO uint32_t dev_in_ep_int; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ - uint32_t reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/ - __IO uint32_t dev_in_ep_txfer_siz; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ - __IO uint32_t dev_in_ep_dma; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ - __IO uint32_t dev_tx_fifo_sts;/*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ - uint32_t reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ - -} -USB_OTG_dev_in_ep_regs; - -/******************************************************************************* - * dev Logical OUT Endpoint-Specific Registers Offsets: B00h-CFCh - * There will be one set of endpoint registers per logical endpoint - * implemented. - * These registers are visible only in dev mode and must not be - * accessed in Host mode, as the results are unknown -******************************************************************************/ -typedef struct _USB_OTG_dev_out_ep_regs -{ - __IO uint32_t dev_out_ep_ctl; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ - __IO uint32_t dev_out_ep_frm_nbr; /* dev OUT Endpoint Frame number B00h + (ep_num * 20h) + 04h*/ - __IO uint32_t dev_out_ep_int; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ - uint32_t reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/ - __IO uint32_t dev_out_ep_txfer_siz; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ - __IO uint32_t dev_out_ep_dma; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ - uint32_t reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ - -} -USB_OTG_dev_out_ep_regs; -/******************************************************************************* - * Host Mode Register Structures - * The Host Global Registers structure defines the size and relative - * field offsets for the Host Mode Global Registers. - * Host Global Registers offsets 400h-7FFh. -*******************************************************************************/ -typedef struct _USB_OTG_host_regs -{ - __IO uint32_t host_cfg; /* Host Configuration Register 400h*/ - __IO uint32_t host_frm_intrvl; /* Host Frame Interval Register 404h*/ - __IO uint32_t host_frm_nbr; /* Host Frame Nbr/Frame Remaining 408h*/ - uint32_t reserved40C; /* Reserved 40Ch*/ - __IO uint32_t host_p_tx_sts; /* Host Periodic Tx FIFO/ Queue Status 410h*/ - __IO uint32_t host_all_int; /* Host All Channels Interrupt Register 414h*/ - __IO uint32_t host_all_int_msk; /* Host All Channels Interrupt Mask 418h*/ - -} -USB_OTG_host_regs; - -/******************************************************************************* -* Host Channel Specific Registers 500h-5FCh -*******************************************************************************/ -typedef struct _USB_OTG_hc_regs -{ - - __IO uint32_t hc_char; - __IO uint32_t hc_split; - __IO uint32_t hc_int; - __IO uint32_t hc_int_msk; - __IO uint32_t hc_txfer_siz; - __IO uint32_t hc_dma; - uint32_t reserved[2]; - -} -USB_OTG_hc_regs; -/******************************************************************************* - * otg Core registers . - * The USB_OTG_core_regs structure defines the size - * and relative field offsets for the Core Global registers. - ******************************************************************************/ -typedef struct USB_OTG_core_regs //000h -{ - USB_OTG_common_regs *common_regs; - USB_OTG_dev_regs *dev_regs; - USB_OTG_host_regs *host_regs; - USB_OTG_dev_in_ep_regs *inep_regs[MAX_EPS_CHANNELS]; - USB_OTG_dev_out_ep_regs *outep_regs[MAX_EPS_CHANNELS]; - USB_OTG_hc_regs *hc_regs[MAX_EPS_CHANNELS]; - __IO uint32_t *hprt0; - __IO uint32_t *data_fifo[MAX_EPS_CHANNELS]; - __IO uint32_t *pcgcctl; - -} -USB_OTG_CORE_REGS , *pUSB_OTG_CORE_REGS; -/******************************************************************************/ - -typedef union _USB_OTG_OTG_ctl_data -{ - uint32_t d32; - struct - { -uint32_t sesreqscs : - 1; -uint32_t sesreq : - 1; -uint32_t reserved2_7 : - 6; -uint32_t hstnegscs : - 1; -uint32_t hnpreq : - 1; -uint32_t hstsethnpen : - 1; -uint32_t devhnpen : - 1; -uint32_t reserved12_15 : - 4; -uint32_t conidsts : - 1; -uint32_t reserved17 : - 1; -uint32_t asesvld : - 1; -uint32_t bsesvld : - 1; -uint32_t currmod : - 1; -uint32_t reserved21_31 : - 11; - } - b; -} USB_OTG_OTG_ctl_data; - -/******************************************************************************/ - -typedef union _USB_OTG_OTG_int_data -{ - uint32_t d32; - struct - { -uint32_t reserved0_1 : - 2; -uint32_t sesenddet : - 1; -uint32_t reserved3_7 : - 5; -uint32_t sesreqsucstschng : - 1; -uint32_t hstnegsucstschng : - 1; -uint32_t reserver10_16 : - 7; -uint32_t hstnegdet : - 1; -uint32_t adevtoutchng : - 1; -uint32_t debdone : - 1; -uint32_t reserved31_20 : - 12; - } - b; -} USB_OTG_OTG_int_data; - - -/******************************************************************************/ - - -typedef union _USB_OTG_ahb_cfg_data -{ - uint32_t d32; - struct - { -uint32_t glblintrmsk : - 1; -uint32_t hburstlen : - 4; -uint32_t dmaenable : - 1; -uint32_t reserved : - 1; -uint32_t nptxfemplvl_txfemplvl : - 1; -uint32_t ptxfemplvl : - 1; -uint32_t reserved9_31 : - 23; - } - b; -} USB_OTG_ahb_cfg_data; - -/******************************************************************************/ - -typedef union _USB_OTG_usb_cfg_data -{ - uint32_t d32; - struct - { -uint32_t toutcal : - 3; -uint32_t phyif : - 1; -uint32_t ulpi_utmi_sel : - 1; -uint32_t fsintf : - 1; -uint32_t physel : - 1; -uint32_t ddrsel : - 1; -uint32_t srpcap : - 1; -uint32_t hnpcap : - 1; -uint32_t usbtrdtim : - 4; -uint32_t nptxfrwnden : - 1; -uint32_t phylpwrclksel : - 1; -uint32_t otgutmifssel : - 1; -uint32_t ulpi_fsls : - 1; -uint32_t ulpi_auto_res : - 1; -uint32_t ulpi_clk_sus_m : - 1; -uint32_t ulpi_ext_vbus_drv : - 1; -uint32_t ulpi_int_vbus_indicator : - 1; -uint32_t term_sel_dl_pulse : - 1; -uint32_t reserved : - 6; -uint32_t force_host : - 1; -uint32_t force_dev : - 1; -uint32_t corrupt_tx : - 1; - } - b; -} USB_OTG_usb_cfg_data; -/******************************************************************************/ - -typedef union _USB_OTG_rst_ctl_data -{ - uint32_t d32; - struct - { -uint32_t csftrst : - 1; -uint32_t hsftrst : - 1; -uint32_t hstfrm : - 1; -uint32_t intknqflsh : - 1; -uint32_t rxfflsh : - 1; -uint32_t txfflsh : - 1; -uint32_t txfnum : - 5; -uint32_t reserved11_29 : - 19; -uint32_t dmareq : - 1; -uint32_t ahbidle : - 1; - } - b; -} USB_OTG_rst_ctl_data; - -/******************************************************************************/ - -typedef union _USB_OTG_int_msk_data -{ - uint32_t d32; - struct - { -uint32_t reserved0 : - 1; -uint32_t modemismatch : - 1; -uint32_t otgintr : - 1; -uint32_t sofintr : - 1; -uint32_t rxstsqlvl : - 1; -uint32_t nptxfempty : - 1; -uint32_t ginnakeff : - 1; -uint32_t goutnakeff : - 1; -uint32_t reserved8 : - 1; -uint32_t i2cintr : - 1; -uint32_t erlysuspend : - 1; -uint32_t usbsuspend : - 1; -uint32_t usbreset : - 1; -uint32_t enumdone : - 1; -uint32_t isooutdrop : - 1; -uint32_t eopframe : - 1; -uint32_t reserved16 : - 1; -uint32_t epmismatch : - 1; -uint32_t inepintr : - 1; -uint32_t outepintr : - 1; -uint32_t incomplisoin : - 1; -uint32_t incomplisoout : - 1; -uint32_t reserved22_23 : - 2; -uint32_t portintr : - 1; -uint32_t hcintr : - 1; -uint32_t ptxfempty : - 1; -uint32_t reserved27 : - 1; -uint32_t conidstschng : - 1; -uint32_t disconnect : - 1; -uint32_t sessreqintr : - 1; -uint32_t wkupintr : - 1; - } - b; -} USB_OTG_int_msk_data; - -/******************************************************************************/ - - -typedef union _USB_OTG_int_sts_data -{ - uint32_t d32; - struct - { -uint32_t curmode : - 1; -uint32_t modemismatch : - 1; -uint32_t otgintr : - 1; -uint32_t sofintr : - 1; -uint32_t rxstsqlvl : - 1; -uint32_t nptxfempty : - 1; -uint32_t ginnakeff : - 1; -uint32_t goutnakeff : - 1; -uint32_t reserved8 : - 1; -uint32_t i2cintr : - 1; -uint32_t erlysuspend : - 1; -uint32_t usbsuspend : - 1; -uint32_t usbreset : - 1; -uint32_t enumdone : - 1; -uint32_t isooutdrop : - 1; -uint32_t eopframe : - 1; -uint32_t intokenrx : - 1; -uint32_t epmismatch : - 1; -uint32_t inepint: - 1; -uint32_t outepintr : - 1; -uint32_t incomplisoin : - 1; -uint32_t incomplisoout : - 1; -uint32_t reserved22_23 : - 2; -uint32_t portintr : - 1; -uint32_t hcintr : - 1; -uint32_t ptxfempty : - 1; -uint32_t reserved27 : - 1; -uint32_t conidstschng : - 1; -uint32_t disconnect : - 1; -uint32_t sessreqintr : - 1; -uint32_t wkupintr : - 1; - } - b; -} USB_OTG_int_sts_data; - -/******************************************************************************/ -typedef union _USB_OTG_dev_rx_sts_data -{ - - uint32_t d32; - struct - { -uint32_t epnum : - 4; -uint32_t bcnt : - 11; -uint32_t dpid : - 2; -uint32_t pktsts : - 4; -uint32_t fn : - 4; -uint32_t reserved : - 7; - } - b; -} USB_OTG_dev_rx_sts_data; - -/******************************************************************************/ -typedef union _USB_OTG_host_rx_sts_data -{ - - uint32_t d32; - struct - { -uint32_t chnum : - 4; -uint32_t bcnt : - 11; -uint32_t dpid : - 2; -uint32_t pktsts : - 4; -uint32_t reserved : - 11; - } - b; -} USB_OTG_host_rx_sts_data; - -/******************************************************************************/ - -typedef union _USB_OTG_fifo_size_data -{ - uint32_t d32; - struct - { -uint32_t startaddr : - 16; -uint32_t depth : - 16; - } - b; -} USB_OTG_fifo_size_data; - -/******************************************************************************/ - -typedef union _USB_OTG_np_tx_sts_data -{ - uint32_t d32; - struct - { -uint32_t nptxfspcavail : - 16; -uint32_t nptxqspcavail : - 8; -uint32_t nptxqtop_terminate : - 1; -uint32_t nptxqtop_token : - 2; -uint32_t nptxqtop_chnep : - 4; -uint32_t reserved : - 1; - } - b; -} USB_OTG_np_tx_sts_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_tx_fifo_sts_data -{ - uint32_t d32; - struct - { -uint32_t txfspcavail : - 16; -uint32_t reserved : - 16; - } - b; -} USB_OTG_dev_tx_fifo_sts_data; - -/******************************************************************************/ -typedef union _USB_OTG_i2c_ctl_data -{ - - uint32_t d32; - struct - { -uint32_t rwdata : - 8; -uint32_t regaddr : - 8; -uint32_t addr : - 7; -uint32_t i2cen : - 1; -uint32_t ack : - 1; -uint32_t i2csuspctl : - 1; -uint32_t i2cdevaddr : - 2; -uint32_t dat_se0: - 1; -uint32_t reserved : - 1; -uint32_t rw : - 1; -uint32_t bsydne : - 1; - } - b; -} USB_OTG_i2c_ctl_data; - -/******************************************************************************/ - -typedef union _USB_OTG_gpio_data -{ - - uint32_t d32; - struct - { - /* input */ -uint32_t ovrcur : - 1; -uint32_t otgid : - 1; -uint32_t reserved_in : - 14; - /* Output */ -uint32_t pwdn : - 1; -uint32_t i2cifen : - 1; -uint32_t vbussensingA : - 1; -uint32_t vbussensingB : - 1; -uint32_t SOFouten : - 1; -uint32_t reserved_out : - 11; - } - b; -} USB_OTG_gpio_data; - - -/******************************************************************************/ - -typedef union _USB_OTG_hw_cfg1_data -{ - - uint32_t d32; - struct - { -uint32_t ep_dir0 : - 2; -uint32_t ep_dir1 : - 2; -uint32_t ep_dir2 : - 2; -uint32_t ep_dir3 : - 2; -uint32_t ep_dir4 : - 2; -uint32_t ep_dir5 : - 2; -uint32_t ep_dir6 : - 2; -uint32_t ep_dir7 : - 2; -uint32_t ep_dir8 : - 2; -uint32_t ep_dir9 : - 2; -uint32_t ep_dir10 : - 2; -uint32_t ep_dir11 : - 2; -uint32_t ep_dir12 : - 2; -uint32_t ep_dir13 : - 2; -uint32_t ep_dir14 : - 2; -uint32_t ep_dir15 : - 2; - } - b; -} USB_OTG_hw_cfg1_data; - -/******************************************************************************/ -typedef union _USB_OTG_hw_cfg2_data -{ - uint32_t d32; - struct - { -uint32_t op_mode : - 3; -uint32_t architecture : - 2; -uint32_t point2point : - 1; -uint32_t hs_phy_type : - 2; -uint32_t fs_phy_type : - 2; -uint32_t num_dev_ep : - 4; -uint32_t num_host_chan : - 4; -uint32_t perio_ep_supported : - 1; -uint32_t dynamic_fifo : - 1; -uint32_t rx_status_q_depth : - 2; -uint32_t nonperio_tx_q_depth : - 2; -uint32_t host_perio_tx_q_depth : - 2; -uint32_t dev_token_q_depth : - 5; -uint32_t reserved31 : - 1; - } - b; -} USB_OTG_hw_cfg2_data; - -/******************************************************************************/ - -typedef union _USB_OTG_hw_cfg3_data -{ - - uint32_t d32; - struct - { -uint32_t xfer_size_cntr_width : - 4; -uint32_t packet_size_cntr_width : - 3; -uint32_t otg_func : - 1; -uint32_t i2c : - 1; -uint32_t vendor_ctrl_if : - 1; -uint32_t optional_features : - 1; -uint32_t synch_reset_type : - 1; -uint32_t ahb_phy_clock_synch : - 1; -uint32_t reserved15_13 : - 3; -uint32_t dfifo_depth : - 16; - } - b; -} USB_OTG_hw_cfg3_data; - -/******************************************************************************/ - -typedef union _USB_OTG_hw_cfg4_data -{ - uint32_t d32; - struct - { -uint32_t num_dev_perio_in_ep : - 4; -uint32_t power_optimiz : - 1; -uint32_t min_ahb_freq : - 9; -uint32_t utmi_phy_data_width : - 2; -uint32_t num_dev_mode_ctrl_ep : - 4; -uint32_t iddig_filt_en : - 1; -uint32_t vbus_valid_filt_en : - 1; -uint32_t a_valid_filt_en : - 1; -uint32_t b_valid_filt_en : - 1; -uint32_t session_end_filt_en : - 1; -uint32_t ded_fifo_en : - 1; -uint32_t num_in_eps : - 4; -uint32_t reserved31_30 : - 2; - } - b; -} USB_OTG_hw_cfg4_data; - -/******************************************************************************/ -typedef union _USB_OTG_dev_cfg_data -{ - - uint32_t d32; - struct - { -uint32_t devspd : - 2; -uint32_t nzstsouthshk : - 1; -uint32_t reserved3 : - 1; -uint32_t devaddr : - 7; -uint32_t perfrint : - 2; -uint32_t reserved13_17 : - 5; -uint32_t epmscnt : - 4; - } - b; -} USB_OTG_dev_cfg_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_ctl_data -{ - - uint32_t d32; - struct - { -uint32_t rmtwkupsig : - 1; -uint32_t sftdiscon : - 1; -uint32_t gnpinnaksts : - 1; -uint32_t goutnaksts : - 1; -uint32_t tstctl : - 3; -uint32_t sgnpinnak : - 1; -uint32_t cgnpinnak : - 1; -uint32_t sgoutnak : - 1; -uint32_t cgoutnak : - 1; -uint32_t reserved : - 21; - } - b; -} USB_OTG_dev_ctl_data; - -/******************************************************************************/ -typedef union _USB_OTG_dev_sts_data -{ - - uint32_t d32; - struct - { -uint32_t suspsts : - 1; -uint32_t enumspd : - 2; -uint32_t errticerr : - 1; -uint32_t reserved4_7: - 4; -uint32_t soffn : - 14; -uint32_t reserved22_31 : - 10; - } - b; -} USB_OTG_dev_sts_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_in_ep_int_data -{ - - uint32_t d32; - struct - { -uint32_t xfercompl : - 1; -uint32_t epdisabled : - 1; -uint32_t ahberr : - 1; -uint32_t timeout : - 1; -uint32_t intktxfemp : - 1; -uint32_t intknepmis : - 1; -uint32_t inepnakeff : - 1; -uint32_t emptyintr : - 1; -uint32_t txfifoundrn : - 1; -uint32_t reserved08_31 : - 23; - } - b; -} USB_OTG_dev_in_ep_int_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_in_ep_int_data USB_OTG_dev_in_ep_msk_data; -/******************************************************************************/ - -typedef union _USB_OTG_dev_out_ep_int_data -{ - - uint32_t d32; - struct - { -uint32_t xfercompl : - 1; -uint32_t epdisabled : - 1; -uint32_t ahberr : - 1; -uint32_t setup : - 1; -uint32_t reserved04_31 : - 28; - } - b; -} USB_OTG_dev_out_ep_int_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_out_ep_int_data USB_OTG_dev_out_ep_msk_data; - -/******************************************************************************/ -typedef union _USB_OTG_dev_all_int_data -{ - - uint32_t d32; - struct - { -uint32_t in : - 16; -uint32_t out : - 16; - } - ep; - struct - { - /** IN Endpoint bits */ -uint32_t inep0 : - 1; -uint32_t inep1 : - 1; -uint32_t inep2 : - 1; -uint32_t inep3 : - 1; -uint32_t inep4 : - 1; -uint32_t inep5 : - 1; -uint32_t inep6 : - 1; -uint32_t inep7 : - 1; -uint32_t inep8 : - 1; -uint32_t inep9 : - 1; -uint32_t inep10 : - 1; -uint32_t inep11 : - 1; -uint32_t inep12 : - 1; -uint32_t inep13 : - 1; -uint32_t inep14 : - 1; -uint32_t inep15 : - 1; - /** OUT Endpoint bits */ -uint32_t outep0 : - 1; -uint32_t outep1 : - 1; -uint32_t outep2 : - 1; -uint32_t outep3 : - 1; -uint32_t outep4 : - 1; -uint32_t outep5 : - 1; -uint32_t outep6 : - 1; -uint32_t outep7 : - 1; -uint32_t outep8 : - 1; -uint32_t outep9 : - 1; -uint32_t outep10 : - 1; -uint32_t outep11 : - 1; -uint32_t outep12 : - 1; -uint32_t outep13 : - 1; -uint32_t outep14 : - 1; -uint32_t outep15 : - 1; - } - b; -} USB_OTG_dev_all_int_data; - -/******************************************************************************/ -typedef union _USB_OTG_token_qr1_data -{ - - uint32_t d32; - struct - { -uint32_t intknwptr : - 5; -uint32_t reserved05_06 : - 2; -uint32_t wrap_bit : - 1; -uint32_t epnums0_5 : - 24; - } - b; -} USB_OTG_token_qr1_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_thr_ctl_data -{ - - uint32_t d32; - struct - { -uint32_t non_iso_thr_en : - 1; -uint32_t iso_thr_en : - 1; -uint32_t tx_thr_len : - 9; -uint32_t reserved11_15 : - 5; -uint32_t rx_thr_en : - 1; -uint32_t rx_thr_len : - 9; -uint32_t reserved26_31 : - 6; - } - b; -} USB_OTG_dev_thr_ctl_data; - -/******************************************************************************/ -typedef union _USB_OTG_dev_ep_ctl_data -{ - - uint32_t d32; - struct - { -uint32_t mps : - 11; -uint32_t nextep : - 4; -uint32_t usbactep : - 1; -uint32_t dpid : - 1; -uint32_t naksts : - 1; -uint32_t eptype : - 2; -uint32_t snp : - 1; -uint32_t stall : - 1; -uint32_t txfnum : - 4; -uint32_t cnak : - 1; -uint32_t snak : - 1; -uint32_t setd0pid : - 1; -uint32_t setd1pid : - 1; -uint32_t epdis : - 1; -uint32_t epena : - 1; - } - b; -} USB_OTG_dev_ep_ctl_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_ep_txfer_siz_data -{ - - uint32_t d32; - struct - { -uint32_t xfersize : - 19; -uint32_t pktcnt : - 10; -uint32_t mc : - 2; -uint32_t reserved : - 1; - } - b; -} USB_OTG_dev_ep_txfer_siz_data; - -/******************************************************************************/ - -typedef union _USB_OTG_dev_ep_txfer_size0_data -{ - - uint32_t d32; - struct - { -uint32_t xfersize : - 7; -uint32_t reserved7_18 : - 12; -uint32_t pktcnt : - 1; -uint32_t reserved20_28 : - 9; -uint32_t supcnt : - 2; - uint32_t reserved31; - } - b; -} USB_OTG_dev_ep_txfer_size0_data; - -/******************************************************************************/ -typedef union _USB_OTG_host_cfg_data -{ - - uint32_t d32; - struct - { -uint32_t fslspclksel : - 2; -uint32_t fslssupp : - 1; - } - b; -} USB_OTG_host_cfg_data; - -/******************************************************************************/ - -typedef union _USB_OTG_Host_frm_intrvl_data -{ - uint32_t d32; - struct - { -uint32_t frint : - 16; -uint32_t reserved : - 16; - } - b; -} USB_OTG_Host_frm_intrvl_data; - -/******************************************************************************/ -#define HFNUM_MAX_FRNUM 0x3FFF -typedef union _USB_OTG_host_frm_nbr_data -{ - - uint32_t d32; - struct - { -uint32_t frnum : - 16; -uint32_t frrem : - 16; - } - b; -} USB_OTG_host_frm_nbr_data; - -/******************************************************************************/ - -typedef union _USB_OTG_host_perio_tx_sts_data -{ - - uint32_t d32; - struct - { -uint32_t ptxfspcavail : - 16; -uint32_t ptxqspcavail : - 8; -uint32_t ptxqtop_terminate : - 1; -uint32_t ptxqtop_token : - 2; -uint32_t ptxqtop_chnum : - 4; -uint32_t ptxqtop_odd : - 1; - } - b; -} USB_OTG_host_perio_tx_sts_data; - -/******************************************************************************/ -typedef union _USB_OTG_hprt0_data -{ - uint32_t d32; - struct - { -uint32_t prtconnsts : - 1; -uint32_t prtconndet : - 1; -uint32_t prtena : - 1; -uint32_t prtenchng : - 1; -uint32_t prtovrcurract : - 1; -uint32_t prtovrcurrchng : - 1; -uint32_t prtres : - 1; -uint32_t prtsusp : - 1; -uint32_t prtrst : - 1; -uint32_t reserved9 : - 1; -uint32_t prtlnsts : - 2; -uint32_t prtpwr : - 1; -uint32_t prttstctl : - 4; -uint32_t prtspd : - 2; -uint32_t reserved19_31 : - 13; - } - b; -} USB_OTG_hprt0_data; - -/******************************************************************************/ - -typedef union _USB_OTG_host_all_int_data -{ - uint32_t d32; - struct - { -uint32_t ch0 : - 1; -uint32_t ch1 : - 1; -uint32_t ch2 : - 1; -uint32_t ch3 : - 1; -uint32_t ch4 : - 1; -uint32_t ch5 : - 1; -uint32_t ch6 : - 1; -uint32_t ch7 : - 1; -uint32_t ch8 : - 1; -uint32_t ch9 : - 1; -uint32_t ch10 : - 1; -uint32_t ch11 : - 1; -uint32_t ch12 : - 1; -uint32_t ch13 : - 1; -uint32_t ch14 : - 1; -uint32_t ch15 : - 1; -uint32_t reserved : - 16; - } - b; - - struct - { -uint32_t chint : - 16; -uint32_t reserved : - 16; - } - b2; -} USB_OTG_host_all_int_data; - - -/******************************************************************************/ - -typedef union _USB_OTG_host_all_int_msk_data -{ - uint32_t d32; - struct - { -uint32_t ch0 : - 1; -uint32_t ch1 : - 1; -uint32_t ch2 : - 1; -uint32_t ch3 : - 1; -uint32_t ch4 : - 1; -uint32_t ch5 : - 1; -uint32_t ch6 : - 1; -uint32_t ch7 : - 1; -uint32_t ch8 : - 1; -uint32_t ch9 : - 1; -uint32_t ch10 : - 1; -uint32_t ch11 : - 1; -uint32_t ch12 : - 1; -uint32_t ch13 : - 1; -uint32_t ch14 : - 1; -uint32_t ch15 : - 1; -uint32_t reserved : - 16; - } - b; - - struct - { -uint32_t chint : - 16; -uint32_t reserved : - 16; - } - b2; -} USB_OTG_host_all_int_msk_data; - -/******************************************************************************/ - -typedef union _USB_OTG_hc_char_data -{ - - uint32_t d32; - struct - { -uint32_t mps : - 11; -uint32_t epnum : - 4; -uint32_t epdir : - 1; -uint32_t reserved : - 1; -uint32_t lspddev : - 1; -uint32_t eptype : - 2; -uint32_t multicnt : - 2; -uint32_t devaddr : - 7; -uint32_t oddfrm : - 1; -uint32_t chdis : - 1; -uint32_t chen : - 1; - } - b; -} USB_OTG_hc_char_data; - -/******************************************************************************/ -typedef union _USB_OTG_hc_splt_data -{ - - uint32_t d32; - struct - { -uint32_t prtaddr : - 7; -uint32_t hubaddr : - 7; -uint32_t xactpos : - 2; -uint32_t compsplt : - 1; -uint32_t reserved : - 14; -uint32_t spltena : - 1; - } - b; -} USB_OTG_hc_splt_data; - -/******************************************************************************/ - -typedef union _USB_OTG_hc_int_data -{ - uint32_t d32; - struct - { -uint32_t xfercomp : - 1; -uint32_t chhltd : - 1; -uint32_t ahberr : - 1; -uint32_t stall : - 1; -uint32_t nak : - 1; -uint32_t ack : - 1; -uint32_t nyet : - 1; -uint32_t xacterr : - 1; -uint32_t bblerr : - 1; -uint32_t frmovrun : - 1; -uint32_t datatglerr : - 1; -uint32_t reserved : - 21; - } - b; -} USB_OTG_hc_int_data; - -/******************************************************************************/ - - -typedef union _USB_OTG_hc_txfer_siz_data -{ - - uint32_t d32; - struct - { -uint32_t xfersize : - 19; -uint32_t pktcnt : - 10; -uint32_t pid : - 2; -uint32_t dopng : - 1; - } - b; -} USB_OTG_hc_txfer_siz_data; - -/******************************************************************************/ - -typedef union _USB_OTG_hc_int_msk_data -{ - - uint32_t d32; - struct - { -uint32_t xfercompl : - 1; -uint32_t chhltd : - 1; -uint32_t ahberr : - 1; -uint32_t stall : - 1; -uint32_t nak : - 1; -uint32_t ack : - 1; -uint32_t nyet : - 1; -uint32_t xacterr : - 1; -uint32_t bblerr : - 1; -uint32_t frmovrun : - 1; -uint32_t datatglerr : - 1; -uint32_t reserved : - 21; - } - b; -} USB_OTG_hc_int_msk_data; - -/******************************************************************************/ - -typedef union _USB_OTG_host_pcgcctl_data -{ - uint32_t d32; - struct - { -uint32_t stoppclk : - 1; -uint32_t gatehclk : - 1; -uint32_t pwrclmp : - 1; -uint32_t rstpdwnmodule : - 1; -uint32_t physuspended : - 1; -uint32_t reserved : - 27; - } - b; -} USB_OTG_host_pcgcctl_data; - -#endif /* STM32F10X_CL */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - -#endif diff --git a/STM32_USB-FS-Device_Driver/inc/usb_core.h b/STM32_USB-FS-Device_Driver/inc/usb_core.h deleted file mode 100644 index 0c62fcb..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_core.h +++ /dev/null @@ -1,243 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_core.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Standard protocol processing functions prototypes -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_CORE_H -#define __USB_CORE_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _CONTROL_STATE -{ - WAIT_SETUP, /* 0 */ - SETTING_UP, /* 1 */ - IN_DATA, /* 2 */ - OUT_DATA, /* 3 */ - LAST_IN_DATA, /* 4 */ - LAST_OUT_DATA, /* 5 */ - WAIT_STATUS_IN, /* 7 */ - WAIT_STATUS_OUT, /* 8 */ - STALLED, /* 9 */ - PAUSE /* 10 */ -} CONTROL_STATE; /* The state machine states of a control pipe */ - -typedef struct OneDescriptor -{ - uint8_t *Descriptor; - uint16_t Descriptor_Size; -} -ONE_DESCRIPTOR, *PONE_DESCRIPTOR; -/* All the request process routines return a value of this type - If the return value is not SUCCESS or NOT_READY, - the software will STALL the correspond endpoint */ -typedef enum _RESULT -{ - USB_SUCCESS = 0, /* Process sucessfully */ - USB_ERROR, - USB_UNSUPPORT, - USB_NOT_READY /* The process has not been finished, endpoint will be - NAK to further rquest */ -} RESULT; - - -/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/ -typedef struct _ENDPOINT_INFO -{ - /* When send data out of the device, - CopyData() is used to get data buffer 'Length' bytes data - if Length is 0, - CopyData() returns the total length of the data - if the request is not supported, returns 0 - (NEW Feature ) - if CopyData() returns -1, the calling routine should not proceed - further and will resume the SETUP process by the class device - if Length is not 0, - CopyData() returns a pointer to indicate the data location - Usb_wLength is the data remain to be sent, - Usb_wOffset is the Offset of original data - When receive data from the host, - CopyData() is used to get user data buffer which is capable - of Length bytes data to copy data from the endpoint buffer. - if Length is 0, - CopyData() returns the available data length, - if Length is not 0, - CopyData() returns user buffer address - Usb_rLength is the data remain to be received, - Usb_rPointer is the Offset of data buffer - */ - uint16_t Usb_wLength; - uint16_t Usb_wOffset; - uint16_t PacketSize; - uint8_t *(*CopyData)(uint16_t Length); -}ENDPOINT_INFO; - -/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ - -typedef struct _DEVICE -{ - uint8_t Total_Endpoint; /* Number of endpoints that are used */ - uint8_t Total_Configuration;/* Number of configuration available */ -} -DEVICE; - -typedef union -{ - uint16_t w; - struct BW - { - uint8_t bb1; - uint8_t bb0; - } - bw; -} uint16_t_uint8_t; - -typedef struct _DEVICE_INFO -{ - uint8_t USBbmRequestType; /* bmRequestType */ - uint8_t USBbRequest; /* bRequest */ - uint16_t_uint8_t USBwValues; /* wValue */ - uint16_t_uint8_t USBwIndexs; /* wIndex */ - uint16_t_uint8_t USBwLengths; /* wLength */ - - uint8_t ControlState; /* of type CONTROL_STATE */ - uint8_t Current_Feature; - uint8_t Current_Configuration; /* Selected configuration */ - uint8_t Current_Interface; /* Selected interface of current configuration */ - uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current - interface*/ - - ENDPOINT_INFO Ctrl_Info; -}DEVICE_INFO; - -typedef struct _DEVICE_PROP -{ - void (*Init)(void); /* Initialize the device */ - void (*Reset)(void); /* Reset routine of this device */ - - /* Device dependent process after the status stage */ - void (*Process_Status_IN)(void); - void (*Process_Status_OUT)(void); - - /* Procedure of process on setup stage of a class specified request with data stage */ - /* All class specified requests with data stage are processed in Class_Data_Setup - Class_Data_Setup() - responses to check all special requests and fills ENDPOINT_INFO - according to the request - If IN tokens are expected, then wLength & wOffset will be filled - with the total transferring bytes and the starting position - If OUT tokens are expected, then rLength & rOffset will be filled - with the total expected bytes and the starting position in the buffer - - If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT - - CAUTION: - Since GET_CONFIGURATION & GET_INTERFACE are highly related to - the individual classes, they will be checked and processed here. - */ - RESULT (*Class_Data_Setup)(uint8_t RequestNo); - - /* Procedure of process on setup stage of a class specified request without data stage */ - /* All class specified requests without data stage are processed in Class_NoData_Setup - Class_NoData_Setup - responses to check all special requests and perform the request - - CAUTION: - Since SET_CONFIGURATION & SET_INTERFACE are highly related to - the individual classes, they will be checked and processed here. - */ - RESULT (*Class_NoData_Setup)(uint8_t RequestNo); - - /*Class_Get_Interface_Setting - This function is used by the file usb_core.c to test if the selected Interface - and Alternate Setting (uint8_t Interface, uint8_t AlternateSetting) are supported by - the application. - This function is writing by user. It should return "SUCCESS" if the Interface - and Alternate Setting are supported by the application or "UNSUPPORT" if they - are not supported. */ - - RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting); - - uint8_t* (*GetDeviceDescriptor)(uint16_t Length); - uint8_t* (*GetConfigDescriptor)(uint16_t Length); - uint8_t* (*GetStringDescriptor)(uint16_t Length); - - uint8_t* RxEP_buffer; - uint8_t MaxPacketSize; - -}DEVICE_PROP; - -typedef struct _USER_STANDARD_REQUESTS -{ - void (*User_GetConfiguration)(void); /* Get Configuration */ - void (*User_SetConfiguration)(void); /* Set Configuration */ - void (*User_GetInterface)(void); /* Get Interface */ - void (*User_SetInterface)(void); /* Set Interface */ - void (*User_GetStatus)(void); /* Get Status */ - void (*User_ClearFeature)(void); /* Clear Feature */ - void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ - void (*User_SetDeviceFeature)(void); /* Set Device Feature */ - void (*User_SetDeviceAddress)(void); /* Set Device Address */ -} -USER_STANDARD_REQUESTS; - -/* Exported constants --------------------------------------------------------*/ -#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT)) - -#define Usb_rLength Usb_wLength -#define Usb_rOffset Usb_wOffset - -#define USBwValue USBwValues.w -#define USBwValue0 USBwValues.bw.bb0 -#define USBwValue1 USBwValues.bw.bb1 -#define USBwIndex USBwIndexs.w -#define USBwIndex0 USBwIndexs.bw.bb0 -#define USBwIndex1 USBwIndexs.bw.bb1 -#define USBwLength USBwLengths.w -#define USBwLength0 USBwLengths.bw.bb0 -#define USBwLength1 USBwLengths.bw.bb1 - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -uint8_t Setup0_Process(void); -uint8_t Post0_Process(void); -uint8_t Out0_Process(void); -uint8_t In0_Process(void); - -RESULT Standard_SetEndPointFeature(void); -RESULT Standard_SetDeviceFeature(void); - -uint8_t *Standard_GetConfiguration(uint16_t Length); -RESULT Standard_SetConfiguration(void); -uint8_t *Standard_GetInterface(uint16_t Length); -RESULT Standard_SetInterface(void); -uint8_t *Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc); - -uint8_t *Standard_GetStatus(uint16_t Length); -RESULT Standard_ClearFeature(void); -void SetDeviceAddress(uint8_t); -void NOP_Process(void); - -extern const DEVICE_PROP Device_Property; -extern const USER_STANDARD_REQUESTS User_Standard_Requests; -extern const DEVICE Device_Table; -extern DEVICE_INFO Device_Info; - -/* cells saving status during interrupt servicing */ -extern __IO uint16_t SaveRState; -extern __IO uint16_t SaveTState; - -#endif /* __USB_CORE_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_def.h b/STM32_USB-FS-Device_Driver/inc/usb_def.h deleted file mode 100644 index 292de68..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_def.h +++ /dev/null @@ -1,80 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_def.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Definitions related to USB Core -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_DEF_H -#define __USB_DEF_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _RECIPIENT_TYPE -{ - DEVICE_RECIPIENT, /* Recipient device */ - INTERFACE_RECIPIENT, /* Recipient interface */ - ENDPOINT_RECIPIENT, /* Recipient endpoint */ - OTHER_RECIPIENT -} RECIPIENT_TYPE; - - -typedef enum _STANDARD_REQUESTS -{ - GET_STATUS = 0, - CLEAR_FEATURE, - RESERVED1, - SET_FEATURE, - RESERVED2, - SET_ADDRESS, - GET_DESCRIPTOR, - SET_DESCRIPTOR, - GET_CONFIGURATION, - SET_CONFIGURATION, - GET_INTERFACE, - SET_INTERFACE, - TOTAL_sREQUEST, /* Total number of Standard request */ - SYNCH_FRAME = 12 -} STANDARD_REQUESTS; - -/* Definition of "USBwValue" */ -typedef enum _DESCRIPTOR_TYPE -{ - DEVICE_DESCRIPTOR = 1, - CONFIG_DESCRIPTOR, - STRING_DESCRIPTOR, - INTERFACE_DESCRIPTOR, - ENDPOINT_DESCRIPTOR -} DESCRIPTOR_TYPE; - -/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */ -typedef enum _FEATURE_SELECTOR -{ - ENDPOINT_STALL, - DEVICE_REMOTE_WAKEUP -} FEATURE_SELECTOR; - -/* Exported constants --------------------------------------------------------*/ -/* Definition of "USBbmRequestType" */ -#define REQUEST_TYPE 0x60 /* Mask to get request type */ -#define STANDARD_REQUEST 0x00 /* Standard request */ -#define CLASS_REQUEST 0x20 /* Class request */ -#define VENDOR_REQUEST 0x40 /* Vendor request */ - -#define RECIPIENT 0x1F /* Mask to get recipient */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#endif /* __USB_DEF_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_init.h b/STM32_USB-FS-Device_Driver/inc/usb_init.h deleted file mode 100644 index c570f8a..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_init.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_init.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Initialization routines & global variables -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_INIT_H -#define __USB_INIT_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -void USB_Init(void); - -/* External variables --------------------------------------------------------*/ -/* The number of current endpoint, it will be used to specify an endpoint */ -extern uint8_t EPindex; -/* The number of current device, it is an index to the Device_Table */ -/*extern uint8_t Device_no; */ -/* Points to the DEVICE_INFO structure of current device */ -/* The purpose of this register is to speed up the execution */ -extern DEVICE_INFO* pInformation; -/* Points to the DEVICE_PROP structure of current device */ -/* The purpose of this register is to speed up the execution */ -extern const DEVICE_PROP* pProperty; -/* Temporary save the state of Rx & Tx status. */ -/* Whenever the Rx or Tx state is changed, its value is saved */ -/* in this variable first and will be set to the EPRB or EPRA */ -/* at the end of interrupt process */ -extern const USER_STANDARD_REQUESTS *pUser_Standard_Requests; - -extern uint16_t SaveState ; -extern uint16_t wInterrupt_Mask; - -#endif /* __USB_INIT_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_int.h b/STM32_USB-FS-Device_Driver/inc/usb_int.h deleted file mode 100644 index 617c88d..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_int.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_int.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Endpoint CTR (Low and High) interrupt's service routines -* prototypes -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_INT_H -#define __USB_INT_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -void CTR_LP(void); -void CTR_HP(void); - -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_INT_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_lib.h b/STM32_USB-FS-Device_Driver/inc/usb_lib.h deleted file mode 100644 index 8d4d094..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_lib.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_lib.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : USB library include files -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_LIB_H -#define __USB_LIB_H - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f10x.h" -#include "usb_type.h" -#include "usb_regs.h" -#include "usb_def.h" -#include "usb_core.h" -#include "usb_init.h" -#ifndef STM32F10X_CL - #include "usb_mem.h" - #include "usb_int.h" -#endif /* STM32F10X_CL */ - -#include "usb_sil.h" - -#ifdef STM32F10X_CL - #include "otgd_fs_cal.h" - #include "otgd_fs_pcd.h" - #include "otgd_fs_dev.h" - #include "otgd_fs_int.h" -#endif /* STM32F10X_CL */ - - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_LIB_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_mem.h b/STM32_USB-FS-Device_Driver/inc/usb_mem.h deleted file mode 100644 index 6b906d9..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_mem.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_mem.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Utility prototypes functions for memory/PMA transfers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_MEM_H -#define __USB_MEM_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); -void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); - -/* External variables --------------------------------------------------------*/ - -#endif /*__USB_MEM_H*/ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_regs.h b/STM32_USB-FS-Device_Driver/inc/usb_regs.h deleted file mode 100644 index e0ff108..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_regs.h +++ /dev/null @@ -1,670 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_regs.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Interface prototype functions to USB cell registers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_REGS_H -#define __USB_REGS_H - -#ifndef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _EP_DBUF_DIR -{ - /* double buffered endpoint direction */ - EP_DBUF_ERR, - EP_DBUF_OUT, - EP_DBUF_IN -}EP_DBUF_DIR; - -/* endpoint buffer number */ -enum EP_BUF_NUM -{ - EP_NOBUF, - EP_BUF0, - EP_BUF1 -}; - -/* Exported constants --------------------------------------------------------*/ -#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */ -#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */ - -/******************************************************************************/ -/* General registers */ -/******************************************************************************/ - -/* Control register */ -#define CNTR ((__IO unsigned *)(RegBase + 0x40)) -/* Interrupt status register */ -#define ISTR ((__IO unsigned *)(RegBase + 0x44)) -/* Frame number register */ -#define FNR ((__IO unsigned *)(RegBase + 0x48)) -/* Device address register */ -#define DADDR ((__IO unsigned *)(RegBase + 0x4C)) -/* Buffer Table address register */ -#define BTABLE ((__IO unsigned *)(RegBase + 0x50)) -/******************************************************************************/ -/* Endpoint registers */ -/******************************************************************************/ -#define EP0REG ((__IO unsigned *)(RegBase)) /* endpoint 0 register address */ - -/* Endpoint Addresses (w/direction) */ -#define EP0_OUT ((uint8_t)0x00) -#define EP0_IN ((uint8_t)0x80) -#define EP1_OUT ((uint8_t)0x01) -#define EP1_IN ((uint8_t)0x81) -#define EP2_OUT ((uint8_t)0x02) -#define EP2_IN ((uint8_t)0x82) -#define EP3_OUT ((uint8_t)0x03) -#define EP3_IN ((uint8_t)0x83) -#define EP4_OUT ((uint8_t)0x04) -#define EP4_IN ((uint8_t)0x84) -#define EP5_OUT ((uint8_t)0x05) -#define EP5_IN ((uint8_t)0x85) -#define EP6_OUT ((uint8_t)0x06) -#define EP6_IN ((uint8_t)0x86) -#define EP7_OUT ((uint8_t)0x07) -#define EP7_IN ((uint8_t)0x87) - -/* endpoints enumeration */ -#define ENDP0 ((uint8_t)0) -#define ENDP1 ((uint8_t)1) -#define ENDP2 ((uint8_t)2) -#define ENDP3 ((uint8_t)3) -#define ENDP4 ((uint8_t)4) -#define ENDP5 ((uint8_t)5) -#define ENDP6 ((uint8_t)6) -#define ENDP7 ((uint8_t)7) - -/******************************************************************************/ -/* ISTR interrupt events */ -/******************************************************************************/ -#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ -#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ -#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ -#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ -#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ -#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ -#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ -#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ - - -#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ -#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ - -#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ -#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ -#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ -#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ -#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ -#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ -#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ -#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ - -/******************************************************************************/ -/* CNTR control register bits definitions */ -/******************************************************************************/ -#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ -#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ -#define CNTR_ERRM (0x2000) /* ERRor Mask */ -#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ -#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ -#define CNTR_RESETM (0x0400) /* RESET Mask */ -#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ -#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ - - -#define CNTR_RESUME (0x0010) /* RESUME request */ -#define CNTR_FSUSP (0x0008) /* Force SUSPend */ -#define CNTR_LPMODE (0x0004) /* Low-power MODE */ -#define CNTR_PDWN (0x0002) /* Power DoWN */ -#define CNTR_FRES (0x0001) /* Force USB RESet */ - -/******************************************************************************/ -/* FNR Frame Number Register bit definitions */ -/******************************************************************************/ -#define FNR_RXDP (0x8000) /* status of D+ data line */ -#define FNR_RXDM (0x4000) /* status of D- data line */ -#define FNR_LCK (0x2000) /* LoCKed */ -#define FNR_LSOF (0x1800) /* Lost SOF */ -#define FNR_FN (0x07FF) /* Frame Number */ -/******************************************************************************/ -/* DADDR Device ADDRess bit definitions */ -/******************************************************************************/ -#define DADDR_EF (0x80) -#define DADDR_ADD (0x7F) -/******************************************************************************/ -/* Endpoint register */ -/******************************************************************************/ -/* bit positions */ -#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ -#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ -#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ -#define EP_SETUP (0x0800) /* EndPoint SETUP */ -#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ -#define EP_KIND (0x0100) /* EndPoint KIND */ -#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ -#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ -#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ -#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ - -/* EndPoint REGister MASK (no toggle fields) */ -#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) - -/* EP_TYPE[1:0] EndPoint TYPE */ -#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ -#define EP_BULK (0x0000) /* EndPoint BULK */ -#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ -#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ -#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ -#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) - - -/* EP_KIND EndPoint KIND */ -#define EPKIND_MASK (~EP_KIND & EPREG_MASK) - -/* STAT_TX[1:0] STATus for TX transfer */ -#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ -#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ -#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ -#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ -#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ -#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ -#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK) - -/* STAT_RX[1:0] STATus for RX transfer */ -#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ -#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ -#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ -#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ -#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ -#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ -#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK) -/* Exported macro ------------------------------------------------------------*/ -/* SetCNTR */ -#define _SetCNTR(wRegValue) (*CNTR = (uint16_t)wRegValue) - -/* SetISTR */ -#define _SetISTR(wRegValue) (*ISTR = (uint16_t)wRegValue) - -/* SetDADDR */ -#define _SetDADDR(wRegValue) (*DADDR = (uint16_t)wRegValue) - -/* SetBTABLE */ -#define _SetBTABLE(wRegValue)(*BTABLE = (uint16_t)(wRegValue & 0xFFF8)) - -/* GetCNTR */ -#define _GetCNTR() ((uint16_t) *CNTR) - -/* GetISTR */ -#define _GetISTR() ((uint16_t) *ISTR) - -/* GetFNR */ -#define _GetFNR() ((uint16_t) *FNR) - -/* GetDADDR */ -#define _GetDADDR() ((uint16_t) *DADDR) - -/* GetBTABLE */ -#define _GetBTABLE() ((uint16_t) *BTABLE) - -/* SetENDPOINT */ -#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \ - (uint16_t)wRegValue) - -/* GetENDPOINT */ -#define _GetENDPOINT(bEpNum) ((uint16_t)(*(EP0REG + bEpNum))) - -/******************************************************************************* -* Macro Name : SetEPType -* Description : sets the type in the endpoint register(bits EP_TYPE[1:0]) -* Input : bEpNum: Endpoint Number. -* wType -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\ - ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType ))) - -/******************************************************************************* -* Macro Name : GetEPType -* Description : gets the type in the endpoint register(bits EP_TYPE[1:0]) -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Type -*******************************************************************************/ -#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) - -/******************************************************************************* -* Macro Name : SetEPTxStatus -* Description : sets the status for tx transfer (bits STAT_TX[1:0]). -* Input : bEpNum: Endpoint Number. -* wState: new state -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxStatus(bEpNum,wState) {\ - register uint16_t _wRegVal; \ - _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\ - /* toggle first bit ? */ \ - if((EPTX_DTOG1 & wState)!= 0) \ - _wRegVal ^= EPTX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPTX_DTOG2 & wState)!= 0) \ - _wRegVal ^= EPTX_DTOG2; \ - _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ - } /* _SetEPTxStatus */ - -/******************************************************************************* -* Macro Name : SetEPRxStatus -* Description : sets the status for rx transfer (bits STAT_TX[1:0]) -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPRxStatus(bEpNum,wState) {\ - register uint16_t _wRegVal; \ - \ - _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\ - /* toggle first bit ? */ \ - if((EPRX_DTOG1 & wState)!= 0) \ - _wRegVal ^= EPRX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPRX_DTOG2 & wState)!= 0) \ - _wRegVal ^= EPRX_DTOG2; \ - _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ - } /* _SetEPRxStatus */ - -/******************************************************************************* -* Macro Name : SetEPRxTxStatus -* Description : sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0]) -* Input : bEpNum: Endpoint Number. -* wStaterx: new state. -* wStatetx: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPRxTxStatus(bEpNum,wStaterx,wStatetx) {\ - register uint32_t _wRegVal; \ - \ - _wRegVal = _GetENDPOINT(bEpNum) & (EPRX_DTOGMASK |EPTX_STAT) ;\ - /* toggle first bit ? */ \ - if((EPRX_DTOG1 & wStaterx)!= 0) \ - _wRegVal ^= EPRX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPRX_DTOG2 & wStaterx)!= 0) \ - _wRegVal ^= EPRX_DTOG2; \ - /* toggle first bit ? */ \ - if((EPTX_DTOG1 & wStatetx)!= 0) \ - _wRegVal ^= EPTX_DTOG1; \ - /* toggle second bit ? */ \ - if((EPTX_DTOG2 & wStatetx)!= 0) \ - _wRegVal ^= EPTX_DTOG2; \ - _SetENDPOINT(bEpNum, _wRegVal | EP_CTR_RX|EP_CTR_TX); \ - } /* _SetEPRxTxStatus */ -/******************************************************************************* -* Macro Name : GetEPTxStatus / GetEPRxStatus -* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] -* /STAT_RX[1:0]) -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : status . -*******************************************************************************/ -#define _GetEPTxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPTX_STAT) - -#define _GetEPRxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPRX_STAT) - -/******************************************************************************* -* Macro Name : SetEPTxValid / SetEPRxValid -* Description : sets directly the VALID tx/rx-status into the enpoint register -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) - -#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) - -/******************************************************************************* -* Macro Name : GetTxStallStatus / GetRxStallStatus. -* Description : checks stall condition in an endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : TRUE = endpoint in stall condition. -*******************************************************************************/ -#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \ - == EP_TX_STALL) -#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \ - == EP_RX_STALL) - -/******************************************************************************* -* Macro Name : SetEP_KIND / ClearEP_KIND. -* Description : set & clear EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ - (EP_CTR_RX|EP_CTR_TX|((_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)))) -#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ - (EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPKIND_MASK)))) - -/******************************************************************************* -* Macro Name : Set_Status_Out / Clear_Status_Out. -* Description : Sets/clears directly STATUS_OUT bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) -#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) - -/******************************************************************************* -* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff. -* Description : Sets/clears directly EP_KIND bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) -#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) - -/******************************************************************************* -* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX. -* Description : Clears bit CTR_RX / CTR_TX in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\ - _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) -#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\ - _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) - -/******************************************************************************* -* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX . -* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \ - EP_CTR_RX|EP_CTR_TX|EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) -#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \ - EP_CTR_RX|EP_CTR_TX|EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) - -/******************************************************************************* -* Macro Name : ClearDTOG_RX / ClearDTOG_TX. -* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\ - _ToggleDTOG_RX(bEpNum) -#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\ - _ToggleDTOG_TX(bEpNum) -/******************************************************************************* -* Macro Name : SetEPAddress. -* Description : Sets address in an endpoint register. -* Input : bEpNum: Endpoint Number. -* bAddr: Address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\ - EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) - -/******************************************************************************* -* Macro Name : GetEPAddress. -* Description : Gets address in an endpoint register. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPAddress(bEpNum) ((uint8_t)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) - -#define _pEPTxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr)) -#define _pEPTxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr)) -#define _pEPRxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr)) -#define _pEPRxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr)) - -/******************************************************************************* -* Macro Name : SetEPTxAddr / SetEPRxAddr. -* Description : sets address of the tx/rx buffer. -* Input : bEpNum: Endpoint Number. -* wAddr: address to be set (must be word aligned). -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) -#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) - -/******************************************************************************* -* Macro Name : GetEPTxAddr / GetEPRxAddr. -* Description : Gets address of the tx/rx buffer. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : address of the buffer. -*******************************************************************************/ -#define _GetEPTxAddr(bEpNum) ((uint16_t)*_pEPTxAddr(bEpNum)) -#define _GetEPRxAddr(bEpNum) ((uint16_t)*_pEPRxAddr(bEpNum)) - -/******************************************************************************* -* Macro Name : SetEPCountRxReg. -* Description : Sets counter of rx buffer with no. of blocks. -* Input : pdwReg: pointer to counter. -* wCount: Counter. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _BlocksOf32(dwReg,wCount,wNBlocks) {\ - wNBlocks = wCount >> 5;\ - if((wCount & 0x1f) == 0)\ - wNBlocks--;\ - *pdwReg = (uint32_t)((wNBlocks << 10) | 0x8000);\ - }/* _BlocksOf32 */ - -#define _BlocksOf2(dwReg,wCount,wNBlocks) {\ - wNBlocks = wCount >> 1;\ - if((wCount & 0x1) != 0)\ - wNBlocks++;\ - *pdwReg = (uint32_t)(wNBlocks << 10);\ - }/* _BlocksOf2 */ - -#define _SetEPCountRxReg(dwReg,wCount) {\ - uint16_t wNBlocks;\ - if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\ - else {_BlocksOf2(dwReg,wCount,wNBlocks);}\ - }/* _SetEPCountRxReg */ - - - -#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\ - uint32_t *pdwReg = _pEPTxCount(bEpNum); \ - _SetEPCountRxReg(pdwReg, wCount);\ - } -/******************************************************************************* -* Macro Name : SetEPTxCount / SetEPRxCount. -* Description : sets counter for the tx/rx buffer. -* Input : bEpNum: endpoint number. -* wCount: Counter value. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount) -#define _SetEPRxCount(bEpNum,wCount) {\ - uint32_t *pdwReg = _pEPRxCount(bEpNum); \ - _SetEPCountRxReg(pdwReg, wCount);\ - } -/******************************************************************************* -* Macro Name : GetEPTxCount / GetEPRxCount. -* Description : gets counter of the tx buffer. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : Counter value. -*******************************************************************************/ -#define _GetEPTxCount(bEpNum)((uint16_t)(*_pEPTxCount(bEpNum)) & 0x3ff) -#define _GetEPRxCount(bEpNum)((uint16_t)(*_pEPRxCount(bEpNum)) & 0x3ff) - -/******************************************************************************* -* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr. -* Description : Sets buffer 0/1 address in a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : wBuf0Addr: buffer 0 address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);} -#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);} - -/******************************************************************************* -* Macro Name : SetEPDblBuffAddr. -* Description : Sets addresses in a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : wBuf0Addr: buffer 0 address. -* : wBuf1Addr = buffer 1 address. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \ - _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\ - _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\ - } /* _SetEPDblBuffAddr */ - -/******************************************************************************* -* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr. -* Description : Gets buffer 0/1 address of a double buffer endpoint. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) -#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) - -/******************************************************************************* -* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count. -* Description : Gets buffer 0/1 address of a double buffer endpoint. -* Input : bEpNum: endpoint number. -* : bDir: endpoint dir EP_DBUF_OUT = OUT -* EP_DBUF_IN = IN -* : wCount: Counter value -* Output : None. -* Return : None. -*******************************************************************************/ -#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \ - if(bDir == EP_DBUF_OUT)\ - /* OUT endpoint */ \ - {_SetEPRxDblBuf0Count(bEpNum,wCount);} \ - else if(bDir == EP_DBUF_IN)\ - /* IN endpoint */ \ - *_pEPTxCount(bEpNum) = (uint32_t)wCount; \ - } /* SetEPDblBuf0Count*/ - -#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \ - if(bDir == EP_DBUF_OUT)\ - /* OUT endpoint */ \ - {_SetEPRxCount(bEpNum,wCount);}\ - else if(bDir == EP_DBUF_IN)\ - /* IN endpoint */\ - *_pEPRxCount(bEpNum) = (uint32_t)wCount; \ - } /* SetEPDblBuf1Count */ - -#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\ - _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ - _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ - } /* _SetEPDblBuffCount */ - -/******************************************************************************* -* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count. -* Description : Gets buffer 0/1 rx/tx counter for double buffering. -* Input : bEpNum: endpoint number. -* Output : None. -* Return : None. -*******************************************************************************/ -#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) -#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) - - -/* External variables --------------------------------------------------------*/ -extern __IO uint16_t wIstr; /* ISTR register last read value */ - -/* Exported functions ------------------------------------------------------- */ -void SetCNTR(uint16_t /*wRegValue*/); -void SetISTR(uint16_t /*wRegValue*/); -void SetDADDR(uint16_t /*wRegValue*/); -void SetBTABLE(uint16_t /*wRegValue*/); -uint16_t GetCNTR(void); -uint16_t GetISTR(void); -uint16_t GetFNR(void); -uint16_t GetDADDR(void); -uint16_t GetBTABLE(void); -void SetENDPOINT(uint8_t /*bEpNum*/, uint16_t /*wRegValue*/); -uint16_t GetENDPOINT(uint8_t /*bEpNum*/); -void SetEPType(uint8_t /*bEpNum*/, uint16_t /*wType*/); -uint16_t GetEPType(uint8_t /*bEpNum*/); -void SetEPTxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); -void SetEPRxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); -void SetDouBleBuffEPStall(uint8_t /*bEpNum*/, uint8_t bDir); -uint16_t GetEPTxStatus(uint8_t /*bEpNum*/); -uint16_t GetEPRxStatus(uint8_t /*bEpNum*/); -void SetEPTxValid(uint8_t /*bEpNum*/); -void SetEPRxValid(uint8_t /*bEpNum*/); -uint16_t GetTxStallStatus(uint8_t /*bEpNum*/); -uint16_t GetRxStallStatus(uint8_t /*bEpNum*/); -void SetEP_KIND(uint8_t /*bEpNum*/); -void ClearEP_KIND(uint8_t /*bEpNum*/); -void Set_Status_Out(uint8_t /*bEpNum*/); -void Clear_Status_Out(uint8_t /*bEpNum*/); -void SetEPDoubleBuff(uint8_t /*bEpNum*/); -void ClearEPDoubleBuff(uint8_t /*bEpNum*/); -void ClearEP_CTR_RX(uint8_t /*bEpNum*/); -void ClearEP_CTR_TX(uint8_t /*bEpNum*/); -void ToggleDTOG_RX(uint8_t /*bEpNum*/); -void ToggleDTOG_TX(uint8_t /*bEpNum*/); -void ClearDTOG_RX(uint8_t /*bEpNum*/); -void ClearDTOG_TX(uint8_t /*bEpNum*/); -void SetEPAddress(uint8_t /*bEpNum*/, uint8_t /*bAddr*/); -uint8_t GetEPAddress(uint8_t /*bEpNum*/); -void SetEPTxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); -void SetEPRxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); -uint16_t GetEPTxAddr(uint8_t /*bEpNum*/); -uint16_t GetEPRxAddr(uint8_t /*bEpNum*/); -void SetEPCountRxReg(uint32_t * /*pdwReg*/, uint16_t /*wCount*/); -void SetEPTxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/); -void SetEPRxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/); -uint16_t GetEPTxCount(uint8_t /*bEpNum*/); -uint16_t GetEPRxCount(uint8_t /*bEpNum*/); -void SetEPDblBuf0Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/); -void SetEPDblBuf1Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf1Addr*/); -void SetEPDblBuffAddr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/, uint16_t /*wBuf1Addr*/); -uint16_t GetEPDblBuf0Addr(uint8_t /*bEpNum*/); -uint16_t GetEPDblBuf1Addr(uint8_t /*bEpNum*/); -void SetEPDblBuffCount(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); -void SetEPDblBuf0Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); -void SetEPDblBuf1Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); -uint16_t GetEPDblBuf0Count(uint8_t /*bEpNum*/); -uint16_t GetEPDblBuf1Count(uint8_t /*bEpNum*/); -EP_DBUF_DIR GetEPDblBufDir(uint8_t /*bEpNum*/); -void FreeUserBuffer(uint8_t bEpNum/*bEpNum*/, uint8_t bDir); -uint16_t ToWord(uint8_t, uint8_t); -uint16_t ByteSwap(uint16_t); - -#endif /* STM32F10X_CL */ - -#endif /* __USB_REGS_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_sil.h b/STM32_USB-FS-Device_Driver/inc/usb_sil.h deleted file mode 100644 index af4884f..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_sil.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_sil.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Simplified Interface Layer function prototypes. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_SIL_H -#define __USB_SIL_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -uint32_t USB_SIL_Init(void); -uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize); -uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer); - -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_SIL_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/inc/usb_type.h b/STM32_USB-FS-Device_Driver/inc/usb_type.h deleted file mode 100644 index 8b8bd25..0000000 --- a/STM32_USB-FS-Device_Driver/inc/usb_type.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_type.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Type definitions used by the USB Library -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_TYPE_H -#define __USB_TYPE_H - -/* Includes ------------------------------------------------------------------*/ -#include "usb_conf.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -#ifndef NULL -#define NULL ((void *)0) -#endif - -#ifndef __STM32F10x_H - -typedef signed long s32; -typedef signed short s16; -typedef signed char s8; - -typedef volatile signed long vs32; -typedef volatile signed short vs16; -typedef volatile signed char vs8; - -typedef unsigned long u32; -typedef unsigned short u16; -typedef unsigned char u8; - -typedef unsigned long const uc32; /* Read Only */ -typedef unsigned short const uc16; /* Read Only */ -typedef unsigned char const uc8; /* Read Only */ - -typedef volatile unsigned long vu32; -typedef volatile unsigned short vu16; -typedef volatile unsigned char vu8; - -typedef volatile unsigned long const vuc32; /* Read Only */ -typedef volatile unsigned short const vuc16; /* Read Only */ -typedef volatile unsigned char const vuc8; /* Read Only */ - - -typedef enum -{ - FALSE = 0, TRUE = !FALSE -} -bool; - -typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus; - -typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState; - -typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus; -#endif -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -/* External variables --------------------------------------------------------*/ - -#endif /* __USB_TYPE_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/otgd_fs_cal.c b/STM32_USB-FS-Device_Driver/src/otgd_fs_cal.c deleted file mode 100644 index 7944cb7..0000000 --- a/STM32_USB-FS-Device_Driver/src/otgd_fs_cal.c +++ /dev/null @@ -1,1334 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_cal.c -* Author : STMicroelectronics -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : OTG FS Device Core Access Layer interface. -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifdef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "otgd_fs_cal.h" -#include "usb_conf.h" -#include "otgd_fs_regs.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ - -USB_OTG_CORE_REGS core_regs; - -/* Private function prototypes -----------------------------------------------*/ -static uint32_t GetMode(void); -static void EnableCommonInt(void); -static USB_OTG_Status SetID(void); -static USB_OTG_Status OTGD_FS_CoreReset(void); - -extern uint32_t STM32_USBH_OTG_ISR_Handler (void); -extern uint32_t STM32_PCD_OTG_ISR_Handler (void); -extern uint32_t STM32_USBO_OTG_ISR_Handler (void); - -#ifdef HOST_MODE_ENABLED -static void InitFSLSPClkSel(void); -#endif - - -/******************************************************************************/ -/* Common Core Layer */ -/******************************************************************************/ - -/******************************************************************************* -* Function Name : OTGD_FS_PhyInit -* Description : Initialize the phy -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_PhyInit(void) -{ - USB_OTG_gpio_data gpioctl; - USB_OTG_usb_cfg_data usbcfg; - USB_OTG_Status status = USB_OTG_OK; - - gpioctl.d32 = 0; - usbcfg.d32 = 0; - - /* Enable the I2C interface and deactivate the power down*/ - gpioctl.d32 = 0; - gpioctl.b.vbussensingB = 1; - gpioctl.b.pwdn = 1; - gpioctl.b.i2cifen = 0; - WRITE_REG32 (&core_regs.common_regs->gpio, gpioctl.d32); - mDELAY(200); - - /* Program GUSBCFG.OtgUtmifsSel to I2C*/ - usbcfg.d32 = READ_REG32(&core_regs.common_regs->usb_cfg); - usbcfg.b.otgutmifssel = 0; - WRITE_REG32 (&core_regs.common_regs->usb_cfg, usbcfg.d32); - - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_WritePacket -* Description : Writes a packet into the Tx FIFO associated with the EP -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_WritePacket(uint8_t *src, uint8_t ch_ep_num, uint16_t bytes) -{ - USB_OTG_Status status = USB_OTG_OK; - uint32_t dword_count = 0 , i = 0; - __IO uint32_t *fifo; - - /* Find the DWORD length, padded by extra bytes as neccessary if MPS - * is not a multiple of DWORD */ - dword_count = (bytes + 3) / 4; - - fifo = core_regs.data_fifo[ch_ep_num]; - - for (i = 0; i < dword_count; i++, src += 4) - { - WRITE_REG32( fifo, *((__packed uint32_t *)src) ); - } - - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_ReadPacket -* Description : Reads a packet from the Rx FIFO -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -void* OTGD_FS_ReadPacket(uint8_t *dest, uint16_t bytes) -{ - uint32_t i = 0; - uint32_t word_count = (bytes + 3) / 4; - - __IO uint32_t *fifo = core_regs.data_fifo[0]; - uint32_t *data_buff = (uint32_t *)dest; - - for (i = 0; i < word_count; i++, data_buff++) - { - *data_buff = READ_REG32(fifo); - } - - /* Return the buffer pointer because if the transfer is composed of several packets, - the data of the next packet must be stored following the previous packet's data */ - return ((void *)data_buff); -} -/******************************************************************************* -* Function Name : EnableCommonInt -* Description : initializes the commmon interrupts, used in both device and - host modes -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -static void EnableCommonInt(void) -{ - - USB_OTG_int_msk_data int_mask; - - int_mask.d32 = 0; - - /* Clear any pending USB_OTG Interrupts */ - WRITE_REG32( &core_regs.common_regs->otg_int, 0xFFFFFFFF); - - /* Clear any pending common interrupts */ - WRITE_REG32( &core_regs.common_regs->int_sts, 0xFFFFFFFF); - - WRITE_REG32( &core_regs.common_regs->int_msk, int_mask.d32); -} -/******************************************************************************* -* Function Name : OTGD_FS_SetAddress -* Description : Initialize core registers addresses. -* Input : BaseAddress -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_SetAddress(uint32_t BaseAddress) -{ - uint32_t i = 0; - USB_OTG_Status status = USB_OTG_OK; - core_regs.common_regs = (USB_OTG_common_regs *)(BaseAddress + USB_OTG_CORE_GLOBAL_REGS_OFFSET); - core_regs.dev_regs = (USB_OTG_dev_regs *) (BaseAddress + USB_OTG_DEV_GLOBAL_REG_OFFSET); - - for (i = 0; i < MAX_EPS_CHANNELS; i++) - { - core_regs.inep_regs[i] = (USB_OTG_dev_in_ep_regs *) (BaseAddress + USB_OTG_DEV_IN_EP_REG_OFFSET + (i * USB_OTG_EP_REG_OFFSET)); - core_regs.outep_regs[i] = (USB_OTG_dev_out_ep_regs *) (BaseAddress + USB_OTG_DEV_OUT_EP_REG_OFFSET + (i * USB_OTG_EP_REG_OFFSET)); - } - - core_regs.host_regs = (USB_OTG_host_regs *)(BaseAddress + USB_OTG_HOST_GLOBAL_REG_OFFSET); - core_regs.hprt0 = (uint32_t *)(BaseAddress + USB_OTG_HOST_PORT_REGS_OFFSET); - - for (i = 0; i < MAX_EPS_CHANNELS; i++) - { - core_regs.hc_regs[i] = (USB_OTG_hc_regs *)(BaseAddress + USB_OTG_HOST_CHAN_REGS_OFFSET + (i * USB_OTG_CHAN_REGS_OFFSET)); - } - - - for (i = 0; i < MAX_EPS_CHANNELS; i++) - { - core_regs.data_fifo[i] = (uint32_t *)(BaseAddress + USB_OTG_DATA_FIFO_OFFSET + (i * USB_OTG_DATA_FIFO_SIZE)); - } - - core_regs.pcgcctl = (uint32_t *)(BaseAddress + USB_OTG_PCGCCTL_OFFSET); - - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_CoreInit -* Description : Initialize the USB_OTG controller registers and prepares the core - for device mode or host mode operation. -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_CoreInit(void) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_usb_cfg_data usbcfg; - - usbcfg.d32 = 0; - - /* Reset the Controller */ - OTGD_FS_CoreReset(); - - usbcfg.d32 = READ_REG32(&core_regs.common_regs->usb_cfg); - usbcfg.b.physel = 1; - WRITE_REG32 (&core_regs.common_regs->usb_cfg, usbcfg.d32); - - /* init and configure the phy */ - OTGD_FS_PhyInit(); - - /* Reset after a PHY select and set Host mode */ - OTGD_FS_CoreReset(); - - /* Set Host or Device Mode */ - SetID(); - - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_CoreReset -* Description : Soft reset of the core -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -static USB_OTG_Status OTGD_FS_CoreReset(void) -{ - USB_OTG_Status status = USB_OTG_OK; - __IO USB_OTG_rst_ctl_data greset; - uint32_t count = 0; - - greset.d32 = 0; - - /* Wait for AHB master IDLE state. */ - do - { - uDELAY(3); - greset.d32 = READ_REG32(&core_regs.common_regs->rst_ctl); - if (++count > 200000) - { - return USB_OTG_OK; - } - } - while (greset.b.ahbidle == 0); - - /* Core Soft Reset */ - count = 0; - greset.b.csftrst = 1; - WRITE_REG32(&core_regs.common_regs->rst_ctl, greset.d32 ); - - do - { - greset.d32 = READ_REG32(&core_regs.common_regs->rst_ctl); - if (++count > 200000) - { - break; - } - } - while (greset.b.csftrst == 1); - - /* Wait for 3 PHY Clocks*/ - uDELAY(10); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_EnableGlobalInt -* Description : Enables the controller's Global Int in the AHB Config reg -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EnableGlobalInt(void) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_ahb_cfg_data ahb_cfg; - - ahb_cfg.d32 = 0; - - ahb_cfg.b.glblintrmsk = 1; /* Enable interrupts */ - MODIFY_REG32(&core_regs.common_regs->ahb_cfg, 0, ahb_cfg.d32); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_DisableGlobalInt -* Description : Disables the controller's Global Int in the AHB Config reg -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_DisableGlobalInt(void) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_ahb_cfg_data ahbcfg; - - ahbcfg.d32 = 0; - ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ - MODIFY_REG32(&core_regs.common_regs->ahb_cfg, ahbcfg.d32, 0); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_FlushTxFifo -* Description : Flush a Tx FIFO -* Input : FIFO num -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_FlushTxFifo (uint32_t num ) -{ - - USB_OTG_Status status = USB_OTG_OK; - __IO USB_OTG_rst_ctl_data greset; - uint32_t count = 0; - - greset.d32 = 0; - - greset.b.txfflsh = 1; - greset.b.txfnum = num; - WRITE_REG32( &core_regs.common_regs->rst_ctl, greset.d32 ); - - do - { - greset.d32 = READ_REG32( &core_regs.common_regs->rst_ctl); - if (++count > 200000) - { - break; - } - } - while (greset.b.txfflsh == 1); - - /* Wait for 3 PHY Clocks*/ - uDELAY(3); - - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_FlushRxFifo -* Description : Flush a Rx FIFO -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_FlushRxFifo( void ) -{ - USB_OTG_Status status = USB_OTG_OK; - __IO USB_OTG_rst_ctl_data greset; - uint32_t count = 0; - - greset.d32 = 0; - - greset.b.rxfflsh = 1; - WRITE_REG32( &core_regs.common_regs->rst_ctl, greset.d32 ); - - do - { - greset.d32 = READ_REG32( &core_regs.common_regs->rst_ctl); - if (++count > 200000) - { - break; - } - } - while (greset.b.rxfflsh == 1); - - /* Wait for 3 PHY Clocks*/ - uDELAY(3); - - return status; -} - -/******************************************************************************* -* Function Name : SetID -* Description : Set ID line -* Input : None -* Output : None -* Return : num_in_ep -*******************************************************************************/ -USB_OTG_Status SetID(void) -{ - - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_usb_cfg_data usbcfg ; - - usbcfg.d32 = 0; - - usbcfg.d32 = READ_REG32(&core_regs.common_regs->usb_cfg); - - usbcfg.b.force_dev = 1; - - WRITE_REG32(&core_regs.common_regs->usb_cfg, usbcfg.d32); - - mDELAY(50); - - return status; -} - -/******************************************************************************* -* Function Name : GetMode -* Description : Get current mode -* Input : None -* Output : None -* Return : current mode -*******************************************************************************/ -static uint32_t GetMode(void) -{ - return (READ_REG32(&core_regs.common_regs->int_sts ) & 0x1); -} - -/******************************************************************************* -* Function Name : IsDeviceMode -* Description : Check if it is device mode -* Input : None -* Output : None -* Return : num_in_ep -*******************************************************************************/ -uint8_t IsDeviceMode(void) -{ - return (GetMode() != HOST_MODE); -} - -/******************************************************************************* -* Function Name : IsHostMode -* Description : Check if it is host mode -* Input : None -* Output : None -* Return : num_in_ep -*******************************************************************************/ -uint8_t IsHostMode(void) -{ - return (GetMode() == HOST_MODE); -} - -/******************************************************************************* -* Function Name : OTGD_FS_ReadCoreItr -* Description : returns the Core Interrupt register -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -uint32_t OTGD_FS_ReadCoreItr(void) -{ - uint32_t v = 0; - - v = READ_REG32(&core_regs.common_regs->int_sts); - v &= READ_REG32(&core_regs.common_regs->int_msk); - - return v; -} - -/******************************************************************************* -* Function Name : OTGD_FS_ReadOtgItr -* Description : returns the USB_OTG Interrupt register -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -uint32_t OTGD_FS_ReadOtgItr (void) -{ - return (READ_REG32 (&core_regs.common_regs->otg_int)); -} - -/******************************************************************************/ -/* PCD Core Layer */ -/******************************************************************************/ - -/******************************************************************************* -* Function Name : InitDevSpeed -* Description : Initializes the DevSpd field of the DCFG register depending - on the PHY type and the enumeration speed of the device. -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -static void InitDevSpeed(void) -{ - USB_OTG_dev_cfg_data dcfg; - - dcfg.d32 = 0; - - dcfg.d32 = READ_REG32(&core_regs.dev_regs->dev_cfg); - dcfg.b.devspd = 0x3; /* Full speed PHY */ - WRITE_REG32(&core_regs.dev_regs->dev_cfg, dcfg.d32); -} -/******************************************************************************* -* Function Name : OTGD_FS_CoreInitDev -* Description : Initialize the USB_OTG controller registers for device mode -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_CoreInitDev (void) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_ep_ctl_data depctl; - USB_OTG_dev_cfg_data dcfg; - USB_OTG_fifo_size_data nptxfifosize; - USB_OTG_fifo_size_data txfifosize; - USB_OTG_dev_in_ep_msk_data msk; - uint32_t i = 0; - - depctl.d32 = 0; - dcfg.d32 = 0; - nptxfifosize.d32 = 0; - txfifosize.d32 = 0; - msk.d32 = 0; - - /* Set device speed */ - InitDevSpeed (); - - /* Restart the Phy Clock */ - WRITE_REG32(core_regs.pcgcctl, 0); - - /* Device configuration register */ - dcfg.d32 = READ_REG32( &core_regs.dev_regs->dev_cfg); - dcfg.b.perfrint = DCFG_FRAME_INTERVAL_80; - WRITE_REG32( &core_regs.dev_regs->dev_cfg, dcfg.d32 ); - - /* set Rx FIFO size */ - WRITE_REG32( &core_regs.common_regs->rx_fifo_siz, RX_FIFO_SIZE); - - /* EP0 TX*/ - nptxfifosize.b.depth = TX0_FIFO_SIZE; - nptxfifosize.b.startaddr = RX_FIFO_SIZE; - WRITE_REG32( &core_regs.common_regs->np_tx_fifo_siz, nptxfifosize.d32 ); - - - /* EP1 TX*/ - txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; - txfifosize.b.depth = TX1_FIFO_SIZE; - WRITE_REG32( &core_regs.common_regs->dev_p_tx_fsiz_dieptxf[0], txfifosize.d32 ); - - - /* EP2 TX*/ - txfifosize.b.startaddr += txfifosize.b.depth; - txfifosize.b.depth = TX2_FIFO_SIZE; - WRITE_REG32( &core_regs.common_regs->dev_p_tx_fsiz_dieptxf[1], txfifosize.d32 ); - - - /* EP3 TX*/ - txfifosize.b.startaddr += txfifosize.b.depth; - txfifosize.b.depth = TX3_FIFO_SIZE; - WRITE_REG32( &core_regs.common_regs->dev_p_tx_fsiz_dieptxf[2], txfifosize.d32 ); - - - /* Flush the FIFOs */ - OTGD_FS_FlushTxFifo(0x10); /* all Tx FIFOs */ - OTGD_FS_FlushRxFifo(); - - /* Clear all pending Device Interrupts */ - WRITE_REG32( &core_regs.dev_regs->dev_in_ep_msk, 0 ); - WRITE_REG32( &core_regs.dev_regs->dev_out_ep_msk, 0 ); - WRITE_REG32( &core_regs.dev_regs->dev_all_int, 0xFFFFFFFF ); - WRITE_REG32( &core_regs.dev_regs->dev_all_int_msk, 0 ); - - for (i = 0; i <= MAX_TX_FIFOS; i++) - { - depctl.d32 = READ_REG32(&core_regs.inep_regs[i]->dev_in_ep_ctl); - if (depctl.b.epena) - { - depctl.d32 = 0; - depctl.b.epdis = 1; - depctl.b.snak = 1; - } - else - { - depctl.d32 = 0; - } - - WRITE_REG32( &core_regs.inep_regs[i]->dev_in_ep_ctl, depctl.d32); - - - WRITE_REG32( &core_regs.inep_regs[i]->dev_in_ep_txfer_siz, 0); - WRITE_REG32( &core_regs.inep_regs[i]->dev_in_ep_int, 0xFF); - } - - for (i = 0; i < 1/* NUM_OUT_EPS*/; i++) - { - depctl.d32 = READ_REG32(&core_regs.outep_regs[i]->dev_out_ep_ctl); - if (depctl.b.epena) - { - depctl.d32 = 0; - depctl.b.epdis = 1; - depctl.b.snak = 1; - } - else - { - depctl.d32 = 0; - } - - WRITE_REG32( &core_regs.outep_regs[i]->dev_out_ep_ctl, depctl.d32); - - WRITE_REG32( &core_regs.outep_regs[i]->dev_out_ep_txfer_siz, 0); - WRITE_REG32( &core_regs.outep_regs[i]->dev_out_ep_int, 0xFF); - } - - msk.d32 = 0; - msk.b.txfifoundrn = 1; - MODIFY_REG32(&core_regs.dev_regs->dev_in_ep_msk, msk.d32, msk.d32); - - OTGD_FS_EnableDevInt(); - - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_EnableDevInt -* Description : Enables the Device mode interrupts -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EnableDevInt(void) -{ - - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_int_msk_data intr_mask; - - intr_mask.d32 = 0; - - /* Disable all interrupts. */ - WRITE_REG32( &core_regs.common_regs->int_msk, 0); - - /* Clear any pending interrupts */ - WRITE_REG32( &core_regs.common_regs->int_sts, 0xFFFFFFFF); - - /* Enable the common interrupts */ - EnableCommonInt(); - - /* Enable the defined interrupts*/ -#ifdef INTR_MODEMISMATCH - intr_mask.b.modemismatch = 1; -#endif /* INTR_MODEMISMATCH */ -#ifdef INTR_SOFINTR - intr_mask.b.sofintr = 1; -#endif /* INTR_SOFINTR */ -#ifdef INTR_RXSTSQLVL - intr_mask.b.rxstsqlvl = 1; -#endif /* INTR_RXSTSQLVL */ -#ifdef INTR_NPTXFEMPTY - intr_mask.b.nptxfempty = 1; -#endif /* INTR_NPTXFEMPTY */ -#ifdef INTR_GINNAKEFF - intr_mask.b.ginnakeff = 1; -#endif /* INTR_GINNAKEFF */ -#ifdef INTR_GOUTNAKEFF - intr_mask.b.goutnakeff = 1; -#endif /* INTR_GOUTNAKEFF */ -#ifdef INTR_ERLYSUSPEND - intr_mask.b.erlysuspend = 1; -#endif /* INTR_ERLYSUSPEND */ -#ifdef INTR_USBSUSPEND - intr_mask.b.usbsuspend = 1; -#endif /* INTR_USBSUSPEND */ -#ifdef INTR_USBRESET - intr_mask.b.usbreset = 1; -#endif /* INTR_USBRESET */ -#ifdef INTR_ENUMDONE - intr_mask.b.enumdone = 1; -#endif /* INTR_ENUMDONE */ -#ifdef INTR_ISOOUTDROP - intr_mask.b.isooutdrop = 1; -#endif /* INTR_ISOOUTDROP */ -#ifdef INTR_EOPFRAME - intr_mask.b.eopframe = 1; -#endif /* INTR_EOPFRAME */ -#ifdef INTR_EPMISMATCH - intr_mask.b.epmismatch = 1; -#endif /* INTR_EPMISMATCH */ -#ifdef INTR_INEPINTR - intr_mask.b.inepintr = 1; -#endif /* INTR_INEPINTR */ -#ifdef INTR_OUTEPINTR - intr_mask.b.outepintr = 1; -#endif /* INTR_OUTEPINTR */ -#ifdef INTR_INCOMPLISOIN - intr_mask.b.incomplisoin = 1; -#endif /* INTR_INCOMPLISOIN */ -#ifdef INTR_INCOMPLISOOUT - intr_mask.b.incomplisoout = 1; -#endif /* INTR_INCOMPLISOOUT */ -#ifdef INTR_DISCONNECT - intr_mask.b.disconnect = 1; -#endif /* INTR_DISCONNECT */ -#ifdef INTR_WKUPINTR - intr_mask.b.wkupintr = 1; -#endif /* INTR_WKUPINTR */ - - MODIFY_REG32( &core_regs.common_regs->int_msk, intr_mask.d32, intr_mask.d32); - return status; - -} -/******************************************************************************* -* Function Name : OTGD_FS_EP0Activate -* Description : enables EP0 OUT to receive SETUP packets and configures EP0 - IN for transmitting packets -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EP0Activate(void) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_sts_data dsts; - USB_OTG_dev_ep_ctl_data diepctl; - USB_OTG_dev_ctl_data dctl; - - dsts.d32 = 0; - diepctl.d32 = 0; - dctl.d32 = 0; - - /* Read the Device Status and Endpoint 0 Control registers */ - dsts.d32 = READ_REG32(&core_regs.dev_regs->dev_sts); - diepctl.d32 = READ_REG32(&core_regs.inep_regs[0]->dev_in_ep_ctl); - - /* Set the MPS of the IN EP based on the enumeration speed */ - switch (dsts.b.enumspd) - { - case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: - case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: - case DSTS_ENUMSPD_FS_PHY_48MHZ: - diepctl.b.mps = DEP0CTL_MPS_64; - break; - case DSTS_ENUMSPD_LS_PHY_6MHZ: - diepctl.b.mps = DEP0CTL_MPS_8; - break; - } - - WRITE_REG32(&core_regs.inep_regs[0]->dev_in_ep_ctl, diepctl.d32); - dctl.b.cgnpinnak = 1; - MODIFY_REG32(&core_regs.dev_regs->dev_ctl, dctl.d32, dctl.d32); - - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_EPActivate -* Description : Activates an EP -* Input : ep -* Output : None -* Return : num_in_ep -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EPActivate(USB_OTG_EP *ep) -{ - - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *addr; - USB_OTG_dev_all_int_data daintmsk; - - depctl.d32 = 0; - daintmsk.d32 = 0; - - /* Read DEPCTLn register */ - if (ep->is_in == 1) - { - addr = &core_regs.inep_regs[ep->num]->dev_in_ep_ctl; - daintmsk.ep.in = 1 << ep->num; - } - else - { - addr = &core_regs.outep_regs[ep->num]->dev_out_ep_ctl; - daintmsk.ep.out = 1 << ep->num; - } - - /* If the EP is already active don't change the EP Control - * register. */ - depctl.d32 = READ_REG32(addr); - if (!depctl.b.usbactep) - { - depctl.b.mps = ep->maxpacket; - depctl.b.eptype = ep->type; - depctl.b.txfnum = ep->tx_fifo_num; - depctl.b.setd0pid = 1; - depctl.b.usbactep = 1; - WRITE_REG32(addr, depctl.d32); - } - - /* Enable the Interrupt for this EP */ - MODIFY_REG32(&core_regs.dev_regs->dev_all_int_msk, 0, daintmsk.d32); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_EPDeactivate -* Description : Deactivates an EP -* Input : ep -* Output : None -* Return : num_in_ep -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EPDeactivate(USB_OTG_EP *ep) -{ - - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *addr; - USB_OTG_dev_all_int_data daintmsk; - - depctl.d32 = 0; - daintmsk.d32 = 0; - - /* Read DEPCTLn register */ - if (ep->is_in == 1) - { - addr = &core_regs.inep_regs[ep->num]->dev_in_ep_ctl; - daintmsk.ep.in = 1 << ep->num; - } - else - { - addr = &core_regs.outep_regs[ep->num]->dev_out_ep_ctl; - daintmsk.ep.out = 1 << ep->num; - } - - depctl.b.usbactep = 0; - WRITE_REG32(addr, depctl.d32); - - /* Disable the Interrupt for this EP */ - MODIFY_REG32(&core_regs.dev_regs->dev_all_int_msk, daintmsk.d32, 0); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_EPStartXfer -* Description : Handle the setup for data xfer for an EP and starts the xfer -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EPStartXfer(USB_OTG_EP *ep) -{ - - USB_OTG_Status status = USB_OTG_OK; - __IO USB_OTG_dev_ep_ctl_data depctl; - USB_OTG_dev_ep_txfer_siz_data deptsiz; - - depctl.d32 = 0; - deptsiz.d32 = 0; - - /* IN endpoint */ - if (ep->is_in == 1) - { - - depctl.d32 = READ_REG32(&(core_regs.inep_regs[ep->num]->dev_in_ep_ctl)); - deptsiz.d32 = READ_REG32(&(core_regs.inep_regs[ep->num]->dev_in_ep_txfer_siz)); - - /* Zero Length Packet? */ - if (ep->xfer_len == 0) - { - deptsiz.b.xfersize = 0; - deptsiz.b.pktcnt = 1; - - } - else - { - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet - * exist ? 1 : 0) - */ - deptsiz.b.xfersize = ep->xfer_len; - deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; - } - WRITE_REG32(&core_regs.inep_regs[ep->num]->dev_in_ep_txfer_siz, deptsiz.d32); - - if (ep->type != EP_TYPE_ISOC) - { - /* Enable the Tx FIFO Empty Interrupt for this EP */ - uint32_t fifoemptymsk = 0; - fifoemptymsk = 1 << ep->num; - MODIFY_REG32(&core_regs.dev_regs->dev_fifo_empty_msk, 0, fifoemptymsk); - } - - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - WRITE_REG32(&core_regs.inep_regs[ep->num]->dev_in_ep_ctl, depctl.d32); - - depctl.d32 = READ_REG32 (&core_regs.inep_regs[0]->dev_in_ep_ctl); - depctl.b.nextep = ep->num; - WRITE_REG32 (&core_regs.inep_regs[0]->dev_in_ep_ctl, depctl.d32); - } - else - { - /* OUT endpoint */ - depctl.d32 = READ_REG32(&(core_regs.outep_regs[ep->num]->dev_out_ep_ctl)); - deptsiz.d32 = READ_REG32(&(core_regs.outep_regs[ep->num]->dev_out_ep_txfer_siz)); - - /* Program the transfer size and packet count as follows: - * pktcnt = N - * xfersize = N * maxpacket - */ - if (ep->xfer_len == 0) - { - deptsiz.b.xfersize = ep->maxpacket; - deptsiz.b.pktcnt = 1; - } - else - { - deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - } - WRITE_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_txfer_siz, deptsiz.d32); - - if (ep->type == EP_TYPE_ISOC) - { - - if (ep->even_odd_frame) - { - depctl.b.setd1pid = 1; - } - else - { - depctl.b.setd0pid = 1; - } - } - - /* EP enable */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - - WRITE_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_ctl, depctl.d32); - - } - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_EP0StartXfer -* Description : Handle the setup for a data xfer for EP0 and starts the xfer -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EP0StartXfer(USB_OTG_EP *ep) -{ - - USB_OTG_Status status = USB_OTG_OK; - uint32_t fifoemptymsk = 0; - USB_OTG_dev_ep_ctl_data depctl; - USB_OTG_dev_ep_txfer_size0_data deptsiz; - USB_OTG_dev_in_ep_regs *in_regs ; - - depctl.d32 = 0; - deptsiz.d32 = 0; - - /* IN endpoint */ - if (ep->is_in == 1) - { - in_regs = core_regs.inep_regs[0]; - depctl.d32 = READ_REG32(&in_regs->dev_in_ep_ctl); - deptsiz.d32 = READ_REG32(&in_regs->dev_in_ep_txfer_siz); - - /* Zero Length Packet? */ - if (ep->xfer_len == 0) - { - deptsiz.b.xfersize = 0; - deptsiz.b.pktcnt = 1; - } - else - { - if (ep->xfer_len > ep->maxpacket) - { - ep->xfer_len = ep->maxpacket; - deptsiz.b.xfersize = ep->maxpacket; - } - else - { - deptsiz.b.xfersize = ep->xfer_len; - } - deptsiz.b.pktcnt = 1; - - } - WRITE_REG32(&in_regs->dev_in_ep_txfer_siz, deptsiz.d32); - - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - WRITE_REG32(&in_regs->dev_in_ep_ctl, depctl.d32); - - /* Enable the Tx FIFO Empty Interrupt for this EP */ - if (ep->xfer_len > 0) - { - fifoemptymsk |= 1 << ep->num; - MODIFY_REG32(&core_regs.dev_regs->dev_fifo_empty_msk, 0, fifoemptymsk); - } - } - else - { - /* OUT endpoint */ - depctl.d32 = READ_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_ctl); - deptsiz.d32 = READ_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_txfer_siz); - - /* Program the transfer size and packet count as follows: - * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) - * pktcnt = N */ - if (ep->xfer_len == 0) - { - deptsiz.b.xfersize = ep->maxpacket; - deptsiz.b.pktcnt = 1; - } - else - { - deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - } - - WRITE_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_txfer_siz, deptsiz.d32); - - /* EP enable */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - WRITE_REG32 (&(core_regs.outep_regs[ep->num]->dev_out_ep_ctl), depctl.d32); - } - return status; -} -/******************************************************************************* -* Function Name : OTGD_FS_EPSetStall -* Description : Set the EP STALL -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EPSetStall(USB_OTG_EP *ep) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *depctl_addr; - - depctl.d32 = 0; - - - if (ep->is_in == 1) - { - depctl_addr = &(core_regs.inep_regs[ep->num]->dev_in_ep_ctl); - depctl.d32 = READ_REG32(depctl_addr); - - /* set the disable and stall bits */ - if (depctl.b.epena) - { - depctl.b.epdis = 1; - } - depctl.b.stall = 1; - WRITE_REG32(depctl_addr, depctl.d32); - } - else - { - depctl_addr = &(core_regs.outep_regs[ep->num]->dev_out_ep_ctl); - depctl.d32 = READ_REG32(depctl_addr); - - /* set the stall bit */ - depctl.b.stall = 1; - WRITE_REG32(depctl_addr, depctl.d32); - } - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_EPClearStall -* Description : Clear the EP STALL -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -USB_OTG_Status OTGD_FS_EPClearStall(USB_OTG_EP *ep) -{ - USB_OTG_Status status = USB_OTG_OK; - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *depctl_addr; - - - depctl.d32 = 0; - - if (ep->is_in == 1) - { - depctl_addr = &(core_regs.inep_regs[ep->num]->dev_in_ep_ctl); - } - else - { - depctl_addr = &(core_regs.outep_regs[ep->num]->dev_out_ep_ctl); - } - - - depctl.d32 = READ_REG32(depctl_addr); - - /* clear the stall bits */ - depctl.b.stall = 0; - - if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) - { - depctl.b.setd0pid = 1; /* DATA0 */ - } - - WRITE_REG32(depctl_addr, depctl.d32); - return status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_ReadDevAllOutEp_itr -* Description : returns the OUT endpoint interrupt bits -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -uint32_t OTGD_FS_ReadDevAllOutEp_itr(void) -{ - uint32_t v = 0; - - v = READ_REG32(&core_regs.dev_regs->dev_all_int); - v &= READ_REG32(&core_regs.dev_regs->dev_all_int_msk); - return ((v & 0xffff0000) >> 16); -} - -/******************************************************************************* -* Function Name : OTGD_FS_ReadDevOutEP_itr -* Description : returns the Device OUT EP Interrupt register -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -uint32_t OTGD_FS_ReadDevOutEP_itr(USB_OTG_EP *ep) -{ - uint32_t v = 0; - - v = READ_REG32(&core_regs.outep_regs[ep->num]->dev_out_ep_int); - v &= READ_REG32(&core_regs.dev_regs->dev_out_ep_msk); - return v; -} -/******************************************************************************* -* Function Name : OTGD_FS_ReadDevAllInEPItr -* Description : Get int status register -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -uint32_t OTGD_FS_ReadDevAllInEPItr(void) -{ - uint32_t v = 0; - - v = READ_REG32(&core_regs.dev_regs->dev_all_int); - v &= READ_REG32(&core_regs.dev_regs->dev_all_int_msk); - return (v & 0xffff); -} - -/******************************************************************************* -* Function Name : OTGD_FS_Dev_GetEPStatus -* Description : returns the EP Status -* Input : - ep: pointer to the EP structure -* Output : None -* Return : status: DEV_EP_TX_STALL, DEV_EP_TX_VALID, DEV_EP_TX_NAK, -* DEV_EP_RX_STALL, DEV_EP_RX_VALID or DEV_EP_RX_NAK, -*******************************************************************************/ -uint32_t OTGD_FS_Dev_GetEPStatus(USB_OTG_EP *ep) -{ - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *depctl_addr; - uint32_t Status = 0; - - depctl.d32 = 0; - - if (ep->is_in == 1) - { - depctl_addr = &(core_regs.inep_regs[ep->num]->dev_in_ep_ctl); - } - else - { - depctl_addr = &(core_regs.outep_regs[ep->num]->dev_out_ep_ctl); - } - - depctl.d32 = READ_REG32(depctl_addr); - - /* Process for IN endpoint */ - if (ep->is_in == 1) - { - if (depctl.b.stall == 1) - Status = DEV_EP_TX_STALL; - else if (depctl.b.naksts == 1) - Status = DEV_EP_TX_NAK; - else - Status = DEV_EP_TX_VALID; - } - /* Process for OUT endpoint */ - else - { - if (depctl.b.stall == 1) - Status = DEV_EP_RX_STALL; - else if (depctl.b.naksts == 1) - Status = DEV_EP_RX_NAK; - else - Status = DEV_EP_RX_VALID; - } - - /* Return the current status */ - return Status; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Dev_SetEPStatus -* Description : Sets the EP Status -* Input : - ep: pointer to the EP structure -* - Status: new status to be set -* Output : None -* Return : None -*******************************************************************************/ -void OTGD_FS_Dev_SetEPStatus(USB_OTG_EP *ep, uint32_t Status) -{ - USB_OTG_dev_ep_ctl_data depctl; - __IO uint32_t *depctl_addr; - - depctl.d32 = 0; - - - if (ep->is_in == 1) - { - depctl_addr = &(core_regs.inep_regs[ep->num]->dev_in_ep_ctl); - } - else - { - depctl_addr = &(core_regs.outep_regs[ep->num]->dev_out_ep_ctl); - } - - depctl.d32 = READ_REG32(depctl_addr); - - /* Process for IN endpoint */ - if (ep->is_in == 1) - { - if (Status == DEV_EP_TX_STALL) - { - OTGD_FS_EPSetStall(ep); return; - } - else if (Status == DEV_EP_TX_NAK) - depctl.b.snak = 1; - else if (Status == DEV_EP_TX_VALID) - { - if (depctl.b.stall == 1) - { - ep->even_odd_frame = 0; - OTGD_FS_EPClearStall(ep); - return; - } - depctl.b.cnak = 1; - depctl.b.usbactep = 1; - depctl.b.epena = 1; - } - else if (Status == DEV_EP_TX_DIS) - depctl.b.usbactep = 0; - } - else /* Process for OUT endpoint */ - { - if (Status == DEV_EP_RX_STALL) - depctl.b.stall = 1; - else if (Status == DEV_EP_RX_NAK) - depctl.b.snak = 1; - else if (Status == DEV_EP_RX_VALID) - { - if (depctl.b.stall == 1) - { - ep->even_odd_frame = 0; - OTGD_FS_EPClearStall(ep); - return; - } - depctl.b.cnak = 1; - depctl.b.usbactep = 1; - depctl.b.epena = 1; - } - else if (Status == DEV_EP_RX_DIS) - { - depctl.b.usbactep = 0; - } - } - - if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) - { - depctl.b.setd0pid = 1; /* DATA0 */ - } - - WRITE_REG32(depctl_addr, depctl.d32); -} - -/******************************************************************************* -* Function Name : OTGD_FS_Dev_SetRemoteWakeup -* Description : Enable Remote wakeup signaling -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -void OTGD_FS_Dev_SetRemoteWakeup() -{ - USB_OTG_dev_ctl_data devctl; - __IO uint32_t *dctl_addr; - - devctl.d32 = 0; - - dctl_addr = &(core_regs.dev_regs->dev_ctl); - - devctl.d32 = READ_REG32( dctl_addr); - - /* Enable the Remote Wakeup signal */ - devctl.b.rmtwkupsig = 1; - - WRITE_REG32(dctl_addr, devctl.d32); -} - -/******************************************************************************* -* Function Name : OTGD_FS_Dev_ResetRemoteWakeup -* Description : Disable Remote wakeup signaling -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -void OTGD_FS_Dev_ResetRemoteWakeup() -{ - USB_OTG_dev_ctl_data devctl; - __IO uint32_t *dctl_addr; - - - devctl.d32 = 0; - - dctl_addr = &(core_regs.dev_regs->dev_ctl); - - devctl.d32 = READ_REG32( dctl_addr); - - /* Disable the Remote Wakeup signal */ - devctl.b.rmtwkupsig = 0; - - - WRITE_REG32(dctl_addr, devctl.d32); -} -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/otgd_fs_dev.c b/STM32_USB-FS-Device_Driver/src/otgd_fs_dev.c deleted file mode 100644 index 9b518e8..0000000 --- a/STM32_USB-FS-Device_Driver/src/otgd_fs_dev.c +++ /dev/null @@ -1,386 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_dev.c -* Author : STMicroelectronics -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : High Layer device mode interface and wrapping layer. -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifdef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "otgd_fs_dev.h" -#include "usb_regs.h" -#include "otgd_fs_cal.h" -#include "otgd_fs_pcd.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ - -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : OTG_DEV_Init -* Description : Initialize the OTG Device IP and EP0. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void OTG_DEV_Init(void) -{ - EP_DESCRIPTOR ep_descriptor; - USB_OTG_EP *ep; - - /* Set the OTG_USB base registers address */ - OTGD_FS_SetAddress(USB_OTG_FS1_BASE_ADDR); - - /* Disable all global interrupts */ - OTGD_FS_DisableGlobalInt(); - - /*Init the Core (common init.) */ - OTGD_FS_CoreInit(); - - /* Init Device */ - OTGD_FS_CoreInitDev(); - - /* Init internal driver structure */ - OTGD_FS_PCD_Init(); - - /* Configure and open the IN control EP0 */ - ep_descriptor.bEndpointAddress = 0x80; - ep_descriptor.wMaxPacketSize = 64; - ep_descriptor.bmAttributes = USB_ENDPOINT_XFER_CONTROL; - OTGD_FS_PCD_EP_Open(&ep_descriptor); - - /* Configure and open the OUT control EP0 */ - ep_descriptor.bEndpointAddress = 0x00; - OTGD_FS_PCD_EP_Open(&ep_descriptor); - - - ep = OTGD_FS_PCD_GetOutEP(0); - OTGD_FS_EPStartXfer(ep); - - /* Enable EP0 to start receiving setup packets */ - OTGD_FS_PCD_EP0_OutStart(); - - /* Enable USB Global interrupt */ - OTGD_FS_EnableGlobalInt(); -} - - -/******************************************************************************* -* Function Name : OTG_DEV_EP_Init -* Description : Initialize the selected endpoint parameters -* Input : - bEpAdd: address of the endpoint (epnum|epdir) -* expample: EP1 OUT -> 0x01 and EP1 IN 0x81. -* - bEpType: OTG_DEV_EP_TYPE_CONTROL, OTG_DEV_EP_TYPE_ISOC, -* OTG_DEV_EP_TYPE_BULK, OTG_DEV_EP_TYPE_INT -* - wEpMaxPackSize: The EP max packet size. -* Output : None. -* Return : Status: New status to be set for the endpoint: -*******************************************************************************/ -void OTG_DEV_EP_Init(uint8_t bEpAdd, uint8_t bEpType, uint16_t wEpMaxPackSize) -{ - EP_DESCRIPTOR ep_descriptor; - USB_OTG_EP *ep; - - /* Set the EP parameters in a structure */ - ep_descriptor.bEndpointAddress = bEpAdd; - ep_descriptor.bmAttributes = bEpType; - ep_descriptor.wMaxPacketSize = wEpMaxPackSize; - - OTGD_FS_PCD_EP_Flush(bEpAdd); - - /* Open the EP with entered parameters */ - OTGD_FS_PCD_EP_Open(&ep_descriptor); - - /* Activate the EP if it is an OUT EP */ - if ((bEpAdd & 0x80) == 0) - { - ep = OTGD_FS_PCD_GetOutEP(bEpAdd & 0x7F); - OTGD_FS_EPStartXfer(ep); - } - else - { - ep = OTGD_FS_PCD_GetInEP(bEpAdd & 0x7F); - ep->even_odd_frame = 0; - OTG_DEV_SetEPTxStatus(bEpAdd, DEV_EP_TX_NAK); - } - -} - -/******************************************************************************* -* Function Name : OTG_DEV_GetEPTxStatus -* Description : Set the related endpoint status. -* Input : Number of the endpoint. -* Output : None. -* Return : Status: New status to be set for the endpoint: -*******************************************************************************/ -uint32_t OTG_DEV_GetEPTxStatus(uint8_t bEpnum) -{ - USB_OTG_EP *ep; - uint32_t status = 0; - - ep = OTGD_FS_PCD_GetInEP(bEpnum & 0x7F); - - status = OTGD_FS_Dev_GetEPStatus(ep); - - return status; -} - -/******************************************************************************* -* Function Name : OTG_DEV_GetEPRxStatus -* Description : returns the related endpoint status. -* Input : Number of the endpoint. -* Output : None. -* Return : Status: New status to be set for the endpoint: -*******************************************************************************/ -uint32_t OTG_DEV_GetEPRxStatus(uint8_t bEpnum) -{ - USB_OTG_EP *ep; - uint32_t status = 0; - - ep = OTGD_FS_PCD_GetOutEP(bEpnum & 0x7F); - - status = OTGD_FS_Dev_GetEPStatus(ep); - - return status; -} - -/******************************************************************************* -* Function Name : OTG_DEV_SetEPTxStatus -* Description : Sets the related endpoint status. -* Input : - bEpnum: Number of the endpoint. -* - Status: New status to be set for the endpoint. It can be -* DEV_EP_TX_VALID, DEV_EP_TX_STALL, DEV_EP_TX_NAK or -* DEV_EP_TX_DISABLE. -* Output : None. -* Return : None. -*******************************************************************************/ -void OTG_DEV_SetEPTxStatus(uint8_t bEpnum, uint32_t Status) -{ - USB_OTG_EP *ep; - - ep = OTGD_FS_PCD_GetInEP(bEpnum & 0x7F); - - if ((bEpnum == 0x80) && (Status == DEV_EP_TX_STALL)) - { - ep->is_in = 1; - } - - OTGD_FS_Dev_SetEPStatus(ep, Status); -} - -/******************************************************************************* -* Function Name : OTG_DEV_SetEPRxStatus -* Description : Sets the related endpoint status. -* Input : - bEpnum: Number of the endpoint. -* - Status: New status to be set for the endpoint. It can be -* DEV_EP_RX_VALID, DEV_EP_RX_STALL, DEV_EP_RX_NAK or -* DEV_EP_RX_DISABLE. -* Output : None. -* Return : None. -*******************************************************************************/ -void OTG_DEV_SetEPRxStatus(uint8_t bEpnum, uint32_t Status) -{ - USB_OTG_EP *ep; - - ep = OTGD_FS_PCD_GetOutEP(bEpnum & 0x7F); - - OTGD_FS_Dev_SetEPStatus(ep, Status); -} - -/******************************************************************************* -* Function Name : USB_DevDisconnect -* Description : Disconnect the Pullup resist. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void USB_DevDisconnect(void) -{ - OTGD_FS_PCD_DevDisconnect(); -} - -/******************************************************************************* -* Function Name : USB_DevConnect -* Description : Disconnect the . -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void USB_DevConnect(void) -{ - OTGD_FS_PCD_DevConnect(); -} - -/*-*-*-*-*-*-*-*-*-* Replace the usb_regs.h defines -*-*-*-*-*-*-*-*-*-*-*-*-*/ - -/******************************************************************************* -* Function Name : SetEPTxStatus -* Description : Set the status of Tx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxStatus(uint8_t bEpNum, uint16_t wState) -{ - _SetEPTxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : SetEPRxStatus -* Description : Set the status of Rx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxStatus(uint8_t bEpNum, uint16_t wState) -{ - _SetEPRxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : GetEPTxStatus -* Description : Returns the endpoint Tx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint TX Status -*******************************************************************************/ -uint16_t GetEPTxStatus(uint8_t bEpNum) -{ - return(_GetEPTxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : GetEPRxStatus -* Description : Returns the endpoint Rx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint RX Status -*******************************************************************************/ -uint16_t GetEPRxStatus(uint8_t bEpNum) -{ - return(_GetEPRxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxValid -* Description : Valid the endpoint Tx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxValid(uint8_t bEpNum) -{ - _SetEPTxStatus(bEpNum, EP_TX_VALID); -} - -/******************************************************************************* -* Function Name : SetEPRxValid -* Description : Valid the endpoint Rx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxValid(uint8_t bEpNum) -{ - _SetEPRxStatus(bEpNum, EP_RX_VALID); -} - -/******************************************************************************* -* Function Name : GetTxStallStatus -* Description : Returns the Stall status of the Tx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Tx Stall status. -*******************************************************************************/ -uint16_t GetTxStallStatus(uint8_t bEpNum) -{ - return(_GetTxStallStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : GetRxStallStatus -* Description : Returns the Stall status of the Rx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx Stall status. -*******************************************************************************/ -uint16_t GetRxStallStatus(uint8_t bEpNum) -{ - return(_GetRxStallStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxCount. -* Description : Set the Tx count. -* Input : bEpNum: Endpoint Number. -* wCount: new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxCount(uint8_t bEpNum, uint16_t wCount) -{ -} - -/******************************************************************************* -* Function Name : SetEPRxCount -* Description : Set the Rx count. -* Input : bEpNum: Endpoint Number. -* wCount: the new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxCount(uint8_t bEpNum, uint16_t wCount) -{ -} - -/******************************************************************************* -* Function Name : ToWord -* Description : merge two byte in a word. -* Input : bh: byte high, bl: bytes low. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -uint16_t ToWord(uint8_t bh, uint8_t bl) -{ - uint16_t wRet = 0; - wRet = (uint16_t)bl | ((uint16_t)bh << 8); - return(wRet); -} - -/******************************************************************************* -* Function Name : ByteSwap -* Description : Swap two byte in a word. -* Input : wSwW: word to Swap. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -uint16_t ByteSwap(uint16_t wSwW) -{ - uint8_t bTemp = 0; - uint16_t wRet = 0; - - bTemp = (uint8_t)(wSwW & 0xff); - wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8); - return(wRet); -} - -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/otgd_fs_int.c b/STM32_USB-FS-Device_Driver/src/otgd_fs_int.c deleted file mode 100644 index 6120a4e..0000000 --- a/STM32_USB-FS-Device_Driver/src/otgd_fs_int.c +++ /dev/null @@ -1,874 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_int.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Endpoint interrupt's service routines. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifdef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f10x.h" -#include "usb_type.h" -#include "otgd_fs_int.h" -#include "usb_lib.h" -#include "usb_istr.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Max size of the received OUT Non periodic packet */ -#define MAX_OUT_PKT_SIZE 160 - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ - -uint8_t USBD_Data_Buffer [MAX_OUT_PKT_SIZE]; -__IO uint8_t IsocBuff [(ISOC_BUFFER_SZE * NUM_SUB_BUFFERS)]; -__IO uint32_t IsocBufferIdx = 0; - -extern USB_OTG_CORE_REGS core_regs; - -__IO uint16_t SaveRState; -__IO uint16_t SaveTState; - -/* Extern variables ----------------------------------------------------------*/ -extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */ -extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */ - -/* Private function prototypes -----------------------------------------------*/ -static uint32_t OTGD_FS_PCD_ReadDevInEP( USB_OTG_EP *ep); -static enum usb_device_speed OTGD_FS_PCD_GetDeviceSpeed(void); -static uint32_t OTGD_FS_PCD_WriteEmptyTxFifo(uint32_t epnum); - -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_ModeMismatch_ISR -* Description : Handles the Mode Mismatch error interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_ModeMismatch_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - gintsts.d32 = 0 ; - - INTR_MODEMISMATCH_Callback(); - - /* Clear interrupt */ - gintsts.b.modemismatch = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_Sof_ISR -* Description : Handles the Start Of Frame detected interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_Sof_ISR(void) -{ - USB_OTG_int_sts_data int_sts ; - int_sts.d32 = 0; - - /* Call user function */ - INTR_SOFINTR_Callback(); - - /* Clear interrupt */ - int_sts.b.sofintr = 1; - WRITE_REG32 (&core_regs.common_regs->int_sts, int_sts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_RxStatusQueueLevel_ISR -* Description : Handles the Rx Status Queue Level Interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_RxStatusQueueLevel_ISR(void) -{ - USB_OTG_int_msk_data int_mask; - USB_OTG_dev_rx_sts_data status; - USB_OTG_EP *ep; - - int_mask.d32 = 0; - status.d32 = 0; - - /* Disable the Rx Status Queue Level interrupt */ - int_mask.b.rxstsqlvl = 1; - MODIFY_REG32( &core_regs.common_regs->int_msk, int_mask.d32, 0); - - /* Get the Status from the top of the FIFO */ - status.d32 = READ_REG32( &core_regs.common_regs->rx_stsp ); - - /* Get the related endpoint structure */ - ep = OTGD_FS_PCD_GetOutEP(status.b.epnum); - - switch (status.b.pktsts) - { - case STS_GOUT_NAK: - break; - case STS_DATA_UPDT: - if (status.b.bcnt) - { - if (ep->type == EP_TYPE_ISOC) - { - /* Call user function */ - INTR_RXSTSQLVL_ISODU_Callback(); - - /* Copy the received buffer to the RAM */ - OTGD_FS_ReadPacket((uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)), status.b.bcnt); - ep->xfer_buff = (uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)); - - /* Check if the end of the global buffer has been reached */ - if (IsocBufferIdx == (NUM_SUB_BUFFERS - 1)) - { - /* Reset the buffer index */ - IsocBufferIdx = 0; - } - else - { - /* Increment the buffer index */ - IsocBufferIdx ++; - } - } - else - { - /* Copy the received buffer to the RAM */ - OTGD_FS_ReadPacket(USBD_Data_Buffer, status.b.bcnt); - ep->xfer_buff = USBD_Data_Buffer; - } - - /* Update the endpoint structure */ - ep->xfer_len = status.b.bcnt; - ep->xfer_count += status.b.bcnt; - } - break; - case STS_XFER_COMP: - break; - case STS_SETUP_COMP: - break; - case STS_SETUP_UPDT: - /* Copy the setup packet received in Fifo into the setup buffer in RAM */ - OTGD_FS_ReadPacket(USBD_Data_Buffer, 8); - ep->xfer_buff = USBD_Data_Buffer; - ep->xfer_count += status.b.bcnt; - ep->xfer_len = status.b.bcnt; - break; - default: - break; - } - - /* Call the user function */ - INTR_RXSTSQLVL_Callback(); - - /* Enable the Rx Status Queue Level interrupt */ - MODIFY_REG32( &core_regs.common_regs->int_msk, 0, int_mask.d32); - - /* Clear interrupt: this is a read only bit, it cannot be cleared by register - access */ - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_NPTxFE_ISR -* Description : Handles the Non Periodic Tx FIFO Empty interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_NPTxFE_ISR(void ) -{ - USB_OTG_int_msk_data gintmsk; - gintmsk.d32 = 0; - - /* Call the user function */ - INTR_NPTXFEMPTY_Callback(); - - gintmsk.b.nptxfempty = 1; - MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); - - /* Clear interrupt: This bit is a read only bit, cannot be cleared - by register access */ - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_GInNakEff_ISR -* Description : Handles the Global IN Endpoints NAK Effective interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_GInNakEff_ISR(void) -{ - - /* Call user function */ - INTR_GINNAKEFF_Callback(); - - /* Clear interrupt: This is a read only bit, it cannot be cleared by register - access */ - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_GOutNakEff_ISR -* Description : Handles the Global OUT Endpoints NAK Effective interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_GOutNakEff_ISR(void) -{ - /* Call user function */ - INTR_GOUTNAKEFF_Callback(); - - /* Clear interrupt: This is a read only bit, it cannot be cleared by register - access */ - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_EarlySuspend_ISR -* Description : Handles the Early Suspend detected interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_EarlySuspend_ISR(void ) -{ - USB_OTG_int_sts_data gintsts; - USB_OTG_int_msk_data gintmsk; - - gintsts.d32 = 0; - gintmsk.d32 = 0; - - - /* Call user function */ - INTR_ERLYSUSPEND_Callback(); - - gintmsk.b.erlysuspend = 1; - MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); - - /* Clear interrupt */ - gintsts.b.erlysuspend = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_USBSuspend_ISR -* Description : Handles the Suspend condition detected interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_USBSuspend_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - /* Call user function */ - INTR_USBSUSPEND_Callback(); - - /* Clear interrupt */ - gintsts.b.usbsuspend = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_UsbReset_ISR -* Description : This interrupt occurs when a USB Reset is detected. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_UsbReset_ISR(void) -{ - USB_OTG_dev_all_int_data daintmsk; - USB_OTG_dev_out_ep_msk_data doepmsk; - USB_OTG_dev_in_ep_msk_data diepmsk; - USB_OTG_dev_cfg_data dcfg; - USB_OTG_dev_ctl_data dctl; - USB_OTG_int_sts_data gintsts; - - daintmsk.d32 = 0; - doepmsk.d32 = 0; - diepmsk.d32 = 0; - dcfg.d32 =0; - dctl.d32 = 0; - gintsts.d32 = 0; - - /* Clear the Remote Wakeup Signalling */ - dctl.b.rmtwkupsig = 1; - MODIFY_REG32(&core_regs.dev_regs->dev_ctl, dctl.d32, 0 ); - - /* Flush the NP Tx FIFO */ - OTGD_FS_FlushTxFifo( 0 ); - - daintmsk.b.inep0 = 1; - daintmsk.b.outep0 = 1; - WRITE_REG32( &core_regs.dev_regs->dev_all_int_msk, daintmsk.d32 ); - - doepmsk.b.setup = 1; - doepmsk.b.xfercompl = 1; - doepmsk.b.ahberr = 1; - doepmsk.b.epdisabled = 1; - WRITE_REG32( &core_regs.dev_regs->dev_out_ep_msk, doepmsk.d32 ); - - diepmsk.b.xfercompl = 1; - diepmsk.b.timeout = 1; - diepmsk.b.epdisabled = 1; - diepmsk.b.ahberr = 1; - diepmsk.b.intknepmis = 1; - WRITE_REG32( &core_regs.dev_regs->dev_in_ep_msk, diepmsk.d32 ); - - /* Reset Device Address */ - dcfg.d32 = READ_REG32( &core_regs.dev_regs->dev_cfg); - dcfg.b.devaddr = 0; - WRITE_REG32( &core_regs.dev_regs->dev_cfg, dcfg.d32); - - /* setup EP0 to receive SETUP packets */ - OTGD_FS_PCD_EP0_OutStart(); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.usbreset = 1; - WRITE_REG32 (&core_regs.common_regs->int_sts, gintsts.d32); - - /* Call the user reset function */ - OTGD_FS_DEVICE_RESET; - - /* Call user function */ - INTR_USBRESET_Callback(); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_EnumDone_ISR -* Description : Reads the device status register and set the device speed -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_EnumDone_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - USB_OTG_usb_cfg_data gusbcfg; - - gintsts.d32 = 0; - gusbcfg.d32 = 0; - - OTGD_FS_EP0Activate(); - - /* Set USB turnaround time based on device speed and PHY interface. */ - gusbcfg.d32 = READ_REG32(&core_regs.common_regs->usb_cfg); - - /* Full or low speed */ - if ( OTGD_FS_PCD_GetDeviceSpeed() == USB_SPEED_FULL) - { - gusbcfg.b.usbtrdtim = 9; - } - WRITE_REG32(&core_regs.common_regs->usb_cfg, gusbcfg.d32); - - /* Call user function */ - INTR_ENUMDONE_Callback(); - - /* Clear interrupt */ - gintsts.b.enumdone = 1; - WRITE_REG32( &core_regs.common_regs->int_sts, gintsts.d32 ); - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_IsoOutDrop_ISR -* Description : Handles the Isochrounous Out packet Dropped interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_IsoOutDrop_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - /* Call user function */ - INTR_ISOOUTDROP_Callback(); - - /* Clear interrupt */ - gintsts.b.isooutdrop = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_EOPF_ISR -* Description : Handles the Expexted End Of Periodic Frame interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_EOPF_ISR(void ) -{ - USB_OTG_int_sts_data gintsts; - USB_OTG_int_msk_data gintmsk; - - gintsts.d32 = 0; - gintmsk.d32 = 0; - - gintmsk.b.eopframe = 1; - MODIFY_REG32(&core_regs.common_regs->int_msk, gintmsk.d32, 0 ); - - /* Call user function */ - INTR_EOPFRAME_Callback(); - - /* Clear interrupt */ - gintsts.b.eopframe = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_EPMismatch_ISR -* Description : Handles the Endpoint Mismatch error interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_EPMismatch_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - - /* Call user function */ - INTR_EPMISMATCH_Callback(); - - /* Clear interrupt */ - gintsts.b.epmismatch = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_InEP_ISR -* Description : Handles all IN endpoints interrupts. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_InEP_ISR(void) -{ - USB_OTG_dev_in_ep_int_data diepint; - - uint32_t ep_intr = 0; - uint32_t epnum = 0; - USB_OTG_EP *ep; - uint32_t fifoemptymsk = 0; - - diepint.d32 = 0; - ep_intr = OTGD_FS_ReadDevAllInEPItr(); - while ( ep_intr ) - { - if (ep_intr&0x1) /* In ITR */ - { - ep = OTGD_FS_PCD_GetInEP(epnum); - diepint.d32 = OTGD_FS_PCD_ReadDevInEP(ep); /* Get In ITR status */ - if ( diepint.b.xfercompl ) - { - fifoemptymsk = 0x1 << ep->num; - MODIFY_REG32(&core_regs.dev_regs->dev_fifo_empty_msk, fifoemptymsk, 0); - - /* Clear the Interrupt flag */ - CLEAR_IN_EP_INTR(epnum, xfercompl); - - if (epnum == 0) - { - /* Call the core IN process for EP0 */ - In0_Process(); - - /* before terminate set Tx & Rx status */ - OTG_DEV_SetEPRxStatus(epnum, SaveRState); - OTG_DEV_SetEPTxStatus(epnum, SaveTState); - } - else - { - OTG_DEV_SetEPTxStatus((epnum | 0x80 ), DEV_EP_TX_NAK); - - (*pEpInt_IN[epnum -1])(); - - /* Toggle Endpoint frame ID */ - if (ep->even_odd_frame == 0) - ep->even_odd_frame = 1; - else - ep->even_odd_frame = 0; - } - } - if ( diepint.b.ahberr ) - { - CLEAR_IN_EP_INTR(epnum, ahberr); - } - if ( diepint.b.timeout ) - { - CLEAR_IN_EP_INTR(epnum, timeout); - } - if (diepint.b.intktxfemp) - { - CLEAR_IN_EP_INTR(epnum, intktxfemp); - } - if (diepint.b.intknepmis) - { - CLEAR_IN_EP_INTR(epnum, intknepmis); - } - if (diepint.b.inepnakeff) - { - CLEAR_IN_EP_INTR(epnum, inepnakeff); - } - if (diepint.b.emptyintr) - { - if ((epnum == 0) || (OTG_DEV_GetEPTxStatus(epnum) == DEV_EP_TX_VALID)) - { - OTGD_FS_PCD_WriteEmptyTxFifo(epnum); - } - - CLEAR_IN_EP_INTR(epnum, emptyintr); - } - if ( diepint.b.epdisabled ) - { - /* Reset Endpoint Frame ID to 0 */ - ep->even_odd_frame = 0; - - CLEAR_IN_EP_INTR(epnum, epdisabled); - } - } - epnum++; - ep_intr >>= 1; - } - - /* Call user function */ - INTR_INEPINTR_Callback(); - - return 1; -} - - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_OutEP_ISR -* Description : Handles all OUT endpoints interrupts. -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_OutEP_ISR(void) -{ - uint32_t ep_intr = 0; - USB_OTG_dev_out_ep_int_data doepint; - uint32_t epnum = 0; - USB_OTG_EP *ep; - - doepint.d32 = 0; - - /* Read in the device interrupt bits */ - ep_intr = OTGD_FS_ReadDevAllOutEp_itr(); - - while ( ep_intr ) - { - if (ep_intr&0x1) - { - /* Get EP pointer */ - ep = OTGD_FS_PCD_GetOutEP(epnum); - doepint.d32 = OTGD_FS_ReadDevOutEP_itr(ep); - - /* Transfer complete */ - if ( doepint.b.xfercompl ) - { - /* Clear the bit in DOEPINTn for this interrupt */ - CLEAR_OUT_EP_INTR(epnum, xfercompl); - - if (epnum == 0) - { - /* Call the OUT process for the EP0 */ - Out0_Process(); - } - else - { - (*pEpInt_OUT[epnum-1])(); - } - } - /* Endpoint disable */ - if ( doepint.b.epdisabled ) - { - /* Clear the bit in DOEPINTn for this interrupt */ - CLEAR_OUT_EP_INTR(epnum, epdisabled); - } - /* AHB Error */ - if ( doepint.b.ahberr ) - { - CLEAR_OUT_EP_INTR(epnum, ahberr); - } - /* Setup Phase Done (control EPs) */ - if ( doepint.b.setup ) - { - if (epnum == 0) - { - /* Call the SETUP process for the EP0 */ - Setup0_Process(); - - /* Before exit, update the Tx status */ - OTG_DEV_SetEPTxStatus(0x80, SaveTState); - } - else - { - /* Other control endpoints */ - } - - /* Clear the EP Interrupt */ - CLEAR_OUT_EP_INTR(epnum, setup); - } - } - epnum++; - ep_intr >>= 1; - } - - /* Call user function */ - INTR_OUTEPINTR_Callback(); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_IncomplIsoIn_ISR -* Description : Handles the Incomplete Isochrous IN tranfer error interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_IncomplIsoIn_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - - /* Call user function */ - INTR_INCOMPLISOIN_Callback(); - - /* Clear interrupt */ - gintsts.b.incomplisoin = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_IncomplIsoOut_ISR -* Description : Handles the Incomplete Isochrous OUT tranfer error interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_IncomplIsoOut_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - - /* Call user function */ - INTR_INCOMPLISOOUT_Callback(); - - /* Clear interrupt */ - gintsts.b.outepintr = 1; - WRITE_REG32(&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_Handle_Wakeup_ISR -* Description : Handles the Wakeup or Remote Wakeup detected interrupt. -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_Handle_Wakeup_ISR(void) -{ - USB_OTG_int_sts_data gintsts; - - gintsts.d32 = 0; - /* Call user function */ - INTR_WKUPINTR_Callback(); - - /* Clear interrupt */ - gintsts.b.wkupintr = 1; - WRITE_REG32 (&core_regs.common_regs->int_sts, gintsts.d32); - - return 1; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_GetDeviceSpeed -* Description : Get the device speed from the device status register -* Input : None -* Output : None -* Return : The Device speed value. -*******************************************************************************/ -static enum usb_device_speed OTGD_FS_PCD_GetDeviceSpeed(void) -{ - USB_OTG_dev_sts_data dsts; - enum usb_device_speed speed = USB_SPEED_UNKNOWN; - - dsts.d32 = 0; - - dsts.d32 = READ_REG32(&core_regs.dev_regs->dev_sts); - - switch (dsts.b.enumspd) - { - case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: - speed = USB_SPEED_HIGH; - break; - case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: - case DSTS_ENUMSPD_FS_PHY_48MHZ: - speed = USB_SPEED_FULL; - break; - - case DSTS_ENUMSPD_LS_PHY_6MHZ: - speed = USB_SPEED_LOW; - break; - } - - return speed; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_ReadDevInEP -* Description : Reads all the Endpoints flags. -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -static uint32_t OTGD_FS_PCD_ReadDevInEP( USB_OTG_EP *ep) -{ - uint32_t v = 0, msk = 0, emp=0; - - msk = READ_REG32(&core_regs.dev_regs->dev_in_ep_msk); - emp = READ_REG32(&core_regs.dev_regs->dev_fifo_empty_msk); - msk |= ((emp >> ep->num) & 0x1) << 7; - v = READ_REG32(&core_regs.inep_regs[ep->num]->dev_in_ep_int) & msk; - - return v; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_WriteEmptyTxFifo -* Description : Checks Fifo for the next packet to be loaded. -* Input : None -* Output : None -* Return : Status -*******************************************************************************/ -static uint32_t OTGD_FS_PCD_WriteEmptyTxFifo(uint32_t epnum) -{ - USB_OTG_dev_tx_fifo_sts_data txstatus; - USB_OTG_EP *ep; - uint32_t len = 0; - uint32_t dwords = 0; - USB_OTG_dev_ep_ctl_data depctl; - - - txstatus.d32 = 0; - depctl.d32 = 0; - - ep = OTGD_FS_PCD_GetInEP(epnum); - - len = ep->xfer_len - ep->xfer_count; - - if (len > ep->maxpacket) - { - len = ep->maxpacket; - } - - dwords = (len + 3) / 4; - txstatus.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_tx_fifo_sts); - - /* Manage the case of 0-length data packets toggling data PID */ - if ((ep->xfer_len == 0) && (ep->xfer_count == 0)) - { - if (ep->num > 0) - { - depctl.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl); - if (ep->even_odd_frame == 1) - { - depctl.b.setd0pid = 0; - depctl.b.setd1pid = 1; - } - else - { - depctl.b.setd0pid = 1; - depctl.b.setd1pid = 0; - } - WRITE_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl, depctl.d32); - } - } - - - while ((txstatus.b.txfspcavail > dwords) && - (ep->xfer_count < ep->xfer_len) && - (ep->xfer_len) != 0) - { - if (ep->num > 0) - { - depctl.d32 = READ_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl); - if (ep->even_odd_frame == 0) - { - depctl.b.setd0pid = 1; - depctl.b.setd1pid = 0; - } - else - { - depctl.b.setd0pid = 0; - depctl.b.setd1pid = 1; - } - WRITE_REG32( &core_regs.inep_regs[epnum]->dev_in_ep_ctl, depctl.d32); - } - - /* Write the FIFO */ - len = ep->xfer_len - ep->xfer_count; - - if (len > ep->maxpacket) - { - len = ep->maxpacket; - } - dwords = (len + 3) / 4; - - OTGD_FS_WritePacket(ep->xfer_buff, epnum, len); - - ep->xfer_count += len; - ep->xfer_buff += len; - - txstatus.d32 = READ_REG32(&core_regs.inep_regs[epnum]->dev_tx_fifo_sts); - } - - return 1; -} -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/otgd_fs_pcd.c b/STM32_USB-FS-Device_Driver/src/otgd_fs_pcd.c deleted file mode 100644 index c838757..0000000 --- a/STM32_USB-FS-Device_Driver/src/otgd_fs_pcd.c +++ /dev/null @@ -1,454 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : otgd_fs_pcd.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Peripheral Device Interface low layer. -******************************************************************************** -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#ifdef STM32F10X_CL - -#include "usb_lib.h" -#include "otgd_fs_cal.h" -#include "otgd_fs_pcd.h" - -USB_OTG_PCD_DEV USB_OTG_PCD_dev; - -extern USB_OTG_CORE_REGS core_regs; -/******************************************************************************* -* Function Name : OTGD_FS_PCD_Init -* Description : Initialize the USB Device portion of the driver. -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void OTGD_FS_PCD_Init(void) -{ - uint32_t i = 0; - USB_OTG_EP *ep; - - ep = &USB_OTG_PCD_dev.ep0; - USB_OTG_PCD_dev.ep0state = 0; - - /* Init ep structure */ - ep->num = 0; - ep->tx_fifo_num = 0; - - /* Control until ep is actvated */ - ep->type = EP_TYPE_CTRL; - ep->maxpacket = MAX_PACKET_SIZE; - - ep->xfer_buff = 0; - ep->xfer_len = 0; - - for (i = 1; i < MAX_TX_FIFOS ; i++) - { - ep = &USB_OTG_PCD_dev.in_ep[i-1]; - - /* Init ep structure */ - ep->is_in = 1; - ep->num = i; - ep->tx_fifo_num = i; - - /* Control until ep is actvated */ - ep->type = EP_TYPE_CTRL; - ep->maxpacket = MAX_PACKET_SIZE; - ep->xfer_buff = 0; - ep->xfer_len = 0; - } - - for (i = 1; i < MAX_TX_FIFOS; i++) - { - ep = &USB_OTG_PCD_dev.out_ep[i-1]; - - /* Init ep structure */ - ep->is_in = 0; - ep->num = i; - ep->tx_fifo_num = i; - - /* Control until ep is activated */ - ep->type = EP_TYPE_CTRL; - ep->maxpacket = MAX_PACKET_SIZE; - ep->xfer_buff = 0; - ep->xfer_len = 0; - } - - USB_OTG_PCD_dev.ep0.maxpacket = MAX_EP0_SIZE; - USB_OTG_PCD_dev.ep0.type = EP_TYPE_CTRL; - -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_Open -* Description : Configure an Endpoint -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Open(EP_DESCRIPTOR *epdesc) -{ - USB_OTG_EP *ep; - - - if ((0x80 & epdesc->bEndpointAddress) != 0) - { - ep = OTGD_FS_PCD_GetInEP(epdesc->bEndpointAddress & 0x7F); - ep->is_in = 1; - } - else - { - ep = OTGD_FS_PCD_GetOutEP(epdesc->bEndpointAddress & 0x7F); - ep->is_in = 0; - } - - ep->num = epdesc->bEndpointAddress & 0x7F; - ep->maxpacket = epdesc->wMaxPacketSize; - ep->type = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - if (ep->is_in) - { - /* Assign a Tx FIFO */ - ep->tx_fifo_num = ep->num; - } - - /* Set initial data PID. */ - if ((epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK ) - { - ep->data_pid_start = 0; - } - - OTGD_FS_EPActivate(ep ); - - return 0; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_Close -* Description : Called when an EP is disabled -* Input : Endpoint address. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Close(uint8_t ep_addr) -{ - - USB_OTG_EP *ep; - - if ((0x80 & ep_addr) != 0) - { - ep = OTGD_FS_PCD_GetInEP(ep_addr & 0x7F); - } - else - { - ep = OTGD_FS_PCD_GetOutEP(ep_addr & 0x7F); - } - - ep->num = ep_addr & 0x7F; - ep->is_in = (0x80 & ep_addr) != 0; - - OTGD_FS_EPDeactivate(ep ); - return 0; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_Read -* Description : Read data from Fifo -* Input : Endpoint address. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Read (uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len) -{ - USB_OTG_EP *ep; - uint32_t i = 0; - - ep = OTGD_FS_PCD_GetOutEP(ep_addr & 0x7F); - - /* copy received data into application buffer */ - for (i = 0 ; i < buf_len ; i++) - { - pbuf[i] = ep->xfer_buff[i]; - } - - /*setup and start the Xfer */ - ep->xfer_buff = pbuf; - ep->xfer_len = buf_len; - ep->xfer_count = 0; - ep->is_in = 0; - ep->num = ep_addr & 0x7F; - - if ( ep->num == 0 ) - { - OTGD_FS_EP0StartXfer(ep); - } - else if (USB_OTG_PCD_dev.ep0state == 0) - { - OTGD_FS_EPStartXfer( ep ); - } - - return 0; -} - -/******************************************************************************* -* Function Name : USBF_EP_Write -* Description : Read data from Fifo -* Input : ep -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Write (uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len) -{ - USB_OTG_EP *ep; - - ep = OTGD_FS_PCD_GetInEP(ep_addr & 0x7f); - - /* assign data to EP structure buffer */ - ep->xfer_buff = pbuf; - - /* Setup and start the Transfer */ - ep->xfer_count = 0; - ep->xfer_len = buf_len; - ep->is_in = 1; - ep->num = ep_addr & 0x7F; - - if ( ep->num == 0 ) - { - OTGD_FS_EP0StartXfer(ep); - } - else if (USB_OTG_PCD_dev.ep0state == 0) - { - OTGD_FS_EPStartXfer( ep ); - } - - return 0; -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_Stall -* Description : Stall an endpoint. -* Input : Endpoint Address. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Stall (uint8_t ep_addr) -{ - USB_OTG_EP *ep; - - if ((0x80 & ep_addr) != 0) - { - ep = OTGD_FS_PCD_GetInEP(ep_addr & 0x7F); - } - else - { - ep = OTGD_FS_PCD_GetOutEP(ep_addr & 0x7F); - } - - ep->num = ep_addr & 0x7F; - ep->is_in = ((ep_addr & 0x80) == 0x80) ? 1 : 0; - - OTGD_FS_EPSetStall(ep); - return (0); -} -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_ClrStall -* Description : Clear stall condition on endpoints. -* Input : Endpoint Address. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_ClrStall (uint8_t ep_addr) -{ - - USB_OTG_EP *ep; - - if ((0x80 & ep_addr) != 0) - { - ep = OTGD_FS_PCD_GetInEP(ep_addr & 0x7F); - } - else - { - ep = OTGD_FS_PCD_GetOutEP(ep_addr & 0x7F); - } - - ep->num = ep_addr & 0x7F; - ep->is_in = ((ep_addr & 0x80) == 0x80) ? 1 : 0; - - OTGD_FS_EPClearStall(ep); - - return (0); -} - -/******************************************************************************* -* Function Name : USBF_FCD_EP_Flush() -* Description : This Function flushes the buffer. -* Input : Endpoint Address. -* Output : None -* Return : status -*******************************************************************************/ -uint32_t OTGD_FS_PCD_EP_Flush (uint8_t ep_addr) -{ - - uint8_t is_out = 0; - uint8_t ep_nbr = 0; - - ep_nbr = ep_addr & 0x7F; - is_out = ((ep_addr & 0x80) == 0x80) ? 0 : 1; - - if (is_out == 0) - { - OTGD_FS_FlushTxFifo(ep_nbr); - } - else - { - OTGD_FS_FlushRxFifo(); - } - OTGD_FS_PCD_EP_ClrStall(ep_addr); - return (0); -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP_SetAddress -* Description : This Function set USB device address -* Input : The new device Address to be set. -* Output : None -* Return : status -*******************************************************************************/ -void OTGD_FS_PCD_EP_SetAddress (uint8_t address) -{ - - USB_OTG_dev_cfg_data dcfg; - - dcfg.d32 = 0; - - dcfg.b.devaddr = address; - MODIFY_REG32( &core_regs.dev_regs->dev_cfg, 0, dcfg.d32); -} - - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_GetInEP -* Description : This function returns pointer to IN EP struct with number ep_num -* Input : Endpoint Number. -* Output : None -* Return : status -*******************************************************************************/ -USB_OTG_EP* OTGD_FS_PCD_GetInEP(uint32_t ep_num) -{ - uint32_t i = 0; - - if (ep_num == 0) - { - return &USB_OTG_PCD_dev.ep0; - } - else - { - for (i = 0; i < MAX_TX_FIFOS; ++i) - { - if (USB_OTG_PCD_dev.in_ep[i].num == ep_num) - return &USB_OTG_PCD_dev.in_ep[i]; - } - return 0; - } -} -/******************************************************************************* -* Function Name : USBF_GetOutEP -* Description : returns pointer to OUT EP struct with number ep_num -* Input : Endpoint Number. -* Output : None -* Return : USBF_EP -*******************************************************************************/ -USB_OTG_EP* OTGD_FS_PCD_GetOutEP(uint32_t ep_num) -{ - uint32_t i = 0; - - if (ep_num == 0) - { - return &USB_OTG_PCD_dev.ep0; - } - else - { - for (i = 0; i < MAX_TX_FIFOS; ++i) - { - if (USB_OTG_PCD_dev.out_ep[i].num == ep_num) - return &USB_OTG_PCD_dev.out_ep[i]; - } - return 0; - } -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_DevConnect -* Description : Connect device -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -void OTGD_FS_PCD_DevConnect(void) -{ - - USB_OTG_dev_ctl_data dctl; - - dctl.d32 = 0; - - dctl.d32 = READ_REG32(&core_regs.dev_regs->dev_ctl); - - /* Connect device */ - dctl.b.sftdiscon = 0; - WRITE_REG32(&core_regs.dev_regs->dev_ctl, dctl.d32); - mDELAY(25); -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_DevDisconnect -* Description : Disconnect device -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -void OTGD_FS_PCD_DevDisconnect (void) -{ - - USB_OTG_dev_ctl_data dctl; - - dctl.d32 = 0; - - dctl.d32 = READ_REG32(&core_regs.dev_regs->dev_ctl); - - /* Disconnect device for 20ms */ - dctl.b.sftdiscon = 1; - WRITE_REG32(&core_regs.dev_regs->dev_ctl, dctl.d32); - mDELAY(25); -} - -/******************************************************************************* -* Function Name : OTGD_FS_PCD_EP0_OutStart -* Description : Configures EPO to receive SETUP packets. -* Input : None -* Output : None -* Return : None -*******************************************************************************/ -void OTGD_FS_PCD_EP0_OutStart(void) -{ - - USB_OTG_dev_ep_txfer_size0_data doeptsize0; - doeptsize0.d32 = 0; - - - doeptsize0.b.supcnt = 3; - doeptsize0.b.pktcnt = 1; - doeptsize0.b.xfersize = 8 * 3; - - WRITE_REG32( &core_regs.outep_regs[0]->dev_out_ep_txfer_siz, doeptsize0.d32 ); - -} - -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/STM32_USB-FS-Device_Driver/src/usb_core.c b/STM32_USB-FS-Device_Driver/src/usb_core.c deleted file mode 100644 index 24ee765..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_core.c +++ /dev/null @@ -1,1088 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_core.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Standard protocol processing (USB v2.0) -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, uint32_t n); -extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, uint32_t n); - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -#define ValBit(VAR,Place) (VAR & (1 << Place)) -#define SetBit(VAR,Place) (VAR |= (1 << Place)) -#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255)) - -#ifdef STM32F10X_CL - #define Send0LengthData() {OTGD_FS_PCD_EP_Write (0, 0, 0) ; vSetEPTxStatus(EP_TX_VALID);} -#else -#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \ - vSetEPTxStatus(EP_TX_VALID); \ - } -#endif /* STM32F10X_CL */ - -#define vSetEPRxStatus(st) (SaveRState = st) -#define vSetEPTxStatus(st) (SaveTState = st) - -#define USB_StatusIn() Send0LengthData() -#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) - -#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */ -#define StatusInfo1 StatusInfo.bw.bb0 - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -uint16_t_uint8_t StatusInfo; - -bool Data_Mul_MaxPacketSize = FALSE; -/* Private function prototypes -----------------------------------------------*/ -static void DataStageOut(void); -static void DataStageIn(void); -static void NoData_Setup0(void); -static void Data_Setup0(void); -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : Standard_GetConfiguration. -* Description : Return the current configuration variable address. -* Input : Length - How many bytes are needed. -* Output : None. -* Return : Return 1 , if the request is invalid when "Length" is 0. -* Return "Buffer" if the "Length" is not 0. -*******************************************************************************/ -uint8_t *Standard_GetConfiguration(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = - sizeof(pInformation->Current_Configuration); - return 0; - } - pUser_Standard_Requests->User_GetConfiguration(); - return (uint8_t *)&pInformation->Current_Configuration; -} - -/******************************************************************************* -* Function Name : Standard_SetConfiguration. -* Description : This routine is called to set the configuration value -* Then each class should configure device themself. -* Input : None. -* Output : None. -* Return : Return USB_SUCCESS, if the request is performed. -* Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetConfiguration(void) -{ - - if ((pInformation->USBwValue0 <= - Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0) - && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/ - { - pInformation->Current_Configuration = pInformation->USBwValue0; - pUser_Standard_Requests->User_SetConfiguration(); - return USB_SUCCESS; - } - else - { - return USB_UNSUPPORT; - } -} - -/******************************************************************************* -* Function Name : Standard_GetInterface. -* Description : Return the Alternate Setting of the current interface. -* Input : Length - How many bytes are needed. -* Output : None. -* Return : Return 0, if the request is invalid when "Length" is 0. -* Return "Buffer" if the "Length" is not 0. -*******************************************************************************/ -uint8_t *Standard_GetInterface(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = - sizeof(pInformation->Current_AlternateSetting); - return 0; - } - pUser_Standard_Requests->User_GetInterface(); - return (uint8_t *)&pInformation->Current_AlternateSetting; -} - -/******************************************************************************* -* Function Name : Standard_SetInterface. -* Description : This routine is called to set the interface. -* Then each class should configure the interface them self. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetInterface(void) -{ - RESULT Re; - /*Test if the specified Interface and Alternate Setting are supported by - the application Firmware*/ - Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); - - if (pInformation->Current_Configuration != 0) - { - if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0) - || (pInformation->USBwValue1 != 0)) - { - return USB_UNSUPPORT; - } - else if (Re == USB_SUCCESS) - { - pUser_Standard_Requests->User_SetInterface(); - pInformation->Current_Interface = pInformation->USBwIndex0; - pInformation->Current_AlternateSetting = pInformation->USBwValue0; - return USB_SUCCESS; - } - - } - - return USB_UNSUPPORT; -} - -/******************************************************************************* -* Function Name : Standard_GetStatus. -* Description : Copy the device request data to "StatusInfo buffer". -* Input : - Length - How many bytes are needed. -* Output : None. -* Return : Return 0, if the request is at end of data block, -* or is invalid when "Length" is 0. -*******************************************************************************/ -uint8_t *Standard_GetStatus(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = 2; - return 0; - } - - /* Reset Status Information */ - StatusInfo.w = 0; - - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - /*Get Device Status */ - uint8_t Feature = pInformation->Current_Feature; - - /* Remote Wakeup enabled */ - if (ValBit(Feature, 5)) - { - SetBit(StatusInfo0, 1); - } - else - { - ClrBit(StatusInfo0, 1); - } - - /* Bus-powered */ - if (ValBit(Feature, 6)) - { - SetBit(StatusInfo0, 0); - } - else /* Self-powered */ - { - ClrBit(StatusInfo0, 0); - } - } - /*Interface Status*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - return (uint8_t *)&StatusInfo; - } - /*Get EndPoint Status*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - uint8_t Related_Endpoint; - uint8_t wIndex0 = pInformation->USBwIndex0; - - Related_Endpoint = (wIndex0 & 0x0f); - if (ValBit(wIndex0, 7)) - { - /* IN endpoint */ - if (_GetTxStallStatus(Related_Endpoint)) - { - SetBit(StatusInfo0, 0); /* IN Endpoint stalled */ - } - } - else - { - /* OUT endpoint */ - if (_GetRxStallStatus(Related_Endpoint)) - { - SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */ - } - } - - } - else - { - return NULL; - } - pUser_Standard_Requests->User_GetStatus(); - return (uint8_t *)&StatusInfo; -} - -/******************************************************************************* -* Function Name : Standard_ClearFeature. -* Description : Clear or disable a specific feature. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_ClearFeature(void) -{ - uint32_t Type_Rec = Type_Recipient; - uint32_t Status; - - - if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - {/*Device Clear Feature*/ - ClrBit(pInformation->Current_Feature, 5); - return USB_SUCCESS; - } - else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - {/*EndPoint Clear Feature*/ - const DEVICE* pDev; - uint32_t Related_Endpoint; - uint32_t wIndex0; - uint32_t rEP; - - if ((pInformation->USBwValue != ENDPOINT_STALL) - || (pInformation->USBwIndex1 != 0)) - { - return USB_UNSUPPORT; - } - - pDev = &Device_Table; - wIndex0 = pInformation->USBwIndex0; - rEP = wIndex0 & ~0x80; - Related_Endpoint = ENDP0 + rEP; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /*Get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if ((rEP >= pDev->Total_Endpoint) || (Status == 0) - || (pInformation->Current_Configuration == 0)) - { - return USB_UNSUPPORT; - } - - - if (wIndex0 & 0x80) - { - /* IN endpoint */ - if (_GetTxStallStatus(Related_Endpoint )) - { - #ifndef STM32F10X_CL - ClearDTOG_TX(Related_Endpoint); - #endif /* STM32F10X_CL */ - SetEPTxStatus(Related_Endpoint, EP_TX_VALID); - } - } - else - { - /* OUT endpoint */ - if (_GetRxStallStatus(Related_Endpoint)) - { - if (Related_Endpoint == ENDP0) - { - /* After clear the STALL, enable the default endpoint receiver */ - _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); - } - else - { - #ifndef STM32F10X_CL - ClearDTOG_RX(Related_Endpoint); - #endif /* STM32F10X_CL */ - _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); - } - } - } - pUser_Standard_Requests->User_ClearFeature(); - return USB_SUCCESS; - } - - return USB_UNSUPPORT; -} - -/******************************************************************************* -* Function Name : Standard_SetEndPointFeature -* Description : Set or enable a specific feature of EndPoint -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetEndPointFeature(void) -{ - uint32_t wIndex0; - uint32_t Related_Endpoint; - uint32_t rEP; - uint32_t Status; - - wIndex0 = pInformation->USBwIndex0; - rEP = wIndex0 & ~0x80; - Related_Endpoint = ENDP0 + rEP; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /* get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if (Related_Endpoint >= Device_Table.Total_Endpoint - || pInformation->USBwValue != 0 || Status == 0 - || pInformation->Current_Configuration == 0) - { - return USB_UNSUPPORT; - } - else - { - if (wIndex0 & 0x80) - { - /* IN endpoint */ - _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); - } - - else - { - /* OUT endpoint */ - _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); - } - } - pUser_Standard_Requests->User_SetEndPointFeature(); - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Standard_SetDeviceFeature. -* Description : Set or enable a specific feature of Device. -* Input : None. -* Output : None. -* Return : - Return USB_SUCCESS, if the request is performed. -* - Return USB_UNSUPPORT, if the request is invalid. -*******************************************************************************/ -RESULT Standard_SetDeviceFeature(void) -{ - SetBit(pInformation->Current_Feature, 5); - pUser_Standard_Requests->User_SetDeviceFeature(); - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Standard_GetDescriptorData. -* Description : Standard_GetDescriptorData is used for descriptors transfer. -* : This routine is used for the descriptors resident in Flash -* or RAM -* pDesc can be in either Flash or RAM -* The purpose of this routine is to have a versatile way to -* response descriptors request. It allows user to generate -* certain descriptors with software or read descriptors from -* external storage part by part. -* Input : - Length - Length of the data in this transfer. -* - pDesc - A pointer points to descriptor struct. -* The structure gives the initial address of the descriptor and -* its original size. -* Output : None. -* Return : Address of a part of the descriptor pointed by the Usb_ -* wOffset The buffer pointed by this address contains at least -* Length bytes. -*******************************************************************************/ -uint8_t *Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR *pDesc) -{ - uint32_t wOffset; - - wOffset = pInformation->Ctrl_Info.Usb_wOffset; - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; - return 0; - } - - return pDesc->Descriptor + wOffset; -} - -/******************************************************************************* -* Function Name : DataStageOut. -* Description : Data stage of a Control Write Transfer. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void DataStageOut(void) -{ - ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; - uint32_t save_rLength; - - save_rLength = pEPinfo->Usb_rLength; - - if (pEPinfo->CopyData && save_rLength) - { - uint8_t *Buffer; - uint32_t Length; - - Length = pEPinfo->PacketSize; - if (Length > save_rLength) - { - Length = save_rLength; - } - - Buffer = (*pEPinfo->CopyData)(Length); - pEPinfo->Usb_rLength -= Length; - pEPinfo->Usb_rOffset += Length; - - #ifdef STM32F10X_CL - OTGD_FS_PCD_EP_Read(ENDP0, Buffer, Length); - #else - usb_lld_from_pmabuf (Buffer, GetEPRxAddr(ENDP0), Length); - #endif /* STM32F10X_CL */ - } - - if (pEPinfo->Usb_rLength != 0) - { - vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */ - SetEPTxCount(ENDP0, 0); - vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage */ - } - /* Set the next State*/ - if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) - { - pInformation->ControlState = OUT_DATA; - } - else - { - if (pEPinfo->Usb_rLength > 0) - { - pInformation->ControlState = LAST_OUT_DATA; - } - else if (pEPinfo->Usb_rLength == 0) - { - pInformation->ControlState = WAIT_STATUS_IN; - USB_StatusIn(); - } - } -} - -/******************************************************************************* -* Function Name : DataStageIn. -* Description : Data stage of a Control Read Transfer. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void DataStageIn(void) -{ - ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; - uint32_t save_wLength = pEPinfo->Usb_wLength; - uint32_t ControlState = pInformation->ControlState; - - uint8_t *DataBuffer; - uint32_t Length; - - if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) - { - if(Data_Mul_MaxPacketSize == TRUE) - { - /* No more data to send and empty packet */ - Send0LengthData(); - ControlState = LAST_IN_DATA; - Data_Mul_MaxPacketSize = FALSE; - } - else - { - /* No more data to send so STALL the TX Status*/ - ControlState = WAIT_STATUS_OUT; - - #ifdef STM32F10X_CL - OTGD_FS_PCD_EP_Read (ENDP0, 0, 0); - #endif /* STM32F10X_CL */ - - #ifndef STM32F10X_CL - vSetEPTxStatus(EP_TX_STALL); - #endif /* STM32F10X_CL */ - } - - goto Expect_Status_Out; - } - - Length = pEPinfo->PacketSize; - ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA; - - if (Length > save_wLength) - { - Length = save_wLength; - } - - DataBuffer = (*pEPinfo->CopyData)(Length); - -#ifdef STM32F10X_CL - OTGD_FS_PCD_EP_Write (ENDP0, DataBuffer, Length); -#else - usb_lld_to_pmabuf (DataBuffer, GetEPTxAddr(ENDP0), Length); -#endif /* STM32F10X_CL */ - - SetEPTxCount(ENDP0, Length); - - pEPinfo->Usb_wLength -= Length; - pEPinfo->Usb_wOffset += Length; - vSetEPTxStatus(EP_TX_VALID); - - USB_StatusOut();/* Expect the host to abort the data IN stage */ - -Expect_Status_Out: - pInformation->ControlState = ControlState; -} - -/******************************************************************************* -* Function Name : NoData_Setup0. -* Description : Proceed the processing of setup request without data stage. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void NoData_Setup0(void) -{ - RESULT Result = USB_UNSUPPORT; - uint32_t RequestNo = pInformation->USBbRequest; - uint32_t ControlState; - - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - /* Device Request*/ - /* SET_CONFIGURATION*/ - if (RequestNo == SET_CONFIGURATION) - { - Result = Standard_SetConfiguration(); - } - - /*SET ADDRESS*/ - else if (RequestNo == SET_ADDRESS) - { - if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) - || (pInformation->USBwIndex != 0) - || (pInformation->Current_Configuration != 0)) - /* Device Address should be 127 or less*/ - { - ControlState = STALLED; - goto exit_NoData_Setup0; - } - else - { - Result = USB_SUCCESS; - - #ifdef STM32F10X_CL - SetDeviceAddress(pInformation->USBwValue0); - #endif /* STM32F10X_CL */ - } - } - /*SET FEATURE for Device*/ - else if (RequestNo == SET_FEATURE) - { - if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) - && (pInformation->USBwIndex == 0) - && (ValBit(pInformation->Current_Feature, 5))) - { - Result = Standard_SetDeviceFeature(); - } - else - { - Result = USB_UNSUPPORT; - } - } - /*Clear FEATURE for Device */ - else if (RequestNo == CLEAR_FEATURE) - { - if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP - && pInformation->USBwIndex == 0 - && ValBit(pInformation->Current_Feature, 5)) - { - Result = Standard_ClearFeature(); - } - else - { - Result = USB_UNSUPPORT; - } - } - - } - - /* Interface Request*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - /*SET INTERFACE*/ - if (RequestNo == SET_INTERFACE) - { - Result = Standard_SetInterface(); - } - } - - /* EndPoint Request*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - /*CLEAR FEATURE for EndPoint*/ - if (RequestNo == CLEAR_FEATURE) - { - Result = Standard_ClearFeature(); - } - /* SET FEATURE for EndPoint*/ - else if (RequestNo == SET_FEATURE) - { - Result = Standard_SetEndPointFeature(); - } - } - else - { - Result = USB_UNSUPPORT; - } - - - if (Result != USB_SUCCESS) - { - Result = (*pProperty->Class_NoData_Setup)(RequestNo); - if (Result == USB_NOT_READY) - { - ControlState = PAUSE; - goto exit_NoData_Setup0; - } - } - - if (Result != USB_SUCCESS) - { - ControlState = STALLED; - goto exit_NoData_Setup0; - } - - ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */ - - USB_StatusIn(); - -exit_NoData_Setup0: - pInformation->ControlState = ControlState; - return; -} - -/******************************************************************************* -* Function Name : Data_Setup0. -* Description : Proceed the processing of setup request with data stage. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Data_Setup0(void) -{ - uint8_t *(*CopyRoutine)(uint16_t); - RESULT Result; - uint32_t Request_No = pInformation->USBbRequest; - - uint32_t Related_Endpoint, Reserved; - uint32_t wOffset, Status; - - - - CopyRoutine = NULL; - wOffset = 0; - - /*GET DESCRIPTOR*/ - if (Request_No == GET_DESCRIPTOR) - { - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - uint8_t wValue1 = pInformation->USBwValue1; - if (wValue1 == DEVICE_DESCRIPTOR) - { - CopyRoutine = pProperty->GetDeviceDescriptor; - } - else if (wValue1 == CONFIG_DESCRIPTOR) - { - CopyRoutine = pProperty->GetConfigDescriptor; - } - else if (wValue1 == STRING_DESCRIPTOR) - { - CopyRoutine = pProperty->GetStringDescriptor; - } /* End of GET_DESCRIPTOR */ - } - } - - /*GET STATUS*/ - else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) - && (pInformation->USBwLength == 0x0002) - && (pInformation->USBwIndex1 == 0)) - { - /* GET STATUS for Device*/ - if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - && (pInformation->USBwIndex == 0)) - { - CopyRoutine = Standard_GetStatus; - } - - /* GET STATUS for Interface*/ - else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - { - if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS) - && (pInformation->Current_Configuration != 0)) - { - CopyRoutine = Standard_GetStatus; - } - } - - /* GET STATUS for EndPoint*/ - else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) - { - Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); - Reserved = pInformation->USBwIndex0 & 0x70; - - if (ValBit(pInformation->USBwIndex0, 7)) - { - /*Get Status of endpoint & stall the request if the related_ENdpoint - is Disabled*/ - Status = _GetEPTxStatus(Related_Endpoint); - } - else - { - Status = _GetEPRxStatus(Related_Endpoint); - } - - if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0) - && (Status != 0)) - { - CopyRoutine = Standard_GetStatus; - } - } - - } - - /*GET CONFIGURATION*/ - else if (Request_No == GET_CONFIGURATION) - { - if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) - { - CopyRoutine = Standard_GetConfiguration; - } - } - /*GET INTERFACE*/ - else if (Request_No == GET_INTERFACE) - { - if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) - && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0) - && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) - && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) - { - CopyRoutine = Standard_GetInterface; - } - - } - - if (CopyRoutine) - { - pInformation->Ctrl_Info.Usb_wOffset = wOffset; - pInformation->Ctrl_Info.CopyData = CopyRoutine; - /* sb in the original the cast to word was directly */ - /* now the cast is made step by step */ - (*CopyRoutine)(0); - Result = USB_SUCCESS; - } - else - { - Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest); - if (Result == USB_NOT_READY) - { - pInformation->ControlState = PAUSE; - return; - } - } - - if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) - { - /* Data is not ready, wait it */ - pInformation->ControlState = PAUSE; - return; - } - if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) - { - /* Unsupported request */ - pInformation->ControlState = STALLED; - return; - } - - - if (ValBit(pInformation->USBbmRequestType, 7)) - { - /* Device ==> Host */ - __IO uint32_t wLength = pInformation->USBwLength; - - /* Restrict the data length to be the one host asks for */ - if (pInformation->Ctrl_Info.Usb_wLength > wLength) - { - pInformation->Ctrl_Info.Usb_wLength = wLength; - } - - else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) - { - if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) - { - Data_Mul_MaxPacketSize = FALSE; - } - else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) - { - Data_Mul_MaxPacketSize = TRUE; - } - } - - pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; - DataStageIn(); - } - else - { - pInformation->ControlState = OUT_DATA; - vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */ - } - - return; -} - -/******************************************************************************* -* Function Name : Setup0_Process -* Description : Get the device request data and dispatch to individual process. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -uint8_t Setup0_Process(void) -{ - - union - { - uint8_t* b; - uint16_t* w; - } pBuf; - -#ifdef STM32F10X_CL - USB_OTG_EP *ep; - uint16_t offset = 0; - - ep = OTGD_FS_PCD_GetOutEP(ENDP0); - pBuf.b = ep->xfer_buff; - - OTGD_FS_EP0StartXfer(ep); -#else - uint16_t offset = 1; - - pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ -#endif /* STM32F10X_CL */ - - if (pInformation->ControlState != PAUSE) - { - pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ - pInformation->USBbRequest = *pBuf.b++; /* bRequest */ - pBuf.w += offset; /* word not accessed because of 32 bits addressing */ - pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */ - pBuf.w += offset; /* word not accessed because of 32 bits addressing */ - pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */ - pBuf.w += offset; /* word not accessed because of 32 bits addressing */ - pInformation->USBwLength = *pBuf.w; /* wLength */ - } - - pInformation->ControlState = SETTING_UP; - if (pInformation->USBwLength == 0) - { - /* Setup with no data stage */ - NoData_Setup0(); - } - else - { - /* Setup with data stage */ - Data_Setup0(); - } - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : In0_Process -* Description : Process the IN token on all default endpoint. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -uint8_t In0_Process(void) -{ - uint32_t ControlState = pInformation->ControlState; - - if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) - { - DataStageIn(); - /* ControlState may be changed outside the function */ - ControlState = pInformation->ControlState; - } - - else if (ControlState == WAIT_STATUS_IN) - { - if ((pInformation->USBbRequest == SET_ADDRESS) && - (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) - { - SetDeviceAddress(pInformation->USBwValue0); - pUser_Standard_Requests->User_SetDeviceAddress(); - } - (*pProperty->Process_Status_IN)(); - ControlState = STALLED; - } - - else - { - ControlState = STALLED; - } - - pInformation->ControlState = ControlState; - - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : Out0_Process -* Description : Process the OUT token on all default endpoint. -* Input : None. -* Output : None. -* Return : Post0_Process. -*******************************************************************************/ -uint8_t Out0_Process(void) -{ - uint32_t ControlState = pInformation->ControlState; - - if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) - { - /* host aborts the transfer before finish */ - ControlState = STALLED; - } - else if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) - { - DataStageOut(); - ControlState = pInformation->ControlState; /* may be changed outside the function */ - } - - else if (ControlState == WAIT_STATUS_OUT) - { - (*pProperty->Process_Status_OUT)(); - #ifndef STM32F10X_CL - ControlState = STALLED; - #endif /* STM32F10X_CL */ - } - - - /* Unexpect state, STALL the endpoint */ - else - { - ControlState = STALLED; - } - - pInformation->ControlState = ControlState; - - return Post0_Process(); -} - -/******************************************************************************* -* Function Name : Post0_Process -* Description : Stall the Endpoint 0 in case of error. -* Input : None. -* Output : None. -* Return : - 0 if the control State is in PAUSE -* - 1 if not. -*******************************************************************************/ -uint8_t Post0_Process(void) -{ -#ifdef STM32F10X_CL - USB_OTG_EP *ep; -#endif /* STM32F10X_CL */ - - if (pInformation->ControlState == STALLED) - { - vSetEPRxStatus(EP_RX_STALL); - vSetEPTxStatus(EP_TX_STALL); - } - -#ifdef STM32F10X_CL - else if ((pInformation->ControlState == OUT_DATA) || - (pInformation->ControlState == WAIT_STATUS_OUT)) - { - ep = OTGD_FS_PCD_GetInEP(0); - ep->is_in = 0; - OTGD_FS_EP0StartXfer(ep); - - vSetEPTxStatus(EP_TX_VALID); - } - - else if ((pInformation->ControlState == IN_DATA) || - (pInformation->ControlState == WAIT_STATUS_IN)) - { - ep = OTGD_FS_PCD_GetInEP(0); - ep->is_in = 1; - OTGD_FS_EP0StartXfer(ep); - } -#endif /* STM32F10X_CL */ - - return (pInformation->ControlState == PAUSE); -} - -/******************************************************************************* -* Function Name : SetDeviceAddress. -* Description : Set the device and all the used Endpoints addresses. -* Input : - Val: device adress. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDeviceAddress(uint8_t Val) -{ -#ifdef STM32F10X_CL - OTGD_FS_PCD_EP_SetAddress ((uint8_t)Val); -#else - uint32_t i; - uint32_t nEP = Device_Table.Total_Endpoint; - - /* set address in every used endpoint */ - for (i = 0; i < nEP; i++) - { - _SetEPAddress((uint8_t)i, (uint8_t)i); - } /* for */ - _SetDADDR(Val | DADDR_EF); /* set device address and enable function */ -#endif /* STM32F10X_CL */ -} - -/******************************************************************************* -* Function Name : NOP_Process -* Description : No operation function. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void NOP_Process(void) -{ -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/usb_init.c b/STM32_USB-FS-Device_Driver/src/usb_init.c deleted file mode 100644 index d318106..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_init.c +++ /dev/null @@ -1,63 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_init.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Initialization routines & global variables -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* The number of current endpoint, it will be used to specify an endpoint */ - uint8_t EPindex; -/* The number of current device, it is an index to the Device_Table */ -/* uint8_t Device_no; */ -/* Points to the DEVICE_INFO structure of current device */ -/* The purpose of this register is to speed up the execution */ -DEVICE_INFO *pInformation; -/* Points to the DEVICE_PROP structure of current device */ -/* The purpose of this register is to speed up the execution */ -const DEVICE_PROP *pProperty; -/* Temporary save the state of Rx & Tx status. */ -/* Whenever the Rx or Tx state is changed, its value is saved */ -/* in this variable first and will be set to the EPRB or EPRA */ -/* at the end of interrupt process */ -uint16_t SaveState ; -uint16_t wInterrupt_Mask; -DEVICE_INFO Device_Info; -const USER_STANDARD_REQUESTS *pUser_Standard_Requests; - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : USB_Init -* Description : USB system initialization -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void USB_Init(void) -{ - pInformation = &Device_Info; - pInformation->ControlState = 2; - pProperty = &Device_Property; - pUser_Standard_Requests = &User_Standard_Requests; - /* Initialize devices one by one */ - pProperty->Init(); -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/usb_int.c b/STM32_USB-FS-Device_Driver/src/usb_int.c deleted file mode 100644 index 00b9838..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_int.c +++ /dev/null @@ -1,188 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_int.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Endpoint CTR (Low and High) interrupt's service routines -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ -#ifndef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -__IO uint16_t SaveRState; -__IO uint16_t SaveTState; - -/* Extern variables ----------------------------------------------------------*/ -extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */ -extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */ - -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : CTR_LP. -* Description : Low priority Endpoint Correct Transfer interrupt's service -* routine. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void CTR_LP(void) -{ - __IO uint16_t wEPVal = 0; - /* stay in loop while pending ints */ - while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) - { - /* extract highest priority endpoint number */ - EPindex = (uint8_t)(wIstr & ISTR_EP_ID); - if (EPindex == 0) - { - /* Decode and service control endpoint interrupt */ - /* calling related service routine */ - /* (Setup0_Process, In0_Process, Out0_Process) */ - - /* save RX & TX status */ - /* and set both to NAK */ - - - SaveRState = _GetENDPOINT(ENDP0); - SaveTState = SaveRState & EPTX_STAT; - SaveRState &= EPRX_STAT; - - _SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK); - - /* DIR bit = origin of the interrupt */ - - if ((wIstr & ISTR_DIR) == 0) - { - /* DIR = 0 */ - - /* DIR = 0 => IN int */ - /* DIR = 0 implies that (EP_CTR_TX = 1) always */ - - - _ClearEP_CTR_TX(ENDP0); - In0_Process(); - - /* before terminate set Tx & Rx status */ - - _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); - return; - } - else - { - /* DIR = 1 */ - - /* DIR = 1 & CTR_RX => SETUP or OUT int */ - /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ - - wEPVal = _GetENDPOINT(ENDP0); - - if ((wEPVal &EP_SETUP) != 0) - { - _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */ - Setup0_Process(); - /* before terminate set Tx & Rx status */ - - _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); - return; - } - - else if ((wEPVal & EP_CTR_RX) != 0) - { - _ClearEP_CTR_RX(ENDP0); - Out0_Process(); - /* before terminate set Tx & Rx status */ - - _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); - return; - } - } - }/* if(EPindex == 0) */ - else - { - /* Decode and service non control endpoints interrupt */ - - /* process related endpoint register */ - wEPVal = _GetENDPOINT(EPindex); - if ((wEPVal & EP_CTR_RX) != 0) - { - /* clear int flag */ - _ClearEP_CTR_RX(EPindex); - - /* call OUT service function */ - (*pEpInt_OUT[EPindex-1])(); - - } /* if((wEPVal & EP_CTR_RX) */ - - if ((wEPVal & EP_CTR_TX) != 0) - { - /* clear int flag */ - _ClearEP_CTR_TX(EPindex); - - /* call IN service function */ - (*pEpInt_IN[EPindex-1])(); - } /* if((wEPVal & EP_CTR_TX) != 0) */ - - }/* if(EPindex == 0) else */ - - }/* while(...) */ -} - -/******************************************************************************* -* Function Name : CTR_HP. -* Description : High Priority Endpoint Correct Transfer interrupt's service -* routine. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void CTR_HP(void) -{ - uint32_t wEPVal = 0; - - while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) - { - _SetISTR((uint16_t)CLR_CTR); /* clear CTR flag */ - /* extract highest priority endpoint number */ - EPindex = (uint8_t)(wIstr & ISTR_EP_ID); - /* process related endpoint register */ - wEPVal = _GetENDPOINT(EPindex); - if ((wEPVal & EP_CTR_RX) != 0) - { - /* clear int flag */ - _ClearEP_CTR_RX(EPindex); - - /* call OUT service function */ - (*pEpInt_OUT[EPindex-1])(); - - } /* if((wEPVal & EP_CTR_RX) */ - else if ((wEPVal & EP_CTR_TX) != 0) - { - /* clear int flag */ - _ClearEP_CTR_TX(EPindex); - - /* call IN service function */ - (*pEpInt_IN[EPindex-1])(); - - - } /* if((wEPVal & EP_CTR_TX) != 0) */ - - }/* while(...) */ -} - -#endif /* STM32F10X_CL */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/usb_mem.c b/STM32_USB-FS-Device_Driver/src/usb_mem.c deleted file mode 100644 index cdffaa9..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_mem.c +++ /dev/null @@ -1,75 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_mem.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Utility functions for memory transfers to/from PMA -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ -#ifndef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/******************************************************************************* -* Function Name : UserToPMABufferCopy -* Description : Copy a buffer from user memory area to packet memory area (PMA) -* Input : - pbUsrBuf: pointer to user memory area. -* - wPMABufAddr: address into PMA. -* - wNBytes: no. of bytes to be copied. -* Output : None. -* Return : None . -*******************************************************************************/ -void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) -{ - uint32_t n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ - uint32_t i, temp1, temp2; - uint16_t *pdwVal; - pdwVal = (uint16_t *)(wPMABufAddr * 2 + PMAAddr); - for (i = n; i != 0; i--) - { - temp1 = (uint16_t) * pbUsrBuf; - pbUsrBuf++; - temp2 = temp1 | (uint16_t) * pbUsrBuf << 8; - *pdwVal++ = temp2; - pdwVal++; - pbUsrBuf++; - } -} -/******************************************************************************* -* Function Name : PMAToUserBufferCopy -* Description : Copy a buffer from user memory area to packet memory area (PMA) -* Input : - pbUsrBuf = pointer to user memory area. -* - wPMABufAddr = address into PMA. -* - wNBytes = no. of bytes to be copied. -* Output : None. -* Return : None. -*******************************************************************************/ -void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) -{ - uint32_t n = (wNBytes + 1) >> 1;/* /2*/ - uint32_t i; - uint32_t *pdwVal; - pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr); - for (i = n; i != 0; i--) - { - *(uint16_t*)pbUsrBuf++ = *pdwVal++; - pbUsrBuf++; - } -} - -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/usb_regs.c b/STM32_USB-FS-Device_Driver/src/usb_regs.c deleted file mode 100644 index a2e923e..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_regs.c +++ /dev/null @@ -1,750 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_regs.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Interface functions to USB cell registers -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ -#ifndef STM32F10X_CL - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : SetCNTR. -* Description : Set the CNTR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetCNTR(uint16_t wRegValue) -{ - _SetCNTR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetCNTR. -* Description : returns the CNTR register value. -* Input : None. -* Output : None. -* Return : CNTR register Value. -*******************************************************************************/ -uint16_t GetCNTR(void) -{ - return(_GetCNTR()); -} - -/******************************************************************************* -* Function Name : SetISTR. -* Description : Set the ISTR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetISTR(uint16_t wRegValue) -{ - _SetISTR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetISTR -* Description : Returns the ISTR register value. -* Input : None. -* Output : None. -* Return : ISTR register Value -*******************************************************************************/ -uint16_t GetISTR(void) -{ - return(_GetISTR()); -} - -/******************************************************************************* -* Function Name : GetFNR -* Description : Returns the FNR register value. -* Input : None. -* Output : None. -* Return : FNR register Value -*******************************************************************************/ -uint16_t GetFNR(void) -{ - return(_GetFNR()); -} - -/******************************************************************************* -* Function Name : SetDADDR -* Description : Set the DADDR register value. -* Input : wRegValue: new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDADDR(uint16_t wRegValue) -{ - _SetDADDR(wRegValue); -} - -/******************************************************************************* -* Function Name : GetDADDR -* Description : Returns the DADDR register value. -* Input : None. -* Output : None. -* Return : DADDR register Value -*******************************************************************************/ -uint16_t GetDADDR(void) -{ - return(_GetDADDR()); -} - -/******************************************************************************* -* Function Name : SetBTABLE -* Description : Set the BTABLE. -* Input : wRegValue: New register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetBTABLE(uint16_t wRegValue) -{ - _SetBTABLE(wRegValue); -} - -/******************************************************************************* -* Function Name : GetBTABLE. -* Description : Returns the BTABLE register value. -* Input : None. -* Output : None. -* Return : BTABLE address. -*******************************************************************************/ -uint16_t GetBTABLE(void) -{ - return(_GetBTABLE()); -} - -/******************************************************************************* -* Function Name : SetENDPOINT -* Description : Setthe Endpoint register value. -* Input : bEpNum: Endpoint Number. -* wRegValue. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetENDPOINT(uint8_t bEpNum, uint16_t wRegValue) -{ - _SetENDPOINT(bEpNum, wRegValue); -} - -/******************************************************************************* -* Function Name : GetENDPOINT -* Description : Return the Endpoint register value. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint register value. -*******************************************************************************/ -uint16_t GetENDPOINT(uint8_t bEpNum) -{ - return(_GetENDPOINT(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPType -* Description : sets the type in the endpoint register. -* Input : bEpNum: Endpoint Number. -* wType: type definition. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPType(uint8_t bEpNum, uint16_t wType) -{ - _SetEPType(bEpNum, wType); -} - -/******************************************************************************* -* Function Name : GetEPType -* Description : Returns the endpoint type. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Type -*******************************************************************************/ -uint16_t GetEPType(uint8_t bEpNum) -{ - return(_GetEPType(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxStatus -* Description : Set the status of Tx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxStatus(uint8_t bEpNum, uint16_t wState) -{ - _SetEPTxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : SetEPRxStatus -* Description : Set the status of Rx endpoint. -* Input : bEpNum: Endpoint Number. -* wState: new state. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxStatus(uint8_t bEpNum, uint16_t wState) -{ - _SetEPRxStatus(bEpNum, wState); -} - -/******************************************************************************* -* Function Name : SetDouBleBuffEPStall -* Description : sets the status for Double Buffer Endpoint to STALL -* Input : bEpNum: Endpoint Number. -* bDir: Endpoint direction. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetDouBleBuffEPStall(uint8_t bEpNum, uint8_t bDir) -{ - uint16_t Endpoint_DTOG_Status; - Endpoint_DTOG_Status = GetENDPOINT(bEpNum); - if (bDir == EP_DBUF_OUT) - { /* OUT double buffered endpoint */ - _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1); - } - else if (bDir == EP_DBUF_IN) - { /* IN double buffered endpoint */ - _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1); - } -} - -/******************************************************************************* -* Function Name : GetEPTxStatus -* Description : Returns the endpoint Tx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint TX Status -*******************************************************************************/ -uint16_t GetEPTxStatus(uint8_t bEpNum) -{ - return(_GetEPTxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : GetEPRxStatus -* Description : Returns the endpoint Rx status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint RX Status -*******************************************************************************/ -uint16_t GetEPRxStatus(uint8_t bEpNum) -{ - return(_GetEPRxStatus(bEpNum)); -} - -/******************************************************************************* -* Function Name : SetEPTxValid -* Description : Valid the endpoint Tx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxValid(uint8_t bEpNum) -{ - _SetEPTxStatus(bEpNum, EP_TX_VALID); -} - -/******************************************************************************* -* Function Name : SetEPRxValid -* Description : Valid the endpoint Rx Status. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxValid(uint8_t bEpNum) -{ - _SetEPRxStatus(bEpNum, EP_RX_VALID); -} - -/******************************************************************************* -* Function Name : SetEP_KIND -* Description : Clear the EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEP_KIND(uint8_t bEpNum) -{ - _SetEP_KIND(bEpNum); -} - -/******************************************************************************* -* Function Name : ClearEP_KIND -* Description : set the EP_KIND bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_KIND(uint8_t bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : Clear_Status_Out -* Description : Clear the Status Out of the related Endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void Clear_Status_Out(uint8_t bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : Set_Status_Out -* Description : Set the Status Out of the related Endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void Set_Status_Out(uint8_t bEpNum) -{ - _SetEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : SetEPDoubleBuff -* Description : Enable the double buffer feature for the endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDoubleBuff(uint8_t bEpNum) -{ - _SetEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : ClearEPDoubleBuff -* Description : Disable the double buffer feature for the endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEPDoubleBuff(uint8_t bEpNum) -{ - _ClearEP_KIND(bEpNum); -} -/******************************************************************************* -* Function Name : GetTxStallStatus -* Description : Returns the Stall status of the Tx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Tx Stall status. -*******************************************************************************/ -uint16_t GetTxStallStatus(uint8_t bEpNum) -{ - return(_GetTxStallStatus(bEpNum)); -} -/******************************************************************************* -* Function Name : GetRxStallStatus -* Description : Returns the Stall status of the Rx endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx Stall status. -*******************************************************************************/ -uint16_t GetRxStallStatus(uint8_t bEpNum) -{ - return(_GetRxStallStatus(bEpNum)); -} -/******************************************************************************* -* Function Name : ClearEP_CTR_RX -* Description : Clear the CTR_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_CTR_RX(uint8_t bEpNum) -{ - _ClearEP_CTR_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearEP_CTR_TX -* Description : Clear the CTR_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearEP_CTR_TX(uint8_t bEpNum) -{ - _ClearEP_CTR_TX(bEpNum); -} -/******************************************************************************* -* Function Name : ToggleDTOG_RX -* Description : Toggle the DTOG_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ToggleDTOG_RX(uint8_t bEpNum) -{ - _ToggleDTOG_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ToggleDTOG_TX -* Description : Toggle the DTOG_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ToggleDTOG_TX(uint8_t bEpNum) -{ - _ToggleDTOG_TX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearDTOG_RX. -* Description : Clear the DTOG_RX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearDTOG_RX(uint8_t bEpNum) -{ - _ClearDTOG_RX(bEpNum); -} -/******************************************************************************* -* Function Name : ClearDTOG_TX. -* Description : Clear the DTOG_TX bit. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -void ClearDTOG_TX(uint8_t bEpNum) -{ - _ClearDTOG_TX(bEpNum); -} -/******************************************************************************* -* Function Name : SetEPAddress -* Description : Set the endpoint address. -* Input : bEpNum: Endpoint Number. -* bAddr: New endpoint address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPAddress(uint8_t bEpNum, uint8_t bAddr) -{ - _SetEPAddress(bEpNum, bAddr); -} -/******************************************************************************* -* Function Name : GetEPAddress -* Description : Get the endpoint address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint address. -*******************************************************************************/ -uint8_t GetEPAddress(uint8_t bEpNum) -{ - return(_GetEPAddress(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPTxAddr -* Description : Set the endpoint Tx buffer address. -* Input : bEpNum: Endpoint Number. -* wAddr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxAddr(uint8_t bEpNum, uint16_t wAddr) -{ - _SetEPTxAddr(bEpNum, wAddr); -} -/******************************************************************************* -* Function Name : SetEPRxAddr -* Description : Set the endpoint Rx buffer address. -* Input : bEpNum: Endpoint Number. -* wAddr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxAddr(uint8_t bEpNum, uint16_t wAddr) -{ - _SetEPRxAddr(bEpNum, wAddr); -} -/******************************************************************************* -* Function Name : GetEPTxAddr -* Description : Returns the endpoint Tx buffer address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx buffer address. -*******************************************************************************/ -uint16_t GetEPTxAddr(uint8_t bEpNum) -{ - return(_GetEPTxAddr(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPRxAddr. -* Description : Returns the endpoint Rx buffer address. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx buffer address. -*******************************************************************************/ -uint16_t GetEPRxAddr(uint8_t bEpNum) -{ - return(_GetEPRxAddr(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPTxCount. -* Description : Set the Tx count. -* Input : bEpNum: Endpoint Number. -* wCount: new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPTxCount(uint8_t bEpNum, uint16_t wCount) -{ - _SetEPTxCount(bEpNum, wCount); -} -/******************************************************************************* -* Function Name : SetEPCountRxReg. -* Description : Set the Count Rx Register value. -* Input : *pdwReg: point to the register. -* wCount: the new register value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPCountRxReg(uint32_t *pdwReg, uint16_t wCount) -{ - _SetEPCountRxReg(dwReg, wCount); -} -/******************************************************************************* -* Function Name : SetEPRxCount -* Description : Set the Rx count. -* Input : bEpNum: Endpoint Number. -* wCount: the new count value. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPRxCount(uint8_t bEpNum, uint16_t wCount) -{ - _SetEPRxCount(bEpNum, wCount); -} -/******************************************************************************* -* Function Name : GetEPTxCount -* Description : Get the Tx count. -* Input : bEpNum: Endpoint Number. -* Output : None -* Return : Tx count value. -*******************************************************************************/ -uint16_t GetEPTxCount(uint8_t bEpNum) -{ - return(_GetEPTxCount(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPRxCount -* Description : Get the Rx count. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Rx count value. -*******************************************************************************/ -uint16_t GetEPRxCount(uint8_t bEpNum) -{ - return(_GetEPRxCount(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPDblBuffAddr -* Description : Set the addresses of the buffer 0 and 1. -* Input : bEpNum: Endpoint Number. -* wBuf0Addr: new address of buffer 0. -* wBuf1Addr: new address of buffer 1. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuffAddr(uint8_t bEpNum, uint16_t wBuf0Addr, uint16_t wBuf1Addr) -{ - _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); -} -/******************************************************************************* -* Function Name : SetEPDblBuf0Addr -* Description : Set the Buffer 1 address. -* Input : bEpNum: Endpoint Number -* wBuf0Addr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf0Addr(uint8_t bEpNum, uint16_t wBuf0Addr) -{ - _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); -} -/******************************************************************************* -* Function Name : SetEPDblBuf1Addr -* Description : Set the Buffer 1 address. -* Input : bEpNum: Endpoint Number -* wBuf1Addr: new address. -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf1Addr(uint8_t bEpNum, uint16_t wBuf1Addr) -{ - _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); -} -/******************************************************************************* -* Function Name : GetEPDblBuf0Addr -* Description : Returns the address of the Buffer 0. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : None. -*******************************************************************************/ -uint16_t GetEPDblBuf0Addr(uint8_t bEpNum) -{ - return(_GetEPDblBuf0Addr(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBuf1Addr -* Description : Returns the address of the Buffer 1. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Address of the Buffer 1. -*******************************************************************************/ -uint16_t GetEPDblBuf1Addr(uint8_t bEpNum) -{ - return(_GetEPDblBuf1Addr(bEpNum)); -} -/******************************************************************************* -* Function Name : SetEPDblBuffCount -* Description : Set the number of bytes for a double Buffer -* endpoint. -* Input : bEpNum,bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuffCount(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) -{ - _SetEPDblBuffCount(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : SetEPDblBuf0Count -* Description : Set the number of bytes in the buffer 0 of a double Buffer -* endpoint. -* Input : bEpNum, bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf0Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) -{ - _SetEPDblBuf0Count(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : SetEPDblBuf1Count -* Description : Set the number of bytes in the buffer 0 of a double Buffer -* endpoint. -* Input : bEpNum, bDir, wCount -* Output : None. -* Return : None. -*******************************************************************************/ -void SetEPDblBuf1Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) -{ - _SetEPDblBuf1Count(bEpNum, bDir, wCount); -} -/******************************************************************************* -* Function Name : GetEPDblBuf0Count -* Description : Returns the number of byte received in the buffer 0 of a double -* Buffer endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Buffer 0 count -*******************************************************************************/ -uint16_t GetEPDblBuf0Count(uint8_t bEpNum) -{ - return(_GetEPDblBuf0Count(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBuf1Count -* Description : Returns the number of data received in the buffer 1 of a double -* Buffer endpoint. -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : Endpoint Buffer 1 count. -*******************************************************************************/ -uint16_t GetEPDblBuf1Count(uint8_t bEpNum) -{ - return(_GetEPDblBuf1Count(bEpNum)); -} -/******************************************************************************* -* Function Name : GetEPDblBufDir -* Description : gets direction of the double buffered endpoint -* Input : bEpNum: Endpoint Number. -* Output : None. -* Return : EP_DBUF_OUT, EP_DBUF_IN, -* EP_DBUF_ERR if the endpoint counter not yet programmed. -*******************************************************************************/ -EP_DBUF_DIR GetEPDblBufDir(uint8_t bEpNum) -{ - if ((uint16_t)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) - return(EP_DBUF_OUT); - else if (((uint16_t)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) - return(EP_DBUF_IN); - else - return(EP_DBUF_ERR); -} -/******************************************************************************* -* Function Name : FreeUserBuffer -* Description : free buffer used from the application realizing it to the line - toggles bit SW_BUF in the double buffered endpoint register -* Input : bEpNum, bDir -* Output : None. -* Return : None. -*******************************************************************************/ -void FreeUserBuffer(uint8_t bEpNum, uint8_t bDir) -{ - if (bDir == EP_DBUF_OUT) - { /* OUT double buffered endpoint */ - _ToggleDTOG_TX(bEpNum); - } - else if (bDir == EP_DBUF_IN) - { /* IN double buffered endpoint */ - _ToggleDTOG_RX(bEpNum); - } -} - -/******************************************************************************* -* Function Name : ToWord -* Description : merge two byte in a word. -* Input : bh: byte high, bl: bytes low. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -uint16_t ToWord(uint8_t bh, uint8_t bl) -{ - uint16_t wRet; - wRet = (uint16_t)bl | ((uint16_t)bh << 8); - return(wRet); -} -/******************************************************************************* -* Function Name : ByteSwap -* Description : Swap two byte in a word. -* Input : wSwW: word to Swap. -* Output : None. -* Return : resulted word. -*******************************************************************************/ -uint16_t ByteSwap(uint16_t wSwW) -{ - uint8_t bTemp; - uint16_t wRet; - bTemp = (uint8_t)(wSwW & 0xff); - wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8); - return(wRet); -} - -#endif /* STM32F10X_CL */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/STM32_USB-FS-Device_Driver/src/usb_sil.c b/STM32_USB-FS-Device_Driver/src/usb_sil.c deleted file mode 100644 index 1c290da..0000000 --- a/STM32_USB-FS-Device_Driver/src/usb_sil.c +++ /dev/null @@ -1,126 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_sil.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Simplified Interface Layer for Global Initialization and -* Endpoint Rea/Write operations. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : USB_SIL_Init -* Description : Initialize the USB Device IP and the Endpoint 0. -* Input : None. -* Output : None. -* Return : Status. -*******************************************************************************/ -uint32_t USB_SIL_Init(void) -{ -#ifndef STM32F10X_CL - - /* USB interrupts initialization */ - /* clear pending interrupts */ - _SetISTR(0); - wInterrupt_Mask = IMR_MSK; - /* set interrupts mask */ - _SetCNTR(wInterrupt_Mask); - -#else - - /* Perform OTG Device initialization procedure (including EP0 init) */ - OTG_DEV_Init(); - -#endif /* STM32F10X_CL */ - - return 0; -} - -/******************************************************************************* -* Function Name : USB_SIL_Write -* Description : Write a buffer of data to a selected endpoint. -* Input : - bEpAddr: The address of the non control endpoint. -* - pBufferPointer: The pointer to the buffer of data to be written -* to the endpoint. -* - wBufferSize: Number of data to be written (in bytes). -* Output : None. -* Return : Status. -*******************************************************************************/ -uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize) -{ -#ifndef STM32F10X_CL - - /* Use the memory interface function to write to the selected endpoint */ - UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize); - - /* Update the data length in the control register */ - SetEPTxCount((bEpAddr & 0x7F), wBufferSize); - -#else - - /* Use the PCD interface layer function to write to the selected endpoint */ - OTGD_FS_PCD_EP_Write (bEpAddr, pBufferPointer, wBufferSize); - -#endif /* STM32F10X_CL */ - - return 0; -} - -/******************************************************************************* -* Function Name : USB_SIL_Read -* Description : Write a buffer of data to a selected endpoint. -* Input : - bEpAddr: The address of the non control endpoint. -* - pBufferPointer: The pointer to which will be saved the -* received data buffer. -* Output : None. -* Return : Number of received data (in Bytes). -*******************************************************************************/ -uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer) -{ - uint32_t DataLength = 0; - -#ifndef STM32F10X_CL - - /* Get the number of received data on the selected Endpoint */ - DataLength = GetEPRxCount(bEpAddr & 0x7F); - - /* Use the memory interface function to write to the selected endpoint */ - PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength); - -#else - - USB_OTG_EP *ep; - - /* Get the structure pointer of the selected Endpoint */ - ep = OTGD_FS_PCD_GetOutEP(bEpAddr); - - /* Get the number of received data */ - DataLength = ep->xfer_len; - - /* Use the PCD interface layer function to read the selected endpoint */ - OTGD_FS_PCD_EP_Read (bEpAddr, pBufferPointer, DataLength); - -#endif /* STM32F10X_CL */ - - /* Return the number of received data */ - return DataLength; -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/hw_config.c b/Virtual_COM_Port/hw_config.c deleted file mode 100644 index 3f822c0..0000000 --- a/Virtual_COM_Port/hw_config.c +++ /dev/null @@ -1,113 +0,0 @@ -/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** -* File Name : hw_config.c -* Author : MCD Application Team -* Version : V3.0.1 -* Date : 04/27/2009 -* Description : Hardware Configuration & Setup -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -#include "usb_prop.h" -#include "usb_desc.h" -#include "hw_config.h" -#include "platform_config.h" -#include "usb_pwr.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : Enter_LowPowerMode -* Description : Power-off system clocks and power while entering suspend mode -* Input : None. -* Return : None. -*******************************************************************************/ -void Enter_LowPowerMode(void) -{ - /* Set the device state to suspend */ - bDeviceState = SUSPENDED; -} - -/******************************************************************************* -* Function Name : Leave_LowPowerMode -* Description : Restores system clocks and power while exiting suspend mode -* Input : None. -* Return : None. -*******************************************************************************/ -void Leave_LowPowerMode(void) -{ - DEVICE_INFO *pInfo = &Device_Info; - - /* Set the device state to the correct state */ - if (pInfo->Current_Configuration != 0) { - /* Device configured */ - bDeviceState = CONFIGURED; - } else { - bDeviceState = ATTACHED; - } -} - -/******************************************************************************* -* Function Name : USB_Cable_Config -* Description : Software Connection/Disconnection of USB Cable -* Input : None. -* Return : Status -*******************************************************************************/ -void USB_Cable_Config (FunctionalState NewState) -{ - if (NewState != DISABLE) { - GPIO_ResetBits(GPIOC, GPIO_Pin_11); - } else { - GPIO_SetBits(GPIOC, GPIO_Pin_11); - } -} - -/******************************************************************************* -* Function Name : Get_SerialNum. -* Description : Create the serial number string descriptor. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Get_SerialNum(void) -{ - uint32_t Device_Serial0, Device_Serial1, Device_Serial2; -/* - Device_Serial0 = *(__IO uint32_t*)(0x1FFFF7E8); - Device_Serial1 = *(__IO uint32_t*)(0x1FFFF7EC); - Device_Serial2 = *(__IO uint32_t*)(0x1FFFF7F0); - - if (Device_Serial0 != 0) - { - Virtual_Com_Port_StringSerial[2] = (uint8_t)(Device_Serial0 & 0x000000FF); - Virtual_Com_Port_StringSerial[4] = (uint8_t)((Device_Serial0 & 0x0000FF00) >> 8); - Virtual_Com_Port_StringSerial[6] = (uint8_t)((Device_Serial0 & 0x00FF0000) >> 16); - Virtual_Com_Port_StringSerial[8] = (uint8_t)((Device_Serial0 & 0xFF000000) >> 24); - - Virtual_Com_Port_StringSerial[10] = (uint8_t)(Device_Serial1 & 0x000000FF); - Virtual_Com_Port_StringSerial[12] = (uint8_t)((Device_Serial1 & 0x0000FF00) >> 8); - Virtual_Com_Port_StringSerial[14] = (uint8_t)((Device_Serial1 & 0x00FF0000) >> 16); - Virtual_Com_Port_StringSerial[16] = (uint8_t)((Device_Serial1 & 0xFF000000) >> 24); - - Virtual_Com_Port_StringSerial[18] = (uint8_t)(Device_Serial2 & 0x000000FF); - Virtual_Com_Port_StringSerial[20] = (uint8_t)((Device_Serial2 & 0x0000FF00) >> 8); - Virtual_Com_Port_StringSerial[22] = (uint8_t)((Device_Serial2 & 0x00FF0000) >> 16); - Virtual_Com_Port_StringSerial[24] = (uint8_t)((Device_Serial2 & 0xFF000000) >> 24); - }*/ -} - -/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/hw_config.h b/Virtual_COM_Port/hw_config.h deleted file mode 100644 index e646777..0000000 --- a/Virtual_COM_Port/hw_config.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** -* File Name : hw_config.h -* Author : MCD Application Team -* Version : V3.0.1 -* Date : 04/27/2009 -* Description : Hardware Configuration & Setup -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __HW_CONFIG_H -#define __HW_CONFIG_H - -/* Includes ------------------------------------------------------------------*/ -#include "usb_type.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported define -----------------------------------------------------------*/ -#define MASS_MEMORY_START 0x04002000 -#define BULK_MAX_PACKET_SIZE 0x00000040 -#define LED_ON 0xF0 -#define LED_OFF 0xFF - -/* Exported functions ------------------------------------------------------- */ -void Enter_LowPowerMode(void); -void Leave_LowPowerMode(void); -void USB_Cable_Config (FunctionalState NewState); -void Get_SerialNum(void); - -/* External variables --------------------------------------------------------*/ - -#endif /*__HW_CONFIG_H*/ -/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/platform.h b/Virtual_COM_Port/platform.h deleted file mode 100644 index b7cd226..0000000 --- a/Virtual_COM_Port/platform.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef PLATFORM_H_ -#define PLATFORM_H_ - -#define LED_PIN GPIO_Pin_12 -#define LED_GPIO GPIOC - -#define LCD_E_PIN GPIO_Pin_10 -#define LCD_E_GPIO GPIOC - -#define LCD_RESET_PIN GPIO_Pin_7 -#define LCD_RESET_GPIO GPIOC - -#define LCD_DC_PIN GPIO_Pin_2 -#define LCD_DC_GPIO GPIOB - -#define TAMP_PIN GPIO_Pin_13 -#define TAMP_GPIO GPIOC - -#define WAKE_PIN GPIO_Pin_0 -#define WAKE_GPIO GPIOA - -#define JOY_CENTER_PIN GPIO_Pin_6 -#define JOY_CENTER_GPIO GPIOC - -#define NRF_CS_PIN GPIO_Pin_4 -#define NRF_CS_GPIO GPIOA - -#define NRF_CE_PIN GPIO_Pin_8 -#define NRF_CE_GPIO GPIOC - -#define NRF_IRQ_PIN GPIO_Pin_9 -#define NRF_IRQ_GPIO GPIOC - -#define ADIS_CS_PIN GPIO_Pin_10 -#define ADIS_CS_GPIO GPIOB - -#define ADIS_RESET_PIN GPIO_Pin_3 -#define ADIS_RESET_GPIO GPIOA - -#define LED_WRITE(x) GPIO_WriteBit(LED_GPIO, LED_PIN, x) - -#define LCD_DC_WRITE(x) GPIO_WriteBit(LCD_DC_GPIO, LCD_DC_PIN, x) -#define LCD_E_WRITE(x) GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, x) -#define LCD_RESET_WRITE(x) GPIO_WriteBit(LCD_RESET_GPIO, LCD_RESET_PIN, x) - -#define TAMP_READ GPIO_ReadInputDataBit(TAMP_GPIO, TAMP_PIN) -#define WAKE_READ GPIO_ReadInputDataBit(WAKE_GPIO, WAKE_PIN) -#define JOY_CENTER_READ GPIO_ReadInputDataBit(JOY_CENTER_GPIO, JOY_CENTER_PIN) - -#define NRF_CE_WRITE(x) GPIO_WriteBit(NRF_CE_GPIO, NRF_CE_PIN, x) -#define NRF_CS_WRITE(x) GPIO_WriteBit(NRF_CS_GPIO, NRF_CS_PIN, x) -#define NRF_IRQ_READ GPIO_ReadInputDataBit(MRF_IRQ_GPIO, NRF_IRQ_PIN) - -#define ADIS_CS_WRITE(x) GPIO_WriteBit(ADIS_CS_GPIO, ADIS_CS_PIN, x) -#define ADIS_RESET_WRITE(x) GPIO_WriteBit(ADIS_RESET_GPIO, ADIS_RESET_PIN, x) -#endif - diff --git a/Virtual_COM_Port/platform_config.h b/Virtual_COM_Port/platform_config.h deleted file mode 100644 index f1fd83f..0000000 --- a/Virtual_COM_Port/platform_config.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** -* File Name : platform_config.h -* Author : MCD Application Team -* Version : V3.0.1 -* Date : 04/27/2009 -* Description : Evaluation board specific configuration file. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __PLATFORM_CONFIG_H -#define __PLATFORM_CONFIG_H - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f10x.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Uncomment the line corresponding to the STMicroelectronics evaluation board - used to run the example */ -#if !defined (USE_STM3210B_EVAL) && !defined (USE_STM3210E_EVAL) - //#define USE_STM3210B_EVAL - #define USE_STM3210E_EVAL -#endif - -/* Define the STM32F10x hardware depending on the used evaluation board */ -#ifdef USE_STM3210B_EVAL - - #define USB_DISCONNECT GPIOD - #define USB_DISCONNECT_PIN GPIO_Pin_9 - #define RCC_APB2Periph_GPIO_DISCONNECT RCC_APB2Periph_GPIOD - -#else /* USE_STM3210E_EVAL */ - - #define USB_DISCONNECT GPIOB - #define USB_DISCONNECT_PIN GPIO_Pin_14 - #define RCC_APB2Periph_GPIO_DISCONNECT RCC_APB2Periph_GPIOB - -#endif /* USE_STM3210B_EVAL */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#endif /* __PLATFORM_CONFIG_H */ - -/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_conf.h b/Virtual_COM_Port/usb_conf.h deleted file mode 100644 index ecbe241..0000000 --- a/Virtual_COM_Port/usb_conf.h +++ /dev/null @@ -1,197 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_conf.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Virtual COM Port Demo configuration header -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_CONF_H -#define __USB_CONF_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -/* External variables --------------------------------------------------------*/ - -/*-------------------------------------------------------------*/ -/* EP_NUM */ -/* defines how many endpoints are used by the device */ -/*-------------------------------------------------------------*/ - -#define EP_NUM (4) - - -#ifndef STM32F10X_CL -/*-------------------------------------------------------------*/ -/* -------------- Buffer Description Table -----------------*/ -/*-------------------------------------------------------------*/ -/* buffer table base address */ -/* buffer table base address */ -#define BTABLE_ADDRESS (0x00) - -/* EP0 */ -/* rx/tx buffer base address */ -#define ENDP0_RXADDR (0x40) -#define ENDP0_TXADDR (0x80) - -/* EP1 */ -/* tx buffer base address */ -#define ENDP1_TXADDR (0xC0) -#define ENDP2_TXADDR (0x100) -#define ENDP3_RXADDR (0x110) - - -/*-------------------------------------------------------------*/ -/* ------------------- ISTR events -------------------------*/ -/*-------------------------------------------------------------*/ -/* IMR_MSK */ -/* mask defining which events has to be handled */ -/* by the device application software */ -#define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM ) - -/*#define CTR_CALLBACK*/ -/*#define DOVR_CALLBACK*/ -/*#define ERR_CALLBACK*/ -/*#define WKUP_CALLBACK*/ -/*#define SUSP_CALLBACK*/ -/*#define RESET_CALLBACK*/ -/*#define SOF_CALLBACK*/ -/*#define ESOF_CALLBACK*/ -#endif /* STM32F10X_CL */ - -#ifdef STM32F10X_CL -/******************************************************************************* -* FIFO Size Configuration -* -* (i) Dedicated data FIFO SPRAM of 1.25 Kbytes = 1280 bytes = 320 32-bits words -* available for the endpoints IN and OUT. -* Device mode features: -* -1 bidirectional CTRL EP 0 -* -3 IN EPs to support any kind of Bulk, Interrupt or Isochronous transfer -* -3 OUT EPs to support any kind of Bulk, Interrupt or Isochronous transfer -* -* ii) Receive data FIFO size = RAM for setup packets + -* OUT endpoint control information + -* data OUT packets + miscellaneous -* Space = ONE 32-bits words -* --> RAM for setup packets = 4 * n + 6 space -* (n is the nbr of CTRL EPs the device core supports) -* --> OUT EP CTRL info = 1 space -* (one space for status information written to the FIFO along with each -* received packet) -* --> data OUT packets = (Largest Packet Size / 4) + 1 spaces -* (MINIMUM to receive packets) -* --> OR data OUT packets = at least 2*(Largest Packet Size / 4) + 1 spaces -* (if high-bandwidth EP is enabled or multiple isochronous EPs) -* --> miscellaneous = 1 space per OUT EP -* (one space for transfer complete status information also pushed to the -* FIFO with each endpoint's last packet) -* -* (iii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for -* that particular IN EP. More space allocated in the IN EP Tx FIFO results -* in a better performance on the USB and can hide latencies on the AHB. -* -* (iv) TXn min size = 16 words. (n : Transmit FIFO index) -* (v) When a TxFIFO is not used, the Configuration should be as follows: -* case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) -* --> Txm can use the space allocated for Txn. -* case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) -* --> Txn should be configured with the minimum space of 16 words -* (vi) The FIFO is used optimally when used TxFIFOs are allocated in the top -* of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. -*******************************************************************************/ - -#define RX_FIFO_SIZE 128 -#define TX0_FIFO_SIZE 64 -#define TX1_FIFO_SIZE 64 -#define TX2_FIFO_SIZE 16 -#define TX3_FIFO_SIZE 16 - -/* OTGD-FS-DEVICE IP interrupts Enable definitions */ -/* Uncomment the define to enable the selected interrupt */ -//#define INTR_MODEMISMATCH -#define INTR_SOFINTR -#define INTR_RXSTSQLVL /* Mandatory */ -//#define INTR_NPTXFEMPTY -//#define INTR_GINNAKEFF -//#define INTR_GOUTNAKEFF -//#define INTR_ERLYSUSPEND -#define INTR_USBSUSPEND /* Mandatory */ -#define INTR_USBRESET /* Mandatory */ -#define INTR_ENUMDONE /* Mandatory */ -//#define INTR_ISOOUTDROP -//#define INTR_EOPFRAME -//#define INTR_EPMISMATCH -#define INTR_INEPINTR /* Mandatory */ -#define INTR_OUTEPINTR /* Mandatory */ -//#define INTR_INCOMPLISOIN -//#define INTR_INCOMPLISOOUT -#define INTR_WKUPINTR /* Mandatory */ - -/* OTGD-FS-DEVICE IP interrupts subroutines */ -/* Comment the define to enable the selected interrupt subroutine and replace it - by user code */ -#define INTR_MODEMISMATCH_Callback NOP_Process -#define INTR_SOFINTR_Callback NOP_Process -#define INTR_RXSTSQLVL_Callback NOP_Process -#define INTR_NPTXFEMPTY_Callback NOP_Process -#define INTR_NPTXFEMPTY_Callback NOP_Process -#define INTR_GINNAKEFF_Callback NOP_Process -#define INTR_GOUTNAKEFF_Callback NOP_Process -#define INTR_ERLYSUSPEND_Callback NOP_Process -#define INTR_USBSUSPEND_Callback NOP_Process -#define INTR_USBRESET_Callback NOP_Process -#define INTR_ENUMDONE_Callback NOP_Process -#define INTR_ISOOUTDROP_Callback NOP_Process -#define INTR_EOPFRAME_Callback NOP_Process -#define INTR_EPMISMATCH_Callback NOP_Process -#define INTR_INEPINTR_Callback NOP_Process -#define INTR_OUTEPINTR_Callback NOP_Process -#define INTR_INCOMPLISOIN_Callback NOP_Process -#define INTR_INCOMPLISOOUT_Callback NOP_Process -#define INTR_WKUPINTR_Callback NOP_Process - -/* Isochronous data update */ -#define INTR_RXSTSQLVL_ISODU_Callback NOP_Process - -/* Isochronous transfer parameters */ -/* Size of a single Isochronous buffer (size of a single transfer) */ -#define ISOC_BUFFER_SZE 1 -/* Number of sub-buffers (number of single buffers/transfers), should be even */ -#define NUM_SUB_BUFFERS 2 - -#endif /* STM32F10X_CL */ - - -/* CTR service routines */ -/* associated to defined endpoints */ -/*#define EP1_IN_Callback NOP_Process -#define EP2_IN_Callback NOP_Process -#define EP3_IN_Callback NOP_Process -#define EP4_IN_Callback NOP_Process -#define EP5_IN_Callback NOP_Process -#define EP6_IN_Callback NOP_Process -#define EP7_IN_Callback NOP_Process - -#define EP1_OUT_Callback NOP_Process -#define EP2_OUT_Callback NOP_Process -#define EP3_OUT_Callback NOP_Process -#define EP4_OUT_Callback NOP_Process -#define EP5_OUT_Callback NOP_Process -#define EP6_OUT_Callback NOP_Process -#define EP7_OUT_Callback NOP_Process*/ - -#endif /* __USB_CONF_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_desc.c b/Virtual_COM_Port/usb_desc.c deleted file mode 100644 index 80f5d52..0000000 --- a/Virtual_COM_Port/usb_desc.c +++ /dev/null @@ -1,161 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_desc.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Descriptors for Virtual Com Port Demo -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -#include "usb_desc.h" - -/* USB Standard Device Descriptor */ -const uint8_t Virtual_Com_Port_DeviceDescriptor[] = - { - 0x12, /* bLength */ - USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ - 0x00, - 0x02, /* bcdUSB = 2.00 */ - 0x02, /* bDeviceClass: CDC */ - 0x00, /* bDeviceSubClass */ - 0x00, /* bDeviceProtocol */ - 0x40, /* bMaxPacketSize0 */ - 0x83, - 0x04, /* idVendor = 0x0483 */ - 0x40, - 0x57, /* idProduct = 0x7540 */ - 0x00, - 0x02, /* bcdDevice = 2.00 */ - 1, /* Index of string descriptor describing manufacturer */ - 2, /* Index of string descriptor describing product */ - 3, /* Index of string descriptor describing the device's serial number */ - 0x01 /* bNumConfigurations */ - }; - -const uint8_t Virtual_Com_Port_ConfigDescriptor[] = - { - /*Configuation Descriptor*/ - 0x09, /* bLength: Configuation Descriptor size */ - USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ - VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, /* wTotalLength:no of returned bytes */ - 0x00, - 0x02, /* bNumInterfaces: 2 interface */ - 0x01, /* bConfigurationValue: Configuration value */ - 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ - 0xC0, /* bmAttributes: self powered */ - 0x32, /* MaxPower 0 mA */ - /*Interface Descriptor*/ - 0x09, /* bLength: Interface Descriptor size */ - USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ - /* Interface descriptor type */ - 0x00, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x01, /* bNumEndpoints: One endpoints used */ - 0x02, /* bInterfaceClass: Communication Interface Class */ - 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x01, /* bInterfaceProtocol: Common AT commands */ - 0x00, /* iInterface: */ - /*Header Functional Descriptor*/ - 0x05, /* bLength: Endpoint Descriptor size */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x00, /* bDescriptorSubtype: Header Func Desc */ - 0x10, /* bcdCDC: spec release number */ - 0x01, - /*Call Managment Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x01, /* bDescriptorSubtype: Call Management Func Desc */ - 0x00, /* bmCapabilities: D0+D1 */ - 0x01, /* bDataInterface: 1 */ - /*ACM Functional Descriptor*/ - 0x04, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ - 0x02, /* bmCapabilities */ - /*Union Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x06, /* bDescriptorSubtype: Union func desc */ - 0x00, /* bMasterInterface: Communication class interface */ - 0x01, /* bSlaveInterface0: Data Class Interface */ - /*Endpoint 2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ - 0x82, /* bEndpointAddress: (IN2) */ - 0x03, /* bmAttributes: Interrupt */ - VIRTUAL_COM_PORT_INT_SIZE, /* wMaxPacketSize: */ - 0x00, - 0xFF, /* bInterval: */ - /*Data class interface descriptor*/ - 0x09, /* bLength: Endpoint Descriptor size */ - USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */ - 0x01, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x02, /* bNumEndpoints: Two endpoints used */ - 0x0A, /* bInterfaceClass: CDC */ - 0x00, /* bInterfaceSubClass: */ - 0x00, /* bInterfaceProtocol: */ - 0x00, /* iInterface: */ - /*Endpoint 3 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ - 0x03, /* bEndpointAddress: (OUT3) */ - 0x02, /* bmAttributes: Bulk */ - VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */ - 0x00, - 0x00, /* bInterval: ignore for Bulk transfer */ - /*Endpoint 1 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ - 0x81, /* bEndpointAddress: (IN1) */ - 0x02, /* bmAttributes: Bulk */ - VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */ - 0x00, - 0x00 /* bInterval */ - }; - -/* USB String Descriptors */ -const uint8_t Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID] = - { - VIRTUAL_COM_PORT_SIZ_STRING_LANGID, - USB_STRING_DESCRIPTOR_TYPE, - 0x09, - 0x04 /* LangID = 0x0409: U.S. English */ - }; - -const uint8_t Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR] = - { - VIRTUAL_COM_PORT_SIZ_STRING_VENDOR, /* Size of Vendor string */ - USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/ - /* Manufacturer: "STMicroelectronics" */ - 'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0, - 'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0, - 'c', 0, 's', 0 - }; - -const uint8_t Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT] = - { - VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT, /* bLength */ - USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - /* Product name: "STM32 Virtual COM Port" */ - 'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, ' ', 0, 'V', 0, 'i', 0, - 'r', 0, 't', 0, 'u', 0, 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, - 'M', 0, ' ', 0, 'P', 0, 'o', 0, 'r', 0, 't', 0, ' ', 0, ' ', 0 - }; - -uint8_t Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL] = - { - VIRTUAL_COM_PORT_SIZ_STRING_SERIAL, /* bLength */ - USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - 'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, '1', 0, '0', 0 - }; - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_desc.h b/Virtual_COM_Port/usb_desc.h deleted file mode 100644 index bc3cc57..0000000 --- a/Virtual_COM_Port/usb_desc.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_desc.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Descriptor Header for Virtual COM Port Device -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_DESC_H -#define __USB_DESC_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported define -----------------------------------------------------------*/ -#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 -#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 -#define USB_STRING_DESCRIPTOR_TYPE 0x03 -#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 -#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 - -#define VIRTUAL_COM_PORT_DATA_SIZE 16 -#define VIRTUAL_COM_PORT_INT_SIZE 8 - -#define VIRTUAL_COM_PORT_SIZ_DEVICE_DESC 18 -#define VIRTUAL_COM_PORT_SIZ_CONFIG_DESC 67 -#define VIRTUAL_COM_PORT_SIZ_STRING_LANGID 4 -#define VIRTUAL_COM_PORT_SIZ_STRING_VENDOR 38 -#define VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT 50 -#define VIRTUAL_COM_PORT_SIZ_STRING_SERIAL 26 - -#define STANDARD_ENDPOINT_DESC_SIZE 0x09 - -/* Exported functions ------------------------------------------------------- */ -extern const uint8_t Virtual_Com_Port_DeviceDescriptor[VIRTUAL_COM_PORT_SIZ_DEVICE_DESC]; -extern const uint8_t Virtual_Com_Port_ConfigDescriptor[VIRTUAL_COM_PORT_SIZ_CONFIG_DESC]; - -extern const uint8_t Virtual_Com_Port_StringLangID[VIRTUAL_COM_PORT_SIZ_STRING_LANGID]; -extern const uint8_t Virtual_Com_Port_StringVendor[VIRTUAL_COM_PORT_SIZ_STRING_VENDOR]; -extern const uint8_t Virtual_Com_Port_StringProduct[VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT]; -extern uint8_t Virtual_Com_Port_StringSerial[VIRTUAL_COM_PORT_SIZ_STRING_SERIAL]; - -#endif /* __USB_DESC_H */ -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_endp.c b/Virtual_COM_Port/usb_endp.c deleted file mode 100644 index a633a24..0000000 --- a/Virtual_COM_Port/usb_endp.c +++ /dev/null @@ -1,67 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_endp.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Endpoint routines -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -#include "usb_desc.h" -#include "usb_mem.h" -#include "hw_config.h" -#include "usb_istr.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -uint8_t buffer_out[VIRTUAL_COM_PORT_DATA_SIZE]; -uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE]; - -__IO uint32_t count_out = 0; -uint32_t count_in = 0; - -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : EP1_IN_Callback -* Description : -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void EP3_IN_Callback(void) -{ - count_in = 0; -} - -/******************************************************************************* -* Function Name : EP3_IN_Callback -* Description : -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void EP5_OUT_Callback(void) -{ - /* Get the received data buffer and update the counter */ - count_out = USB_SIL_Read(EP5_OUT, buffer_out); - -#ifndef STM32F10X_CL - /* Enable the receive of data on EP3 */ - SetEPRxValid(ENDP3); -#endif /* STM32F10X_CL */ -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/Virtual_COM_Port/usb_istr.c b/Virtual_COM_Port/usb_istr.c deleted file mode 100644 index c07c964..0000000 --- a/Virtual_COM_Port/usb_istr.c +++ /dev/null @@ -1,419 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_istr.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : ISTR events interrupt service routines -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -#include "usb_prop.h" -#include "usb_pwr.h" -#include "usb_istr.h" - -/* function prototypes Automatically built defining related macros */ -void NOP_Proc(void) { -} - -#define WEAK __attribute__ ((weak)) -void WEAK EP1_IN_Callback(void); -void WEAK EP2_IN_Callback(void); -void WEAK EP3_IN_Callback(void); -void WEAK EP4_IN_Callback(void); -void WEAK EP5_IN_Callback(void); -void WEAK EP6_IN_Callback(void); -void WEAK EP7_IN_Callback(void); - -void WEAK EP1_OUT_Callback(void); -void WEAK EP2_OUT_Callback(void); -void WEAK EP3_OUT_Callback(void); -void WEAK EP4_OUT_Callback(void); -void WEAK EP5_OUT_Callback(void); -void WEAK EP6_OUT_Callback(void); -void WEAK EP7_OUT_Callback(void); - -#pragma weak EP1_IN_Callback = NOP_Proc -#pragma weak EP2_IN_Callback = NOP_Proc -#pragma weak EP3_IN_Callback = NOP_Proc -#pragma weak EP4_IN_Callback = NOP_Proc -#pragma weak EP5_IN_Callback = NOP_Proc -#pragma weak EP6_IN_Callback = NOP_Proc -#pragma weak EP7_IN_Callback = NOP_Proc - -#pragma weak EP1_OUT_Callback = NOP_Proc -#pragma weak EP2_OUT_Callback = NOP_Proc -#pragma weak EP3_OUT_Callback = NOP_Proc -#pragma weak EP4_OUT_Callback = NOP_Proc -#pragma weak EP5_OUT_Callback = NOP_Proc -#pragma weak EP6_OUT_Callback = NOP_Proc -#pragma weak EP7_OUT_Callback = NOP_Proc - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -__IO uint16_t wIstr; /* ISTR register last read value */ -__IO uint8_t bIntPackSOF = 0; /* SOFs received between 2 consecutive packets */ - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/* function pointers to non-control endpoints service routines */ -void (*const pEpInt_IN[7])(void) = - { - EP1_IN_Callback, - EP2_IN_Callback, - EP3_IN_Callback, - EP4_IN_Callback, - EP5_IN_Callback, - EP6_IN_Callback, - EP7_IN_Callback, - }; - -void (*const pEpInt_OUT[7])(void) = - { - EP1_OUT_Callback, - EP2_OUT_Callback, - EP3_OUT_Callback, - EP4_OUT_Callback, - EP5_OUT_Callback, - EP6_OUT_Callback, - EP7_OUT_Callback, - }; - -#ifndef STM32F10X_CL - -/******************************************************************************* -* Function Name : USB_Istr -* Description : STR events interrupt service routine -* Input : -* Output : -* Return : -*******************************************************************************/ -void USB_Istr(void) -{ - - wIstr = _GetISTR(); - -#if (IMR_MSK & ISTR_CTR) - if (wIstr & ISTR_CTR & wInterrupt_Mask) - { - /* servicing of the endpoint correct transfer interrupt */ - /* clear of the CTR flag into the sub */ - CTR_LP(); -#ifdef CTR_CALLBACK - CTR_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_RESET) - if (wIstr & ISTR_RESET & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_RESET); - Device_Property.Reset(); -#ifdef RESET_CALLBACK - RESET_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_DOVR) - if (wIstr & ISTR_DOVR & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_DOVR); -#ifdef DOVR_CALLBACK - DOVR_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_ERR) - if (wIstr & ISTR_ERR & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_ERR); -#ifdef ERR_CALLBACK - ERR_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_WKUP) - if (wIstr & ISTR_WKUP & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_WKUP); - Resume(RESUME_EXTERNAL); -#ifdef WKUP_CALLBACK - WKUP_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_SUSP) - if (wIstr & ISTR_SUSP & wInterrupt_Mask) - { - - /* check if SUSPEND is possible */ - if (fSuspendEnabled) - { - Suspend(); - } - else - { - /* if not possible then resume after xx ms */ - Resume(RESUME_LATER); - } - /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - _SetISTR((uint16_t)CLR_SUSP); -#ifdef SUSP_CALLBACK - SUSP_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_SOF) - if (wIstr & ISTR_SOF & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_SOF); - bIntPackSOF++; - -#ifdef SOF_CALLBACK - SOF_Callback(); -#endif - } -#endif - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#if (IMR_MSK & ISTR_ESOF) - if (wIstr & ISTR_ESOF & wInterrupt_Mask) - { - _SetISTR((uint16_t)CLR_ESOF); - /* resume handling timing is made with ESOFs */ - Resume(RESUME_ESOF); /* request without change of the machine state */ - -#ifdef ESOF_CALLBACK - ESOF_Callback(); -#endif - } -#endif -} /* USB_Istr */ - -/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ -#else /* STM32F10X_CL */ - - -/******************************************************************************* -* Function Name : STM32_PCD_OTG_ISR_Handler -* Description : Handles all USB Device Interrupts -* Input : None -* Output : None -* Return : status -*******************************************************************************/ -u32 STM32_PCD_OTG_ISR_Handler (void) -{ - USB_OTG_int_sts_data gintr_status; - u32 retval = 0; - - if (IsDeviceMode()) /* ensure that we are in device mode */ - { - gintr_status.d32 = OTGD_FS_ReadCoreItr(); - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - - /* If there is no interrupt pending exit the interrupt routine */ - if (!gintr_status.d32) - { - return 0; - } - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Early Suspend interrupt */ -#ifdef INTR_ERLYSUSPEND - if (gintr_status.b.erlysuspend) - { - retval |= OTGD_FS_Handle_EarlySuspend_ISR(); - } -#endif /* INTR_ERLYSUSPEND */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* End of Periodic Frame interrupt */ -#ifdef INTR_EOPFRAME - if (gintr_status.b.eopframe) - { - retval |= OTGD_FS_Handle_EOPF_ISR(); - } -#endif /* INTR_EOPFRAME */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Non Periodic Tx FIFO Emty interrupt */ -#ifdef INTR_NPTXFEMPTY - if (gintr_status.b.nptxfempty) - { - retval |= OTGD_FS_Handle_NPTxFE_ISR(); - } -#endif /* INTR_NPTXFEMPTY */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Wakeup or RemoteWakeup interrupt */ -#ifdef INTR_WKUPINTR - if (gintr_status.b.wkupintr) - { - retval |= OTGD_FS_Handle_Wakeup_ISR(); - } -#endif /* INTR_WKUPINTR */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Suspend interrupt */ -#ifdef INTR_USBSUSPEND - if (gintr_status.b.usbsuspend) - { - /* check if SUSPEND is possible */ - if (fSuspendEnabled) - { - Suspend(); - } - else - { - /* if not possible then resume after xx ms */ - Resume(RESUME_LATER); /* This case shouldn't happen in OTG Device mode because - there's no ESOF interrupt to increment the ResumeS.bESOFcnt in the Resume state machine */ - } - - retval |= OTGD_FS_Handle_USBSuspend_ISR(); - } -#endif /* INTR_USBSUSPEND */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Start of Frame interrupt */ -#ifdef INTR_SOFINTR - if (gintr_status.b.sofintr) - { - /* Update the frame number variable */ - bIntPackSOF++; - - retval |= OTGD_FS_Handle_Sof_ISR(); - } -#endif /* INTR_SOFINTR */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Receive FIFO Queue Status Level interrupt */ -#ifdef INTR_RXSTSQLVL - if (gintr_status.b.rxstsqlvl) - { - retval |= OTGD_FS_Handle_RxStatusQueueLevel_ISR(); - } -#endif /* INTR_RXSTSQLVL */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Enumeration Done interrupt */ -#ifdef INTR_ENUMDONE - if (gintr_status.b.enumdone) - { - retval |= OTGD_FS_Handle_EnumDone_ISR(); - } -#endif /* INTR_ENUMDONE */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Reset interrutp */ -#ifdef INTR_USBRESET - if (gintr_status.b.usbreset) - { - retval |= OTGD_FS_Handle_UsbReset_ISR(); - } -#endif /* INTR_USBRESET */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* IN Endpoint interrupt */ -#ifdef INTR_INEPINTR - if (gintr_status.b.inepint) - { - retval |= OTGD_FS_Handle_InEP_ISR(); - } -#endif /* INTR_INEPINTR */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* OUT Endpoint interrupt */ -#ifdef INTR_OUTEPINTR - if (gintr_status.b.outepintr) - { - retval |= OTGD_FS_Handle_OutEP_ISR(); - } -#endif /* INTR_OUTEPINTR */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Mode Mismatch interrupt */ -#ifdef INTR_MODEMISMATCH - if (gintr_status.b.modemismatch) - { - retval |= OTGD_FS_Handle_ModeMismatch_ISR(); - } -#endif /* INTR_MODEMISMATCH */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Global IN Endpoints NAK Effective interrupt */ -#ifdef INTR_GINNAKEFF - if (gintr_status.b.ginnakeff) - { - retval |= OTGD_FS_Handle_GInNakEff_ISR(); - } -#endif /* INTR_GINNAKEFF */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Global OUT Endpoints NAK effective interrupt */ -#ifdef INTR_GOUTNAKEFF - if (gintr_status.b.goutnakeff) - { - retval |= OTGD_FS_Handle_GOutNakEff_ISR(); - } -#endif /* INTR_GOUTNAKEFF */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Isochrounous Out packet Dropped interrupt */ -#ifdef INTR_ISOOUTDROP - if (gintr_status.b.isooutdrop) - { - retval |= OTGD_FS_Handle_IsoOutDrop_ISR(); - } -#endif /* INTR_ISOOUTDROP */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Endpoint Mismatch error interrupt */ -#ifdef INTR_EPMISMATCH - if (gintr_status.b.epmismatch) - { - retval |= OTGD_FS_Handle_EPMismatch_ISR(); - } -#endif /* INTR_EPMISMATCH */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Incomplete Isochrous IN tranfer error interrupt */ -#ifdef INTR_INCOMPLISOIN - if (gintr_status.b.incomplisoin) - { - retval |= OTGD_FS_Handle_IncomplIsoIn_ISR(); - } -#endif /* INTR_INCOMPLISOIN */ - - /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ - /* Incomplete Isochrous OUT tranfer error interrupt */ -#ifdef INTR_INCOMPLISOOUT - if (gintr_status.b.outepintr) - { - retval |= OTGD_FS_Handle_IncomplIsoOut_ISR(); - } -#endif /* INTR_INCOMPLISOOUT */ - - } - return retval; -} - -#endif /* STM32F10X_CL */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_istr.h b/Virtual_COM_Port/usb_istr.h deleted file mode 100644 index 77698f6..0000000 --- a/Virtual_COM_Port/usb_istr.h +++ /dev/null @@ -1,104 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_istr.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : This file includes the peripherals header files in the -* user application. -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_ISTR_H -#define __USB_ISTR_H - -/* Includes ------------------------------------------------------------------*/ -#include "usb_conf.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -#ifndef STM32F10X_CL - void USB_Istr(void); -#else /* STM32F10X_CL */ - u32 STM32_PCD_OTG_ISR_Handler(void); -#endif /* STM32F10X_CL */ - - -#ifndef STM32F10X_CL - -#ifdef CTR_CALLBACK -void CTR_Callback(void); -#endif - -#ifdef DOVR_CALLBACK -void DOVR_Callback(void); -#endif - -#ifdef ERR_CALLBACK -void ERR_Callback(void); -#endif - -#ifdef WKUP_CALLBACK -void WKUP_Callback(void); -#endif - -#ifdef SUSP_CALLBACK -void SUSP_Callback(void); -#endif - -#ifdef RESET_CALLBACK -void RESET_Callback(void); -#endif - -#ifdef SOF_CALLBACK -void SOF_Callback(void); -#endif - -#ifdef ESOF_CALLBACK -void ESOF_Callback(void); -#endif - -#else /* STM32F10X_CL */ - -/* Interrupt subroutines user callbacks prototypes. - These callbacks are called into the respective interrupt sunroutine functinos - and can be tailored for various user application purposes. - Note: Make sure that the correspondant interrupt is enabled through the - definition in usb_conf.h file */ -void INTR_MODEMISMATCH_Callback(void); -void INTR_SOFINTR_Callback(void); -void INTR_RXSTSQLVL_Callback(void); -void INTR_NPTXFEMPTY_Callback(void); -void INTR_GINNAKEFF_Callback(void); -void INTR_GOUTNAKEFF_Callback(void); -void INTR_ERLYSUSPEND_Callback(void); -void INTR_USBSUSPEND_Callback(void); -void INTR_USBRESET_Callback(void); -void INTR_ENUMDONE_Callback(void); -void INTR_ISOOUTDROP_Callback(void); -void INTR_EOPFRAME_Callback(void); -void INTR_EPMISMATCH_Callback(void); -void INTR_INEPINTR_Callback(void); -void INTR_OUTEPINTR_Callback(void); -void INTR_INCOMPLISOIN_Callback(void); -void INTR_INCOMPLISOOUT_Callback(void); -void INTR_WKUPINTR_Callback(void); - -/* Isochronous data update */ -void INTR_RXSTSQLVL_ISODU_Callback(void); - -#endif /* STM32F10X_CL */ - - -#endif /*__USB_ISTR_H*/ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_prop.c b/Virtual_COM_Port/usb_prop.c deleted file mode 100644 index 0f6d85b..0000000 --- a/Virtual_COM_Port/usb_prop.c +++ /dev/null @@ -1,419 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_prop.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : All processing related to Virtual Com Port Demo -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "usb_lib.h" -#include "usb_conf.h" -#include "usb_prop.h" -#include "usb_desc.h" -#include "usb_pwr.h" -#include "hw_config.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -uint8_t Request = 0; - -LINE_CODING linecoding = - { - 115200, /* baud rate*/ - 0x00, /* stop bits-1*/ - 0x00, /* parity - none*/ - 0x08 /* no. of bits 8*/ - }; - -/* -------------------------------------------------------------------------- */ -/* Structures initializations */ -/* -------------------------------------------------------------------------- */ - -DEVICE Device_Table = - { - EP_NUM, - 1 - }; - -DEVICE_PROP Device_Property = - { - Virtual_Com_Port_init, - Virtual_Com_Port_Reset, - Virtual_Com_Port_Status_In, - Virtual_Com_Port_Status_Out, - Virtual_Com_Port_Data_Setup, - Virtual_Com_Port_NoData_Setup, - Virtual_Com_Port_Get_Interface_Setting, - Virtual_Com_Port_GetDeviceDescriptor, - Virtual_Com_Port_GetConfigDescriptor, - Virtual_Com_Port_GetStringDescriptor, - 0, - 0x40 /*MAX PACKET SIZE*/ - }; - -USER_STANDARD_REQUESTS User_Standard_Requests = - { - Virtual_Com_Port_GetConfiguration, - Virtual_Com_Port_SetConfiguration, - Virtual_Com_Port_GetInterface, - Virtual_Com_Port_SetInterface, - Virtual_Com_Port_GetStatus, - Virtual_Com_Port_ClearFeature, - Virtual_Com_Port_SetEndPointFeature, - Virtual_Com_Port_SetDeviceFeature, - Virtual_Com_Port_SetDeviceAddress - }; - -ONE_DESCRIPTOR Device_Descriptor = - { - (uint8_t*)Virtual_Com_Port_DeviceDescriptor, - VIRTUAL_COM_PORT_SIZ_DEVICE_DESC - }; - -ONE_DESCRIPTOR Config_Descriptor = - { - (uint8_t*)Virtual_Com_Port_ConfigDescriptor, - VIRTUAL_COM_PORT_SIZ_CONFIG_DESC - }; - -ONE_DESCRIPTOR String_Descriptor[4] = - { - {(uint8_t*)Virtual_Com_Port_StringLangID, VIRTUAL_COM_PORT_SIZ_STRING_LANGID}, - {(uint8_t*)Virtual_Com_Port_StringVendor, VIRTUAL_COM_PORT_SIZ_STRING_VENDOR}, - {(uint8_t*)Virtual_Com_Port_StringProduct, VIRTUAL_COM_PORT_SIZ_STRING_PRODUCT}, - {(uint8_t*)Virtual_Com_Port_StringSerial, VIRTUAL_COM_PORT_SIZ_STRING_SERIAL} - }; - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Extern function prototypes ------------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/******************************************************************************* -* Function Name : Virtual_Com_Port_init. -* Description : Virtual COM Port Mouse init routine. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_init(void) -{ - - /* Update the serial number string descriptor with the data from the unique - ID*/ - Get_SerialNum(); - - pInformation->Current_Configuration = 0; - - /* Connect the device */ - PowerOn(); - - /* Perform basic device initialization operations */ - USB_SIL_Init(); - - /* configure the USART to the default settings */ - //USART_Config_Default(); - - bDeviceState = UNCONNECTED; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_Reset -* Description : Virtual_Com_Port Mouse reset routine -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_Reset(void) -{ - /* Set Virtual_Com_Port DEVICE as not configured */ - pInformation->Current_Configuration = 0; - - /* Current Feature initialization */ - pInformation->Current_Feature = Virtual_Com_Port_ConfigDescriptor[7]; - - /* Set Virtual_Com_Port DEVICE with the default Interface*/ - pInformation->Current_Interface = 0; - -#ifdef STM32F10X_CL - /* EP0 is already configured by USB_SIL_Init() function */ - - /* Init EP1 IN as Bulk endpoint */ - OTG_DEV_EP_Init(EP1_IN, OTG_DEV_EP_TYPE_BULK, VIRTUAL_COM_PORT_DATA_SIZE); - - /* Init EP2 IN as Interrupt endpoint */ - OTG_DEV_EP_Init(EP2_IN, OTG_DEV_EP_TYPE_INT, VIRTUAL_COM_PORT_INT_SIZE); - - /* Init EP3 OUT as Bulk endpoint */ - OTG_DEV_EP_Init(EP3_OUT, OTG_DEV_EP_TYPE_BULK, VIRTUAL_COM_PORT_DATA_SIZE); -#else - - SetBTABLE(BTABLE_ADDRESS); - - /* Initialize Endpoint 0 */ - SetEPType(ENDP0, EP_CONTROL); - SetEPTxStatus(ENDP0, EP_TX_STALL); - SetEPRxAddr(ENDP0, ENDP0_RXADDR); - SetEPTxAddr(ENDP0, ENDP0_TXADDR); - Clear_Status_Out(ENDP0); - SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); - SetEPRxValid(ENDP0); - - /* Initialize Endpoint 1 */ - SetEPType(ENDP1, EP_BULK); - SetEPTxAddr(ENDP1, ENDP1_TXADDR); - SetEPTxStatus(ENDP1, EP_TX_NAK); - SetEPRxStatus(ENDP1, EP_RX_DIS); - - /* Initialize Endpoint 2 */ - SetEPType(ENDP2, EP_INTERRUPT); - SetEPTxAddr(ENDP2, ENDP2_TXADDR); - SetEPRxStatus(ENDP2, EP_RX_DIS); - SetEPTxStatus(ENDP2, EP_TX_NAK); - - /* Initialize Endpoint 3 */ - SetEPType(ENDP3, EP_BULK); - SetEPRxAddr(ENDP3, ENDP3_RXADDR); - SetEPRxCount(ENDP3, VIRTUAL_COM_PORT_DATA_SIZE); - SetEPRxStatus(ENDP3, EP_RX_VALID); - SetEPTxStatus(ENDP3, EP_TX_DIS); - - /* Set this device to response on default address */ - SetDeviceAddress(0); -#endif /* STM32F10X_CL */ - - bDeviceState = ATTACHED; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_SetConfiguration. -* Description : Udpade the device state to configured. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_SetConfiguration(void) -{ - DEVICE_INFO *pInfo = &Device_Info; - - if (pInfo->Current_Configuration != 0) - { - /* Device configured */ - bDeviceState = CONFIGURED; - } -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_SetConfiguration. -* Description : Udpade the device state to addressed. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_SetDeviceAddress (void) -{ - bDeviceState = ADDRESSED; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_Status_In. -* Description : Virtual COM Port Status In Routine. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_Status_In(void) -{ - if (Request == SET_LINE_CODING) - { - //USART_Config(); - Request = 0; - } -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_Status_Out -* Description : Virtual COM Port Status OUT Routine. -* Input : None. -* Output : None. -* Return : None. -*******************************************************************************/ -void Virtual_Com_Port_Status_Out(void) -{} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_Data_Setup -* Description : handle the data class specific requests -* Input : Request Nb. -* Output : None. -* Return : USB_UNSUPPORT or USB_SUCCESS. -*******************************************************************************/ -RESULT Virtual_Com_Port_Data_Setup(uint8_t RequestNo) -{ - uint8_t *(*CopyRoutine)(uint16_t); - - CopyRoutine = NULL; - - if (RequestNo == GET_LINE_CODING) - { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - { - CopyRoutine = Virtual_Com_Port_GetLineCoding; - } - } - else if (RequestNo == SET_LINE_CODING) - { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - { - CopyRoutine = Virtual_Com_Port_SetLineCoding; - } - Request = SET_LINE_CODING; - } - - if (CopyRoutine == NULL) - { - return USB_UNSUPPORT; - } - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine)(0); - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_NoData_Setup. -* Description : handle the no data class specific requests. -* Input : Request Nb. -* Output : None. -* Return : USB_UNSUPPORT or USB_SUCCESS. -*******************************************************************************/ -RESULT Virtual_Com_Port_NoData_Setup(uint8_t RequestNo) -{ - - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - { - if (RequestNo == SET_COMM_FEATURE) - { - return USB_SUCCESS; - } - else if (RequestNo == SET_CONTROL_LINE_STATE) - { - return USB_SUCCESS; - } - } - - return USB_UNSUPPORT; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_GetDeviceDescriptor. -* Description : Gets the device descriptor. -* Input : Length. -* Output : None. -* Return : The address of the device descriptor. -*******************************************************************************/ -uint8_t *Virtual_Com_Port_GetDeviceDescriptor(uint16_t Length) -{ - return Standard_GetDescriptorData(Length, &Device_Descriptor); -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_GetConfigDescriptor. -* Description : get the configuration descriptor. -* Input : Length. -* Output : None. -* Return : The address of the configuration descriptor. -*******************************************************************************/ -uint8_t *Virtual_Com_Port_GetConfigDescriptor(uint16_t Length) -{ - return Standard_GetDescriptorData(Length, &Config_Descriptor); -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_GetStringDescriptor -* Description : Gets the string descriptors according to the needed index -* Input : Length. -* Output : None. -* Return : The address of the string descriptors. -*******************************************************************************/ -uint8_t *Virtual_Com_Port_GetStringDescriptor(uint16_t Length) -{ - uint8_t wValue0 = pInformation->USBwValue0; - if (wValue0 > 4) - { - return NULL; - } - else - { - return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]); - } -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_Get_Interface_Setting. -* Description : test the interface and the alternate setting according to the -* supported one. -* Input1 : uint8_t: Interface : interface number. -* Input2 : uint8_t: AlternateSetting : Alternate Setting number. -* Output : None. -* Return : The address of the string descriptors. -*******************************************************************************/ -RESULT Virtual_Com_Port_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting) -{ - if (AlternateSetting > 0) - { - return USB_UNSUPPORT; - } - else if (Interface > 1) - { - return USB_UNSUPPORT; - } - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_GetLineCoding. -* Description : send the linecoding structure to the PC host. -* Input : Length. -* Output : None. -* Return : Inecoding structure base address. -*******************************************************************************/ -uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding); - return NULL; - } - return(uint8_t *)&linecoding; -} - -/******************************************************************************* -* Function Name : Virtual_Com_Port_SetLineCoding. -* Description : Set the linecoding structure fields. -* Input : Length. -* Output : None. -* Return : Linecoding structure base address. -*******************************************************************************/ -uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding); - return NULL; - } - return(uint8_t *)&linecoding; -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/Virtual_COM_Port/usb_prop.h b/Virtual_COM_Port/usb_prop.h deleted file mode 100644 index 3adf76b..0000000 --- a/Virtual_COM_Port/usb_prop.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_prop.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : All processing related to Virtual COM Port Demo (Endpoint 0) -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __usb_prop_H -#define __usb_prop_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef struct -{ - uint32_t bitrate; - uint8_t format; - uint8_t paritytype; - uint8_t datatype; -}LINE_CODING; - -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported define -----------------------------------------------------------*/ - -#define Virtual_Com_Port_GetConfiguration NOP_Process -//#define Virtual_Com_Port_SetConfiguration NOP_Process -#define Virtual_Com_Port_GetInterface NOP_Process -#define Virtual_Com_Port_SetInterface NOP_Process -#define Virtual_Com_Port_GetStatus NOP_Process -#define Virtual_Com_Port_ClearFeature NOP_Process -#define Virtual_Com_Port_SetEndPointFeature NOP_Process -#define Virtual_Com_Port_SetDeviceFeature NOP_Process -//#define Virtual_Com_Port_SetDeviceAddress NOP_Process - -#define SEND_ENCAPSULATED_COMMAND 0x00 -#define GET_ENCAPSULATED_RESPONSE 0x01 -#define SET_COMM_FEATURE 0x02 -#define GET_COMM_FEATURE 0x03 -#define CLEAR_COMM_FEATURE 0x04 -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 -#define SEND_BREAK 0x23 - -/* Exported functions ------------------------------------------------------- */ -void Virtual_Com_Port_init(void); -void Virtual_Com_Port_Reset(void); -void Virtual_Com_Port_SetConfiguration(void); -void Virtual_Com_Port_SetDeviceAddress (void); -void Virtual_Com_Port_Status_In (void); -void Virtual_Com_Port_Status_Out (void); -RESULT Virtual_Com_Port_Data_Setup(uint8_t); -RESULT Virtual_Com_Port_NoData_Setup(uint8_t); -RESULT Virtual_Com_Port_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting); -uint8_t *Virtual_Com_Port_GetDeviceDescriptor(uint16_t ); -uint8_t *Virtual_Com_Port_GetConfigDescriptor(uint16_t); -uint8_t *Virtual_Com_Port_GetStringDescriptor(uint16_t); - -uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length); -uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length); - -#endif /* __usb_prop_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ - diff --git a/Virtual_COM_Port/usb_pwr.c b/Virtual_COM_Port/usb_pwr.c deleted file mode 100644 index 1346779..0000000 --- a/Virtual_COM_Port/usb_pwr.c +++ /dev/null @@ -1,251 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_pwr.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Connection/disconnection & power management -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32f10x.h" -#include "usb_lib.h" -#include "usb_conf.h" -#include "usb_pwr.h" -#include "hw_config.h" - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -__IO uint32_t bDeviceState = UNCONNECTED; /* USB device status */ -__IO bool fSuspendEnabled = TRUE; /* true when suspend is possible */ - -struct -{ - __IO RESUME_STATE eState; - __IO uint8_t bESOFcnt; -}ResumeS; - -/* Extern variables ----------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Extern function prototypes ------------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ - -/******************************************************************************* -* Function Name : PowerOn -* Description : -* Input : None. -* Output : None. -* Return : USB_SUCCESS. -*******************************************************************************/ -RESULT PowerOn(void) -{ -#ifndef STM32F10X_CL - uint16_t wRegVal; - - /*** cable plugged-in ? ***/ - USB_Cable_Config(ENABLE); - - /*** CNTR_PWDN = 0 ***/ - wRegVal = CNTR_FRES; - _SetCNTR(wRegVal); - - /*** CNTR_FRES = 0 ***/ - wInterrupt_Mask = 0; - _SetCNTR(wInterrupt_Mask); - /*** Clear pending interrupts ***/ - _SetISTR(0); - /*** Set interrupt mask ***/ - wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; - _SetCNTR(wInterrupt_Mask); -#endif /* STM32F10X_CL */ - - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : PowerOff -* Description : handles switch-off conditions -* Input : None. -* Output : None. -* Return : USB_SUCCESS. -*******************************************************************************/ -RESULT PowerOff() -{ -#ifndef STM32F10X_CL - /* disable all ints and force USB reset */ - _SetCNTR(CNTR_FRES); - /* clear interrupt status register */ - _SetISTR(0); - /* Disable the Pull-Up*/ - USB_Cable_Config(DISABLE); - /* switch-off device */ - _SetCNTR(CNTR_FRES + CNTR_PDWN); -#endif /* STM32F10X_CL */ - - /* sw variables reset */ - /* ... */ - - return USB_SUCCESS; -} - -/******************************************************************************* -* Function Name : Suspend -* Description : sets suspend mode operating conditions -* Input : None. -* Output : None. -* Return : USB_SUCCESS. -*******************************************************************************/ -void Suspend(void) -{ -#ifndef STM32F10X_CL - uint16_t wCNTR; - /* suspend preparation */ - /* ... */ - - /* macrocell enters suspend mode */ - wCNTR = _GetCNTR(); - wCNTR |= CNTR_FSUSP; - _SetCNTR(wCNTR); -#endif /* STM32F10X_CL */ - - /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ - /* power reduction */ - /* ... on connected devices */ - -#ifndef STM32F10X_CL - /* force low-power mode in the macrocell */ - wCNTR = _GetCNTR(); - wCNTR |= CNTR_LPMODE; - _SetCNTR(wCNTR); -#endif /* STM32F10X_CL */ - - /* switch-off the clocks */ - /* ... */ - Enter_LowPowerMode(); - -} - -/******************************************************************************* -* Function Name : Resume_Init -* Description : Handles wake-up restoring normal operations -* Input : None. -* Output : None. -* Return : USB_SUCCESS. -*******************************************************************************/ -void Resume_Init(void) -{ -#ifndef STM32F10X_CL - uint16_t wCNTR; -#endif /* STM32F10X_CL */ - - /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ - /* restart the clocks */ - /* ... */ - -#ifndef STM32F10X_CL - /* CNTR_LPMODE = 0 */ - wCNTR = _GetCNTR(); - wCNTR &= (~CNTR_LPMODE); - _SetCNTR(wCNTR); -#endif /* STM32F10X_CL */ - - /* restore full power */ - /* ... on connected devices */ - Leave_LowPowerMode(); - -#ifndef STM32F10X_CL - /* reset FSUSP bit */ - _SetCNTR(IMR_MSK); -#endif /* STM32F10X_CL */ - - /* reverse suspend preparation */ - /* ... */ - -} - -/******************************************************************************* -* Function Name : Resume -* Description : This is the state machine handling resume operations and -* timing sequence. The control is based on the Resume structure -* variables and on the ESOF interrupt calling this subroutine -* without changing machine state. -* Input : a state machine value (RESUME_STATE) -* RESUME_ESOF doesn't change ResumeS.eState allowing -* decrementing of the ESOF counter in different states. -* Output : None. -* Return : None. -*******************************************************************************/ -void Resume(RESUME_STATE eResumeSetVal) -{ -#ifndef STM32F10X_CL - uint16_t wCNTR; -#endif /* STM32F10X_CL */ - - if (eResumeSetVal != RESUME_ESOF) - ResumeS.eState = eResumeSetVal; - - switch (ResumeS.eState) - { - case RESUME_EXTERNAL: - Resume_Init(); - ResumeS.eState = RESUME_OFF; - break; - case RESUME_INTERNAL: - Resume_Init(); - ResumeS.eState = RESUME_START; - break; - case RESUME_LATER: - ResumeS.bESOFcnt = 2; - ResumeS.eState = RESUME_WAIT; - break; - case RESUME_WAIT: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) - ResumeS.eState = RESUME_START; - break; - case RESUME_START: - #ifdef STM32F10X_CL - OTGD_FS_Dev_SetRemoteWakeup(); - #else - wCNTR = _GetCNTR(); - wCNTR |= CNTR_RESUME; - _SetCNTR(wCNTR); - #endif /* STM32F10X_CL */ - ResumeS.eState = RESUME_ON; - ResumeS.bESOFcnt = 10; - break; - case RESUME_ON: - #ifndef STM32F10X_CL - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) - { - #endif /* STM32F10X_CL */ - #ifdef STM32F10X_CL - OTGD_FS_Dev_ResetRemoteWakeup(); - #else - wCNTR = _GetCNTR(); - wCNTR &= (~CNTR_RESUME); - _SetCNTR(wCNTR); - #endif /* STM32F10X_CL */ - ResumeS.eState = RESUME_OFF; - #ifndef STM32F10X_CL - } - #endif /* STM32F10X_CL */ - break; - case RESUME_OFF: - case RESUME_ESOF: - default: - ResumeS.eState = RESUME_OFF; - break; - } -} - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/Virtual_COM_Port/usb_pwr.h b/Virtual_COM_Port/usb_pwr.h deleted file mode 100644 index 21a9927..0000000 --- a/Virtual_COM_Port/usb_pwr.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_pwr.h -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : Connection/disconnection & power management header -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_PWR_H -#define __USB_PWR_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -typedef enum _RESUME_STATE -{ - RESUME_EXTERNAL, - RESUME_INTERNAL, - RESUME_LATER, - RESUME_WAIT, - RESUME_START, - RESUME_ON, - RESUME_OFF, - RESUME_ESOF -} RESUME_STATE; - -typedef enum _DEVICE_STATE -{ - UNCONNECTED, - ATTACHED, - POWERED, - SUSPENDED, - ADDRESSED, - CONFIGURED -} DEVICE_STATE; - -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -void Suspend(void); -void Resume_Init(void); -void Resume(RESUME_STATE eResumeSetVal); -RESULT PowerOn(void); -RESULT PowerOff(void); - -/* External variables --------------------------------------------------------*/ -extern __IO uint32_t bDeviceState; /* USB device status */ -extern __IO bool fSuspendEnabled; /* true when suspend is possible */ - -#endif /*__USB_PWR_H*/ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/boards/common/hw_config.c b/boards/common/hw_config.c index d355262..0a59997 100644 --- a/boards/common/hw_config.c +++ b/boards/common/hw_config.c @@ -1,36 +1,8 @@ -/* Hardware specific USB functions */ -/* - * For detail, please see the documentation of - * STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib) - * by STMicroelectronics' MCD Application Team - */ +/* Hardware specific function */ #include "ch.h" #include "hal.h" #include "board.h" -#include "usb_lib.h" -#include "usb_prop.h" -#include "usb_desc.h" -#include "hw_config.h" -#include "platform_config.h" -#include "usb_pwr.h" - -void -Enter_LowPowerMode (void) -{ - bDeviceState = SUSPENDED; -} - -void -Leave_LowPowerMode (void) -{ - DEVICE_INFO *pInfo = &Device_Info; - - if (pInfo->Current_Configuration != 0) - bDeviceState = CONFIGURED; - else - bDeviceState = ATTACHED; -} const uint8_t * unique_device_id (void) diff --git a/src/Makefile.in b/src/Makefile.in index e6d5271..f5e2fac 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -70,10 +70,12 @@ include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk include $(CHIBIOS)/os/hal/hal.mk include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk include $(CHIBIOS)/os/kernel/kernel.mk -include stmusb.mk -include vcomport.mk include crypt.mk +ifneq ($(ENABLE_VCOMPORT),) +VCOMSRC += usb_endp.c +endif + # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ @@ -85,7 +87,6 @@ CSRC = $(PORTSRC) \ $(BOARD_DIR)/board.c \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - $(STMUSBSRC) \ $(VCOMSRC) \ $(CRYPTSRC) \ main.c usb_lld.c \ @@ -109,7 +110,7 @@ endif ASMSRC = $(PORTASM) \ $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s -INCDIR = $(CRYPTINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \ +INCDIR = $(CRYPTINCDIR) \ $(PORTINC) $(KERNINC) $(TESTINC) \ $(HALINC) $(PLATFORMINC) ../boards/common $(BOARD_DIR) \ $(CHIBIOS)/os/various diff --git a/src/main.c b/src/main.c index 5f62801..b838409 100644 --- a/src/main.c +++ b/src/main.c @@ -22,16 +22,9 @@ */ #include "config.h" - -#include "usb_lib.h" - #include "ch.h" #include "gnuk.h" #include "usb_lld.h" -#include "usb_istr.h" -#include "usb_desc.h" -#include "hw_config.h" -#include "usb_pwr.h" #ifdef DEBUG struct stdout { @@ -380,7 +373,6 @@ main (int argc, char **argv) flash_unlock (); device_initialize_once (); usb_lld_init (); - USB_Init (); random_init (); #ifdef DEBUG diff --git a/src/stmusb.mk b/src/stmusb.mk deleted file mode 100644 index b459268..0000000 --- a/src/stmusb.mk +++ /dev/null @@ -1,7 +0,0 @@ -STMUSBDIR = ../STM32_USB-FS-Device_Driver -STMUSBSRCDIR = $(STMUSBDIR)/src -STMUSBINCDIR = $(STMUSBDIR)/inc -STMUSBSRC= \ - $(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \ - $(STMUSBSRCDIR)/usb_core.c \ - $(STMUSBSRCDIR)/usb_regs.c diff --git a/src/usb-cdc-vport.c b/src/usb-cdc-vport.c deleted file mode 100644 index 23a1c81..0000000 --- a/src/usb-cdc-vport.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is included by usb_prop.c to provide Virtual COM port feature - */ - -/* Original is ../Virtual_COM_Port/usb_prop.c by STMicroelectronics */ -/* Chopped and modified for Gnuk */ - -#include "usb-cdc.h" - -/* Original copyright notice is following: */ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_prop.c -* Author : MCD Application Team -* Version : V3.1.1 -* Date : 04/07/2010 -* Description : All processing related to Virtual Com Port Demo -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -typedef struct -{ - uint32_t bitrate; - uint8_t format; - uint8_t paritytype; - uint8_t datatype; -} LINE_CODING; - -static LINE_CODING linecoding = { - 115200, /* baud rate*/ - 0x00, /* stop bits-1*/ - 0x00, /* parity - none*/ - 0x08 /* no. of bits 8*/ -}; - -static uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding); - return NULL; - } - - return (uint8_t *)&linecoding; -} - -static uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length) -{ - if (Length == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding); - return NULL; - } - - return (uint8_t *)&linecoding; -} - -static RESULT -Virtual_Com_Port_Data_Setup (uint8_t RequestNo) -{ - uint8_t *(*CopyRoutine)(uint16_t); - - CopyRoutine = NULL; - - if (RequestNo == USB_CDC_REQ_GET_LINE_CODING) - CopyRoutine = Virtual_Com_Port_GetLineCoding; - else if (RequestNo == USB_CDC_REQ_SET_LINE_CODING) - CopyRoutine = Virtual_Com_Port_SetLineCoding; - - if (CopyRoutine == NULL) - return USB_UNSUPPORT; - - pInformation->Ctrl_Info.CopyData = CopyRoutine; - pInformation->Ctrl_Info.Usb_wOffset = 0; - (*CopyRoutine) (0); /* Set Ctrl_Info.Usb_wLength */ - - return USB_SUCCESS; -} - -static RESULT -Virtual_Com_Port_NoData_Setup (uint8_t RequestNo) -{ - if (RequestNo == USB_CDC_REQ_SET_CONTROL_LINE_STATE) - /* Do nothing and success */ - return USB_SUCCESS; - - return USB_UNSUPPORT; -} diff --git a/src/usb-icc.c b/src/usb-icc.c index 7766bcf..3cc1b87 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -25,10 +25,6 @@ #include "ch.h" #include "hal.h" #include "gnuk.h" -#include "usb_lib.h" -#include "usb_mem.h" -#include "hw_config.h" -#include "usb_istr.h" #include "usb_lld.h" /* diff --git a/src/usb_conf.h b/src/usb_conf.h index 4416def..16b692f 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -1,24 +1,9 @@ -/* USB configuration file for USB-FS-Device_Lib */ -/* - * For detail, please see the documentation of - * STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib) - * by STMicroelectronics - */ +/* USB buffer memory definition and number of string descriptors */ #ifndef __USB_CONF_H #define __USB_CONF_H -#ifdef PINPAD_DND_SUPPORT -# define EP_NUM (8) -#else -# ifdef ENABLE_VIRTUAL_COM_PORT -# define EP_NUM (6) -# else -# define EP_NUM (3) -# endif -#endif - -#define BTABLE_ADDRESS (0x00) +#define NUM_STRING_DESC 4 /* EP0 */ #define ENDP0_RXADDR (0x40) @@ -41,6 +26,4 @@ /* EP7 */ #define ENDP7_RXADDR (0x1c0) -#define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM ) - #endif /* __USB_CONF_H */ diff --git a/src/usb_desc.c b/src/usb_desc.c index eec9bc6..caa7506 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -3,8 +3,9 @@ */ #include "config.h" -#include "usb_lib.h" -#include "usb_desc.h" +#include "ch.h" +#include "usb_lld.h" +#include "usb_conf.h" #define USB_ICC_INTERFACE_CLASS 0x0B #define USB_ICC_INTERFACE_SUBCLASS 0x00 @@ -282,19 +283,19 @@ const uint8_t gnukStringSerial[] = { }; -const ONE_DESCRIPTOR Device_Descriptor = { - (uint8_t*)gnukDeviceDescriptor, +const struct Descriptor Device_Descriptor = { + gnukDeviceDescriptor, sizeof (gnukDeviceDescriptor) }; -const ONE_DESCRIPTOR Config_Descriptor = { - (uint8_t*)gnukConfigDescriptor, +const struct Descriptor Config_Descriptor = { + gnukConfigDescriptor, sizeof (gnukConfigDescriptor) }; -const ONE_DESCRIPTOR String_Descriptor[] = { - {(uint8_t*)gnukStringLangID, sizeof (gnukStringLangID)}, - {(uint8_t*)gnukStringVendor, sizeof (gnukStringVendor)}, - {(uint8_t*)gnukStringProduct, sizeof (gnukStringProduct)}, - {(uint8_t*)gnukStringSerial, sizeof (gnukStringSerial)}, +const struct Descriptor String_Descriptors[NUM_STRING_DESC] = { + {gnukStringLangID, sizeof (gnukStringLangID)}, + {gnukStringVendor, sizeof (gnukStringVendor)}, + {gnukStringProduct, sizeof (gnukStringProduct)}, + {gnukStringSerial, sizeof (gnukStringSerial)}, }; diff --git a/src/usb_endp.c b/src/usb_endp.c index 42a3aaf..0870caa 100644 --- a/src/usb_endp.c +++ b/src/usb_endp.c @@ -2,21 +2,19 @@ * Virtual COM port (for debug output only) */ -#include "usb_lib.h" - #include "config.h" #include "ch.h" #include "gnuk.h" void -EP3_IN_Callback(void) +EP3_IN_Callback (void) { if (stdout_thread) chEvtSignalI (stdout_thread, EV_TX_READY); } void -EP5_OUT_Callback(void) +EP5_OUT_Callback (void) { - SetEPRxValid (ENDP5); + usb_lld_rx_enable (ENDP5); } diff --git a/src/usb_lld.c b/src/usb_lld.c index 4af51fe..25ac005 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -1,21 +1,1011 @@ #include "ch.h" #include "hal.h" -#include "usb_lib.h" #include "usb_lld.h" -extern void USB_Istr (void); +#define USB_MAX_PACKET_SIZE 64 /* For FS device */ + +#define RECIPIENT 0x1F /* Mask to get recipient */ + +enum STANDARD_REQUESTS +{ + GET_STATUS = 0, + CLEAR_FEATURE, + RESERVED1, + SET_FEATURE, + RESERVED2, + SET_ADDRESS, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + SYNCH_FRAME, + TOTAL_REQUEST /* Total number of Standard request */ +}; + +/* The state machine states of a control pipe */ +enum CONTROL_STATE +{ + WAIT_SETUP, /* 0 */ + SETTING_UP, /* 1 */ + IN_DATA, /* 2 */ + OUT_DATA, /* 3 */ + LAST_IN_DATA, /* 4 */ + LAST_OUT_DATA, /* 5 */ + WAIT_STATUS_IN, /* 7 */ + WAIT_STATUS_OUT, /* 8 */ + STALLED, /* 9 */ + PAUSE /* 10 */ +}; + +enum FEATURE_SELECTOR +{ + ENDPOINT_STALL, + DEVICE_REMOTE_WAKEUP +}; + +struct DATA_INFO +{ + uint16_t len; + uint16_t offset; + uint8_t *addr; + uint8_t require_zlp; +}; + +struct CONTROL_INFO +{ + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}; + +struct DEVICE_INFO +{ + uint8_t current_configuration; + uint8_t current_feature; + uint8_t state; +}; + +static struct CONTROL_INFO *ctrl_p; +static struct DEVICE_INFO *dev_p; +static struct DATA_INFO *data_p; + +#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */ +#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */ + +/* Control register */ +#define CNTR ((__IO uint16_t *)(REG_BASE + 0x40)) +/* Interrupt status register */ +#define ISTR ((__IO uint16_t *)(REG_BASE + 0x44)) +/* Frame number register */ +#define FNR ((__IO uint16_t *)(REG_BASE + 0x48)) +/* Device address register */ +#define DADDR ((__IO uint16_t *)(REG_BASE + 0x4C)) +/* Buffer Table address register */ +#define BTABLE ((__IO uint16_t *)(REG_BASE + 0x50)) + +#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ +#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ +#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ +#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ +#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ +#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ +#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ +#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ + +#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ +#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ + +#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ +#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ +#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ +#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ +#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ +#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ +#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ +#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ + +#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ +#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ +#define CNTR_ERRM (0x2000) /* ERRor Mask */ +#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ +#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ +#define CNTR_RESETM (0x0400) /* RESET Mask */ +#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ +#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ + +#define CNTR_RESUME (0x0010) /* RESUME request */ +#define CNTR_FSUSP (0x0008) /* Force SUSPend */ +#define CNTR_LPMODE (0x0004) /* Low-power MODE */ +#define CNTR_PDWN (0x0002) /* Power DoWN */ +#define CNTR_FRES (0x0001) /* Force USB RESet */ + +#define DADDR_EF (0x80) +#define DADDR_ADD (0x7F) + +#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ +#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ +#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ +#define EP_SETUP (0x0800) /* EndPoint SETUP */ +#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ +#define EP_KIND (0x0100) /* EndPoint KIND */ +#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ +#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ +#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ +#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ + +#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) + +/* STAT_TX[1:0] STATus for TX transfer */ +#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ +#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ +#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ +#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ +#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ +#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ + +/* STAT_RX[1:0] STATus for RX transfer */ +#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ +#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ +#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ +#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ +#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ + +static void usb_handle_transfer (void); + +static void st103_set_btable (void) +{ + *BTABLE = 0; +} + +static uint16_t st103_get_istr (void) +{ + return *ISTR; +} + +static void st103_set_istr (uint16_t istr) +{ + *ISTR = istr; +} + +static void st103_set_cntr (uint16_t cntr) +{ + *CNTR = cntr; +} + +static void st103_set_daddr (uint16_t daddr) +{ + *DADDR = daddr | DADDR_EF; +} + +static void st103_set_epreg (uint8_t ep_num, uint16_t value) +{ + uint16_t *reg_p = (uint16_t *)(REG_BASE + ep_num*4); + + *reg_p = value; +} + +static uint16_t st103_get_epreg (uint8_t ep_num) +{ + uint16_t *reg_p = (uint16_t *)(REG_BASE + ep_num*4); + + return *reg_p; +} + +static void st103_set_tx_addr (uint8_t ep_num, uint16_t addr) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+0)*2); + + *reg_p = addr; +} + +static uint16_t st103_get_tx_addr (uint8_t ep_num) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+0)*2); + + return *reg_p; +} + + +static void st103_set_tx_count (uint8_t ep_num, uint16_t size) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+2)*2); + + *reg_p = size; +} + +static uint16_t st103_get_tx_count (uint8_t ep_num) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+2)*2); + + return *reg_p & 0x03ff; +} + + +static void st103_set_rx_addr (uint8_t ep_num, uint16_t addr) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+4)*2); + + *reg_p = addr; +} + +static uint16_t st103_get_rx_addr (uint8_t ep_num) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+4)*2); + + return *reg_p; +} + + +static void st103_set_rx_buf_size (uint8_t ep_num, uint16_t size) +{ /* Assume size is even */ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+6)*2); + uint16_t value; + + if (size <= 62) + value = (size & 0x3e) << 9; + else + value = 0x8000 | (((size >> 5) - 1) << 10); + + *reg_p = value; +} + +static uint16_t st103_get_rx_count (uint8_t ep_num) +{ + uint16_t *reg_p = (uint16_t *)(PMA_ADDR + (ep_num*8+6)*2); + + return *reg_p & 0x03ff; +} + + +static void st103_ep_clear_ctr_rx (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num) & ~EP_CTR_RX & EPREG_MASK; + + st103_set_epreg (ep_num, value); +} + +static void st103_ep_clear_ctr_tx (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num) & ~EP_CTR_TX & EPREG_MASK; + + st103_set_epreg (ep_num, value); +} + +static void st103_ep_set_rxtx_status (uint8_t ep_num, uint16_t st_rx, + uint16_t st_tx) +{ + uint16_t value = st103_get_epreg (ep_num); + + value &= (EPREG_MASK|EPRX_STAT|EPTX_STAT); + value ^= (EPRX_DTOG1 & st_rx); + value ^= (EPRX_DTOG2 & st_rx); + value ^= (EPTX_DTOG1 & st_tx); + value ^= (EPTX_DTOG2 & st_tx); + value |= EP_CTR_RX | EP_CTR_TX; + st103_set_epreg (ep_num, value); +} + +static void st103_ep_set_rx_status (uint8_t ep_num, uint16_t st_rx) +{ + uint16_t value = st103_get_epreg (ep_num); + + value &= (EPREG_MASK|EPRX_STAT); + value ^= (EPRX_DTOG1 & st_rx); + value ^= (EPRX_DTOG2 & st_rx); + value |= EP_CTR_RX | EP_CTR_TX; + st103_set_epreg (ep_num, value); +} + +static uint16_t st103_ep_get_rx_status (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num); + + return value & EPRX_STAT; +} + +static void st103_ep_set_tx_status (uint8_t ep_num, uint16_t st_tx) +{ + uint16_t value = st103_get_epreg (ep_num); + + value &= (EPREG_MASK|EPTX_STAT); + value ^= (EPTX_DTOG1 & st_tx); + value ^= (EPTX_DTOG2 & st_tx); + value |= EP_CTR_RX | EP_CTR_TX; + st103_set_epreg (ep_num, value); +} + +static uint16_t st103_ep_get_tx_status (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num); + + return value & EPTX_STAT; +} + +static void st103_ep_clear_dtog_rx (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num); + + if ((value & EP_DTOG_RX)) + { + value &= EPREG_MASK; + value |= EP_CTR_RX | EP_CTR_TX | EP_DTOG_RX; + st103_set_epreg (ep_num, value); + } +} + +static void st103_ep_clear_dtog_tx (uint8_t ep_num) +{ + uint16_t value = st103_get_epreg (ep_num); + + if ((value & EP_DTOG_TX)) + { + value &= EPREG_MASK; + value |= EP_CTR_RX | EP_CTR_TX | EP_DTOG_TX; + st103_set_epreg (ep_num, value); + } +} + +static const struct usb_device_method* method_p; + +static void +usb_interrupt_handler (void) +{ + uint16_t istr_value = st103_get_istr (); + + if (istr_value & ISTR_CTR) + usb_handle_transfer (); + + if (istr_value & ISTR_RESET) + { + st103_set_istr (CLR_RESET); + method_p->reset (); + } + + if (istr_value & ISTR_DOVR) + st103_set_istr (CLR_DOVR); + + if (istr_value & ISTR_ERR) + st103_set_istr (CLR_ERR); +} CH_IRQ_HANDLER (Vector90) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); - USB_Istr(); + usb_interrupt_handler (); chSysUnlockFromIsr(); CH_IRQ_EPILOGUE(); } -void usb_lld_init (void) { +static void handle_datastage_out (void) +{ + if (data_p->addr && data_p->len) + { + uint8_t *buf; + uint32_t len = USB_MAX_PACKET_SIZE; + + if (len > data_p->len) + len = data_p->len; + + buf = data_p->addr + data_p->offset; + data_p->len -= len; + data_p->offset += len; + + usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len); + } + + if (data_p->len != 0) + { + st103_ep_set_rx_status (ENDP0, EP_RX_VALID); + st103_set_tx_count (ENDP0, 0); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + } + + if (data_p->len >= USB_MAX_PACKET_SIZE) + dev_p->state = OUT_DATA; + else + if (data_p->len > 0) + dev_p->state = LAST_OUT_DATA; + else if (data_p->len == 0) + { + dev_p->state = WAIT_STATUS_IN; + st103_set_tx_count (ENDP0, 0); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + } +} + +static void handle_datastage_in (void) +{ + uint32_t len = USB_MAX_PACKET_SIZE;; + const uint8_t *buf; + + if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA)) + { + if (data_p->require_zlp == TRUE) + { + data_p->require_zlp = FALSE; + + /* No more data to send. Send empty packet */ + st103_set_tx_count (ENDP0, 0); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + } + else + { + /* No more data to send. Thus, STALL the TX Status*/ + dev_p->state = WAIT_STATUS_OUT; + st103_ep_set_tx_status (ENDP0, EP_TX_STALL); + } + return; + } + + dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA; + + if (len > data_p->len) + len = data_p->len; + + buf = (const uint8_t *)data_p->addr + data_p->offset; + usb_lld_to_pmabuf (buf, st103_get_tx_addr (ENDP0), len); + st103_set_tx_count (ENDP0, len); + + data_p->len -= len; + data_p->offset += len; + st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID); +} + +typedef int (*HANDLER) (uint8_t rcp, + uint16_t value, uint16_t index, uint16_t length); + +static int std_none (uint8_t rcp, + uint16_t value, uint16_t index, uint16_t length) +{ + (void)rcp; (void)value; (void)index; (void)length; + return USB_UNSUPPORT; +} + +static int std_get_status (uint8_t rcp, + uint16_t value, uint16_t index, uint16_t length) +{ + static uint16_t status_info; + + status_info = 0; /* Reset Status Information */ + data_p->addr = (uint8_t *)&status_info; + + if (value != 0 || length != 2 || (index >> 8) != 0) + return USB_UNSUPPORT; + + if (rcp == DEVICE_RECIPIENT) + { + if (index == 0) + { + /* Get Device Status */ + uint8_t feature = dev_p->current_feature; + + /* Remote Wakeup enabled */ + if ((feature & (1 << 5))) + status_info |= 2; + else + status_info &= ~2; + + /* Bus-powered */ + if ((feature & (1 << 6))) + status_info |= 1; + else /* Self-powered */ + status_info &= ~1; + + data_p->len = 2; + return USB_SUCCESS; + } + } + else if (rcp == INTERFACE_RECIPIENT) + { + int r; + + if (dev_p->current_configuration == 0) + return USB_UNSUPPORT; + + r = (*method_p->interface) (USB_QUERY_INTERFACE, index, 0); + if (r != USB_SUCCESS) + return USB_UNSUPPORT; + + data_p->len = 2; + return USB_SUCCESS; + } + else if (rcp == ENDPOINT_RECIPIENT) + { + uint8_t endpoint = (index & 0x0f); + uint16_t status; + + if ((index & 0x70) != 0 || endpoint == ENDP0) + return USB_UNSUPPORT; + + if ((index & 0x80)) + { + status = st103_ep_get_tx_status (endpoint); + if (status == 0) /* Disabled */ + return USB_UNSUPPORT; + else if (status == EP_TX_STALL) + status_info |= 1; /* IN Endpoint stalled */ + } + else + { + status = st103_ep_get_rx_status (endpoint); + if (status == 0) /* Disabled */ + return USB_UNSUPPORT; + else if (status == EP_RX_STALL) + status_info |= 1; /* OUT Endpoint stalled */ + } + + data_p->len = 2; + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_clear_feature (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == DEVICE_RECIPIENT) + { + if (length != 0 || index != 0) + return USB_UNSUPPORT; + + if (value == DEVICE_REMOTE_WAKEUP) + { + dev_p->current_feature &= ~(1 << 5); + return USB_SUCCESS; + } + } + else if (rcp == ENDPOINT_RECIPIENT) + { + uint8_t endpoint = (index & 0x0f); + uint16_t status; + + if (dev_p->current_configuration == 0) + return USB_UNSUPPORT; + + if (length != 0 || (index >> 8) != 0 || value != ENDPOINT_STALL + || endpoint == ENDP0) + return USB_UNSUPPORT; + + if ((index & 0x80)) + status = st103_ep_get_tx_status (endpoint); + else + status = st103_ep_get_rx_status (endpoint); + + if (status == 0) /* Disabled */ + return USB_UNSUPPORT; + + if (index & 0x80) + { /* IN endpoint */ + if (st103_ep_get_tx_status (endpoint) == EP_TX_STALL) + { + st103_ep_clear_dtog_tx (endpoint); + st103_ep_set_tx_status (endpoint, EP_TX_VALID); + } + } + else + { /* OUT endpoint */ + if (st103_ep_get_rx_status (endpoint) == EP_RX_STALL) + { + st103_ep_clear_dtog_rx (endpoint); + st103_ep_set_rx_status (endpoint, EP_RX_VALID); + } + } + + // event?? + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_set_feature (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == DEVICE_RECIPIENT) + { + if (length != 0 || index != 0) + return USB_UNSUPPORT; + + if (value == DEVICE_REMOTE_WAKEUP) + { + dev_p->current_feature |= 1 << 5; + // event?? + return USB_SUCCESS; + } + } + else if (rcp == ENDPOINT_RECIPIENT) + { + uint8_t endpoint = (index & 0x0f); + uint32_t status; + + if (dev_p->current_configuration == 0) + return USB_UNSUPPORT; + + if (length != 0 || (index >> 8) != 0 || value != 0 || endpoint == ENDP0) + return USB_UNSUPPORT; + + if ((index & 0x80)) + status = st103_ep_get_tx_status (endpoint); + else + status = st103_ep_get_rx_status (endpoint); + + if (status == 0) /* Disabled */ + return USB_UNSUPPORT; + + if (index & 0x80) + /* IN endpoint */ + st103_ep_set_tx_status (endpoint, EP_TX_STALL); + else + /* OUT endpoint */ + st103_ep_set_rx_status (endpoint, EP_RX_STALL); + + // event?? + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_set_address (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == DEVICE_RECIPIENT) + { + if (length == 0 && value <= 127 && index == 0 + && dev_p->current_configuration == 0) + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_get_descriptor (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + (void)length; + if (rcp == DEVICE_RECIPIENT) + return (*method_p->get_descriptor) ((value >> 8), index, value); + + return USB_UNSUPPORT; +} + +static int std_get_configuration (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + (void)value; (void)index; (void)length; + if (rcp == DEVICE_RECIPIENT) + { + data_p->addr = &dev_p->current_configuration; + data_p->len = 1; + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_set_configuration (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0) + { + int r; + + r = (*method_p->event) (USB_EVENT_CONFIG, value); + if (r == USB_SUCCESS) + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static int std_get_interface (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == INTERFACE_RECIPIENT) + { + if (value != 0 || (index >> 8) != 0 || length != 1) + return USB_UNSUPPORT; + + if (dev_p->current_configuration == 0) + return USB_UNSUPPORT; + + return (*method_p->interface) (USB_GET_INTERFACE, index, 0); + } + + return USB_UNSUPPORT; +} + +static int std_set_interface (uint8_t rcp, uint16_t value, + uint16_t index, uint16_t length) +{ + if (rcp == INTERFACE_RECIPIENT) + { + int r; + + if (length != 0 || (index >> 8) != 0 || (value >> 8) != 0) + return USB_UNSUPPORT; + + if (dev_p->current_configuration != 0) + return USB_UNSUPPORT; + + r = (*method_p->interface) (USB_SET_INTERFACE, index, value); + if (r == USB_SUCCESS) + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +static const HANDLER std_request_handler[TOTAL_REQUEST] = { + std_get_status, + std_clear_feature, + std_none, + std_set_feature, + std_none, + std_set_address, + std_get_descriptor, + std_none, /* set_descriptor is not supported */ + std_get_configuration, + std_set_configuration, + std_get_interface, + std_set_interface, + std_none, /* sync_frame is not supported (for now) */ +}; + +static void handle_setup0 (void) +{ + const uint16_t *pw; + uint16_t w; + uint8_t req; + int r = USB_UNSUPPORT; + HANDLER handler; + uint8_t type_rcp; + + pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2)); + w = *pw++; + + ctrl_p->bmRequestType = w & 0xff; + ctrl_p->bRequest = req = w >> 8; + pw++; + ctrl_p->wValue = *pw++; + pw++; + ctrl_p->wIndex = *pw++; + pw++; + ctrl_p->wLength = *pw; + + dev_p->state = STALLED; + data_p->len = 0; + data_p->offset = 0; + + type_rcp = (ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT)); + if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) /* Interface */ + || (ctrl_p->bmRequestType & REQUEST_TYPE) == VENDOR_REQUEST) + { + if (ctrl_p->wLength == 0) + r = (*method_p->setup_with_nodata) (type_rcp, req, ctrl_p->wIndex); + else + { + (*method_p->setup_with_data) (type_rcp, req, ctrl_p->wIndex); + if (data_p->len != 0) + r = USB_SUCCESS; + } + } + else if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST) + { + if (req < TOTAL_REQUEST) + { + handler = std_request_handler[req]; + r = (*handler) (ctrl_p->bmRequestType & RECIPIENT, + ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength); + } + } + + if (r != USB_SUCCESS) + dev_p->state = STALLED; + else + { + if (ctrl_p->wLength == 0) + { + dev_p->state = WAIT_STATUS_IN; + st103_set_tx_count (ENDP0, 0); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + } + else if (ctrl_p->bmRequestType & 0x80) + { + uint32_t len = ctrl_p->wLength; + + /* Restrict the data length to be the one host asks for */ + if (data_p->len > len) + data_p->len = len; + + if ((data_p->len % USB_MAX_PACKET_SIZE) == 0) + data_p->require_zlp = TRUE; + else + data_p->require_zlp = FALSE; + + handle_datastage_in (); + } + else + { + dev_p->state = OUT_DATA; + st103_ep_set_rx_status (ENDP0, EP_RX_VALID); + /* enable for next data reception */ + } + } +} + +static void handle_in0 (void) +{ + if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA) + handle_datastage_in (); + else if (dev_p->state == WAIT_STATUS_IN) + { + if ((ctrl_p->bRequest == SET_ADDRESS) && + ((ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT)) + == (STANDARD_REQUEST | DEVICE_RECIPIENT))) + { + st103_set_daddr (ctrl_p->wValue); + (*method_p->event) (USB_EVENT_ADDRESS, ctrl_p->wValue); + } + dev_p->state = STALLED; + } + else + dev_p->state = STALLED; +} + +static void handle_out0 (void) +{ + if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA) + /* host aborts the transfer before finish */ + dev_p->state = STALLED; + else if (dev_p->state == OUT_DATA || dev_p->state == LAST_OUT_DATA) + handle_datastage_out (); + else if (dev_p->state == WAIT_STATUS_OUT) + dev_p->state = STALLED; + /* Unexpect state, STALL the endpoint */ + else + dev_p->state = STALLED; +} + +static void nop_proc (void) +{ +} + +#define WEAK __attribute__ ((weak)) +void WEAK EP1_IN_Callback (void); +void WEAK EP2_IN_Callback (void); +void WEAK EP3_IN_Callback (void); +void WEAK EP4_IN_Callback (void); +void WEAK EP5_IN_Callback (void); +void WEAK EP6_IN_Callback (void); +void WEAK EP7_IN_Callback (void); + +void WEAK EP1_OUT_Callback (void); +void WEAK EP2_OUT_Callback (void); +void WEAK EP3_OUT_Callback (void); +void WEAK EP4_OUT_Callback (void); +void WEAK EP5_OUT_Callback (void); +void WEAK EP6_OUT_Callback (void); +void WEAK EP7_OUT_Callback (void); + +#pragma weak EP1_IN_Callback = nop_proc +#pragma weak EP2_IN_Callback = nop_proc +#pragma weak EP3_IN_Callback = nop_proc +#pragma weak EP4_IN_Callback = nop_proc +#pragma weak EP5_IN_Callback = nop_proc +#pragma weak EP6_IN_Callback = nop_proc +#pragma weak EP7_IN_Callback = nop_proc + +#pragma weak EP1_OUT_Callback = nop_proc +#pragma weak EP2_OUT_Callback = nop_proc +#pragma weak EP3_OUT_Callback = nop_proc +#pragma weak EP4_OUT_Callback = nop_proc +#pragma weak EP5_OUT_Callback = nop_proc +#pragma weak EP6_OUT_Callback = nop_proc +#pragma weak EP7_OUT_Callback = nop_proc + +void (*const ep_intr_handler_IN[7]) (void) = { + EP1_IN_Callback, + EP2_IN_Callback, + EP3_IN_Callback, + EP4_IN_Callback, + EP5_IN_Callback, + EP6_IN_Callback, + EP7_IN_Callback, +}; + +void (*const ep_intr_handler_OUT[7]) (void) = { + EP1_OUT_Callback, + EP2_OUT_Callback, + EP3_OUT_Callback, + EP4_OUT_Callback, + EP5_OUT_Callback, + EP6_OUT_Callback, + EP7_OUT_Callback, +}; + +static void +usb_handle_transfer (void) +{ + uint16_t ep_value = 0; + uint16_t istr_value; + uint8_t ep_index; + + while (((istr_value = st103_get_istr ()) & ISTR_CTR) != 0) + { + ep_index = (istr_value & ISTR_EP_ID); + if (ep_index == 0) + { + if ((istr_value & ISTR_DIR) == 0) + { /* DIR = 0 */ + /* DIR = 0 => IN int */ + /* DIR = 0 implies that (EP_CTR_TX = 1) always */ + + st103_ep_clear_ctr_tx (ENDP0); + handle_in0 (); + } + else + { /* DIR = 1 */ + /* DIR = 1 & CTR_RX => SETUP or OUT int */ + /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ + + ep_value = st103_get_epreg (ENDP0); + if ((ep_value & EP_SETUP) != 0) + { + st103_ep_clear_ctr_rx (ENDP0); + handle_setup0 (); + } + else if ((ep_value & EP_CTR_RX) != 0) + { + st103_ep_clear_ctr_rx (ENDP0); + handle_out0 (); + } + } + + if (dev_p->state == STALLED) + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL); + } + else + { + /* Decode and service non control endpoints interrupt */ + /* process related endpoint register */ + ep_value = st103_get_epreg (ep_index); + + if ((ep_value & EP_CTR_RX) != 0) + { + st103_ep_clear_ctr_rx (ep_index); + (*ep_intr_handler_OUT[ep_index-1]) (); + } + + if ((ep_value & EP_CTR_TX) != 0) + { + st103_ep_clear_ctr_tx (ep_index); + (*ep_intr_handler_IN[ep_index-1]) (); + } + } + } +} + +static struct CONTROL_INFO Control_Info; +static struct DEVICE_INFO Device_Info; +static struct DATA_INFO Data_Info; + +void usb_lld_reset (void) +{ + st103_set_btable (); + st103_set_daddr (0); +} + +void usb_lld_init (void) +{ RCC->APB1ENR |= RCC_APB1ENR_USBEN; NVICEnableVector (USB_LP_CAN1_RX0_IRQn, CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); @@ -26,9 +1016,138 @@ void usb_lld_init (void) { */ RCC->APB1RSTR = RCC_APB1RSTR_USBRST; RCC->APB1RSTR = 0; + + dev_p = &Device_Info; + ctrl_p = &Control_Info; + data_p = &Data_Info; + dev_p->state = IN_DATA; + method_p = &Device_Method; + + method_p->init(); + + /* Reset USB */ + st103_set_cntr (CNTR_FRES); + st103_set_cntr (0); + + /* Clear Interrupt Status Register, and enable interrupt for USB */ + st103_set_istr (0); + st103_set_cntr (CNTR_CTRM | CNTR_RESETM); } -void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n) +void usb_lld_txcpy (const void *src, + int ep_num, int offset, size_t len) +{ + usb_lld_to_pmabuf (src, st103_get_tx_addr (ep_num) + offset, len); +} + +void usb_lld_write (uint8_t ep_num, const void *buf, size_t len) +{ + usb_lld_to_pmabuf (buf, st103_get_tx_addr (ep_num), len); + st103_set_tx_count (ep_num, len); + st103_ep_set_tx_status (ep_num, EP_TX_VALID); +} + +void usb_lld_rxcpy (uint8_t *dst, + int ep_num, int offset, size_t len) +{ + usb_lld_from_pmabuf (dst, st103_get_rx_addr (ep_num) + offset, len); +} + +void usb_lld_tx_enable (int ep_num, size_t len) +{ + st103_set_tx_count (ep_num, len); + st103_ep_set_tx_status (ep_num, EP_TX_VALID); +} + +int usb_lld_tx_data_len (int ep_num) +{ + return st103_get_tx_count (ep_num); +} + +int usb_lld_rx_data_len (int ep_num) +{ + return st103_get_rx_count (ep_num); +} + +void usb_lld_stall_tx (int ep_num) +{ + st103_ep_set_tx_status (ep_num, EP_TX_STALL); +} + +void usb_lld_stall_rx (int ep_num) +{ + st103_ep_set_rx_status (ep_num, EP_RX_STALL); +} + +void usb_lld_rx_enable (int ep_num) +{ + st103_ep_set_rx_status (ep_num, EP_RX_VALID); +} + +void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind, + int ep_rx_addr, int ep_tx_addr, + int ep_rx_buf_size) +{ + uint16_t epreg_value = st103_get_epreg (ep_num); + uint16_t ep_rxtx_status = 0; /* Both disabled */ + + /* Clear: Write 1 if 1: EP_DTOG_RX, EP_DTOG_TX */ + /* Set: Write: EP_T_FIELD, EP_KIND, EPADDR_FIELD */ + /* Set: Toggle: EPRX_STAT, EPTX_STAT */ + epreg_value &= (EPRX_STAT | EP_SETUP | EPTX_STAT | EP_DTOG_RX | EP_DTOG_TX); +#if USB_KEEP_CORRECT_TRANSFER_FLAGS + /* Keep: Write 1: EP_CTR_RX, EP_CTR_TX */ + epreg_value |= (EP_CTR_RX|EP_CTR_TX); +#else + /* Clear: Write 0: EP_CTR_RX, EP_CTR_TX */ +#endif + epreg_value |= ep_type; + epreg_value |= ep_kind; + epreg_value |= ep_num; + + if (ep_rx_addr) + { + ep_rxtx_status |= EP_RX_VALID; + st103_set_rx_addr (ep_num, ep_rx_addr); + st103_set_rx_buf_size (ep_num, ep_rx_buf_size); + } + + if (ep_tx_addr) + { + ep_rxtx_status |= EP_TX_NAK; + st103_set_tx_addr (ep_num, ep_tx_addr); + } + + epreg_value ^= (EPRX_DTOG1 & ep_rxtx_status); + epreg_value ^= (EPRX_DTOG2 & ep_rxtx_status); + epreg_value ^= (EPTX_DTOG1 & ep_rxtx_status); + epreg_value ^= (EPTX_DTOG2 & ep_rxtx_status); + + st103_set_epreg (ep_num, epreg_value); +} + +void usb_lld_set_configuration (uint8_t config) +{ + dev_p->current_configuration = config; +} + +uint8_t usb_lld_current_configuration (void) +{ + return dev_p->current_configuration; +} + +void usb_lld_set_feature (uint8_t feature) +{ + dev_p->current_feature = feature; +} + +void usb_lld_set_data_to_send (const void *p, size_t len) +{ + data_p->addr = (uint8_t *)p; + data_p->len = len; +} + +void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n) { const uint8_t *s = (const uint8_t *)src; uint16_t *p; @@ -37,9 +1156,9 @@ void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n) if (n == 0) return; - if ((wPMABufAddr & 1)) + if ((addr & 1)) { - p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2); + p = (uint16_t *)(PMA_ADDR + (addr - 1) * 2); w = *p; w = (w & 0xff) | (*s++) << 8; *p = w; @@ -47,7 +1166,7 @@ void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n) n--; } else - p = (uint16_t *)(PMAAddr + wPMABufAddr * 2); + p = (uint16_t *)(PMA_ADDR + addr * 2); while (n >= 2) { @@ -65,7 +1184,7 @@ void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n) } } -void usb_lld_from_pmabuf (void *dst, uint16_t wPMABufAddr, size_t n) +void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n) { uint8_t *d = (uint8_t *)dst; uint16_t *p; @@ -74,16 +1193,16 @@ void usb_lld_from_pmabuf (void *dst, uint16_t wPMABufAddr, size_t n) if (n == 0) return; - if ((wPMABufAddr & 1)) + if ((addr & 1)) { - p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2); + p = (uint16_t *)(PMA_ADDR + (addr - 1) * 2); w = *p; *d++ = (w >> 8); p += 2; n--; } else - p = (uint16_t *)(PMAAddr + wPMABufAddr * 2); + p = (uint16_t *)(PMA_ADDR + addr * 2); while (n >= 2) { diff --git a/src/usb_lld.h b/src/usb_lld.h index a74dcd7..f27d017 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -1,55 +1,143 @@ +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 + +#define STANDARD_ENDPOINT_DESC_SIZE 0x09 + +/* endpoints enumeration */ +#define ENDP0 ((uint8_t)0) +#define ENDP1 ((uint8_t)1) +#define ENDP2 ((uint8_t)2) +#define ENDP3 ((uint8_t)3) +#define ENDP4 ((uint8_t)4) +#define ENDP5 ((uint8_t)5) +#define ENDP6 ((uint8_t)6) +#define ENDP7 ((uint8_t)7) + +/* EP_TYPE[1:0] EndPoint TYPE */ +#define EP_BULK (0x0000) /* EndPoint BULK */ +#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ +#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ + +enum RECIPIENT_TYPE +{ + DEVICE_RECIPIENT, /* Recipient device */ + INTERFACE_RECIPIENT, /* Recipient interface */ + ENDPOINT_RECIPIENT, /* Recipient endpoint */ + OTHER_RECIPIENT +}; + +enum DESCRIPTOR_TYPE +{ + DEVICE_DESCRIPTOR = 1, + CONFIG_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR +}; + +#define REQUEST_TYPE 0x60 /* Mask to get request type */ +#define STANDARD_REQUEST 0x00 /* Standard request */ +#define CLASS_REQUEST 0x20 /* Class request */ +#define VENDOR_REQUEST 0x40 /* Vendor request */ + +struct Descriptor +{ + const uint8_t *Descriptor; + uint16_t Descriptor_Size; +}; + +enum +{ + USB_UNSUPPORT = 0, + USB_SUCCESS = 1, +}; + +struct usb_device_method +{ + void (*init) (void); + void (*reset) (void); + void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index); + int (*setup_with_nodata) (uint8_t rcp, uint8_t req_no, uint16_t index); + int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value); + int (*event) (uint8_t event_type, uint16_t value); + int (*interface) (uint8_t cmd, uint16_t interface, uint16_t value); +}; + +enum { + USB_EVENT_RESET, + USB_EVENT_ADDRESS, + USB_EVENT_CONFIG, + USB_EVENT_SUSPEND, + USB_EVENT_WAKEUP, + USB_EVENT_STALL, +}; + +enum { + USB_SET_INTERFACE, + USB_GET_INTERFACE, + USB_QUERY_INTERFACE, +}; + +extern void USB_Cable_Config (int NewState); + +extern const struct usb_device_method Device_Method; + +extern const struct Descriptor Device_Descriptor; +extern const struct Descriptor Config_Descriptor; +extern const struct Descriptor String_Descriptors[]; + +enum DEVICE_STATE +{ + UNCONNECTED, + ATTACHED, + POWERED, + SUSPENDED, + ADDRESSED, + CONFIGURED +}; + +extern uint32_t bDeviceState; + #define STM32_USB_IRQ_PRIORITY 11 -void usb_lld_init (void); + +extern void usb_lld_init (void); extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n); + extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n); -extern inline void usb_lld_stall_tx (int ep_num) -{ - SetEPTxStatus (ep_num, EP_TX_STALL); -} +extern void usb_lld_stall_tx (int ep_num); -extern inline void usb_lld_stall_rx (int ep_num) -{ - SetEPRxStatus (ep_num, EP_RX_STALL); -} +extern void usb_lld_stall_rx (int ep_num); -extern inline int usb_lld_tx_data_len (int ep_num) -{ - return GetEPTxCount (ep_num); -} +extern int usb_lld_tx_data_len (int ep_num); -extern inline void usb_lld_txcpy (const void *src, - int ep_num, int offset, size_t len) -{ - usb_lld_to_pmabuf (src, GetEPTxAddr (ep_num) + offset, len); -} +extern void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len); -extern inline void usb_lld_tx_enable (int ep_num, size_t len) -{ - SetEPTxCount (ep_num, len); - SetEPTxValid (ep_num); -} +extern void usb_lld_tx_enable (int ep_num, size_t len); -extern inline void usb_lld_write (uint8_t ep_num, const void *buf, size_t len) -{ - usb_lld_to_pmabuf (buf, GetEPTxAddr (ep_num), len); - SetEPTxCount (ep_num, len); - SetEPTxValid (ep_num); -} +extern void usb_lld_write (uint8_t ep_num, const void *buf, size_t len); -extern inline void usb_lld_rx_enable (int ep_num) -{ - SetEPRxValid (ep_num); -} +extern void usb_lld_rx_enable (int ep_num); -extern inline int usb_lld_rx_data_len (int ep_num) -{ - return GetEPRxCount (ep_num); -} +extern int usb_lld_rx_data_len (int ep_num); -extern inline void usb_lld_rxcpy (uint8_t *dst, - int ep_num, int offset, size_t len) -{ - usb_lld_from_pmabuf (dst, GetEPRxAddr (ep_num) + offset, len); -} +extern void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len); + +extern void usb_lld_reset (void); + +extern void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind, + int ep_rx_addr, int ep_tx_addr, + int ep_rx_memory_size); + +extern void usb_lld_set_configuration (uint8_t config); + +extern uint8_t usb_lld_current_configuration (void); + +extern void usb_lld_set_feature (uint8_t feature); + +extern void usb_lld_set_data_to_send (const void *p, size_t len); diff --git a/src/usb_msc.c b/src/usb_msc.c index 4147ec6..5cfec84 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -21,8 +21,6 @@ * */ -#include "usb_lib.h" - #include "config.h" #include "ch.h" #include "gnuk.h" diff --git a/src/usb_prop.c b/src/usb_prop.c index 56c0cb3..b5b03df 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -1,7 +1,7 @@ /* - * usb_prop.c - glue/interface code between Gnuk and USB-FS-Device_Lib + * usb_prop.c - interface code between Gnuk and USB * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -25,15 +25,49 @@ #define GNUK_MAX_PACKET_SIZE 64 #include "config.h" -#include "usb_lib.h" +#include "ch.h" +#include "usb_lld.h" #include "usb_conf.h" -#include "usb_prop.h" -#include "usb_desc.h" -#include "usb_pwr.h" -#include "hw_config.h" #ifdef ENABLE_VIRTUAL_COM_PORT -#include "usb-cdc-vport.c" +#include "usb-cdc.h" + +struct line_coding +{ + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +}; + +static const struct line_coding line_coding = { + 115200, /* baud rate: 115200 */ + 0x00, /* stop bits: 1 */ + 0x00, /* parity: none */ + 0x08 /* bits: 8 */ +}; + +static void +Virtual_Com_Port_Data_Setup (uint8_t RequestNo) +{ + if (RequestNo != USB_CDC_REQ_GET_LINE_CODING) + return USB_UNSUPPORT; + + /* RequestNo == USB_CDC_REQ_SET_LINE_CODING is not supported */ + + usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); + return USB_SUCCESS; +} + +static int +Virtual_Com_Port_NoData_Setup (uint8_t RequestNo) +{ + if (RequestNo == USB_CDC_REQ_SET_CONTROL_LINE_STATE) + /* Do nothing and success */ + return USB_SUCCESS; + + return USB_UNSUPPORT; +} #endif #ifdef PINPAD_DND_SUPPORT @@ -41,215 +75,61 @@ #endif -static void -SetEPRxCount_allocated_size (uint8_t bEpNum, uint16_t wCount) -{ /* Assume wCount is even */ - uint32_t *pdwReg = _pEPRxCount (bEpNum); - uint16_t value; - - if (wCount <= 62) - value = (wCount & 0x3e) << 9; - else - value = 0x8000 | (((wCount >> 5) - 1) << 10); - - *pdwReg = (uint32_t)value; -} +uint32_t bDeviceState = UNCONNECTED; /* USB device status */ static void gnuk_device_init (void) { - pInformation->Current_Configuration = 0; - - /* Connect the device */ - PowerOn (); - - /* Perform basic device initialization operations */ - _SetISTR (0); - wInterrupt_Mask = IMR_MSK; - _SetCNTR (wInterrupt_Mask); - + usb_lld_set_configuration (0); + USB_Cable_Config (1); bDeviceState = UNCONNECTED; } static void -gnuk_device_reset (void) +gnuk_setup_endpoints_for_interface (uint16_t interface) { - /* Set DEVICE as not configured */ - pInformation->Current_Configuration = 0; - - /* Current Feature initialization */ - pInformation->Current_Feature = Config_Descriptor.Descriptor[7]; - - /* Set DEVICE with the default Interface*/ - pInformation->Current_Interface = 0; - - SetBTABLE (BTABLE_ADDRESS); - - /* Initialize Endpoint 0 */ - SetEPType (ENDP0, EP_CONTROL); - SetEPTxStatus (ENDP0, EP_TX_STALL); - SetEPRxAddr (ENDP0, ENDP0_RXADDR); - SetEPTxAddr (ENDP0, ENDP0_TXADDR); - Clear_Status_Out (ENDP0); - SetEPRxCount_allocated_size (ENDP0, GNUK_MAX_PACKET_SIZE); - SetEPRxValid (ENDP0); - - /* Initialize Endpoint 1 */ - SetEPType (ENDP1, EP_BULK); - SetEPTxAddr (ENDP1, ENDP1_TXADDR); - SetEPTxStatus (ENDP1, EP_TX_NAK); - SetEPRxStatus (ENDP1, EP_RX_DIS); - - /* Initialize Endpoint 2 */ - SetEPType (ENDP2, EP_BULK); - SetEPRxAddr (ENDP2, ENDP2_RXADDR); - SetEPRxCount_allocated_size (ENDP2, GNUK_MAX_PACKET_SIZE); - SetEPRxStatus (ENDP2, EP_RX_VALID); - SetEPTxStatus (ENDP2, EP_TX_DIS); - -#ifdef ENABLE_VIRTUAL_COM_PORT - /* Initialize Endpoint 3 */ - SetEPType (ENDP3, EP_BULK); - SetEPTxAddr (ENDP3, ENDP3_TXADDR); - SetEPTxStatus (ENDP3, EP_TX_NAK); - SetEPRxStatus (ENDP3, EP_RX_DIS); - - /* Initialize Endpoint 4 */ - SetEPType (ENDP4, EP_INTERRUPT); - SetEPTxAddr (ENDP4, ENDP4_TXADDR); - SetEPTxStatus (ENDP4, EP_TX_NAK); - SetEPRxStatus (ENDP4, EP_RX_DIS); - - /* Initialize Endpoint 5 */ - SetEPType (ENDP5, EP_BULK); - SetEPRxAddr (ENDP5, ENDP5_RXADDR); - SetEPRxCount_allocated_size (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE); - SetEPRxStatus (ENDP5, EP_RX_VALID); - SetEPTxStatus (ENDP5, EP_TX_DIS); -#endif - -#ifdef PINPAD_DND_SUPPORT - /* Initialize Endpoint 6 */ - SetEPType (ENDP6, EP_BULK); - SetEPTxAddr (ENDP6, ENDP6_TXADDR); - SetEPTxStatus (ENDP6, EP_TX_NAK); - SetEPRxStatus (ENDP6, EP_RX_DIS); - - /* Initialize Endpoint 7 */ - SetEPType (ENDP7, EP_BULK); - SetEPRxAddr (ENDP7, ENDP7_RXADDR); - SetEPRxCount_allocated_size (ENDP7, 64); - SetEPRxStatus (ENDP7, EP_RX_STALL); - SetEPTxStatus (ENDP7, EP_TX_DIS); -#endif - - /* Set this device to response on default address */ - SetDeviceAddress (0); - - bDeviceState = ATTACHED; -} - -static void -gnuk_device_SetConfiguration (void) -{ - DEVICE_INFO *pInfo = &Device_Info; - - if (pInfo->Current_Configuration != 0) - { /* Device 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 -gnuk_device_SetInterface (void) -{ - uint16_t intf = pInformation->USBwIndex0; - - /* alternateSetting: pInformation->USBwValue0 should be 0 */ - - if (intf == 0) + if (interface == 0) { - ClearDTOG_RX (ENDP2); - ClearDTOG_TX (ENDP1); + /* Initialize Endpoint 1 */ + usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0); + + /* Initialize Endpoint 2 */ + usb_lld_setup_endpoint (ENDP2, EP_BULK, 0, ENDP2_RXADDR, 0, + GNUK_MAX_PACKET_SIZE); } #ifdef ENABLE_VIRTUAL_COM_PORT - else if (intf == 1) + else if (interface == 1) { - ClearDTOG_TX (ENDP4); + /* Initialize Endpoint 4 */ + usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0); } - else if (intf == 2) + else if (interface == 2) { - ClearDTOG_RX (ENDP5); - ClearDTOG_TX (ENDP3); + /* Initialize Endpoint 3 */ + usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0); + + /* Initialize Endpoint 5 */ + usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0, + VIRTUAL_COM_PORT_DATA_SIZE); } #endif #ifdef PINPAD_DND_SUPPORT # ifdef ENABLE_VIRTUAL_COM_PORT - else if (intf == 3) - { - ClearDTOG_TX (ENDP6); - ClearDTOG_RX (ENDP7); - } + else if (interface == 3) # else - else if (intf == 1) - { - ClearDTOG_TX (ENDP6); - ClearDTOG_RX (ENDP7); - } + else if (interface == 1) # endif + { + /* Initialize Endpoint 6 */ + usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, 0, ENDP6_TXADDR, 0); + + /* Initialize Endpoint 7 */ + usb_lld_setup_endpoint (ENDP7, EP_BULK, 0, ENDP7_RXADDR, 0, 64); + usb_lld_stall_rx (ENDP7); + } #endif } -static void -gnuk_device_SetDeviceAddress (void) -{ - bDeviceState = ADDRESSED; -} - -/* IN from port 0 */ -static void -gnuk_device_Status_In (void) -{ -} - -/* OUT to port 0 */ -static void -gnuk_device_Status_Out (void) -{ -} - -static uint8_t * -gnuk_device_GetDeviceDescriptor (uint16_t Length) -{ - return Standard_GetDescriptorData (Length, - (PONE_DESCRIPTOR)&Device_Descriptor); -} - -static uint8_t * -gnuk_device_GetConfigDescriptor (uint16_t Length) -{ - return Standard_GetDescriptorData (Length, - (PONE_DESCRIPTOR)&Config_Descriptor); -} - -static uint8_t * -gnuk_device_GetStringDescriptor (uint16_t Length) -{ - uint8_t wValue0 = pInformation->USBwValue0; - - if (wValue0 >= (sizeof (String_Descriptor) / sizeof (ONE_DESCRIPTOR))) - return NULL; - else - return - Standard_GetDescriptorData (Length, - (PONE_DESCRIPTOR)&String_Descriptor[wValue0]); -} - #ifdef PINPAD_DND_SUPPORT # ifdef ENABLE_VIRTUAL_COM_PORT # define NUM_INTERFACES 4 /* two for CDC, one for CCID, and MSC */ @@ -264,15 +144,28 @@ gnuk_device_GetStringDescriptor (uint16_t Length) # endif #endif -static RESULT -gnuk_device_Get_Interface_Setting (uint8_t Interface, uint8_t AlternateSetting) +static void +gnuk_device_reset (void) { - if (AlternateSetting > 0) /* Any interface, we have no alternate */ - return USB_UNSUPPORT; - else if (Interface > NUM_INTERFACES) - return USB_UNSUPPORT; + int i; - return USB_SUCCESS; + /* Set DEVICE as not configured */ + usb_lld_set_configuration (0); + + /* Current Feature initialization */ + usb_lld_set_feature (Config_Descriptor.Descriptor[7]); + + usb_lld_reset (); + + /* Initialize Endpoint 0 */ + usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, + ENDP0_RXADDR, ENDP0_TXADDR, + GNUK_MAX_PACKET_SIZE); + + for (i = 0; i < NUM_INTERFACES; i++) + gnuk_setup_endpoints_for_interface (i); + + bDeviceState = ATTACHED; } #define USB_CCID_REQ_ABORT 0x01 @@ -280,104 +173,48 @@ gnuk_device_Get_Interface_Setting (uint8_t Interface, uint8_t AlternateSetting) #define USB_CCID_REQ_GET_DATA_RATES 0x03 static const uint8_t freq_table[] = { 0xf3, 0x0d, 0, 0, }; /* dwDefaultClock */ -static uint8_t * -gnuk_clock_frequencies (uint16_t len) -{ - if (len == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof (freq_table); - return NULL; - } - - return (uint8_t *)freq_table; -} static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */ -static uint8_t * -gnuk_data_rates (uint16_t len) -{ - if (len == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof (data_rate_table); - return NULL; - } - - return (uint8_t *)data_rate_table; -} #if defined(PINPAD_DND_SUPPORT) static const uint8_t lun_table[] = { 0, 0, 0, 0, }; -static uint8_t * -msc_lun_info (uint16_t len) -{ - if (len == 0) - { - pInformation->Ctrl_Info.Usb_wLength = sizeof (lun_table); - return NULL; - } - - return (uint8_t *)lun_table; -} #endif -static RESULT -gnuk_setup_with_data (uint8_t RequestNo) +static void +gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index) { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ - if (pInformation->USBwIndex0 == 0) + if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + if (index == 0) { if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) - { - pInformation->Ctrl_Info.CopyData = gnuk_clock_frequencies; - pInformation->Ctrl_Info.Usb_wOffset = 0; - gnuk_clock_frequencies (0); - return USB_SUCCESS; - } + usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES) - { - pInformation->Ctrl_Info.CopyData = gnuk_data_rates; - pInformation->Ctrl_Info.Usb_wOffset = 0; - gnuk_data_rates (0); - return USB_SUCCESS; - } - else - return USB_UNSUPPORT; + usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table)); } #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 1) - return Virtual_Com_Port_Data_Setup (RequestNo); - else if (pInformation->USBwIndex0 == 3) + else if (index == 1) + Virtual_Com_Port_Data_Setup (RequestNo); + else if (index == 3) # else - else if (pInformation->USBwIndex0 == 1) + else if (index == 1) # endif { if (RequestNo == MSC_GET_MAX_LUN_COMMAND) - { - pInformation->Ctrl_Info.CopyData = msc_lun_info; - pInformation->Ctrl_Info.Usb_wOffset = 0; - msc_lun_info (0); - return USB_SUCCESS; - } - else - return USB_UNSUPPORT; + usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); } #elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 1) - return Virtual_Com_Port_Data_Setup (RequestNo); + else if (index == 1) + Virtual_Com_Port_Data_Setup (RequestNo); #endif - else - return USB_UNSUPPORT; - else - return USB_UNSUPPORT; } -static RESULT -gnuk_setup_with_nodata (uint8_t RequestNo) +static int +gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) { - if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ - if (pInformation->USBwIndex0 == 0) + if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + if (index == 0) { if (RequestNo == USB_CCID_REQ_ABORT) /* wValue: bSeq, bSlot */ @@ -388,11 +225,11 @@ gnuk_setup_with_nodata (uint8_t RequestNo) } #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 1) + else if (index == 1) return Virtual_Com_Port_NoData_Setup (RequestNo); - else if (pInformation->USBwIndex0 == 3) + else if (index == 3) # else - else if (pInformation->USBwIndex0 == 1) + else if (index == 1) # endif { if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND) @@ -404,7 +241,7 @@ gnuk_setup_with_nodata (uint8_t RequestNo) return USB_UNSUPPORT; } #elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (pInformation->USBwIndex0 == 1) + else if (index == 1) return Virtual_Com_Port_NoData_Setup (RequestNo); #endif else @@ -413,38 +250,117 @@ gnuk_setup_with_nodata (uint8_t RequestNo) return USB_UNSUPPORT; } +static int +gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) +{ + (void)index; + if (desc_type == DEVICE_DESCRIPTOR) + { + usb_lld_set_data_to_send (Device_Descriptor.Descriptor, + Device_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == CONFIG_DESCRIPTOR) + { + usb_lld_set_data_to_send (Config_Descriptor.Descriptor, + Config_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == STRING_DESCRIPTOR) + { + uint8_t desc_index = value & 0xff; + + if (desc_index < NUM_STRING_DESC) + { + usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor, + String_Descriptors[desc_index].Descriptor_Size); + return USB_SUCCESS; + } + } + + return USB_UNSUPPORT; +} + +static int gnuk_usb_event (uint8_t event_type, uint16_t value) +{ + switch (event_type) + { + case USB_EVENT_RESET: + break; + case USB_EVENT_ADDRESS: + bDeviceState = ADDRESSED; + break; + case USB_EVENT_CONFIG: + if (usb_lld_current_configuration () == 0) + { + int i; + extern void *main_thread; +#define LED_STATUS_MODE (8) + + if (value != 1) + return USB_UNSUPPORT; + + usb_lld_set_configuration (value); + for (i = 0; i < NUM_INTERFACES; i++) + gnuk_setup_endpoints_for_interface (i); + bDeviceState = CONFIGURED; + chEvtSignalI (main_thread, LED_STATUS_MODE); + return USB_SUCCESS; + } + else + { + if (value != 0) + return USB_UNSUPPORT; + + usb_lld_set_configuration (0); + // Disable all endpoints??? + bDeviceState = ADDRESSED; + } + default: + break; + } + + return USB_UNSUPPORT; +} + +static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt) +{ + static uint8_t zero = 0; + + if (interface >= NUM_INTERFACES) + return USB_UNSUPPORT; + + switch (cmd) + { + case USB_SET_INTERFACE: + if (alt != 0) + return USB_UNSUPPORT; + else + { + gnuk_setup_endpoints_for_interface (interface); + return USB_SUCCESS; + } + + case USB_GET_INTERFACE: + usb_lld_set_data_to_send (&zero, 1); + return USB_SUCCESS; + + default: + case USB_QUERY_INTERFACE: + return USB_SUCCESS; + } +} + /* * Interface to USB core */ -const DEVICE_PROP Device_Property = { +const struct usb_device_method Device_Method = { gnuk_device_init, gnuk_device_reset, - gnuk_device_Status_In, - gnuk_device_Status_Out, gnuk_setup_with_data, gnuk_setup_with_nodata, - gnuk_device_Get_Interface_Setting, - gnuk_device_GetDeviceDescriptor, - gnuk_device_GetConfigDescriptor, - gnuk_device_GetStringDescriptor, - 0, - GNUK_MAX_PACKET_SIZE -}; - -const DEVICE Device_Table = { - EP_NUM, - 1 -}; - -const USER_STANDARD_REQUESTS User_Standard_Requests = { - NOP_Process, /* GetConfiguration */ - gnuk_device_SetConfiguration, - NOP_Process, /* GetInterface */ - gnuk_device_SetInterface, - NOP_Process, /* GetStatus */ - NOP_Process, /* ClearFeature */ - NOP_Process, /* SetEndPointFeature */ - NOP_Process, /* SetDeviceFeature */ - gnuk_device_SetDeviceAddress + gnuk_get_descriptor, + gnuk_usb_event, + gnuk_interface, }; diff --git a/src/usb_prop.h b/src/usb_prop.h deleted file mode 100644 index b39196a..0000000 --- a/src/usb_prop.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __usb_prop_H -#define __usb_prop_H - -extern const ONE_DESCRIPTOR Device_Descriptor; -extern const ONE_DESCRIPTOR Config_Descriptor; -extern const ONE_DESCRIPTOR String_Descriptor[4]; -#endif /* __usb_prop_H */ diff --git a/src/vcomport.mk b/src/vcomport.mk deleted file mode 100644 index b545ae8..0000000 --- a/src/vcomport.mk +++ /dev/null @@ -1,5 +0,0 @@ -VCOMDIR = ../Virtual_COM_Port -VCOMSRC= $(VCOMDIR)/usb_istr.c $(VCOMDIR)/usb_pwr.c -ifneq ($(ENABLE_VCOMPORT),) -VCOMSRC += usb_endp.c -endif From ab8a3eed290a90c5d4cbf67e1f630ce70d2d8312 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 May 2012 09:23:57 +0900 Subject: [PATCH 065/300] configure: mention FST_01 --- ChangeLog | 4 ++++ src/configure | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 239f3c6..a84ad3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-05-11 Niibe Yutaka + + * src/configure ($help): Add FST_01. + 2012-05-10 Niibe Yutaka * STM32_USB-FS-Device_Driver, Virtual_COM_Port: Remove. diff --git a/src/configure b/src/configure index d357cdb..fd7049a 100755 --- a/src/configure +++ b/src/configure @@ -3,7 +3,7 @@ # # This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka # -# Copyright (C) 2010, 2011 Free Software Initiative of Japan +# Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan # # This file is a part of Gnuk, a GnuPG USB Token implementation. # Gnuk is free software: you can redistribute it and/or modify it @@ -84,6 +84,7 @@ Configuration: STBEE_MINI STM8S_DISCOVERY STBEE + FST_01 --enable-debug debug with virtual COM port [no] --enable-pinpad={dnd,cir,dial} PIN entry support [no] From a0a1b8177bbd8b88aefe21dc73e3270daa9f0e11 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 May 2012 09:28:04 +0900 Subject: [PATCH 066/300] Fixes for New USB stack --- ChangeLog | 10 ++++++++++ GNUK_USB_DEVICE_ID | 2 ++ src/main.c | 1 + src/usb-cdc.h | 3 +++ src/usb_desc.c | 1 + src/usb_endp.c | 1 + src/usb_prop.c | 47 +++++++++++++++++++++++----------------------- 7 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 GNUK_USB_DEVICE_ID diff --git a/ChangeLog b/ChangeLog index a84ad3a..f88fe2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2012-05-11 Niibe Yutaka + * src/usb_prop.c (vcom_port_setup_with_nodata) Rename. + (vcom_port_data_setup): Rename and fix return value. + + * src/usb-cdc.h (VIRTUAL_COM_PORT_DATA_SIZE) + (VIRTUAL_COM_PORT_INT_SIZE): New. + + * src/main.c (#include): Add usb-cdc.h. + * src/usb_desc.c (#include): Add usb-cdc.h. + * src/usb_endp.c (#include): Add usb_lld.h. + * src/configure ($help): Add FST_01. 2012-05-10 Niibe Yutaka diff --git a/GNUK_USB_DEVICE_ID b/GNUK_USB_DEVICE_ID new file mode 100644 index 0000000..33f5407 --- /dev/null +++ b/GNUK_USB_DEVICE_ID @@ -0,0 +1,2 @@ +# VID:PID bcdDev Product_STRING Vender_STRING +234b:0000 0200 FSIJ USB Token Free Software Initiative of Japan diff --git a/src/main.c b/src/main.c index b838409..adf3c69 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,7 @@ #include "ch.h" #include "gnuk.h" #include "usb_lld.h" +#include "usb-cdc.h" #ifdef DEBUG struct stdout { diff --git a/src/usb-cdc.h b/src/usb-cdc.h index 93fcd4e..d004c79 100644 --- a/src/usb-cdc.h +++ b/src/usb-cdc.h @@ -5,3 +5,6 @@ #define USB_CDC_REQ_GET_LINE_CODING 0x21 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 #define USB_CDC_REQ_SEND_BREAK 0x23 + +#define VIRTUAL_COM_PORT_DATA_SIZE 16 +#define VIRTUAL_COM_PORT_INT_SIZE 8 diff --git a/src/usb_desc.c b/src/usb_desc.c index caa7506..e814695 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -6,6 +6,7 @@ #include "ch.h" #include "usb_lld.h" #include "usb_conf.h" +#include "usb-cdc.h" #define USB_ICC_INTERFACE_CLASS 0x0B #define USB_ICC_INTERFACE_SUBCLASS 0x00 diff --git a/src/usb_endp.c b/src/usb_endp.c index 0870caa..ac60fe7 100644 --- a/src/usb_endp.c +++ b/src/usb_endp.c @@ -5,6 +5,7 @@ #include "config.h" #include "ch.h" #include "gnuk.h" +#include "usb_lld.h" void EP3_IN_Callback (void) diff --git a/src/usb_prop.c b/src/usb_prop.c index b5b03df..62a61a2 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -48,19 +48,18 @@ static const struct line_coding line_coding = { }; static void -Virtual_Com_Port_Data_Setup (uint8_t RequestNo) +vcom_port_data_setup (uint8_t RequestNo) { if (RequestNo != USB_CDC_REQ_GET_LINE_CODING) - return USB_UNSUPPORT; + return; /* RequestNo == USB_CDC_REQ_SET_LINE_CODING is not supported */ usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); - return USB_SUCCESS; } static int -Virtual_Com_Port_NoData_Setup (uint8_t RequestNo) +vcom_port_setup_with_nodata (uint8_t RequestNo) { if (RequestNo == USB_CDC_REQ_SET_CONTROL_LINE_STATE) /* Do nothing and success */ @@ -184,29 +183,31 @@ static void gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index) { if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ - if (index == 0) - { - if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) - usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); - else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES) - usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table)); - } + { + if (index == 0) + { + if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) + usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); + else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES) + usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table)); + } #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) - else if (index == 1) - Virtual_Com_Port_Data_Setup (RequestNo); - else if (index == 3) + else if (index == 1) + vcom_port_data_setup (RequestNo); + else if (index == 3) # else - else if (index == 1) + else if (index == 1) # endif - { - if (RequestNo == MSC_GET_MAX_LUN_COMMAND) - usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); - } + { + if (RequestNo == MSC_GET_MAX_LUN_COMMAND) + usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); + } #elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (index == 1) - Virtual_Com_Port_Data_Setup (RequestNo); + else if (index == 1) + vcom_port_data_setup (RequestNo); #endif + } } @@ -226,7 +227,7 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) #if defined(PINPAD_DND_SUPPORT) # if defined(ENABLE_VIRTUAL_COM_PORT) else if (index == 1) - return Virtual_Com_Port_NoData_Setup (RequestNo); + return vcom_port_setup_with_nodata (RequestNo); else if (index == 3) # else else if (index == 1) @@ -242,7 +243,7 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) } #elif defined(ENABLE_VIRTUAL_COM_PORT) else if (index == 1) - return Virtual_Com_Port_NoData_Setup (RequestNo); + return vcom_port_setup_with_nodata (RequestNo); #endif else return USB_UNSUPPORT; From ac28ee171cf60f284b32bb27ce1e0eb003ca0963 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 May 2012 14:09:14 +0900 Subject: [PATCH 067/300] configure option --vidpid to specify USB device ID --- .gitignore | 2 +- ChangeLog | 11 +++++++++++ GNUK_USB_DEVICE_ID | 1 + NEWS | 4 ++++ README | 46 +++++++++++++++++++++++++++++++++++++++++++++- src/Makefile.in | 2 +- src/configure | 42 ++++++++++++++++++++++++++++++++++++++++-- src/main.c | 2 +- src/usb_desc.c | 26 ++++---------------------- 9 files changed, 108 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 4029f69..269bd36 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ src/gnuk.dmp src/gnuk.elf src/gnuk.hex src/gnuk.map -src/random_bits +src/*.inc diff --git a/ChangeLog b/ChangeLog index f88fe2d..5e36e1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2012-05-11 Niibe Yutaka + * src/configure (--vidpid): New mandatory option. + + * GNUK_USB_DEVICE_ID: New file. + + * src/usb_desc.c (gnukDeviceDescriptor): Include + usb-vid-pid-ver.c.inc. + (gnukStringVendor, gnukStringProduct): Remove. It's in the + file, usb-string-vender-product.c.inc. + + * src/Makefile.in (distclean): Delete *.inc. + * src/usb_prop.c (vcom_port_setup_with_nodata) Rename. (vcom_port_data_setup): Rename and fix return value. diff --git a/GNUK_USB_DEVICE_ID b/GNUK_USB_DEVICE_ID index 33f5407..839863e 100644 --- a/GNUK_USB_DEVICE_ID +++ b/GNUK_USB_DEVICE_ID @@ -1,2 +1,3 @@ # VID:PID bcdDev Product_STRING Vender_STRING 234b:0000 0200 FSIJ USB Token Free Software Initiative of Japan +########## ## ########## ################# diff --git a/NEWS b/NEWS index 8c055cd..606c98f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,10 @@ Gnuk NEWS - User visible changes Released 2012-05-XX, by NIIBE Yutaka +** New mandatory option '--vidpid' for configure +You must specify USB vendor ID and product ID for Gnuk. +The file GNUK_USB_DEVICE_ID lists valid USB device IDs. + ** New USB stack Gnuk used to use USB stack of USB-FS-Device_Lib by ST. Now, it has original implementation. Hopefully, size and quality are improved. diff --git a/README b/README index 227bd52..d010385 100644 --- a/README +++ b/README @@ -226,6 +226,47 @@ Gnuk is distributed with external source code. Cortex-M3. +USB vendor ID and product ID (USB device ID) +============================================ + +When you have a vender ID and assign a product ID for Gnuk, please +contact Niibe, so that it is listed to the file GNUK_USB_DEVICE_ID. + +When you modify Gnuk and install it to device, you should replace +"FSIJ" in the string gnukStringSerial to yours, so that it can be +checked as device serial number. + +FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices +with Gnuk under one of following conditions: + + * For everyone for experiment purpose: + + - You must not distribute a binary with FSIJ's USB device ID, but + must use the binary by yourself only for your experiment. Note + that "Distributing binary" includes distributing a device which + holds the binary. + + * For general individuals: + + - You must use your Gnuk device with a card serial number + generated by chip unique ID or with the one *not* by FSIJ. + + * For individuals with explicit permission from FSIJ. + + - You should have an assigned card serial number by FSIJ, + please use that number for your device. + (There a file 'GNUK_SERIAL_NUMBER' in the official release.) + +FSIJ could permit companies or business entities to use USB device ID +of FSIJ for devices with unmodified version of Gnuk, provided they +support Free Software and respect users' freedom for computing. +Please ask FSIJ for permission. + +Otherwise, companies which want to distribute Gnuk devices, please use +your own USB vendor ID and product ID. When you modify Gnuk, please +replace "FSIJ" in the string gnukStringSerial to yours. + + Host Requirements ================= @@ -268,7 +309,10 @@ Change directory to `src': Then, run `configure': - $ ./configure + $ ./configure --vidpid + +Here, you need to specify USB vendor ID and product ID. +Please read section 'USB vendor ID and product ID' above. Type: diff --git a/src/Makefile.in b/src/Makefile.in index f5e2fac..89781b4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -213,4 +213,4 @@ include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd distclean: clean - -rm -f Makefile gnuk.ld config.h + -rm -f Makefile gnuk.ld config.h *.inc diff --git a/src/configure b/src/configure index fd7049a..25ddd0e 100755 --- a/src/configure +++ b/src/configure @@ -21,6 +21,7 @@ # Default settings help=no +vidpid=none target=OLIMEX_STM32_H103 verbose=no with_dfu=default @@ -38,10 +39,12 @@ for option; do case $option in -h | --help) help=yes ;; - --target=*) - target=$optarg ;; -v | --verbose) verbose=yes ;; + --vidpid=*) + vidpid=$optarg ;; + --target=*) + target=$optarg ;; --enable-debug) debug=yes ;; --disable-debug) @@ -76,6 +79,7 @@ Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit [no] + --vidpid=VID:PID specify vendor/product ID [] --target=TARGET specify target [OLIMEX_STM32_H103] supported targes are: OLIMEX_STM32_H103 @@ -94,6 +98,40 @@ EOF exit 0 fi +if test "$vidpid" = "none"; then + echo "Please specify Vendor ID and Product ID by --vidpid option." + exit 1 +fi + +if !(IFS=" " + while read VIDPID VERSION PRODUCT VENDOR; do + if test "$vidpid" = "$VIDPID"; then + (echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\n 0x\4, 0x\3, /* idProduct */%p" + echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p" + ) > usb-vid-pid-ver.c.inc + (echo 'static const uint8_t gnukStringVendor[] = {' + echo " ${#VENDOR}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* Manufacturer: \"$VENDOR\" */" + echo $VENDOR | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + echo + echo 'static const uint8_t gnukStringProduct[] = {' + echo " ${#PRODUCT}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* Product name: \"$PRODUCT\" */" + echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + ) >usb-string-vendor-product.c.inc + exit 0 + fi + done; exit 1) < ../GNUK_USB_DEVICE_ID +then + echo "Please specify valid Vendor ID and Product ID." + echo "Check ../GNUK_USB_DEVICE_ID." + exit 1 +fi + BOARD_DIR=../boards/$target if test -d $BOARD_DIR; then echo "Configured for target: $target" diff --git a/src/main.c b/src/main.c index adf3c69..7832d82 100644 --- a/src/main.c +++ b/src/main.c @@ -161,7 +161,7 @@ extern msg_t USBthread (void *arg); #define LED_TIMEOUT_STOP MS2ST(500) -#define ID_OFFSET 12 +#define ID_OFFSET 22 static void device_initialize_once (void) { diff --git a/src/usb_desc.c b/src/usb_desc.c index e814695..60270b5 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -22,9 +22,7 @@ static const uint8_t gnukDeviceDescriptor[] = { 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ 0x40, /* bMaxPacketSize0 */ - 0x4b, 0x23, /* idVendor = 0x234b (FSIJ) */ - 0x00, 0x00, /* idProduct = 0x0000 (FSIJ USB Token) */ - 0x00, 0x02, /* bcdDevice = 2.00 */ +#include "usb-vid-pid-ver.c.inc" 1, /* Index of string descriptor describing manufacturer */ 2, /* Index of string descriptor describing product */ 3, /* Index of string descriptor describing the device's serial number */ @@ -255,28 +253,12 @@ static const uint8_t gnukStringLangID[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; -static const uint8_t gnukStringVendor[] = { - 33*2+2, /* bLength */ - USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType*/ - /* Manufacturer: "Free Software Initiative of Japan" */ - 'F', 0, 'r', 0, 'e', 0, 'e', 0, ' ', 0, 'S', 0, 'o', 0, 'f', 0, - 't', 0, 'w', 0, 'a', 0, 'r', 0, 'e', 0, ' ', 0, 'I', 0, 'n', 0, - 'i', 0, 't', 0, 'i', 0, 'a', 0, 't', 0, 'i', 0, 'v', 0, 'e', 0, - ' ', 0, 'o', 0, 'f', 0, ' ', 0, 'J', 0, 'a', 0, 'p', 0, 'a', 0, - 'n', 0 -}; - -static const uint8_t gnukStringProduct[] = { - 14*2+2, /* bLength */ - USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - /* Product name: "FSIJ USB Token" */ - 'F', 0, 'S', 0, 'I', 0, 'J', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, - ' ', 0, 'T', 0, 'o', 0, 'k', 0, 'e', 0, 'n', 0 -}; +#include "usb-string-vender-product.c.inc" const uint8_t gnukStringSerial[] = { - 13*2+2, /* bLength */ + 18*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, '0', 0, '.', 0, '1', 0, '7', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From f5cefbcab4f0485fbeeb4c31f9458409c8d145b2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 May 2012 14:14:11 +0900 Subject: [PATCH 068/300] fix typo --- src/usb_desc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usb_desc.c b/src/usb_desc.c index 60270b5..96292af 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -253,7 +253,7 @@ static const uint8_t gnukStringLangID[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; -#include "usb-string-vender-product.c.inc" +#include "usb-string-vendor-product.c.inc" const uint8_t gnukStringSerial[] = { 18*2+2, /* bLength */ From 7fb547a87e2a2cc3541ce925bb66160982f09d24 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 12 May 2012 08:06:33 +0900 Subject: [PATCH 069/300] cleanup usage of USB endpoint --- ChangeLog | 23 +++++++++++++++++++++++ src/main.c | 10 +++++++++- src/usb-icc.c | 4 ++-- src/usb_conf.h | 23 +++++++++++++++++------ src/usb_desc.c | 8 ++++---- src/usb_msc.c | 38 +++++++++++++++++++------------------- src/usb_prop.c | 16 +++++----------- 7 files changed, 79 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e36e1e..43dda42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-05-12 Niibe Yutaka + + * src/usb_msc.c (ep6_out): Rename (was: ep7_out). + (usb_start_receive): Use ep6_out and ENDP6. + (EP6_OUT_Callback): Rename (was: EP7_OUT_Callback). + Use ep6_out and ENDP6. + (msc_handle_command): Use ep6_out and ENDP6. + + * src/main.c (main): Wait USB reset. + + * src/usb-icc.c (EP1_OUT_Callback): Rename from EP2_OUT_Callback. + (USBthread): Use ENDP1 for both of epi_init and epo_init. + + * src/usb_conf.h (ENDP1_RXADDR, ENDP2_TXADDR, ENDP6_RXADDR): New. + (ENDP3_TXADDR, ENDP4_TXADDR, ENDP5_RXADDR): New value. + (ENDP7_RXADDR): Remove. + + * src/usb_desc.c (gnukConfigDescriptor): Use endpoint OUT1 (was + IN2), endpoint OUT6 (IN7). + + * src/usb_prop.c (gnuk_setup_endpoints_for_interface): Use ENDP1 + and ENDP6 for both directions. + 2012-05-11 Niibe Yutaka * src/configure (--vidpid): New mandatory option. diff --git a/src/main.c b/src/main.c index 7832d82..47bfd68 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* * main.c - main routine of Gnuk * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -376,6 +376,14 @@ main (int argc, char **argv) usb_lld_init (); random_init (); + while (1) + { + if (bDeviceState != UNCONNECTED) + break; + + chThdSleepMilliseconds (250); + } + #ifdef DEBUG stdout_init (); diff --git a/src/usb-icc.c b/src/usb-icc.c index 3cc1b87..1f875bc 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -635,7 +635,7 @@ icc_prepare_receive (struct ccid *c) */ void -EP2_OUT_Callback (void) +EP1_OUT_Callback (void) { struct ep_out *epo = &endpoint_out; size_t len = usb_lld_rx_data_len (epo->ep_num); @@ -1285,7 +1285,7 @@ USBthread (void *arg) (void)arg; epi_init (epi, ENDP1, notify_tx, c); - epo_init (epo, ENDP2, notify_icc, c); + epo_init (epo, ENDP1, notify_icc, c); ccid_init (c, epi, epo, a, chThdSelf ()); apdu_init (a); diff --git a/src/usb_conf.h b/src/usb_conf.h index 16b692f..3838451 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -5,25 +5,36 @@ #define NUM_STRING_DESC 4 +/* Control pipe */ /* EP0 */ #define ENDP0_RXADDR (0x40) #define ENDP0_TXADDR (0x80) +/* CCID/ICCD BULK_IN, BULK_OUT */ /* EP1 */ #define ENDP1_TXADDR (0xc0) +#define ENDP1_RXADDR (0x100) + +/* HID INTR_IN, INTR_OUT */ /* EP2 */ -#define ENDP2_RXADDR (0x100) +#define ENDP2_TXADDR (0x140) +#define ENDP2_RXADDR (0x148) +/* CDC BULK_IN, INTR_IN, BULK_OUT */ /* EP3 */ -#define ENDP3_TXADDR (0x140) +#define ENDP3_TXADDR (0x14a) /* EP4 */ -#define ENDP4_TXADDR (0x150) +#define ENDP4_TXADDR (0x15a) /* EP5 */ -#define ENDP5_RXADDR (0x160) +#define ENDP5_RXADDR (0x162) +/* 0x172 - 0x180 : 14-byte */ + +/* MSC BULK_IN, BULK_OUT */ /* EP6 */ #define ENDP6_TXADDR (0x180) -/* EP7 */ -#define ENDP7_RXADDR (0x1c0) +#define ENDP6_RXADDR (0x1c0) + +/* EP7: free */ #endif /* __USB_CONF_H */ diff --git a/src/usb_desc.c b/src/usb_desc.c index 96292af..b9c9c5d 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -129,17 +129,17 @@ static const uint8_t gnukConfigDescriptor[] = { 0, /* bPinSupport: No PIN pad */ #endif 1, /* bMaxCCIDBusySlots: 1 */ - /*Endpoint 1 Descriptor*/ + /*Endpoint IN1 Descriptor*/ 7, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ 0x81, /* bEndpointAddress: (IN1) */ 0x02, /* bmAttributes: Bulk */ USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */ 0x00, /* bInterval */ - /*Endpoint 2 Descriptor*/ + /*Endpoint OUT1 Descriptor*/ 7, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ - 0x02, /* bEndpointAddress: (OUT2) */ + 0x01, /* bEndpointAddress: (OUT1) */ 0x02, /* bmAttributes: Bulk */ USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */ 0x00, /* bInterval */ @@ -238,7 +238,7 @@ static const uint8_t gnukConfigDescriptor[] = { /* Endpoint Descriptor.*/ 7, /* bLength: Endpoint Descriptor size */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ - 0x07, /* bEndpointAddress: (OUT7) */ + 0x06, /* bEndpointAddress: (OUT6) */ 0x02, /* bmAttributes (Bulk). */ 0x40, 0x00, /* wMaxPacketSize. */ 0x00, /* bInterval (ignored for bulk). */ diff --git a/src/usb_msc.c b/src/usb_msc.c index 5cfec84..2112d0a 100644 --- a/src/usb_msc.c +++ b/src/usb_msc.c @@ -40,7 +40,7 @@ struct usb_endp_out { }; static struct usb_endp_in ep6_in; -static struct usb_endp_out ep7_out; +static struct usb_endp_out ep6_out; static Thread *the_thread; @@ -102,32 +102,32 @@ void EP6_IN_Callback (void) static void usb_start_receive (uint8_t *p, size_t n) { - ep7_out.rxbuf = p; - ep7_out.rxsize = n; - ep7_out.rxcnt = 0; - usb_lld_rx_enable (ENDP7); + ep6_out.rxbuf = p; + ep6_out.rxsize = n; + ep6_out.rxcnt = 0; + usb_lld_rx_enable (ENDP6); } /* "Data Received" call back */ -void EP7_OUT_Callback (void) +void EP6_OUT_Callback (void) { - size_t n = (size_t)usb_lld_rx_data_len (ENDP7); + size_t n = (size_t)usb_lld_rx_data_len (ENDP6); int err = 0; - if (n > ep7_out.rxsize) + if (n > ep6_out.rxsize) { /* buffer overflow */ err = 1; - n = ep7_out.rxsize; + n = ep6_out.rxsize; } - usb_lld_rxcpy (ep7_out.rxbuf, ENDP7, 0, n); - ep7_out.rxbuf += n; - ep7_out.rxcnt += n; - ep7_out.rxsize -= n; + usb_lld_rxcpy (ep6_out.rxbuf, ENDP6, 0, n); + ep6_out.rxbuf += n; + ep6_out.rxcnt += n; + ep6_out.rxsize -= n; - if (n == ENDP_MAX_SIZE && ep7_out.rxsize != 0) + if (n == ENDP_MAX_SIZE && ep6_out.rxsize != 0) { /* More data to be received */ - usb_lld_rx_enable (ENDP7); + usb_lld_rx_enable (ENDP6); return; } @@ -316,19 +316,19 @@ void msc_handle_command (void) if (msg != RDY_TIMEOUT) { chSysLock (); - usb_lld_stall_rx (ENDP7); + usb_lld_stall_rx (ENDP6); chSysUnlock (); } return; } - n = ep7_out.rxcnt; + n = ep6_out.rxcnt; if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE)) { msc_state = MSC_ERROR; chSysLock (); - usb_lld_stall_rx (ENDP7); + usb_lld_stall_rx (ENDP6); chSysUnlock (); return; } @@ -432,7 +432,7 @@ void msc_handle_command (void) msc_state = MSC_ERROR; chSysLock (); usb_lld_stall_tx (ENDP6); - usb_lld_stall_rx (ENDP7); + usb_lld_stall_rx (ENDP6); chSysUnlock (); return; } diff --git a/src/usb_prop.c b/src/usb_prop.c index 62a61a2..f42ead4 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -90,10 +90,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface) if (interface == 0) { /* Initialize Endpoint 1 */ - usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0); - - /* Initialize Endpoint 2 */ - usb_lld_setup_endpoint (ENDP2, EP_BULK, 0, ENDP2_RXADDR, 0, + usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR, ENDP1_TXADDR, GNUK_MAX_PACKET_SIZE); } #ifdef ENABLE_VIRTUAL_COM_PORT @@ -120,11 +117,9 @@ gnuk_setup_endpoints_for_interface (uint16_t interface) # endif { /* Initialize Endpoint 6 */ - usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, 0, ENDP6_TXADDR, 0); - - /* Initialize Endpoint 7 */ - usb_lld_setup_endpoint (ENDP7, EP_BULK, 0, ENDP7_RXADDR, 0, 64); - usb_lld_stall_rx (ENDP7); + usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, ENDP6_RXADDR, ENDP6_TXADDR, + 64); + usb_lld_stall_rx (ENDP6); } #endif } @@ -157,8 +152,7 @@ gnuk_device_reset (void) usb_lld_reset (); /* Initialize Endpoint 0 */ - usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, - ENDP0_RXADDR, ENDP0_TXADDR, + usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, GNUK_MAX_PACKET_SIZE); for (i = 0; i < NUM_INTERFACES; i++) From 2f38503c61df6872905298513cfe52ff046aa76b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 11:56:56 +0900 Subject: [PATCH 070/300] remove void statements --- src/flash.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/flash.c b/src/flash.c index 31b2c1a..be47955 100644 --- a/src/flash.c +++ b/src/flash.c @@ -1,7 +1,7 @@ /* * flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -311,7 +311,6 @@ flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len) hw = data[i*2] | 0xff00; if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) flash_warning ("DO WRITE ERROR"); - addr += 2; } } @@ -369,7 +368,6 @@ flash_do_release (const uint8_t *do_data) { if (flash_program_halfword (addr, 0) != FLASH_COMPLETE) flash_warning ("fill-zero pad failure"); - addr += 2; } /* Fill 0x0000 for "tag_number and length" word */ From 27f26564ba99488665b94b86f0262468d1cc6c4e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 11:57:34 +0900 Subject: [PATCH 071/300] fix description --- GNUK_USB_DEVICE_ID | 2 +- README | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/GNUK_USB_DEVICE_ID b/GNUK_USB_DEVICE_ID index 839863e..f019651 100644 --- a/GNUK_USB_DEVICE_ID +++ b/GNUK_USB_DEVICE_ID @@ -1,3 +1,3 @@ -# VID:PID bcdDev Product_STRING Vender_STRING +# VID:PID bcdDev Product_STRING Vender_STRING 234b:0000 0200 FSIJ USB Token Free Software Initiative of Japan ########## ## ########## ################# diff --git a/README b/README index d010385..0a071ab 100644 --- a/README +++ b/README @@ -229,17 +229,20 @@ Gnuk is distributed with external source code. USB vendor ID and product ID (USB device ID) ============================================ -When you have a vender ID and assign a product ID for Gnuk, please -contact Niibe, so that it is listed to the file GNUK_USB_DEVICE_ID. +When you have a vender ID and assign a product ID for Gnuk, edit the +file GNUK_USB_DEVICE_ID and add an entry for yours. In this case, +please contact Niibe, so that it is listed to the file in the official +release of source code. -When you modify Gnuk and install it to device, you should replace -"FSIJ" in the string gnukStringSerial to yours, so that it can be -checked as device serial number. +When you are modifing Gnuk and installing the binary to device, you +should replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to +yours, so that the device will say it's modified version by device +serial number. FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices with Gnuk under one of following conditions: - * For everyone for experiment purpose: + * For everyone for experimental purpose: - You must not distribute a binary with FSIJ's USB device ID, but must use the binary by yourself only for your experiment. Note @@ -248,8 +251,9 @@ with Gnuk under one of following conditions: * For general individuals: - - You must use your Gnuk device with a card serial number - generated by chip unique ID or with the one *not* by FSIJ. + - You must use your Gnuk device with a card serial number which is + *not* by FSIJ. Easy one would be a card serial number generated + by chip unique ID. * For individuals with explicit permission from FSIJ. @@ -264,7 +268,7 @@ Please ask FSIJ for permission. Otherwise, companies which want to distribute Gnuk devices, please use your own USB vendor ID and product ID. When you modify Gnuk, please -replace "FSIJ" in the string gnukStringSerial to yours. +replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to yours. Host Requirements @@ -309,9 +313,11 @@ Change directory to `src': Then, run `configure': - $ ./configure --vidpid + $ ./configure --vidpid= + +Here, you need to specify USB vendor ID and product ID. For FSIJ's, +it's: --vidpid=234b:0000 -Here, you need to specify USB vendor ID and product ID. Please read section 'USB vendor ID and product ID' above. Type: From a158ea48ab9c4dcb01eb6cc62b51f5d4c9ac50bf Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 13:16:43 +0900 Subject: [PATCH 072/300] rename --- src/Makefile.in | 2 +- src/{usb_msc.c => usb-msc.c} | 2 +- src/{usb_msc.h => usb-msc.h} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{usb_msc.c => usb-msc.c} (99%) rename src/{usb_msc.h => usb-msc.h} (100%) diff --git a/src/Makefile.in b/src/Makefile.in index 89781b4..4a97c8c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -103,7 +103,7 @@ CSRC += pin-$(ENABLE_PINPAD).c endif ifeq ($(ENABLE_PINPAD),dnd) -CSRC += usb_msc.c +CSRC += usb-msc.c endif # List ASM source files here diff --git a/src/usb_msc.c b/src/usb-msc.c similarity index 99% rename from src/usb_msc.c rename to src/usb-msc.c index 2112d0a..6aef706 100644 --- a/src/usb_msc.c +++ b/src/usb-msc.c @@ -25,7 +25,7 @@ #include "ch.h" #include "gnuk.h" #include "usb_lld.h" -#include "usb_msc.h" +#include "usb-msc.h" struct usb_endp_in { const uint8_t *txbuf; /* Pointer to the transmission buffer. */ diff --git a/src/usb_msc.h b/src/usb-msc.h similarity index 100% rename from src/usb_msc.h rename to src/usb-msc.h From 9275a6fdcb16475858d3577570dfccae1f7b9c4f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 13:32:47 +0900 Subject: [PATCH 073/300] cleanup --- ChangeLog | 12 +++++++++++ src/usb-msc.c | 2 +- src/usb_prop.c | 55 +++++++++++++++++--------------------------------- 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43dda42..896188b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2012-05-14 Niibe Yutaka + + * src/usb_prop.c (MSC_INTERFACE_NO): New. + (gnuk_setup_endpoints_for_interface): Cleanup with MSC_INTERFACE_NO. + (gnuk_setup_with_data, gnuk_setup_with_nodata): Likewise. + + * src/usb-msc.c: Rename from usb_msc.c. + + * src/usb-msc.h: Rename from usb_msc.h. + + * src/Makefile.in: Follow the rename of usb-msc.c. + 2012-05-12 Niibe Yutaka * src/usb_msc.c (ep6_out): Rename (was: ep7_out). diff --git a/src/usb-msc.c b/src/usb-msc.c index 6aef706..0a5ebac 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -1,5 +1,5 @@ /* - * usb_msc.c -- USB Mass Storage Class protocol handling + * usb-msc.c -- USB Mass Storage Class protocol handling * * Copyright (C) 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka diff --git a/src/usb_prop.c b/src/usb_prop.c index f42ead4..bd1bf18 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -67,12 +67,21 @@ vcom_port_setup_with_nodata (uint8_t RequestNo) return USB_UNSUPPORT; } + +#define VCOM_NUM_INTERFACES 2 +#else +#define VCOM_NUM_INTERFACES 0 #endif #ifdef PINPAD_DND_SUPPORT #include "usb_msc.h" +#define MSC_NUM_INTERFACES 1 +#else +#define MSC_NUM_INTERFACES 0 #endif +#define NUM_INTERFACES (1+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES) +#define MSC_INTERFACE_NO (1+VCOM_NUM_INTERFACES) uint32_t bDeviceState = UNCONNECTED; /* USB device status */ @@ -110,11 +119,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface) } #endif #ifdef PINPAD_DND_SUPPORT -# ifdef ENABLE_VIRTUAL_COM_PORT - else if (interface == 3) -# else - else if (interface == 1) -# endif + else if (interface == MSC_INTERFACE_NO) { /* Initialize Endpoint 6 */ usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, ENDP6_RXADDR, ENDP6_TXADDR, @@ -124,20 +129,6 @@ gnuk_setup_endpoints_for_interface (uint16_t interface) #endif } -#ifdef PINPAD_DND_SUPPORT -# ifdef ENABLE_VIRTUAL_COM_PORT -# define NUM_INTERFACES 4 /* two for CDC, one for CCID, and MSC */ -# else -# define NUM_INTERFACES 2 /* CCID and MSC */ -# endif -#else -# ifdef ENABLE_VIRTUAL_COM_PORT -# define NUM_INTERFACES 3 /* two for CDC, one for CCID */ -# else -# define NUM_INTERFACES 1 /* CCID only */ -# endif -#endif - static void gnuk_device_reset (void) { @@ -185,21 +176,16 @@ gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index) else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES) usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table)); } -#if defined(PINPAD_DND_SUPPORT) -# if defined(ENABLE_VIRTUAL_COM_PORT) +#ifdef ENABLE_VIRTUAL_COM_PORT else if (index == 1) vcom_port_data_setup (RequestNo); - else if (index == 3) -# else - else if (index == 1) -# endif +#endif +#ifdef PINPAD_DND_SUPPORT + else if (index == MSC_INTERFACE_NO) { if (RequestNo == MSC_GET_MAX_LUN_COMMAND) usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); } -#elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (index == 1) - vcom_port_data_setup (RequestNo); #endif } } @@ -218,14 +204,12 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) else return USB_UNSUPPORT; } -#if defined(PINPAD_DND_SUPPORT) -# if defined(ENABLE_VIRTUAL_COM_PORT) +#ifdef ENABLE_VIRTUAL_COM_PORT else if (index == 1) return vcom_port_setup_with_nodata (RequestNo); - else if (index == 3) -# else - else if (index == 1) -# endif +#endif +#ifdef PINPAD_DND_SUPPORT + else if (index == MSC_INTERFACE_NO) { if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND) { @@ -235,9 +219,6 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) else return USB_UNSUPPORT; } -#elif defined(ENABLE_VIRTUAL_COM_PORT) - else if (index == 1) - return vcom_port_setup_with_nodata (RequestNo); #endif else return USB_UNSUPPORT; From ee61781b92cf4274abe96c2d7ad245376a6759fa Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 14:26:44 +0900 Subject: [PATCH 074/300] more cleanup --- ChangeLog | 5 ++++- src/Makefile.in | 2 +- src/hardclock.c | 14 -------------- 3 files changed, 5 insertions(+), 16 deletions(-) delete mode 100644 src/hardclock.c diff --git a/ChangeLog b/ChangeLog index 896188b..15953a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-14 Niibe Yutaka + * src/hardclock.c: Remove. + * src/usb_prop.c (MSC_INTERFACE_NO): New. (gnuk_setup_endpoints_for_interface): Cleanup with MSC_INTERFACE_NO. (gnuk_setup_with_data, gnuk_setup_with_nodata): Likewise. @@ -8,7 +10,8 @@ * src/usb-msc.h: Rename from usb_msc.h. - * src/Makefile.in: Follow the rename of usb-msc.c. + * src/Makefile.in: Follow the rename of usb-msc.c and remove of + hardclock.c. 2012-05-12 Niibe Yutaka diff --git a/src/Makefile.in b/src/Makefile.in index 4a97c8c..743618a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -91,7 +91,7 @@ CSRC = $(PORTSRC) \ $(CRYPTSRC) \ 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 \ + usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ random.c neug.c ifneq ($(ENABLE_DEBUG),) diff --git a/src/hardclock.c b/src/hardclock.c deleted file mode 100644 index 30cc8c1..0000000 --- a/src/hardclock.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "config.h" -#include "ch.h" -#include "hal.h" -#include "gnuk.h" - -uint32_t -hardclock (void) -{ - uint32_t r = SysTick->VAL; - - DEBUG_INFO ("Random: "); - DEBUG_WORD (r); - return r; -} From 5ff82b6d8bfbd38f425bd6f924b93bc15a358b54 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 15:38:03 +0900 Subject: [PATCH 075/300] fix --- ChangeLog | 4 ++++ src/pin-dnd.c | 2 +- src/usb_prop.c | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15953a8..f30f708 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-14 Niibe Yutaka + * src/openpgp-do.c (proc_key_import): Fix checking extended header. + * src/hardclock.c: Remove. * src/usb_prop.c (MSC_INTERFACE_NO): New. @@ -13,6 +15,8 @@ * src/Makefile.in: Follow the rename of usb-msc.c and remove of hardclock.c. + * src/pin-dnd.c, src/usb_prop.c: Follow the rename of usb-msc.h. + 2012-05-12 Niibe Yutaka * src/usb_msc.c (ep6_out): Rename (was: ep7_out). diff --git a/src/pin-dnd.c b/src/pin-dnd.c index 70d1de9..08238e6 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -25,7 +25,7 @@ #include "ch.h" #include "board.h" #include "gnuk.h" -#include "usb_msc.h" +#include "usb-msc.h" struct folder { uint8_t parent; diff --git a/src/usb_prop.c b/src/usb_prop.c index bd1bf18..7bdf33c 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -74,7 +74,7 @@ vcom_port_setup_with_nodata (uint8_t RequestNo) #endif #ifdef PINPAD_DND_SUPPORT -#include "usb_msc.h" +#include "usb-msc.h" #define MSC_NUM_INTERFACES 1 #else #define MSC_NUM_INTERFACES 0 From a8b116b93f28eb8ef3eadd0988316b9b61fb491f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 15:38:50 +0900 Subject: [PATCH 076/300] add key removal tool --- ChangeLog | 2 + src/openpgp-do.c | 24 ++++++--- tool/gnuk_remove_keys.py | 105 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 6 deletions(-) create mode 100755 tool/gnuk_remove_keys.py diff --git a/ChangeLog b/ChangeLog index f30f708..663e048 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-14 Niibe Yutaka + * tool/gnuk_remove_keys.py: New. + * src/openpgp-do.c (proc_key_import): Fix checking extended header. * src/hardclock.c: Remove. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index d263663..90de71b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -841,13 +841,13 @@ gpg_do_chks_prvkey (enum kind_of_key kk, } /* - * 4d, xx, xx: Extended Header List + * 4d, xx, xx, xx: Extended Header List * b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT) * 7f48, xx: cardholder private key template * 91 xx - * 92 xx - * 93 xx - * 5f48, xx: cardholder private key + * 92 xx xx + * 93 xx xx + * 5f48, xx xx xx: cardholder private key */ static int proc_key_import (const uint8_t *data, int len) @@ -855,6 +855,7 @@ proc_key_import (const uint8_t *data, int len) int r; enum kind_of_key kk; const uint8_t *keystring_admin; + const uint8_t *p = data; if (admin_authorized == BY_ADMIN) keystring_admin = keystring_md_pw3; @@ -863,9 +864,20 @@ proc_key_import (const uint8_t *data, int len) DEBUG_BINARY (data, len); - if (data[4] == 0xb6) + if (*p++ != 0x4d) + return 0; + + /* length field */ + if (*p == 0x82) + p += 3; + else if (*p == 0x81) + p += 2; + else + p += 1; + + if (*p == 0xb6) kk = GPG_KEY_FOR_SIGNING; - else if (data[4] == 0xb8) + else if (*p == 0xb8) kk = GPG_KEY_FOR_DECRYPTION; else /* 0xa4 */ kk = GPG_KEY_FOR_AUTHENTICATION; diff --git a/tool/gnuk_remove_keys.py b/tool/gnuk_remove_keys.py new file mode 100755 index 0000000..00beb1b --- /dev/null +++ b/tool/gnuk_remove_keys.py @@ -0,0 +1,105 @@ +#! /usr/bin/python + +""" +gnuk_remove_keys.py - a tool to remove keys in Gnuk Token + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +import sys, os, string + +# Assume only single CCID device is attached to computer and it's Gnuk Token + +from smartcard.CardType import AnyCardType +from smartcard.CardRequest import CardRequest +from smartcard.util import toHexString + +def s2l(s): + return [ ord(c) for c in s ] + +class GnukToken(object): + def __init__(self): + cardtype = AnyCardType() + cardrequest = CardRequest(timeout=1, cardType=cardtype) + cardservice = cardrequest.waitforcard() + self.connection = cardservice.connection + + def cmd_get_response(self, expected_len): + apdu = [0x00, 0xc0, 0x00, 0x00, expected_len ] + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + return response + + def cmd_verify(self, who, passwd): + apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd) + response, sw1, sw2 = self.connection.transmit(apdu) + if not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + + def cmd_select_openpgp(self): + apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + response, sw1, sw2 = self.connection.transmit(apdu) + if sw1 == 0x61: + response = self.cmd_get_response(sw2) + elif not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + + def cmd_put_data_key_import_remove(self, keyno): + if keyno == 1: + keyspec = 0xb6 # SIG + elif keyno == 2: + keyspec = 0xb8 # DEC + else + keyspec = 0xa4 # AUT + apdu = [0x00, 0xdb, 0x3f, 0xff, 0x4d, 0x02, keyspec, 0x00 ] + response, sw1, sw2 = self.connection.transmit(apdu) + if sw1 == 0x61: + response = self.cmd_get_response(sw2) + elif not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + return response + +DEFAULT_PW3 = "12345678" +BY_ADMIN = 3 + +def main(fileid, is_update, data, passwd): + gnuk = GnukToken() + + gnuk.connection.connect() + print "Token:", gnuk.connection.getReader() + print "ATR:", toHexString( gnuk.connection.getATR() ) + + gnuk.cmd_verify(BY_ADMIN, passwd) + gnuk.cmd_select_openpgp() + gnuk.cmd_put_data_key_import_remove(1) + gnuk.cmd_put_data_key_import_remove(2) + gnuk.cmd_put_data_key_import_remove(3) + + gnuk.connection.disconnect() + return 0 + + +if __name__ == '__main__': + passwd = DEFAULT_PW3 + if sys.argv[1] == '-p': + from getpass import getpass + passwd = getpass("Admin password:") + sys.argv.pop(1) + main(passwd) From 4505715cf30e5f623d78580f8c572834d7bd26ed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 14 May 2012 16:10:26 +0900 Subject: [PATCH 077/300] fix --- tool/gnuk_put_binary.py | 16 ++++++++-------- tool/gnuk_remove_keys.py | 27 +++++++++++++++++---------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index f29f763..c4b66f6 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -44,7 +44,7 @@ class GnukToken(object): self.connection = cardservice.connection def cmd_get_response(self, expected_len): - apdu = [0x00, 0xc0, 0x00, 0x00, expected_len ] + apdu = [0x00, 0xc0, 0x00, 0x00, expected_len] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) @@ -67,19 +67,19 @@ class GnukToken(object): if count == 0: d = data[:256] if len(d) <= 255: - apdu = [0x00, ins, 0x80+fileid, 0x00, len(d) ] + s2l(d) + apdu = [0x00, ins, 0x80+fileid, 0x00, len(d)] + s2l(d) else: - apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255 ] + s2l(d[:255]) + apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255] + s2l(d[:255]) response, sw1, sw2 = self.connection.transmit(apdu0) apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:]) else: d = data[256*count:256*(count+1)] if len(d) <= 255: - apdu = [0x00, ins, count, 0x00, len(d) ] + s2l(d) + apdu = [0x00, ins, count, 0x00, len(d)] + s2l(d) else: - apdu0 = [0x10, ins, count, 0x00, 255 ] + s2l(d[:255]) + apdu0 = [0x10, ins, count, 0x00, 255] + s2l(d[:255]) response, sw1, sw2 = self.connection.transmit(apdu0) - apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:]) + apdu = [0x00, ins, 0x80+fileid, 0x00, 1] + s2l(d[255:]) response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): if is_update: @@ -89,7 +89,7 @@ class GnukToken(object): count += 1 def cmd_select_openpgp(self): - apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01] response, sw1, sw2 = self.connection.transmit(apdu) if sw1 == 0x61: response = self.cmd_get_response(sw2) @@ -144,7 +144,7 @@ if __name__ == '__main__': passwd = DEFAULT_PW3 if sys.argv[1] == '-p': from getpass import getpass - passwd = getpass("Admin password:") + passwd = getpass("Admin password: ") sys.argv.pop(1) if sys.argv[1] == '-u': is_update = True diff --git a/tool/gnuk_remove_keys.py b/tool/gnuk_remove_keys.py index 00beb1b..dfdd07c 100755 --- a/tool/gnuk_remove_keys.py +++ b/tool/gnuk_remove_keys.py @@ -41,7 +41,7 @@ class GnukToken(object): self.connection = cardservice.connection def cmd_get_response(self, expected_len): - apdu = [0x00, 0xc0, 0x00, 0x00, expected_len ] + apdu = [0x00, 0xc0, 0x00, 0x00, expected_len] response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) @@ -54,32 +54,33 @@ class GnukToken(object): raise ValueError, ("%02x%02x" % (sw1, sw2)) def cmd_select_openpgp(self): - apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ] + apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01] response, sw1, sw2 = self.connection.transmit(apdu) if sw1 == 0x61: response = self.cmd_get_response(sw2) elif not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) + def cmd_put_data_remove(self, tagh, tagl): + apdu = [0x00, 0xda, tagh, tagl, 0] + response, sw1, sw2 = self.connection.transmit(apdu) + return response + def cmd_put_data_key_import_remove(self, keyno): if keyno == 1: keyspec = 0xb6 # SIG elif keyno == 2: keyspec = 0xb8 # DEC - else + else: keyspec = 0xa4 # AUT - apdu = [0x00, 0xdb, 0x3f, 0xff, 0x4d, 0x02, keyspec, 0x00 ] + apdu = [0x00, 0xdb, 0x3f, 0xff, 4, 0x4d, 0x02, keyspec, 0x00] response, sw1, sw2 = self.connection.transmit(apdu) - if sw1 == 0x61: - response = self.cmd_get_response(sw2) - elif not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, ("%02x%02x" % (sw1, sw2)) return response DEFAULT_PW3 = "12345678" BY_ADMIN = 3 -def main(fileid, is_update, data, passwd): +def main(passwd): gnuk = GnukToken() gnuk.connection.connect() @@ -88,8 +89,14 @@ def main(fileid, is_update, data, passwd): gnuk.cmd_verify(BY_ADMIN, passwd) gnuk.cmd_select_openpgp() + gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG + gnuk.cmd_put_data_remove(0x00, 0xcd) # KGTIME_SIG gnuk.cmd_put_data_key_import_remove(1) + gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC + gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_DEC gnuk.cmd_put_data_key_import_remove(2) + gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT + gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_AUT gnuk.cmd_put_data_key_import_remove(3) gnuk.connection.disconnect() @@ -100,6 +107,6 @@ if __name__ == '__main__': passwd = DEFAULT_PW3 if sys.argv[1] == '-p': from getpass import getpass - passwd = getpass("Admin password:") + passwd = getpass("Admin password: ") sys.argv.pop(1) main(passwd) From a921d408c552581873453b6f7943522cb2506f89 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 15 May 2012 10:16:25 +0900 Subject: [PATCH 078/300] version 0.18 --- ChangeLog | 11 ++++ NEWS | 6 ++- README | 40 ++++++++------- doc/NOTES | 76 ++++++++++++++++++++++------ src/Makefile.in | 7 --- src/main.c | 13 +++++ src/usb_desc.c | 3 +- src/usb_endp.c | 21 -------- tool/openocd-script/lock.tcl | 2 +- tool/openocd-script/options_read.tcl | 2 +- tool/openocd-script/unlock.tcl | 2 +- tool/openocd-script/write.tcl | 2 +- 12 files changed, 116 insertions(+), 69 deletions(-) delete mode 100644 src/usb_endp.c diff --git a/ChangeLog b/ChangeLog index 663e048..7038335 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-05-15 Niibe Yutaka + + * Version 0.18. + + * src/usb_desc.c (gnukStringSerial): Updated. + + * src/main.c (EP3_IN_Callback, EP5_OUT_Callback): Move from + usb_endp.c. + + * src/usb_endp.c: Remove. + 2012-05-14 Niibe Yutaka * tool/gnuk_remove_keys.py: New. diff --git a/NEWS b/NEWS index 606c98f..f6a8bad 100644 --- a/NEWS +++ b/NEWS @@ -2,12 +2,16 @@ Gnuk NEWS - User visible changes * Major changes in Gnuk 0.18 - Released 2012-05-XX, by NIIBE Yutaka + Released 2012-05-15, by NIIBE Yutaka ** New mandatory option '--vidpid' for configure You must specify USB vendor ID and product ID for Gnuk. The file GNUK_USB_DEVICE_ID lists valid USB device IDs. +** New tool: gnuk_remove_keys.py +The tool gnuk_remove_keys.py is to remove all keys in Gnuk Token +and reset PW1 and RC (if any). + ** New USB stack Gnuk used to use USB stack of USB-FS-Device_Lib by ST. Now, it has original implementation. Hopefully, size and quality are improved. diff --git a/README b/README index 0a071ab..e25625c 100644 --- a/README +++ b/README @@ -1,8 +1,8 @@ Gnuk - software for GnuPG USB Token - Version 0.17 - 2012-02-02 - Niibe Yutaka + Version 0.18 + 2012-05-15 + Niibe Yutaka Free Software Initiative of Japan What's Gnuk? @@ -14,8 +14,8 @@ STM32F103 processor. I wish that Gnuk will be a developer's soother who uses GnuPG. I have been nervous of storing secret key(s) on usual secondary storage. -While I want to work at different places, but it is not the choice for -me to bring a card reader all the time. With Gnuk, this issue will be +There is a solution with OpenPGP card, but it is not the choice for 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 @@ -30,18 +30,19 @@ Q0: How Gnuk USB Token is superior than other solutions (OpenPGP 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. - (It is welcome for me that some vendor will manufacture Gnuk USB - Token. Even I can help design of hardware, if needed.) - Good points are: +A0: IMRHO, not quite, since there is no ready-to-use out-of-box Gnuk + product yet. (It is welcome for me that some vendor will + manufacture Gnuk USB Token. Even I can help design of hardware, + if needed.) + Good points for Gnuk are: * If you have skill of electronics and like DIY, you can build Gnuk Token cheaper (see Q8-A8). * You can study Gnuk to modify and to enhance. For example, you can implement your own authentication method with some sensor such as acceleration sensor. * It is "of Free Software"; Gnuk is distributed under GPLv3+, - "by Free Software"; Gnuk development requires only Free Software - (GNU Toolchain, Python, etc.), + "by Free Software"; Gnuk development requires only Free Software + (GNU Toolchain, Python, etc.), "for Free Software"; Gnuk supports GnuPG. Q1: What kind of key algorithm is supported? @@ -90,7 +91,7 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of and confirm scdaemon doesn't exist, then, $ gpg-connect-agent learn /bye -Qa: With GNOME, I can't use Gnuk Token for SSH. How can we use it for SSH? +Qa: With GNOME 2, 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: @@ -112,7 +113,8 @@ Ac: Perhaps, you can use a part of STM32F4 Discovery Kit as SWD Release notes ============= -This is eighteenth release of Gnuk. While it works well for specific +This is nineteenth release of Gnuk. In this release, the usage of USB +device ID by FSIJ is clarified. While it works well for specific usages and it is considered stable, it is still somewhat experimental. Tested features are: @@ -131,16 +133,17 @@ Tested features are: * Verify with pin pad * Modify with pin pad * Card holder certificate + * Removal of keys (Overriding key import is not supported, + but you can remove all keys to import again). It is known not-working well: * For some version of kernel and libccid, --enable-debug can't - work well. Please make sure to disable DEBUG option if it - doesn't work well. + work well. Please make sure to disable DEBUG option if it + doesn't work well. Not supported feature(s): - * Overriding key import. You need to remove all keys first. * Key generation on device side @@ -316,9 +319,8 @@ Then, run `configure': $ ./configure --vidpid= Here, you need to specify USB vendor ID and product ID. For FSIJ's, -it's: --vidpid=234b:0000 - -Please read section 'USB vendor ID and product ID' above. +it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and +product ID' above. Type: diff --git a/doc/NOTES b/doc/NOTES index 457ee66..ad39233 100644 --- a/doc/NOTES +++ b/doc/NOTES @@ -1,28 +1,72 @@ -USB communication -================= +USB communication (current) +=========================== - * No command chaining, but extended APDU and extended Lc and Le. - I think that this keep the code simple. +* Get response, command chaining, short APDU only. - * Once in the past (version <= 0.4), the value of - dwMaxCCIDMessageLength was 64 and we supported ICC block chaining, - so that we could not handle multple Bulk transactions. - * Now, the value of dwMaxCCIDMessageLength is 320, that's the size - of header of ICC block plus size of maximum APDU (by 64 - granularity). Still, some ccid implementation (ccid 1.3.11, for - example) sends ICC block using chaining unfortunately, so we keep - the code of ICC block chaining. +If it were only for token and no smartcard: + +* Get response, command chaining and short APDU would be considered + useless. + +* It would be wise to use extended APDU and CCID/ICCD block chaining. + +The question would be: When lower layer (CCID/ICCD layer) support +enough mechanism of block assembly, why not use one in the application +layer (ISO 7816)? + +For token implementation, CCID/ICCD would be lower layer and ISO 7816 +would be higher layer, but it's different in fact. The figure of +communication is like:: + + host <-----------> reader <---------> smartcard + CCID/ICCD ISO 7816 + + host <--> token + +Given the situation host side (GnuPG) already has the features of +handling get response, command chaining, and short APDU only, it is +rather better to do that on token side too. + +Besides, supporting extended APDU on host side, it would be needed to +prepare 64KB buffer (that's the maximum size), as there is no explicit +limitation for buffer size. 64KB would be large, and this could be +avoided when we use short APDU only. + + +USB communication (second attempt) +================================== + +* No get response, no command chaining, but extended APDU and extended + Lc and Le. I think that this keep the code simple. + +* The value of dwMaxCCIDMessageLength is 320, that's the size + of header of ICC block plus size of maximum APDU (by 64 + granularity). Still, some ccid implementation (ccid 1.3.11, for + example) sends ICC block using chaining unfortunately, so we keep + the code of ICC block chaining. + + +USB communication (initial attempt) +=================================== + +* Once in the past (version <= 0.4), the value of + dwMaxCCIDMessageLength was 64 and we supported CCID/ICCD block chaining, + so that we could not handle multple Bulk transactions. OpenPGP card protocol implementation ==================================== I try to follow "no clear password(s)" policy, even if it is on -protected flash memory. Futher, keystrings for user and reset code -are removed after key imports. Because of this, replacing keys -are not possible without password information. Thus, replacing -existing keys are not supported. +protected flash memory. Further, keystrings for user and reset code +are removed after key imports. Because of this, replacing keys are +not possible without password information. (Thus, replacing existing +keys are not supported.) + +Therefore, there is "no clear password" and "no keystrings" on flash +ROM when Gnuk is used by admin-less mode. When it is used with admin, +the keystring of admin is on flash ROM. How a private key is stored diff --git a/src/Makefile.in b/src/Makefile.in index 743618a..eed49be 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -3,9 +3,6 @@ BOARD_DIR=@BOARD_DIR@ @PINPAD_MAKE_OPTION@ @DEBUG_MAKE_OPTION@ -ifneq ($(ENABLE_DEBUG),) -ENABLE_VCOMPORT=1 -endif ############################################################################## # Build global options @@ -72,10 +69,6 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk include $(CHIBIOS)/os/kernel/kernel.mk include crypt.mk -ifneq ($(ENABLE_VCOMPORT),) -VCOMSRC += usb_endp.c -endif - # C sources that can be compiled in ARM or THUMB mode depending on the global # setting. CSRC = $(PORTSRC) \ diff --git a/src/main.c b/src/main.c index 47bfd68..0f4bb0b 100644 --- a/src/main.c +++ b/src/main.c @@ -140,6 +140,19 @@ STDOUTthread (void *arg) goto again; return 0; } + +void +EP3_IN_Callback (void) +{ + if (stdout_thread) + chEvtSignalI (stdout_thread, EV_TX_READY); +} + +void +EP5_OUT_Callback (void) +{ + usb_lld_rx_enable (ENDP5); +} #else void _write (const char *s, int size) diff --git a/src/usb_desc.c b/src/usb_desc.c index b9c9c5d..0ebc03d 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -258,8 +258,9 @@ static const uint8_t gnukStringLangID[] = { const uint8_t gnukStringSerial[] = { 18*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + /* FSIJ-0.18 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '0', 0, '.', 0, '1', 0, '7', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '1', 0, '8', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/src/usb_endp.c b/src/usb_endp.c deleted file mode 100644 index ac60fe7..0000000 --- a/src/usb_endp.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Virtual COM port (for debug output only) - */ - -#include "config.h" -#include "ch.h" -#include "gnuk.h" -#include "usb_lld.h" - -void -EP3_IN_Callback (void) -{ - if (stdout_thread) - chEvtSignalI (stdout_thread, EV_TX_READY); -} - -void -EP5_OUT_Callback (void) -{ - usb_lld_rx_enable (ENDP5); -} diff --git a/tool/openocd-script/lock.tcl b/tool/openocd-script/lock.tcl index ecb5a96..9142fd0 100644 --- a/tool/openocd-script/lock.tcl +++ b/tool/openocd-script/lock.tcl @@ -3,4 +3,4 @@ reset halt stm32x lock 0 reset -exit +shutdown diff --git a/tool/openocd-script/options_read.tcl b/tool/openocd-script/options_read.tcl index 7ea8c40..7c7658a 100644 --- a/tool/openocd-script/options_read.tcl +++ b/tool/openocd-script/options_read.tcl @@ -2,4 +2,4 @@ init reset halt stm32x options_read 0 -exit +shutdown diff --git a/tool/openocd-script/unlock.tcl b/tool/openocd-script/unlock.tcl index 2f14aeb..67883ed 100644 --- a/tool/openocd-script/unlock.tcl +++ b/tool/openocd-script/unlock.tcl @@ -3,4 +3,4 @@ reset halt stm32x unlock 0 reset -exit +shutdown diff --git a/tool/openocd-script/write.tcl b/tool/openocd-script/write.tcl index 50d4382..1ddf8cd 100644 --- a/tool/openocd-script/write.tcl +++ b/tool/openocd-script/write.tcl @@ -2,4 +2,4 @@ init reset halt flash write_image erase gnuk.elf -exit +shutdown From 429c6f3d8b7e24b39c3b85170aa3cc5ef66a9e7e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 17 May 2012 12:15:24 +0900 Subject: [PATCH 079/300] fileid change/cleanup --- ChangeLog | 13 +++++++++++++ src/flash.c | 34 ++++++++++++++++------------------ src/gnuk.h | 5 ++--- src/openpgp.c | 27 ++++++++++++++------------- tool/gnuk_put_binary.py | 12 ++++++------ tool/gnuk_put_binary_libusb.py | 18 +++--------------- 6 files changed, 54 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7038335..e23f92f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-05-16 Niibe Yutaka + + * tool/gnuk_put_binary.py (main): Fix fileid. + * tool/gnuk_put_binary_libusb.py: Ditto. + + * src/openpgp.c (FILE_EF_RANDOM): Remove. + (cmd_update_binary, cmds): ifdef CERTDO_SUPPORT. + (cmd_write_binary): Fix fileid. + + * src/flash.c (flash_check_blank): Always enable. + (flash_erase_binary): ifdef CERTDO_SUPPORT. + (flash_write_binary): Call flash_check_blank. + 2012-05-15 Niibe Yutaka * Version 0.18. diff --git a/src/flash.c b/src/flash.c index be47955..f6322c1 100644 --- a/src/flash.c +++ b/src/flash.c @@ -579,25 +579,23 @@ flash_cnt123_clear (const uint8_t **addr_p) } -#if defined(CERTDO_SUPPORT) static int -flash_check_blank (const uint8_t *page, int size) +flash_check_blank (const uint8_t *p_start, int size) { const uint8_t *p; - for (p = page; p < page + size; p++) + for (p = p_start; p < p_start + size; p++) if (*p != 0xff) return 0; return 1; } -#endif +#if defined(CERTDO_SUPPORT) #define FLASH_CH_CERTIFICATE_SIZE 2048 int flash_erase_binary (uint8_t file_id) { -#if defined(CERTDO_SUPPORT) if (file_id == FILEID_CH_CERTIFICATE) { const uint8_t *p = &ch_certificate_start; @@ -611,12 +609,10 @@ flash_erase_binary (uint8_t file_id) return 0; } - else -#else - (void)file_id; -#endif - return -1; + + return -1; } +#endif int @@ -626,19 +622,18 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t maxsize; const uint8_t *p; -#if defined(CERTDO_SUPPORT) - if (file_id == FILEID_CH_CERTIFICATE) - { - maxsize = FLASH_CH_CERTIFICATE_SIZE; - p = &ch_certificate_start; - } - else -#endif if (file_id == FILEID_SERIAL_NO) { maxsize = 6; p = &openpgpcard_aid[8]; } +#if defined(CERTDO_SUPPORT) + else if (file_id == FILEID_CH_CERTIFICATE) + { + maxsize = FLASH_CH_CERTIFICATE_SIZE; + p = &ch_certificate_start; + } +#endif else return -1; @@ -650,6 +645,9 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, uint32_t addr; int i; + if (flash_check_blank (p, len) == 0) + return -1; + addr = (uint32_t)p + offset; for (i = 0; i < len/2; i++) { diff --git a/src/gnuk.h b/src/gnuk.h index f5a2f43..1eb923f 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -137,9 +137,8 @@ extern void flash_clear_halfword (uint32_t addr); extern void flash_increment_counter (uint8_t counter_tag_nr); extern void flash_reset_counter (uint8_t counter_tag_nr); -#define FILEID_CH_CERTIFICATE 0 -#define FILEID_RANDOM 1 -#define FILEID_SERIAL_NO 2 +#define FILEID_SERIAL_NO 0 +#define FILEID_CH_CERTIFICATE 1 extern int flash_erase_binary (uint8_t file_id); extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset); diff --git a/src/openpgp.c b/src/openpgp.c index eec46ee..88c92fc 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -78,7 +78,6 @@ set_res_sw (uint8_t sw1, uint8_t sw2) #define FILE_EF_DIR 3 #define FILE_EF_SERIAL 4 #define FILE_EF_CH_CERTIFICATE 5 -#define FILE_EF_RANDOM 6 static uint8_t file_selection; @@ -701,6 +700,7 @@ cmd_internal_authenticate (void) } +#if defined(CERTDO_SUPPORT) static void cmd_update_binary (void) { @@ -718,10 +718,10 @@ cmd_update_binary (void) } if ((P1 (apdu) & 0x80)) - if ((P1 (apdu) & 0x7f) <= FILEID_RANDOM) + if ((P1 (apdu) & 0x7f) == FILEID_CH_CERTIFICATE) { - file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f); - r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE); + file_selection = FILE_EF_CH_CERTIFICATE; + r = flash_erase_binary (FILEID_CH_CERTIFICATE); if (r < 0) { DEBUG_INFO ("memory error.\r\n"); @@ -738,8 +738,7 @@ cmd_update_binary (void) } else { - if (file_selection != FILE_EF_CH_CERTIFICATE - && file_selection != FILE_EF_RANDOM) + if (file_selection != FILE_EF_CH_CERTIFICATE) { GPG_COMMAND_NOT_ALLOWED (); return; @@ -751,7 +750,7 @@ cmd_update_binary (void) DEBUG_SHORT (len); DEBUG_SHORT (offset); - r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE, + r = flash_write_binary (FILEID_CH_CERTIFICATE, apdu.cmd_apdu_data, len, offset); if (r < 0) { @@ -763,6 +762,7 @@ cmd_update_binary (void) GPG_SUCCESS (); DEBUG_INFO ("UPDATE BINARY done.\r\n"); } +#endif static void @@ -782,9 +782,9 @@ cmd_write_binary (void) } if ((P1 (apdu) & 0x80)) - if ((P1 (apdu) & 0x7f) <= FILEID_SERIAL_NO) + if ((P1 (apdu) & 0x7f) <= FILEID_CH_CERTIFICATE) { - file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f); + file_selection = FILE_EF_SERIAL + (P1 (apdu) & 0x7f); offset = 0; } else @@ -794,9 +794,8 @@ cmd_write_binary (void) } else { - if (file_selection != FILE_EF_CH_CERTIFICATE - && file_selection != FILE_EF_RANDOM - && file_selection != FILE_EF_SERIAL) + if (file_selection != FILE_EF_SERIAL + && file_selection != FILE_EF_CH_CERTIFICATE) { GPG_COMMAND_NOT_ALLOWED (); return; @@ -808,7 +807,7 @@ cmd_write_binary (void) DEBUG_SHORT (len); DEBUG_SHORT (offset); - r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE, + r = flash_write_binary (file_selection - FILE_EF_SERIAL, apdu.cmd_apdu_data, len, offset); if (r < 0) { @@ -839,7 +838,9 @@ const struct command cmds[] = { { INS_READ_BINARY, cmd_read_binary }, { INS_GET_DATA, cmd_get_data }, { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */ +#if defined(CERTDO_SUPPORT) { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */ +#endif { INS_PUT_DATA, cmd_put_data }, { INS_PUT_DATA_ODD, cmd_put_data }, }; diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index c4b66f6..217d818 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -125,16 +125,16 @@ def main(fileid, is_update, data, passwd): gnuk.cmd_verify(BY_ADMIN, passwd) gnuk.cmd_write_binary(fileid, data, is_update) if fileid == 0: - 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:]) + elif fileid == 1: + gnuk.cmd_select_openpgp() + data_in_device = gnuk.cmd_get_data(0x7f, 0x21) + compare(data[:-2], data_in_device) gnuk.connection.disconnect() return 0 @@ -152,7 +152,7 @@ if __name__ == '__main__': else: is_update = False if sys.argv[1] == '-s': - fileid = 2 # serial number + fileid = 0 # serial number filename = sys.argv[2] f = open(filename) email = os.environ['EMAIL'] @@ -168,7 +168,7 @@ if __name__ == '__main__': print "Writing serial number" data = binascii.unhexlify(serial_data_hex) else: - fileid = 0 # Card holder certificate + fileid = 1 # Card holder certificate filename = sys.argv[1] f = open(filename) data = f.read() diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index ae47ba9..98069c8 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -241,7 +241,7 @@ def main(fileid, is_update, data): else: icc.cmd_write_binary(fileid, data) icc.cmd_select_openpgp() - if fileid == 0: + if fileid == 1: data = data[:-2] data_in_device = icc.cmd_get_data(0x7f, 0x21) compare(data, data_in_device) @@ -255,7 +255,7 @@ if __name__ == '__main__': else: is_update = False if sys.argv[1] == '-s': - fileid = 2 # serial number + fileid = 0 # serial number filename = sys.argv[2] f = open(filename) email = os.environ['EMAIL'] @@ -270,20 +270,8 @@ if __name__ == '__main__': exit(1) print "Writing serial number" data = binascii.unhexlify(serial_data_hex) - elif sys.argv[1] == '-r': - fileid = 1 # Random number bits - if len(sys.argv) == 3: - filename = sys.argv[2] - f = open(filename) - else: - filename = stdin - f = sys.stdin - data = f.read() - f.close() - print "%s: %d" % (filename, len(data)) - print "Updating random bits" else: - fileid = 0 # Card holder certificate + fileid = 1 # Card holder certificate filename = sys.argv[1] f = open(filename) data = f.read() From f2afeacdcb274d4bfbbac9853a5aa57b170939b9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 17 May 2012 12:45:51 +0900 Subject: [PATCH 080/300] fix usb_lld.c --- ChangeLog | 9 +++++++ README | 16 ++++++----- src/usb_lld.c | 75 +++++++++++++++++++++++---------------------------- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index e23f92f..a34ad01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-05-17 Niibe Yutaka + + * src/usb_lld.c (LAST_OUT_DATA): Remove. + (handle_datastage_out): Cleanup and call st103_ep_set_rxtx_status. + (handle_datastage_in): Call st103_ep_set_rxtx_status and + st103_ep_set_tx_status. + (handle_setup0): Likewise. + (handle_out0): Remove LAST_OUT_DATA. + 2012-05-16 Niibe Yutaka * tool/gnuk_put_binary.py (main): Fix fileid. diff --git a/README b/README index e25625c..d49abac 100644 --- a/README +++ b/README @@ -235,7 +235,7 @@ USB vendor ID and product ID (USB device ID) When you have a vender ID and assign a product ID for Gnuk, edit the file GNUK_USB_DEVICE_ID and add an entry for yours. In this case, please contact Niibe, so that it is listed to the file in the official -release of source code. +release of the source code. When you are modifing Gnuk and installing the binary to device, you should replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to @@ -264,14 +264,16 @@ with Gnuk under one of following conditions: please use that number for your device. (There a file 'GNUK_SERIAL_NUMBER' in the official release.) -FSIJ could permit companies or business entities to use USB device ID -of FSIJ for devices with unmodified version of Gnuk, provided they -support Free Software and respect users' freedom for computing. -Please ask FSIJ for permission. +FSIJ could give companies or business entities "second source +manufacturer" license to use USB device ID of FSIJ for devices with +unmodified version of Gnuk, provided they support Free Software and +respect users' freedom for computing. Please ask FSIJ for the +license. Otherwise, companies which want to distribute Gnuk devices, please use -your own USB vendor ID and product ID. When you modify Gnuk, please -replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to yours. +your own USB vendor ID and product ID. Note that please replace +"FSIJ" in the string gnukStringSerial (usb_desc.c) to yours, when you +modify Gnuk. Host Requirements diff --git a/src/usb_lld.c b/src/usb_lld.c index 25ac005..f90cd8c 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -27,16 +27,15 @@ enum STANDARD_REQUESTS /* The state machine states of a control pipe */ enum CONTROL_STATE { - WAIT_SETUP, /* 0 */ - SETTING_UP, /* 1 */ - IN_DATA, /* 2 */ - OUT_DATA, /* 3 */ - LAST_IN_DATA, /* 4 */ - LAST_OUT_DATA, /* 5 */ - WAIT_STATUS_IN, /* 7 */ - WAIT_STATUS_OUT, /* 8 */ - STALLED, /* 9 */ - PAUSE /* 10 */ + WAIT_SETUP, + SETTING_UP, + IN_DATA, + OUT_DATA, + LAST_IN_DATA, + WAIT_STATUS_IN, + WAIT_STATUS_OUT, + STALLED, + PAUSE }; enum FEATURE_SELECTOR @@ -400,24 +399,17 @@ static void handle_datastage_out (void) usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len); } - if (data_p->len != 0) + if (data_p->len == 0) + { + dev_p->state = WAIT_STATUS_IN; + st103_set_tx_count (ENDP0, 0); + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); + } + else { st103_ep_set_rx_status (ENDP0, EP_RX_VALID); - st103_set_tx_count (ENDP0, 0); - st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + dev_p->state = OUT_DATA; } - - if (data_p->len >= USB_MAX_PACKET_SIZE) - dev_p->state = OUT_DATA; - else - if (data_p->len > 0) - dev_p->state = LAST_OUT_DATA; - else if (data_p->len == 0) - { - dev_p->state = WAIT_STATUS_IN; - st103_set_tx_count (ENDP0, 0); - st103_ep_set_tx_status (ENDP0, EP_TX_VALID); - } } static void handle_datastage_in (void) @@ -437,10 +429,11 @@ static void handle_datastage_in (void) } else { - /* No more data to send. Thus, STALL the TX Status*/ + /* No more data to send, but receive OUT.*/ dev_p->state = WAIT_STATUS_OUT; - st103_ep_set_tx_status (ENDP0, EP_TX_STALL); + st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); } + return; } @@ -451,11 +444,10 @@ static void handle_datastage_in (void) buf = (const uint8_t *)data_p->addr + data_p->offset; usb_lld_to_pmabuf (buf, st103_get_tx_addr (ENDP0), len); - st103_set_tx_count (ENDP0, len); - data_p->len -= len; data_p->offset += len; - st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID); + st103_set_tx_count (ENDP0, len); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); } typedef int (*HANDLER) (uint8_t rcp, @@ -781,7 +773,6 @@ static void handle_setup0 (void) pw++; ctrl_p->wLength = *pw; - dev_p->state = STALLED; data_p->len = 0; data_p->offset = 0; @@ -812,13 +803,7 @@ static void handle_setup0 (void) dev_p->state = STALLED; else { - if (ctrl_p->wLength == 0) - { - dev_p->state = WAIT_STATUS_IN; - st103_set_tx_count (ENDP0, 0); - st103_ep_set_tx_status (ENDP0, EP_TX_VALID); - } - else if (ctrl_p->bmRequestType & 0x80) + if (ctrl_p->bmRequestType & 0x80) { uint32_t len = ctrl_p->wLength; @@ -831,13 +816,19 @@ static void handle_setup0 (void) else data_p->require_zlp = FALSE; + dev_p->state = IN_DATA; handle_datastage_in (); } - else + else if (ctrl_p->wLength == 0) + { + dev_p->state = WAIT_STATUS_IN; + st103_set_tx_count (ENDP0, 0); + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); + } + else { dev_p->state = OUT_DATA; - st103_ep_set_rx_status (ENDP0, EP_RX_VALID); - /* enable for next data reception */ + st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); } } } @@ -866,7 +857,7 @@ static void handle_out0 (void) if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA) /* host aborts the transfer before finish */ dev_p->state = STALLED; - else if (dev_p->state == OUT_DATA || dev_p->state == LAST_OUT_DATA) + else if (dev_p->state == OUT_DATA) handle_datastage_out (); else if (dev_p->state == WAIT_STATUS_OUT) dev_p->state = STALLED; From e2e2e1a045ff6fec864f2f49bb68141ac562bab1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 17 May 2012 13:29:39 +0900 Subject: [PATCH 081/300] disable all endpoints when configure(0) --- ChangeLog | 4 ++++ src/usb_prop.c | 60 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index a34ad01..703ed63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-05-17 Niibe Yutaka + * src/usb_prop.c (gnuk_setup_endpoints_for_interface): Add STOP + argument. + (gnuk_usb_event): Disable all endpoints when configure(0). + * src/usb_lld.c (LAST_OUT_DATA): Remove. (handle_datastage_out): Cleanup and call st103_ep_set_rxtx_status. (handle_datastage_in): Call st103_ep_set_rxtx_status and diff --git a/src/usb_prop.c b/src/usb_prop.c index 7bdf33c..1787156 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -94,37 +94,56 @@ gnuk_device_init (void) } static void -gnuk_setup_endpoints_for_interface (uint16_t interface) +gnuk_setup_endpoints_for_interface (uint16_t interface, int stop) { if (interface == 0) { - /* Initialize Endpoint 1 */ - usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR, ENDP1_TXADDR, - GNUK_MAX_PACKET_SIZE); + if (!stop) + usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR, ENDP1_TXADDR, + GNUK_MAX_PACKET_SIZE); + else + { + usb_lld_stall_rx (ENDP1); + usb_lld_stall_tx (ENDP1); + } } #ifdef ENABLE_VIRTUAL_COM_PORT else if (interface == 1) { - /* Initialize Endpoint 4 */ - usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0); + if (!stop) + usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0); + else + usb_lld_stall_tx (ENDP4); } else if (interface == 2) { - /* Initialize Endpoint 3 */ - usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0); - - /* Initialize Endpoint 5 */ - usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0, - VIRTUAL_COM_PORT_DATA_SIZE); + if (!stop) + { + usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0); + usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0, + VIRTUAL_COM_PORT_DATA_SIZE); + } + else + { + usb_lld_stall_tx (ENDP3); + usb_lld_stall_rx (ENDP5); + } } #endif #ifdef PINPAD_DND_SUPPORT else if (interface == MSC_INTERFACE_NO) { - /* Initialize Endpoint 6 */ - usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, ENDP6_RXADDR, ENDP6_TXADDR, - 64); - usb_lld_stall_rx (ENDP6); + if (!stop) + { + usb_lld_setup_endpoint (ENDP6, EP_BULK, 0, + ENDP6_RXADDR, ENDP6_TXADDR, 64); + usb_lld_stall_rx (ENDP6); + } + else + { + usb_lld_stall_tx (ENDP6); + usb_lld_stall_rx (ENDP6); + } } #endif } @@ -147,7 +166,7 @@ gnuk_device_reset (void) GNUK_MAX_PACKET_SIZE); for (i = 0; i < NUM_INTERFACES; i++) - gnuk_setup_endpoints_for_interface (i); + gnuk_setup_endpoints_for_interface (i, 0); bDeviceState = ATTACHED; } @@ -278,7 +297,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) usb_lld_set_configuration (value); for (i = 0; i < NUM_INTERFACES; i++) - gnuk_setup_endpoints_for_interface (i); + gnuk_setup_endpoints_for_interface (i, 0); bDeviceState = CONFIGURED; chEvtSignalI (main_thread, LED_STATUS_MODE); return USB_SUCCESS; @@ -289,7 +308,8 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) return USB_UNSUPPORT; usb_lld_set_configuration (0); - // Disable all endpoints??? + for (i = 0; i < NUM_INTERFACES; i++) + gnuk_setup_endpoints_for_interface (i, 1); bDeviceState = ADDRESSED; } default: @@ -313,7 +333,7 @@ static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt) return USB_UNSUPPORT; else { - gnuk_setup_endpoints_for_interface (interface); + gnuk_setup_endpoints_for_interface (interface, 0); return USB_SUCCESS; } From ce338a9727c7d3ea69398e8c6a2b372bdf226f81 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 17 May 2012 17:02:49 +0900 Subject: [PATCH 082/300] implement downloading program --- ChangeLog | 22 ++++ src/gnuk.h | 5 + src/openpgp.c | 46 ++++++++- src/usb-icc.c | 11 ++ src/usb_lld.c | 104 +++++++++++++------ src/usb_lld.h | 10 +- src/usb_prop.c | 100 ++++++++++++------ tool/gnuk_upgrade.py | 239 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 471 insertions(+), 66 deletions(-) create mode 100755 tool/gnuk_upgrade.py diff --git a/ChangeLog b/ChangeLog index 703ed63..4bfe9dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,25 @@ 2012-05-17 Niibe Yutaka + * tool/gnuk_upgrade.py: New tool. + + * src/gnuk.h (ICC_STATE_EXITED, ICC_STATE_EXEC_REQUESTED): New. + + * src/openpgp.c (INS_EXTERNAL_AUTHENTICATE) + (cmd_external_authenticate): New. + (INS_GET_CHALLENGE, cmd_get_challenge): New. + + * src/usb-icc.c (USBthread): Finish the thread with + ICC_STATE_EXITED, after EXTERNAL_AUTHENTICATE. + * src/usb_prop.c (gnuk_setup_endpoints_for_interface): Add STOP argument. (gnuk_usb_event): Disable all endpoints when configure(0). + (vcom_port_data_setup): Check direction and support + USB_CDC_REQ_SET_LINE_CODING. + (vcom_port_setup_with_nodata): Check direction. + (gnuk_setup_with_data): Check direction and add FSIJ_GNUK device + requests. + (gnuk_setup_with_nodata): Likewise. * src/usb_lld.c (LAST_OUT_DATA): Remove. (handle_datastage_out): Cleanup and call st103_ep_set_rxtx_status. @@ -10,6 +27,11 @@ st103_ep_set_tx_status. (handle_setup0): Likewise. (handle_out0): Remove LAST_OUT_DATA. + (std_none, std_get_status, std_clear_feature, std_set_feature) + (std_set_address, std_get_descriptor, std_get_configuration) + (std_set_configuration, std_get_interface, std_set_interface): + Check direction. + (handle_setup0): Add length for setup_with_data 2012-05-16 Niibe Yutaka diff --git a/src/gnuk.h b/src/gnuk.h index 1eb923f..1b1874a 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -76,6 +76,9 @@ enum icc_state ICC_STATE_EXECUTE, /* Busy4 */ ICC_STATE_RECEIVE, /* APDU Received Partially */ ICC_STATE_SEND, /* APDU Sent Partially */ + + ICC_STATE_EXITED, /* ICC Thread Terminated */ + ICC_STATE_EXEC_REQUESTED, /* Exec requested */ }; extern enum icc_state *icc_state_p; @@ -385,3 +388,5 @@ extern uint8_t pin_input_len; extern int pinpad_getline (int msg_code, systime_t timeout); #endif + +extern uint8_t __heap_base__, __heap_end__; diff --git a/src/openpgp.c b/src/openpgp.c index 88c92fc..d062f11 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -1,7 +1,7 @@ /* * openpgp.c -- OpenPGP card protocol support * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -39,6 +39,8 @@ #define INS_PSO 0x2a #define INS_RESET_RETRY_COUNTER 0x2c #define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47 +#define INS_EXTERNAL_AUTHENTICATE 0x82 +#define INS_GET_CHALLENGE 0x84 #define INS_INTERNAL_AUTHENTICATE 0x88 #define INS_SELECT_FILE 0xa4 #define INS_READ_BINARY 0xb0 @@ -821,6 +823,43 @@ cmd_write_binary (void) } +static void +cmd_external_authenticate (void) +{ + DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); + + if (!ac_check_status (AC_ADMIN_AUTHORIZED)) + { + GPG_SECURITY_FAILURE (); + return; + } + + chThdTerminate (chThdSelf ()); + set_res_sw (0xff, 0xff); + DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n"); +} + +static void +cmd_get_challenge (void) +{ + const uint8_t *rand; + int i; + + DEBUG_INFO (" - GET CHALLENGE\r\n"); + + for (i = 0; i < 6; i++) + { + rand = random_bytes_get (); + memcpy (res_APDU + i * 16, rand, 16); + random_bytes_free (rand); + } + + res_APDU_size = 96; + GPG_SUCCESS (); + DEBUG_INFO ("GET CHALLENGE done.\r\n"); +} + + struct command { uint8_t command; @@ -833,11 +872,14 @@ const struct command cmds[] = { { INS_PSO, cmd_pso }, { INS_RESET_RETRY_COUNTER, cmd_reset_user_password }, { INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp }, + { INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */ + cmd_external_authenticate }, + { INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */ { INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate }, { INS_SELECT_FILE, cmd_select_file }, { INS_READ_BINARY, cmd_read_binary }, { INS_GET_DATA, cmd_get_data }, - { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */ + { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */ #if defined(CERTDO_SUPPORT) { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */ #endif diff --git a/src/usb-icc.c b/src/usb-icc.c index 1f875bc..67b04e5 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -1273,6 +1273,7 @@ icc_handle_timeout (struct ccid *c) static struct ccid ccid; +#define GPG_THREAD_TERMINATED 0xffff msg_t USBthread (void *arg) @@ -1303,6 +1304,16 @@ USBthread (void *arg) else if (m == EV_EXEC_FINISHED) if (c->icc_state == ICC_STATE_EXECUTE) { + if (c->a->sw == GPG_THREAD_TERMINATED) + { + c->sw1sw2[0] = 0x90; + c->sw1sw2[1] = 0x00; + c->state = APDU_STATE_RESULT; + icc_send_data_block (c, 0); + c->icc_state = ICC_STATE_EXITED; + break; + } + c->a->cmd_apdu_data_len = 0; c->sw1sw2[0] = c->a->sw >> 8; c->sw1sw2[1] = c->a->sw & 0xff; diff --git a/src/usb_lld.c b/src/usb_lld.c index f90cd8c..13fa6c3 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -4,8 +4,6 @@ #define USB_MAX_PACKET_SIZE 64 /* For FS device */ -#define RECIPIENT 0x1F /* Mask to get recipient */ - enum STANDARD_REQUESTS { GET_STATUS = 0, @@ -450,25 +448,27 @@ static void handle_datastage_in (void) st103_ep_set_tx_status (ENDP0, EP_TX_VALID); } -typedef int (*HANDLER) (uint8_t rcp, +typedef int (*HANDLER) (uint8_t req, uint16_t value, uint16_t index, uint16_t length); -static int std_none (uint8_t rcp, +static int std_none (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { - (void)rcp; (void)value; (void)index; (void)length; + (void)req; (void)value; (void)index; (void)length; return USB_UNSUPPORT; } -static int std_get_status (uint8_t rcp, +static int std_get_status (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { static uint16_t status_info; + uint8_t rcp = req & RECIPIENT; status_info = 0; /* Reset Status Information */ data_p->addr = (uint8_t *)&status_info; - if (value != 0 || length != 2 || (index >> 8) != 0) + if (value != 0 || length != 2 || (index >> 8) != 0 + || (req & REQUEST_DIR) == 0) return USB_UNSUPPORT; if (rcp == DEVICE_RECIPIENT) @@ -540,9 +540,14 @@ static int std_get_status (uint8_t rcp, return USB_UNSUPPORT; } -static int std_clear_feature (uint8_t rcp, uint16_t value, +static int std_clear_feature (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + if (rcp == DEVICE_RECIPIENT) { if (length != 0 || index != 0) @@ -598,9 +603,14 @@ static int std_clear_feature (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_set_feature (uint8_t rcp, uint16_t value, +static int std_set_feature (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + if (rcp == DEVICE_RECIPIENT) { if (length != 0 || index != 0) @@ -646,9 +656,14 @@ static int std_set_feature (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_set_address (uint8_t rcp, uint16_t value, +static int std_set_address (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + if (rcp == DEVICE_RECIPIENT) { if (length == 0 && value <= 127 && index == 0 @@ -659,9 +674,14 @@ static int std_set_address (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_get_descriptor (uint8_t rcp, uint16_t value, +static int std_get_descriptor (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 0) + return USB_UNSUPPORT; + (void)length; if (rcp == DEVICE_RECIPIENT) return (*method_p->get_descriptor) ((value >> 8), index, value); @@ -669,9 +689,14 @@ static int std_get_descriptor (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_get_configuration (uint8_t rcp, uint16_t value, +static int std_get_configuration (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 0) + return USB_UNSUPPORT; + (void)value; (void)index; (void)length; if (rcp == DEVICE_RECIPIENT) { @@ -683,9 +708,14 @@ static int std_get_configuration (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_set_configuration (uint8_t rcp, uint16_t value, +static int std_set_configuration (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + if (rcp == DEVICE_RECIPIENT && index == 0 && length == 0) { int r; @@ -698,9 +728,14 @@ static int std_set_configuration (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_get_interface (uint8_t rcp, uint16_t value, +static int std_get_interface (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 0) + return USB_UNSUPPORT; + if (rcp == INTERFACE_RECIPIENT) { if (value != 0 || (index >> 8) != 0 || length != 1) @@ -715,9 +750,14 @@ static int std_get_interface (uint8_t rcp, uint16_t value, return USB_UNSUPPORT; } -static int std_set_interface (uint8_t rcp, uint16_t value, +static int std_set_interface (uint8_t req, uint16_t value, uint16_t index, uint16_t length) { + uint8_t rcp = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + if (rcp == INTERFACE_RECIPIENT) { int r; @@ -759,7 +799,6 @@ static void handle_setup0 (void) uint8_t req; int r = USB_UNSUPPORT; HANDLER handler; - uint8_t type_rcp; pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2)); w = *pw++; @@ -776,34 +815,35 @@ static void handle_setup0 (void) data_p->len = 0; data_p->offset = 0; - type_rcp = (ctrl_p->bmRequestType & (REQUEST_TYPE | RECIPIENT)); - if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) /* Interface */ - || (ctrl_p->bmRequestType & REQUEST_TYPE) == VENDOR_REQUEST) - { - if (ctrl_p->wLength == 0) - r = (*method_p->setup_with_nodata) (type_rcp, req, ctrl_p->wIndex); - else - { - (*method_p->setup_with_data) (type_rcp, req, ctrl_p->wIndex); - if (data_p->len != 0) - r = USB_SUCCESS; - } - } - else if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST) + if ((ctrl_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST) { if (req < TOTAL_REQUEST) { handler = std_request_handler[req]; - r = (*handler) (ctrl_p->bmRequestType & RECIPIENT, + r = (*handler) (ctrl_p->bmRequestType, ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength); } } + else + { + if (ctrl_p->wLength == 0) + r = (*method_p->setup_with_nodata) (ctrl_p->bmRequestType, + req, ctrl_p->wIndex); + else + { + (*method_p->setup_with_data) (ctrl_p->bmRequestType, req, + ctrl_p->wIndex, ctrl_p->wLength); + if (data_p->len != 0) + r = USB_SUCCESS; + } + } + if (r != USB_SUCCESS) dev_p->state = STALLED; else { - if (ctrl_p->bmRequestType & 0x80) + if (ctrl_p->bmRequestType & REQUEST_DIR) { uint32_t len = ctrl_p->wLength; diff --git a/src/usb_lld.h b/src/usb_lld.h index f27d017..7355ba3 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -39,10 +39,12 @@ enum DESCRIPTOR_TYPE ENDPOINT_DESCRIPTOR }; +#define REQUEST_DIR 0x80 /* Mask to get request dir */ #define REQUEST_TYPE 0x60 /* Mask to get request type */ #define STANDARD_REQUEST 0x00 /* Standard request */ #define CLASS_REQUEST 0x20 /* Class request */ #define VENDOR_REQUEST 0x40 /* Vendor request */ +#define RECIPIENT 0x1F /* Mask to get recipient */ struct Descriptor { @@ -60,7 +62,8 @@ struct usb_device_method { void (*init) (void); void (*reset) (void); - void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index); + void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index, + uint16_t len); int (*setup_with_nodata) (uint8_t rcp, uint8_t req_no, uint16_t index); int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value); int (*event) (uint8_t event_type, uint16_t value); @@ -141,3 +144,8 @@ extern uint8_t usb_lld_current_configuration (void); extern void usb_lld_set_feature (uint8_t feature); extern void usb_lld_set_data_to_send (const void *p, size_t len); + +extern inline void usb_lld_set_data_to_recv (void *p, size_t len) +{ + usb_lld_set_data_to_send ((const void *)p, len); +} diff --git a/src/usb_prop.c b/src/usb_prop.c index 1787156..f2996f9 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -28,6 +28,7 @@ #include "ch.h" #include "usb_lld.h" #include "usb_conf.h" +#include "gnuk.h" #ifdef ENABLE_VIRTUAL_COM_PORT #include "usb-cdc.h" @@ -40,7 +41,7 @@ struct line_coding uint8_t datatype; }; -static const struct line_coding line_coding = { +static struct line_coding line_coding = { 115200, /* baud rate: 115200 */ 0x00, /* stop bits: 1 */ 0x00, /* parity: none */ @@ -48,20 +49,19 @@ static const struct line_coding line_coding = { }; static void -vcom_port_data_setup (uint8_t RequestNo) +vcom_port_data_setup (uint8_t req, uint8_t req_no) { - if (RequestNo != USB_CDC_REQ_GET_LINE_CODING) - return; + if ((req & REQUEST_DIR) == 1 && req_no == USB_CDC_REQ_GET_LINE_CODING) + usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); - /* RequestNo == USB_CDC_REQ_SET_LINE_CODING is not supported */ - - usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); + if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_LINE_CODING) + usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding)); } static int -vcom_port_setup_with_nodata (uint8_t RequestNo) +vcom_port_setup_with_nodata (uint8_t req, uint8_t req_no) { - if (RequestNo == USB_CDC_REQ_SET_CONTROL_LINE_STATE) + if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE) /* Do nothing and success */ return USB_SUCCESS; @@ -183,26 +183,54 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */ static const uint8_t lun_table[] = { 0, 0, 0, 0, }; #endif +static const uint8_t *mem_info[] = { &__heap_base__, &__heap_end__, }; + +#define USB_FSIJ_GNUK_MEMINFO 0 +#define USB_FSIJ_GNUK_DOWNLOAD 1 +#define USB_FSIJ_GNUK_EXEC 2 + static void -gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index) +gnuk_setup_with_data (uint8_t req, uint8_t req_no, uint16_t index, + uint16_t len) { - if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + uint8_t recipient = req & RECIPIENT; + + if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT)) + { + if ((req & REQUEST_DIR) == 1 && req_no == USB_FSIJ_GNUK_MEMINFO) + usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); + else if ((req & REQUEST_DIR) == 0 && req_no == USB_FSIJ_GNUK_DOWNLOAD) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return; + + if ((uint32_t)(index * 0x100) < (uint32_t)&__heap_base__ + || (uint32_t)((index * 0x100) + len) > (uint32_t)&__heap_end__) + return; + + usb_lld_set_data_to_recv ((void *)0x20000000 + index*0x100, len); + } + } + else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { if (index == 0) { - if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) + if ((req & REQUEST_DIR) == 1 + && req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); - else if (RequestNo == USB_CCID_REQ_GET_DATA_RATES) - usb_lld_set_data_to_send (data_rate_table, sizeof (data_rate_table)); + else if ((req & REQUEST_DIR) == 1 + && req_no == USB_CCID_REQ_GET_DATA_RATES) + usb_lld_set_data_to_send (data_rate_table, + sizeof (data_rate_table)); } #ifdef ENABLE_VIRTUAL_COM_PORT else if (index == 1) - vcom_port_data_setup (RequestNo); + vcom_port_data_setup (req, req_no); #endif #ifdef PINPAD_DND_SUPPORT else if (index == MSC_INTERFACE_NO) { - if (RequestNo == MSC_GET_MAX_LUN_COMMAND) + if ((req & REQUEST_DIR) == 1 && req_no == MSC_GET_MAX_LUN_COMMAND) usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); } #endif @@ -211,12 +239,28 @@ gnuk_setup_with_data (uint8_t recipient, uint8_t RequestNo, uint16_t index) static int -gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) +gnuk_setup_with_nodata (uint8_t req, uint8_t req_no, uint16_t index) { - if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */ + uint8_t recipient = req & RECIPIENT; + + if ((req & REQUEST_DIR) == 1) + return USB_UNSUPPORT; + + if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT)) + { + if (req_no == USB_FSIJ_GNUK_EXEC) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return USB_UNSUPPORT; + + *icc_state_p = ICC_STATE_EXEC_REQUESTED; + return USB_SUCCESS; + } + } + else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) if (index == 0) { - if (RequestNo == USB_CCID_REQ_ABORT) + if (req_no == USB_CCID_REQ_ABORT) /* wValue: bSeq, bSlot */ /* Abortion is not supported in Gnuk */ return USB_UNSUPPORT; @@ -225,24 +269,20 @@ gnuk_setup_with_nodata (uint8_t recipient, uint8_t RequestNo, uint16_t index) } #ifdef ENABLE_VIRTUAL_COM_PORT else if (index == 1) - return vcom_port_setup_with_nodata (RequestNo); + return vcom_port_setup_with_nodata (req, req_no); #endif #ifdef PINPAD_DND_SUPPORT else if (index == MSC_INTERFACE_NO) { - if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND) + if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) { /* Should call resetting MSC thread, something like msc_reset() */ return USB_SUCCESS; } - else - return USB_UNSUPPORT; } #endif - else - return USB_UNSUPPORT; - else - return USB_UNSUPPORT; + + return USB_UNSUPPORT; } static int @@ -278,6 +318,8 @@ gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) static int gnuk_usb_event (uint8_t event_type, uint16_t value) { + int i; + switch (event_type) { case USB_EVENT_RESET: @@ -288,10 +330,6 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) case USB_EVENT_CONFIG: if (usb_lld_current_configuration () == 0) { - int i; - extern void *main_thread; -#define LED_STATUS_MODE (8) - if (value != 1) return USB_UNSUPPORT; diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py new file mode 100755 index 0000000..c041ef6 --- /dev/null +++ b/tool/gnuk_upgrade.py @@ -0,0 +1,239 @@ +#! /usr/bin/python + +""" +gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +from intel_hex import * +from struct import * +import sys, time, os, binascii, string + +# INPUT: binary file + +# Assume only single CCID device is attached to computer, and it's Gnuk Token + +import usb + +# USB class, subclass, protocol +CCID_CLASS = 0x0B +CCID_SUBCLASS = 0x00 +CCID_PROTOCOL_0 = 0x00 + +def icc_compose(msg_type, data_len, slot, seq, param, data): + return pack('BBBB', cls, ins, p1, p2) + else: + return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data + +# This class only supports Gnuk (for now) +class gnuk_token: + def __init__(self, device, configuration, interface): + """ + __init__(device, configuration, interface) -> None + Initialize the device. + device: usb.Device object. + configuration: configuration number. + interface: usb.Interface object representing the interface and altenate setting. + """ + if interface.interfaceClass != CCID_CLASS: + raise ValueError, "Wrong interface class" + if interface.interfaceSubClass != CCID_SUBCLASS: + raise ValueError, "Wrong interface sub class" + self.__devhandle = device.open() + try: + self.__devhandle.setConfiguration(configuration) + except: + pass + self.__devhandle.claimInterface(interface) + self.__devhandle.setAltInterface(interface) + + self.__intf = interface.interfaceNumber + self.__alt = interface.alternateSetting + self.__conf = configuration + + self.__bulkout = 2 + self.__bulkin = 0x81 + + self.__timeout = 10000 + self.__seq = 0 + + def icc_get_result(self): + msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) + if len(msg) < 10: + print msg + raise ValueError, "icc_get_result" + msg_type = msg[0] + data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) + slot = msg[5] + seq = msg[6] + status = msg[7] + error = msg[8] + chain = msg[9] + data = msg[10:] + # XXX: check msg_type, data_len, slot, seq, error + return (status, chain, data) + + def icc_get_status(self): + msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_power_on(self): + msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check status, chain + return data # ATR + + def icc_power_off(self): + msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_send_data_block(self, data): + msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + return self.icc_get_result() + + def icc_send_cmd(self, data): + status, chain, data_rcv = self.icc_send_data_block(data) + if chain == 0: + return data_rcv + elif chain == 1: + d = data_rcv + while True: + msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data_rcv = self.icc_get_result() + # XXX: check status + d += data_rcv + if chain == 2: + break + elif chain == 3: + continue + else: + raise ValueError, "icc_send_cmd chain" + return d + else: + raise ValueError, "icc_send_cmd" + + def cmd_get_response(self, expected_len): + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, [expected_len]) + response = self.icc_send_cmd(cmd_data) + return response + + def cmd_verify(self, who, passwd): + cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, "cmd_verify" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_verify" + + def cmd_select_openpgp(self): + cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, "cmd_select_openpgp" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + + def cmd_external_authenticate(self, who, signed): + cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, "cmd_external_authenticate" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_external_authenticate" + +def compare(data_original, data_in_device): + i = 0 + for d in data_original: + if ord(d) != data_in_device[i]: + raise ValueError, "verify failed at %08x" % i + i += 1 + +def get_device(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + for config in dev.configurations: + for intf in config.interfaces: + for alt in intf: + if alt.interfaceClass == CCID_CLASS and \ + alt.interfaceSubClass == CCID_SUBCLASS and \ + alt.interfaceProtocol == CCID_PROTOCOL_0: + return dev, config, alt + raise ValueError, "Device not found" + +def main(passwd, data): + dev, config, intf = get_device() + print "Device: ", dev.filename + print "Configuration: ", config.value + print "Interface: ", intf.interfaceNumber + icc = gnuk_token(dev, config, intf) + if icc.icc_get_status() == 2: + raise ValueError, "No ICC present" + elif icc.icc_get_status() == 1: + icc.icc_power_on() + icc.cmd_verify(3, passwd) + icc.cmd_select_openpgp() + challenge = icc.cmd_get_challenge() + signed = challenge + icc.cmd_external_authenticate(signed) + # set_configure(0) to disable all interfaces but control pipe + # check mem_info + # download flash install program + # exec + # ... + # Then, send upgrade program... + return 0 + +DEFAULT_PW3 = "12345678" + +if __name__ == '__main__': + passwd = DEFAULT_PW3 + if sys.argv[1] == '-p': + from getpass import getpass + passwd = getpass("Admin password: ") + sys.argv.pop(1) + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + print "%s: %d" % (filename, len(data)) + print "Downloading flash upgrade program" + main(passwd, data) From 87d36deeb929d47509d502da754db17aafedf456 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 18 May 2012 11:39:04 +0900 Subject: [PATCH 083/300] more changes for upgrade feature and USB API --- ChangeLog | 18 +++++ src/usb_lld.c | 34 +++++---- src/usb_lld.h | 13 +++- src/usb_prop.c | 191 ++++++++++++++++++++++++++++--------------------- 4 files changed, 157 insertions(+), 99 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bfe9dd..775052a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2012-05-18 Niibe Yutaka + + * src/usb_lld.h (USB_SETUP_SET, USB_SETUP_GET): New. + (usb_device_method.ctrl_write_finish): New. + (usb_device_method.setup): Merge setup_with_data, and + setup_with_nodata. + + * src/usb_lld.c (usb_lld_shutdown, usb_lld_prepare_shutdown): New. + (handle_setup0): Call ->setup. + (handle_in0): Call ->ctrl_write_finish. + + * src/usb_prop.c (vcom_port_data_setup): Merge + vcom_port_setup_with_nodata. + (download_check_crc32): New. + (gnuk_setup): Merge gnuk_setup_with_data and + gnuk_setup_with_nodata. + (gnuk_ctrl_write_finish): New. + 2012-05-17 Niibe Yutaka * tool/gnuk_upgrade.py: New tool. diff --git a/src/usb_lld.c b/src/usb_lld.c index 13fa6c3..33197d6 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -825,25 +825,14 @@ static void handle_setup0 (void) } } else - { - if (ctrl_p->wLength == 0) - r = (*method_p->setup_with_nodata) (ctrl_p->bmRequestType, - req, ctrl_p->wIndex); - else - { - (*method_p->setup_with_data) (ctrl_p->bmRequestType, req, - ctrl_p->wIndex, ctrl_p->wLength); - if (data_p->len != 0) - r = USB_SUCCESS; - } - } - + r = (*method_p->setup) (ctrl_p->bmRequestType, req, + ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength); if (r != USB_SUCCESS) dev_p->state = STALLED; else { - if (ctrl_p->bmRequestType & REQUEST_DIR) + if (USB_SETUP_GET (ctrl_p->bmRequestType)) { uint32_t len = ctrl_p->wLength; @@ -886,6 +875,11 @@ static void handle_in0 (void) st103_set_daddr (ctrl_p->wValue); (*method_p->event) (USB_EVENT_ADDRESS, ctrl_p->wValue); } + else + (*method_p->ctrl_write_finish) (ctrl_p->bmRequestType, + ctrl_p->bRequest, ctrl_p->wValue, + ctrl_p->wIndex, ctrl_p->wLength); + dev_p->state = STALLED; } else @@ -1065,6 +1059,18 @@ void usb_lld_init (void) st103_set_cntr (CNTR_CTRM | CNTR_RESETM); } +void usb_lld_prepare_shutdown (void) +{ + st103_set_istr (0); + st103_set_cntr (0); +} + +void usb_lld_shutdown (void) +{ + st103_set_cntr (CNTR_PDWN); + RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; +} + void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len) { diff --git a/src/usb_lld.h b/src/usb_lld.h index 7355ba3..a01038c 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -46,6 +46,9 @@ enum DESCRIPTOR_TYPE #define VENDOR_REQUEST 0x40 /* Vendor request */ #define RECIPIENT 0x1F /* Mask to get recipient */ +#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0) +#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0) + struct Descriptor { const uint8_t *Descriptor; @@ -62,9 +65,10 @@ struct usb_device_method { void (*init) (void); void (*reset) (void); - void (*setup_with_data) (uint8_t rcp, uint8_t req_no, uint16_t index, - uint16_t len); - int (*setup_with_nodata) (uint8_t rcp, uint8_t req_no, uint16_t index); + void (*ctrl_write_finish) (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, uint16_t len); + int (*setup) (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, uint16_t len); int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value); int (*event) (uint8_t event_type, uint16_t value); int (*interface) (uint8_t cmd, uint16_t interface, uint16_t value); @@ -149,3 +153,6 @@ extern inline void usb_lld_set_data_to_recv (void *p, size_t len) { usb_lld_set_data_to_send ((const void *)p, len); } + +extern void usb_lld_prepare_shutdown (void); +extern void usb_lld_shutdown (void); diff --git a/src/usb_prop.c b/src/usb_prop.c index f2996f9..58ec32f 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -48,22 +48,28 @@ static struct line_coding line_coding = { 0x08 /* bits: 8 */ }; -static void +static int vcom_port_data_setup (uint8_t req, uint8_t req_no) { - if ((req & REQUEST_DIR) == 1 && req_no == USB_CDC_REQ_GET_LINE_CODING) - usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); - - if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_LINE_CODING) - usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding)); -} - -static int -vcom_port_setup_with_nodata (uint8_t req, uint8_t req_no) -{ - if ((req & REQUEST_DIR) == 0 && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE) - /* Do nothing and success */ - return USB_SUCCESS; + if (USB_SETUP_GET (req)) + { + if (req_no == USB_CDC_REQ_GET_LINE_CODING) + { + usb_lld_set_data_to_send (&line_coding, sizeof(line_coding)); + return USB_SUCCESS; + } + } + else /* USB_SETUP_SET (req) */ + { + if (req_no == USB_CDC_REQ_SET_LINE_CODING) + { + usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding)); + return USB_SUCCESS; + } + else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE) + /* Do nothing and success */ + return USB_SUCCESS; + } return USB_UNSUPPORT; } @@ -189,102 +195,123 @@ static const uint8_t *mem_info[] = { &__heap_base__, &__heap_end__, }; #define USB_FSIJ_GNUK_DOWNLOAD 1 #define USB_FSIJ_GNUK_EXEC 2 -static void -gnuk_setup_with_data (uint8_t req, uint8_t req_no, uint16_t index, - uint16_t len) +static int download_check_crc32 (const uint8_t *p) { - uint8_t recipient = req & RECIPIENT; - - if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT)) - { - if ((req & REQUEST_DIR) == 1 && req_no == USB_FSIJ_GNUK_MEMINFO) - usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); - else if ((req & REQUEST_DIR) == 0 && req_no == USB_FSIJ_GNUK_DOWNLOAD) - { - if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) - return; - - if ((uint32_t)(index * 0x100) < (uint32_t)&__heap_base__ - || (uint32_t)((index * 0x100) + len) > (uint32_t)&__heap_end__) - return; - - usb_lld_set_data_to_recv ((void *)0x20000000 + index*0x100, len); - } - } - else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) - { - if (index == 0) - { - if ((req & REQUEST_DIR) == 1 - && req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) - usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); - else if ((req & REQUEST_DIR) == 1 - && req_no == USB_CCID_REQ_GET_DATA_RATES) - usb_lld_set_data_to_send (data_rate_table, - sizeof (data_rate_table)); - } -#ifdef ENABLE_VIRTUAL_COM_PORT - else if (index == 1) - vcom_port_data_setup (req, req_no); -#endif -#ifdef PINPAD_DND_SUPPORT - else if (index == MSC_INTERFACE_NO) - { - if ((req & REQUEST_DIR) == 1 && req_no == MSC_GET_MAX_LUN_COMMAND) - usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); - } -#endif - } + return USB_SUCCESS; } - static int -gnuk_setup_with_nodata (uint8_t req, uint8_t req_no, uint16_t index) +gnuk_setup (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, uint16_t len) { - uint8_t recipient = req & RECIPIENT; + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); - if ((req & REQUEST_DIR) == 1) - return USB_UNSUPPORT; - - if (recipient == (VENDOR_REQUEST | DEVICE_RECIPIENT)) + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)) { - if (req_no == USB_FSIJ_GNUK_EXEC) + if (USB_SETUP_GET (req)) { - if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) - return USB_UNSUPPORT; + if (req_no == USB_FSIJ_GNUK_MEMINFO) + { + usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); + return USB_SUCCESS; + } + } + else /* SETUP_SET */ + { + uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index); - *icc_state_p = ICC_STATE_EXEC_REQUESTED; - return USB_SUCCESS; + if (req_no == USB_FSIJ_GNUK_DOWNLOAD) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return USB_UNSUPPORT; + + if (addr < &__heap_base__ || addr + len > &__heap_end__) + return USB_UNSUPPORT; + + if (index == 0) + memset (addr, 0, 256); + usb_lld_set_data_to_recv (addr, len); + return USB_SUCCESS; + } + else if (req_no == USB_FSIJ_GNUK_EXEC && len == 0) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return USB_UNSUPPORT; + + /* There is a trailer at addr: size, crc32 */ + return download_check_crc32 (addr); + } } } - else if (recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)) if (index == 0) { - if (req_no == USB_CCID_REQ_ABORT) - /* wValue: bSeq, bSlot */ - /* Abortion is not supported in Gnuk */ - return USB_UNSUPPORT; + if (USB_SETUP_GET (req)) + { + if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES) + { + usb_lld_set_data_to_send (freq_table, sizeof (freq_table)); + return USB_SUCCESS; + } + else if (req_no == USB_CCID_REQ_GET_DATA_RATES) + { + usb_lld_set_data_to_send (data_rate_table, + sizeof (data_rate_table)); + return USB_SUCCESS; + } + } else - return USB_UNSUPPORT; + { + if (req_no == USB_CCID_REQ_ABORT) + /* wValue: bSeq, bSlot */ + /* Abortion is not supported in Gnuk */ + return USB_UNSUPPORT; + } } #ifdef ENABLE_VIRTUAL_COM_PORT else if (index == 1) - return vcom_port_setup_with_nodata (req, req_no); + return vcom_port_data_setup (req, req_no); #endif #ifdef PINPAD_DND_SUPPORT else if (index == MSC_INTERFACE_NO) { - if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) + if (USB_SETUP_GET (req)) { + if (req_no == MSC_GET_MAX_LUN_COMMAND) + { + usb_lld_set_data_to_send (lun_table, sizeof (lun_table)); + return USB_SUCCESS; + } + } + else + if (req_no == MSC_MASS_STORAGE_RESET_COMMAND) /* Should call resetting MSC thread, something like msc_reset() */ return USB_SUCCESS; - } } #endif return USB_UNSUPPORT; } +static void gnuk_ctrl_write_finish (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, + uint16_t len) +{ + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); + + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) + && USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC && len == 0) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return; + + (void)value; (void)index; + usb_lld_prepare_shutdown (); /* No further USB communication */ + *icc_state_p = ICC_STATE_EXEC_REQUESTED; + } +} + + static int gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) { @@ -392,8 +419,8 @@ static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt) const struct usb_device_method Device_Method = { gnuk_device_init, gnuk_device_reset, - gnuk_setup_with_data, - gnuk_setup_with_nodata, + gnuk_ctrl_write_finish, + gnuk_setup, gnuk_get_descriptor, gnuk_usb_event, gnuk_interface, From c723df084171090da08325aad72756bb65694024 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 18 May 2012 16:54:17 +0900 Subject: [PATCH 084/300] more regnual --- src/Makefile.in | 8 ---- src/gnuk.h | 2 +- src/gnuk.ld.in | 2 + src/main.c | 9 +++- src/usb_lld.h | 1 - src/usb_prop.c | 10 ++--- tool/gnuk_put_binary_libusb.py | 2 +- tool/gnuk_upgrade.py | 76 ++++++++++++++++++++++++---------- 8 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index eed49be..4237c36 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -80,7 +80,6 @@ CSRC = $(PORTSRC) \ $(BOARD_DIR)/board.c \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ - $(VCOMSRC) \ $(CRYPTSRC) \ main.c usb_lld.c \ usb_desc.c usb_prop.c \ @@ -195,13 +194,6 @@ ULIBS = # End of user defines ############################################################################## -ifeq ($(USE_FWLIB),yes) - include $(CHIBIOS)/ext/stm32lib/stm32lib.mk - CSRC += $(STM32SRC) - INCDIR += $(STM32INC) - USE_OPT += -DUSE_STDPERIPH_DRIVER -endif - include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd diff --git a/src/gnuk.h b/src/gnuk.h index 1b1874a..5972d3d 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -389,4 +389,4 @@ extern int pinpad_getline (int msg_code, systime_t timeout); #endif -extern uint8_t __heap_base__, __heap_end__; +extern uint8_t _regnual_start, __heap_end__; diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 31f0387..23a382f 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -114,6 +114,8 @@ SECTIONS PROVIDE(end = .); _end = .; + . = ALIGN(256); + _regnual_start = .; @CERTDO_SUPPORT_START@ .gnuk_ch_certificate : diff --git a/src/main.c b/src/main.c index 0f4bb0b..8da6e43 100644 --- a/src/main.c +++ b/src/main.c @@ -375,7 +375,7 @@ led_blink (int spec) * See the hwinit1_common function. */ int -main (int argc, char **argv) +main (int argc, char *argv[]) { int count = 0; @@ -418,6 +418,9 @@ main (int argc, char **argv) { eventmask_t m; + if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) + break; + count++; m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL); switch (m) @@ -469,6 +472,10 @@ main (int argc, char **argv) #endif } + usb_lld_shutdown (); + /* erase by mass erase */ + /* set vector */ + /* SYSRESETREQ to invoke regnual */ return 0; } diff --git a/src/usb_lld.h b/src/usb_lld.h index a01038c..2652dad 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -75,7 +75,6 @@ struct usb_device_method }; enum { - USB_EVENT_RESET, USB_EVENT_ADDRESS, USB_EVENT_CONFIG, USB_EVENT_SUSPEND, diff --git a/src/usb_prop.c b/src/usb_prop.c index 58ec32f..7bddfc2 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -189,7 +189,7 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */ static const uint8_t lun_table[] = { 0, 0, 0, 0, }; #endif -static const uint8_t *mem_info[] = { &__heap_base__, &__heap_end__, }; +static const uint8_t *mem_info[] = { &_regnual_start, &__heap_end__, }; #define USB_FSIJ_GNUK_MEMINFO 0 #define USB_FSIJ_GNUK_DOWNLOAD 1 @@ -225,7 +225,7 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) return USB_UNSUPPORT; - if (addr < &__heap_base__ || addr + len > &__heap_end__) + if (addr < &_regnual_start || addr + len > &__heap_end__) return USB_UNSUPPORT; if (index == 0) @@ -349,11 +349,9 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) switch (event_type) { - case USB_EVENT_RESET: - break; case USB_EVENT_ADDRESS: bDeviceState = ADDRESSED; - break; + return USB_SUCCESS; case USB_EVENT_CONFIG: if (usb_lld_current_configuration () == 0) { @@ -365,7 +363,6 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) gnuk_setup_endpoints_for_interface (i, 0); bDeviceState = CONFIGURED; chEvtSignalI (main_thread, LED_STATUS_MODE); - return USB_SUCCESS; } else { @@ -377,6 +374,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) gnuk_setup_endpoints_for_interface (i, 1); bDeviceState = ADDRESSED; } + return USB_SUCCESS; default: break; } diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 98069c8..8ed42e0 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -75,7 +75,7 @@ class gnuk_token: self.__alt = interface.alternateSetting self.__conf = configuration - self.__bulkout = 2 + self.__bulkout = 1 self.__bulkin = 0x81 self.__timeout = 10000 diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index c041ef6..682d877 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -46,7 +46,7 @@ def iso7816_compose(ins, p1, p2, data): if data_len == 0: return pack('>BBBB', cls, ins, p1, p2) else: - return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data + return pack('>BBBBB', cls, ins, p1, p2, data_len) + data # This class only supports Gnuk (for now) class gnuk_token: @@ -74,16 +74,28 @@ class gnuk_token: self.__alt = interface.alternateSetting self.__conf = configuration - self.__bulkout = 2 + self.__bulkout = 1 self.__bulkin = 0x81 self.__timeout = 10000 self.__seq = 0 + def stop_icc(self): + # XXX: need to disclaim interface and close device and re-open??? + # self.__devhandle.setConfiguration(0) + return + + def mem_info(self): + mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0, + value = 0, index = 0, buffer = 8, + timeout = 10) + start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0] + end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4] + return (start, end) + def icc_get_result(self): msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) if len(msg) < 10: - print msg raise ValueError, "icc_get_result" msg_type = msg[0] data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) @@ -150,33 +162,42 @@ class gnuk_token: raise ValueError, "icc_send_cmd" def cmd_get_response(self, expected_len): - cmd_data = iso7816_compose(0xc0, 0x00, 0x00, [expected_len]) + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) response = self.icc_send_cmd(cmd_data) - return response + return response[:-2] def cmd_verify(self, who, passwd): cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, "cmd_verify" + raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_verify" + raise ValueError, sw def cmd_select_openpgp(self): cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, "cmd_select_openpgp" + raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): raise ValueError, ("%02x%02x" % (sw[0], sw[1])) - def cmd_external_authenticate(self, who, signed): + def cmd_external_authenticate(self, signed): cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, "cmd_external_authenticate" + raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_external_authenticate" + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + + def cmd_get_challenge(self): + cmd_data = iso7816_compose(0x84, 0x00, 0x00, '') + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) def compare(data_original, data_in_device): i = 0 @@ -199,7 +220,13 @@ def get_device(): return dev, config, alt raise ValueError, "Device not found" -def main(passwd, data): +def to_string(t): + result = "" + for c in t: + result += chr(c) + return result + +def main(passwd, data_regnual, data_upgrade): dev, config, intf = get_device() print "Device: ", dev.filename print "Configuration: ", config.value @@ -212,14 +239,17 @@ def main(passwd, data): icc.cmd_verify(3, passwd) icc.cmd_select_openpgp() challenge = icc.cmd_get_challenge() - signed = challenge + signed = to_string(challenge) icc.cmd_external_authenticate(signed) - # set_configure(0) to disable all interfaces but control pipe - # check mem_info + icc.stop_icc() # disable all interfaces but control pipe + mem_info icc.mem_info() + print "%08x: %08x" % mem_info # download flash install program # exec # ... + print "Downloading flash upgrade program" # Then, send upgrade program... + print "Downloading the program" return 0 DEFAULT_PW3 = "12345678" @@ -230,10 +260,14 @@ if __name__ == '__main__': from getpass import getpass passwd = getpass("Admin password: ") sys.argv.pop(1) - filename = sys.argv[1] - f = open(filename) - data = f.read() + filename_regnual = sys.argv[1] + filename_upgrade = sys.argv[2] + f = open(filename_regnual) + data_regnual = f.read() f.close() - print "%s: %d" % (filename, len(data)) - print "Downloading flash upgrade program" - main(passwd, data) + print "%s: %d" % (filename_regnual, len(data_regnual)) + f = open(filename_upgrade) + data_upgrade = f.read() + f.close() + print "%s: %d" % (filename_upgrade, len(data_upgrade)) + main(passwd, data_regnual, data_upgrade) From 0c4fb96c1ad93900a7d8dd1082734e7f54d763bd Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 18 May 2012 19:02:26 +0900 Subject: [PATCH 085/300] bug fix for control_write --- src/usb_lld.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/usb_lld.c b/src/usb_lld.c index 33197d6..d6e8c39 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -385,16 +385,15 @@ static void handle_datastage_out (void) if (data_p->addr && data_p->len) { uint8_t *buf; - uint32_t len = USB_MAX_PACKET_SIZE; + uint32_t len = st103_get_rx_count (ENDP0); if (len > data_p->len) len = data_p->len; buf = data_p->addr + data_p->offset; + usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len); data_p->len -= len; data_p->offset += len; - - usb_lld_from_pmabuf (buf, st103_get_rx_addr (ENDP0), len); } if (data_p->len == 0) @@ -405,8 +404,8 @@ static void handle_datastage_out (void) } else { - st103_ep_set_rx_status (ENDP0, EP_RX_VALID); dev_p->state = OUT_DATA; + st103_ep_set_rx_status (ENDP0, EP_RX_VALID); } } @@ -427,7 +426,7 @@ static void handle_datastage_in (void) } else { - /* No more data to send, but receive OUT.*/ + /* No more data to send, but receive OUT acknowledge.*/ dev_p->state = WAIT_STATUS_OUT; st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); } @@ -857,7 +856,7 @@ static void handle_setup0 (void) else { dev_p->state = OUT_DATA; - st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); + st103_ep_set_rx_status (ENDP0, EP_RX_VALID); } } } From 48f143aa3153ae15ead1ba3d089a420d696f8b64 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 18 May 2012 19:02:53 +0900 Subject: [PATCH 086/300] more upgrade --- src/usb_prop.c | 2 +- tool/gnuk_upgrade.py | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/usb_prop.c b/src/usb_prop.c index 7bddfc2..98c29e3 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -228,7 +228,7 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (addr < &_regnual_start || addr + len > &__heap_end__) return USB_UNSUPPORT; - if (index == 0) + if (index == 0 && len != 256) memset (addr, 0, 256); usb_lld_set_data_to_recv (addr, len); return USB_SUCCESS; diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 682d877..b9e3757 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -93,6 +93,33 @@ class gnuk_token: end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4] return (start, end) + def download(self, start, data): + addr = start + addr_end = start + len(data) + i = (addr - 0x20000000) / 0x100 + print "start %08x" % addr + print "end %08x" % addr_end + while addr < addr_end: + print "# %08x: %d : %d" % (addr, i, 256) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = i, index = 0, + buffer = data[i*256:i*256+256], + timeout = 10) + i = i+1 + addr = addr + 256 + residue = len(data) % 256 + if residue != 0: + print "# %08x: %d : %d" % (addr, i, residue) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = i, index = 0, + buffer = data[i*256:], + timeout = 10) + + def execute(self): + self.__devhandle.controlMsg(requestType = 0x40, request = 2, + value = 0, index = 0, buffer = None, + timeout = 10) + def icc_get_result(self): msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) if len(msg) < 10: @@ -242,12 +269,12 @@ def main(passwd, data_regnual, data_upgrade): signed = to_string(challenge) icc.cmd_external_authenticate(signed) icc.stop_icc() # disable all interfaces but control pipe - mem_info icc.mem_info() - print "%08x: %08x" % mem_info - # download flash install program - # exec - # ... - print "Downloading flash upgrade program" + mem_info = icc.mem_info() + print "%08x:%08x" % mem_info + print "Downloading flash upgrade program..." + icc.download(mem_info[0], data_regnual) + print "Run flash upgrade program..." + icc.execute() # Then, send upgrade program... print "Downloading the program" return 0 From b7599feb4f2b33da115a1f15552405ed3cce11e9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 18 May 2012 19:03:09 +0900 Subject: [PATCH 087/300] more upgrade --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 775052a..6b8fd9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-05-18 Niibe Yutaka + * src/usb_lld.c (handle_datastage_out): Fix rx copying. + (handle_setup0): Bug fix not stalling TX, it will be possible + to go IN transaction, soon after OUT transaction. + * src/usb_lld.h (USB_SETUP_SET, USB_SETUP_GET): New. (usb_device_method.ctrl_write_finish): New. (usb_device_method.setup): Merge setup_with_data, and From 810b0d9a5b4dfa38d0a408af1e46ed09cc1ec052 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 19 May 2012 01:40:44 +0900 Subject: [PATCH 088/300] bug fix for control_read --- ChangeLog | 6 ++++++ src/usb_lld.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b8fd9d..ecb47ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-05-19 Niibe Yutaka + + * src/usb_lld.c (handle_datastage_in): Bug fix, erable RX when + sending ZLP. It will be possible to get OUT transaction soon + after IN transaction. + 2012-05-18 Niibe Yutaka * src/usb_lld.c (handle_datastage_out): Fix rx copying. diff --git a/src/usb_lld.c b/src/usb_lld.c index d6e8c39..948f3a7 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -422,11 +422,11 @@ static void handle_datastage_in (void) /* No more data to send. Send empty packet */ st103_set_tx_count (ENDP0, 0); - st103_ep_set_tx_status (ENDP0, EP_TX_VALID); + st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID); } else { - /* No more data to send, but receive OUT acknowledge.*/ + /* No more data to send, proceed to receive OUT acknowledge.*/ dev_p->state = WAIT_STATUS_OUT; st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); } From f95cf8942b020aba47fd27da4dd04fc882e1b500 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 19 May 2012 02:05:31 +0900 Subject: [PATCH 089/300] upgrade: gnuk side working now --- src/gnuk.ld.in | 2 +- src/main.c | 17 ++++++++++++++++- src/usb_prop.c | 12 ++++++++++-- tool/gnuk_upgrade.py | 20 +++++++++++++------- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 23a382f..91e6c12 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -114,7 +114,7 @@ SECTIONS PROVIDE(end = .); _end = .; - . = ALIGN(256); + . = ALIGN(512); _regnual_start = .; @CERTDO_SUPPORT_START@ diff --git a/src/main.c b/src/main.c index 8da6e43..9b99567 100644 --- a/src/main.c +++ b/src/main.c @@ -23,6 +23,7 @@ #include "config.h" #include "ch.h" +#include "hal.h" #include "gnuk.h" #include "usb_lld.h" #include "usb-cdc.h" @@ -473,9 +474,23 @@ main (int argc, char *argv[]) } usb_lld_shutdown (); - /* erase by mass erase */ + USB_Cable_Config (0); + set_led (1); + chThdSleep (MS2ST (100)); + port_disable (); /* set vector */ + SCB->VTOR = (uint32_t)&_regnual_start; +#if 0 /* SYSRESETREQ to invoke regnual */ + NVIC_SystemReset (); +#else + { + /* Not yet: erase by mass erase and go to entry */ + void (**func)(void) = (void (**)(void))(&_regnual_start + 4); + + (**func) (); + } +#endif return 0; } diff --git a/src/usb_prop.c b/src/usb_prop.c index 98c29e3..a7ca500 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -189,7 +189,7 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */ static const uint8_t lun_table[] = { 0, 0, 0, 0, }; #endif -static const uint8_t *mem_info[] = { &_regnual_start, &__heap_end__, }; +static const uint8_t *const mem_info[] = { &_regnual_start, &__heap_end__, }; #define USB_FSIJ_GNUK_MEMINFO 0 #define USB_FSIJ_GNUK_DOWNLOAD 1 @@ -197,6 +197,14 @@ static const uint8_t *mem_info[] = { &_regnual_start, &__heap_end__, }; static int download_check_crc32 (const uint8_t *p) { + uint32_t crc32 = 0; + + crc32 += (*--p << 24); + crc32 += (*--p << 16); + crc32 += (*--p << 8); + crc32 += (*--p); + + /* Not yet: Calculate crc32 from &_regnual_start to p, then compare */ return USB_SUCCESS; } @@ -238,7 +246,7 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) return USB_UNSUPPORT; - /* There is a trailer at addr: size, crc32 */ + /* There is a trailer at addr: crc32 */ return download_check_crc32 (addr); } } diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index b9e3757..43a53fa 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -95,29 +95,33 @@ class gnuk_token: def download(self, start, data): addr = start - addr_end = start + len(data) + addr_end = (start + len(data)) & 0xffffff00 i = (addr - 0x20000000) / 0x100 + j = 0 print "start %08x" % addr print "end %08x" % addr_end while addr < addr_end: print "# %08x: %d : %d" % (addr, i, 256) self.__devhandle.controlMsg(requestType = 0x40, request = 1, value = i, index = 0, - buffer = data[i*256:i*256+256], + buffer = data[j*256:j*256+256], timeout = 10) i = i+1 + j = j+1 addr = addr + 256 residue = len(data) % 256 if residue != 0: print "# %08x: %d : %d" % (addr, i, residue) self.__devhandle.controlMsg(requestType = 0x40, request = 1, value = i, index = 0, - buffer = data[i*256:], + buffer = data[j*256:], timeout = 10) - def execute(self): + def execute(self, last_addr): + i = (last_addr - 0x20000000) / 0x100 + o = (last_addr - 0x20000000) % 0x100 self.__devhandle.controlMsg(requestType = 0x40, request = 2, - value = 0, index = 0, buffer = None, + value = i, index = o, buffer = None, timeout = 10) def icc_get_result(self): @@ -254,6 +258,8 @@ def to_string(t): return result def main(passwd, data_regnual, data_upgrade): + data_regnual += pack(' Date: Sat, 19 May 2012 02:07:31 +0900 Subject: [PATCH 090/300] testing regnual --- regnual/Makefile.in | 182 +++++++++++++++++++++++++++ regnual/regnual.c | 280 ++++++++++++++++++++++++++++++++++++++++++ regnual/regnual.ld.in | 98 +++++++++++++++ 3 files changed, 560 insertions(+) create mode 100644 regnual/Makefile.in create mode 100644 regnual/regnual.c create mode 100644 regnual/regnual.ld.in diff --git a/regnual/Makefile.in b/regnual/Makefile.in new file mode 100644 index 0000000..58254d8 --- /dev/null +++ b/regnual/Makefile.in @@ -0,0 +1,182 @@ +# Makefile for reGNUal + +BOARD_DIR=@BOARD_DIR@ + +############################################################################## +# Build global options +# NOTE: Can be overridden externally. +# + +# Compiler options here. +ifeq ($(USE_OPT),) + USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 +endif + +# C++ specific options here (added to USE_OPT). +ifeq ($(USE_CPPOPT),) + USE_CPPOPT = -fno-rtti +endif + +# Enable this if you want the linker to remove unused code and data +ifeq ($(USE_LINK_GC),) + USE_LINK_GC = yes +endif + +# If enabled, this option allows to compile the application in THUMB mode. +ifeq ($(USE_THUMB),) + USE_THUMB = yes +endif + +# Enable register caching optimization (read documentation). +ifeq ($(USE_CURRP_CACHING),) + USE_CURRP_CACHING = no +endif + +# +# Build global options +############################################################################## + +############################################################################## +# Architecture or project specific options +# + +# Enable this if you really want to use the STM FWLib. +ifeq ($(USE_FWLIB),) + USE_FWLIB = no +endif + +# +# Architecture or project specific options +############################################################################## + +############################################################################## +# Project, sources and paths +# + +# Define project name here +PROJECT = regnual + +# Define linker script file here +LDSCRIPT= regnual.ld + +# Imported source files +CHIBIOS = ../ChibiOS_2.0.8 +include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk +include $(CHIBIOS)/os/hal/hal.mk +include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk +include $(CHIBIOS)/os/kernel/kernel.mk + +# C sources that can be compiled in ARM or THUMB mode depending on the global +# setting. +CSRC = $(PORTSRC) \ + $(KERNSRC) \ + $(HALSRC) \ + $(PLATFORMSRC) \ + $(BOARDSRC) \ + ../boards/common/hw_config.c \ + $(BOARD_DIR)/board.c \ + $(CHIBIOS)/os/various/evtimer.c \ + $(CHIBIOS)/os/various/syscalls.c \ + regnual.c usb_lld.c + +# List ASM source files here +ASMSRC = $(PORTASM) \ + $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s + +INCDIR = $(CRYPTINCDIR) \ + $(PORTINC) $(KERNINC) $(TESTINC) \ + $(HALINC) $(PLATFORMINC) ../boards/common $(BOARD_DIR) \ + $(CHIBIOS)/os/various + +# +# Project, sources and paths +############################################################################## + +############################################################################## +# Compiler settings +# + +MCU = cortex-m3 + +#TRGT = arm-elf- +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +CPPC = $(TRGT)g++ +# Enable loading with g++ only if you need C++ runtime support. +# NOTE: You can use C++ even without C++ support if you are careful. C++ +# runtime support makes code size explode. +LD = $(TRGT)gcc +#LD = $(TRGT)g++ +CP = $(TRGT)objcopy +AS = $(TRGT)gcc -x assembler-with-cpp +OD = $(TRGT)objdump +HEX = $(CP) -O ihex +BIN = $(CP) -O binary + +# ARM-specific options here +AOPT = + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB + +# Define C warning options here +CWARN = -Wall -Wextra -Wstrict-prototypes + +# Define C++ warning options here +CPPWARN = -Wall -Wextra + +# +# Compiler settings +############################################################################## + +############################################################################## +# Start of default section +# + +# List all default C defines here, like -D_DEBUG=1 +DDEFS = -DCORTEX_USE_BASEPRI=TRUE + +# List all default ASM defines here, like -D_DEBUG=1 +DADEFS = + +# List all default directories to look for include files here +DINCDIR = + +# List the default directory to look for the libraries here +DLIBDIR = + +# List all default libraries here +DLIBS = + +# +# End of default section +############################################################################## + +############################################################################## +# Start of user section +# + +# List all user C define here, like -D_DEBUG=1 +UDEFS = + +# Define ASM defines here +UADEFS = + +# List all user directories here +UINCDIR = + +# List the user directory to look for the libraries here +ULIBDIR = + +# List all user libraries here +ULIBS = + +# +# End of user defines +############################################################################## + +include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk +MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd + +distclean: clean + -rm -f Makefile regnual.ld diff --git a/regnual/regnual.c b/regnual/regnual.c new file mode 100644 index 0000000..9f1d3f8 --- /dev/null +++ b/regnual/regnual.c @@ -0,0 +1,280 @@ +/* + * regnual.c -- Firmware installation for STM32F103 Flash ROM + * + * Copyright (C) 2012 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + +/* + * ReGNUal + */ + +#include "ch.h" +#include "usb_lld.h" + +extern void set_led (int); +extern void *memset (void *s, int c, size_t n); + +#define ENDP0_RXADDR (0x40) +#define ENDP0_TXADDR (0x80) + +/* USB Standard Device Descriptor */ +static const uint8_t regnual_device_desc[] = { + 18, /* bLength */ + USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ + 0x10, 0x01, /* bcdUSB = 1.1 */ + 0xFF, /* bDeviceClass: VENDOR */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + 0x40, /* bMaxPacketSize0 */ +#include "usb-vid-pid-ver.c.inc" + 1, /* Index of string descriptor describing manufacturer */ + 2, /* Index of string descriptor describing product */ + 3, /* Index of string descriptor describing the device's serial number */ + 0x01 /* bNumConfigurations */ +}; + +static const uint8_t regnual_config_desc[] = { + 9, + USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ + 9, 0, /* wTotalLength: no of returned bytes */ + 0, /* bNumInterfaces: None, but control pipe */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: None */ +#if defined(USB_SELF_POWERED) + 0xC0, /* bmAttributes: self powered */ +#else + 0x80, /* bmAttributes: bus powered */ +#endif + 50, /* MaxPower 100 mA */ +}; + +static const uint8_t regnual_string_lang_id[] = { + 4, /* bLength */ + USB_STRING_DESCRIPTOR_TYPE, + 0x09, 0x04 /* LangID = 0x0409: US-English */ +}; + +#include "usb-string-vendor-product.c.inc" + +static const uint8_t regnual_string_serial[] = { + 8*2+2, + USB_STRING_DESCRIPTOR_TYPE, + /* FSIJ-0.0 */ + 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, + '0', 0, '.', 0, '0', 0, +}; + +const struct Descriptor Device_Descriptor = { + regnual_device_desc, + sizeof (regnual_device_desc) +}; + +const struct Descriptor Config_Descriptor = { + regnual_config_desc, + sizeof (regnual_config_desc) +}; + +const struct Descriptor String_Descriptors[] = { + {regnual_string_lang_id, sizeof (regnual_string_lang_id)}, + {gnukStringVendor, sizeof (gnukStringVendor)}, + {gnukStringProduct, sizeof (gnukStringProduct)}, + {regnual_string_serial, sizeof (regnual_string_serial)}, +}; + +#define NUM_STRING_DESC (sizeof (String_Descriptors)/sizeof (struct Descriptor)) + +static void +regnual_device_init (void) +{ + usb_lld_set_configuration (0); + USB_Cable_Config (1); +} + +static void +regnual_device_reset (void) +{ + /* Set DEVICE as not configured */ + usb_lld_set_configuration (0); + + /* Current Feature initialization */ + usb_lld_set_feature (Config_Descriptor.Descriptor[7]); + + usb_lld_reset (); + + /* Initialize Endpoint 0 */ + usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, + 64); +} + +#define USB_REGNUAL_MEMINFO 0 +#define USB_REGNUAL_SEND 1 +#define USB_REGNUAL_CRC32 2 +#define USB_REGNUAL_FLASH 3 +#define USB_REGNUAL_ERASE 4 +#define USB_REGNUAL_PROTECT 5 +#define USB_REGNUAL_FINISH 6 + +static uint8_t mem[1024]; + +static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, + uint16_t len) +{ + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); + + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) + && USB_SETUP_SET (req) && req_no == USB_REGNUAL_FINISH && len == 0) + { + (void)value; (void)index; + /* RESET MCU */ + } +} + +extern uint8_t _flash_start, _flash_end; +static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; + +static int +regnual_setup (uint8_t req, uint8_t req_no, + uint16_t value, uint16_t index, uint16_t len) +{ + uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); + + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)) + { + if (USB_SETUP_GET (req)) + { + if (req_no == USB_REGNUAL_MEMINFO) + { + usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_CRC32) + { + static uint32_t crc32_check = 0; /* calculate CRC32 for mem */ + + usb_lld_set_data_to_send (&crc32_check, sizeof (uint32_t)); + return USB_SUCCESS; + } + } + else /* SETUP_SET */ + { + if (req_no == USB_REGNUAL_SEND) + { + if (value >= 4 || value * 0x100 + index + len > 1024) + return USB_UNSUPPORT; + + if (value == 0 && index == 0) + memset (mem + value * 0x100, 0xff, 1024); + usb_lld_set_data_to_recv (mem + value * 0x100 + index, len); + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_FLASH && len == 0) + { + uint8_t *addr = (uint8_t *)(0x08000000 + value * 0x400); + + /* flash write, verify */ + return USB_SUCCESS; + } + } + } + + return USB_UNSUPPORT; +} + +static int +regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) +{ + (void)index; + if (desc_type == DEVICE_DESCRIPTOR) + { + usb_lld_set_data_to_send (Device_Descriptor.Descriptor, + Device_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == CONFIG_DESCRIPTOR) + { + usb_lld_set_data_to_send (Config_Descriptor.Descriptor, + Config_Descriptor.Descriptor_Size); + return USB_SUCCESS; + } + else if (desc_type == STRING_DESCRIPTOR) + { + uint8_t desc_index = value & 0xff; + + if (desc_index < NUM_STRING_DESC) + { + usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor, + String_Descriptors[desc_index].Descriptor_Size); + return USB_SUCCESS; + } + } + + return USB_UNSUPPORT; +} + +static int regnual_usb_event (uint8_t event_type, uint16_t value) +{ + (void)value; + + switch (event_type) + { + case USB_EVENT_ADDRESS: + case USB_EVENT_CONFIG: + return USB_SUCCESS; + default: + break; + } + + return USB_UNSUPPORT; +} + +static int regnual_interface (uint8_t cmd, uint16_t interface, uint16_t alt) +{ + (void)cmd; (void)interface; (void)alt; + return USB_UNSUPPORT; +} + +const struct usb_device_method Device_Method = { + regnual_device_init, + regnual_device_reset, + regnual_ctrl_write_finish, + regnual_setup, + regnual_get_descriptor, + regnual_usb_event, + regnual_interface, +}; + +int +main (int argc, char *argv[]) +{ + (void)argc; (void)argv; + + set_led (0); + + usb_lld_init (); + + while (1) + { + set_led (1); + chThdSleep (MS2ST (200)); + set_led (0); + chThdSleep (MS2ST (200)); + } +} diff --git a/regnual/regnual.ld.in b/regnual/regnual.ld.in new file mode 100644 index 0000000..54aceb5 --- /dev/null +++ b/regnual/regnual.ld.in @@ -0,0 +1,98 @@ +/* + * ST32F103 memory setup. + */ +__main_stack_size__ = 0x0400; +__process_stack_size__ = 0x0200; +__stacks_total_size__ = __main_stack_size__ + __process_stack_size__; + +MEMORY +{ + flash : org = @ORIGIN@, len = @FLASH_SIZE@k + ram0 : org = 0x20000000, len = @REGNUAL_START@ + ram1 : org = 0x20001300, len = 20k - @REGNUAL_START@ +} + +_flash_start = 0x08000000; +_flash_end = @FLASH_END@; + +__ram_start__ = ORIGIN(ram0); +__ram_size__ = 20k; +__ram_end__ = __ram_start__ + __ram_size__; + +SECTIONS +{ + . = 0; + + .bss : + { + _bss_start = .; + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > ram0 + + .text : ALIGN(16) SUBALIGN(16) + { + _text = .; + KEEP(*(vectors)) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > ram1 + + .ctors : + { + PROVIDE(_ctors_start_ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(_ctors_end_ = .); + } > ram1 + + .dtors : + { + PROVIDE(_dtors_start_ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(_dtors_end_ = .); + } > ram1 + + .ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} + + __exidx_start = .; + .ARM.exidx : {*(.ARM.exidx* .gnu.linkonce.armexidx.*)} > ram1 + __exidx_end = .; + + .eh_frame_hdr : {*(.eh_frame_hdr)} + + .eh_frame : ONLY_IF_RO {*(.eh_frame)} + + . = ALIGN(4); + _etext = .; + _textdata = _etext; + + .data : + { + _data = .; + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + _edata = .; + } > ram1 + + PROVIDE(end = .); + _end = .; +} + +__heap_base__ = _end; +__heap_end__ = __ram_end__ - __stacks_total_size__; From 449b3c35ba75c0a88c5faafeae2e6e098f6871dc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 10:44:37 +0900 Subject: [PATCH 091/300] update regnual --- regnual/regnual.c | 24 ++-- regnual/sys-stbee.h | 16 +++ regnual/sys.c | 310 ++++++++++++++++++++++++++++++++++++++++++++ regnual/types.h | 10 ++ 4 files changed, 349 insertions(+), 11 deletions(-) create mode 100644 regnual/sys-stbee.h create mode 100644 regnual/sys.c create mode 100644 regnual/types.h diff --git a/regnual/regnual.c b/regnual/regnual.c index 9f1d3f8..b6707e5 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -25,7 +25,7 @@ * ReGNUal */ -#include "ch.h" +#include "types.h" #include "usb_lld.h" extern void set_led (int); @@ -100,13 +100,6 @@ const struct Descriptor String_Descriptors[] = { #define NUM_STRING_DESC (sizeof (String_Descriptors)/sizeof (struct Descriptor)) -static void -regnual_device_init (void) -{ - usb_lld_set_configuration (0); - USB_Cable_Config (1); -} - static void regnual_device_reset (void) { @@ -252,7 +245,6 @@ static int regnual_interface (uint8_t cmd, uint16_t interface, uint16_t alt) } const struct usb_device_method Device_Method = { - regnual_device_init, regnual_device_reset, regnual_ctrl_write_finish, regnual_setup, @@ -261,6 +253,16 @@ const struct usb_device_method Device_Method = { regnual_interface, }; +static void wait (int count) +{ + int i; + + for (i = 0; i < count; i++) + asm volatile ("" : : "r" (i) : "memory"); +} + +#define WAIT 2400000 + int main (int argc, char *argv[]) { @@ -273,8 +275,8 @@ main (int argc, char *argv[]) while (1) { set_led (1); - chThdSleep (MS2ST (200)); + wait (WAIT); set_led (0); - chThdSleep (MS2ST (200)); + wait (WAIT); } } diff --git a/regnual/sys-stbee.h b/regnual/sys-stbee.h new file mode 100644 index 0000000..e164790 --- /dev/null +++ b/regnual/sys-stbee.h @@ -0,0 +1,16 @@ +/* + * system settings. + */ +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#define STM32_PLLMUL_VALUE 6 +#define STM32_HSECLK 12000000 + +#define GPIO_USB_CLEAR_TO_ENABLE 3 +#define GPIO_LED_CLEAR_TO_EMIT 4 + +#define VAL_GPIO_ODR 0xFFFFFFFF +#define VAL_GPIO_CRH 0x88888888 /* PD15...PD8 */ +#define VAL_GPIO_CRL 0x88862888 /* PD7...PD0 */ + +#define GPIO_USB_BASE GPIOD_BASE +#define GPIO_LED_BASE GPIOD_BASE diff --git a/regnual/sys.c b/regnual/sys.c new file mode 100644 index 0000000..ad7745b --- /dev/null +++ b/regnual/sys.c @@ -0,0 +1,310 @@ +#include "types.h" +#include "sys.h" + +#define STM32_SW_PLL (2 << 0) +#define STM32_PLLSRC_HSE (1 << 16) + +#define STM32_PLLXTPRE_DIV1 (0 << 17) +#define STM32_PLLXTPRE_DIV2 (1 << 17) + +#define STM32_HPRE_DIV1 (0 << 4) + +#define STM32_PPRE1_DIV2 (4 << 8) + +#define STM32_PPRE2_DIV2 (4 << 11) + +#define STM32_ADCPRE_DIV4 (1 << 14) + +#define STM32_MCO_NOCLOCK (0 << 24) + +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#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_MCO STM32_MCO_NOCLOCK + +#define STM32_PLLCLKIN (STM32_HSECLK / 1) +#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) +#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) +#define STM32_SYSCLK STM32_PLLCLKOUT +#define STM32_HCLK (STM32_SYSCLK / 1) + +#define STM32_FLASHBITS 0x00000012 + +struct NVIC { + uint32_t ISER[8]; + uint32_t unused1[24]; + uint32_t ICER[8]; + uint32_t unused2[24]; + uint32_t ISPR[8]; + uint32_t unused3[24]; + uint32_t ICPR[8]; + uint32_t unused4[24]; + uint32_t IABR[8]; + uint32_t unused5[56]; + uint32_t IPR[60]; +}; + +#define NVICBase ((struct NVIC *)0xE000E100) +#define NVIC_ISER(n) (NVICBase->ISER[n]) +#define NVIC_ICPR(n) (NVICBase->ICPR[n]) +#define NVIC_IPR(n) (NVICBase->IPR[n]) + +static void NVICEnableVector (uint32_t n, uint32_t prio) +{ + unsigned int sh = (n & 3) << 3; + + NVIC_IPR (n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); + NVIC_ICPR (n >> 5) = 1 << (n & 0x1F); + NVIC_ISER (n >> 5) = 1 << (n & 0x1F); +} + + +#define PERIPH_BASE 0x40000000 +#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) +#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) + +struct RCC { + __IO uint32_t CR; + __IO uint32_t CFGR; + __IO uint32_t CIR; + __IO uint32_t APB2RSTR; + __IO uint32_t APB1RSTR; + __IO uint32_t AHBENR; + __IO uint32_t APB2ENR; + __IO uint32_t APB1ENR; + __IO uint32_t BDCR; + __IO uint32_t CSR; +}; + +#define RCC_BASE (AHBPERIPH_BASE + 0x1000) +#define RCC ((struct RCC *)RCC_BASE) + +#define RCC_APB1ENR_USBEN 0x00800000 +#define RCC_APB1RSTR_USBRST 0x00800000 + +#define RCC_CR_HSION 0x00000001 +#define RCC_CR_HSIRDY 0x00000002 +#define RCC_CR_HSITRIM 0x000000F8 +#define RCC_CR_HSEON 0x00010000 +#define RCC_CR_HSERDY 0x00020000 +#define RCC_CR_PLLON 0x01000000 +#define RCC_CR_PLLRDY 0x02000000 + +#define RCC_CFGR_SWS 0x0000000C +#define RCC_CFGR_SWS_HSI 0x00000000 + +struct FLASH { + __IO uint32_t ACR; + __IO uint32_t KEYR; + __IO uint32_t OPTKEYR; + __IO uint32_t SR; + __IO uint32_t CR; + __IO uint32_t AR; + __IO uint32_t RESERVED; + __IO uint32_t OBR; + __IO uint32_t WRPR; +}; + +#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) +#define FLASH ((struct FLASH *) FLASH_R_BASE) + +static __attribute__ ((used)) +void clock_init (void) +{ + /* HSI setup */ + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) + ; + RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; + RCC->CFGR = 0; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) + ; + + /* HSE setup */ + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) + ; + + /* PLL setup */ + RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) + ; + + /* Clock settings */ + RCC->CFGR = STM32_MCO | STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC | + STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; + + /* Flash setup */ + FLASH->ACR = STM32_FLASHBITS; + + /* Switching on the configured clock source. */ + RCC->CFGR |= STM32_SW; + while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) + ; +} + +#define RCC_APB2ENR_IOPAEN 0x00000004 +#define RCC_APB2RSTR_IOPARST 0x00000004 +#define RCC_APB2ENR_IOPDEN 0x00000020 +#define RCC_APB2RSTR_IOPDRST 0x00000020 + +#define VAL_GPIOAODR 0xFFFFFFFF +#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */ +#define VAL_GPIOACRL 0x88888884 /* PA7...PA0 */ + +struct GPIO { + __IO uint32_t CRL; + __IO uint32_t CRH; + __IO uint32_t IDR; + __IO uint32_t ODR; + __IO uint32_t BSRR; + __IO uint32_t BRR; + __IO uint32_t LCKR; +}; + +#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) +#define GPIOA ((struct GPIO *) GPIOA_BASE) +#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) +#define GPIOB ((struct GPIO *) GPIOB_BASE) +#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) +#define GPIOC ((struct GPIO *) GPIOC_BASE) +#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) +#define GPIOD ((struct GPIO *) GPIOD_BASE) +#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) +#define GPIOE ((struct GPIO *) GPIOE_BASE) + +#define GPIO_USB ((struct GPIO *) GPIO_USB_BASE) +#define GPIO_LED ((struct GPIO *) GPIO_LED_BASE) + +static __attribute__ ((used)) +void gpio_init (void) +{ + /* Enable GPIOD clock. */ + RCC->APB2ENR |= RCC_APB2ENR_IOPDEN; + RCC->APB2RSTR = RCC_APB2RSTR_IOPDRST; + RCC->APB2RSTR = 0; + + GPIO_USB->ODR = VAL_GPIO_ODR; + GPIO_USB->CRH = VAL_GPIO_CRH; + GPIO_USB->CRL = VAL_GPIO_CRL; + +#if GPIO_USB_BASE != GPIO_LED_BASE + GPIO_LED->ODR = VAL_GPIO_LED_ODR; + GPIO_LED->CRH = VAL_GPIO_LED_CRH; + GPIO_LED->CRL = VAL_GPIO_LED_CRL; +#endif +} + +static void +usb_cable_config (int on) +{ +#if defined(GPIO_USB_CLEAR_TO_ENABLE) + if (on) + GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); + else + GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); +#endif +} + +void +set_led (int on) +{ +#if defined(GPIO_LED_CLEAR_TO_EMIT) + if (on) + GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT); + else + GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT); +#endif +} + + +#define USB_IRQ 20 +#define USB_IRQ_PRIORITY ((11) << 4) + +void usb_lld_sys_init (void) +{ + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + NVICEnableVector (USB_IRQ, USB_IRQ_PRIORITY); + RCC->APB1RSTR = RCC_APB1RSTR_USBRST; + RCC->APB1RSTR = 0; + usb_cable_config (1); +} + +void usb_lld_sys_shutdown (void) +{ + RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; +} + + +static void fatal (void) +{ + for (;;); +} + +static void none (void) +{ +} + +static __attribute__ ((naked)) +void reset (void) +{ + asm volatile ("cpsid i\n\t" /* Mask all interrupts */ + "ldr r0, =__ram_end__\n\t" + "msr MSP, r0\n\t" /* Main (interrupt handler) stack */ + "ldr r1, =__main_stack_size__\n\t" + "subs r0, r0, r1\n\t" + "msr PSP, r0\n\t" /* Process (main routine) stack */ + "bl clock_init\n\t" + "movs r0, #0\n\t" + "ldr r1, =_bss_start\n\t" + "ldr r2, =_bss_start\n" + "0:\n\t" + "cmp r1, r2\n\t" + "bge 1f\n\t" + "str r0, [r1]\n\t" + "adds r1, r1, #4\n\t" + "b 0b\n" + "1:\n\t" + "movs r0, #2\n\t" /* Switch to PSP */ + "msr CONTROL, r0\n\t" + "isb\n\t" + "bl gpio_init\n\t" + "movs r0, #0\n\t" + "msr BASEPRI, r0\n\t" /* Enable interrupts */ + "cpsie i\n\t" + "mov r1, r0\n\t" + "bl main\n" + "2:\n\t" + "b 2b\n" + : /* no output */ : /* no input */ : "memory"); +} + +typedef void (*handler)(void); +extern uint8_t __ram_end__; +extern void usb_interrupt_handler (void); + +handler vector_table[] __attribute__ ((section(".vectors"))) = { + (handler)&__ram_end__, + reset, + fatal, /* nmi */ + fatal, /* hard fault */ + /* 10 */ + fatal, /* mem manage */ + fatal, /* bus fault */ + fatal, /* usage fault */ + none, + /* 20 */ + none, none, none, none, none, none, none, none, + /* 40 */ + none, none, none, none, none, none, none, none, + /* 60 */ + none, none, none, none, none, none, none, none, + /* 80 */ + none, none, none, none, + /* 90 */ + usb_interrupt_handler, +}; diff --git a/regnual/types.h b/regnual/types.h new file mode 100644 index 0000000..6b727bf --- /dev/null +++ b/regnual/types.h @@ -0,0 +1,10 @@ +typedef unsigned long size_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#define TRUE 1 +#define FALSE 0 + +#define __IO volatile From 12c94c1f225251e7dc8eb896ff23fda40129fb4d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 10:52:15 +0900 Subject: [PATCH 092/300] Gnuk change to support reGNUal --- ChangeLog | 15 ++++++ src/Makefile.in | 2 +- src/usb_lld.c | 122 +++++++++++++++++----------------------------- src/usb_lld.h | 6 ++- src/usb_lld_sys.c | 34 +++++++++++++ src/usb_prop.c | 9 ---- 6 files changed, 99 insertions(+), 89 deletions(-) create mode 100644 src/usb_lld_sys.c diff --git a/ChangeLog b/ChangeLog index ecb47ad..7548819 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2012-05-22 Niibe Yutaka + + * src/usb_lld.c: Support FREE_STANDING environment as well as + under ChibiOS/RT. + (usb_lld_init): Call usb_lld_sys_init. Don't call user defined + method. Call usb_lld_set_configuration. + (usb_lld_shutdown): Call usb_lld_sys_shutdown. + (Vector90): Move to usb_lld_sys.c. + (usb_interrupt_handler): Export to global. + + * src/usb_lld_sys.c: New. + + * src/usb_prop.c (Device_Method): Remove gnuk_device_init. + (gnuk_device_init): Remove. + 2012-05-19 Niibe Yutaka * src/usb_lld.c (handle_datastage_in): Bug fix, erable RX when diff --git a/src/Makefile.in b/src/Makefile.in index 4237c36..0c6e20f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -81,7 +81,7 @@ CSRC = $(PORTSRC) \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ $(CRYPTSRC) \ - main.c usb_lld.c \ + main.c usb_lld.c usb_lld_sys.c \ usb_desc.c usb_prop.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ random.c neug.c diff --git a/src/usb_lld.c b/src/usb_lld.c index 948f3a7..578f764 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -1,5 +1,10 @@ +#ifdef FREE_STANDING +#include "types.h" +#else #include "ch.h" #include "hal.h" +#endif + #include "usb_lld.h" #define USB_MAX_PACKET_SIZE 64 /* For FS device */ @@ -66,9 +71,15 @@ struct DEVICE_INFO uint8_t state; }; -static struct CONTROL_INFO *ctrl_p; -static struct DEVICE_INFO *dev_p; -static struct DATA_INFO *data_p; +static struct CONTROL_INFO control_info; +static struct DEVICE_INFO device_info; +static struct DATA_INFO data_info; +extern const struct usb_device_method Device_Method; + +static struct CONTROL_INFO *const ctrl_p = &control_info; +static struct DEVICE_INFO *const dev_p = &device_info; +static struct DATA_INFO *const data_p = &data_info; +static const struct usb_device_method *const method_p = &Device_Method; #define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */ #define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */ @@ -347,9 +358,36 @@ static void st103_ep_clear_dtog_tx (uint8_t ep_num) } } -static const struct usb_device_method* method_p; +void usb_lld_init (void) +{ + usb_lld_sys_init (); -static void + dev_p->state = IN_DATA; + + usb_lld_set_configuration (0); + + /* Reset USB */ + st103_set_cntr (CNTR_FRES); + st103_set_cntr (0); + + /* Clear Interrupt Status Register, and enable interrupt for USB */ + st103_set_istr (0); + st103_set_cntr (CNTR_CTRM | CNTR_RESETM); +} + +void usb_lld_prepare_shutdown (void) +{ + st103_set_istr (0); + st103_set_cntr (0); +} + +void usb_lld_shutdown (void) +{ + st103_set_cntr (CNTR_PDWN); + usb_lld_sys_shutdown (); +} + +void usb_interrupt_handler (void) { uint16_t istr_value = st103_get_istr (); @@ -370,16 +408,6 @@ usb_interrupt_handler (void) st103_set_istr (CLR_ERR); } -CH_IRQ_HANDLER (Vector90) { - CH_IRQ_PROLOGUE(); - chSysLockFromIsr(); - - usb_interrupt_handler (); - - chSysUnlockFromIsr(); - CH_IRQ_EPILOGUE(); -} - static void handle_datastage_out (void) { if (data_p->addr && data_p->len) @@ -903,7 +931,7 @@ static void nop_proc (void) { } -#define WEAK __attribute__ ((weak)) +#define WEAK __attribute__ ((weak, alias ("nop_proc"))) void WEAK EP1_IN_Callback (void); void WEAK EP2_IN_Callback (void); void WEAK EP3_IN_Callback (void); @@ -920,22 +948,6 @@ void WEAK EP5_OUT_Callback (void); void WEAK EP6_OUT_Callback (void); void WEAK EP7_OUT_Callback (void); -#pragma weak EP1_IN_Callback = nop_proc -#pragma weak EP2_IN_Callback = nop_proc -#pragma weak EP3_IN_Callback = nop_proc -#pragma weak EP4_IN_Callback = nop_proc -#pragma weak EP5_IN_Callback = nop_proc -#pragma weak EP6_IN_Callback = nop_proc -#pragma weak EP7_IN_Callback = nop_proc - -#pragma weak EP1_OUT_Callback = nop_proc -#pragma weak EP2_OUT_Callback = nop_proc -#pragma weak EP3_OUT_Callback = nop_proc -#pragma weak EP4_OUT_Callback = nop_proc -#pragma weak EP5_OUT_Callback = nop_proc -#pragma weak EP6_OUT_Callback = nop_proc -#pragma weak EP7_OUT_Callback = nop_proc - void (*const ep_intr_handler_IN[7]) (void) = { EP1_IN_Callback, EP2_IN_Callback, @@ -1018,58 +1030,12 @@ usb_handle_transfer (void) } } -static struct CONTROL_INFO Control_Info; -static struct DEVICE_INFO Device_Info; -static struct DATA_INFO Data_Info; - void usb_lld_reset (void) { st103_set_btable (); st103_set_daddr (0); } -void usb_lld_init (void) -{ - RCC->APB1ENR |= RCC_APB1ENR_USBEN; - NVICEnableVector (USB_LP_CAN1_RX0_IRQn, - CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); - /* - * Note that we also have other IRQ(s): - * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) - * USBWakeUp_IRQn (suspend/resume) - */ - RCC->APB1RSTR = RCC_APB1RSTR_USBRST; - RCC->APB1RSTR = 0; - - dev_p = &Device_Info; - ctrl_p = &Control_Info; - data_p = &Data_Info; - dev_p->state = IN_DATA; - method_p = &Device_Method; - - method_p->init(); - - /* Reset USB */ - st103_set_cntr (CNTR_FRES); - st103_set_cntr (0); - - /* Clear Interrupt Status Register, and enable interrupt for USB */ - st103_set_istr (0); - st103_set_cntr (CNTR_CTRM | CNTR_RESETM); -} - -void usb_lld_prepare_shutdown (void) -{ - st103_set_istr (0); - st103_set_cntr (0); -} - -void usb_lld_shutdown (void) -{ - st103_set_cntr (CNTR_PDWN); - RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; -} - void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len) { diff --git a/src/usb_lld.h b/src/usb_lld.h index 2652dad..cffbfbe 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -63,7 +63,6 @@ enum struct usb_device_method { - void (*init) (void); void (*reset) (void); void (*ctrl_write_finish) (uint8_t req, uint8_t req_no, uint16_t value, uint16_t index, uint16_t len); @@ -155,3 +154,8 @@ extern inline void usb_lld_set_data_to_recv (void *p, size_t len) extern void usb_lld_prepare_shutdown (void); extern void usb_lld_shutdown (void); + +extern void usb_interrupt_handler (void); + +extern void usb_lld_sys_init (void); +extern void usb_lld_sys_shutdown (void); diff --git a/src/usb_lld_sys.c b/src/usb_lld_sys.c new file mode 100644 index 0000000..be78d7e --- /dev/null +++ b/src/usb_lld_sys.c @@ -0,0 +1,34 @@ +#include "ch.h" +#include "hal.h" +#include "usb_lld.h" + +CH_IRQ_HANDLER (Vector90) { + CH_IRQ_PROLOGUE(); + chSysLockFromIsr(); + + usb_interrupt_handler (); + + chSysUnlockFromIsr(); + CH_IRQ_EPILOGUE(); +} + +void usb_lld_sys_init (void) +{ + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + NVICEnableVector (USB_LP_CAN1_RX0_IRQn, + CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); + /* + * Note that we also have other IRQ(s): + * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) + * USBWakeUp_IRQn (suspend/resume) + */ + RCC->APB1RSTR = RCC_APB1RSTR_USBRST; + RCC->APB1RSTR = 0; + + USB_Cable_Config (1); +} + +void usb_lld_sys_shutdown (void) +{ + RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; +} diff --git a/src/usb_prop.c b/src/usb_prop.c index a7ca500..df4ac0c 100644 --- a/src/usb_prop.c +++ b/src/usb_prop.c @@ -91,14 +91,6 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no) uint32_t bDeviceState = UNCONNECTED; /* USB device status */ -static void -gnuk_device_init (void) -{ - usb_lld_set_configuration (0); - USB_Cable_Config (1); - bDeviceState = UNCONNECTED; -} - static void gnuk_setup_endpoints_for_interface (uint16_t interface, int stop) { @@ -423,7 +415,6 @@ static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt) */ const struct usb_device_method Device_Method = { - gnuk_device_init, gnuk_device_reset, gnuk_ctrl_write_finish, gnuk_setup, From abfe779728bca13b599b178fb083a04e0d15e8ec Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 11:14:22 +0900 Subject: [PATCH 093/300] add regnual --- .gitignore | 14 +- ChangeLog | 4 + regnual/Makefile | 46 +++++++ regnual/Makefile.in | 182 -------------------------- regnual/{regnual.ld.in => regnual.ld} | 9 +- 5 files changed, 64 insertions(+), 191 deletions(-) create mode 100644 regnual/Makefile delete mode 100644 regnual/Makefile.in rename regnual/{regnual.ld.in => regnual.ld} (89%) diff --git a/.gitignore b/.gitignore index 269bd36..96f5c0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,20 @@ -# generated files by 'configure' -src/Makefile -src/config.h -src/gnuk.ld *.lst *.o *.pyc src/.dep +src/Makefile +src/config.h +src/gnuk.ld src/gnuk.bin src/gnuk.dmp src/gnuk.elf src/gnuk.hex src/gnuk.map src/*.inc +regnual/sys.h +regnual/*.inc +regnual/regnual.bin +regnual/regnual.hex +regnual/regnual.elf +regnual/usb_lld.c +regnual/usb_lld.h diff --git a/ChangeLog b/ChangeLog index 7548819..665cf3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-05-22 Niibe Yutaka + * regnual/types.h, regnual/sys.c, regnual/regnual.ld: New. + * regnual/regnual.c, regnual/Makefile: New. + * regnual/sys-stbee.h: New. + * src/usb_lld.c: Support FREE_STANDING environment as well as under ChibiOS/RT. (usb_lld_init): Call usb_lld_sys_init. Don't call user defined diff --git a/regnual/Makefile b/regnual/Makefile new file mode 100644 index 0000000..c94711d --- /dev/null +++ b/regnual/Makefile @@ -0,0 +1,46 @@ +# Makefile for reGNUal + +PROJECT = regnual + +SRCS = regnual.c usb_lld.c sys.c +OBJS = regnual.o usb_lld.o sys.o +LDSCRIPT= regnual.ld + +################################### +MCU = cortex-m3 + +TRGT = arm-none-eabi- +CC = $(TRGT)gcc +LD = $(TRGT)ld +OBJCOPY = $(TRGT)objcopy +OBJDUMP = $(TRGT)objdump + +# THUMB-specific options here +TOPT = -mthumb -DTHUMB +# Define C warning options here +CWARN = -Wall -Wextra -Wstrict-prototypes +MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd +DEFS = -DFREE_STANDING + +CFLAGS = -O2 -g +CFLAGS += $(CWARN) -fno-common $(MCFLAGS) $(TOPT) $(DEFS) + +LDFLAGS = -T$(LDSCRIPT) -nostartfiles + + +#################### + +all: regnual.hex + +regnual.hex: regnual.elf + $(OBJCOPY) -Obinary regnual.elf regnual.bin + $(OBJCOPY) -Oihex regnual.elf regnual.hex + +regnual.elf: $(OBJS) $(LDSCRIPT) + $(CC) $(LDFLAGS) -o regnual.elf $(OBJS) + +clean: + -rm -f $(OBJS) regnual.elf regnual.hex regnual.bin + +distclean: clean + -rm -f Makefile regnual.ld diff --git a/regnual/Makefile.in b/regnual/Makefile.in deleted file mode 100644 index 58254d8..0000000 --- a/regnual/Makefile.in +++ /dev/null @@ -1,182 +0,0 @@ -# Makefile for reGNUal - -BOARD_DIR=@BOARD_DIR@ - -############################################################################## -# Build global options -# NOTE: Can be overridden externally. -# - -# Compiler options here. -ifeq ($(USE_OPT),) - USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 -endif - -# C++ specific options here (added to USE_OPT). -ifeq ($(USE_CPPOPT),) - USE_CPPOPT = -fno-rtti -endif - -# Enable this if you want the linker to remove unused code and data -ifeq ($(USE_LINK_GC),) - USE_LINK_GC = yes -endif - -# If enabled, this option allows to compile the application in THUMB mode. -ifeq ($(USE_THUMB),) - USE_THUMB = yes -endif - -# Enable register caching optimization (read documentation). -ifeq ($(USE_CURRP_CACHING),) - USE_CURRP_CACHING = no -endif - -# -# Build global options -############################################################################## - -############################################################################## -# Architecture or project specific options -# - -# Enable this if you really want to use the STM FWLib. -ifeq ($(USE_FWLIB),) - USE_FWLIB = no -endif - -# -# Architecture or project specific options -############################################################################## - -############################################################################## -# Project, sources and paths -# - -# Define project name here -PROJECT = regnual - -# Define linker script file here -LDSCRIPT= regnual.ld - -# Imported source files -CHIBIOS = ../ChibiOS_2.0.8 -include $(CHIBIOS)/os/hal/platforms/STM32/platform.mk -include $(CHIBIOS)/os/hal/hal.mk -include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk -include $(CHIBIOS)/os/kernel/kernel.mk - -# C sources that can be compiled in ARM or THUMB mode depending on the global -# setting. -CSRC = $(PORTSRC) \ - $(KERNSRC) \ - $(HALSRC) \ - $(PLATFORMSRC) \ - $(BOARDSRC) \ - ../boards/common/hw_config.c \ - $(BOARD_DIR)/board.c \ - $(CHIBIOS)/os/various/evtimer.c \ - $(CHIBIOS)/os/various/syscalls.c \ - regnual.c usb_lld.c - -# List ASM source files here -ASMSRC = $(PORTASM) \ - $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s - -INCDIR = $(CRYPTINCDIR) \ - $(PORTINC) $(KERNINC) $(TESTINC) \ - $(HALINC) $(PLATFORMINC) ../boards/common $(BOARD_DIR) \ - $(CHIBIOS)/os/various - -# -# Project, sources and paths -############################################################################## - -############################################################################## -# Compiler settings -# - -MCU = cortex-m3 - -#TRGT = arm-elf- -TRGT = arm-none-eabi- -CC = $(TRGT)gcc -CPPC = $(TRGT)g++ -# Enable loading with g++ only if you need C++ runtime support. -# NOTE: You can use C++ even without C++ support if you are careful. C++ -# runtime support makes code size explode. -LD = $(TRGT)gcc -#LD = $(TRGT)g++ -CP = $(TRGT)objcopy -AS = $(TRGT)gcc -x assembler-with-cpp -OD = $(TRGT)objdump -HEX = $(CP) -O ihex -BIN = $(CP) -O binary - -# ARM-specific options here -AOPT = - -# THUMB-specific options here -TOPT = -mthumb -DTHUMB - -# Define C warning options here -CWARN = -Wall -Wextra -Wstrict-prototypes - -# Define C++ warning options here -CPPWARN = -Wall -Wextra - -# -# Compiler settings -############################################################################## - -############################################################################## -# Start of default section -# - -# List all default C defines here, like -D_DEBUG=1 -DDEFS = -DCORTEX_USE_BASEPRI=TRUE - -# List all default ASM defines here, like -D_DEBUG=1 -DADEFS = - -# List all default directories to look for include files here -DINCDIR = - -# List the default directory to look for the libraries here -DLIBDIR = - -# List all default libraries here -DLIBS = - -# -# End of default section -############################################################################## - -############################################################################## -# Start of user section -# - -# List all user C define here, like -D_DEBUG=1 -UDEFS = - -# Define ASM defines here -UADEFS = - -# List all user directories here -UINCDIR = - -# List the user directory to look for the libraries here -ULIBDIR = - -# List all user libraries here -ULIBS = - -# -# End of user defines -############################################################################## - -include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk -MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd - -distclean: clean - -rm -f Makefile regnual.ld diff --git a/regnual/regnual.ld.in b/regnual/regnual.ld similarity index 89% rename from regnual/regnual.ld.in rename to regnual/regnual.ld index 54aceb5..d7a73e9 100644 --- a/regnual/regnual.ld.in +++ b/regnual/regnual.ld @@ -7,13 +7,12 @@ __stacks_total_size__ = __main_stack_size__ + __process_stack_size__; MEMORY { - flash : org = @ORIGIN@, len = @FLASH_SIZE@k - ram0 : org = 0x20000000, len = @REGNUAL_START@ - ram1 : org = 0x20001300, len = 20k - @REGNUAL_START@ + ram0 : org = 0x20000000, len = 0x1400 + ram1 : org = 0x20001400, len = 20k - 0x1400 } _flash_start = 0x08000000; -_flash_end = @FLASH_END@; +_flash_end = 0x08010000; __ram_start__ = ORIGIN(ram0); __ram_size__ = 20k; @@ -38,7 +37,7 @@ SECTIONS .text : ALIGN(16) SUBALIGN(16) { _text = .; - KEEP(*(vectors)) + KEEP(*(.vectors)) *(.text) *(.text.*) *(.rodata) From 11be1691876183c8b6506d90913268de491664bc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 11:20:16 +0900 Subject: [PATCH 094/300] improve regnual config --- .gitignore | 1 - regnual/Makefile | 10 +++++++++- regnual/regnual.c | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 96f5c0b..e912801 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ src/gnuk.hex src/gnuk.map src/*.inc regnual/sys.h -regnual/*.inc regnual/regnual.bin regnual/regnual.hex regnual/regnual.elf diff --git a/regnual/Makefile b/regnual/Makefile index c94711d..5e1e6eb 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -32,10 +32,18 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles all: regnual.hex +regnual.o: regnual.c usb_lld.h + regnual.hex: regnual.elf $(OBJCOPY) -Obinary regnual.elf regnual.bin $(OBJCOPY) -Oihex regnual.elf regnual.hex +usb_lld.c: ../src/usb_lld.c usb_lld.h + cp -p ../src/usb_lld.c . + +usb_lld.h: ../src/usb_lld.h + cp -p ../src/usb_lld.h . + regnual.elf: $(OBJS) $(LDSCRIPT) $(CC) $(LDFLAGS) -o regnual.elf $(OBJS) @@ -43,4 +51,4 @@ clean: -rm -f $(OBJS) regnual.elf regnual.hex regnual.bin distclean: clean - -rm -f Makefile regnual.ld + -rm -f usb_lld.c usb_lld.h sys.h diff --git a/regnual/regnual.c b/regnual/regnual.c index b6707e5..8611d98 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -43,7 +43,7 @@ static const uint8_t regnual_device_desc[] = { 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ 0x40, /* bMaxPacketSize0 */ -#include "usb-vid-pid-ver.c.inc" +#include "../src/usb-vid-pid-ver.c.inc" 1, /* Index of string descriptor describing manufacturer */ 2, /* Index of string descriptor describing product */ 3, /* Index of string descriptor describing the device's serial number */ @@ -71,7 +71,7 @@ static const uint8_t regnual_string_lang_id[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; -#include "usb-string-vendor-product.c.inc" +#include "../src/usb-string-vendor-product.c.inc" static const uint8_t regnual_string_serial[] = { 8*2+2, From cc80c3e43386ddd6487bf2ebccaa9d128a0c87ed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 12:07:02 +0900 Subject: [PATCH 095/300] rename to usb_ctrl.c --- ChangeLog | 2 ++ src/{usb_prop.c => usb_ctrl.c} | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename src/{usb_prop.c => usb_ctrl.c} (99%) diff --git a/ChangeLog b/ChangeLog index 665cf3a..ff78b47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-22 Niibe Yutaka + * src/usb_ctrl.c: Rename (was: usb_prop.c). + * regnual/types.h, regnual/sys.c, regnual/regnual.ld: New. * regnual/regnual.c, regnual/Makefile: New. * regnual/sys-stbee.h: New. diff --git a/src/usb_prop.c b/src/usb_ctrl.c similarity index 99% rename from src/usb_prop.c rename to src/usb_ctrl.c index df4ac0c..08c64ea 100644 --- a/src/usb_prop.c +++ b/src/usb_ctrl.c @@ -1,5 +1,5 @@ /* - * usb_prop.c - interface code between Gnuk and USB + * usb_ctrl.c - USB control pipe device specific code for Gnuk * * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka From ab4e0c2167b369a1106cac315b92b372e4920970 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 12:26:49 +0900 Subject: [PATCH 096/300] configure support for regnual --- ChangeLog | 2 ++ src/configure | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index ff78b47..347d52e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-22 Niibe Yutaka + * src/configure (../regnual/sys.h): Create symblic link. + * src/usb_ctrl.c: Rename (was: usb_prop.c). * regnual/types.h, regnual/sys.c, regnual/regnual.ld: New. diff --git a/src/configure b/src/configure index 25ddd0e..28e45b8 100755 --- a/src/configure +++ b/src/configure @@ -135,6 +135,7 @@ fi BOARD_DIR=../boards/$target if test -d $BOARD_DIR; then echo "Configured for target: $target" + TARGET_LOWER=`echo $target | tr '[:upper:]_' '[:lower:]-'` else echo "Unsupported target \`$target'" >&2 exit 1 @@ -218,6 +219,8 @@ else echo "CERT.3 Data Object is not supported" fi +ln -sf sys-$TARGET_LOWER.h ../regnual/sys.h + sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ From 86b1c1848a201a0cc00d5722e9e60bda8cdb2a6f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 16:35:13 +0900 Subject: [PATCH 097/300] Makefile.in for usb_ctrl.c rename --- src/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.in b/src/Makefile.in index 0c6e20f..4130b46 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,7 +82,7 @@ CSRC = $(PORTSRC) \ $(CHIBIOS)/os/various/syscalls.c \ $(CRYPTSRC) \ main.c usb_lld.c usb_lld_sys.c \ - usb_desc.c usb_prop.c \ + usb_desc.c usb_ctrl.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ random.c neug.c From b202f953762a533f78619c9035657d21871ae2d3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 16:36:23 +0900 Subject: [PATCH 098/300] add flash and reset routines --- regnual/sys.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/regnual/sys.c b/regnual/sys.c index ad7745b..a8454db 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -240,6 +240,26 @@ void usb_lld_sys_shutdown (void) } + +#define FLASH_KEY1 0x45670123UL +#define FLASH_KEY2 0xCDEF89ABUL + +enum flash_status +{ + FLASH_BUSY = 1, + FLASH_ERROR_PG, + FLASH_ERROR_WRP, + FLASH_COMPLETE, + FLASH_TIMEOUT +}; + +static void __attribute__ ((used)) +flash_unlock (void) +{ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; +} + static void fatal (void) { for (;;); @@ -272,6 +292,7 @@ void reset (void) "movs r0, #2\n\t" /* Switch to PSP */ "msr CONTROL, r0\n\t" "isb\n\t" + "bl flash_unlock\n\t" "bl gpio_init\n\t" "movs r0, #0\n\t" "msr BASEPRI, r0\n\t" /* Enable interrupts */ @@ -283,6 +304,11 @@ void reset (void) : /* no output */ : /* no input */ : "memory"); } +#define intr_disable() asm volatile ("cpsid i" : : "r" (0) : "memory") + +#define intr_enable() asm volatile ("msr BASEPRI, %0\n\t" \ + "cpsie i" : : "r" (0) : "memory") + typedef void (*handler)(void); extern uint8_t __ram_end__; extern void usb_interrupt_handler (void); @@ -308,3 +334,162 @@ handler vector_table[] __attribute__ ((section(".vectors"))) = { /* 90 */ usb_interrupt_handler, }; + +#define FLASH_SR_BSY 0x01 +#define FLASH_SR_PGERR 0x04 +#define FLASH_SR_WRPRTERR 0x10 +#define FLASH_SR_EOP 0x20 + +#define FLASH_CR_PG 0x0001 +#define FLASH_CR_PER 0x0002 +#define FLASH_CR_MER 0x0004 +#define FLASH_CR_OPTPG 0x0010 +#define FLASH_CR_OPTER 0x0020 +#define FLASH_CR_STRT 0x0040 +#define FLASH_CR_LOCK 0x0080 +#define FLASH_CR_OPTWRE 0x0200 +#define FLASH_CR_ERRIE 0x0400 +#define FLASH_CR_EOPIE 0x1000 + +static int +flash_get_status (void) +{ + int status; + + if ((FLASH->SR & FLASH_SR_BSY) != 0) + status = FLASH_BUSY; + else if ((FLASH->SR & FLASH_SR_PGERR) != 0) + status = FLASH_ERROR_PG; + else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0 ) + status = FLASH_ERROR_WRP; + else + status = FLASH_COMPLETE; + + return status; +} + +static int +flash_wait_for_last_operation (uint32_t timeout) +{ + int status; + + do + if (--timeout == 0) + return FLASH_TIMEOUT; + else + status = flash_get_status (); + while (status == FLASH_BUSY); + + return status; +} + +#define FLASH_PROGRAM_TIMEOUT 0x00010000 +#define FLASH_ERASE_TIMEOUT 0x01000000 + +static int +flash_program_halfword (uint32_t addr, uint16_t data) +{ + int status; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + + intr_disable (); + if (status == FLASH_COMPLETE) + { + FLASH->CR |= FLASH_CR_PG; + + *(volatile uint16_t *)addr = data; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + if (status != FLASH_TIMEOUT) + FLASH->CR &= ~FLASH_CR_PG; + } + intr_enable (); + + return status; +} + +int +flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) +{ + int status; + + while (len) + { + uint16_t hw = *src++; + + hw |= (*src++ << 8); + status = flash_program_halfword (dst_addr, hw); + if (status != FLASH_COMPLETE) + return 0; + + dst_addr += 2; + len -= 2; + } + + return 1; +} + +int +flash_erase_page (uint32_t addr) +{ + int status; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + + intr_disable (); + if (status == FLASH_COMPLETE) + { + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = addr; + FLASH->CR |= FLASH_CR_STRT; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + if (status != FLASH_TIMEOUT) + FLASH->CR &= ~FLASH_CR_PER; + } + intr_enable (); + + return status == FLASH_COMPLETE; +} + +int +flash_protect (void) +{ + /* Not yet implemented */ + return 1; +} + +struct SCB +{ + __IO uint32_t CPUID; + __IO uint32_t ICSR; + __IO uint32_t VTOR; + __IO uint32_t AIRCR; + __IO uint32_t SCR; + __IO uint32_t CCR; + __IO uint8_t SHP[12]; + __IO uint32_t SHCSR; + __IO uint32_t CFSR; + __IO uint32_t HFSR; + __IO uint32_t DFSR; + __IO uint32_t MMFAR; + __IO uint32_t BFAR; + __IO uint32_t AFSR; + __IO uint32_t PFR[2]; + __IO uint32_t DFR; + __IO uint32_t ADR; + __IO uint32_t MMFR[4]; + __IO uint32_t ISAR[5]; +}; + +#define SCS_BASE (0xE000E000) +#define SCB_BASE (SCS_BASE + 0x0D00) +#define SCB ((struct SCB *) SCB_BASE) + +#define SYSRESETREQ 0x04 +void nvic_system_reset (void) +{ + SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ); + asm volatile ("dsb"); +} From 244cdbff3f98a6b445a094ef3566ea7b13c95eaf Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 16:37:30 +0900 Subject: [PATCH 099/300] set data_p->addr=NULL --- regnual/types.h | 2 ++ src/usb_lld.c | 1 + 2 files changed, 3 insertions(+) diff --git a/regnual/types.h b/regnual/types.h index 6b727bf..ed28a12 100644 --- a/regnual/types.h +++ b/regnual/types.h @@ -7,4 +7,6 @@ typedef unsigned int uint32_t; #define TRUE 1 #define FALSE 0 +#define NULL 0 + #define __IO volatile diff --git a/src/usb_lld.c b/src/usb_lld.c index 578f764..5fc9bac 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -839,6 +839,7 @@ static void handle_setup0 (void) pw++; ctrl_p->wLength = *pw; + data_p->addr = NULL; data_p->len = 0; data_p->offset = 0; From 6c205c3111cbee9f6aa1723c80396d5954e349ca Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 16:38:02 +0900 Subject: [PATCH 100/300] main cleanup --- src/main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main.c b/src/main.c index 9b99567..a1cb495 100644 --- a/src/main.c +++ b/src/main.c @@ -480,17 +480,12 @@ main (int argc, char *argv[]) port_disable (); /* set vector */ SCB->VTOR = (uint32_t)&_regnual_start; -#if 0 - /* SYSRESETREQ to invoke regnual */ - NVIC_SystemReset (); -#else { /* Not yet: erase by mass erase and go to entry */ void (**func)(void) = (void (**)(void))(&_regnual_start + 4); (**func) (); } -#endif return 0; } From 84e3a5c1a625f385035894daa6083f6eb6732002 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 May 2012 17:02:54 +0900 Subject: [PATCH 101/300] regnual: flash write support --- regnual/regnual.c | 78 +++++++++++++++++++++++------------- tool/gnuk_upgrade.py | 94 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 138 insertions(+), 34 deletions(-) diff --git a/regnual/regnual.c b/regnual/regnual.c index 8611d98..21fab3f 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -28,9 +28,16 @@ #include "types.h" #include "usb_lld.h" -extern void set_led (int); extern void *memset (void *s, int c, size_t n); +extern void set_led (int); +extern uint8_t _flash_start, _flash_end; +extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len); +extern int flash_erase_page (uint32_t addr); +extern int flash_protect (void); +extern void nvic_system_reset (void); + + #define ENDP0_RXADDR (0x40) #define ENDP0_TXADDR (0x80) @@ -81,24 +88,24 @@ static const uint8_t regnual_string_serial[] = { '0', 0, '.', 0, '0', 0, }; -const struct Descriptor Device_Descriptor = { +const struct Descriptor device_desc = { regnual_device_desc, sizeof (regnual_device_desc) }; -const struct Descriptor Config_Descriptor = { +const struct Descriptor config_desc = { regnual_config_desc, sizeof (regnual_config_desc) }; -const struct Descriptor String_Descriptors[] = { +const struct Descriptor string_descs[] = { {regnual_string_lang_id, sizeof (regnual_string_lang_id)}, {gnukStringVendor, sizeof (gnukStringVendor)}, {gnukStringProduct, sizeof (gnukStringProduct)}, {regnual_string_serial, sizeof (regnual_string_serial)}, }; -#define NUM_STRING_DESC (sizeof (String_Descriptors)/sizeof (struct Descriptor)) +#define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor)) static void regnual_device_reset (void) @@ -107,7 +114,7 @@ regnual_device_reset (void) usb_lld_set_configuration (0); /* Current Feature initialization */ - usb_lld_set_feature (Config_Descriptor.Descriptor[7]); + usb_lld_set_feature (config_desc.Descriptor[7]); usb_lld_reset (); @@ -124,7 +131,10 @@ regnual_device_reset (void) #define USB_REGNUAL_PROTECT 5 #define USB_REGNUAL_FINISH 6 -static uint8_t mem[1024]; +static uint8_t mem[256]; + +static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; + static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, uint16_t index, @@ -133,16 +143,13 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) - && USB_SETUP_SET (req) && req_no == USB_REGNUAL_FINISH && len == 0) + && USB_SETUP_SET (req) && len == 0) { - (void)value; (void)index; - /* RESET MCU */ - } + if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) + nvic_system_reset (); + } } -extern uint8_t _flash_start, _flash_end; -static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; - static int regnual_setup (uint8_t req, uint8_t req_no, uint16_t value, uint16_t index, uint16_t len) @@ -170,21 +177,38 @@ regnual_setup (uint8_t req, uint8_t req_no, { if (req_no == USB_REGNUAL_SEND) { - if (value >= 4 || value * 0x100 + index + len > 1024) + if (value != 0 || index + len > 256) return USB_UNSUPPORT; - if (value == 0 && index == 0) - memset (mem + value * 0x100, 0xff, 1024); - usb_lld_set_data_to_recv (mem + value * 0x100 + index, len); + if (index != 0) + memset (mem, 0xff, 256); + + usb_lld_set_data_to_recv (mem + index, len); return USB_SUCCESS; } else if (req_no == USB_REGNUAL_FLASH && len == 0) { - uint8_t *addr = (uint8_t *)(0x08000000 + value * 0x400); + uint32_t dst_addr = (0x08000000 + value * 0x100); - /* flash write, verify */ - return USB_SUCCESS; + if (flash_write (dst_addr, mem, 256) == 0) + return USB_SUCCESS; } + else if (req_no == USB_REGNUAL_ERASE && len == 0 && index == 0) + { + uint32_t dst_addr = (0x08000000 + value * 0x100); + + if (flash_erase_page (dst_addr)) + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_PROTECT && len == 0 + && value == 0 && index == 0) + { + if (flash_protect ()) + return USB_SUCCESS; + } + else if (req_no == USB_REGNUAL_FINISH && len == 0 + && value == 0 && index == 0) + return USB_SUCCESS; } } @@ -197,14 +221,14 @@ regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) (void)index; if (desc_type == DEVICE_DESCRIPTOR) { - usb_lld_set_data_to_send (Device_Descriptor.Descriptor, - Device_Descriptor.Descriptor_Size); + usb_lld_set_data_to_send (device_desc.Descriptor, + device_desc.Descriptor_Size); return USB_SUCCESS; } else if (desc_type == CONFIG_DESCRIPTOR) { - usb_lld_set_data_to_send (Config_Descriptor.Descriptor, - Config_Descriptor.Descriptor_Size); + usb_lld_set_data_to_send (config_desc.Descriptor, + config_desc.Descriptor_Size); return USB_SUCCESS; } else if (desc_type == STRING_DESCRIPTOR) @@ -213,8 +237,8 @@ regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) if (desc_index < NUM_STRING_DESC) { - usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor, - String_Descriptors[desc_index].Descriptor_Size); + usb_lld_set_data_to_send (string_descs[desc_index].Descriptor, + string_descs[desc_index].Descriptor_Size); return USB_SUCCESS; } } diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 43a53fa..52ac333 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -48,6 +48,59 @@ def iso7816_compose(ins, p1, p2, data): else: return pack('>BBBBB', cls, ins, p1, p2, data_len) + data +class regnual: + def __init__(self, device): + self.__devhandle = device.open() + + def mem_info(self): + mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0, + value = 0, index = 0, buffer = 8, + timeout = 10000) + start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0] + end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4] + return (start, end) + + def download(self, start, data): + addr = start + addr_end = (start + len(data)) & 0xffffff00 + i = (addr - 0x08000000) / 0x100 + j = 0 + print "start %08x" % addr + print "end %08x" % addr_end + while addr < addr_end: + print "# %08x: %d: %d : %d" % (addr, i, j, 256) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = 0, index = 0, + buffer = data[j*256:j*256+256], + timeout = 10000) + print "flash" + self.__devhandle.controlMsg(requestType = 0x40, request = 3, + value = i, index = 0, + buffer = None, + timeout = 10000) + i = i+1 + j = j+1 + addr = addr + 256 + residue = len(data) % 256 + if residue != 0: + print "# %08x: %d : %d" % (addr, i, residue) + print "send" + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = 0, index = 0, + buffer = data[j*256:], + timeout = 10000) + if (i % 4) != 0 or residue: + print "flash" + self.__devhandle.controlMsg(requestType = 0x40, request = 3, + value = i, index = 0, + buffer = None, + timeout = 10000) + + def finish(self): + self.__devhandle.controlMsg(requestType = 0x40, request = 6, + value = 0, index = 0, buffer = None, + timeout = 10000) + # This class only supports Gnuk (for now) class gnuk_token: def __init__(self, device, configuration, interface): @@ -80,9 +133,9 @@ class gnuk_token: self.__timeout = 10000 self.__seq = 0 - def stop_icc(self): - # XXX: need to disclaim interface and close device and re-open??? - # self.__devhandle.setConfiguration(0) + def stop_gnuk(self): + self.__devhandle.releaseInterface() + self.__devhandle.setConfiguration(0) return def mem_info(self): @@ -237,7 +290,7 @@ def compare(data_original, data_in_device): raise ValueError, "verify failed at %08x" % i i += 1 -def get_device(): +def get_ccid_device(): busses = usb.busses() for bus in busses: devices = bus.devices @@ -251,6 +304,21 @@ def get_device(): return dev, config, alt raise ValueError, "Device not found" +USB_VENDOR_FSIJ=0x234b +USB_PRODUCT_GNUK=0x0000 + +def get_gnuk_device(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + if dev.idVendor != USB_VENDOR_FSIJ: + continue + if dev.idProduct != USB_PRODUCT_GNUK: + continue + return dev + raise ValueError, "Device not found" + def to_string(t): result = "" for c in t: @@ -260,7 +328,7 @@ def to_string(t): def main(passwd, data_regnual, data_upgrade): data_regnual += pack(' Date: Tue, 22 May 2012 19:51:52 +0900 Subject: [PATCH 102/300] add -m flags for linking --- regnual/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/regnual/Makefile b/regnual/Makefile index 5e1e6eb..a6cad6f 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -16,7 +16,7 @@ OBJCOPY = $(TRGT)objcopy OBJDUMP = $(TRGT)objdump # THUMB-specific options here -TOPT = -mthumb -DTHUMB +TOPT = -mthumb -DTHUMB -mno-thumb-interwork # Define C warning options here CWARN = -Wall -Wextra -Wstrict-prototypes MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd @@ -25,7 +25,7 @@ DEFS = -DFREE_STANDING CFLAGS = -O2 -g CFLAGS += $(CWARN) -fno-common $(MCFLAGS) $(TOPT) $(DEFS) -LDFLAGS = -T$(LDSCRIPT) -nostartfiles +LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) #################### From 8e4775ab4ac06d7e792a28c62b546cc1a791182f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 12:16:31 +0900 Subject: [PATCH 103/300] improve regnual --- ChangeLog | 6 +++++ regnual/regnual.c | 59 +++++++++++++++++++++++----------------------- regnual/regnual.ld | 2 +- regnual/sys.c | 25 +------------------- 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 347d52e..d20bd8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-05-23 Niibe Yutaka + + * regnual/regnual.c (regnual_setup): Don't call flash_write here. + (regnual_ctrl_write_finish): But call here. + (USB_REGNUAL_RESULT): New. + 2012-05-22 Niibe Yutaka * src/configure (../regnual/sys.h): Create symblic link. diff --git a/regnual/regnual.c b/regnual/regnual.c index 21fab3f..779ecab 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -33,8 +33,7 @@ extern void *memset (void *s, int c, size_t n); extern void set_led (int); extern uint8_t _flash_start, _flash_end; extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len); -extern int flash_erase_page (uint32_t addr); -extern int flash_protect (void); +extern int flash_protect (uint16_t protection); extern void nvic_system_reset (void); @@ -123,15 +122,15 @@ regnual_device_reset (void) 64); } -#define USB_REGNUAL_MEMINFO 0 -#define USB_REGNUAL_SEND 1 -#define USB_REGNUAL_CRC32 2 -#define USB_REGNUAL_FLASH 3 -#define USB_REGNUAL_ERASE 4 -#define USB_REGNUAL_PROTECT 5 -#define USB_REGNUAL_FINISH 6 +#define USB_REGNUAL_MEMINFO 0 +#define USB_REGNUAL_SEND 1 +#define USB_REGNUAL_RESULT 2 +#define USB_REGNUAL_FLASH 3 +#define USB_REGNUAL_PROTECT 4 +#define USB_REGNUAL_FINISH 5 static uint8_t mem[256]; +static uint32_t result; static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; @@ -145,9 +144,21 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req) && len == 0) { - if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) + if (req_no == USB_REGNUAL_SEND && index == 0) + { + result = 0; // calculate crc32 here!!! + } + else if (req_no == USB_REGNUAL_FLASH && index == 0) + { + uint32_t dst_addr = (0x08000000 + value * 0x100); + + result = flash_write (dst_addr, mem, 256); + } + else if (req_no == USB_REGNUAL_PROTECT && index == 0) + result = flash_protect (value); + else if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) nvic_system_reset (); - } + } } static int @@ -165,11 +176,9 @@ regnual_setup (uint8_t req, uint8_t req_no, usb_lld_set_data_to_send (mem_info, sizeof (mem_info)); return USB_SUCCESS; } - else if (req_no == USB_REGNUAL_CRC32) + else if (req_no == USB_REGNUAL_RESULT) { - static uint32_t crc32_check = 0; /* calculate CRC32 for mem */ - - usb_lld_set_data_to_send (&crc32_check, sizeof (uint32_t)); + usb_lld_set_data_to_send (&result, sizeof (uint32_t)); return USB_SUCCESS; } } @@ -180,30 +189,22 @@ regnual_setup (uint8_t req, uint8_t req_no, if (value != 0 || index + len > 256) return USB_UNSUPPORT; - if (index != 0) - memset (mem, 0xff, 256); + if (index + len < 256) + memset (mem + index + len, 0xff, 256 - (index + len)); usb_lld_set_data_to_recv (mem + index, len); return USB_SUCCESS; } - else if (req_no == USB_REGNUAL_FLASH && len == 0) + else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0) { uint32_t dst_addr = (0x08000000 + value * 0x100); - if (flash_write (dst_addr, mem, 256) == 0) + if (dst_addr + 256 <= (uint32_t)&_flash_end) return USB_SUCCESS; } - else if (req_no == USB_REGNUAL_ERASE && len == 0 && index == 0) + else if (req_no == USB_REGNUAL_PROTECT && len == 0 && index == 0) { - uint32_t dst_addr = (0x08000000 + value * 0x100); - - if (flash_erase_page (dst_addr)) - return USB_SUCCESS; - } - else if (req_no == USB_REGNUAL_PROTECT && len == 0 - && value == 0 && index == 0) - { - if (flash_protect ()) + if (value == 0) return USB_SUCCESS; } else if (req_no == USB_REGNUAL_FINISH && len == 0 diff --git a/regnual/regnual.ld b/regnual/regnual.ld index d7a73e9..c2f2df4 100644 --- a/regnual/regnual.ld +++ b/regnual/regnual.ld @@ -12,7 +12,7 @@ MEMORY } _flash_start = 0x08000000; -_flash_end = 0x08010000; +_flash_end = 0x08020000; __ram_start__ = ORIGIN(ram0); __ram_size__ = 20k; diff --git a/regnual/sys.c b/regnual/sys.c index a8454db..254dd2f 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -431,30 +431,7 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) } int -flash_erase_page (uint32_t addr) -{ - int status; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - - intr_disable (); - if (status == FLASH_COMPLETE) - { - FLASH->CR |= FLASH_CR_PER; - FLASH->AR = addr; - FLASH->CR |= FLASH_CR_STRT; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - if (status != FLASH_TIMEOUT) - FLASH->CR &= ~FLASH_CR_PER; - } - intr_enable (); - - return status == FLASH_COMPLETE; -} - -int -flash_protect (void) +flash_protect (uint16_t protection) { /* Not yet implemented */ return 1; From 80e2d33a5152e86d35023d0844421aa83aca0d77 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 12:17:11 +0900 Subject: [PATCH 104/300] fix --- src/main.c | 5 +++-- src/usb_ctrl.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index a1cb495..80e263f 100644 --- a/src/main.c +++ b/src/main.c @@ -473,10 +473,11 @@ main (int argc, char *argv[]) #endif } + set_led (1); + /* USB Dissconnect (when supported) */ usb_lld_shutdown (); USB_Cable_Config (0); - set_led (1); - chThdSleep (MS2ST (100)); + chThdSleep (MS2ST (1)); /* > 2.5us required */ port_disable (); /* set vector */ SCB->VTOR = (uint32_t)&_regnual_start; diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 08c64ea..da116d0 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -228,8 +228,9 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (addr < &_regnual_start || addr + len > &__heap_end__) return USB_UNSUPPORT; - if (index == 0 && len != 256) - memset (addr, 0, 256); + if (index + len < 256) + memset (addr + index + len, 0, 256 - (index + len)); + usb_lld_set_data_to_recv (addr, len); return USB_SUCCESS; } From 365b59cd564d5007175f4861dc961d5c7e04cb93 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 12:17:56 +0900 Subject: [PATCH 105/300] follow change of regnual protocol --- tool/gnuk_upgrade.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 52ac333..4cff58d 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -73,31 +73,40 @@ class regnual: value = 0, index = 0, buffer = data[j*256:j*256+256], timeout = 10000) - print "flash" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, timeout = 10000) + time.sleep(0.01) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "failure" i = i+1 j = j+1 addr = addr + 256 residue = len(data) % 256 if residue != 0: print "# %08x: %d : %d" % (addr, i, residue) - print "send" self.__devhandle.controlMsg(requestType = 0x40, request = 1, value = 0, index = 0, buffer = data[j*256:], timeout = 10000) - if (i % 4) != 0 or residue: - print "flash" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, timeout = 10000) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "failure" def finish(self): - self.__devhandle.controlMsg(requestType = 0x40, request = 6, + self.__devhandle.controlMsg(requestType = 0x40, request = 5, value = 0, index = 0, buffer = None, timeout = 10000) @@ -133,6 +142,9 @@ class gnuk_token: self.__timeout = 10000 self.__seq = 0 + def reset_device(self): + self.__devhandle.reset() + def stop_gnuk(self): self.__devhandle.releaseInterface() self.__devhandle.setConfiguration(0) @@ -349,11 +361,16 @@ def main(passwd, data_regnual, data_upgrade): icc.download(mem_info[0], data_regnual) print "Run flash upgrade program..." icc.execute(mem_info[1] + len(data_regnual)) + # + try: + icc.reset_device() + except: + pass del icc icc = None # - print "Wait 3 seconds..." - time.sleep(3) + print "Wait 1 seconds..." + time.sleep(1) # Then, send upgrade program... dev = get_gnuk_device() print "Device: ", dev.filename @@ -361,7 +378,7 @@ def main(passwd, data_regnual, data_upgrade): mem_info = reg.mem_info() print "%08x:%08x" % mem_info print "Downloading the program" - reg.download(mem_info[0]+0x3000, data_upgrade) + reg.download(mem_info[0], data_upgrade) reg.finish() return 0 From d31b2211c6f3d1ef8024cfc859ec8ca4b9cd1866 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 14:55:04 +0900 Subject: [PATCH 106/300] mass erase --- ChangeLog | 3 +++ src/main.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index d20bd8b..c82af5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-05-23 Niibe Yutaka + * src/main.c (flash_mass_erase_and_exec, good_bye): New. + (main): Call good_bye. + * regnual/regnual.c (regnual_setup): Don't call flash_write here. (regnual_ctrl_write_finish): But call here. (USB_REGNUAL_RESULT): New. diff --git a/src/main.c b/src/main.c index 80e263f..f1e9257 100644 --- a/src/main.c +++ b/src/main.c @@ -369,6 +369,67 @@ led_blink (int spec) chEvtSignal (main_thread, LED_TWOSHOT); } + +static void __attribute__((naked)) +flash_mass_erase_and_exec (void) +{ + asm volatile (/* r0 = ; */ + "mov r0, #0x01000000\n\t" + /* r2 = (struct FLASH *)FLASH_R_BASE */ + "mov r2, #8192\n\t" + "movt r2, 16386\n\t" + /* FLASH->CR |= FLASH_CR_MER; */ + "ldr r1, [r2, #16]\n\t" + "orr r1, r1, #4\n\t" + "str r1, [r2, #16]\n\t" + /* FLASH->CR |= FLASH_CR_STRT; */ + "orr r1, r1, #64\n\t" + "str r1, [r2, #16]\n" + "0: subs r0, r0, #1\n\t" + "beq 1f\n\t" + /* r1 = FLASH->SR; */ + "ldr r1, [r2, #12]\n\t" + /* BUSY? */ + "tst r1, #1\n\t" + "bne 0b\n\t" + /* PGERR? */ + "tst r1, #4\n\t" + "bne 1f\n\t" + /* WRPRTERR? */ + "tst r1, #16\n\t" + "bne 1f\n\t" + /* Success. */ + /* exec */ + "bx r3\n" + "1: b 1b" + : /* no output*/ : /* no input */ : "memory"); +} + +static void __attribute__((noreturn)) +good_bye (void) +{ + register uint32_t dst __asm__ ("r0") = 0x20000000; + register uint32_t src __asm__ ("r1") = (uint32_t)flash_mass_erase_and_exec; + register uint32_t len __asm__ ("r2") = sizeof (flash_mass_erase_and_exec); + register void (**func )(void) __asm__ ("r3") + = (void (**)(void))(&_regnual_start + 4); + + /* copy function flash_mass_erase_and_exec to SRAM and jump to it */ + asm volatile ("mov r5, r0\n" + "add r2, r2, r1\n" + "0: ldr r4, [r1]\n\t" + "str r4, [r0]\n\t" + "adds r0, r0, #4\n\t" + "adds r1, r1, #4\n\t" + "cmp r2, r1\n\t" + "bgt 0b\n\t" + "bx r5" + : /* no output */ + : "r" (dst), "r" (src), "r" (len), "r" (func) + : "memory"); + for (;;); +} + /* * Entry point. * @@ -481,12 +542,10 @@ main (int argc, char *argv[]) port_disable (); /* set vector */ SCB->VTOR = (uint32_t)&_regnual_start; - { - /* Not yet: erase by mass erase and go to entry */ - void (**func)(void) = (void (**)(void))(&_regnual_start + 4); + /* leave Gnuk */ + good_bye (); - (**func) (); - } + /* Never reached */ return 0; } From b1cc1ec6f6a9b9b8b29a96fc46753980dabee59a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 15:25:20 +0900 Subject: [PATCH 107/300] protection --- ChangeLog | 5 +++++ regnual/regnual.c | 14 ++++++-------- regnual/sys.c | 34 +++++++++++++++++++++++++++++++--- tool/gnuk_upgrade.py | 12 ++++++++++++ 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index c82af5b..cea58d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,10 +3,15 @@ * src/main.c (flash_mass_erase_and_exec, good_bye): New. (main): Call good_bye. + * tool/gnuk_upgrade.py (regnual.protect): New. + (main): Call regnual.protect(). + * regnual/regnual.c (regnual_setup): Don't call flash_write here. (regnual_ctrl_write_finish): But call here. (USB_REGNUAL_RESULT): New. + * regnual/sys.c (flash_protect): New. + 2012-05-22 Niibe Yutaka * src/configure (../regnual/sys.h): Create symblic link. diff --git a/regnual/regnual.c b/regnual/regnual.c index 779ecab..8fcca88 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -33,7 +33,7 @@ extern void *memset (void *s, int c, size_t n); extern void set_led (int); extern uint8_t _flash_start, _flash_end; extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len); -extern int flash_protect (uint16_t protection); +extern int flash_protect (void); extern void nvic_system_reset (void); @@ -154,8 +154,8 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, result = flash_write (dst_addr, mem, 256); } - else if (req_no == USB_REGNUAL_PROTECT && index == 0) - result = flash_protect (value); + else if (req_no == USB_REGNUAL_PROTECT && value == 0 && index == 0) + result = flash_protect (); else if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) nvic_system_reset (); } @@ -202,11 +202,9 @@ regnual_setup (uint8_t req, uint8_t req_no, if (dst_addr + 256 <= (uint32_t)&_flash_end) return USB_SUCCESS; } - else if (req_no == USB_REGNUAL_PROTECT && len == 0 && index == 0) - { - if (value == 0) - return USB_SUCCESS; - } + else if (req_no == USB_REGNUAL_PROTECT && len == 0 + && value == 0 && index == 0) + return USB_SUCCESS; else if (req_no == USB_REGNUAL_FINISH && len == 0 && value == 0 && index == 0) return USB_SUCCESS; diff --git a/regnual/sys.c b/regnual/sys.c index 254dd2f..e99fcb2 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -430,11 +430,39 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) return 1; } +#define FLASH_OPTION_BYTE_RDP 0x1ffff800 + int -flash_protect (uint16_t protection) +flash_protect (void) { - /* Not yet implemented */ - return 1; + int status; + uint16_t rdp; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + + intr_disable (); + if (status == FLASH_COMPLETE) + { + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + + FLASH->CR |= FLASH_CR_OPTER; + FLASH->CR |= FLASH_CR_STRT; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + if (status != FLASH_TIMEOUT) + FLASH->CR &= ~FLASH_CR_OPTER; + } + intr_enable (); + + if (status != FLASH_COMPLETE) + return 0; + + rdp = *(volatile uint16_t *)FLASH_OPTION_BYTE_RDP; + if (rdp == 0x00ff) + return 1; + else + return 0; } struct SCB diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 4cff58d..c1dfbd3 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -105,6 +105,17 @@ class regnual: if r_value == 0: print "failure" + def protect(self): + self.__devhandle.controlMsg(requestType = 0x40, request = 4, + value = 0, index = 0, buffer = None, + timeout = 10000) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "protect failure" + def finish(self): self.__devhandle.controlMsg(requestType = 0x40, request = 5, value = 0, index = 0, buffer = None, @@ -379,6 +390,7 @@ def main(passwd, data_regnual, data_upgrade): print "%08x:%08x" % mem_info print "Downloading the program" reg.download(mem_info[0], data_upgrade) + reg.protect() reg.finish() return 0 From dec12d4b15db918b74b7428f04648f819487f38b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 15:48:49 +0900 Subject: [PATCH 108/300] fix --- regnual/sys.c | 11 +++++------ tool/gnuk_upgrade.py | 6 ++++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/regnual/sys.c b/regnual/sys.c index e99fcb2..4fc4daa 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -351,6 +351,8 @@ handler vector_table[] __attribute__ ((section(".vectors"))) = { #define FLASH_CR_ERRIE 0x0400 #define FLASH_CR_EOPIE 0x1000 +#define FLASH_OBR_RDPRT 0x00000002 + static int flash_get_status (void) { @@ -430,15 +432,13 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) return 1; } -#define FLASH_OPTION_BYTE_RDP 0x1ffff800 - int flash_protect (void) { int status; uint16_t rdp; - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); intr_disable (); if (status == FLASH_COMPLETE) @@ -449,7 +449,7 @@ flash_protect (void) FLASH->CR |= FLASH_CR_OPTER; FLASH->CR |= FLASH_CR_STRT; - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); if (status != FLASH_TIMEOUT) FLASH->CR &= ~FLASH_CR_OPTER; } @@ -458,8 +458,7 @@ flash_protect (void) if (status != FLASH_COMPLETE) return 0; - rdp = *(volatile uint16_t *)FLASH_OPTION_BYTE_RDP; - if (rdp == 0x00ff) + if ((FLASH->OBR & FLASH_OBR_RDPRT) != 0) return 1; else return 0; diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index c1dfbd3..d979a74 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -77,7 +77,7 @@ class regnual: value = i, index = 0, buffer = None, timeout = 10000) - time.sleep(0.01) + time.sleep(0.010) res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, value = 0, index = 0, buffer = 4, timeout = 10000) @@ -98,6 +98,7 @@ class regnual: value = i, index = 0, buffer = None, timeout = 10000) + time.sleep(0.010) res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, value = 0, index = 0, buffer = 4, timeout = 10000) @@ -109,12 +110,13 @@ class regnual: self.__devhandle.controlMsg(requestType = 0x40, request = 4, value = 0, index = 0, buffer = None, timeout = 10000) + time.sleep(0.100) res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, value = 0, index = 0, buffer = 4, timeout = 10000) r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] if r_value == 0: - print "protect failure" + print "protection failure" def finish(self): self.__devhandle.controlMsg(requestType = 0x40, request = 5, From b02c6a480d05ed3183a4fa3e5f4a8a7fdf932813 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 16:02:02 +0900 Subject: [PATCH 109/300] support stm8s-discovery --- regnual/sys-stm8s-discovery.h | 13 ++++++++++++ regnual/sys.c | 37 +++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 regnual/sys-stm8s-discovery.h diff --git a/regnual/sys-stm8s-discovery.h b/regnual/sys-stm8s-discovery.h new file mode 100644 index 0000000..d9d6933 --- /dev/null +++ b/regnual/sys-stm8s-discovery.h @@ -0,0 +1,13 @@ +#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HSECLK 8000000 + +#undef GPIO_USB_CLEAR_TO_ENABLE +#define GPIO_LED_SET_TO_EMIT 8 + +#define VAL_GPIO_ODR 0xFFFFFFFF +#define VAL_GPIO_CRH 0x88888883 /* PD15...PD8 */ +#define VAL_GPIO_CRL 0x88888888 /* PD7...PD0 */ + +#define GPIO_LED_BASE GPIOA_BASE +#undef GPIO_USB_BASE diff --git a/regnual/sys.c b/regnual/sys.c index 4fc4daa..b7aac3d 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -177,7 +177,9 @@ struct GPIO { #define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) #define GPIOE ((struct GPIO *) GPIOE_BASE) +#ifdef GPIO_USB_BASE #define GPIO_USB ((struct GPIO *) GPIO_USB_BASE) +#endif #define GPIO_LED ((struct GPIO *) GPIO_LED_BASE) static __attribute__ ((used)) @@ -188,37 +190,53 @@ void gpio_init (void) RCC->APB2RSTR = RCC_APB2RSTR_IOPDRST; RCC->APB2RSTR = 0; - GPIO_USB->ODR = VAL_GPIO_ODR; - GPIO_USB->CRH = VAL_GPIO_CRH; - GPIO_USB->CRL = VAL_GPIO_CRL; + GPIO_LED->ODR = VAL_GPIO_ODR; + GPIO_LED->CRH = VAL_GPIO_CRH; + GPIO_LED->CRL = VAL_GPIO_CRL; -#if GPIO_USB_BASE != GPIO_LED_BASE - GPIO_LED->ODR = VAL_GPIO_LED_ODR; - GPIO_LED->CRH = VAL_GPIO_LED_CRH; - GPIO_LED->CRL = VAL_GPIO_LED_CRL; +#if defined(GPIO_USB_BASE) && GPIO_USB_BASE != GPIO_LED_BASE + GPIO_USB->ODR = VAL_GPIO_USB_ODR; + GPIO_USB->CRH = VAL_GPIO_USB_CRH; + GPIO_USB->CRL = VAL_GPIO_USB_CRL; #endif } static void usb_cable_config (int on) { -#if defined(GPIO_USB_CLEAR_TO_ENABLE) +#ifdef GPIO_USB_BASE +# ifdef GPIO_USB_CLEAR_TO_ENABLE if (on) GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); else GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); +# endif +# ifdef GPIO_USB_SET_TO_ENABLE + if (on) + GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE); + else + GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE); +# endif +#else + (void)on; #endif } void set_led (int on) { -#if defined(GPIO_LED_CLEAR_TO_EMIT) +#ifdef GPIO_LED_CLEAR_TO_EMIT if (on) GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT); else GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT); #endif +#ifdef GPIO_LED_SET_TO_EMIT + if (on) + GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT); + else + GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT); +#endif } @@ -436,7 +454,6 @@ int flash_protect (void) { int status; - uint16_t rdp; status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); From 4a59c73bc38e7ec95837436a8bc62c7781f3d863 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 17:07:30 +0900 Subject: [PATCH 110/300] main.c --- ChangeLog | 2 ++ src/main.c | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index cea58d3..c7aa96a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-23 Niibe Yutaka + * regnual/sys-stm8s-discovery.h: New. + * src/main.c (flash_mass_erase_and_exec, good_bye): New. (main): Call good_bye. diff --git a/src/main.c b/src/main.c index f1e9257..7d486ad 100644 --- a/src/main.c +++ b/src/main.c @@ -370,11 +370,13 @@ led_blink (int spec) } +#define FMEAE_SIZE 56 + static void __attribute__((naked)) flash_mass_erase_and_exec (void) { asm volatile (/* r0 = ; */ - "mov r0, #0x01000000\n\t" + "mov r0, #0xF0000000\n\t" /* r2 = (struct FLASH *)FLASH_R_BASE */ "mov r2, #8192\n\t" "movt r2, 16386\n\t" @@ -383,6 +385,7 @@ flash_mass_erase_and_exec (void) "orr r1, r1, #4\n\t" "str r1, [r2, #16]\n\t" /* FLASH->CR |= FLASH_CR_STRT; */ + "ldr r1, [r2, #16]\n\t" "orr r1, r1, #64\n\t" "str r1, [r2, #16]\n" "0: subs r0, r0, #1\n\t" @@ -408,21 +411,23 @@ flash_mass_erase_and_exec (void) static void __attribute__((noreturn)) good_bye (void) { - register uint32_t dst __asm__ ("r0") = 0x20000000; + register uint32_t dst __asm__ ("r0") = 0x20000000; /* SRAM top */ register uint32_t src __asm__ ("r1") = (uint32_t)flash_mass_erase_and_exec; - register uint32_t len __asm__ ("r2") = sizeof (flash_mass_erase_and_exec); + register uint32_t len __asm__ ("r2") = FMEAE_SIZE; register void (**func )(void) __asm__ ("r3") = (void (**)(void))(&_regnual_start + 4); /* copy function flash_mass_erase_and_exec to SRAM and jump to it */ - asm volatile ("mov r5, r0\n" + asm volatile ("ldr r3, [r3, #4]\n\t" + "mov r5, r0\n\t" "add r2, r2, r1\n" "0: ldr r4, [r1]\n\t" "str r4, [r0]\n\t" - "adds r0, r0, #4\n\t" - "adds r1, r1, #4\n\t" + "add r0, r0, #4\n\t" + "add r1, r1, #4\n\t" "cmp r2, r1\n\t" - "bgt 0b\n\t" + "bhi 0b\n\t" + "isb\n\t" "bx r5" : /* no output */ : "r" (dst), "r" (src), "r" (len), "r" (func) From 21053abc511b92855caa578daa6f1063be9930cb Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 23 May 2012 17:50:47 +0900 Subject: [PATCH 111/300] fix main --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 7d486ad..66826c5 100644 --- a/src/main.c +++ b/src/main.c @@ -418,7 +418,7 @@ good_bye (void) = (void (**)(void))(&_regnual_start + 4); /* copy function flash_mass_erase_and_exec to SRAM and jump to it */ - asm volatile ("ldr r3, [r3, #4]\n\t" + asm volatile ("ldr r3, [r3]\n\t" "mov r5, r0\n\t" "add r2, r2, r1\n" "0: ldr r4, [r1]\n\t" From 0c721d6e10b74830f3512440e1994fa72caa9b0a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 May 2012 09:03:22 +0900 Subject: [PATCH 112/300] remove space --- src/flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash.c b/src/flash.c index f6322c1..4f4bc07 100644 --- a/src/flash.c +++ b/src/flash.c @@ -62,7 +62,7 @@ flash_get_status (void) status = FLASH_BUSY; else if ((FLASH->SR & FLASH_SR_PGERR) != 0) status = FLASH_ERROR_PG; - else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0 ) + else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0) status = FLASH_ERROR_WRP; else status = FLASH_COMPLETE; From 94e38ae1bc342b9ca72c8554f64da5f226d8a927 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 May 2012 09:03:51 +0900 Subject: [PATCH 113/300] reset device --- tool/gnuk_upgrade.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index d979a74..e587c3a 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -123,6 +123,12 @@ class regnual: value = 0, index = 0, buffer = None, timeout = 10000) + def reset_device(self): + try: + self.__devhandle.reset() + except: + pass + # This class only supports Gnuk (for now) class gnuk_token: def __init__(self, device, configuration, interface): @@ -156,7 +162,10 @@ class gnuk_token: self.__seq = 0 def reset_device(self): - self.__devhandle.reset() + try: + self.__devhandle.reset() + except: + pass def stop_gnuk(self): self.__devhandle.releaseInterface() @@ -375,10 +384,7 @@ def main(passwd, data_regnual, data_upgrade): print "Run flash upgrade program..." icc.execute(mem_info[1] + len(data_regnual)) # - try: - icc.reset_device() - except: - pass + icc.reset_device() del icc icc = None # @@ -394,6 +400,7 @@ def main(passwd, data_regnual, data_upgrade): reg.download(mem_info[0], data_upgrade) reg.protect() reg.finish() + reg.reset_device() return 0 DEFAULT_PW3 = "12345678" From e99d129c97c843ca7d6fe01154099742cfcc6156 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 May 2012 09:07:00 +0900 Subject: [PATCH 114/300] fix mass erase on SRAM --- ChangeLog | 5 ++++ src/main.c | 83 ++++++++++++++++++++++-------------------------------- 2 files changed, 39 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7aa96a..5178c65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-05-24 Niibe Yutaka + + * src/main.c (good_bye): Care LSB of function pointer. + (flash_mass_erase_and_exec): Implemented in C. + 2012-05-23 Niibe Yutaka * regnual/sys-stm8s-discovery.h: New. diff --git a/src/main.c b/src/main.c index 66826c5..6eb86e7 100644 --- a/src/main.c +++ b/src/main.c @@ -370,68 +370,53 @@ led_blink (int spec) } -#define FMEAE_SIZE 56 +#define FMEAE_SIZE 128 + +#define FLASH_MASS_ERASE_TIMEOUT 0xF0000000 static void __attribute__((naked)) flash_mass_erase_and_exec (void) { - asm volatile (/* r0 = ; */ - "mov r0, #0xF0000000\n\t" - /* r2 = (struct FLASH *)FLASH_R_BASE */ - "mov r2, #8192\n\t" - "movt r2, 16386\n\t" - /* FLASH->CR |= FLASH_CR_MER; */ - "ldr r1, [r2, #16]\n\t" - "orr r1, r1, #4\n\t" - "str r1, [r2, #16]\n\t" - /* FLASH->CR |= FLASH_CR_STRT; */ - "ldr r1, [r2, #16]\n\t" - "orr r1, r1, #64\n\t" - "str r1, [r2, #16]\n" - "0: subs r0, r0, #1\n\t" - "beq 1f\n\t" - /* r1 = FLASH->SR; */ - "ldr r1, [r2, #12]\n\t" - /* BUSY? */ - "tst r1, #1\n\t" - "bne 0b\n\t" - /* PGERR? */ - "tst r1, #4\n\t" - "bne 1f\n\t" - /* WRPRTERR? */ - "tst r1, #16\n\t" - "bne 1f\n\t" - /* Success. */ - /* exec */ - "bx r3\n" - "1: b 1b" - : /* no output*/ : /* no input */ : "memory"); + void (**func )(void) = (void (**)(void))(&_regnual_start + 4); + + if ((FLASH->SR & FLASH_SR_BSY) == 0) + { + uint32_t t = FLASH_MASS_ERASE_TIMEOUT; + + FLASH->CR |= FLASH_CR_MER; + FLASH->CR |= FLASH_CR_STRT; + + while ((FLASH->SR & FLASH_SR_BSY) != 0 && t) + --t; + + if ((FLASH->SR & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR)) == 0) + (**func) (); + } + + palClearPad (IOPORT1, GPIOA_LED); + for (;;); } static void __attribute__((noreturn)) good_bye (void) { register uint32_t dst __asm__ ("r0") = 0x20000000; /* SRAM top */ - register uint32_t src __asm__ ("r1") = (uint32_t)flash_mass_erase_and_exec; + register uint32_t src __asm__ ("r1") = (uint32_t)flash_mass_erase_and_exec & ~1; register uint32_t len __asm__ ("r2") = FMEAE_SIZE; - register void (**func )(void) __asm__ ("r3") - = (void (**)(void))(&_regnual_start + 4); + register uint32_t entry __asm__ ("r3") = dst | 1; + register uint32_t use __asm__ ("r4"); /* copy function flash_mass_erase_and_exec to SRAM and jump to it */ - asm volatile ("ldr r3, [r3]\n\t" - "mov r5, r0\n\t" - "add r2, r2, r1\n" - "0: ldr r4, [r1]\n\t" - "str r4, [r0]\n\t" - "add r0, r0, #4\n\t" - "add r1, r1, #4\n\t" - "cmp r2, r1\n\t" - "bhi 0b\n\t" - "isb\n\t" - "bx r5" - : /* no output */ - : "r" (dst), "r" (src), "r" (len), "r" (func) - : "memory"); + asm volatile("add r2, r2, r1\n" + "0: ldr r4, [r1], #4\n\t" + "cmp r2, r1\n\t" + "str r4, [r0], #4\n\t" + "bhi 0b\n\t" + "isb\n\t" + "bx r3" + : "=r" (dst), "=r" (src), "=r" (len), "=r" (use) + : "0" (dst), "1" (src), "2" (len), "r" (entry) + : "memory"); for (;;); } From 1c910fc3e2bee72994408327ef931be56dc1b115 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 May 2012 19:09:05 +0900 Subject: [PATCH 115/300] clear CR_MER --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index 6eb86e7..d704e1c 100644 --- a/src/main.c +++ b/src/main.c @@ -389,6 +389,7 @@ flash_mass_erase_and_exec (void) while ((FLASH->SR & FLASH_SR_BSY) != 0 && t) --t; + FLASH->CR &= ~FLASH_CR_MER; if ((FLASH->SR & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR)) == 0) (**func) (); } From 37f82b602681f86b9b708a8bbbbd77009ef47a84 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 24 May 2012 21:59:11 +0900 Subject: [PATCH 116/300] fix --- regnual/sys.c | 60 ++++++++++++++++++++++++++------------------------- src/main.c | 8 +++---- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/regnual/sys.c b/regnual/sys.c index b7aac3d..1f1d77f 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -271,11 +271,34 @@ enum flash_status FLASH_TIMEOUT }; +#define FLASH_SR_BSY 0x01 +#define FLASH_SR_PGERR 0x04 +#define FLASH_SR_WRPRTERR 0x10 +#define FLASH_SR_EOP 0x20 + +#define FLASH_CR_PG 0x0001 +#define FLASH_CR_PER 0x0002 +#define FLASH_CR_MER 0x0004 +#define FLASH_CR_OPTPG 0x0010 +#define FLASH_CR_OPTER 0x0020 +#define FLASH_CR_STRT 0x0040 +#define FLASH_CR_LOCK 0x0080 +#define FLASH_CR_OPTWRE 0x0200 +#define FLASH_CR_ERRIE 0x0400 +#define FLASH_CR_EOPIE 0x1000 + +#define FLASH_OBR_RDPRT 0x00000002 + +#define OPTION_BYTES_ADDR 0x1ffff800 + static void __attribute__ ((used)) flash_unlock (void) { - FLASH->KEYR = FLASH_KEY1; - FLASH->KEYR = FLASH_KEY2; + if ((FLASH->CR & FLASH_CR_LOCK) != 0) + { + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } } static void fatal (void) @@ -353,24 +376,6 @@ handler vector_table[] __attribute__ ((section(".vectors"))) = { usb_interrupt_handler, }; -#define FLASH_SR_BSY 0x01 -#define FLASH_SR_PGERR 0x04 -#define FLASH_SR_WRPRTERR 0x10 -#define FLASH_SR_EOP 0x20 - -#define FLASH_CR_PG 0x0001 -#define FLASH_CR_PER 0x0002 -#define FLASH_CR_MER 0x0004 -#define FLASH_CR_OPTPG 0x0010 -#define FLASH_CR_OPTER 0x0020 -#define FLASH_CR_STRT 0x0040 -#define FLASH_CR_LOCK 0x0080 -#define FLASH_CR_OPTWRE 0x0200 -#define FLASH_CR_ERRIE 0x0400 -#define FLASH_CR_EOPIE 0x1000 - -#define FLASH_OBR_RDPRT 0x00000002 - static int flash_get_status (void) { @@ -421,8 +426,7 @@ flash_program_halfword (uint32_t addr, uint16_t data) *(volatile uint16_t *)addr = data; status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - if (status != FLASH_TIMEOUT) - FLASH->CR &= ~FLASH_CR_PG; + FLASH->CR &= ~FLASH_CR_PG; } intr_enable (); @@ -441,7 +445,7 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) hw |= (*src++ << 8); status = flash_program_halfword (dst_addr, hw); if (status != FLASH_COMPLETE) - return 0; + return 0; /* error return */ dst_addr += 2; len -= 2; @@ -454,6 +458,7 @@ int flash_protect (void) { int status; + uint32_t option_bytes_value; status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); @@ -467,18 +472,15 @@ flash_protect (void) FLASH->CR |= FLASH_CR_STRT; status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - if (status != FLASH_TIMEOUT) - FLASH->CR &= ~FLASH_CR_OPTER; + FLASH->CR &= ~FLASH_CR_OPTER; } intr_enable (); if (status != FLASH_COMPLETE) return 0; - if ((FLASH->OBR & FLASH_OBR_RDPRT) != 0) - return 1; - else - return 0; + option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR; + return (option_bytes_value & 0xff) == 0xff ? 1 : 0; } struct SCB diff --git a/src/main.c b/src/main.c index d704e1c..135a9d4 100644 --- a/src/main.c +++ b/src/main.c @@ -381,20 +381,18 @@ flash_mass_erase_and_exec (void) if ((FLASH->SR & FLASH_SR_BSY) == 0) { - uint32_t t = FLASH_MASS_ERASE_TIMEOUT; - FLASH->CR |= FLASH_CR_MER; FLASH->CR |= FLASH_CR_STRT; - while ((FLASH->SR & FLASH_SR_BSY) != 0 && t) - --t; + while ((FLASH->SR & FLASH_SR_BSY) != 0) + ; FLASH->CR &= ~FLASH_CR_MER; + if ((FLASH->SR & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR)) == 0) (**func) (); } - palClearPad (IOPORT1, GPIOA_LED); for (;;); } From 8c6ffaa167feb19ed08338405d8df26c2337fa37 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 25 May 2012 09:12:37 +0900 Subject: [PATCH 117/300] fix sys.c --- ChangeLog | 5 ++++ regnual/sys.c | 73 +++------------------------------------------------ 2 files changed, 8 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5178c65..d3f44ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-05-25 Niibe Yutaka + + * regnual/sys.c (clock_init, gpio_init, flash_unlock): Removed. + (entry): Rename (was: reset). + 2012-05-24 Niibe Yutaka * src/main.c (good_bye): Care LSB of function pointer. diff --git a/regnual/sys.c b/regnual/sys.c index 1f1d77f..ff92e23 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -111,41 +111,6 @@ struct FLASH { #define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) #define FLASH ((struct FLASH *) FLASH_R_BASE) -static __attribute__ ((used)) -void clock_init (void) -{ - /* HSI setup */ - RCC->CR |= RCC_CR_HSION; - while (!(RCC->CR & RCC_CR_HSIRDY)) - ; - RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION; - RCC->CFGR = 0; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) - ; - - /* HSE setup */ - RCC->CR |= RCC_CR_HSEON; - while (!(RCC->CR & RCC_CR_HSERDY)) - ; - - /* PLL setup */ - RCC->CFGR |= STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC; - RCC->CR |= RCC_CR_PLLON; - while (!(RCC->CR & RCC_CR_PLLRDY)) - ; - - /* Clock settings */ - RCC->CFGR = STM32_MCO | STM32_PLLMUL | STM32_PLLXTPRE | STM32_PLLSRC | - STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE; - - /* Flash setup */ - FLASH->ACR = STM32_FLASHBITS; - - /* Switching on the configured clock source. */ - RCC->CFGR |= STM32_SW; - while ((RCC->CFGR & RCC_CFGR_SWS) != (STM32_SW << 2)) - ; -} #define RCC_APB2ENR_IOPAEN 0x00000004 #define RCC_APB2RSTR_IOPARST 0x00000004 @@ -182,25 +147,6 @@ struct GPIO { #endif #define GPIO_LED ((struct GPIO *) GPIO_LED_BASE) -static __attribute__ ((used)) -void gpio_init (void) -{ - /* Enable GPIOD clock. */ - RCC->APB2ENR |= RCC_APB2ENR_IOPDEN; - RCC->APB2RSTR = RCC_APB2RSTR_IOPDRST; - RCC->APB2RSTR = 0; - - GPIO_LED->ODR = VAL_GPIO_ODR; - GPIO_LED->CRH = VAL_GPIO_CRH; - GPIO_LED->CRL = VAL_GPIO_CRL; - -#if defined(GPIO_USB_BASE) && GPIO_USB_BASE != GPIO_LED_BASE - GPIO_USB->ODR = VAL_GPIO_USB_ODR; - GPIO_USB->CRH = VAL_GPIO_USB_CRH; - GPIO_USB->CRL = VAL_GPIO_USB_CRL; -#endif -} - static void usb_cable_config (int on) { @@ -258,7 +204,6 @@ void usb_lld_sys_shutdown (void) } - #define FLASH_KEY1 0x45670123UL #define FLASH_KEY2 0xCDEF89ABUL @@ -291,16 +236,6 @@ enum flash_status #define OPTION_BYTES_ADDR 0x1ffff800 -static void __attribute__ ((used)) -flash_unlock (void) -{ - if ((FLASH->CR & FLASH_CR_LOCK) != 0) - { - FLASH->KEYR = FLASH_KEY1; - FLASH->KEYR = FLASH_KEY2; - } -} - static void fatal (void) { for (;;); @@ -310,8 +245,9 @@ static void none (void) { } +/* Note: it is not reset */ static __attribute__ ((naked)) -void reset (void) +void entry (void) { asm volatile ("cpsid i\n\t" /* Mask all interrupts */ "ldr r0, =__ram_end__\n\t" @@ -319,7 +255,6 @@ void reset (void) "ldr r1, =__main_stack_size__\n\t" "subs r0, r0, r1\n\t" "msr PSP, r0\n\t" /* Process (main routine) stack */ - "bl clock_init\n\t" "movs r0, #0\n\t" "ldr r1, =_bss_start\n\t" "ldr r2, =_bss_start\n" @@ -333,8 +268,6 @@ void reset (void) "movs r0, #2\n\t" /* Switch to PSP */ "msr CONTROL, r0\n\t" "isb\n\t" - "bl flash_unlock\n\t" - "bl gpio_init\n\t" "movs r0, #0\n\t" "msr BASEPRI, r0\n\t" /* Enable interrupts */ "cpsie i\n\t" @@ -356,7 +289,7 @@ extern void usb_interrupt_handler (void); handler vector_table[] __attribute__ ((section(".vectors"))) = { (handler)&__ram_end__, - reset, + entry, fatal, /* nmi */ fatal, /* hard fault */ /* 10 */ From 6b47ee56b8118158edb3eb6677317e8a5853bdf7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 25 May 2012 15:20:08 +0900 Subject: [PATCH 118/300] use functions in sys --- ChangeLog | 26 +++ boards/STM8S_DISCOVERY/board.c | 16 -- boards/STM8S_DISCOVERY/board.h | 6 + boards/common/hw_config.c | 14 -- regnual/Makefile | 2 +- regnual/regnual.c | 1 + regnual/regnual.ld | 1 + regnual/sys-stbee.h | 16 -- regnual/sys-stm8s-discovery.h | 13 -- regnual/sys.c | 386 +-------------------------------- src/Makefile.in | 5 +- src/configure | 3 - src/flash.c | 131 +---------- src/gnuk.h | 4 - src/main.c | 55 +---- src/openpgp-do.c | 1 + src/sys.c | 276 +++++++++++++++++++++++ src/sys.h | 92 ++++++++ src/usb_ctrl.c | 11 + src/usb_lld.c | 2 +- src/usb_lld.h | 3 - src/usb_lld_sys.c | 34 --- 22 files changed, 431 insertions(+), 667 deletions(-) delete mode 100644 boards/common/hw_config.c delete mode 100644 regnual/sys-stbee.h delete mode 100644 regnual/sys-stm8s-discovery.h create mode 100644 src/sys.c create mode 100644 src/sys.h delete mode 100644 src/usb_lld_sys.c diff --git a/ChangeLog b/ChangeLog index d3f44ae..d42d18a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,31 @@ 2012-05-25 Niibe Yutaka + * boards/STM8S_DISCOVERY/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/STM8S_DISCOVERY/board.c (USB_Cable_Config, set_led): + Remove. + + * regnual/Makefile: Add -I ../src to CFLAGS. + + * regnual/regnual.ld (vector): New. + + * regnual/sys.c: Remove implementation, but jump to vector by sys.h. + + * src/Makefile.in: Follow change of files. + + * src/configure: Undo changes of 2012-05-22. + + * boards/common/hw_config.c: Remove. Mov function to sys.c. + * src/flash.c: Move functions to sys.c. + * src/sys.c: New. + + * src/main.c (main): Call flash_mass_erase_and_exec. + + * src/usb_lld.c: Include sys.h. + + * src/usb_lld_sys.c: Remove. Move interrupt handler to... + * src/usb_ctrl.c: ... this file. + * regnual/sys.c (clock_init, gpio_init, flash_unlock): Removed. (entry): Rename (was: reset). diff --git a/boards/STM8S_DISCOVERY/board.c b/boards/STM8S_DISCOVERY/board.c index 355efc9..554b598 100644 --- a/boards/STM8S_DISCOVERY/board.c +++ b/boards/STM8S_DISCOVERY/board.c @@ -46,22 +46,6 @@ hwinit1 (void) AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP_PARTIALREMAP; } -void -USB_Cable_Config (FunctionalState NewState) -{ - /* No functionality to stop USB. */ - (void)NewState; -} - -void -set_led (int value) -{ - if (value) - palSetPad (IOPORT1, GPIOA_LED); - else - palClearPad (IOPORT1, GPIOA_LED); -} - #if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) diff --git a/boards/STM8S_DISCOVERY/board.h b/boards/STM8S_DISCOVERY/board.h index 71ad5f2..a9cb272 100644 --- a/boards/STM8S_DISCOVERY/board.h +++ b/boards/STM8S_DISCOVERY/board.h @@ -32,6 +32,12 @@ * Setup for the ST-Link part of STM8S-Discovery board. */ +#undef SET_USB_CONDITION /* No functionality to disconnect USB */ +#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ +#define GPIO_LED GPIOA_LED +#define IOPORT_LED GPIOA +#define FLASH_PAGE_SIZE 1024 + /* * Board identifier. */ diff --git a/boards/common/hw_config.c b/boards/common/hw_config.c deleted file mode 100644 index 0a59997..0000000 --- a/boards/common/hw_config.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Hardware specific function */ - -#include "ch.h" -#include "hal.h" -#include "board.h" - -const uint8_t * -unique_device_id (void) -{ - /* STM32F103 has 96-bit unique device identifier */ - const uint8_t *addr = (const uint8_t *)0x1ffff7e8; - - return addr; -} diff --git a/regnual/Makefile b/regnual/Makefile index a6cad6f..991fad4 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -23,7 +23,7 @@ MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd DEFS = -DFREE_STANDING CFLAGS = -O2 -g -CFLAGS += $(CWARN) -fno-common $(MCFLAGS) $(TOPT) $(DEFS) +CFLAGS += $(CWARN) -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS) LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) diff --git a/regnual/regnual.c b/regnual/regnual.c index 8fcca88..1b761da 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -27,6 +27,7 @@ #include "types.h" #include "usb_lld.h" +#include "sys.h" extern void *memset (void *s, int c, size_t n); diff --git a/regnual/regnual.ld b/regnual/regnual.ld index c2f2df4..8b7313e 100644 --- a/regnual/regnual.ld +++ b/regnual/regnual.ld @@ -11,6 +11,7 @@ MEMORY ram1 : org = 0x20001400, len = 20k - 0x1400 } +vector = 0x08000000; _flash_start = 0x08000000; _flash_end = 0x08020000; diff --git a/regnual/sys-stbee.h b/regnual/sys-stbee.h deleted file mode 100644 index e164790..0000000 --- a/regnual/sys-stbee.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * system settings. - */ -#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 -#define STM32_PLLMUL_VALUE 6 -#define STM32_HSECLK 12000000 - -#define GPIO_USB_CLEAR_TO_ENABLE 3 -#define GPIO_LED_CLEAR_TO_EMIT 4 - -#define VAL_GPIO_ODR 0xFFFFFFFF -#define VAL_GPIO_CRH 0x88888888 /* PD15...PD8 */ -#define VAL_GPIO_CRL 0x88862888 /* PD7...PD0 */ - -#define GPIO_USB_BASE GPIOD_BASE -#define GPIO_LED_BASE GPIOD_BASE diff --git a/regnual/sys-stm8s-discovery.h b/regnual/sys-stm8s-discovery.h deleted file mode 100644 index d9d6933..0000000 --- a/regnual/sys-stm8s-discovery.h +++ /dev/null @@ -1,13 +0,0 @@ -#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 -#define STM32_PLLMUL_VALUE 9 -#define STM32_HSECLK 8000000 - -#undef GPIO_USB_CLEAR_TO_ENABLE -#define GPIO_LED_SET_TO_EMIT 8 - -#define VAL_GPIO_ODR 0xFFFFFFFF -#define VAL_GPIO_CRH 0x88888883 /* PD15...PD8 */ -#define VAL_GPIO_CRL 0x88888888 /* PD7...PD0 */ - -#define GPIO_LED_BASE GPIOA_BASE -#undef GPIO_USB_BASE diff --git a/regnual/sys.c b/regnual/sys.c index ff92e23..fc8d0a9 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -1,240 +1,4 @@ #include "types.h" -#include "sys.h" - -#define STM32_SW_PLL (2 << 0) -#define STM32_PLLSRC_HSE (1 << 16) - -#define STM32_PLLXTPRE_DIV1 (0 << 17) -#define STM32_PLLXTPRE_DIV2 (1 << 17) - -#define STM32_HPRE_DIV1 (0 << 4) - -#define STM32_PPRE1_DIV2 (4 << 8) - -#define STM32_PPRE2_DIV2 (4 << 11) - -#define STM32_ADCPRE_DIV4 (1 << 14) - -#define STM32_MCO_NOCLOCK (0 << 24) - -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#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_MCO STM32_MCO_NOCLOCK - -#define STM32_PLLCLKIN (STM32_HSECLK / 1) -#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18) -#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE) -#define STM32_SYSCLK STM32_PLLCLKOUT -#define STM32_HCLK (STM32_SYSCLK / 1) - -#define STM32_FLASHBITS 0x00000012 - -struct NVIC { - uint32_t ISER[8]; - uint32_t unused1[24]; - uint32_t ICER[8]; - uint32_t unused2[24]; - uint32_t ISPR[8]; - uint32_t unused3[24]; - uint32_t ICPR[8]; - uint32_t unused4[24]; - uint32_t IABR[8]; - uint32_t unused5[56]; - uint32_t IPR[60]; -}; - -#define NVICBase ((struct NVIC *)0xE000E100) -#define NVIC_ISER(n) (NVICBase->ISER[n]) -#define NVIC_ICPR(n) (NVICBase->ICPR[n]) -#define NVIC_IPR(n) (NVICBase->IPR[n]) - -static void NVICEnableVector (uint32_t n, uint32_t prio) -{ - unsigned int sh = (n & 3) << 3; - - NVIC_IPR (n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); - NVIC_ICPR (n >> 5) = 1 << (n & 0x1F); - NVIC_ISER (n >> 5) = 1 << (n & 0x1F); -} - - -#define PERIPH_BASE 0x40000000 -#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) -#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) - -struct RCC { - __IO uint32_t CR; - __IO uint32_t CFGR; - __IO uint32_t CIR; - __IO uint32_t APB2RSTR; - __IO uint32_t APB1RSTR; - __IO uint32_t AHBENR; - __IO uint32_t APB2ENR; - __IO uint32_t APB1ENR; - __IO uint32_t BDCR; - __IO uint32_t CSR; -}; - -#define RCC_BASE (AHBPERIPH_BASE + 0x1000) -#define RCC ((struct RCC *)RCC_BASE) - -#define RCC_APB1ENR_USBEN 0x00800000 -#define RCC_APB1RSTR_USBRST 0x00800000 - -#define RCC_CR_HSION 0x00000001 -#define RCC_CR_HSIRDY 0x00000002 -#define RCC_CR_HSITRIM 0x000000F8 -#define RCC_CR_HSEON 0x00010000 -#define RCC_CR_HSERDY 0x00020000 -#define RCC_CR_PLLON 0x01000000 -#define RCC_CR_PLLRDY 0x02000000 - -#define RCC_CFGR_SWS 0x0000000C -#define RCC_CFGR_SWS_HSI 0x00000000 - -struct FLASH { - __IO uint32_t ACR; - __IO uint32_t KEYR; - __IO uint32_t OPTKEYR; - __IO uint32_t SR; - __IO uint32_t CR; - __IO uint32_t AR; - __IO uint32_t RESERVED; - __IO uint32_t OBR; - __IO uint32_t WRPR; -}; - -#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) -#define FLASH ((struct FLASH *) FLASH_R_BASE) - - -#define RCC_APB2ENR_IOPAEN 0x00000004 -#define RCC_APB2RSTR_IOPARST 0x00000004 -#define RCC_APB2ENR_IOPDEN 0x00000020 -#define RCC_APB2RSTR_IOPDRST 0x00000020 - -#define VAL_GPIOAODR 0xFFFFFFFF -#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */ -#define VAL_GPIOACRL 0x88888884 /* PA7...PA0 */ - -struct GPIO { - __IO uint32_t CRL; - __IO uint32_t CRH; - __IO uint32_t IDR; - __IO uint32_t ODR; - __IO uint32_t BSRR; - __IO uint32_t BRR; - __IO uint32_t LCKR; -}; - -#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) -#define GPIOA ((struct GPIO *) GPIOA_BASE) -#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) -#define GPIOB ((struct GPIO *) GPIOB_BASE) -#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) -#define GPIOC ((struct GPIO *) GPIOC_BASE) -#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) -#define GPIOD ((struct GPIO *) GPIOD_BASE) -#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) -#define GPIOE ((struct GPIO *) GPIOE_BASE) - -#ifdef GPIO_USB_BASE -#define GPIO_USB ((struct GPIO *) GPIO_USB_BASE) -#endif -#define GPIO_LED ((struct GPIO *) GPIO_LED_BASE) - -static void -usb_cable_config (int on) -{ -#ifdef GPIO_USB_BASE -# ifdef GPIO_USB_CLEAR_TO_ENABLE - if (on) - GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); - else - GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE); -# endif -# ifdef GPIO_USB_SET_TO_ENABLE - if (on) - GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE); - else - GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE); -# endif -#else - (void)on; -#endif -} - -void -set_led (int on) -{ -#ifdef GPIO_LED_CLEAR_TO_EMIT - if (on) - GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT); - else - GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT); -#endif -#ifdef GPIO_LED_SET_TO_EMIT - if (on) - GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT); - else - GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT); -#endif -} - - -#define USB_IRQ 20 -#define USB_IRQ_PRIORITY ((11) << 4) - -void usb_lld_sys_init (void) -{ - RCC->APB1ENR |= RCC_APB1ENR_USBEN; - NVICEnableVector (USB_IRQ, USB_IRQ_PRIORITY); - RCC->APB1RSTR = RCC_APB1RSTR_USBRST; - RCC->APB1RSTR = 0; - usb_cable_config (1); -} - -void usb_lld_sys_shutdown (void) -{ - RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; -} - - -#define FLASH_KEY1 0x45670123UL -#define FLASH_KEY2 0xCDEF89ABUL - -enum flash_status -{ - FLASH_BUSY = 1, - FLASH_ERROR_PG, - FLASH_ERROR_WRP, - FLASH_COMPLETE, - FLASH_TIMEOUT -}; - -#define FLASH_SR_BSY 0x01 -#define FLASH_SR_PGERR 0x04 -#define FLASH_SR_WRPRTERR 0x10 -#define FLASH_SR_EOP 0x20 - -#define FLASH_CR_PG 0x0001 -#define FLASH_CR_PER 0x0002 -#define FLASH_CR_MER 0x0004 -#define FLASH_CR_OPTPG 0x0010 -#define FLASH_CR_OPTER 0x0020 -#define FLASH_CR_STRT 0x0040 -#define FLASH_CR_LOCK 0x0080 -#define FLASH_CR_OPTWRE 0x0200 -#define FLASH_CR_ERRIE 0x0400 -#define FLASH_CR_EOPIE 0x1000 - -#define FLASH_OBR_RDPRT 0x00000002 - -#define OPTION_BYTES_ADDR 0x1ffff800 static void fatal (void) { @@ -249,9 +13,7 @@ static void none (void) static __attribute__ ((naked)) void entry (void) { - asm volatile ("cpsid i\n\t" /* Mask all interrupts */ - "ldr r0, =__ram_end__\n\t" - "msr MSP, r0\n\t" /* Main (interrupt handler) stack */ + asm volatile ("ldr r0, =__ram_end__\n\t" "ldr r1, =__main_stack_size__\n\t" "subs r0, r0, r1\n\t" "msr PSP, r0\n\t" /* Process (main routine) stack */ @@ -278,11 +40,6 @@ void entry (void) : /* no output */ : /* no input */ : "memory"); } -#define intr_disable() asm volatile ("cpsid i" : : "r" (0) : "memory") - -#define intr_enable() asm volatile ("msr BASEPRI, %0\n\t" \ - "cpsie i" : : "r" (0) : "memory") - typedef void (*handler)(void); extern uint8_t __ram_end__; extern void usb_interrupt_handler (void); @@ -308,144 +65,3 @@ handler vector_table[] __attribute__ ((section(".vectors"))) = { /* 90 */ usb_interrupt_handler, }; - -static int -flash_get_status (void) -{ - int status; - - if ((FLASH->SR & FLASH_SR_BSY) != 0) - status = FLASH_BUSY; - else if ((FLASH->SR & FLASH_SR_PGERR) != 0) - status = FLASH_ERROR_PG; - else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0 ) - status = FLASH_ERROR_WRP; - else - status = FLASH_COMPLETE; - - return status; -} - -static int -flash_wait_for_last_operation (uint32_t timeout) -{ - int status; - - do - if (--timeout == 0) - return FLASH_TIMEOUT; - else - status = flash_get_status (); - while (status == FLASH_BUSY); - - return status; -} - -#define FLASH_PROGRAM_TIMEOUT 0x00010000 -#define FLASH_ERASE_TIMEOUT 0x01000000 - -static int -flash_program_halfword (uint32_t addr, uint16_t data) -{ - int status; - - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - - intr_disable (); - if (status == FLASH_COMPLETE) - { - FLASH->CR |= FLASH_CR_PG; - - *(volatile uint16_t *)addr = data; - - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - FLASH->CR &= ~FLASH_CR_PG; - } - intr_enable (); - - return status; -} - -int -flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) -{ - int status; - - while (len) - { - uint16_t hw = *src++; - - hw |= (*src++ << 8); - status = flash_program_halfword (dst_addr, hw); - if (status != FLASH_COMPLETE) - return 0; /* error return */ - - dst_addr += 2; - len -= 2; - } - - return 1; -} - -int -flash_protect (void) -{ - int status; - uint32_t option_bytes_value; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - - intr_disable (); - if (status == FLASH_COMPLETE) - { - FLASH->OPTKEYR = FLASH_KEY1; - FLASH->OPTKEYR = FLASH_KEY2; - - FLASH->CR |= FLASH_CR_OPTER; - FLASH->CR |= FLASH_CR_STRT; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - FLASH->CR &= ~FLASH_CR_OPTER; - } - intr_enable (); - - if (status != FLASH_COMPLETE) - return 0; - - option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR; - return (option_bytes_value & 0xff) == 0xff ? 1 : 0; -} - -struct SCB -{ - __IO uint32_t CPUID; - __IO uint32_t ICSR; - __IO uint32_t VTOR; - __IO uint32_t AIRCR; - __IO uint32_t SCR; - __IO uint32_t CCR; - __IO uint8_t SHP[12]; - __IO uint32_t SHCSR; - __IO uint32_t CFSR; - __IO uint32_t HFSR; - __IO uint32_t DFSR; - __IO uint32_t MMFAR; - __IO uint32_t BFAR; - __IO uint32_t AFSR; - __IO uint32_t PFR[2]; - __IO uint32_t DFR; - __IO uint32_t ADR; - __IO uint32_t MMFR[4]; - __IO uint32_t ISAR[5]; -}; - -#define SCS_BASE (0xE000E000) -#define SCB_BASE (SCS_BASE + 0x0D00) -#define SCB ((struct SCB *) SCB_BASE) - -#define SYSRESETREQ 0x04 -void nvic_system_reset (void) -{ - SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ); - asm volatile ("dsb"); -} diff --git a/src/Makefile.in b/src/Makefile.in index 4130b46..d896426 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,15 +76,14 @@ CSRC = $(PORTSRC) \ $(HALSRC) \ $(PLATFORMSRC) \ $(BOARDSRC) \ - ../boards/common/hw_config.c \ $(BOARD_DIR)/board.c \ $(CHIBIOS)/os/various/evtimer.c \ $(CHIBIOS)/os/various/syscalls.c \ $(CRYPTSRC) \ - main.c usb_lld.c usb_lld_sys.c \ + main.c usb_lld.c \ usb_desc.c usb_ctrl.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ - random.c neug.c + random.c neug.c sys.c ifneq ($(ENABLE_DEBUG),) CSRC += debug.c diff --git a/src/configure b/src/configure index 28e45b8..25ddd0e 100755 --- a/src/configure +++ b/src/configure @@ -135,7 +135,6 @@ fi BOARD_DIR=../boards/$target if test -d $BOARD_DIR; then echo "Configured for target: $target" - TARGET_LOWER=`echo $target | tr '[:upper:]_' '[:lower:]-'` else echo "Unsupported target \`$target'" >&2 exit 1 @@ -219,8 +218,6 @@ else echo "CERT.3 Data Object is not supported" fi -ln -sf sys-$TARGET_LOWER.h ../regnual/sys.h - sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ diff --git a/src/flash.c b/src/flash.c index 4f4bc07..76b98a2 100644 --- a/src/flash.c +++ b/src/flash.c @@ -32,108 +32,9 @@ #include "config.h" #include "ch.h" #include "hal.h" +#include "sys.h" #include "gnuk.h" -#define FLASH_KEY1 0x45670123UL -#define FLASH_KEY2 0xCDEF89ABUL - -enum flash_status -{ - FLASH_BUSY = 1, - FLASH_ERROR_PG, - FLASH_ERROR_WRP, - FLASH_COMPLETE, - FLASH_TIMEOUT -}; - -void -flash_unlock (void) -{ - FLASH->KEYR = FLASH_KEY1; - FLASH->KEYR = FLASH_KEY2; -} - -static int -flash_get_status (void) -{ - int status; - - if ((FLASH->SR & FLASH_SR_BSY) != 0) - status = FLASH_BUSY; - else if ((FLASH->SR & FLASH_SR_PGERR) != 0) - status = FLASH_ERROR_PG; - else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0) - status = FLASH_ERROR_WRP; - else - status = FLASH_COMPLETE; - - return status; -} - -static int -flash_wait_for_last_operation (uint32_t timeout) -{ - int status; - - do - if (--timeout == 0) - return FLASH_TIMEOUT; - else - status = flash_get_status (); - while (status == FLASH_BUSY); - - return status; -} - -#define FLASH_PROGRAM_TIMEOUT 0x00010000 -#define FLASH_ERASE_TIMEOUT 0x01000000 - -static int -flash_program_halfword (uint32_t addr, uint16_t data) -{ - int status; - - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - - chSysLock (); - if (status == FLASH_COMPLETE) - { - FLASH->CR |= FLASH_CR_PG; - - *(volatile uint16_t *)addr = data; - - status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); - if (status != FLASH_TIMEOUT) - FLASH->CR &= ~FLASH_CR_PG; - } - chSysUnlock (); - - return status; -} - -static int -flash_erase_page (uint32_t addr) -{ - int status; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - - chSysLock (); - if (status == FLASH_COMPLETE) - { - FLASH->CR |= FLASH_CR_PER; - FLASH->AR = addr; - FLASH->CR |= FLASH_CR_STRT; - - status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); - if (status != FLASH_TIMEOUT) - FLASH->CR &= ~FLASH_CR_PER; - } - chSysUnlock () - - return status; -} - /* * Flash memory map * @@ -294,14 +195,14 @@ flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len) addr = (uint32_t)p; hw = nr | (len << 8); - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) flash_warning ("DO WRITE ERROR"); addr += 2; for (i = 0; i < len/2; i++) { hw = data[i*2] | (data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) flash_warning ("DO WRITE ERROR"); addr += 2; } @@ -309,7 +210,7 @@ flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len) if ((len & 1)) { hw = data[i*2] | 0xff00; - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) flash_warning ("DO WRITE ERROR"); } } @@ -359,19 +260,19 @@ flash_do_release (const uint8_t *do_data) /* Fill zero for content and pad */ for (i = 0; i < len/2; i ++) { - if (flash_program_halfword (addr, 0) != FLASH_COMPLETE) + if (flash_program_halfword (addr, 0) != 0) flash_warning ("fill-zero failure"); addr += 2; } if ((len & 1)) { - if (flash_program_halfword (addr, 0) != FLASH_COMPLETE) + if (flash_program_halfword (addr, 0) != 0) flash_warning ("fill-zero pad failure"); } /* Fill 0x0000 for "tag_number and length" word */ - if (flash_program_halfword (addr_tag, 0) != FLASH_COMPLETE) + if (flash_program_halfword (addr_tag, 0) != 0) flash_warning ("fill-zero tag_nr failure"); } @@ -399,7 +300,7 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data, for (i = 0; i < KEY_CONTENT_LEN/2; i ++) { hw = key_data[i*2] | (key_data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) return -1; addr += 2; } @@ -407,7 +308,7 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data, for (i = 0; i < KEY_CONTENT_LEN/2; i ++) { hw = modulus[i*2] | (modulus[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) return -1; addr += 2; } @@ -579,18 +480,6 @@ flash_cnt123_clear (const uint8_t **addr_p) } -static int -flash_check_blank (const uint8_t *p_start, int size) -{ - const uint8_t *p; - - for (p = p_start; p < p_start + size; p++) - if (*p != 0xff) - return 0; - - return 1; -} - #if defined(CERTDO_SUPPORT) #define FLASH_CH_CERTIFICATE_SIZE 2048 int @@ -652,7 +541,7 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, for (i = 0; i < len/2; i++) { hw = data[i*2] | (data[i*2+1]<<8); - if (flash_program_halfword (addr, hw) != FLASH_COMPLETE) + if (flash_program_halfword (addr, hw) != 0) flash_warning ("DO WRITE ERROR"); addr += 2; } diff --git a/src/gnuk.h b/src/gnuk.h index 5972d3d..36b333f 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -129,7 +129,6 @@ 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); @@ -322,8 +321,6 @@ extern uint32_t get_salt (void); extern uint32_t hardclock (void); -extern void set_led (int); - #define NUM_ALL_PRV_KEYS 3 /* SIG, DEC and AUT */ extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1]; @@ -351,7 +348,6 @@ extern void flash_bool_write_internal (const uint8_t *p, int nr); extern void flash_cnt123_write_internal (const uint8_t *p, int which, int v); extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len); -extern const unsigned char *unique_device_id (void); extern const uint8_t gnukStringSerial[]; #define LED_ONESHOT_SHORT ((eventmask_t)1) diff --git a/src/main.c b/src/main.c index 135a9d4..2df00c4 100644 --- a/src/main.c +++ b/src/main.c @@ -24,6 +24,7 @@ #include "config.h" #include "ch.h" #include "hal.h" +#include "sys.h" #include "gnuk.h" #include "usb_lld.h" #include "usb-cdc.h" @@ -370,55 +371,6 @@ led_blink (int spec) } -#define FMEAE_SIZE 128 - -#define FLASH_MASS_ERASE_TIMEOUT 0xF0000000 - -static void __attribute__((naked)) -flash_mass_erase_and_exec (void) -{ - void (**func )(void) = (void (**)(void))(&_regnual_start + 4); - - if ((FLASH->SR & FLASH_SR_BSY) == 0) - { - FLASH->CR |= FLASH_CR_MER; - FLASH->CR |= FLASH_CR_STRT; - - while ((FLASH->SR & FLASH_SR_BSY) != 0) - ; - - FLASH->CR &= ~FLASH_CR_MER; - - if ((FLASH->SR & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR)) == 0) - (**func) (); - } - - for (;;); -} - -static void __attribute__((noreturn)) -good_bye (void) -{ - register uint32_t dst __asm__ ("r0") = 0x20000000; /* SRAM top */ - register uint32_t src __asm__ ("r1") = (uint32_t)flash_mass_erase_and_exec & ~1; - register uint32_t len __asm__ ("r2") = FMEAE_SIZE; - register uint32_t entry __asm__ ("r3") = dst | 1; - register uint32_t use __asm__ ("r4"); - - /* copy function flash_mass_erase_and_exec to SRAM and jump to it */ - asm volatile("add r2, r2, r1\n" - "0: ldr r4, [r1], #4\n\t" - "cmp r2, r1\n\t" - "str r4, [r0], #4\n\t" - "bhi 0b\n\t" - "isb\n\t" - "bx r3" - : "=r" (dst), "=r" (src), "=r" (len), "=r" (use) - : "0" (dst), "1" (src), "2" (len), "r" (entry) - : "memory"); - for (;;); -} - /* * Entry point. * @@ -524,15 +476,12 @@ main (int argc, char *argv[]) } set_led (1); - /* USB Dissconnect (when supported) */ usb_lld_shutdown (); - USB_Cable_Config (0); - chThdSleep (MS2ST (1)); /* > 2.5us required */ port_disable (); /* set vector */ SCB->VTOR = (uint32_t)&_regnual_start; /* leave Gnuk */ - good_bye (); + flash_mass_erase_and_exec (); /* Never reached */ return 0; diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 90de71b..5849f6f 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -25,6 +25,7 @@ #include "config.h" #include "ch.h" +#include "sys.h" #include "gnuk.h" #include "openpgp.h" diff --git a/src/sys.c b/src/sys.c new file mode 100644 index 0000000..0c6e7b7 --- /dev/null +++ b/src/sys.c @@ -0,0 +1,276 @@ +#include "ch.h" +#include "hal.h" +#include "board.h" +#include "usb_lld.h" + +static const uint8_t * +unique_device_id (void) +{ + /* STM32F103 has 96-bit unique device identifier */ + const uint8_t *addr = (const uint8_t *)0x1ffff7e8; + + return addr; +} + +static void +usb_cable_config (int enable) +{ +#if defined(SET_USB_CONDITION) + if (SET_USB_CONDITION (enable)) + palSetPad (IOPORT_USB, GPIO_USB); + else + palClearPad (IOPORT_USB, GPIO_USB); +#else + (void)enable; +#endif +} + +static void +set_led (int on) +{ + if (SET_LED_CONDITION (on)) + palSetPad (IOPORT_LED, GPIO_LED); + else + palClearPad (IOPORT_LED, GPIO_LED); +} + + +#define FLASH_KEY1 0x45670123UL +#define FLASH_KEY2 0xCDEF89ABUL + +static void +flash_unlock (void) +{ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; +} + + +static int +flash_wait_for_last_operation (uint32_t timeout) +{ + int status; + + do + { + status = FLASH->SR; + if (--timeout == 0) + break; + } + while ((status & FLASH_SR_BSY) != 0); + + return status & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR); +} + +#define FLASH_PROGRAM_TIMEOUT 0x00010000 +#define FLASH_ERASE_TIMEOUT 0x01000000 + +static int +flash_program_halfword (uint32_t addr, uint16_t data) +{ + int status; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + + port_disable (); + if (status == 0) + { + FLASH->CR |= FLASH_CR_PG; + + *(volatile uint16_t *)addr = data; + + status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT); + FLASH->CR &= ~FLASH_CR_PG; + } + port_enable (); + + return status; +} + +static int +flash_erase_page (uint32_t addr) +{ + int status; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + + port_disable (); + if (status == 0) + { + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = addr; + FLASH->CR |= FLASH_CR_STRT; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + FLASH->CR &= ~FLASH_CR_PER; + } + port_enable (); + + return status; +} + +static int +flash_check_blank (const uint8_t *p_start, size_t size) +{ + const uint8_t *p; + + for (p = p_start; p < p_start + size; p++) + if (*p != 0xff) + return 0; + + return 1; +} + +static int +flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) +{ + int status; + + while (len) + { + uint16_t hw = *src++; + + hw |= (*src++ << 8); + status = flash_program_halfword (dst_addr, hw); + if (status != 0) + return 0; /* error return */ + + dst_addr += 2; + len -= 2; + } + + return 1; +} + +#define OPTION_BYTES_ADDR 0x1ffff800 + +static int +flash_protect (void) +{ + int status; + uint32_t option_bytes_value; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + + port_disable (); + if (status == 0) + { + FLASH->OPTKEYR = FLASH_KEY1; + FLASH->OPTKEYR = FLASH_KEY2; + + FLASH->CR |= FLASH_CR_OPTER; + FLASH->CR |= FLASH_CR_STRT; + + status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); + FLASH->CR &= ~FLASH_CR_OPTER; + } + port_enable (); + + if (status != 0) + return 0; + + option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR; + return (option_bytes_value & 0xff) == 0xff ? 1 : 0; +} + +#define FLASH_MASS_ERASE_TIMEOUT 0xF0000000 + +extern uint8_t __flash_start__, __flash_end__; +extern uint8_t _regnual_start; + +static void __attribute__((naked)) +flash_mass_erase_and_exec (void) +{ + void (**func )(void) = (void (**)(void))(&_regnual_start + 4); + uint32_t addr = (uint32_t)&__flash_start__; + uint32_t end = (uint32_t)&__flash_end__; + int r; + + while (addr < end) + { + r = flash_erase_page (addr); + if (r != 0) + break; + + addr += FLASH_PAGE_SIZE; + } + + if (addr >= end) + (**func) (); + + for (;;); +} + +static void +nvic_enable_vector (uint32_t n, uint32_t prio) +{ + unsigned int sh = (n & 3) << 3; + + NVIC_IPR (n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); + NVIC_ICPR (n >> 5) = 1 << (n & 0x1F); + NVIC_ISER (n >> 5) = 1 << (n & 0x1F); +} + +static void +usb_lld_sys_init (void) +{ + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + nvic_enable_vector (USB_LP_CAN1_RX0_IRQn, + CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); + /* + * Note that we also have other IRQ(s): + * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) + * USBWakeUp_IRQn (suspend/resume) + */ + RCC->APB1RSTR = RCC_APB1RSTR_USBRST; + RCC->APB1RSTR = 0; + + usb_cable_config (1); +} + +static void +usb_lld_sys_shutdown (void) +{ + RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; + usb_cable_config (0); +} + +#define SYSRESETREQ 0x04 +static void +nvic_system_reset (void) +{ + SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ); + asm volatile ("dsb"); +} + +static void __attribute__ ((naked)) +reset (void) +{ + asm volatile ("cpsid i\n\t" /* Mask all interrupts */ + "ldr r0, =_text\n\t" + "ldr r1, [r0], #4\n\t" + "msr MSP, r1\n\t" /* Main (exception handler) stack */ + "ldr r1, [r0]\n\t" /* Reset handler */ + "bx r1\n" + : /* no output */ : /* no input */ : "memory"); +} + +typedef void (*handler)(void); +extern uint8_t __ram_end__; + +handler vector[] __attribute__ ((section(".vectors"))) = { + (handler)&__ram_end__, + reset, + (handler)unique_device_id, + (handler)set_led, + flash_unlock, + (handler)flash_program_halfword, + (handler)flash_erase_page, + (handler)flash_check_blank, + (handler)flash_write, + (handler)flash_protect, + (handler)flash_mass_erase_and_exec, + usb_lld_sys_init, + usb_lld_sys_shutdown, + nvic_system_reset, +}; diff --git a/src/sys.h b/src/sys.h new file mode 100644 index 0000000..18b6b3f --- /dev/null +++ b/src/sys.h @@ -0,0 +1,92 @@ +typedef void (*handler)(void); +extern handler vector[12]; + +static inline const uint8_t * +unique_device_id (void) +{ + const uint8_t * (*func) (void) = (const uint8_t * (*)(void))vector[0]; + + return (*func) (); +} + +static inline void +set_led (int on) +{ + void (*func) (int) = (void (*)(int))vector[1]; + + return (*func) (on); +} + +static inline void +flash_unlock (void) +{ + (*vector[2]) (); +} + +static inline int +flash_program_halfword (uint32_t addr, uint16_t data) +{ + int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[3]; + + return (*func) (addr, data); +} + +static inline int +flash_erase_page (uint32_t addr) +{ + int (*func) (uint32_t) = (int (*)(uint32_t))vector[4]; + + return (*func) (addr); +} + +static inline int +flash_check_blank (const uint8_t *p_start, size_t size) +{ + int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[5]; + + return (*func) (p_start, size); +} + +static inline int +flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) +{ + int (*func) (uint32_t, const uint8_t *, size_t) + = (int (*)(uint32_t, const uint8_t *, size_t))vector[6]; + + return (*func) (dst_addr, src, len); +} + +static inline int +flash_protect (void) +{ + int (*func) (void) = (int (*)(void))vector[7]; + + return (*func) (); +} + +static inline void __attribute__((noreturn)) +flash_mass_erase_and_exec (void) +{ + void (*func) (void) = (void (*)(void))vector[8]; + + (*func) (); + for (;;); +} + +static inline void +usb_lld_sys_init (void) +{ + (*vector[9]) (); +} + +static inline void +usb_lld_sys_shutdown (void) +{ + (*vector[10]) (); +} + +static inline void +nvic_system_reset (void) +{ + (*vector[11]) (); +} diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index da116d0..c7ee886 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -423,3 +423,14 @@ const struct usb_device_method Device_Method = { gnuk_usb_event, gnuk_interface, }; + +CH_IRQ_HANDLER (Vector90) +{ + CH_IRQ_PROLOGUE(); + chSysLockFromIsr(); + + usb_interrupt_handler (); + + chSysUnlockFromIsr(); + CH_IRQ_EPILOGUE(); +} diff --git a/src/usb_lld.c b/src/usb_lld.c index 5fc9bac..1c31a04 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -4,7 +4,7 @@ #include "ch.h" #include "hal.h" #endif - +#include "sys.h" #include "usb_lld.h" #define USB_MAX_PACKET_SIZE 64 /* For FS device */ diff --git a/src/usb_lld.h b/src/usb_lld.h index cffbfbe..78a35e3 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -156,6 +156,3 @@ extern void usb_lld_prepare_shutdown (void); extern void usb_lld_shutdown (void); extern void usb_interrupt_handler (void); - -extern void usb_lld_sys_init (void); -extern void usb_lld_sys_shutdown (void); diff --git a/src/usb_lld_sys.c b/src/usb_lld_sys.c deleted file mode 100644 index be78d7e..0000000 --- a/src/usb_lld_sys.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "ch.h" -#include "hal.h" -#include "usb_lld.h" - -CH_IRQ_HANDLER (Vector90) { - CH_IRQ_PROLOGUE(); - chSysLockFromIsr(); - - usb_interrupt_handler (); - - chSysUnlockFromIsr(); - CH_IRQ_EPILOGUE(); -} - -void usb_lld_sys_init (void) -{ - RCC->APB1ENR |= RCC_APB1ENR_USBEN; - NVICEnableVector (USB_LP_CAN1_RX0_IRQn, - CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY)); - /* - * Note that we also have other IRQ(s): - * USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous) - * USBWakeUp_IRQn (suspend/resume) - */ - RCC->APB1RSTR = RCC_APB1RSTR_USBRST; - RCC->APB1RSTR = 0; - - USB_Cable_Config (1); -} - -void usb_lld_sys_shutdown (void) -{ - RCC->APB1ENR &= ~RCC_APB1ENR_USBEN; -} From 2113d5b7516b3ad10828dfd6fbfeb14a459cc28f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 25 May 2012 15:36:09 +0900 Subject: [PATCH 119/300] boards changes --- ChangeLog | 20 ++++++++++++++++++++ boards/FST_01/board.h | 7 +++++++ boards/FST_01_00/board.c | 19 ------------------- boards/FST_01_00/board.h | 7 +++++++ boards/OLIMEX_STM32_H103/board.c | 18 ------------------ boards/OLIMEX_STM32_H103/board.h | 7 +++++++ boards/STM32_PRIMER2/board.c | 18 ------------------ boards/STM32_PRIMER2/board.h | 7 +++++++ 8 files changed, 48 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index d42d18a..5389f24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,25 @@ 2012-05-25 Niibe Yutaka + * boards/OLIMEX_STM32_H103/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/OLIMEX_STM32_H103/board.c (USB_Cable_Config, set_led): + Remove. + + * boards/STM32_PRIMER2/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/STM32_PRIMER2/board.c (USB_Cable_Config, set_led): + Remove. + + * boards/FST_01_00/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/FST_01_00/board.c (USB_Cable_Config, set_led): Remove. + + * boards/FST_01/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/FST_01/board.c (USB_Cable_Config, set_led): Remove. + + * regnual/sys-stm8s-discovery.h, sys-stbee.h: Remove. + * boards/STM8S_DISCOVERY/board.h (SET_USB_CONDITION) (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. * boards/STM8S_DISCOVERY/board.c (USB_Cable_Config, set_led): diff --git a/boards/FST_01/board.h b/boards/FST_01/board.h index df3f3bf..a8332f3 100644 --- a/boards/FST_01/board.h +++ b/boards/FST_01/board.h @@ -30,6 +30,13 @@ /* * Setup for the FST-01 board. */ +#define SET_USB_CONDITION(en) en /* To connect USB, call palSetPad */ +#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ +#define GPIO_USB GPIOA_USB_ENABLE +#define IOPORT_USB GPIOA +#define GPIO_LED GPIOB_LED +#define IOPORT_LED GPIOB +#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/FST_01_00/board.c b/boards/FST_01_00/board.c index 2425ffe..a9e918d 100644 --- a/boards/FST_01_00/board.c +++ b/boards/FST_01_00/board.c @@ -15,22 +15,3 @@ 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); -} diff --git a/boards/FST_01_00/board.h b/boards/FST_01_00/board.h index a938218..59c4531 100644 --- a/boards/FST_01_00/board.h +++ b/boards/FST_01_00/board.h @@ -30,6 +30,13 @@ /* * Setup for the FST-01 board (experimental version 00). */ +#define SET_USB_CONDITION(en) en /* To connect USB, call palSetPad */ +#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ +#define GPIO_USB GPIOA_USB_ENABLE +#define IOPORT_USB GPIOA +#define GPIO_LED GPIOA_LED +#define IOPORT_LED GPIOA +#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/OLIMEX_STM32_H103/board.c b/boards/OLIMEX_STM32_H103/board.c index 0e22542..a9e918d 100644 --- a/boards/OLIMEX_STM32_H103/board.c +++ b/boards/OLIMEX_STM32_H103/board.c @@ -15,21 +15,3 @@ hwinit1 (void) { hwinit1_common (); } - -void -USB_Cable_Config (FunctionalState NewState) -{ - if (NewState != DISABLE) - palClearPad (IOPORT3, GPIOC_DISC); - else - palSetPad (IOPORT3, GPIOC_DISC); -} - -void -set_led (int value) -{ - if (value) - palClearPad (IOPORT3, GPIOC_LED); - else - palSetPad (IOPORT3, GPIOC_LED); -} diff --git a/boards/OLIMEX_STM32_H103/board.h b/boards/OLIMEX_STM32_H103/board.h index 9554c51..1e7df8d 100644 --- a/boards/OLIMEX_STM32_H103/board.h +++ b/boards/OLIMEX_STM32_H103/board.h @@ -30,6 +30,13 @@ /* * Setup for the Olimex STM32-H103 proto board. */ +#define SET_USB_CONDITION(en) (!en) /* To connect USB, call palClearPad */ +#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */ +#define GPIO_USB GPIOC_DISC +#define IOPORT_USB GPIOC +#define GPIO_LED GPIOC_LED +#define IOPORT_LED GPIOC +#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/STM32_PRIMER2/board.c b/boards/STM32_PRIMER2/board.c index b75d3eb..95baddb 100644 --- a/boards/STM32_PRIMER2/board.c +++ b/boards/STM32_PRIMER2/board.c @@ -21,21 +21,3 @@ hwinit1(void) palClearPad (IOPORT5, GPIOE_LED); palClearPad (IOPORT3, GPIOC_SHUTDOWN); } - -void -USB_Cable_Config (FunctionalState NewState) -{ - if (NewState != DISABLE) - palClearPad (IOPORT4, GPIOD_DISC); - else - palSetPad (IOPORT4, GPIOD_DISC); -} - -void -set_led (int value) -{ - if (value) - palClearPad (IOPORT5, GPIOE_LEDR); - else - palSetPad (IOPORT5, GPIOE_LEDR); -} diff --git a/boards/STM32_PRIMER2/board.h b/boards/STM32_PRIMER2/board.h index b295095..89f79c4 100644 --- a/boards/STM32_PRIMER2/board.h +++ b/boards/STM32_PRIMER2/board.h @@ -30,6 +30,13 @@ /* * Setup for the STM32 Primer2. */ +#define SET_USB_CONDITION(en) (!en) /* To connect USB, call palClearPad */ +#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */ +#define GPIO_USB GPIOD_DISC +#define IOPORT_USB GPIOD +#define GPIO_LED GPIOE_LEDR +#define IOPORT_LED GPIOE +#define FLASH_PAGE_SIZE 2048 /* * Board identifier. From 1e9b73de49db7c939307ab4093c0480c39ada39c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 25 May 2012 17:06:14 +0900 Subject: [PATCH 120/300] sys section at non-writable area --- ChangeLog | 2 ++ src/gnuk.ld.in | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5389f24..83a7228 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-25 Niibe Yutaka + * src/gnuk.ld.in (.sys): New section. + * boards/OLIMEX_STM32_H103/board.h (SET_USB_CONDITION) (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. * boards/OLIMEX_STM32_H103/board.c (USB_Cable_Config, set_led): diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 91e6c12..29a1b8c 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -33,10 +33,14 @@ __stacks_total_size__ = __main_stack_size__ + __process_stack_size__; MEMORY { - flash : org = @ORIGIN@, len = @FLASH_SIZE@k + flash0 : org = @ORIGIN@, len = 4k + flash : org = @ORIGIN@+0x1000, len = @FLASH_SIZE@k - 4k ram : org = 0x20000000, len = 20k } +__flash_start__ = ORIGIN(flash); +__flash_end__ = ORIGIN(flash) + LENGTH(flash); + __ram_start__ = ORIGIN(ram); __ram_size__ = LENGTH(ram); __ram_end__ = __ram_start__ + __ram_size__; @@ -45,6 +49,15 @@ SECTIONS { . = 0; + .sys : ALIGN(16) SUBALIGN(16) + { + KEEP(*(.vectors)) + sys.o(.text) + sys.o(.text.*) + sys.o(.rodata) + sys.o(.rodata.*) + } > flash0 + .text : ALIGN(16) SUBALIGN(16) { _text = .; From 7dd703c28bb4e300ecdf67430460129f839bcbb2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 26 May 2012 12:50:23 +0900 Subject: [PATCH 121/300] SCR->VCR --- ChangeLog | 4 ++++ src/sys.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 83a7228..02b5de1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-05-26 Niibe Yutaka + + * src/sys.c (reset): Set SCR->VCR here. + 2012-05-25 Niibe Yutaka * src/gnuk.ld.in (.sys): New section. diff --git a/src/sys.c b/src/sys.c index 0c6e7b7..4ad3fc3 100644 --- a/src/sys.c +++ b/src/sys.c @@ -247,6 +247,11 @@ static void __attribute__ ((naked)) reset (void) { asm volatile ("cpsid i\n\t" /* Mask all interrupts */ + "mov.w r0, #0xed00\n\t" /* SCR */ + "movt r0, #0xe000\n\t" + "mov.w r1, #0x1000\n\t" /* 08001000 */ + "movt r1, #0x0800\n\t" + "str r1, [r0, #8]\n\t" /* SCR->VCR = 0x08001000 */ "ldr r0, =_text\n\t" "ldr r1, [r0], #4\n\t" "msr MSP, r1\n\t" /* Main (exception handler) stack */ From cdc9d441a661435f72dc6ef1dc09e6e2d7c3c03b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 26 May 2012 13:29:59 +0900 Subject: [PATCH 122/300] fix sys.h --- src/sys.c | 9 ++++----- src/sys.h | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/sys.c b/src/sys.c index 4ad3fc3..d178f19 100644 --- a/src/sys.c +++ b/src/sys.c @@ -252,11 +252,10 @@ reset (void) "mov.w r1, #0x1000\n\t" /* 08001000 */ "movt r1, #0x0800\n\t" "str r1, [r0, #8]\n\t" /* SCR->VCR = 0x08001000 */ - "ldr r0, =_text\n\t" - "ldr r1, [r0], #4\n\t" - "msr MSP, r1\n\t" /* Main (exception handler) stack */ - "ldr r1, [r0]\n\t" /* Reset handler */ - "bx r1\n" + "ldr r0, [r1], #4\n\t" + "msr MSP, r0\n\t" /* Main (exception handler) stack */ + "ldr r0, [r1]\n\t" /* Reset handler */ + "bx r0\n" : /* no output */ : /* no input */ : "memory"); } diff --git a/src/sys.h b/src/sys.h index 18b6b3f..609aec0 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,10 +1,10 @@ typedef void (*handler)(void); -extern handler vector[12]; +extern handler vector[14]; static inline const uint8_t * unique_device_id (void) { - const uint8_t * (*func) (void) = (const uint8_t * (*)(void))vector[0]; + const uint8_t * (*func) (void) = (const uint8_t * (*)(void))vector[2]; return (*func) (); } @@ -12,7 +12,7 @@ unique_device_id (void) static inline void set_led (int on) { - void (*func) (int) = (void (*)(int))vector[1]; + void (*func) (int) = (void (*)(int))vector[3]; return (*func) (on); } @@ -20,13 +20,13 @@ set_led (int on) static inline void flash_unlock (void) { - (*vector[2]) (); + (*vector[4]) (); } static inline int flash_program_halfword (uint32_t addr, uint16_t data) { - int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[3]; + int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[5]; return (*func) (addr, data); } @@ -34,7 +34,7 @@ flash_program_halfword (uint32_t addr, uint16_t data) static inline int flash_erase_page (uint32_t addr) { - int (*func) (uint32_t) = (int (*)(uint32_t))vector[4]; + int (*func) (uint32_t) = (int (*)(uint32_t))vector[6]; return (*func) (addr); } @@ -42,7 +42,7 @@ flash_erase_page (uint32_t addr) static inline int flash_check_blank (const uint8_t *p_start, size_t size) { - int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[5]; + int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[7]; return (*func) (p_start, size); } @@ -51,7 +51,7 @@ static inline int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) { int (*func) (uint32_t, const uint8_t *, size_t) - = (int (*)(uint32_t, const uint8_t *, size_t))vector[6]; + = (int (*)(uint32_t, const uint8_t *, size_t))vector[8]; return (*func) (dst_addr, src, len); } @@ -59,7 +59,7 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) static inline int flash_protect (void) { - int (*func) (void) = (int (*)(void))vector[7]; + int (*func) (void) = (int (*)(void))vector[9]; return (*func) (); } @@ -67,7 +67,7 @@ flash_protect (void) static inline void __attribute__((noreturn)) flash_mass_erase_and_exec (void) { - void (*func) (void) = (void (*)(void))vector[8]; + void (*func) (void) = (void (*)(void))vector[10]; (*func) (); for (;;); @@ -76,17 +76,17 @@ flash_mass_erase_and_exec (void) static inline void usb_lld_sys_init (void) { - (*vector[9]) (); + (*vector[11]) (); } static inline void usb_lld_sys_shutdown (void) { - (*vector[10]) (); + (*vector[12]) (); } static inline void nvic_system_reset (void) { - (*vector[11]) (); + (*vector[13]) (); } From 8538ac19d0727b88fa8a6ba099f0b786beff2b41 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 26 May 2012 13:36:55 +0900 Subject: [PATCH 123/300] fix --- regnual/Makefile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/regnual/Makefile b/regnual/Makefile index 991fad4..c1a2fbc 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -32,18 +32,15 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) all: regnual.hex -regnual.o: regnual.c usb_lld.h +regnual.o: regnual.c regnual.hex: regnual.elf $(OBJCOPY) -Obinary regnual.elf regnual.bin $(OBJCOPY) -Oihex regnual.elf regnual.hex -usb_lld.c: ../src/usb_lld.c usb_lld.h +usb_lld.c: ../src/usb_lld.c cp -p ../src/usb_lld.c . -usb_lld.h: ../src/usb_lld.h - cp -p ../src/usb_lld.h . - regnual.elf: $(OBJS) $(LDSCRIPT) $(CC) $(LDFLAGS) -o regnual.elf $(OBJS) @@ -51,4 +48,4 @@ clean: -rm -f $(OBJS) regnual.elf regnual.hex regnual.bin distclean: clean - -rm -f usb_lld.c usb_lld.h sys.h + -rm -f usb_lld.c From ded02a6808e180a1ea679b7bf53206d1174a3fa8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 26 May 2012 16:01:55 +0900 Subject: [PATCH 124/300] fix --- regnual/regnual.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regnual/regnual.ld b/regnual/regnual.ld index 8b7313e..c470c1d 100644 --- a/regnual/regnual.ld +++ b/regnual/regnual.ld @@ -12,7 +12,7 @@ MEMORY } vector = 0x08000000; -_flash_start = 0x08000000; +_flash_start = 0x08001000; _flash_end = 0x08020000; __ram_start__ = ORIGIN(ram0); From 0bda48c9858a719734faef5632db340d04267eb1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 26 May 2012 20:15:07 +0900 Subject: [PATCH 125/300] disable systick --- src/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 2df00c4..6e56d87 100644 --- a/src/main.c +++ b/src/main.c @@ -477,10 +477,13 @@ main (int argc, char *argv[]) set_led (1); usb_lld_shutdown (); + /* Disable SysTick */ + SysTick->CTRL = 0; + /* Disable all interrupts */ port_disable (); - /* set vector */ + /* Set vector */ SCB->VTOR = (uint32_t)&_regnual_start; - /* leave Gnuk */ + /* Leave Gnuk */ flash_mass_erase_and_exec (); /* Never reached */ From 4e8af02ac0d1781913859e9478ddbcf86e4ffdb8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 11:03:26 +0900 Subject: [PATCH 126/300] fix regnual/sys.c --- regnual/sys.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/regnual/sys.c b/regnual/sys.c index fc8d0a9..702e4c8 100644 --- a/regnual/sys.c +++ b/regnual/sys.c @@ -15,28 +15,21 @@ void entry (void) { asm volatile ("ldr r0, =__ram_end__\n\t" "ldr r1, =__main_stack_size__\n\t" - "subs r0, r0, r1\n\t" - "msr PSP, r0\n\t" /* Process (main routine) stack */ - "movs r0, #0\n\t" + "sub r0, r0, r1\n\t" + "mov sp, r0\n\t" + "mov r0, #0\n\t" "ldr r1, =_bss_start\n\t" - "ldr r2, =_bss_start\n" + "ldr r2, =_bss_end\n" "0:\n\t" - "cmp r1, r2\n\t" - "bge 1f\n\t" - "str r0, [r1]\n\t" - "adds r1, r1, #4\n\t" - "b 0b\n" - "1:\n\t" - "movs r0, #2\n\t" /* Switch to PSP */ - "msr CONTROL, r0\n\t" - "isb\n\t" - "movs r0, #0\n\t" - "msr BASEPRI, r0\n\t" /* Enable interrupts */ - "cpsie i\n\t" + "str r0, [r1], #4\n\t" + "cmp r2, r1\n\t" + "bhi 0b\n\t" + "cpsie i\n\t" /* Enable interrupts */ + "mov r0, #0\n\t" "mov r1, r0\n\t" "bl main\n" - "2:\n\t" - "b 2b\n" + "1:\n\t" + "b 1b\n" : /* no output */ : /* no input */ : "memory"); } From cb1dc21b61c7fa1d8e0513a8406bf9ba9750a45f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 11:18:21 +0900 Subject: [PATCH 127/300] Update by reGNUal works now --- ChangeLog | 11 +++++++++++ tool/gnuk_upgrade.py | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02b5de1..cfd1cfc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-05-28 Niibe Yutaka + + * tool/gnuk_upgrade.py (main): First 4096-byte of Gnuk is system + block. Don't send it to reGNUal. + + * regnual/sys.c (entry): Fix clearing BSS. It is called with all + interrupts disabled. + + * regnual/regnual.ld (_flash_start): It's 0x08001000 now, because + there is system block now (was: 0x08000000). + 2012-05-26 Niibe Yutaka * src/sys.c (reset): Set SCR->VCR here. diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index e587c3a..2318ece 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -384,12 +384,13 @@ def main(passwd, data_regnual, data_upgrade): print "Run flash upgrade program..." icc.execute(mem_info[1] + len(data_regnual)) # + time.sleep(2) icc.reset_device() del icc icc = None # - print "Wait 1 seconds..." - time.sleep(1) + print "Wait 3 seconds..." + time.sleep(3) # Then, send upgrade program... dev = get_gnuk_device() print "Device: ", dev.filename @@ -421,4 +422,4 @@ if __name__ == '__main__': data_upgrade = f.read() f.close() print "%s: %d" % (filename_upgrade, len(data_upgrade)) - main(passwd, data_regnual, data_upgrade) + main(passwd, data_regnual, data_upgrade[4096:]) From f072de436bac2f4b671fdf4388ba185b96898daa Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 11:46:49 +0900 Subject: [PATCH 128/300] better usage of .sys section --- ChangeLog | 5 ++++- polarssl-0.14.0/library/aes.c | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index cfd1cfc..9b4460f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-05-28 Niibe Yutaka + * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify the + section ".sys", so that we will have more room for flash ROM. + * tool/gnuk_upgrade.py (main): First 4096-byte of Gnuk is system block. Don't send it to reGNUal. @@ -22,7 +25,7 @@ * boards/OLIMEX_STM32_H103/board.c (USB_Cable_Config, set_led): Remove. - * boards/STM32_PRIMER2/board.h (SET_USB_CONDITION) + * boards/STM32_PRIMER2/board.h (SET_USB_CONDITION) (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. * boards/STM32_PRIMER2/board.c (USB_Cable_Config, set_led): Remove. diff --git a/polarssl-0.14.0/library/aes.c b/polarssl-0.14.0/library/aes.c index 45f74a6..4f87e88 100644 --- a/polarssl-0.14.0/library/aes.c +++ b/polarssl-0.14.0/library/aes.c @@ -172,15 +172,15 @@ static const unsigned char FSb[256] = V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) #define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long FT0[256] = { FT }; +static const unsigned long FT0[256] __attribute__((section(".sys"))) = { FT }; #undef V #define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long FT1[256] = { FT }; +static const unsigned long FT1[256] __attribute__((section(".sys"))) = { FT }; #undef V #define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long FT2[256] = { FT }; +static const unsigned long FT2[256] __attribute__((section(".sys"))) = { FT }; #undef V #define V(a,b,c,d) 0x##d##a##b##c From 54f52838ef3a97c86424ded74000e4c794473909 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 11:48:35 +0900 Subject: [PATCH 129/300] cleanup hwinit0 --- ChangeLog | 3 +++ boards/CQ_STARM/board.c | 6 ------ boards/FST_01/board.c | 6 ------ boards/FST_01_00/board.c | 6 ------ boards/OLIMEX_STM32_H103/board.c | 6 ------ boards/STBEE/board.c | 6 ------ boards/STBEE_MINI/board.c | 6 ------ boards/STM32_PRIMER2/board.c | 6 ------ boards/STM8S_DISCOVERY/board.c | 6 ------ boards/common/hwinit.c | 6 ++---- 10 files changed, 5 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b4460f..38b8f00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-05-28 Niibe Yutaka + * boards/common/hwinit.c (hwinit0): Define here. + * boards/*/board.c (hwinit0): Removed. + * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify the section ".sys", so that we will have more room for flash ROM. diff --git a/boards/CQ_STARM/board.c b/boards/CQ_STARM/board.c index cd2a779..693a8f2 100644 --- a/boards/CQ_STARM/board.c +++ b/boards/CQ_STARM/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/FST_01/board.c b/boards/FST_01/board.c index cdd64bd..6e3a844 100644 --- a/boards/FST_01/board.c +++ b/boards/FST_01/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/FST_01_00/board.c b/boards/FST_01_00/board.c index a9e918d..c079a0c 100644 --- a/boards/FST_01_00/board.c +++ b/boards/FST_01_00/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/OLIMEX_STM32_H103/board.c b/boards/OLIMEX_STM32_H103/board.c index a9e918d..c079a0c 100644 --- a/boards/OLIMEX_STM32_H103/board.c +++ b/boards/OLIMEX_STM32_H103/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/STBEE/board.c b/boards/STBEE/board.c index 391165d..75af80b 100644 --- a/boards/STBEE/board.c +++ b/boards/STBEE/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/STBEE_MINI/board.c b/boards/STBEE_MINI/board.c index c65d3d9..5abd5e0 100644 --- a/boards/STBEE_MINI/board.c +++ b/boards/STBEE_MINI/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/STM32_PRIMER2/board.c b/boards/STM32_PRIMER2/board.c index 95baddb..83a288b 100644 --- a/boards/STM32_PRIMER2/board.c +++ b/boards/STM32_PRIMER2/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0(void) -{ - hwinit0_common (); -} - void hwinit1(void) { diff --git a/boards/STM8S_DISCOVERY/board.c b/boards/STM8S_DISCOVERY/board.c index 554b598..1fdf2a9 100644 --- a/boards/STM8S_DISCOVERY/board.c +++ b/boards/STM8S_DISCOVERY/board.c @@ -4,12 +4,6 @@ #include "../common/hwinit.c" -void -hwinit0 (void) -{ - hwinit0_common (); -} - void hwinit1 (void) { diff --git a/boards/common/hwinit.c b/boards/common/hwinit.c index 648b6aa..a12f1b9 100644 --- a/boards/common/hwinit.c +++ b/boards/common/hwinit.c @@ -29,10 +29,8 @@ * This initialization is performed just after reset before BSS and DATA * segments initialization. */ -/* - * Common code for hwinit0 - */ -static void hwinit0_common (void) +void +hwinit0 (void) { #ifdef DFU_SUPPORT SCB->VTOR = 0x08003000; From 3588fbd97ab745c17ed25a17a8cbfe1a89d66ec3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 12:04:27 +0900 Subject: [PATCH 130/300] AES data .sys works now --- ChangeLog | 2 ++ src/gnuk.ld.in | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 38b8f00..1231e9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-28 Niibe Yutaka + * src/gnuk.ld.in (.sys): Add alignment settings. + * boards/common/hwinit.c (hwinit0): Define here. * boards/*/board.c (hwinit0): Removed. diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 29a1b8c..26506cc 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -56,6 +56,8 @@ SECTIONS sys.o(.text.*) sys.o(.rodata) sys.o(.rodata.*) + . = ALIGN(1024); + *(.sys) } > flash0 .text : ALIGN(16) SUBALIGN(16) From ba8609be414fa2727dcdb27a52fe570db4852f70 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 12:53:58 +0900 Subject: [PATCH 131/300] DFU Support --- ChangeLog | 9 +++++---- boards/common/hwinit.c | 4 ---- src/sys.c | 12 ++++++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1231e9f..224b8bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,13 @@ 2012-05-28 Niibe Yutaka - * src/gnuk.ld.in (.sys): Add alignment settings. - - * boards/common/hwinit.c (hwinit0): Define here. - * boards/*/board.c (hwinit0): Removed. + * boards/*/board.c (hwinit0): Removed... + * boards/common/hwinit.c (hwinit0): ... and define here. + (hwinit0) [DFU_SUPPORT]: Don't set SCB->VTOR here. + * src/sys.c (reset) [DFU_SUPPORT]: Set SCB->VTOR here. * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify the section ".sys", so that we will have more room for flash ROM. + * src/gnuk.ld.in (.sys): Add alignment settings. * tool/gnuk_upgrade.py (main): First 4096-byte of Gnuk is system block. Don't send it to reGNUal. diff --git a/boards/common/hwinit.c b/boards/common/hwinit.c index a12f1b9..e84788e 100644 --- a/boards/common/hwinit.c +++ b/boards/common/hwinit.c @@ -32,10 +32,6 @@ void hwinit0 (void) { -#ifdef DFU_SUPPORT - SCB->VTOR = 0x08003000; -#endif - stm32_clock_init(); } diff --git a/src/sys.c b/src/sys.c index d178f19..c8065f2 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,3 +1,4 @@ +#include "config.h" #include "ch.h" #include "hal.h" #include "board.h" @@ -173,8 +174,6 @@ flash_protect (void) return (option_bytes_value & 0xff) == 0xff ? 1 : 0; } -#define FLASH_MASS_ERASE_TIMEOUT 0xF0000000 - extern uint8_t __flash_start__, __flash_end__; extern uint8_t _regnual_start; @@ -249,9 +248,14 @@ reset (void) asm volatile ("cpsid i\n\t" /* Mask all interrupts */ "mov.w r0, #0xed00\n\t" /* SCR */ "movt r0, #0xe000\n\t" - "mov.w r1, #0x1000\n\t" /* 08001000 */ +#ifdef DFU_SUPPORT + "mov.w r1, #0x4000\n\t" /* 0x08004000 */ "movt r1, #0x0800\n\t" - "str r1, [r0, #8]\n\t" /* SCR->VCR = 0x08001000 */ +#else + "mov.w r1, #0x1000\n\t" /* 0x08001000 */ + "movt r1, #0x0800\n\t" +#endif + "str r1, [r0, #8]\n\t" /* Set SCR->VCR */ "ldr r0, [r1], #4\n\t" "msr MSP, r0\n\t" /* Main (exception handler) stack */ "ldr r0, [r1]\n\t" /* Reset handler */ From 1576b8303eadca04c3c9f68291c6dd0bae3178dc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 May 2012 13:00:58 +0900 Subject: [PATCH 132/300] flash write range check --- ChangeLog | 1 + src/sys.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 224b8bd..9c039c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ * boards/common/hwinit.c (hwinit0): ... and define here. (hwinit0) [DFU_SUPPORT]: Don't set SCB->VTOR here. * src/sys.c (reset) [DFU_SUPPORT]: Set SCB->VTOR here. + (flash_write): Range check. * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify the section ".sys", so that we will have more room for flash ROM. diff --git a/src/sys.c b/src/sys.c index c8065f2..92246f2 100644 --- a/src/sys.c +++ b/src/sys.c @@ -4,6 +4,10 @@ #include "board.h" #include "usb_lld.h" +extern uint8_t __flash_start__, __flash_end__; +extern uint8_t _regnual_start; + + static const uint8_t * unique_device_id (void) { @@ -126,6 +130,11 @@ static int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) { int status; + uint32_t flash_start = (uint32_t)&__flash_start__; + uint32_t flash_end = (uint32_t)&__flash_end__; + + if (dst_addr < flash_start || dst_addr + len > flash_end) + return 0; while (len) { @@ -174,8 +183,6 @@ flash_protect (void) return (option_bytes_value & 0xff) == 0xff ? 1 : 0; } -extern uint8_t __flash_start__, __flash_end__; -extern uint8_t _regnual_start; static void __attribute__((naked)) flash_mass_erase_and_exec (void) From 8d8e67f1ad0d939870320d60b56aab2cb1d9eb66 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 08:37:36 +0900 Subject: [PATCH 133/300] support DFU board --- ChangeLog | 32 +++++++++++++++++++++++++------- boards/CQ_STARM/board.c | 20 -------------------- boards/CQ_STARM/board.h | 5 +++++ boards/FST_01/board.c | 18 ------------------ boards/STBEE/board.c | 18 ------------------ boards/STBEE/board.h | 7 +++++++ boards/STBEE_MINI/board.c | 18 ------------------ boards/STBEE_MINI/board.h | 7 +++++++ 8 files changed, 44 insertions(+), 81 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9c039c0..99cd90d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2012-05-29 Niibe Yutaka + + * boards/STBEE_MINI/board.h (SET_USB_CONDITION, GPIO_USB) + (IOPORT_USB, SET_LED_CONDITION, GPIO_LED, IOPORT_LED) + (FLASH_PAGE_SIZE): New. + * boards/STBEE_MINI/board.c (USB_Cable_Config, set_led): Remove. + + * boards/STBEE/board.h (SET_USB_CONDITION, GPIO_USB, IOPORT_USB) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/STBEE/board.c (USB_Cable_Config, set_led): Remove. + + * boards/CQ_STARM/board.h (SET_USB_CONDITION) + (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/CQ_STARM/board.c (USB_Cable_Config, set_led): Remove. + 2012-05-28 Niibe Yutaka * boards/*/board.c (hwinit0): Removed... @@ -27,21 +42,24 @@ * src/gnuk.ld.in (.sys): New section. - * boards/OLIMEX_STM32_H103/board.h (SET_USB_CONDITION) - (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/OLIMEX_STM32_H103/board.h (SET_USB_CONDITION, GPIO_USB) + (IOPORT_USB, SET_LED_CONDITION, GPIO_LED, IOPORT_LED) + (FLASH_PAGE_SIZE): New. * boards/OLIMEX_STM32_H103/board.c (USB_Cable_Config, set_led): Remove. - * boards/STM32_PRIMER2/board.h (SET_USB_CONDITION) - (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/STM32_PRIMER2/board.h (SET_USB_CONDITION, GPIO_USB) + (IOPORT_USB, SET_LED_CONDITION, GPIO_LED, IOPORT_LED) + (FLASH_PAGE_SIZE): New. * boards/STM32_PRIMER2/board.c (USB_Cable_Config, set_led): Remove. - * boards/FST_01_00/board.h (SET_USB_CONDITION) - (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. + * boards/FST_01_00/board.h (SET_USB_CONDITION, GPIO_USB) + (IOPORT_USB, SET_LED_CONDITION, GPIO_LED, IOPORT_LED) + (FLASH_PAGE_SIZE): New. * boards/FST_01_00/board.c (USB_Cable_Config, set_led): Remove. - * boards/FST_01/board.h (SET_USB_CONDITION) + * boards/FST_01/board.h (SET_USB_CONDITION, GPIO_USB, IOPORT_USB) (SET_LED_CONDITION, GPIO_LED, IOPORT_LED, FLASH_PAGE_SIZE): New. * boards/FST_01/board.c (USB_Cable_Config, set_led): Remove. diff --git a/boards/CQ_STARM/board.c b/boards/CQ_STARM/board.c index 693a8f2..c079a0c 100644 --- a/boards/CQ_STARM/board.c +++ b/boards/CQ_STARM/board.c @@ -9,23 +9,3 @@ hwinit1 (void) { hwinit1_common (); } - -void -USB_Cable_Config (FunctionalState NewState) -{ - /* CQ STARM has no functionality to stop USB. */ - /* - * It seems that users can add the functionality with USB_DC (PD9) - * though - */ - (void)NewState; -} - -void -set_led (int value) -{ - if (value) - palSetPad (IOPORT3, GPIOC_LED); - else - palClearPad (IOPORT3, GPIOC_LED); -} diff --git a/boards/CQ_STARM/board.h b/boards/CQ_STARM/board.h index 9d001d2..c9d1443 100644 --- a/boards/CQ_STARM/board.h +++ b/boards/CQ_STARM/board.h @@ -30,6 +30,11 @@ /* * Setup for the CQ STARM board. */ +#undef SET_USB_CONDITION /* No functionality to disconnect USB */ +#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ +#define GPIO_LED GPIOC_LED +#define IOPORT_LED GPIOC +#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/FST_01/board.c b/boards/FST_01/board.c index 6e3a844..7db9dee 100644 --- a/boards/FST_01/board.c +++ b/boards/FST_01/board.c @@ -42,24 +42,6 @@ hwinit1 (void) #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_CIR_SUPPORT) void cir_ext_disable (void) diff --git a/boards/STBEE/board.c b/boards/STBEE/board.c index 75af80b..efbbb79 100644 --- a/boards/STBEE/board.c +++ b/boards/STBEE/board.c @@ -64,24 +64,6 @@ hwinit1 (void) #endif } -void -USB_Cable_Config (FunctionalState NewState) -{ - if (NewState != DISABLE) - palClearPad (IOPORT4, GPIOD_USB_ENABLE); - else - palSetPad (IOPORT4, GPIOD_USB_ENABLE); -} - -void -set_led (int value) -{ - if (value) - palClearPad (IOPORT4, GPIOD_LED1); - else - palSetPad (IOPORT4, GPIOD_LED1); -} - #if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) diff --git a/boards/STBEE/board.h b/boards/STBEE/board.h index b31f5e5..1e75f11 100644 --- a/boards/STBEE/board.h +++ b/boards/STBEE/board.h @@ -31,6 +31,13 @@ /* * Setup for the STBee board. */ +#define SET_USB_CONDITION(en) (!en) /* To connect USB, call palClearPad */ +#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */ +#define GPIO_USB GPIOD_USB_ENABLE +#define IOPORT_USB GPIOD +#define GPIO_LED GPIOD_LED1 +#define IOPORT_LED GPIOD +#define FLASH_PAGE_SIZE 2048 /* * Board identifier. diff --git a/boards/STBEE_MINI/board.c b/boards/STBEE_MINI/board.c index 5abd5e0..2d3e0a1 100644 --- a/boards/STBEE_MINI/board.c +++ b/boards/STBEE_MINI/board.c @@ -77,24 +77,6 @@ hwinit1 (void) palSetPad (IOPORT1, GPIOA_LED2); } -void -USB_Cable_Config (FunctionalState NewState) -{ - if (NewState != DISABLE) - palSetPad (IOPORT1, GPIOA_USB_ENABLE); - else - palClearPad (IOPORT1, GPIOA_USB_ENABLE); -} - -void -set_led (int value) -{ - if (value) - palClearPad (IOPORT1, GPIOA_LED1); - else - palSetPad (IOPORT1, GPIOA_LED1); -} - #if defined(PINPAD_CIR_SUPPORT) void cir_ext_disable (void) diff --git a/boards/STBEE_MINI/board.h b/boards/STBEE_MINI/board.h index cdd7527..da19e1d 100644 --- a/boards/STBEE_MINI/board.h +++ b/boards/STBEE_MINI/board.h @@ -31,6 +31,13 @@ /* * Setup for the STBee Mini board. */ +#define SET_USB_CONDITION(en) (en) /* To connect USB, call palSetPad */ +#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */ +#define GPIO_USB GPIOA_USB_ENABLE +#define IOPORT_USB GPIOA +#define GPIO_LED GPIOA_LED1 +#define IOPORT_LED GPIOA +#define FLASH_PAGE_SIZE 1024 /* * Board identifier. From e2ab8c91832725c6b0d3a2c57c1cfd2acf11ade8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 09:04:41 +0900 Subject: [PATCH 134/300] improve DFU_SUPPORT --- ChangeLog | 6 ++++++ polarssl-0.14.0/library/aes.c | 6 +++--- src/gnuk.ld.in | 4 +++- src/sys.c | 23 ++++++++++------------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99cd90d..4afe3f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2012-05-29 Niibe Yutaka + * src/sys.c (reset): Don't depend if DFU_SUPPORT or not. + + * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify sections + in detail, so that addresses won't be affected by compiler. + * src/gnuk.ld.in (.sys): Define sections in detail. + * boards/STBEE_MINI/board.h (SET_USB_CONDITION, GPIO_USB) (IOPORT_USB, SET_LED_CONDITION, GPIO_LED, IOPORT_LED) (FLASH_PAGE_SIZE): New. diff --git a/polarssl-0.14.0/library/aes.c b/polarssl-0.14.0/library/aes.c index 4f87e88..ea4904c 100644 --- a/polarssl-0.14.0/library/aes.c +++ b/polarssl-0.14.0/library/aes.c @@ -172,15 +172,15 @@ static const unsigned char FSb[256] = V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) #define V(a,b,c,d) 0x##a##b##c##d -static const unsigned long FT0[256] __attribute__((section(".sys"))) = { FT }; +static const unsigned long FT0[256] __attribute__((section(".sys.0"))) = { FT }; #undef V #define V(a,b,c,d) 0x##b##c##d##a -static const unsigned long FT1[256] __attribute__((section(".sys"))) = { FT }; +static const unsigned long FT1[256] __attribute__((section(".sys.1"))) = { FT }; #undef V #define V(a,b,c,d) 0x##c##d##a##b -static const unsigned long FT2[256] __attribute__((section(".sys"))) = { FT }; +static const unsigned long FT2[256] __attribute__((section(".sys.2"))) = { FT }; #undef V #define V(a,b,c,d) 0x##d##a##b##c diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 26506cc..b9ff5f9 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -57,7 +57,9 @@ SECTIONS sys.o(.rodata) sys.o(.rodata.*) . = ALIGN(1024); - *(.sys) + *(.sys.0) + *(.sys.1) + *(.sys.2) } > flash0 .text : ALIGN(16) SUBALIGN(16) diff --git a/src/sys.c b/src/sys.c index 92246f2..2e6e98e 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,4 +1,3 @@ -#include "config.h" #include "ch.h" #include "hal.h" #include "board.h" @@ -252,20 +251,18 @@ nvic_system_reset (void) static void __attribute__ ((naked)) reset (void) { - asm volatile ("cpsid i\n\t" /* Mask all interrupts */ - "mov.w r0, #0xed00\n\t" /* SCR */ + asm volatile ("cpsid i\n\t" /* Mask all interrupts. */ + "mov.w r0, #0xed00\n\t" /* r0 = SCR */ "movt r0, #0xe000\n\t" -#ifdef DFU_SUPPORT - "mov.w r1, #0x4000\n\t" /* 0x08004000 */ - "movt r1, #0x0800\n\t" -#else - "mov.w r1, #0x1000\n\t" /* 0x08001000 */ - "movt r1, #0x0800\n\t" -#endif - "str r1, [r0, #8]\n\t" /* Set SCR->VCR */ + "mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */ + "mov r2, #0x1000\n\t" + "add r1, r1, r2\n\t" + "sub r2, r2, #1\n\t" + "bic r1, r1, r2\n\t" + "str r1, [r0, #8]\n\t" /* Set SCR->VCR */ "ldr r0, [r1], #4\n\t" - "msr MSP, r0\n\t" /* Main (exception handler) stack */ - "ldr r0, [r1]\n\t" /* Reset handler */ + "msr MSP, r0\n\t" /* Main (exception handler) stack. */ + "ldr r0, [r1]\n\t" /* Reset handler. */ "bx r0\n" : /* no output */ : /* no input */ : "memory"); } From 08563d5a65f695a6b7b9a67bcf720a843f82817e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 09:41:25 +0900 Subject: [PATCH 135/300] improve sys interface for flash_erase_all_and_exec --- ChangeLog | 5 +++++ src/gnuk.ld.in | 3 ++- src/main.c | 2 +- src/sys.c | 31 ++++++++++++++++++++++++++----- src/sys.h | 6 +++--- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4afe3f3..730b58e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ 2012-05-29 Niibe Yutaka * src/sys.c (reset): Don't depend if DFU_SUPPORT or not. + (flash_erase_all_and_exec): Rename and change the argument. + * src/gnuk.ld.in (__flash_start__): Real flash ROM address, + regardless of DFU_SUPPORT. + * src/main.c (main): Call flash_erase_all_and_exec with SRAM + address. * polarssl-0.14.0/library/aes.c (FT0, FT1, FT2): Specify sections in detail, so that addresses won't be affected by compiler. diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index b9ff5f9..3d4f675 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -38,7 +38,8 @@ MEMORY ram : org = 0x20000000, len = 20k } -__flash_start__ = ORIGIN(flash); +/* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */ +__flash_start__ = 0x08001000; __flash_end__ = ORIGIN(flash) + LENGTH(flash); __ram_start__ = ORIGIN(ram); diff --git a/src/main.c b/src/main.c index 6e56d87..aa1344b 100644 --- a/src/main.c +++ b/src/main.c @@ -484,7 +484,7 @@ main (int argc, char *argv[]) /* Set vector */ SCB->VTOR = (uint32_t)&_regnual_start; /* Leave Gnuk */ - flash_mass_erase_and_exec (); + flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); /* Never reached */ return 0; diff --git a/src/sys.c b/src/sys.c index 2e6e98e..f69d0c2 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,10 +1,32 @@ +/* + * sys.c - system services at the first flash ROM blocks + * + * Copyright (C) 2012 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + #include "ch.h" #include "hal.h" #include "board.h" #include "usb_lld.h" extern uint8_t __flash_start__, __flash_end__; -extern uint8_t _regnual_start; static const uint8_t * @@ -184,9 +206,8 @@ flash_protect (void) static void __attribute__((naked)) -flash_mass_erase_and_exec (void) +flash_erase_all_and_exec (void (*entry)(void)) { - void (**func )(void) = (void (**)(void))(&_regnual_start + 4); uint32_t addr = (uint32_t)&__flash_start__; uint32_t end = (uint32_t)&__flash_end__; int r; @@ -201,7 +222,7 @@ flash_mass_erase_and_exec (void) } if (addr >= end) - (**func) (); + (*entry) (); for (;;); } @@ -281,7 +302,7 @@ handler vector[] __attribute__ ((section(".vectors"))) = { (handler)flash_check_blank, (handler)flash_write, (handler)flash_protect, - (handler)flash_mass_erase_and_exec, + (handler)flash_erase_all_and_exec, usb_lld_sys_init, usb_lld_sys_shutdown, nvic_system_reset, diff --git a/src/sys.h b/src/sys.h index 609aec0..4a3d89b 100644 --- a/src/sys.h +++ b/src/sys.h @@ -65,11 +65,11 @@ flash_protect (void) } static inline void __attribute__((noreturn)) -flash_mass_erase_and_exec (void) +flash_erase_all_and_exec (void (*entry)(void)) { - void (*func) (void) = (void (*)(void))vector[10]; + void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[10]; - (*func) (); + (*func) (entry); for (;;); } From 01de6a74c503669d819e6f4e3b1b2b228178d040 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 10:07:23 +0900 Subject: [PATCH 136/300] DFU support for reGNUal upgrade --- ChangeLog | 7 +++++++ boards/CQ_STARM/board.h | 1 - boards/FST_01/board.h | 1 - boards/FST_01_00/board.h | 1 - boards/OLIMEX_STM32_H103/board.h | 1 - boards/STBEE/board.h | 1 - boards/STBEE_MINI/board.h | 1 - boards/STM32_PRIMER2/board.h | 1 - boards/STM8S_DISCOVERY/board.h | 1 - src/config.h.in | 1 + src/configure | 1 + src/flash.c | 5 ----- src/gnuk.ld.in | 1 + src/main.c | 25 ++++++++++++++++++++++++- src/sys.c | 1 + 15 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 730b58e..7181adc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-05-29 Niibe Yutaka + * src/main.c (main) [DFU_SUPPORT]: Kill DFU and install .sys. + + * src/config.h.in (FLASH_PAGE_SIZE): New. + * src/configure: Support FLASH_PAGE_SIZE for config.h + * boards/*/board.h (FLASH_PAGE_SIZE): Remove. + * src/flash.c (FLASH_PAGE_SIZE): Remove. + * src/sys.c (reset): Don't depend if DFU_SUPPORT or not. (flash_erase_all_and_exec): Rename and change the argument. * src/gnuk.ld.in (__flash_start__): Real flash ROM address, diff --git a/boards/CQ_STARM/board.h b/boards/CQ_STARM/board.h index c9d1443..5268912 100644 --- a/boards/CQ_STARM/board.h +++ b/boards/CQ_STARM/board.h @@ -34,7 +34,6 @@ #define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ #define GPIO_LED GPIOC_LED #define IOPORT_LED GPIOC -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/FST_01/board.h b/boards/FST_01/board.h index a8332f3..cf911a3 100644 --- a/boards/FST_01/board.h +++ b/boards/FST_01/board.h @@ -36,7 +36,6 @@ #define IOPORT_USB GPIOA #define GPIO_LED GPIOB_LED #define IOPORT_LED GPIOB -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/FST_01_00/board.h b/boards/FST_01_00/board.h index 59c4531..5428bcf 100644 --- a/boards/FST_01_00/board.h +++ b/boards/FST_01_00/board.h @@ -36,7 +36,6 @@ #define IOPORT_USB GPIOA #define GPIO_LED GPIOA_LED #define IOPORT_LED GPIOA -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/OLIMEX_STM32_H103/board.h b/boards/OLIMEX_STM32_H103/board.h index 1e7df8d..a6c2d84 100644 --- a/boards/OLIMEX_STM32_H103/board.h +++ b/boards/OLIMEX_STM32_H103/board.h @@ -36,7 +36,6 @@ #define IOPORT_USB GPIOC #define GPIO_LED GPIOC_LED #define IOPORT_LED GPIOC -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/STBEE/board.h b/boards/STBEE/board.h index 1e75f11..75a3f41 100644 --- a/boards/STBEE/board.h +++ b/boards/STBEE/board.h @@ -37,7 +37,6 @@ #define IOPORT_USB GPIOD #define GPIO_LED GPIOD_LED1 #define IOPORT_LED GPIOD -#define FLASH_PAGE_SIZE 2048 /* * Board identifier. diff --git a/boards/STBEE_MINI/board.h b/boards/STBEE_MINI/board.h index da19e1d..da3adae 100644 --- a/boards/STBEE_MINI/board.h +++ b/boards/STBEE_MINI/board.h @@ -37,7 +37,6 @@ #define IOPORT_USB GPIOA #define GPIO_LED GPIOA_LED1 #define IOPORT_LED GPIOA -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/boards/STM32_PRIMER2/board.h b/boards/STM32_PRIMER2/board.h index 89f79c4..0991242 100644 --- a/boards/STM32_PRIMER2/board.h +++ b/boards/STM32_PRIMER2/board.h @@ -36,7 +36,6 @@ #define IOPORT_USB GPIOD #define GPIO_LED GPIOE_LEDR #define IOPORT_LED GPIOE -#define FLASH_PAGE_SIZE 2048 /* * Board identifier. diff --git a/boards/STM8S_DISCOVERY/board.h b/boards/STM8S_DISCOVERY/board.h index a9cb272..f352bc1 100644 --- a/boards/STM8S_DISCOVERY/board.h +++ b/boards/STM8S_DISCOVERY/board.h @@ -36,7 +36,6 @@ #define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */ #define GPIO_LED GPIOA_LED #define IOPORT_LED GPIOA -#define FLASH_PAGE_SIZE 1024 /* * Board identifier. diff --git a/src/config.h.in b/src/config.h.in index 37fbb30..cb61d1b 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,3 +6,4 @@ @PINPAD_DEFINE@ @PINPAD_MORE_DEFINE@ @CERTDO_DEFINE@ +#define FLASH_PAGE_SIZE @FLASH_PAGE_SIZE@ diff --git a/src/configure b/src/configure index 25ddd0e..d170a00 100755 --- a/src/configure +++ b/src/configure @@ -238,5 +238,6 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \ -e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \ -e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \ -e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \ + -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \ < config.h.in > config.h exit 0 diff --git a/src/flash.c b/src/flash.c index 76b98a2..78ebdb1 100644 --- a/src/flash.c +++ b/src/flash.c @@ -56,11 +56,6 @@ * 1.5-KiB Key store (512-byte (p, q and N) key-store * 3) */ #define FLASH_DATA_POOL_HEADER_SIZE 2 -#if defined(STM32F10X_HD) -#define FLASH_PAGE_SIZE 2048 -#else -#define FLASH_PAGE_SIZE 1024 -#endif #define FLASH_DATA_POOL_SIZE (FLASH_PAGE_SIZE*2) #define FLASH_KEYSTORE_SIZE (512*3) diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index 3d4f675..bd57af7 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -52,6 +52,7 @@ SECTIONS .sys : ALIGN(16) SUBALIGN(16) { + _sys = .; KEEP(*(.vectors)) sys.o(.text) sys.o(.text.*) diff --git a/src/main.c b/src/main.c index aa1344b..d935fb0 100644 --- a/src/main.c +++ b/src/main.c @@ -483,8 +483,31 @@ main (int argc, char *argv[]) port_disable (); /* Set vector */ SCB->VTOR = (uint32_t)&_regnual_start; - /* Leave Gnuk */ +#ifdef DFU_SUPPORT +#define FLASH_SYS_START_ADDR 0x08000000 +#define FLASH_SYS_END_ADDR (0x08000000+0x1000) + { + extern uint8_t _sys; + uint32_t addr; + handler *new_vector = (handler *)FLASH_SYS_START_ADDR; + void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10]; + + /* Kill DFU */ + for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR; + addr += FLASH_PAGE_SIZE) + flash_erase_page (addr); + + /* copy system service routines */ + flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000); + + /* Leave Gnuk to exec reGNUal */ + (*func) (*((void (**)(void))(&_regnual_start+4))); + for (;;); + } +#else + /* Leave Gnuk to exec reGNUal */ flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); +#endif /* Never reached */ return 0; diff --git a/src/sys.c b/src/sys.c index f69d0c2..2c71b99 100644 --- a/src/sys.c +++ b/src/sys.c @@ -21,6 +21,7 @@ * */ +#include "config.h" #include "ch.h" #include "hal.h" #include "board.h" From 7ae467f8747628f52e60800fd7176a1059cd4873 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 10:58:00 +0900 Subject: [PATCH 137/300] fix board name --- boards/STM8S_DISCOVERY/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/STM8S_DISCOVERY/board.h b/boards/STM8S_DISCOVERY/board.h index f352bc1..27b7fce 100644 --- a/boards/STM8S_DISCOVERY/board.h +++ b/boards/STM8S_DISCOVERY/board.h @@ -41,7 +41,7 @@ * Board identifier. */ #define BOARD_ST_DISCOVERY -#define BOARD_NAME "ST-Link" +#define BOARD_NAME "STM8S Discovery" #define CPU_WITH_NO_GPIOE 1 /* From cc95fff0744c85fe44c2d604b525333ef91e6e0d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 11:19:15 +0900 Subject: [PATCH 138/300] support revision detail and configure options in USB strings --- ChangeLog | 5 ++++ src/configure | 77 +++++++++++++++++++++++++++++++------------------- src/usb_conf.h | 2 +- src/usb_desc.c | 7 +++-- 4 files changed, 58 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7181adc..167eb6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2012-05-29 Niibe Yutaka + * src/usb_conf.h (NUM_STRING_DESC): Incremented to 6 (was: 4). + * src/configure: Generate strings for revision detail and config + options. + * src/usb_desc.c (gnuk_revision_detail, gnuk_config_options): New. + * src/main.c (main) [DFU_SUPPORT]: Kill DFU and install .sys. * src/config.h.in (FLASH_PAGE_SIZE): New. diff --git a/src/configure b/src/configure index d170a00..908b602 100755 --- a/src/configure +++ b/src/configure @@ -103,35 +103,6 @@ if test "$vidpid" = "none"; then exit 1 fi -if !(IFS=" " - while read VIDPID VERSION PRODUCT VENDOR; do - if test "$vidpid" = "$VIDPID"; then - (echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\n 0x\4, 0x\3, /* idProduct */%p" - echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p" - ) > usb-vid-pid-ver.c.inc - (echo 'static const uint8_t gnukStringVendor[] = {' - echo " ${#VENDOR}*2+2, /* bLength */" - echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" - echo " /* Manufacturer: \"$VENDOR\" */" - echo $VENDOR | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" - echo '};' - echo - echo 'static const uint8_t gnukStringProduct[] = {' - echo " ${#PRODUCT}*2+2, /* bLength */" - echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" - echo " /* Product name: \"$PRODUCT\" */" - echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" - echo '};' - ) >usb-string-vendor-product.c.inc - exit 0 - fi - done; exit 1) < ../GNUK_USB_DEVICE_ID -then - echo "Please specify valid Vendor ID and Product ID." - echo "Check ../GNUK_USB_DEVICE_ID." - exit 1 -fi - BOARD_DIR=../boards/$target if test -d $BOARD_DIR; then echo "Configured for target: $target" @@ -186,6 +157,7 @@ if test "$with_dfu" = "yes"; then FLASH_SIZE=`expr $FLASH_SIZE - 12` DFU_DEFINE="#define DFU_SUPPORT 1" else + with_dfu=no echo "Configured for bare system (no-DFU)" ORIGIN=0x08000000 DFU_DEFINE="#undef DFU_SUPPORT" @@ -198,6 +170,7 @@ if test "$pinpad" = "no"; then PINPAD_MORE_DEFINE="" echo "PIN pad option disabled" elif test "$pinpad" = "yes"; then + pinpad=dnd PINPAD_MAKE_OPTION="ENABLE_PINPAD=dnd" PINPAD_DEFINE="#define PINPAD_SUPPORT 1" PINPAD_MORE_DEFINE="#define PINPAD_DND_SUPPORT 1" @@ -218,6 +191,52 @@ else echo "CERT.3 Data Object is not supported" fi +REVISION=`git describe --dirty="-modified"` +CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo" + +if !(IFS=" " + while read VIDPID VERSION PRODUCT VENDOR; do + if test "$vidpid" = "$VIDPID"; then + (echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\n 0x\4, 0x\3, /* idProduct */%p" + echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p" + ) > usb-vid-pid-ver.c.inc + (echo 'static const uint8_t gnukStringVendor[] = {' + echo " ${#VENDOR}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* Manufacturer: \"$VENDOR\" */" + echo $VENDOR | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + echo + echo 'static const uint8_t gnukStringProduct[] = {' + echo " ${#PRODUCT}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* Product name: \"$PRODUCT\" */" + echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + echo + echo 'static const uint8_t gnuk_revision_detail[] = {' + echo " ${#REVISION}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* revision detail: \"$REVISION\" */" + echo $REVISION | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + echo + echo 'static const uint8_t gnuk_config_options[] = {' + echo " ${#CONFIG}*2+2, /* bLength */" + echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" + echo " /* configure options: \"$CONFIG\" */" + echo $CONFIG | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" + echo '};' + ) >usb-strings.c.inc + exit 0 + fi + done; exit 1) < ../GNUK_USB_DEVICE_ID +then + echo "Please specify valid Vendor ID and Product ID." + echo "Check ../GNUK_USB_DEVICE_ID." + exit 1 +fi + sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ diff --git a/src/usb_conf.h b/src/usb_conf.h index 3838451..ac49ec1 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -3,7 +3,7 @@ #ifndef __USB_CONF_H #define __USB_CONF_H -#define NUM_STRING_DESC 4 +#define NUM_STRING_DESC 6 /* Control pipe */ /* EP0 */ diff --git a/src/usb_desc.c b/src/usb_desc.c index 0ebc03d..13a45c7 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -253,12 +253,12 @@ static const uint8_t gnukStringLangID[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; -#include "usb-string-vendor-product.c.inc" +#include "usb-strings.c.inc" const uint8_t gnukStringSerial[] = { 18*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - /* FSIJ-0.18 */ + /* FSIJ-0.19 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, '0', 0, '.', 0, '1', 0, '8', 0, /* Version number of Gnuk */ '-', 0, @@ -266,7 +266,6 @@ const uint8_t gnukStringSerial[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; - const struct Descriptor Device_Descriptor = { gnukDeviceDescriptor, sizeof (gnukDeviceDescriptor) @@ -282,4 +281,6 @@ const struct Descriptor String_Descriptors[NUM_STRING_DESC] = { {gnukStringVendor, sizeof (gnukStringVendor)}, {gnukStringProduct, sizeof (gnukStringProduct)}, {gnukStringSerial, sizeof (gnukStringSerial)}, + {gnuk_revision_detail, sizeof (gnuk_revision_detail)}, + {gnuk_config_options, sizeof (gnuk_config_options)}, }; From f8bb88227a1b2df3166db6d8ed687851ea251be7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 11:53:50 +0900 Subject: [PATCH 139/300] fix API of RSA --- ChangeLog | 3 +++ polarssl-0.14.0/include/polarssl/rsa.h | 2 +- polarssl-0.14.0/library/rsa.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 167eb6c..6f6ecee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-05-29 Niibe Yutaka + * polarssl-0.14.0/include/polarssl/rsa.h (rsa_pkcs1_verify) + * polarssl-0.14.0/library/rsa.c (rsa_pkcs1_verify): Fix API. + * src/usb_conf.h (NUM_STRING_DESC): Incremented to 6 (was: 4). * src/configure: Generate strings for revision detail and config options. diff --git a/polarssl-0.14.0/include/polarssl/rsa.h b/polarssl-0.14.0/include/polarssl/rsa.h index 5fae794..0e1f46a 100644 --- a/polarssl-0.14.0/include/polarssl/rsa.h +++ b/polarssl-0.14.0/include/polarssl/rsa.h @@ -330,7 +330,7 @@ int rsa_pkcs1_verify( rsa_context *ctx, int hash_id, int hashlen, const unsigned char *hash, - unsigned char *sig ); + const unsigned char *sig ); /** * \brief Free the components of an RSA key diff --git a/polarssl-0.14.0/library/rsa.c b/polarssl-0.14.0/library/rsa.c index e42aab4..0411701 100644 --- a/polarssl-0.14.0/library/rsa.c +++ b/polarssl-0.14.0/library/rsa.c @@ -538,7 +538,7 @@ int rsa_pkcs1_verify( rsa_context *ctx, int hash_id, int hashlen, const unsigned char *hash, - unsigned char *sig ) + const unsigned char *sig ) { int ret, len, siglen; unsigned char *p, c; From 6ba65c8d8ba0594ea9204823d417bc59c32caf04 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 29 May 2012 12:14:10 +0900 Subject: [PATCH 140/300] rsa_verify function --- ChangeLog | 2 ++ src/call-rsa.c | 30 ++++++++++++++++++++++++++++++ src/gnuk.h | 2 ++ 3 files changed, 34 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6f6ecee..e01de34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-29 Niibe Yutaka + * src/call-rsa.c (rsa_verify): New function. + * polarssl-0.14.0/include/polarssl/rsa.h (rsa_pkcs1_verify) * polarssl-0.14.0/library/rsa.c (rsa_pkcs1_verify): Fix API. diff --git a/src/call-rsa.c b/src/call-rsa.c index f9a90ef..424aaf9 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -183,3 +183,33 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, return 0; } } + +int +rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen, + const uint8_t *signature) +{ + int r; + + rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); + rsa_ctx.len = KEY_CONTENT_LEN; + mpi_read_string (&rsa_ctx.E, 16, "10001"); + mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN); + + DEBUG_INFO ("RSA verify..."); + + r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_RAW, hashlen, + hash, signature); + + rsa_free (&rsa_ctx); + if (r < 0) + { + DEBUG_INFO ("fail:"); + DEBUG_SHORT (r); + return r; + } + else + { + DEBUG_INFO ("verified.\r\n"); + return 0; + } +} diff --git a/src/gnuk.h b/src/gnuk.h index 36b333f..45bb99c 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -225,6 +225,8 @@ extern int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *); extern const uint8_t *modulus_calc (const uint8_t *, int); extern void modulus_free (const uint8_t *); extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *); +extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen, + const uint8_t *signature); extern const uint8_t *gpg_do_read_simple (uint8_t); extern void gpg_do_write_simple (uint8_t, const uint8_t *, int); From 093c98bb0f5f023aefaab20d7846a2c7af585502 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 30 May 2012 18:50:22 +0900 Subject: [PATCH 141/300] external authenticate implemented --- ChangeLog | 9 ++++++++- README | 3 +++ src/gnuk.h | 1 + src/openpgp.c | 42 +++++++++++++++++++++++++++++++----------- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index e01de34..9b05e18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-05-30 Niibe Yutaka + + * src/openpgp.c (CHALLENGE_LEN): New. + (cmd_external_authenticate): Authentication by response with + public key. + (cmd_get_challenge): 16-byte is enough for challenge. + 2012-05-29 Niibe Yutaka * src/call-rsa.c (rsa_verify): New function. @@ -227,7 +234,7 @@ (std_set_address, std_get_descriptor, std_get_configuration) (std_set_configuration, std_get_interface, std_set_interface): Check direction. - (handle_setup0): Add length for setup_with_data + (handle_setup0): Add length for setup_with_data. 2012-05-16 Niibe Yutaka diff --git a/README b/README index d49abac..b0627b7 100644 --- a/README +++ b/README @@ -228,6 +228,9 @@ Gnuk is distributed with external source code. The file include/polarssl/bn_mul.h is heavily modified for ARM Cortex-M3. + The file library/aes.c is modified so that some constants can + go to .sys section. + USB vendor ID and product ID (USB device ID) ============================================ diff --git a/src/gnuk.h b/src/gnuk.h index 45bb99c..7e55465 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -121,6 +121,7 @@ extern void gpg_do_get_data (uint16_t tag, int with_tag); extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len); extern void gpg_do_public_key (uint8_t kk_byte); +extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno); enum kind_of_key { diff --git a/src/openpgp.c b/src/openpgp.c index d062f11..076f245 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -50,6 +50,9 @@ #define INS_PUT_DATA 0xda #define INS_PUT_DATA_ODD 0xdb /* For key import */ +#define CHALLENGE_LEN 16 +static const uint8_t *challenge; /* Random bytes */ + static const uint8_t select_file_TOP_result[] __attribute__ ((aligned (1))) = { 0x00, 0x00, /* unused */ @@ -826,9 +829,31 @@ cmd_write_binary (void) static void cmd_external_authenticate (void) { + const uint8_t *pubkey; + const uint8_t *signature = apdu.cmd_apdu_data; + int len = apdu.cmd_apdu_data_len; + uint8_t keyno = P2 (apdu); + int r; + DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) + if (keyno > 2) + { + GPG_CONDITION_NOT_SATISFIED (); + return; + } + + pubkey = gpg_get_firmware_update_key (keyno); + if (pubkey == NULL || len != 256) + { + GPG_CONDITION_NOT_SATISFIED (); + return; + } + + r = rsa_verify (pubkey, challenge, CHALLENGE_LEN, signature); + random_bytes_free (challenge); + challenge = NULL; + if (r < 0) { GPG_SECURITY_FAILURE (); return; @@ -842,19 +867,14 @@ cmd_external_authenticate (void) static void cmd_get_challenge (void) { - const uint8_t *rand; - int i; - DEBUG_INFO (" - GET CHALLENGE\r\n"); - for (i = 0; i < 6; i++) - { - rand = random_bytes_get (); - memcpy (res_APDU + i * 16, rand, 16); - random_bytes_free (rand); - } + if (challenge) + random_bytes_free (challenge); - res_APDU_size = 96; + challenge = random_bytes_get (); + memcpy (res_APDU, challenge, CHALLENGE_LEN); + res_APDU_size = CHALLENGE_LEN; GPG_SUCCESS (); DEBUG_INFO ("GET CHALLENGE done.\r\n"); } From ab51c5421da96b55052a384ad9b7f9fd6ae41f9c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 08:58:08 +0900 Subject: [PATCH 142/300] revice system service, version string --- ChangeLog | 10 ++++++++++ src/gnuk.ld.in | 2 ++ src/sys.c | 17 +++++++---------- src/sys.h | 29 ++++++++++++++++------------- src/usb_conf.h | 2 +- src/usb_desc.c | 2 ++ 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b05e18..c4115d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2012-05-31 Niibe Yutaka + + Version string of system service is now USB string. + * src/sys.h (unique_device_id): Define here, not as system + service. + * src/sys.c (sys_version): Version string for system service. + * src/usb_desc.c (String_Descriptors): Add sys_version. + * src/usb_conf.h (NUM_STRING_DESC): 7 (was: 6). + * src/gnuk.ld.in (.sys.version): New section. + 2012-05-30 Niibe Yutaka * src/openpgp.c (CHALLENGE_LEN): New. diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index bd57af7..e87bf1e 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -54,6 +54,8 @@ SECTIONS { _sys = .; KEEP(*(.vectors)) + . = ALIGN(16); + *(.sys.version) sys.o(.text) sys.o(.text.*) sys.o(.rodata) diff --git a/src/sys.c b/src/sys.c index 2c71b99..0c1cc00 100644 --- a/src/sys.c +++ b/src/sys.c @@ -30,15 +30,6 @@ extern uint8_t __flash_start__, __flash_end__; -static const uint8_t * -unique_device_id (void) -{ - /* STM32F103 has 96-bit unique device identifier */ - const uint8_t *addr = (const uint8_t *)0x1ffff7e8; - - return addr; -} - static void usb_cable_config (int enable) { @@ -295,7 +286,6 @@ extern uint8_t __ram_end__; handler vector[] __attribute__ ((section(".vectors"))) = { (handler)&__ram_end__, reset, - (handler)unique_device_id, (handler)set_led, flash_unlock, (handler)flash_program_halfword, @@ -308,3 +298,10 @@ handler vector[] __attribute__ ((section(".vectors"))) = { usb_lld_sys_shutdown, nvic_system_reset, }; + +const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = { + 3*2+2, /* bLength */ + 0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE*/ + /* sys version: "1.0" */ + '1', 0, '.', 0, '0', 0, +}; diff --git a/src/sys.h b/src/sys.h index 4a3d89b..3884c95 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,18 +1,21 @@ +extern const uint8_t sys_version[8]; + typedef void (*handler)(void); extern handler vector[14]; static inline const uint8_t * unique_device_id (void) { - const uint8_t * (*func) (void) = (const uint8_t * (*)(void))vector[2]; + /* STM32F103 has 96-bit unique device identifier */ + const uint8_t *addr = (const uint8_t *)0x1ffff7e8; - return (*func) (); + return addr; } static inline void set_led (int on) { - void (*func) (int) = (void (*)(int))vector[3]; + void (*func) (int) = (void (*)(int))vector[2]; return (*func) (on); } @@ -20,13 +23,13 @@ set_led (int on) static inline void flash_unlock (void) { - (*vector[4]) (); + (*vector[3]) (); } static inline int flash_program_halfword (uint32_t addr, uint16_t data) { - int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[5]; + int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[4]; return (*func) (addr, data); } @@ -34,7 +37,7 @@ flash_program_halfword (uint32_t addr, uint16_t data) static inline int flash_erase_page (uint32_t addr) { - int (*func) (uint32_t) = (int (*)(uint32_t))vector[6]; + int (*func) (uint32_t) = (int (*)(uint32_t))vector[5]; return (*func) (addr); } @@ -42,7 +45,7 @@ flash_erase_page (uint32_t addr) static inline int flash_check_blank (const uint8_t *p_start, size_t size) { - int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[7]; + int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[6]; return (*func) (p_start, size); } @@ -51,7 +54,7 @@ static inline int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) { int (*func) (uint32_t, const uint8_t *, size_t) - = (int (*)(uint32_t, const uint8_t *, size_t))vector[8]; + = (int (*)(uint32_t, const uint8_t *, size_t))vector[7]; return (*func) (dst_addr, src, len); } @@ -59,7 +62,7 @@ flash_write (uint32_t dst_addr, const uint8_t *src, size_t len) static inline int flash_protect (void) { - int (*func) (void) = (int (*)(void))vector[9]; + int (*func) (void) = (int (*)(void))vector[8]; return (*func) (); } @@ -67,7 +70,7 @@ flash_protect (void) static inline void __attribute__((noreturn)) flash_erase_all_and_exec (void (*entry)(void)) { - void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[10]; + void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[9]; (*func) (entry); for (;;); @@ -76,17 +79,17 @@ flash_erase_all_and_exec (void (*entry)(void)) static inline void usb_lld_sys_init (void) { - (*vector[11]) (); + (*vector[10]) (); } static inline void usb_lld_sys_shutdown (void) { - (*vector[12]) (); + (*vector[11]) (); } static inline void nvic_system_reset (void) { - (*vector[13]) (); + (*vector[12]) (); } diff --git a/src/usb_conf.h b/src/usb_conf.h index ac49ec1..75241e3 100644 --- a/src/usb_conf.h +++ b/src/usb_conf.h @@ -3,7 +3,7 @@ #ifndef __USB_CONF_H #define __USB_CONF_H -#define NUM_STRING_DESC 6 +#define NUM_STRING_DESC 7 /* Control pipe */ /* EP0 */ diff --git a/src/usb_desc.c b/src/usb_desc.c index 13a45c7..681d41f 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -4,6 +4,7 @@ #include "config.h" #include "ch.h" +#include "sys.h" #include "usb_lld.h" #include "usb_conf.h" #include "usb-cdc.h" @@ -283,4 +284,5 @@ const struct Descriptor String_Descriptors[NUM_STRING_DESC] = { {gnukStringSerial, sizeof (gnukStringSerial)}, {gnuk_revision_detail, sizeof (gnuk_revision_detail)}, {gnuk_config_options, sizeof (gnuk_config_options)}, + {sys_version, sizeof (sys_version)}, }; From c5762e7891e76c2e9d18426d8cbfefb68f0c003f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 11:58:14 +0900 Subject: [PATCH 143/300] firmware update keys handling --- ChangeLog | 13 +++ src/flash.c | 5 + src/gnuk.h | 6 +- src/gnuk.ld.in | 3 + src/openpgp.c | 241 ++++++++++++++++++++++++++++++------------------- src/openpgp.h | 2 +- 6 files changed, 175 insertions(+), 95 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4115d7..5f9d7fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,18 @@ 2012-05-31 Niibe Yutaka + Support "firmware update" keys. + * src/flash.c (flash_write_binary): Support update keys. + * src/gnuk.h (FILEID_UPDATE_KEY_0, FILEID_UPDATE_KEY_1) + (FILEID_UPDATE_KEY_2,FILEID_UPDATE_KEY_3): New. + * src/gnuk.ld.in (_updatekey_store): New. + * src/openpgp.c (FILE_EF_UPDATE_KEY_0, FILE_EF_UPDATE_KEY_1) + (FILE_EF_UPDATE_KEY_2, FILE_EF_UPDATE_KEY_3): New. + (gpg_get_firmware_update_key): New. + (cmd_read_binary): Support update keys and certificate. + (modify_binary): New. + (cmd_update_binary, cmd_write_binary): Use modify_binary. + (cmd_external_authenticate): Support up to four keys. + Version string of system service is now USB string. * src/sys.h (unique_device_id): Define here, not as system service. diff --git a/src/flash.c b/src/flash.c index 78ebdb1..b12fcfb 100644 --- a/src/flash.c +++ b/src/flash.c @@ -511,6 +511,11 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, maxsize = 6; p = &openpgpcard_aid[8]; } + else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3) + { + maxsize = KEY_CONTENT_LEN; + p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0); + } #if defined(CERTDO_SUPPORT) else if (file_id == FILEID_CH_CERTIFICATE) { diff --git a/src/gnuk.h b/src/gnuk.h index 7e55465..ebf9aae 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -141,7 +141,11 @@ extern void flash_increment_counter (uint8_t counter_tag_nr); extern void flash_reset_counter (uint8_t counter_tag_nr); #define FILEID_SERIAL_NO 0 -#define FILEID_CH_CERTIFICATE 1 +#define FILEID_UPDATE_KEY_0 1 +#define FILEID_UPDATE_KEY_1 2 +#define FILEID_UPDATE_KEY_2 3 +#define FILEID_UPDATE_KEY_3 4 +#define FILEID_CH_CERTIFICATE 5 extern int flash_erase_binary (uint8_t file_id); extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset); diff --git a/src/gnuk.ld.in b/src/gnuk.ld.in index e87bf1e..1ab53e7 100644 --- a/src/gnuk.ld.in +++ b/src/gnuk.ld.in @@ -159,6 +159,9 @@ SECTIONS _keystore_pool = .; . += 512*3; . = ALIGN(@FLASH_PAGE_SIZE@); + _updatekey_store = .; + . += 1024; + . = ALIGN(@FLASH_PAGE_SIZE@); } > flash =0xffffffff } diff --git a/src/openpgp.c b/src/openpgp.c index 076f245..3d5785e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -81,8 +81,12 @@ set_res_sw (uint8_t sw1, uint8_t sw2) #define FILE_DF_OPENPGP 1 #define FILE_MF 2 #define FILE_EF_DIR 3 -#define FILE_EF_SERIAL 4 -#define FILE_EF_CH_CERTIFICATE 5 +#define FILE_EF_SERIAL_NO 4 +#define FILE_EF_UPDATE_KEY_0 5 +#define FILE_EF_UPDATE_KEY_1 6 +#define FILE_EF_UPDATE_KEY_2 7 +#define FILE_EF_UPDATE_KEY_3 8 +#define FILE_EF_CH_CERTIFICATE 9 static uint8_t file_selection; @@ -484,23 +488,95 @@ cmd_pgp_gakp (void) } } +const uint8_t * +gpg_get_firmware_update_key (uint8_t keyno) +{ + extern uint8_t _updatekey_store; + const uint8_t *p; + + p = &_updatekey_store + keyno * KEY_CONTENT_LEN; + return p; +} + +#ifdef CERTDO_SUPPORT +#define FILEID_CH_CERTIFICATE_IS_VALID 1 +#else +#define FILEID_CH_CERTIFICATE_IS_VALID 0 +#endif + static void cmd_read_binary (void) { + int is_short_EF = (P1 (apdu) & 0x80) != 0; + uint8_t file_id; + const uint8_t *p; + uint16_t offset; + DEBUG_INFO (" - Read binary\r\n"); - if (file_selection == FILE_EF_SERIAL) + if (is_short_EF) + file_id = (P1 (apdu) & 0x1f); + else + file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO; + + if ((!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE) + || file_id > FILEID_CH_CERTIFICATE) { - if (P2 (apdu) >= 6) - GPG_BAD_P0_P1 (); - else - { - gpg_do_get_data (0x004f, 1); /* AID */ - res_APDU[0] = 0x5a; - } + GPG_NO_FILE (); + return; + } + + if (is_short_EF) + { + file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO; + offset = P2 (apdu); } else - GPG_NO_RECORD(); + offset = (P1 (apdu) << 8) | P2 (apdu); + + if (file_id == FILEID_SERIAL_NO) + { + if (offset != 0) + GPG_BAD_P1_P2 (); + else + { + gpg_do_get_data (0x004f, 1); /* Get AID... */ + res_APDU[0] = 0x5a; /* ... and overwrite the first byte of data. */ + } + return; + } + + if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3) + { + if (offset != 0) + GPG_MEMORY_FAILURE (); + else + { + p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0); + res_APDU_size = KEY_CONTENT_LEN; + memcpy (res_APDU, p, KEY_CONTENT_LEN); + GPG_SUCCESS (); + } + } +#if defined(CERTDO_SUPPORT) + else /* file_id == FILEID_CH_CERTIFICATE */ + { + uint16_t len = 256; + + p = &ch_certificate_start; + if (offset >= FLASH_CH_CERTIFICATE_SIZE) + GPG_MEMORY_FAILURE (); + else + { + if (offset + len >= FLASH_CH_CERTIFICATE_SIZE) + len = FLASH_CH_CERTIFICATE_SIZE - offset; + + res_APDU_size = len; + memcpy (res_APDU, p + offset, len); + GPG_SUCCESS (); + } + } +#endif } static void @@ -543,7 +619,7 @@ cmd_select_file (void) * MF.EF-GDO -- Serial number of the card and name of the owner */ GPG_SUCCESS (); - file_selection = FILE_EF_SERIAL; + file_selection = FILE_EF_SERIAL_NO; } else if (apdu.cmd_apdu_data_len == 2 && apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00) @@ -704,17 +780,17 @@ cmd_internal_authenticate (void) DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n"); } +#define MBD_OPRATION_WRITE 0 +#define MBD_OPRATION_UPDATE 1 -#if defined(CERTDO_SUPPORT) static void -cmd_update_binary (void) +modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len) { - int len = apdu.cmd_apdu_data_len; + uint8_t file_id; uint16_t offset; + int is_short_EF = (p1 & 0x80) != 0; int r; - DEBUG_INFO (" - UPDATE BINARY\r\n"); - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) { DEBUG_INFO ("security error."); @@ -722,41 +798,52 @@ cmd_update_binary (void) return; } - if ((P1 (apdu) & 0x80)) - if ((P1 (apdu) & 0x7f) == FILEID_CH_CERTIFICATE) - { - file_selection = FILE_EF_CH_CERTIFICATE; - r = flash_erase_binary (FILEID_CH_CERTIFICATE); - if (r < 0) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - return; - } - - offset = 0; - } - else - { - GPG_NO_FILE (); - return; - } + if (is_short_EF) + file_id = (p1 & 0x1f); else - { - if (file_selection != FILE_EF_CH_CERTIFICATE) - { - GPG_COMMAND_NOT_ALLOWED (); - return; - } + file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO; - offset = (P1 (apdu) << 8) | P2 (apdu); + if (!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE) + { + GPG_NO_FILE (); + return; } + if (op == MBD_OPRATION_UPDATE && file_id != FILEID_CH_CERTIFICATE) + { + GPG_CONDITION_NOT_SATISFIED (); + return; + } + + if (file_id > FILEID_CH_CERTIFICATE) + { + GPG_NO_FILE (); + return; + } + + if (is_short_EF) + { + file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO; + offset = p2; + + if (op == MBD_OPRATION_UPDATE) + { + r = flash_erase_binary (file_id); + if (r < 0) + { + DEBUG_INFO ("memory error.\r\n"); + GPG_MEMORY_FAILURE (); + return; + } + } + } + else + offset = (p1 << 8) | p2; + DEBUG_SHORT (len); DEBUG_SHORT (offset); - r = flash_write_binary (FILEID_CH_CERTIFICATE, - apdu.cmd_apdu_data, len, offset); + r = flash_write_binary (file_id, apdu.cmd_apdu_data, len, offset); if (r < 0) { DEBUG_INFO ("memory error.\r\n"); @@ -765,6 +852,17 @@ cmd_update_binary (void) } GPG_SUCCESS (); +} + + +#if defined(CERTDO_SUPPORT) +static void +cmd_update_binary (void) +{ + int len = apdu.cmd_apdu_data_len; + + DEBUG_INFO (" - UPDATE BINARY\r\n"); + modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len); DEBUG_INFO ("UPDATE BINARY done.\r\n"); } #endif @@ -774,54 +872,9 @@ static void cmd_write_binary (void) { int len = apdu.cmd_apdu_data_len; - uint16_t offset; - int r; DEBUG_INFO (" - WRITE BINARY\r\n"); - - if (!ac_check_status (AC_ADMIN_AUTHORIZED)) - { - DEBUG_INFO ("security error."); - GPG_SECURITY_FAILURE (); - return; - } - - if ((P1 (apdu) & 0x80)) - if ((P1 (apdu) & 0x7f) <= FILEID_CH_CERTIFICATE) - { - file_selection = FILE_EF_SERIAL + (P1 (apdu) & 0x7f); - offset = 0; - } - else - { - GPG_NO_FILE (); - return; - } - else - { - if (file_selection != FILE_EF_SERIAL - && file_selection != FILE_EF_CH_CERTIFICATE) - { - GPG_COMMAND_NOT_ALLOWED (); - return; - } - - offset = (P1 (apdu) << 8) | P2 (apdu); - } - - DEBUG_SHORT (len); - DEBUG_SHORT (offset); - - r = flash_write_binary (file_selection - FILE_EF_SERIAL, - apdu.cmd_apdu_data, len, offset); - if (r < 0) - { - DEBUG_INFO ("memory error.\r\n"); - GPG_MEMORY_FAILURE (); - return; - } - - GPG_SUCCESS (); + modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len); DEBUG_INFO ("WRITE BINARY done.\r\n"); } @@ -837,14 +890,16 @@ cmd_external_authenticate (void) DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); - if (keyno > 2) + if (keyno > 4) { GPG_CONDITION_NOT_SATISFIED (); return; } pubkey = gpg_get_firmware_update_key (keyno); - if (pubkey == NULL || len != 256) + if (len != 256 + || (pubkey[0] == 0xff && pubkey[1] == 0xff) /* not registered */ + || (pubkey[0] == 0x00 && pubkey[1] == 0x00) /* removed */) { GPG_CONDITION_NOT_SATISFIED (); return; diff --git a/src/openpgp.h b/src/openpgp.h index b92c2c8..b8693b9 100644 --- a/src/openpgp.h +++ b/src/openpgp.h @@ -6,7 +6,7 @@ #define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81) #define GPG_NO_FILE() set_res_sw (0x6a, 0x82) #define GPG_NO_RECORD() set_res_sw (0x6a, 0x88) -#define GPG_BAD_P0_P1() set_res_sw (0x6b, 0x00) +#define GPG_BAD_P1_P2() set_res_sw (0x6b, 0x00) #define GPG_NO_INS() set_res_sw (0x6d, 0x00) #define GPG_ERROR() set_res_sw (0x6f, 0x00) #define GPG_SUCCESS() set_res_sw (0x90, 0x00) From 34bd06974330c33b96b2189af50a7e3adb11f969 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 12:06:33 +0900 Subject: [PATCH 144/300] invalidating all update keys, flash_erase_page will be called --- src/openpgp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/openpgp.c b/src/openpgp.c index 3d5785e..c26dcc7 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -872,9 +872,25 @@ static void cmd_write_binary (void) { int len = apdu.cmd_apdu_data_len; + int i; + const uint8_t *p; DEBUG_INFO (" - WRITE BINARY\r\n"); modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len); + + for (i = 0; i < 4; i++) + { + p = gpg_get_firmware_update_key (i); + if (p[0] != 0x00 || p[1] != 0x00) /* still valid */ + break; + } + + if (i == 4) /* all update keys are removed */ + { + p = gpg_get_firmware_update_key (0) + flash_erase_page ((uint32_t)p); + } + DEBUG_INFO ("WRITE BINARY done.\r\n"); } From 95f328f94f2611353140cd1bd9f8eb7d25b8b1d0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 12:10:08 +0900 Subject: [PATCH 145/300] update tools --- tool/gnuk_put_binary.py | 2 +- tool/gnuk_put_binary_libusb.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 217d818..3446b62 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -168,7 +168,7 @@ if __name__ == '__main__': print "Writing serial number" data = binascii.unhexlify(serial_data_hex) else: - fileid = 1 # Card holder certificate + fileid = 5 # Card holder certificate filename = sys.argv[1] f = open(filename) data = f.read() diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 8ed42e0..a6bb0e3 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -271,7 +271,7 @@ if __name__ == '__main__': print "Writing serial number" data = binascii.unhexlify(serial_data_hex) else: - fileid = 1 # Card holder certificate + fileid = 5 # Card holder certificate filename = sys.argv[1] f = open(filename) data = f.read() From 2215a6dd2c91106e98590b287cc6ea1f27806b72 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 12:34:11 +0900 Subject: [PATCH 146/300] challenge/response definition change --- ChangeLog | 4 ++++ src/call-rsa.c | 6 ++---- src/gnuk.h | 2 +- src/openpgp.c | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f9d7fd..fa29bf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-05-31 Niibe Yutaka + * src/call-rsa.c (rsa_verify): It's SIG_RSA_MD5. + * src/openpgp.c (cmd_external_authenticate): Follow the change of + rsa_verify. + Support "firmware update" keys. * src/flash.c (flash_write_binary): Support update keys. * src/gnuk.h (FILEID_UPDATE_KEY_0, FILEID_UPDATE_KEY_1) diff --git a/src/call-rsa.c b/src/call-rsa.c index 424aaf9..1de254b 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -185,8 +185,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, } int -rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen, - const uint8_t *signature) +rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) { int r; @@ -197,8 +196,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen, DEBUG_INFO ("RSA verify..."); - r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_RAW, hashlen, - hash, signature); + r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_MD5, 16, hash, sig); rsa_free (&rsa_ctx); if (r < 0) diff --git a/src/gnuk.h b/src/gnuk.h index ebf9aae..0220595 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -230,7 +230,7 @@ extern int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *); extern const uint8_t *modulus_calc (const uint8_t *, int); extern void modulus_free (const uint8_t *); extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *); -extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen, +extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *signature); extern const uint8_t *gpg_do_read_simple (uint8_t); diff --git a/src/openpgp.c b/src/openpgp.c index c26dcc7..9f8ee0a 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -887,8 +887,8 @@ cmd_write_binary (void) if (i == 4) /* all update keys are removed */ { - p = gpg_get_firmware_update_key (0) - flash_erase_page ((uint32_t)p); + p = gpg_get_firmware_update_key (0); + flash_erase_page ((uint32_t)p); } DEBUG_INFO ("WRITE BINARY done.\r\n"); @@ -921,7 +921,7 @@ cmd_external_authenticate (void) return; } - r = rsa_verify (pubkey, challenge, CHALLENGE_LEN, signature); + r = rsa_verify (pubkey, challenge, signature); random_bytes_free (challenge); challenge = NULL; if (r < 0) From fa2ae42e692ccb727706a50eb12a27f35b54c92d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 13:09:57 +0900 Subject: [PATCH 147/300] SHA1 for external authentication --- ChangeLog | 2 +- src/call-rsa.c | 2 +- src/openpgp.c | 15 +++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa29bf2..adadd14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 2012-05-31 Niibe Yutaka - * src/call-rsa.c (rsa_verify): It's SIG_RSA_MD5. + * src/call-rsa.c (rsa_verify): It's SIG_RSA_SHA1. * src/openpgp.c (cmd_external_authenticate): Follow the change of rsa_verify. diff --git a/src/call-rsa.c b/src/call-rsa.c index 1de254b..fc5dc48 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -196,7 +196,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) DEBUG_INFO ("RSA verify..."); - r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_MD5, 16, hash, sig); + r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA1, 20, hash, sig); rsa_free (&rsa_ctx); if (r < 0) diff --git a/src/openpgp.c b/src/openpgp.c index 9f8ee0a..6e5b8fb 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -900,9 +900,9 @@ cmd_external_authenticate (void) { const uint8_t *pubkey; const uint8_t *signature = apdu.cmd_apdu_data; + const uint8_t *hash = apdu.cmd_apdu_data + 256; int len = apdu.cmd_apdu_data_len; uint8_t keyno = P2 (apdu); - int r; DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); @@ -920,11 +920,13 @@ cmd_external_authenticate (void) GPG_CONDITION_NOT_SATISFIED (); return; } - - r = rsa_verify (pubkey, challenge, signature); + + memcpy (hash, unique_device_id (), 4); + memcpy (hash+4, challenge, CHALLENGE_LEN); random_bytes_free (challenge); challenge = NULL; - if (r < 0) + + if (rsa_verify (pubkey, hash, signature) < 0) { GPG_SECURITY_FAILURE (); return; @@ -944,8 +946,9 @@ cmd_get_challenge (void) random_bytes_free (challenge); challenge = random_bytes_get (); - memcpy (res_APDU, challenge, CHALLENGE_LEN); - res_APDU_size = CHALLENGE_LEN; + memcpy (res_APDU, unique_device_id (), 4); + memcpy (res_APDU+4, challenge, CHALLENGE_LEN); + res_APDU_size = CHALLENGE_LEN + 4; GPG_SUCCESS (); DEBUG_INFO ("GET CHALLENGE done.\r\n"); } From 41633871fe1ed0259a8e5f1612ae965fe8380947 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 15:03:31 +0900 Subject: [PATCH 148/300] update --- NEWS | 13 +++++++++++++ tool/gnuk_upgrade.py | 13 +++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index f6a8bad..8ab6437 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,18 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 0.19 + + Released 2012-06-XX, by NIIBE Yutaka + +** System service blocks at the beginning of flash ROM. + +** USB strings for revision detail, configure options, and system service. + +** Firmware upgrade feature + +** New tool: gnuk_upgrade.py + + * Major changes in Gnuk 0.18 Released 2012-05-15, by NIIBE Yutaka diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 2318ece..43034c8 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -359,7 +359,7 @@ def to_string(t): result += chr(c) return result -def main(passwd, data_regnual, data_upgrade): +def main(data_regnual, data_upgrade): data_regnual += pack(' Date: Thu, 31 May 2012 15:06:25 +0900 Subject: [PATCH 149/300] fix --- src/openpgp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openpgp.c b/src/openpgp.c index 6e5b8fb..f7e225a 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -25,6 +25,7 @@ #include "ch.h" #include "hal.h" #include "gnuk.h" +#include "sys.h" #include "openpgp.h" #include "polarssl/config.h" #include "polarssl/sha1.h" @@ -900,7 +901,7 @@ cmd_external_authenticate (void) { const uint8_t *pubkey; const uint8_t *signature = apdu.cmd_apdu_data; - const uint8_t *hash = apdu.cmd_apdu_data + 256; + uint8_t *hash = apdu.cmd_apdu_data + 256; int len = apdu.cmd_apdu_data_len; uint8_t keyno = P2 (apdu); From 7860f1e729038c8852011c7a00f8bc9c046dac51 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 31 May 2012 18:19:39 +0900 Subject: [PATCH 150/300] buffer size of rsa_verify --- ChangeLog | 2 ++ polarssl-0.14.0/library/rsa.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index adadd14..2a4848a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-05-31 Niibe Yutaka + * polarssl-0.14.0/library/rsa.c (rsa_pkcs1_verify): BUF size is + 256 (was: 1024). * src/call-rsa.c (rsa_verify): It's SIG_RSA_SHA1. * src/openpgp.c (cmd_external_authenticate): Follow the change of rsa_verify. diff --git a/polarssl-0.14.0/library/rsa.c b/polarssl-0.14.0/library/rsa.c index 0411701..54a219b 100644 --- a/polarssl-0.14.0/library/rsa.c +++ b/polarssl-0.14.0/library/rsa.c @@ -542,7 +542,7 @@ int rsa_pkcs1_verify( rsa_context *ctx, { int ret, len, siglen; unsigned char *p, c; - unsigned char buf[1024]; + unsigned char buf[256]; siglen = ctx->len; From 42f9c16fd874df290faec644dbead8dbb30eb72d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 09:34:28 +0900 Subject: [PATCH 151/300] Bug fixes for USB protocol stack. --- ChangeLog | 8 ++++++++ src/main.c | 2 +- src/usb_ctrl.c | 7 +++++-- src/usb_lld.c | 23 ++++++----------------- src/usb_lld.h | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a4848a..d1f76ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2012-06-01 Niibe Yutaka + + USB bug fixes. + * src/usb_ctrl.c (gnuk_usb_event): Bug fix for handling + USB_EVENT_CONFIG. Do nothing when current_conf == value. + * src/usb_lld.c (std_clear_feature): Bug fix. Always clear DTOG. + (usb_lld_init): New argument for FEATURE. + 2012-05-31 Niibe Yutaka * polarssl-0.14.0/library/rsa.c (rsa_pkcs1_verify): BUF size is diff --git a/src/main.c b/src/main.c index d935fb0..33fe8e8 100644 --- a/src/main.c +++ b/src/main.c @@ -389,7 +389,7 @@ main (int argc, char *argv[]) flash_unlock (); device_initialize_once (); - usb_lld_init (); + usb_lld_init (Config_Descriptor.Descriptor[7]); random_init (); while (1) diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index c7ee886..9c80e78 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -347,6 +347,7 @@ gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value) static int gnuk_usb_event (uint8_t event_type, uint16_t value) { int i; + uint8_t current_conf; switch (event_type) { @@ -354,7 +355,8 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) bDeviceState = ADDRESSED; return USB_SUCCESS; case USB_EVENT_CONFIG: - if (usb_lld_current_configuration () == 0) + current_conf = usb_lld_current_configuration (); + if (current_conf == 0) { if (value != 1) return USB_UNSUPPORT; @@ -365,7 +367,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) bDeviceState = CONFIGURED; chEvtSignalI (main_thread, LED_STATUS_MODE); } - else + else if (current_conf != value) { if (value != 0) return USB_UNSUPPORT; @@ -375,6 +377,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) gnuk_setup_endpoints_for_interface (i, 1); bDeviceState = ADDRESSED; } + /* Do nothing when current_conf == value */ return USB_SUCCESS; default: break; diff --git a/src/usb_lld.c b/src/usb_lld.c index 1c31a04..3827c32 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -358,13 +358,14 @@ static void st103_ep_clear_dtog_tx (uint8_t ep_num) } } -void usb_lld_init (void) +void usb_lld_init (uint8_t feature) { usb_lld_sys_init (); dev_p->state = IN_DATA; usb_lld_set_configuration (0); + usb_lld_set_feature (feature); /* Reset USB */ st103_set_cntr (CNTR_FRES); @@ -606,22 +607,10 @@ static int std_clear_feature (uint8_t req, uint16_t value, if (status == 0) /* Disabled */ return USB_UNSUPPORT; - if (index & 0x80) - { /* IN endpoint */ - if (st103_ep_get_tx_status (endpoint) == EP_TX_STALL) - { - st103_ep_clear_dtog_tx (endpoint); - st103_ep_set_tx_status (endpoint, EP_TX_VALID); - } - } - else - { /* OUT endpoint */ - if (st103_ep_get_rx_status (endpoint) == EP_RX_STALL) - { - st103_ep_clear_dtog_rx (endpoint); - st103_ep_set_rx_status (endpoint, EP_RX_VALID); - } - } + if (index & 0x80) /* IN endpoint */ + st103_ep_clear_dtog_tx (endpoint); + else /* OUT endpoint */ + st103_ep_clear_dtog_rx (endpoint); // event?? return USB_SUCCESS; diff --git a/src/usb_lld.h b/src/usb_lld.h index 78a35e3..481c7a7 100644 --- a/src/usb_lld.h +++ b/src/usb_lld.h @@ -109,7 +109,7 @@ extern uint32_t bDeviceState; #define STM32_USB_IRQ_PRIORITY 11 -extern void usb_lld_init (void); +extern void usb_lld_init (uint8_t feature); extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n); From 441051a4858054646fe7de7281df8700cebb0b54 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 13:15:13 +0900 Subject: [PATCH 152/300] ifdef-out USB strings for reGNUal --- ChangeLog | 4 ++++ src/configure | 2 ++ src/usb_desc.c | 1 + 3 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index d1f76ae..47a4035 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-06-01 Niibe Yutaka + * src/configure (usb-strings.c.inc): ifdef-out + gnuk_revision_detail and gnuk_config_options (for reGNUal). + * src/usb_desc.c (USB_STRINGS_FOR_GNUK): Define. + USB bug fixes. * src/usb_ctrl.c (gnuk_usb_event): Bug fix for handling USB_EVENT_CONFIG. Do nothing when current_conf == value. diff --git a/src/configure b/src/configure index 908b602..80796c7 100755 --- a/src/configure +++ b/src/configure @@ -214,6 +214,7 @@ if !(IFS=" " echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" echo '};' echo + echo '#ifdef USB_STRINGS_FOR_GNUK' echo 'static const uint8_t gnuk_revision_detail[] = {' echo " ${#REVISION}*2+2, /* bLength */" echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */" @@ -227,6 +228,7 @@ if !(IFS=" " echo " /* configure options: \"$CONFIG\" */" echo $CONFIG | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p" echo '};' + echo '#endif' ) >usb-strings.c.inc exit 0 fi diff --git a/src/usb_desc.c b/src/usb_desc.c index 681d41f..a7c1af6 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -254,6 +254,7 @@ static const uint8_t gnukStringLangID[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; +#define USB_STRINGS_FOR_GNUK 1 #include "usb-strings.c.inc" const uint8_t gnukStringSerial[] = { From 19d9e55613dfc3db4717e504c609f3aedeb326ca Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 13:18:34 +0900 Subject: [PATCH 153/300] update regnual --- ChangeLog | 5 +++++ regnual/Makefile | 2 +- regnual/regnual.c | 19 +++++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47a4035..470b85b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2012-06-01 Niibe Yutaka + Update of reGNUal. + * regnual/regnual.c (main): Follow the change of usb_lld_init. + (regnual_config_desc): Include interface descriptor. + (usb-strings.c.inc): Change the file name. + * regnual/Makefile (regnual.o): Depend on sys.h. * src/configure (usb-strings.c.inc): ifdef-out gnuk_revision_detail and gnuk_config_options (for reGNUal). * src/usb_desc.c (USB_STRINGS_FOR_GNUK): Define. diff --git a/regnual/Makefile b/regnual/Makefile index c1a2fbc..5e0036e 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -32,7 +32,7 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) all: regnual.hex -regnual.o: regnual.c +regnual.o: regnual.c ../src/sys.h regnual.hex: regnual.elf $(OBJCOPY) -Obinary regnual.elf regnual.bin diff --git a/regnual/regnual.c b/regnual/regnual.c index 1b761da..b36c498 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -60,8 +60,8 @@ static const uint8_t regnual_device_desc[] = { static const uint8_t regnual_config_desc[] = { 9, USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */ - 9, 0, /* wTotalLength: no of returned bytes */ - 0, /* bNumInterfaces: None, but control pipe */ + 18, 0, /* wTotalLength: no of returned bytes */ + 1, /* bNumInterfaces: single vender interface */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: None */ #if defined(USB_SELF_POWERED) @@ -70,6 +70,17 @@ static const uint8_t regnual_config_desc[] = { 0x80, /* bmAttributes: bus powered */ #endif 50, /* MaxPower 100 mA */ + + /* Interface Descriptor */ + 9, + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ + 0, /* bInterfaceNumber: Index of this interface */ + 0, /* Alternate setting for this interface */ + 0, /* bNumEndpoints: None */ + 0xFF, + 0, + 0, + 0, /* string index for interface */ }; static const uint8_t regnual_string_lang_id[] = { @@ -78,7 +89,7 @@ static const uint8_t regnual_string_lang_id[] = { 0x09, 0x04 /* LangID = 0x0409: US-English */ }; -#include "../src/usb-string-vendor-product.c.inc" +#include "../src/usb-strings.c.inc" static const uint8_t regnual_string_serial[] = { 8*2+2, @@ -294,7 +305,7 @@ main (int argc, char *argv[]) set_led (0); - usb_lld_init (); + usb_lld_init (regnual_config_desc[7]); while (1) { From 75b480f2c22a7f38d07511e45de82e044d026c97 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 13:19:10 +0900 Subject: [PATCH 154/300] fix gnuk_put_binary --- tool/gnuk_put_binary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 3446b62..3c2dae4 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -131,10 +131,10 @@ def main(fileid, is_update, data, passwd): print "%02x" % d, print compare(data, data_in_device[8:]) - elif fileid == 1: + elif fileid == 5: gnuk.cmd_select_openpgp() data_in_device = gnuk.cmd_get_data(0x7f, 0x21) - compare(data[:-2], data_in_device) + compare(data, data_in_device) gnuk.connection.disconnect() return 0 From 78d9a56277a6c522b5645a3b321d62c7f90496e5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 13:20:47 +0900 Subject: [PATCH 155/300] firmware update key registration --- ChangeLog | 3 + tool/gnuk_put_binary_libusb.py | 147 ++++++++++++++++++++++++--------- 2 files changed, 113 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 470b85b..f399954 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-06-01 Niibe Yutaka + * tool/gnuk_put_binary_libusb.py (main): Support firmware update + key registration. + Update of reGNUal. * regnual/regnual.c (main): Follow the change of usb_lld_init. (regnual_config_desc): Include interface descriptor. diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index a6bb0e3..86de1e4 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -4,7 +4,7 @@ gnuk_put_binary.py - a tool to put binary to Gnuk Token This tool is for importing certificate, updating random number, etc. -Copyright (C) 2011 Free Software Initiative of Japan +Copyright (C) 2011, 2012 Free Software Initiative of Japan Author: NIIBE Yutaka This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -41,13 +41,12 @@ CCID_PROTOCOL_0 = 0x00 def icc_compose(msg_type, data_len, slot, seq, param, data): return pack('BBBB', cls, ins, p1, p2) else: - return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data + return pack('>BBBBB', cls, ins, p1, p2, data_len) + data # This class only supports Gnuk (for now) class gnuk_token: @@ -150,27 +149,57 @@ class gnuk_token: else: raise ValueError, "icc_send_cmd" + def cmd_get_response(self, expected_len): + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) + response = self.icc_send_cmd(cmd_data) + return response[:-2] + def cmd_verify(self, who, passwd): cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, "cmd_verify" + raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_verify" + raise ValueError, sw + + def cmd_read_binary(self, fileid): + cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) def cmd_write_binary(self, fileid, data): count = 0 data_len = len(data) while count*256 < data_len: if count == 0: - cmd_data = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:256]) + if len(data) < 128: + cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128], 0x10) + cmd_data1 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[128:256]) else: - cmd_data = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)]) - sw = self.icc_send_cmd(cmd_data) + if len(data[256*count:256*count+128]) < 128: + cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128], 0x10) + cmd_data1 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)]) + sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: - raise ValueError, "cmd_write_binary" + raise ValueError, "cmd_write_binary 0" if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary" + raise ValueError, "cmd_write_binary 0" + if cmd_data1: + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError, "cmd_write_binary 1" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_write_binary 1" count += 1 def cmd_update_binary(self, fileid, data): @@ -178,31 +207,48 @@ class gnuk_token: data_len = len(data) while count*256 < data_len: if count == 0: - cmd_data = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:256]) + if len(data) < 128: + cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128], 0x10) + cmd_data1 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[128:256]) else: - cmd_data = iso7816_compose(0xd6, count, 0x00, data[256*count:256*(count+1)]) - sw = self.icc_send_cmd(cmd_data) + if len(data[256*count:256*count+128]) < 128: + cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128], 0x10) + cmd_data1 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*(count+1)]) + sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: - raise ValueError, "cmd_update_binary" + raise ValueError, "cmd_write_binary 0" if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_update_binary" + raise ValueError, "cmd_write_binary 0" + if cmd_data1: + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError, "cmd_write_binary 1" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_write_binary 1" count += 1 def cmd_select_openpgp(self): - cmd_data = iso7816_compose(0xa4, 0x04, 0x00, "\xD2\x76\x00\x01\x24\x01") + cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, "cmd_select_openpgp" + raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_select_openpgp" + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) def cmd_get_data(self, tagh, tagl): cmd_data = iso7816_compose(0xca, tagh, tagl, "") - result = self.icc_send_cmd(cmd_data) - sw = result[-2:] - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_get_data" - return result[:-2] + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) def compare(data_original, data_in_device): i = 0 @@ -211,7 +257,7 @@ def compare(data_original, data_in_device): raise ValueError, "verify failed at %08x" % i i += 1 -def get_device(): +def gnuk_devices(): busses = usb.busses() for bus in busses: devices = bus.devices @@ -222,33 +268,53 @@ def get_device(): if alt.interfaceClass == CCID_CLASS and \ alt.interfaceSubClass == CCID_SUBCLASS and \ alt.interfaceProtocol == CCID_PROTOCOL_0: - return dev, config, alt - raise ValueError, "Device not found" + yield dev, config, alt -def main(fileid, is_update, data): - dev, config, intf = get_device() - print "Device: ", dev.filename - print "Configuration: ", config.value - print "Interface: ", intf.interfaceNumber - icc = gnuk_token(dev, config, intf) +DEFAULT_PW3 = "12345678" +BY_ADMIN = 3 + +def main(fileid, is_update, data, passwd): + icc = None + for (dev, config, intf) in gnuk_devices(): + try: + icc = gnuk_token(dev, config, intf) + print "Device: ", dev.filename + print "Configuration: ", config.value + print "Interface: ", intf.interfaceNumber + break + except: + pass if icc.icc_get_status() == 2: raise ValueError, "No ICC present" elif icc.icc_get_status() == 1: icc.icc_power_on() - icc.cmd_verify(3, "12345678") + icc.cmd_verify(BY_ADMIN, passwd) if is_update: icc.cmd_update_binary(fileid, data) else: icc.cmd_write_binary(fileid, data) icc.cmd_select_openpgp() - if fileid == 1: - data = data[:-2] + if fileid == 0: + data_in_device = icc.cmd_get_data(0x00, 0x4f) + for d in data_in_device: + print "%02x" % d, + print + compare(data, data_in_device[8:]) + elif fileid >= 1 and fileid <= 4: + data_in_device = icc.cmd_read_binary(fileid) + compare(data, data_in_device) + else: data_in_device = icc.cmd_get_data(0x7f, 0x21) compare(data, data_in_device) icc.icc_power_off() return 0 if __name__ == '__main__': + passwd = DEFAULT_PW3 + if sys.argv[1] == '-p': + from getpass import getpass + passwd = getpass("Admin password: ") + sys.argv.pop(1) if sys.argv[1] == '-u': is_update = True sys.argv.pop(1) @@ -270,6 +336,13 @@ if __name__ == '__main__': exit(1) print "Writing serial number" data = binascii.unhexlify(serial_data_hex) + elif sys.argv[1] == '-k': # firmware update key + keyno = sys.argv[2] + fileid = 1 + int(keyno) + filename = sys.argv[3] + f = open(filename) + data = f.read() + f.close() else: fileid = 5 # Card holder certificate filename = sys.argv[1] @@ -278,4 +351,4 @@ if __name__ == '__main__': f.close() print "%s: %d" % (filename, len(data)) print "Updating card holder certificate" - main(fileid, is_update, data) + main(fileid, is_update, data, passwd) From 879b8b9966b275d8d02970f819d69db1fdf45458 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 1 Jun 2012 13:23:00 +0900 Subject: [PATCH 156/300] firmware update using public key --- ChangeLog | 2 + tool/gnuk_upgrade.py | 96 +++++++++++++++++++++++++++++++++----------- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index f399954..e9b5b9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-06-01 Niibe Yutaka + Support firmware update with public key authentication. + * tool/gnuk_upgrade.py (gpg_sign): New. * tool/gnuk_put_binary_libusb.py (main): Support firmware update key registration. diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 43034c8..9677a01 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -40,8 +40,7 @@ CCID_PROTOCOL_0 = 0x00 def icc_compose(msg_type, data_len, slot, seq, param, data): return pack('BBBB', cls, ins, p1, p2) @@ -49,8 +48,19 @@ def iso7816_compose(ins, p1, p2, data): return pack('>BBBBB', cls, ins, p1, p2, data_len) + data class regnual: - def __init__(self, device): - self.__devhandle = device.open() + def __init__(self, dev): + conf = dev.configurations[0] + intf_alt = conf.interfaces[0] + intf = intf_alt[0] + if intf.interfaceClass != 0xff: + raise ValueError, "Wrong interface class" + self.__devhandle = dev.open() + try: + self.__devhandle.setConfiguration(conf) + except: + pass + self.__devhandle.claimInterface(intf) + self.__devhandle.setAltInterface(intf) def mem_info(self): mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0, @@ -301,7 +311,13 @@ class gnuk_token: raise ValueError, ("%02x%02x" % (sw[0], sw[1])) def cmd_external_authenticate(self, signed): - cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed) + cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[0:128], cls=0x10) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[128:]) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: raise ValueError, sw @@ -324,7 +340,7 @@ def compare(data_original, data_in_device): raise ValueError, "verify failed at %08x" % i i += 1 -def get_ccid_device(): +def ccid_devices(): busses = usb.busses() for bus in busses: devices = bus.devices @@ -335,13 +351,12 @@ def get_ccid_device(): if alt.interfaceClass == CCID_CLASS and \ alt.interfaceSubClass == CCID_SUBCLASS and \ alt.interfaceProtocol == CCID_PROTOCOL_0: - return dev, config, alt - raise ValueError, "Device not found" + yield dev, config, alt USB_VENDOR_FSIJ=0x234b USB_PRODUCT_GNUK=0x0000 -def get_gnuk_device(): +def gnuk_devices(): busses = usb.busses() for bus in busses: devices = bus.devices @@ -350,8 +365,7 @@ def get_gnuk_device(): continue if dev.idProduct != USB_PRODUCT_GNUK: continue - return dev - raise ValueError, "Device not found" + yield dev def to_string(t): result = "" @@ -359,21 +373,49 @@ def to_string(t): result += chr(c) return result -def main(data_regnual, data_upgrade): +from subprocess import check_output + +def gpg_sign(keygrip, hash): + result = check_output(["gpg-connect-agent", + "SIGKEY %s" % keygrip, + "SETHASH --hash=sha1 %s" % hash, + "PKSIGN", "/bye"]) + signed = "" + while True: + i = result.find('%') + if i < 0: + signed += result + break + hex_str = result[i+1:i+3] + signed += result[0:i] + signed += chr(int(hex_str,16)) + result = result[i+3:] + + pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26 + signed = signed[pos:-7] + if len(signed) != 256: + raise ValueError, binascii.hexlify(signed) + return signed + +def main(keygrip, data_regnual, data_upgrade): data_regnual += pack(' Date: Mon, 4 Jun 2012 11:30:04 +0900 Subject: [PATCH 157/300] fix --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8ab6437..ba2d202 100644 --- a/NEWS +++ b/NEWS @@ -35,7 +35,7 @@ original implementation. Hopefully, size and quality are improved. Released 2012-02-02, by NIIBE Yutaka ** USB CCID/ICCD protocol implementation change -Gnuk now only supports short APDU level exchange, not support. +Gnuk now only supports short APDU level exchange, not supporting extended APDU level exchange. Thus, Gnuk could be compatible to older host side software implementation. From 07b1266727d792ff3a9d874f072a3788ab59c335 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 4 Jun 2012 11:34:10 +0900 Subject: [PATCH 158/300] bug fix --- ChangeLog | 4 ++++ regnual/regnual.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e9b5b9e..e82d5ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-04 Niibe Yutaka + + * regnual/regnual.c (regnual_ctrl_write_finish): Bug fix. + 2012-06-01 Niibe Yutaka Support firmware update with public key authentication. diff --git a/regnual/regnual.c b/regnual/regnual.c index b36c498..66603c9 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -156,7 +156,7 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req) && len == 0) { - if (req_no == USB_REGNUAL_SEND && index == 0) + if (req_no == USB_REGNUAL_SEND && value == 0) { result = 0; // calculate crc32 here!!! } From f73634d17c9af8a9df602602bf3e3964e955a3ad Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 4 Jun 2012 16:31:40 +0900 Subject: [PATCH 159/300] Implement CRC32 check --- ChangeLog | 7 ++++ regnual/regnual.c | 46 ++++++++++++++++++---- src/usb_ctrl.c | 36 ++++++++++++----- tool/gnuk_upgrade.py | 92 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 159 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index e82d5ca..5043cfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-06-04 Niibe Yutaka + Implement CRC32 check for firmware update. + * src/usb_ctrl.c (download_check_crc32): New. + * regnual/regnual.c (calc_crc32): New. + (regnual_ctrl_write_finish): Call calc_crc32. + * tool/gnuk_upgrade.py (crc32): New. + (regnual.download): Check crc32code. + * regnual/regnual.c (regnual_ctrl_write_finish): Bug fix. 2012-06-01 Niibe Yutaka diff --git a/regnual/regnual.c b/regnual/regnual.c index 66603c9..eecf698 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -147,28 +147,58 @@ static uint32_t result; static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; +static uint32_t fetch (int i) +{ + uint32_t r; + + r = (mem[i*4] << 24) | (mem[i*4+1] << 16) | (mem[i*4+2] << 8) | mem[i*4+3]; + return r; +} + +struct CRC { + __IO uint32_t DR; + __IO uint8_t IDR; + uint8_t RESERVED0; + uint16_t RESERVED1; + __IO uint32_t CR; +}; + +#define CRC_CR_RESET 0x01 +static uint32_t calc_crc32 (void) +{ + struct CRC *CRC = (struct CRC *)0x40023000; + int i; + + CRC->CR = CRC_CR_RESET; + + for (i = 0; i < 256/4; i++) + CRC->DR = fetch (i); + + return CRC->DR; +} + + static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, uint16_t index, uint16_t len) { uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); - if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) - && USB_SETUP_SET (req) && len == 0) + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req)) { if (req_no == USB_REGNUAL_SEND && value == 0) - { - result = 0; // calculate crc32 here!!! - } - else if (req_no == USB_REGNUAL_FLASH && index == 0) + result = calc_crc32 (); + else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0) { uint32_t dst_addr = (0x08000000 + value * 0x100); result = flash_write (dst_addr, mem, 256); } - else if (req_no == USB_REGNUAL_PROTECT && value == 0 && index == 0) + else if (req_no == USB_REGNUAL_PROTECT && len == 0 + && value == 0 && index == 0) result = flash_protect (); - else if (req_no == USB_REGNUAL_FINISH && value == 0 && index == 0) + else if (req_no == USB_REGNUAL_FINISH && len == 0 + && value == 0 && index == 0) nvic_system_reset (); } } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 9c80e78..f43f229 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -26,6 +26,7 @@ #include "config.h" #include "ch.h" +#include "hal.h" #include "usb_lld.h" #include "usb_conf.h" #include "gnuk.h" @@ -187,17 +188,30 @@ static const uint8_t *const mem_info[] = { &_regnual_start, &__heap_end__, }; #define USB_FSIJ_GNUK_DOWNLOAD 1 #define USB_FSIJ_GNUK_EXEC 2 -static int download_check_crc32 (const uint8_t *p) +static uint32_t reverse32 (uint32_t v) { - uint32_t crc32 = 0; + uint32_t r; - crc32 += (*--p << 24); - crc32 += (*--p << 16); - crc32 += (*--p << 8); - crc32 += (*--p); + r = (v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); + return r; +} - /* Not yet: Calculate crc32 from &_regnual_start to p, then compare */ - return USB_SUCCESS; +/* After calling this function, CRC module remain enabled. */ +static int download_check_crc32 (const uint32_t *end_p) +{ + uint32_t crc32 = *end_p; + const uint32_t *p; + + RCC->AHBENR |= RCC_AHBENR_CRCEN; + CRC->CR = CRC_CR_RESET; + + for (p = (const uint32_t *)&_regnual_start; p < end_p; p++) + CRC->DR = reverse32 (*p); + + if ((CRC->DR ^ crc32) == 0xffffffff) + return USB_SUCCESS; + + return USB_UNSUPPORT; } static int @@ -239,8 +253,10 @@ gnuk_setup (uint8_t req, uint8_t req_no, if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) return USB_UNSUPPORT; - /* There is a trailer at addr: crc32 */ - return download_check_crc32 (addr); + if (((uint32_t)addr & 0x03)) + return USB_UNSUPPORT; + + return download_check_crc32 ((uint32_t *)addr); } } } diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 9677a01..18ed48b 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -83,6 +83,13 @@ class regnual: value = 0, index = 0, buffer = data[j*256:j*256+256], timeout = 10000) + crc32code = crc32(data[j*256:j*256+256], 0xffffffff) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, @@ -104,6 +111,13 @@ class regnual: value = 0, index = 0, buffer = data[j*256:], timeout = 10000) + crc32code = crc32(data[j*256:].ljust(256,chr(255)), 0xffffffff) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" self.__devhandle.controlMsg(requestType = 0x40, request = 3, value = i, index = 0, buffer = None, @@ -397,9 +411,79 @@ def gpg_sign(keygrip, hash): raise ValueError, binascii.hexlify(signed) return signed -def main(keygrip, data_regnual, data_upgrade): - data_regnual += pack('>24)^ord(b) + crc = UNSIGNED((crc << 8)) ^ crctab[idx] + return UNSIGNED(~crc) + +def main(keygrip, data_regnual, data_upgrade): + l = len(data_regnual) + if (l & 0x03) != 0: + data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) + crc32code = crc32(data_regnual, 0xffffffff) + print "CRC32: %04x\n" % crc32code + data_regnual += pack(' Date: Mon, 4 Jun 2012 18:13:35 +0900 Subject: [PATCH 160/300] CertDO bug fixes --- ChangeLog | 7 +++++++ src/flash.c | 3 +-- src/gnuk.h | 2 ++ tool/gnuk_put_binary_libusb.py | 27 ++++++++++++++++++--------- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5043cfa..3147a15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-06-04 Niibe Yutaka + Card holder certificate data object bug fixes. + * tool/gnuk_put_binary_libusb.py (gnuk_token.cmd_get_response): + Handle larger data such as card holder certificate. + * src/flash.c (flash_write_binary): Bug fix. Call + flash_check_blank with p + offset. + * src/gnuk.h (FLASH_CH_CERTIFICATE_SIZE): Define here (was: flash.c). + Implement CRC32 check for firmware update. * src/usb_ctrl.c (download_check_crc32): New. * regnual/regnual.c (calc_crc32): New. diff --git a/src/flash.c b/src/flash.c index b12fcfb..f9aa02c 100644 --- a/src/flash.c +++ b/src/flash.c @@ -476,7 +476,6 @@ flash_cnt123_clear (const uint8_t **addr_p) #if defined(CERTDO_SUPPORT) -#define FLASH_CH_CERTIFICATE_SIZE 2048 int flash_erase_binary (uint8_t file_id) { @@ -534,7 +533,7 @@ flash_write_binary (uint8_t file_id, const uint8_t *data, uint32_t addr; int i; - if (flash_check_blank (p, len) == 0) + if (flash_check_blank (p + offset, len) == 0) return -1; addr = (uint32_t)p + offset; diff --git a/src/gnuk.h b/src/gnuk.h index 0220595..1488bd0 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -149,6 +149,8 @@ extern void flash_reset_counter (uint8_t counter_tag_nr); extern int flash_erase_binary (uint8_t file_id); extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset); +#define FLASH_CH_CERTIFICATE_SIZE 2048 + /* Linker set these two symbols */ extern uint8_t ch_certificate_start; extern uint8_t random_bits_start; diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 86de1e4..6115ca7 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -150,9 +150,18 @@ class gnuk_token: raise ValueError, "icc_send_cmd" def cmd_get_response(self, expected_len): - cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) - response = self.icc_send_cmd(cmd_data) - return response[:-2] + result = [] + while True: + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) + response = self.icc_send_cmd(cmd_data) + result += response[:-2] + sw = response[-2:] + if sw[0] == 0x90 and sw[1] == 0x00: + return result + elif sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + else: + expected_len = sw[1] def cmd_verify(self, who, passwd): cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) @@ -188,7 +197,7 @@ class gnuk_token: cmd_data1 = None else: cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)]) + cmd_data1 = iso7816_compose(0xd0, count, 0x00, data[256*count+128:256*(count+1)]) sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: raise ValueError, "cmd_write_binary 0" @@ -219,18 +228,18 @@ class gnuk_token: cmd_data1 = None else: cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*(count+1)]) + cmd_data1 = iso7816_compose(0xd6, count, 0x00, data[256*count+128:256*(count+1)]) sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: - raise ValueError, "cmd_write_binary 0" + raise ValueError, "cmd_update_binary 0" if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 0" + raise ValueError, "cmd_update_binary 0" if cmd_data1: sw = self.icc_send_cmd(cmd_data1) if len(sw) != 2: - raise ValueError, "cmd_write_binary 1" + raise ValueError, "cmd_update_binary 1" if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 1" + raise ValueError, "cmd_update_binary 1" count += 1 def cmd_select_openpgp(self): From bfa4952f31049a1bc7140047eb66fa6280764e66 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 5 Jun 2012 10:33:50 +0900 Subject: [PATCH 161/300] use RBIT instruction of Thumb-2 --- ChangeLog | 9 ++++++ regnual/regnual.c | 15 ++++++++-- src/usb_ctrl.c | 8 ++--- tool/gnuk_upgrade.py | 71 ++++---------------------------------------- 4 files changed, 31 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3147a15..e0a4d49 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-06-05 Niibe Yutaka + + Take advantage of the Thumb-2 "rbit" instruction. + * regnual/regnual.c (fetch): Reverse bits. + * src/usb_ctrl.c (rbit): New. Deleted reverse32. + (download_check_crc32): Use rbit. + * tool/gnuk_upgrade.py (crc32): Just use binascii.crc32. + (crctab): Remove. + 2012-06-04 Niibe Yutaka Card holder certificate data object bug fixes. diff --git a/regnual/regnual.c b/regnual/regnual.c index eecf698..7534e4c 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -147,14 +147,23 @@ static uint32_t result; static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, }; -static uint32_t fetch (int i) +static uint32_t rbit (uint32_t v) { uint32_t r; - r = (mem[i*4] << 24) | (mem[i*4+1] << 16) | (mem[i*4+2] << 8) | mem[i*4+3]; + asm ("rbit %0, %1" : "=r" (r) : "r" (v)); return r; } +static uint32_t fetch (int i) +{ + uint32_t v; + + v = (mem[i*4+3] << 24) | (mem[i*4+2] << 16) | (mem[i*4+1] << 8) | mem[i*4]; + + return rbit (v); +} + struct CRC { __IO uint32_t DR; __IO uint8_t IDR; @@ -174,7 +183,7 @@ static uint32_t calc_crc32 (void) for (i = 0; i < 256/4; i++) CRC->DR = fetch (i); - return CRC->DR; + return rbit (CRC->DR); } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index f43f229..4609f01 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -188,11 +188,11 @@ static const uint8_t *const mem_info[] = { &_regnual_start, &__heap_end__, }; #define USB_FSIJ_GNUK_DOWNLOAD 1 #define USB_FSIJ_GNUK_EXEC 2 -static uint32_t reverse32 (uint32_t v) +static uint32_t rbit (uint32_t v) { uint32_t r; - r = (v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); + asm ("rbit %0, %1" : "=r" (r) : "r" (v)); return r; } @@ -206,9 +206,9 @@ static int download_check_crc32 (const uint32_t *end_p) CRC->CR = CRC_CR_RESET; for (p = (const uint32_t *)&_regnual_start; p < end_p; p++) - CRC->DR = reverse32 (*p); + CRC->DR = rbit (*p); - if ((CRC->DR ^ crc32) == 0xffffffff) + if ((rbit (CRC->DR) ^ crc32) == 0xffffffff) return USB_SUCCESS; return USB_UNSUPPORT; diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 18ed48b..b03cdef 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -83,7 +83,7 @@ class regnual: value = 0, index = 0, buffer = data[j*256:j*256+256], timeout = 10000) - crc32code = crc32(data[j*256:j*256+256], 0xffffffff) + crc32code = crc32(data[j*256:j*256+256]) res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, value = 0, index = 0, buffer = 4, timeout = 10000) @@ -111,7 +111,7 @@ class regnual: value = 0, index = 0, buffer = data[j*256:], timeout = 10000) - crc32code = crc32(data[j*256:].ljust(256,chr(255)), 0xffffffff) + crc32code = crc32(data[j*256:].ljust(256,chr(255))) res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, value = 0, index = 0, buffer = 4, timeout = 10000) @@ -411,77 +411,18 @@ def gpg_sign(keygrip, hash): raise ValueError, binascii.hexlify(signed) return signed -crctab = [ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, - 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, - 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, - 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, - 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, - 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, - 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, - 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, - 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, - 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, - 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, - 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, - 0x2e003dc5, 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, - 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, - 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, - 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, - 0x40d816ba, 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, - 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, - 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, - 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, - 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, - 0xd1799b34, 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, - 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, - 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, - 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, - 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, - 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, - 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, - 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, - 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, - 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, - 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, - 0x81b02d74, 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, - 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, - 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, - 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, - 0x0fdc1bec, 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, - 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, - 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, - 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, - 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, - 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, - 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, - 0xb1f740b4 ] - def UNSIGNED(n): return n & 0xffffffff -# (1) Alas, zlib.crc32 (== binascii.crc32) uses same polynomial, but in a -# different way of endian-ness. -# (2) POSIX cksum command uses same calculation, but the initial value -# is different. -def crc32(bytestr, crc): - for b in bytestr: - idx = (crc>>24)^ord(b) - crc = UNSIGNED((crc << 8)) ^ crctab[idx] - return UNSIGNED(~crc) +def crc32(bytestr): + crc = binascii.crc32(bytestr) + return UNSIGNED(crc) def main(keygrip, data_regnual, data_upgrade): l = len(data_regnual) if (l & 0x03) != 0: data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) - crc32code = crc32(data_regnual, 0xffffffff) + crc32code = crc32(data_regnual) print "CRC32: %04x\n" % crc32code data_regnual += pack(' Date: Tue, 5 Jun 2012 11:18:41 +0900 Subject: [PATCH 162/300] fix gnuk_put_binary --- ChangeLog | 7 +++++ tool/gnuk_put_binary.py | 50 +++++++++++++++++++++++-------- tool/gnuk_put_binary_libusb.py | 54 ++++++++-------------------------- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0a4d49..b0ee12c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2012-06-05 Niibe Yutaka + Firmware update key handling. + * tool/gnuk_put_binary.py (GnukToken.cmd_get_response): Handle + larger data such as card holder certificate. + (GnukToken.cmd_write_binary): Bug fix for cert do write. + (GnukToken.cmd_read_binary): New. + (main): Support firmware update key. + Take advantage of the Thumb-2 "rbit" instruction. * regnual/regnual.c (fetch): Reverse bits. * src/usb_ctrl.c (rbit): New. Deleted reverse32. diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 3c2dae4..63a5e60 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -4,7 +4,7 @@ gnuk_put_binary.py - a tool to put binary to Gnuk Token This tool is for importing certificate, updating random number, etc. -Copyright (C) 2011 Free Software Initiative of Japan +Copyright (C) 2011, 2012 Free Software Initiative of Japan Author: NIIBE Yutaka This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -44,11 +44,17 @@ class GnukToken(object): self.connection = cardservice.connection def cmd_get_response(self, expected_len): - apdu = [0x00, 0xc0, 0x00, 0x00, expected_len] - response, sw1, sw2 = self.connection.transmit(apdu) - if not (sw1 == 0x90 and sw2 == 0x00): - raise ValueError, ("%02x%02x" % (sw1, sw2)) - return response + result = [] + while True: + apdu = [0x00, 0xc0, 0x00, 0x00, expected_len] + response, sw1, sw2 = self.connection.transmit(apdu) + result += response + if sw1 == 0x90 and sw2 == 0x00: + return result + elif sw1 != 0x61: + raise ValueError, ("%02x%02x" % (sw1, sw2)) + else: + expected_len = sw2 def cmd_verify(self, who, passwd): apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd) @@ -56,6 +62,15 @@ class GnukToken(object): if not (sw1 == 0x90 and sw2 == 0x00): raise ValueError, ("%02x%02x" % (sw1, sw2)) + def cmd_read_binary(self, fileid): + apdu = [0x00, 0xb0, 0x80+fileid, 0x00] + response, sw1, sw2 = self.connection.transmit(apdu) + if sw1 == 0x61: + response = self.cmd_get_response(sw2) + elif not (sw1 == 0x90 and sw2 == 0x00): + raise ValueError, ("%02x%02x" % (sw1, sw2)) + return response + def cmd_write_binary(self, fileid, data, is_update): count = 0 data_len = len(data) @@ -66,7 +81,7 @@ class GnukToken(object): while count*256 < data_len: if count == 0: d = data[:256] - if len(d) <= 255: + if len(d) <= 255: apdu = [0x00, ins, 0x80+fileid, 0x00, len(d)] + s2l(d) else: apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255] + s2l(d[:255]) @@ -74,18 +89,18 @@ class GnukToken(object): apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:]) else: d = data[256*count:256*(count+1)] - if len(d) <= 255: + if len(d) <= 255: apdu = [0x00, ins, count, 0x00, len(d)] + s2l(d) else: apdu0 = [0x10, ins, count, 0x00, 255] + s2l(d[:255]) response, sw1, sw2 = self.connection.transmit(apdu0) - apdu = [0x00, ins, 0x80+fileid, 0x00, 1] + s2l(d[255:]) + apdu = [0x00, ins, count, 0x00, 1] + s2l(d[255:]) response, sw1, sw2 = self.connection.transmit(apdu) if not (sw1 == 0x90 and sw2 == 0x00): if is_update: - raise ValueError, ("%02x%02x" % (sw1, sw2)) + raise ValueError, ("update failure: %02x%02x" % (sw1, sw2)) else: - raise ValueError, ("%02x%02x" % (sw1, sw2)) + raise ValueError, ("write failure: %02x%02x" % (sw1, sw2)) count += 1 def cmd_select_openpgp(self): @@ -124,15 +139,17 @@ def main(fileid, is_update, data, passwd): gnuk.cmd_verify(BY_ADMIN, passwd) gnuk.cmd_write_binary(fileid, data, is_update) + gnuk.cmd_select_openpgp() if fileid == 0: - 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:]) + elif fileid >= 1 and fileid <= 4: + data_in_device = gnuk.cmd_read_binary(fileid) + compare(data, data_in_device) elif fileid == 5: - gnuk.cmd_select_openpgp() data_in_device = gnuk.cmd_get_data(0x7f, 0x21) compare(data, data_in_device) @@ -167,6 +184,13 @@ if __name__ == '__main__': exit(1) print "Writing serial number" data = binascii.unhexlify(serial_data_hex) + elif sys.argv[1] == '-k': # firmware update key + keyno = sys.argv[2] + fileid = 1 + int(keyno) + filename = sys.argv[3] + f = open(filename) + data = f.read() + f.close() else: fileid = 5 # Card holder certificate filename = sys.argv[1] diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 6115ca7..4c056fc 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -180,24 +180,28 @@ class gnuk_token: raise ValueError, ("%02x%02x" % (sw[0], sw[1])) return self.cmd_get_response(sw[1]) - def cmd_write_binary(self, fileid, data): + def cmd_write_binary(self, fileid, data, is_update): count = 0 data_len = len(data) + if is_update: + ins = 0xd6 + else: + ins = 0xd0 while count*256 < data_len: if count == 0: if len(data) < 128: - cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128]) + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128]) cmd_data1 = None else: - cmd_data0 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:128], 0x10) - cmd_data1 = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[128:256]) + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10) + cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256]) else: if len(data[256*count:256*count+128]) < 128: - cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128]) + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128]) cmd_data1 = None else: - cmd_data0 = iso7816_compose(0xd0, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(0xd0, count, 0x00, data[256*count+128:256*(count+1)]) + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10) + cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: raise ValueError, "cmd_write_binary 0" @@ -211,37 +215,6 @@ class gnuk_token: raise ValueError, "cmd_write_binary 1" count += 1 - def cmd_update_binary(self, fileid, data): - count = 0 - data_len = len(data) - while count*256 < data_len: - if count == 0: - if len(data) < 128: - cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:128], 0x10) - cmd_data1 = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[128:256]) - else: - if len(data[256*count:256*count+128]) < 128: - cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(0xd6, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(0xd6, count, 0x00, data[256*count+128:256*(count+1)]) - sw = self.icc_send_cmd(cmd_data0) - if len(sw) != 2: - raise ValueError, "cmd_update_binary 0" - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_update_binary 0" - if cmd_data1: - sw = self.icc_send_cmd(cmd_data1) - if len(sw) != 2: - raise ValueError, "cmd_update_binary 1" - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_update_binary 1" - count += 1 - def cmd_select_openpgp(self): cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") sw = self.icc_send_cmd(cmd_data) @@ -298,10 +271,7 @@ def main(fileid, is_update, data, passwd): elif icc.icc_get_status() == 1: icc.icc_power_on() icc.cmd_verify(BY_ADMIN, passwd) - if is_update: - icc.cmd_update_binary(fileid, data) - else: - icc.cmd_write_binary(fileid, data) + icc.cmd_write_binary(fileid, data, is_update) icc.cmd_select_openpgp() if fileid == 0: data_in_device = icc.cmd_get_data(0x00, 0x4f) From 75bfa6068a5fdf79f72ecee78eff60c7a22c1095 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 6 Jun 2012 08:39:13 +0900 Subject: [PATCH 163/300] improve regnual --- ChangeLog | 4 ++++ regnual/regnual.c | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0ee12c..4ab7881 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-06 Niibe Yutaka + + * regnual/regnual.c (fetch): Better implementation. + 2012-06-05 Niibe Yutaka Firmware update key handling. diff --git a/regnual/regnual.c b/regnual/regnual.c index 7534e4c..0d04739 100644 --- a/regnual/regnual.c +++ b/regnual/regnual.c @@ -159,8 +159,7 @@ static uint32_t fetch (int i) { uint32_t v; - v = (mem[i*4+3] << 24) | (mem[i*4+2] << 16) | (mem[i*4+1] << 8) | mem[i*4]; - + v = *(uint32_t *)(&mem[i*4]); return rbit (v); } From 808cb61b9a543cc0723b6193763872036f22ae4c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 6 Jun 2012 09:02:17 +0900 Subject: [PATCH 164/300] doc/firmware-update --- doc/firmware-update | 128 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 doc/firmware-update diff --git a/doc/firmware-update b/doc/firmware-update new file mode 100644 index 0000000..19b0442 --- /dev/null +++ b/doc/firmware-update @@ -0,0 +1,128 @@ +Firmware update feature +======================= + +The firmware update feature of Gnuk is experimental. Please be +careful using that. + +Note that updating firmware, all data objects and keys will be +removed. There is _no way_ to preserve those data. + + + +Preparation +=========== + +In addition to settings of Gnuk, I create a file +/etc/udev/rules.d/92-gnuk.rules:: + + # For updating firmware, permission settings are needed. + + SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \ + ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd" + + +While I am a member of group "pcscd" in /etc/group. + +This is needed for reGNUal, the firmware update program. + + +Registering a public key for firmware update +============================================ + +You need to register a public key to update the firmware. It should +be RSA 2048-bit. + +One way to extract public key data is by using "gpg-connect-agent" +command connecting gpg-agent. + +We can examine key information of gpg-agent by "KEYINFO" command. +Here is my example:: + + $ gpg-connect-agent "KEYINFO --list" /bye + S KEYINFO 4970A0D537CA2EF7CE6A106E47AD89B0EFB684C8 D - - - - - + S KEYINFO 65F67E742101C7FE6D5B33FCEFCF4F65EAF0688C T D276000124010200F517000000010000 OPENPGP.2 - - - + S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - - + S KEYINFO 7D180C0C2A991B25204110A92F5F92A5A509845B D - - - - - + S KEYINFO 101DE7B639FE29F4636BDEECF442A9273AFA6565 T D276000124010200F517000000010000 OPENPGP.1 - - - + OK + +I have two local keys (in my PC) and three keys in my token. + +With the script below, I extract public key of the keygrip +5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin:: + + $ ./get_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED + +Here is the script, get_public_key.py:: + + #! /usr/bin/python + + import sys, binascii + from subprocess import check_output + + def get_gpg_public_key(keygrip): + result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"]) + key = "" + while True: + i = result.find('%') + if i < 0: + key += result + break + hex_str = result[i+1:i+3] + key += result[0:i] + key += chr(int(hex_str,16)) + result = result[i+3:] + + pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too + key = key[pos:-17] # )(1:e3:XYZ)))\nOK\n + if len(key) != 256: + raise ValueError, binascii.hexlify(key) + return key + + if __name__ == '__main__': + keygrip = sys.argv[1] + k = get_gpg_public_key(keygrip) + shorthand = keygrip[0:8] + ".bin" + f = open(shorthand,"w") + f.write(k) + f.close() + + +Then, we can put the data of public key into token by:: + + $ tool/gnuk_put_binary_libusb.py -k 0 5D6C8968.bin + + +Invoking firmware update +======================== + +We specify the keygrip to authenticate, reGNUal binary, and Gnuk binary. + + $ ../tool/gnuk_upgrade.py 5D6C89682D07CCFC034AF508420BF2276D8018ED ../regnual/regnual.bin gnuk.bin + + +Two or more tokens +================== + +Currently, GnuPG doesn't support multiple devices connected to the +host. + +In order to update the firmware of a token TARGET, we use GnuPG to +authenticate with public key. If it is on another token AUTH, it is +somewhat complicated. + +What I do is: +(1) Don't run PC/SC daemon:: + + # /etc/init.d/pcscd stop + +(2) To make sure, kill scdaemon:: + + $ killall -9 scdaemon + +(3) Connect the token of AUTH, and use it:: + + $ gpg --card-status + +(4) Connect TARGET, and invoke gnuk_update.py +-- From 3da8a3b3269fcdd5a7c4c6c6df7dd909e0fc83c7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 6 Jun 2012 09:05:24 +0900 Subject: [PATCH 165/300] version 0.18 --- AUTHORS | 43 +++++++++++++++++++++++++------------------ ChangeLog | 4 ++++ NEWS | 23 ++++++++++++++++++----- README | 36 ++++++++++++++++++++++-------------- src/usb_desc.c | 2 +- 5 files changed, 70 insertions(+), 38 deletions(-) diff --git a/AUTHORS b/AUTHORS index 4b44825..ec2f636 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,32 +37,39 @@ NIIBE Yutaka: Wrote a tool for Gnuk: tool/gnuk_put_binary.py tool/gnuk_put_binary_libusb.py + tool/gnuk_remove_keys.py + tool/gnuk_upgrade.py Wrote a tool for USB Hub: tool/hub_ctrl.py - Wrote: + Wrote a tool for testing card reader with pinpad: + tool/pinpadtest.py + Wrote reGNUal implementation: + regnual/regnual.c + regnual/sys.c + Wrote Gnuk implementation: gnuk.svg src/configure src/ac.c - src/main.c - src/usb_lld.h - src/gnuk.h - src/usb_lld.c - src/usb-icc.c - src/openpgp-do.c - src/flash.c - src/debug.c - src/usb_desc.c - src/usb-cdc-vport.c - src/hardclock.c - src/openpgp.h - src/openpgp.c src/call-rsa.c - src/random.c + src/debug.c + src/flash.c + src/gnuk.h + src/main.c + src/neug.c + src/openpgp-do.c + src/openpgp.c + src/openpgp.h src/pin-cir.c src/pin-dial.c src/pin-dnd.c - src/usb_msc.c - src/usb_msc.h - src/neug.c + src/random.c + src/sys.c + src/usb-icc.c + src/usb-msc.c + src/usb-msc.h + src/usb_ctrl.c + src/usb_desc.c + src/usb_lld.c + src/usb_lld.h * and others. diff --git a/ChangeLog b/ChangeLog index 4ab7881..d2f01a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-06-06 Niibe Yutaka + * Version 0.19. + + * src/usb_desc.c (gnukStringSerial): Updated. + * regnual/regnual.c (fetch): Better implementation. 2012-06-05 Niibe Yutaka diff --git a/NEWS b/NEWS index ba2d202..17aeb84 100644 --- a/NEWS +++ b/NEWS @@ -2,15 +2,28 @@ Gnuk NEWS - User visible changes * Major changes in Gnuk 0.19 - Released 2012-06-XX, by NIIBE Yutaka - -** System service blocks at the beginning of flash ROM. - -** USB strings for revision detail, configure options, and system service. + Released 2012-06-06, by NIIBE Yutaka ** Firmware upgrade feature +Firmware upgrade is now possible after the public key authentication +using EXTERNAL AUTHENTICATE command of ISO 7816. Firmware upgrade is +done together with reGNUal, the firmware upgrade program. + +** System service blocks at the beginning of flash ROM. +Once flash ROM is protected, first 4-KiB cannot be modified. Gnuk +use this area for "system service". Note that this area will not +be able to be modified by firmware upgrade (or by any method). ** New tool: gnuk_upgrade.py +The tool gnuk_upgrade.py is to do public key authentication using +gpg-agent and send reGNUal to Gnuk. Then, we put new Gnuk binary +into the device with reGNUal. + +** USB strings for revision detail, configure options, and system service. +USB strings now have more information. There are revision detail +string, configure options string, system service version string, as +well as vendor string and product string. These strings could be +examined to check Gnuk Token. * Major changes in Gnuk 0.18 diff --git a/README b/README index b0627b7..695217a 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - software for GnuPG USB Token - Version 0.18 - 2012-05-15 + Version 0.19 + 2012-06-06 Niibe Yutaka Free Software Initiative of Japan @@ -106,16 +106,16 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: "GPG Password Agent" and "SSH Key Agent". Qc: Do you know a good SWD debugger to connect FST-01 or something? -Ac: Perhaps, you can use a part of STM32F4 Discovery Kit as SWD - debugger. It seems that there is a free software tool for that. +Ac: STLink v2 is cheap one. See http://code.google.com/p/arm-utilities/ + for a control program. Release notes ============= -This is nineteenth release of Gnuk. In this release, the usage of USB -device ID by FSIJ is clarified. While it works well for specific -usages and it is considered stable, it is still somewhat experimental. +This is twentieth release of Gnuk. In this release, firmware upgrade +feature is added. While it is daily use, some features (including +firmware upgrade) are still considered experimental. Tested features are: @@ -157,7 +157,7 @@ With DfuSe support, CQ STARM, STBee, and STBee Mini are also our targets. But those targets with DfuSe are basically not for normal use but for experiments, because it would be impossible for DfuSe to disable read from flash. For real use, please consider killing DfuSe -and enable read protection using JTAG debugger. +and enabling read protection using JTAG debugger. I think that it could run on Olimex STM32-P103, or other boards with STM32F103. Besides, we are porting it to STM32 Primer 2. @@ -174,15 +174,17 @@ Another PIN-pad support is connecting rotary encoder, push switch and 7-segment LED display. Both of PIN verification and PIN modification are supported for this circuit extension. -Recently, "DnDpinentry" support is added. This is using usual file +Also, there is "DnDpinentry" support. This is using usual file manager for pinentry. User does "drag and drop" folders and it will be pin entry. This feature doesn't require any additional hardware. See doc/settings-for-DnDpinentry for your desktop configuration. +However, this will be removed in future version, as it found it's +not that useful. -Note that you need pinpad support for GnuPG, it's currently in the -master branch of GnuPG git repository at git.gnupg.org, and it's under -evaluation. When it will be considered stable, it will be put onto -stable branch. +Note that you need pinpad support for GnuPG to use PIN-pad enabled +Gnuk. The pinpad support for GnuPG is currently in the master branch +of GnuPG git repository at git.gnupg.org, and it's under evaluation. +When it will be considered stable, it will be put onto stable branch. Souce code @@ -203,7 +205,7 @@ Please read relevant licenses for external source code, too. 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 +should be able to access everything on the Token, regardless of its protections. Private keys, and other information should be protected properly. @@ -620,6 +622,12 @@ You can observe the traffic of USB using "usbmon". See the file: linux/Documentation/usb/usbmon.txt +Firmware update +=============== + +See doc/firmware-update. + + Read-only Git Repository ======================== diff --git a/src/usb_desc.c b/src/usb_desc.c index a7c1af6..9cb5406 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -262,7 +262,7 @@ const uint8_t gnukStringSerial[] = { USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ /* FSIJ-0.19 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '0', 0, '.', 0, '1', 0, '8', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '1', 0, '9', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From 2db7875da7d83bfd844234a9fccca60b17a0f016 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 7 Jun 2012 10:39:48 +0900 Subject: [PATCH 166/300] polarssl change --- ChangeLog | 12 ++++++++++++ README | 7 +++++++ polarssl-0.14.0/include/polarssl/bignum.h | 4 ++-- polarssl-0.14.0/include/polarssl/rsa.h | 4 ++-- polarssl-0.14.0/library/bignum.c | 8 ++++---- polarssl-0.14.0/library/rsa.c | 8 +++++--- 6 files changed, 32 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2f01a1..30fb049 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2012-06-07 Niibe Yutaka + + PolarSSL modification. + * polarssl-0.14.0/library/rsa.c (rsa_gen_key): Don't set D, DP, + DQ, and QP. It's only for key generation. + * polarssl-0.14.0/library/rsa.c (rsa_gen_key, rsa_pkcs1_encrypt): + Change f_rng function return type. + * polarssl-0.14.0/include/polarssl/rsa.h: Likewise. + * polarssl-0.14.0/library/bignum.c (mpi_is_prime, mpi_gen_prime): + Change f_rng function return type. + * polarssl-0.14.0/include/polarssl/bignum.h: Likewise. + 2012-06-06 Niibe Yutaka * Version 0.19. diff --git a/README b/README index 695217a..8ff5925 100644 --- a/README +++ b/README @@ -230,6 +230,13 @@ Gnuk is distributed with external source code. The file include/polarssl/bn_mul.h is heavily modified for ARM Cortex-M3. + The files include/polarssl/rsa.h, library/rsa.c, + include/polarssl/bignum.h, and library/bignum.c are modified so that + f_rng function returns unsigned char. + + The file library/rsa.c is modified so that it only computes things + needed for Gnuk. + The file library/aes.c is modified so that some constants can go to .sys section. diff --git a/polarssl-0.14.0/include/polarssl/bignum.h b/polarssl-0.14.0/include/polarssl/bignum.h index 80399a2..6070332 100644 --- a/polarssl-0.14.0/include/polarssl/bignum.h +++ b/polarssl-0.14.0/include/polarssl/bignum.h @@ -501,7 +501,7 @@ int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); * 1 if memory allocation failed, * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime */ -int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ); +int mpi_is_prime( mpi *X, unsigned char (*f_rng)(void *), void *p_rng ); /** * \brief Prime number generation @@ -517,7 +517,7 @@ int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ); * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 */ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, - int (*f_rng)(void *), void *p_rng ); + unsigned char (*f_rng)(void *), void *p_rng ); /** * \brief Checkup routine diff --git a/polarssl-0.14.0/include/polarssl/rsa.h b/polarssl-0.14.0/include/polarssl/rsa.h index 0e1f46a..c0569b4 100644 --- a/polarssl-0.14.0/include/polarssl/rsa.h +++ b/polarssl-0.14.0/include/polarssl/rsa.h @@ -183,7 +183,7 @@ void rsa_init( rsa_context *ctx, * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code */ int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *), + unsigned char (*f_rng)(void *), void *p_rng, int nbits, int exponent ); @@ -258,7 +258,7 @@ int rsa_private( rsa_context *ctx, * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *), + unsigned char (*f_rng)(void *), void *p_rng, int mode, int ilen, const unsigned char *input, diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index cb1b7eb..5ef7351 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -1693,7 +1693,7 @@ static const int small_prime[] = /* * Miller-Rabin primality test (HAC 4.24) */ -int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ) +int mpi_is_prime( mpi *X, unsigned char (*f_rng)(void *), void *p_rng ) { int ret, i, j, n, s, xs; mpi W, R, T, A, RR; @@ -1755,7 +1755,7 @@ int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng ) p = (unsigned char *) A.p; for( j = 0; j < A.n * ciL; j++ ) - *p++ = (unsigned char) f_rng( p_rng ); + *p++ = f_rng( p_rng ); j = mpi_msb( &A ) - mpi_msb( &W ); MPI_CHK( mpi_shift_r( &A, j + 1 ) ); @@ -1809,7 +1809,7 @@ cleanup: * Prime number generation */ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, - int (*f_rng)(void *), void *p_rng ) + unsigned char (*f_rng)(void *), void *p_rng ) { int ret, k, n; unsigned char *p; @@ -1827,7 +1827,7 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, p = (unsigned char *) X->p; for( k = 0; k < X->n * ciL; k++ ) - *p++ = (unsigned char) f_rng( p_rng ); + *p++ = f_rng( p_rng ); k = mpi_msb( X ); if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); diff --git a/polarssl-0.14.0/library/rsa.c b/polarssl-0.14.0/library/rsa.c index 54a219b..943ef84 100644 --- a/polarssl-0.14.0/library/rsa.c +++ b/polarssl-0.14.0/library/rsa.c @@ -58,7 +58,7 @@ void rsa_init( rsa_context *ctx, * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *), + unsigned char (*f_rng)(void *), void *p_rng, int nbits, int exponent ) { @@ -101,6 +101,7 @@ int rsa_gen_key( rsa_context *ctx, } while( mpi_cmp_int( &G, 1 ) != 0 ); +#if 0 /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) @@ -111,6 +112,7 @@ int rsa_gen_key( rsa_context *ctx, MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); +#endif ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; @@ -295,7 +297,7 @@ cleanup: * Add the message padding, then do an RSA operation */ int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *), + unsigned char (*f_rng)(void *), void *p_rng, int mode, int ilen, const unsigned char *input, @@ -323,7 +325,7 @@ int rsa_pkcs1_encrypt( rsa_context *ctx, int rng_dl = 100; do { - *p = (unsigned char) f_rng( p_rng ); + *p = f_rng( p_rng ); } while( *p == 0 && --rng_dl ); // Check if RNG failed to generate data From 39a3cb8b0993e37da78aac1c692698c863095d58 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 7 Jun 2012 10:48:25 +0900 Subject: [PATCH 167/300] implement key generation --- ChangeLog | 10 ++++ README | 16 +++---- src/call-rsa.c | 34 +++++++++++++- src/gnuk.h | 4 ++ src/openpgp-do.c | 120 +++++++++++++++++++++++++++++++++++++++++------ src/openpgp.c | 7 ++- src/random.c | 27 +++++++++++ 7 files changed, 191 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 30fb049..ae9ca35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2012-06-07 Niibe Yutaka + Implement key generation. + * src/openpgp.c (cmd_pgp_gakp): Call gpg_do_keygen. + * src/openpgp-do.c (proc_key_import): Call with modulus = NULL. + (gpg_do_keygen): New function. + (gpg_reset_digital_signature_counter): New function. + (gpg_do_write_prvkey): New argument MODULUS. Call + gpg_reset_digital_signature_counter. + * src/call-rsa.c (rsa_genkey): New function. + * src/random.c (random_byte): New function. + PolarSSL modification. * polarssl-0.14.0/library/rsa.c (rsa_gen_key): Don't set D, DP, DQ, and QP. It's only for key generation. diff --git a/README b/README index 8ff5925..2424da6 100644 --- a/README +++ b/README @@ -135,6 +135,7 @@ Tested features are: * Card holder certificate * Removal of keys (Overriding key import is not supported, but you can remove all keys to import again). + * Key generation on device side It is known not-working well: @@ -142,10 +143,6 @@ It is known not-working well: work well. Please make sure to disable DEBUG option if it doesn't work well. -Not supported feature(s): - - * Key generation on device side - Targets ======= @@ -566,9 +563,12 @@ command is: Note that the factory setting of user password is "123456" and admin password is "12345678" as the specification. -No, Gnuk doesn't support key generation. You need to create your -keys on your computer, and import them to Gnuk Token. After you create -your keys (they must be 2048-bit RSA), you can import them. +It is recommended to create your keys on your computer, and import +them to Gnuk Token. After you create your keys (they must be 2048-bit +RSA), you can import them. + +Gnuk supports key generation, but this feature is young and should be +considered experimental. For detail, please see doc/DEMO and doc/DEMO-2. @@ -577,7 +577,7 @@ you can import the keys (again) to (possibly another) Gnuk Token. In this case, you can use GnuPG's option to specify the home directory by --homedir. -After creating keys by: +After creating keys on your computer by: $ gpg --gen-key ... diff --git a/src/call-rsa.c b/src/call-rsa.c index fc5dc48..2f2a887 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -1,7 +1,7 @@ /* * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -211,3 +211,35 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) return 0; } } + +#define RSA_EXPONENT 0x10001 + +const uint8_t * +rsa_genkey (void) +{ + int r; + uint8_t index = 0; + uint8_t *p_q_modulus = (uint8_t *)malloc (KEY_CONTENT_LEN*2); + uint8_t *p = p_q_modulus; + uint8_t *q = p_q_modulus + KEY_CONTENT_LEN/2; + uint8_t *modulus = p_q_modulus + KEY_CONTENT_LEN; + + if (p_q_modulus == NULL) + return NULL; + + rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); + r = rsa_gen_key (&rsa_ctx, random_byte, &index, + KEY_CONTENT_LEN * 8, RSA_EXPONENT); + if (r < 0) + { + free (p_q_modulus); + rsa_free (&rsa_ctx); + return NULL; + } + + mpi_write_binary (&rsa_ctx.P, p, KEY_CONTENT_LEN/2); + mpi_write_binary (&rsa_ctx.Q, q, KEY_CONTENT_LEN/2); + mpi_write_binary (&rsa_ctx.N, modulus, KEY_CONTENT_LEN); + rsa_free (&rsa_ctx); + return p_q_modulus; +} diff --git a/src/gnuk.h b/src/gnuk.h index 1488bd0..7b637d8 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -120,6 +120,7 @@ extern void gpg_data_copy (const uint8_t *p); extern void gpg_do_get_data (uint16_t tag, int with_tag); extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len); extern void gpg_do_public_key (uint8_t kk_byte); +extern void gpg_do_keygen (uint8_t kk_byte); extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno); @@ -234,6 +235,7 @@ extern void modulus_free (const uint8_t *); extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *); extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *signature); +extern const uint8_t *rsa_genkey (void); extern const uint8_t *gpg_do_read_simple (uint8_t); extern void gpg_do_write_simple (uint8_t, const uint8_t *, int); @@ -327,6 +329,8 @@ extern const uint8_t *random_bytes_get (void); extern void random_bytes_free (const uint8_t *); /* 4-byte salt */ extern uint32_t get_salt (void); +/* iterator returning a byta at a time */ +extern uint8_t random_byte (void *arg); extern uint32_t hardclock (void); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 5849f6f..8f797db 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1,7 +1,7 @@ /* * openpgp-do.c -- OpenPGP card Data Objects (DO) handling * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -163,6 +163,17 @@ gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc) } } +static void +gpg_reset_digital_signature_counter (void) +{ + if (digital_signature_counter != 0) + { + flash_put_data (NR_COUNTER_DS); + flash_put_data (NR_COUNTER_DS_LSB); + digital_signature_counter = 0; + } +} + void gpg_increment_digital_signature_counter (void) { @@ -673,12 +684,11 @@ static int8_t num_prv_keys; static int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, - const uint8_t *keystring_admin) + const uint8_t *keystring_admin, const uint8_t *modulus) { uint8_t nr = get_do_ptr_nr_for_kk (kk); const uint8_t *p; int r; - const uint8_t *modulus; struct prvkey_data *pd; uint8_t *key_addr; const uint8_t *dek; @@ -686,10 +696,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, const uint8_t *ks_pw1; const uint8_t *ks_rc; struct key_data_internal kdi; - -#if 0 - assert (key_len == KEY_CONTENT_LEN); -#endif + int modulus_allocated_here = 0; DEBUG_INFO ("Key import\r\n"); DEBUG_SHORT (key_len); @@ -698,15 +705,23 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, /* No replace support, you need to remove it first. */ return -1; + if (key_len != KEY_CONTENT_LEN) + return -1; + pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data)); if (pd == NULL) return -1; - modulus = modulus_calc (key_data, key_len); if (modulus == NULL) { - free (pd); - return -1; + modulus = modulus_calc (key_data, key_len); + if (modulus == NULL) + { + free (pd); + return -1; + } + + modulus_allocated_here = 1; } DEBUG_INFO ("Getting keystore address...\r\n"); @@ -714,7 +729,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (key_addr == NULL) { free (pd); - modulus_free (modulus); + if (modulus_allocated_here) + modulus_free (modulus); return -1; } @@ -736,7 +752,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, encrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal)); r = flash_key_write (key_addr, kdi.data, modulus); - modulus_free (modulus); + if (modulus_allocated_here) + modulus_free (modulus); if (r < 0) { @@ -749,7 +766,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, memcpy (pd->crm_encrypted, (uint8_t *)&kdi.check, ADDITIONAL_DATA_SIZE); if (kk == GPG_KEY_FOR_SIGNING) - ac_reset_pso_cds (); + { + ac_reset_pso_cds (); + gpg_reset_digital_signature_counter (); + } else ac_reset_other (); @@ -908,7 +928,7 @@ proc_key_import (const uint8_t *data, int len) /* It should starts with 00 01 00 01 (E) */ /* Skip E, 4-byte */ - r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin); + r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL); if (r < 0) return 0; else @@ -1460,3 +1480,75 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size) else *do_data_p = NULL; } + +void +gpg_do_keygen (uint8_t kk_byte) +{ + enum kind_of_key kk; + const uint8_t *keystring_admin; + const uint8_t *p_q_modulus; + const uint8_t *p_q; + const uint8_t *modulus; + int r; + + DEBUG_INFO ("Keygen\r\n"); + DEBUG_BYTE (kk_byte); + + if (kk_byte == 0xb6) + kk = GPG_KEY_FOR_SIGNING; + else if (kk_byte == 0xb8) + kk = GPG_KEY_FOR_DECRYPTION; + else /* 0xa4 */ + kk = GPG_KEY_FOR_AUTHENTICATION; + + if (admin_authorized == BY_ADMIN) + keystring_admin = keystring_md_pw3; + else + keystring_admin = NULL; + + p_q_modulus = rsa_genkey (); + if (p_q_modulus == NULL) + { + GPG_MEMORY_FAILURE (); + return; + } + + p_q = p_q_modulus; + modulus = p_q_modulus + KEY_CONTENT_LEN; + + r = gpg_do_write_prvkey (kk, p_q, KEY_CONTENT_LEN, + keystring_admin, modulus); + free ((uint8_t *)p_q_modulus); + if (r < 0) + { + GPG_ERROR (); + return; + } + + DEBUG_INFO ("Calling gpg_do_public_key...\r\n"); + + if (kk == GPG_KEY_FOR_SIGNING) + { + /* Authintication has been reset within gpg_do_write_prvkey. */ + /* But GnuPG expects it's ready for signing. */ + /* Thus, we call verify_pso_cds here. */ + const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); + const uint8_t *pw; + int pw_len; + + if (ks_pw1) + { + pw = ks_pw1+1; + pw_len = ks_pw1[0]; + } + else + { + pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; + pw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + } + + verify_pso_cds (pw, pw_len); + } + + gpg_do_public_key (kk_byte); +} diff --git a/src/openpgp.c b/src/openpgp.c index f7e225a..c5013af 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -480,12 +480,11 @@ cmd_pgp_gakp (void) /* Get public key */ gpg_do_public_key (apdu.cmd_apdu_data[0]); else - { /* Generate key pair */ + { if (!ac_check_status (AC_ADMIN_AUTHORIZED)) GPG_SECURITY_FAILURE (); - - /* XXX: Not yet supported */ - GPG_ERROR (); + /* Generate key pair */ + gpg_do_keygen (apdu.cmd_apdu_data[0]); } } diff --git a/src/random.c b/src/random.c index 95299f6..8fb06bc 100644 --- a/src/random.c +++ b/src/random.c @@ -70,3 +70,30 @@ get_salt (void) { return neug_get (NEUG_KICK_FILLING); } + + +/* + * Rundom byte iterator + */ +uint8_t +random_byte (void *arg) +{ + uint8_t *index_p = (uint8_t *)arg; + uint8_t index = *index_p; + uint8_t *p = ((uint8_t *)random_word) + index; + uint8_t v; + + neug_wait_full (); + + v = *p; + + if (++index >= RANDOM_BYTES_LENGTH) + { + index = 0; + neug_flush (); + } + + *index_p = index; + + return v; +} From ee743ca042a374730479a1df43633c816854c2b4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 7 Jun 2012 13:59:13 +0900 Subject: [PATCH 168/300] internal authenticate input check --- ChangeLog | 3 +++ src/openpgp.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index ae9ca35..1469014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-06-07 Niibe Yutaka + * src/openpgp.c (cmd_internal_authenticate): Add check for input + length. + Implement key generation. * src/openpgp.c (cmd_pgp_gakp): Call gpg_do_keygen. * src/openpgp-do.c (proc_key_import): Call with modulus = NULL. diff --git a/src/openpgp.c b/src/openpgp.c index c5013af..a46e95e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -744,6 +744,8 @@ cmd_pso (void) DEBUG_INFO ("PSO done.\r\n"); } + +#define MAX_DIGEST_INFO_LEN 102 /* 40% */ static void cmd_internal_authenticate (void) { @@ -763,6 +765,13 @@ cmd_internal_authenticate (void) return; } + if (len > MAX_DIGEST_INFO_LEN) + { + DEBUG_INFO ("input is too long."); + GPG_CONDITION_NOT_SATISFIED (); + return; + } + r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_AUTHENTICATION]); if (r < 0) From 3fa01ef7a98d12544b416f9338d401a8ad4e7da6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 7 Jun 2012 15:29:49 +0900 Subject: [PATCH 169/300] improve bignum --- polarssl-0.14.0/library/bignum.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index 5ef7351..05606ed 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -1813,13 +1813,10 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, { int ret, k, n; unsigned char *p; - mpi Y; if( nbits < 3 ) return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - mpi_init( &Y, NULL ); - n = BITS_TO_LIMBS( nbits ); MPI_CHK( mpi_grow( X, n ) ); @@ -1840,13 +1837,16 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) { if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; + break; MPI_CHK( mpi_add_int( X, X, 2 ) ); } } else { + mpi Y; + mpi_init( &Y, NULL ); + MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); MPI_CHK( mpi_shift_r( &Y, 1 ) ); @@ -1858,22 +1858,20 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, break; if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; + break; } if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; + break; MPI_CHK( mpi_add_int( &Y, X, 1 ) ); MPI_CHK( mpi_add_int( X, X, 2 ) ); MPI_CHK( mpi_shift_r( &Y, 1 ) ); } + + mpi_free( &Y, NULL ); } -cleanup: - - mpi_free( &Y, NULL ); - return( ret ); } From 17fd82ffa1fbfb4e052ba40e54c5c8450feee3d4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 7 Jun 2012 15:37:40 +0900 Subject: [PATCH 170/300] Revert "improve bignum" This reverts commit 3fa01ef7a98d12544b416f9338d401a8ad4e7da6. --- polarssl-0.14.0/library/bignum.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index 05606ed..5ef7351 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -1813,10 +1813,13 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, { int ret, k, n; unsigned char *p; + mpi Y; if( nbits < 3 ) return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + mpi_init( &Y, NULL ); + n = BITS_TO_LIMBS( nbits ); MPI_CHK( mpi_grow( X, n ) ); @@ -1837,16 +1840,13 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) { if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - break; + goto cleanup; MPI_CHK( mpi_add_int( X, X, 2 ) ); } } else { - mpi Y; - mpi_init( &Y, NULL ); - MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); MPI_CHK( mpi_shift_r( &Y, 1 ) ); @@ -1858,20 +1858,22 @@ int mpi_gen_prime( mpi *X, int nbits, int dh_flag, break; if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - break; + goto cleanup; } if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - break; + goto cleanup; MPI_CHK( mpi_add_int( &Y, X, 1 ) ); MPI_CHK( mpi_add_int( X, X, 2 ) ); MPI_CHK( mpi_shift_r( &Y, 1 ) ); } - - mpi_free( &Y, NULL ); } +cleanup: + + mpi_free( &Y, NULL ); + return( ret ); } From 258552e5443bedbee1d51ec78a5ea76e5b8a9daf Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 8 Jun 2012 09:48:40 +0900 Subject: [PATCH 171/300] Emit LED light --- ChangeLog | 11 +++++++++++ src/gnuk.h | 2 +- src/main.c | 31 +++++++++++++------------------ src/openpgp-do.c | 2 ++ src/openpgp.c | 8 +++++++- src/usb-icc.c | 1 + 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1469014..02ed6dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-06-08 Niibe Yutaka + + Emit LED light while computation (or asking user input). + * src/usb-icc.c (icc_handle_timeout): Call led_blink. + * src/openpgp.c (cmd_pso, cmd_internal_authenticate): Call + LED_WAIT_MODE, LED_STATUS_MODE to show "it's under computation". + * src/openpgp-do.c (gpg_do_keygen): Ditto. + * src/gnuk.h (LED_WAIT_MODE): Rename (was: LED_INPUT_MODE). + * src/main.c (display_interaction): Change the behavior of LED, + now, it's mostly ON (was: mostly OFF). + 2012-06-07 Niibe Yutaka * src/openpgp.c (cmd_internal_authenticate): Add check for input diff --git a/src/gnuk.h b/src/gnuk.h index 7b637d8..cebb700 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -367,7 +367,7 @@ extern const uint8_t gnukStringSerial[]; #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_WAIT_MODE ((eventmask_t)16) #define LED_FATAL_MODE ((eventmask_t)32) extern Thread *main_thread; extern void led_blink (int spec); diff --git a/src/main.c b/src/main.c index 33fe8e8..1ebf12f 100644 --- a/src/main.c +++ b/src/main.c @@ -210,14 +210,14 @@ 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 +#define GNUK_INIT 0 +#define GNUK_RUNNING 1 +#define GNUK_WAIT 2 +#define GNUK_FATAL 255 /* * 0 for initializing * 1 for normal mode - * 2 for input waiting + * 2 for input waiting / under calculation * 255 for fatal */ static uint8_t main_mode; @@ -226,10 +226,11 @@ static void display_interaction (void) { eventmask_t m; + set_led (1); while (1) { m = chEvtWaitOne (ALL_EVENTS); - set_led (1); + set_led (0); switch (m) { case LED_ONESHOT_SHORT: @@ -239,24 +240,21 @@ static void display_interaction (void) chThdSleep (MS2ST (400)); break; case LED_TWOSHOT: - chThdSleep (MS2ST (50)); - set_led (0); chThdSleep (MS2ST (50)); set_led (1); chThdSleep (MS2ST (50)); + set_led (0); + 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); + set_led (1); } } @@ -434,11 +432,8 @@ main (int argc, char *argv[]) case LED_FATAL_MODE: main_mode = GNUK_FATAL; break; - case LED_INPUT_MODE: - main_mode = GNUK_INPUT_WAIT; - set_led (1); - chThdSleep (MS2ST (400)); - set_led (0); + case LED_WAIT_MODE: + main_mode = GNUK_WAIT; break; default: break; @@ -455,7 +450,7 @@ main (int argc, char *argv[]) set_led (0); chThdSleep (LED_TIMEOUT_STOP * 3); break; - case GNUK_INPUT_WAIT: + case GNUK_WAIT: display_interaction (); break; case GNUK_RUNNING: diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 8f797db..43088f6 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1506,7 +1506,9 @@ gpg_do_keygen (uint8_t kk_byte) else keystring_admin = NULL; + chEvtSignal (main_thread, LED_WAIT_MODE); p_q_modulus = rsa_genkey (); + chEvtSignal (main_thread, LED_STATUS_MODE); if (p_q_modulus == NULL) { GPG_MEMORY_FAILURE (); diff --git a/src/openpgp.c b/src/openpgp.c index a46e95e..9fad156 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -118,7 +118,7 @@ get_pinpad_input (int msg_code) { int r; - chEvtSignal (main_thread, LED_INPUT_MODE); + chEvtSignal (main_thread, LED_WAIT_MODE); r = pinpad_getline (msg_code, MS2ST (8000)); chEvtSignal (main_thread, LED_STATUS_MODE); return r; @@ -701,8 +701,10 @@ cmd_pso (void) DEBUG_SHORT (len); DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN); + chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_SIGNING]); + chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) { ac_reset_pso_cds (); @@ -727,8 +729,10 @@ cmd_pso (void) /* Skip padding 0x00 */ len--; + chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, &kd[GPG_KEY_FOR_DECRYPTION]); + chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) GPG_ERROR (); } @@ -772,8 +776,10 @@ cmd_internal_authenticate (void) return; } + chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_AUTHENTICATION]); + chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) GPG_ERROR (); } diff --git a/src/usb-icc.c b/src/usb-icc.c index 67b04e5..bb04104 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -1260,6 +1260,7 @@ icc_handle_timeout (struct ccid *c) { case ICC_STATE_EXECUTE: icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT); + led_blink (2); break; default: break; From ec0297050a3e45ce444c64a25ae195d18854dbdf Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 8 Jun 2012 11:01:05 +0900 Subject: [PATCH 172/300] polarssl bugfix --- ChangeLog | 3 +++ polarssl-0.14.0/library/bignum.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 02ed6dc..cbdb996 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-06-08 Niibe Yutaka + * polarssl-0.14.0/library/bignum.c (mpi_cmp_mpi): Bug fix. + Though it doesn't matter for Gnuk usage. + Emit LED light while computation (or asking user input). * src/usb-icc.c (icc_handle_timeout): Call led_blink. * src/openpgp.c (cmd_pso, cmd_internal_authenticate): Call diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index 5ef7351..d71c8ea 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -649,7 +649,7 @@ int mpi_cmp_mpi( const mpi *X, const mpi *Y ) return( 0 ); if( i > j ) return( X->s ); - if( j > i ) return( -X->s ); + if( j > i ) return( -Y->s ); if( X->s > 0 && Y->s < 0 ) return( 1 ); if( Y->s > 0 && X->s < 0 ) return( -1 ); From 956e89d10a7d3efd8bf43ce30eb31e385584132d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 13 Jun 2012 09:07:26 +0900 Subject: [PATCH 173/300] keygen is configure option --- ChangeLog | 13 +++++++++++++ NEWS | 9 +++++++++ polarssl-0.14.0/include/polarssl/config.h | 2 ++ polarssl-0.14.0/library/bignum.c | 4 ++-- src/Makefile.in | 2 +- src/call-rsa.c | 2 ++ src/configure | 20 ++++++++++++++++++-- src/openpgp-do.c | 2 ++ src/openpgp.c | 4 ++++ src/random.c | 4 +++- 10 files changed, 56 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbdb996..a0930ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-06-13 Niibe Yutaka + + Key generation is configure option. + * src/configure (keygen): Add --enable-keygen option. + * src/Makefile.in (UDEFS): Add definition of KEYGEN_SUPPORT. + * src/call-rsa.c [KEYGEN_SUPPORT] (rsa_genkey): Conditionalize. + * src/random.c [KEYGEN_SUPPORT] (random_byte): Ditto. + * src/openpgp.c [KEYGEN_SUPPORT] (cmd_pgp_gakp): Ditto. + * src/openpgp-do.c [KEYGEN_SUPPORT] (gpg_do_keygen): Ditto. + * polarssl-0.14.0/include/polarssl/config.h: Ditto. + * polarssl-0.14.0/library/bignum.c [POLARSSL_GENPRIME] + (mpi_inv_mod): Unconditionalize. + 2012-06-08 Niibe Yutaka * polarssl-0.14.0/library/bignum.c (mpi_cmp_mpi): Bug fix. diff --git a/NEWS b/NEWS index 17aeb84..992df93 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,14 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk XXXX + + Released 2012-XX-XX, by NIIBE Yutaka + +** Key generation feature added +Finally, key generation is supported. Note that it is very slow. It +will takes a few minutes to generate two keys. + + * Major changes in Gnuk 0.19 Released 2012-06-06, by NIIBE Yutaka diff --git a/polarssl-0.14.0/include/polarssl/config.h b/polarssl-0.14.0/include/polarssl/config.h index 6c9b61b..880054b 100644 --- a/polarssl-0.14.0/include/polarssl/config.h +++ b/polarssl-0.14.0/include/polarssl/config.h @@ -86,10 +86,12 @@ */ #define POLARSSL_VERSION_C +#ifdef KEYGEN_SUPPORT /* * Enable the prime-number generation code. */ #define POLARSSL_GENPRIME +#endif /* * Uncomment this macro to store the AES tables in ROM. diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index d71c8ea..cf39845 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -1570,8 +1570,6 @@ cleanup: return( ret ); } -#if defined(POLARSSL_GENPRIME) - /* * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) */ @@ -1665,6 +1663,8 @@ cleanup: return( ret ); } +#if defined(POLARSSL_GENPRIME) + static const int small_prime[] = { 3, 5, 7, 11, 13, 17, 19, 23, diff --git a/src/Makefile.in b/src/Makefile.in index d896426..3f73460 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -175,7 +175,7 @@ DLIBS = # # List all user C define here, like -D_DEBUG=1 -UDEFS = +UDEFS = @KEYGEN_SUPPORT@ # Define ASM defines here UADEFS = diff --git a/src/call-rsa.c b/src/call-rsa.c index 2f2a887..e64f356 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -214,6 +214,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) #define RSA_EXPONENT 0x10001 +#ifdef KEYGEN_SUPPORT const uint8_t * rsa_genkey (void) { @@ -243,3 +244,4 @@ rsa_genkey (void) rsa_free (&rsa_ctx); return p_q_modulus; } +#endif diff --git a/src/configure b/src/configure index 80796c7..a15b449 100755 --- a/src/configure +++ b/src/configure @@ -28,6 +28,7 @@ with_dfu=default debug=no pinpad=no certdo=no +keygen=no # Process each option for option; do @@ -59,6 +60,10 @@ for option; do certdo=yes ;; --disable-certdo) certdo=no ;; + --enable-keygen) + keygen=yes ;; + --disable-keygen) + keygen=no ;; --with-dfu) with_dfu=yes ;; --without-dfu) @@ -93,6 +98,7 @@ Configuration: --enable-pinpad={dnd,cir,dial} PIN entry support [no] --enable-certdo support CERT.3 data object [no] + --enable-keygen support key generation [no] --with-dfu build image for DFU [] EOF exit 0 @@ -188,11 +194,20 @@ if test "$certdo" = "yes"; then echo "CERT.3 Data Object is supported" else CERTDO_DEFINE="#undef CERTDO_SUPPORT" - echo "CERT.3 Data Object is not supported" + echo "CERT.3 Data Object is NOT supported" +fi + +# --enable-keygen option +if test "$keygen" = "yes"; then + KEYGEN_SUPPORT="-DKEYGEN_SUPPORT" + echo "Key generation on device is supported" +else + KEYGEN_SUPPORT="" + echo "Key generation on device is NOT supported" fi REVISION=`git describe --dirty="-modified"` -CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo" +CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:keygen=$keygen" if !(IFS=" " while read VIDPID VERSION PRODUCT VENDOR; do @@ -242,6 +257,7 @@ fi sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \ -e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \ -e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \ + -e "s%@KEYGEN_SUPPORT@%$KEYGEN_SUPPORT%" \ < Makefile.in > Makefile if test "$certdo" = "yes"; then sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \ diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 43088f6..348bc04 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1481,6 +1481,7 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size) *do_data_p = NULL; } +#ifdef KEYGEN_SUPPORT void gpg_do_keygen (uint8_t kk_byte) { @@ -1554,3 +1555,4 @@ gpg_do_keygen (uint8_t kk_byte) gpg_do_public_key (kk_byte); } +#endif diff --git a/src/openpgp.c b/src/openpgp.c index 9fad156..e6605aa 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -483,8 +483,12 @@ cmd_pgp_gakp (void) { if (!ac_check_status (AC_ADMIN_AUTHORIZED)) GPG_SECURITY_FAILURE (); +#ifdef KEYGEN_SUPPORT /* Generate key pair */ gpg_do_keygen (apdu.cmd_apdu_data[0]); +#else + GPG_FUNCTION_NOT_SUPPORTED (); +#endif } } diff --git a/src/random.c b/src/random.c index 8fb06bc..a2d5a79 100644 --- a/src/random.c +++ b/src/random.c @@ -72,8 +72,9 @@ get_salt (void) } +#ifdef KEYGEN_SUPPORT /* - * Rundom byte iterator + * Random byte iterator */ uint8_t random_byte (void *arg) @@ -97,3 +98,4 @@ random_byte (void *arg) return v; } +#endif From 81f8f94dd45808be70791964f70a172697884ffe Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 13 Jun 2012 15:12:10 +0900 Subject: [PATCH 174/300] bug fix for LED display --- ChangeLog | 2 ++ src/main.c | 1 + 2 files changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index a0930ad..bfa1b96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-06-13 Niibe Yutaka + * src/main.c (display_interaction): Assign to main_mode. + Key generation is configure option. * src/configure (keygen): Add --enable-keygen option. * src/Makefile.in (UDEFS): Add definition of KEYGEN_SUPPORT. diff --git a/src/main.c b/src/main.c index 1ebf12f..1bd2e99 100644 --- a/src/main.c +++ b/src/main.c @@ -247,6 +247,7 @@ static void display_interaction (void) chThdSleep (MS2ST (50)); break; case LED_STATUS_MODE: + main_mode = GNUK_RUNNING; return; case LED_FATAL_MODE: main_mode = GNUK_FATAL; From 670e9058f17135e81b548f036ebac100b5e86831 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 14 Jun 2012 08:46:59 +0900 Subject: [PATCH 175/300] SHA256 --- ChangeLog | 15 ++++ NEWS | 5 ++ README | 10 ++- src/ac.c | 25 +++--- src/crypt.mk | 4 +- src/gnuk.h | 2 +- src/openpgp-do.c | 8 +- src/openpgp.c | 18 ++-- src/sha256.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++ src/sha256.h | 14 +++ 10 files changed, 292 insertions(+), 32 deletions(-) create mode 100644 src/sha256.c create mode 100644 src/sha256.h diff --git a/ChangeLog b/ChangeLog index bfa1b96..69c78d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,21 @@ +2012-06-14 Niibe Yutaka + + KDF is now SHA-256 (was: SHA1). + * src/sha256.c: New file. Based on the implementation by Dr Brian + Gladman. + * src/openpgp.c (cmd_change_password, cmd_reset_user_password): + Use sha256. + * src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey): Likewise. + * src/ac.c (verify_user_0, calc_md, verify_admin): Likewise. + * src/crypt.mk (CRYPTSRC): Add sha256.c, removing sha1.c. + * src/gnuk.h (KEYSTRING_MD_SIZE): It's 32 for SHA-256. + 2012-06-13 Niibe Yutaka + Bug fixes. * src/main.c (display_interaction): Assign to main_mode. + * src/openpgp.c (cmd_change_password): Bug fix for admin less mode + to admin full mode. Variable who_old should be admin_authorized. Key generation is configure option. * src/configure (keygen): Add --enable-keygen option. diff --git a/NEWS b/NEWS index 992df93..971e952 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,11 @@ Gnuk NEWS - User visible changes Finally, key generation is supported. Note that it is very slow. It will takes a few minutes to generate two keys. +** KDF (Key Derivation Function) is now SHA-256 +Data encryption key for private keys are computed by KDF (Key +Derivation Function, sometimes also is refered as string to key +function, S2K). It was SHA1 before, but it is replaced by SHA-256. + * Major changes in Gnuk 0.19 diff --git a/README b/README index 2424da6..3d5bc90 100644 --- a/README +++ b/README @@ -189,6 +189,11 @@ Souce code Gnuk source code is under src/ directory. +Note that SHA-2 hash function implementation, src/sha256.c, is based +on the original implementation by Dr. Brian Gladman. See: + + http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php + License ======= @@ -197,7 +202,7 @@ It is distributed under GNU General Public Licence version 3 or later (GPLv3+). Please see src/COPYING. Please note that it is distributed with external source code too. -Please read relevant licenses for external source code, too. +Please read relevant licenses for external source code as well. 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 @@ -221,8 +226,7 @@ Gnuk is distributed with external source code. * polarssl-0.14.0/ -- PolarSSL 0.14.0 Taken from http://polarssl.org/ - We use PolarSSL for RSA computation, AES encryption/decryption - and SHA-1 computation. + We use PolarSSL for RSA computation, AES encryption/decryption. The file include/polarssl/bn_mul.h is heavily modified for ARM Cortex-M3. diff --git a/src/ac.c b/src/ac.c index 87e09ba..2e530a0 100644 --- a/src/ac.c +++ b/src/ac.c @@ -24,9 +24,7 @@ #include "config.h" #include "ch.h" #include "gnuk.h" - -#include "polarssl/config.h" -#include "polarssl/sha1.h" +#include "sha256.h" uint8_t volatile auth_status; /* Initialized to AC_NONE_AUTHORIZED */ @@ -89,7 +87,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known, } success_one_step: - sha1 (pw, pw_len, keystring); + sha256 (pw, pw_len, keystring); if (access == AC_PSO_CDS_AUTHORIZED) { r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); @@ -161,28 +159,27 @@ static void calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len, uint8_t md[KEYSTRING_MD_SIZE]) { - sha1_context sha1_ctx; + sha256_context sha256_ctx; - sha1_starts (&sha1_ctx); + sha256_start (&sha256_ctx); while (count > pw_len + 8) { - sha1_update (&sha1_ctx, salt, 8); - sha1_update (&sha1_ctx, pw, pw_len); + sha256_update (&sha256_ctx, salt, 8); + sha256_update (&sha256_ctx, pw, pw_len); count -= pw_len + 8; } if (count <= 8) - sha1_update (&sha1_ctx, salt, count); + sha256_update (&sha256_ctx, salt, count); else { - sha1_update (&sha1_ctx, salt, 8); + sha256_update (&sha256_ctx, salt, 8); count -= 8; - sha1_update (&sha1_ctx, pw, count); + sha256_update (&sha256_ctx, pw, count); } - sha1_finish (&sha1_ctx, md); - memset (&sha1_ctx, 0, sizeof (sha1_ctx)); + sha256_finish (&sha256_ctx, md); } uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE]; @@ -283,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len) if (r <= 0) return r; - sha1 (pw, pw_len, keystring_md_pw3); + sha256 (pw, pw_len, keystring_md_pw3); auth_status |= AC_ADMIN_AUTHORIZED; return 1; } diff --git a/src/crypt.mk b/src/crypt.mk index f0b7ea5..e9c530d 100644 --- a/src/crypt.mk +++ b/src/crypt.mk @@ -1,6 +1,6 @@ CRYPTDIR = ../polarssl-0.14.0 CRYPTSRCDIR = $(CRYPTDIR)/library CRYPTINCDIR = $(CRYPTDIR)/include -CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \ +CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \ $(CRYPTSRCDIR)/aes.c \ - call-rsa.c + sha256.c call-rsa.c diff --git a/src/gnuk.h b/src/gnuk.h index cebb700..30cb99e 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -198,7 +198,7 @@ extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const ui #define KEYSTRING_PASSLEN_SIZE 1 #define KEYSTRING_SALT_SIZE 8 /* optional */ #define KEYSTRING_ITER_SIZE 1 /* optional */ -#define KEYSTRING_MD_SIZE 20 +#define KEYSTRING_MD_SIZE 32 #define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE) #define KEYSTRING_SIZE_RC (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE) #define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \ diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 348bc04..c333234 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -28,10 +28,10 @@ #include "sys.h" #include "gnuk.h" #include "openpgp.h" +#include "sha256.h" #include "polarssl/config.h" #include "polarssl/aes.h" -#include "polarssl/sha1.h" #define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */ static const uint8_t *pw_err_counter_p[3]; @@ -543,7 +543,7 @@ proc_resetting_code (const uint8_t *data, int len) newpw_len = len; newpw = data; - sha1 (newpw, newpw_len, new_ks); + sha256 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); if (r <= -2) @@ -780,8 +780,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); - sha1 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, - strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); + sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, + strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE); } diff --git a/src/openpgp.c b/src/openpgp.c index e6605aa..2fa8f0a 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -27,8 +27,7 @@ #include "gnuk.h" #include "sys.h" #include "openpgp.h" -#include "polarssl/config.h" -#include "polarssl/sha1.h" +#include "sha256.h" #define CLS(a) a.cmd_apdu_head[0] #define INS(a) a.cmd_apdu_head[1] @@ -225,6 +224,7 @@ cmd_change_password (void) const uint8_t *newpw; int pw_len, newpw_len; int who = p2 - 0x80; + int who_old; int r; DEBUG_INFO ("Change PW\r\n"); @@ -244,6 +244,7 @@ cmd_change_password (void) const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1); + who_old = who; if (pw_len < 0) { @@ -284,14 +285,15 @@ cmd_change_password (void) newpw = pw + pw_len; newpw_len = len - pw_len; gpg_set_pw3 (newpw, newpw_len); + who_old = admin_authorized; } } - sha1 (pw, pw_len, old_ks); - sha1 (newpw, newpw_len, new_ks); + sha256 (pw, pw_len, old_ks); + sha256 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; - r = gpg_change_keystring (who, old_ks, who, new_ks); + r = gpg_change_keystring (who_old, old_ks, who, new_ks); if (r <= -2) { DEBUG_INFO ("memory error.\r\n"); @@ -366,8 +368,8 @@ cmd_reset_user_password (void) pw_len = ks_rc[0]; newpw = pw + pw_len; newpw_len = len - pw_len; - sha1 (pw, pw_len, old_ks); - sha1 (newpw, newpw_len, new_ks); + sha256 (pw, pw_len, old_ks); + sha256 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks); if (r <= -2) @@ -418,7 +420,7 @@ cmd_reset_user_password (void) newpw_len = len; newpw = pw; - sha1 (newpw, newpw_len, new_ks); + sha256 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks); if (r <= -2) diff --git a/src/sha256.c b/src/sha256.c new file mode 100644 index 0000000..d896296 --- /dev/null +++ b/src/sha256.c @@ -0,0 +1,223 @@ +/* + * sha256.c -- Compute SHA-256 hash + * + * Just for little endian architecture. + * + * Code taken from: + * http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php + * + * File names are sha2.c, sha2.h, brg_types.h, brg_endian.h + * in the archive sha2-07-01-07.zip. + * + * Code is modified in the style of PolarSSL API. + * + * See original copyright notice below. + */ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 +*/ + +#include +#include +#include "sha256.h" + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 +#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) + +static void bswap32_buf (uint32_t *p, int n) +{ + while (n--) + p[n] = __builtin_bswap32 (p[n]); /* bswap32 is GCC extention */ +} + +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +/* round transforms for SHA256 compression functions */ +#define vf(n,i) v[(n - i) & 7] + +#define hf(i) (p[i & 15] += \ + g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) + +#define v_cycle(i,j) \ + vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ + + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ + vf(3,i) += vf(7,i); \ + vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)) + +#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) +#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) +#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) +#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) +#define k_0 k256 + +const uint32_t k256[64] = { + 0X428A2F98, 0X71374491, 0XB5C0FBCF, 0XE9B5DBA5, + 0X3956C25B, 0X59F111F1, 0X923F82A4, 0XAB1C5ED5, + 0XD807AA98, 0X12835B01, 0X243185BE, 0X550C7DC3, + 0X72BE5D74, 0X80DEB1FE, 0X9BDC06A7, 0XC19BF174, + 0XE49B69C1, 0XEFBE4786, 0X0FC19DC6, 0X240CA1CC, + 0X2DE92C6F, 0X4A7484AA, 0X5CB0A9DC, 0X76F988DA, + 0X983E5152, 0XA831C66D, 0XB00327C8, 0XBF597FC7, + 0XC6E00BF3, 0XD5A79147, 0X06CA6351, 0X14292967, + 0X27B70A85, 0X2E1B2138, 0X4D2C6DFC, 0X53380D13, + 0X650A7354, 0X766A0ABB, 0X81C2C92E, 0X92722C85, + 0XA2BFE8A1, 0XA81A664B, 0XC24B8B70, 0XC76C51A3, + 0XD192E819, 0XD6990624, 0XF40E3585, 0X106AA070, + 0X19A4C116, 0X1E376C08, 0X2748774C, 0X34B0BCB5, + 0X391C0CB3, 0X4ED8AA4A, 0X5B9CCA4F, 0X682E6FF3, + 0X748F82EE, 0X78A5636F, 0X84C87814, 0X8CC70208, + 0X90BEFFFA, 0XA4506CEB, 0XBEF9A3F7, 0XC67178F2, +}; + +void +sha256_process (sha256_context *ctx) +{ + uint32_t i; + uint32_t *p = ctx->wbuf; + uint32_t v[8]; + + memcpy (v, ctx->state, 8 * sizeof (uint32_t)); + + for (i = 0; i < 64; i += 16) + { + v_cycle ( 0, i); + v_cycle ( 1, i); + v_cycle ( 2, i); + v_cycle ( 3, i); + v_cycle ( 4, i); + v_cycle ( 5, i); + v_cycle ( 6, i); + v_cycle ( 7, i); + v_cycle ( 8, i); + v_cycle ( 9, i); + v_cycle (10, i); + v_cycle (11, i); + v_cycle (12, i); + v_cycle (13, i); + v_cycle (14, i); + v_cycle (15, i); + } + + ctx->state[0] += v[0]; + ctx->state[1] += v[1]; + ctx->state[2] += v[2]; + ctx->state[3] += v[3]; + ctx->state[4] += v[4]; + ctx->state[5] += v[5]; + ctx->state[6] += v[6]; + ctx->state[7] += v[7]; +} + +void +sha256_update (sha256_context *ctx, const unsigned char *input, + unsigned int ilen) +{ + uint32_t left = (ctx->total[0] & SHA256_MASK); + uint32_t fill = SHA256_BLOCK_SIZE - left; + + ctx->total[0] += ilen; + if (ctx->total[0] < ilen) + ctx->total[1]++; + + while (ilen >= fill) + { + memcpy (((unsigned char*)ctx->wbuf) + left, input, fill); + bswap32_buf (ctx->wbuf, SHA256_BLOCK_SIZE >> 2); + sha256_process (ctx); + input += fill; + ilen -= fill; + left = 0; + fill = SHA256_BLOCK_SIZE; + } + + memcpy (((unsigned char*)ctx->wbuf) + left, input, ilen); +} + +void +sha256_finish (sha256_context *ctx, unsigned char output[32]) +{ + uint32_t last = (ctx->total[0] & SHA256_MASK); + + bswap32_buf (ctx->wbuf, (last + 3) >> 2); + + ctx->wbuf[last >> 2] &= 0xffffff80 << (8 * (~last & 3)); + ctx->wbuf[last >> 2] |= 0x00000080 << (8 * (~last & 3)); + + if (last > SHA256_BLOCK_SIZE - 9) + { + if (last < 60) + ctx->wbuf[15] = 0; + sha256_process (ctx); + last = 0; + } + else + last = (last >> 2) + 1; + + while (last < 14) + ctx->wbuf[last++] = 0; + + ctx->wbuf[14] = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + ctx->wbuf[15] = ctx->total[0] << 3; + sha256_process (ctx); + + bswap32_buf (ctx->state, SHA256_DIGEST_SIZE >> 2); + memcpy (output, ctx->state, SHA256_DIGEST_SIZE); +} + +const uint32_t initial_state[8] = +{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +void +sha256_start (sha256_context *ctx) +{ + ctx->total[0] = ctx->total[1] = 0; + memcpy (ctx->state, initial_state, 8 * sizeof(uint32_t)); +} + +void +sha256 (const unsigned char *input, unsigned int ilen, + unsigned char output[32]) +{ + sha256_context ctx; + + sha256_start (&ctx); + sha256_update (&ctx, input, ilen); + sha256_finish (&ctx, output); + + memset (&ctx, 0, sizeof (sha256_context)); +} diff --git a/src/sha256.h b/src/sha256.h new file mode 100644 index 0000000..d52fb77 --- /dev/null +++ b/src/sha256.h @@ -0,0 +1,14 @@ +typedef struct +{ + uint32_t total[2]; + uint32_t state[8]; + uint32_t wbuf[16]; +} sha256_context; + +extern void sha256 (const unsigned char *input, unsigned int ilen, + unsigned char output[32]); +extern void sha256_start (sha256_context *ctx); +extern void sha256_finish (sha256_context *ctx, unsigned char output[32]); +extern void sha256_update (sha256_context *ctx, const unsigned char *input, + unsigned int ilen); +extern void sha256_process (sha256_context *ctx); From a2855c9442c771a2b70328ed853a67f6791b21f8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 14 Jun 2012 08:53:05 +0900 Subject: [PATCH 176/300] use mpi_lset instead of mpi_read_string --- ChangeLog | 5 +++++ polarssl-0.14.0/library/bignum.c | 2 +- src/call-rsa.c | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69c78d4..bd16ada 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2012-06-14 Niibe Yutaka + * src/call-rsa.c (rsa_sign, rsa_decrypt, rsa_verify): Use + mpi_lset (was: mpi_read_string). + * polarssl-0.14.0/library/bignum.c (mpi_get_digit) + (mpi_read_string): ifdef-out. + KDF is now SHA-256 (was: SHA1). * src/sha256.c: New file. Based on the implementation by Dr Brian Gladman. diff --git a/polarssl-0.14.0/library/bignum.c b/polarssl-0.14.0/library/bignum.c index cf39845..dbe85d8 100644 --- a/polarssl-0.14.0/library/bignum.c +++ b/polarssl-0.14.0/library/bignum.c @@ -225,6 +225,7 @@ int mpi_size( const mpi *X ) return( ( mpi_msb( X ) + 7 ) >> 3 ); } +#if 0 /* * Convert an ASCII character to digit value */ @@ -310,7 +311,6 @@ cleanup: return( ret ); } -#if 0 /* * Helper to write the digits high-order first */ diff --git a/src/call-rsa.c b/src/call-rsa.c index e64f356..13fa819 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -47,7 +47,7 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = KEY_CONTENT_LEN; - mpi_read_string (&rsa_ctx.E, 16, "10001"); + mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], 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); @@ -138,7 +138,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, rsa_ctx.len = msg_len; DEBUG_WORD (msg_len); - mpi_read_string (&rsa_ctx.E, 16, "10001"); + mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], KEY_CONTENT_LEN / 2); @@ -191,7 +191,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = KEY_CONTENT_LEN; - mpi_read_string (&rsa_ctx.E, 16, "10001"); + mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN); DEBUG_INFO ("RSA verify..."); From a5d77ec5af3bb72763cf00f83255f74580b9d73c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 14 Jun 2012 09:13:59 +0900 Subject: [PATCH 177/300] protection improvement (1): different S2K for PW1 and Reset-code --- ChangeLog | 6 ++++++ NEWS | 4 ++++ src/gnuk.h | 3 +++ src/openpgp-do.c | 2 +- src/openpgp.c | 19 ++++++++++++++++++- src/sha256.c | 3 +-- 6 files changed, 33 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd16ada..20f4403 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2012-06-14 Niibe Yutaka + * src/openpgp.c (resetcode_s2k): New. + (cmd_reset_user_password): Use resetcode_s2k. + * src/openpgp-do.c (proc_resetting_code): Likewise. + + * src/sha256.c (sha256_finish): Clear out CTX at the end. + * src/call-rsa.c (rsa_sign, rsa_decrypt, rsa_verify): Use mpi_lset (was: mpi_read_string). * polarssl-0.14.0/library/bignum.c (mpi_get_digit) diff --git a/NEWS b/NEWS index 971e952..6b6a4e8 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ Data encryption key for private keys are computed by KDF (Key Derivation Function, sometimes also is refered as string to key function, S2K). It was SHA1 before, but it is replaced by SHA-256. +** Protection improvement (even when data is disclosed) +Even if PW1 and Reset-code is same, content of encripted DEK is +different now. + * Major changes in Gnuk 0.19 diff --git a/src/gnuk.h b/src/gnuk.h index 30cb99e..c0fed78 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -193,6 +193,9 @@ struct prvkey_data { #define BY_RESETCODE 2 #define BY_ADMIN 3 +extern void resetcode_s2k (const unsigned char *input, unsigned int ilen, + unsigned char output[32]); + extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const uint8_t *modulus); #define KEYSTRING_PASSLEN_SIZE 1 diff --git a/src/openpgp-do.c b/src/openpgp-do.c index c333234..07c564a 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -543,7 +543,7 @@ proc_resetting_code (const uint8_t *data, int len) newpw_len = len; newpw = data; - sha256 (newpw, newpw_len, new_ks); + resetcode_s2k (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); if (r <= -2) diff --git a/src/openpgp.c b/src/openpgp.c index 2fa8f0a..43c089c 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -328,6 +328,23 @@ cmd_change_password (void) } } + +#define RESETCODE_S2K_MAGIC "\xffRESET\r\n" + +void +resetcode_s2k (const unsigned char *input, unsigned int ilen, + unsigned char output[32]) +{ + sha256_context ctx; + + sha256_start (&ctx); + sha256_update (&ctx, input, ilen); + sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC, + sizeof (RESETCODE_S2K_MAGIC)); + sha256_finish (&ctx, output); +} + + static void cmd_reset_user_password (void) { @@ -368,7 +385,7 @@ cmd_reset_user_password (void) pw_len = ks_rc[0]; newpw = pw + pw_len; newpw_len = len - pw_len; - sha256 (pw, pw_len, old_ks); + resetcode_s2k (pw, pw_len, old_ks); sha256 (newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks); diff --git a/src/sha256.c b/src/sha256.c index d896296..a91abe4 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -194,6 +194,7 @@ sha256_finish (sha256_context *ctx, unsigned char output[32]) bswap32_buf (ctx->state, SHA256_DIGEST_SIZE >> 2); memcpy (output, ctx->state, SHA256_DIGEST_SIZE); + memset (&ctx, 0, sizeof (sha256_context)); } const uint32_t initial_state[8] = @@ -218,6 +219,4 @@ sha256 (const unsigned char *input, unsigned int ilen, sha256_start (&ctx); sha256_update (&ctx, input, ilen); sha256_finish (&ctx, output); - - memset (&ctx, 0, sizeof (sha256_context)); } From 2e5973e7cc18025036c42f9eb6098010d52eb00f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 14 Jun 2012 16:00:07 +0900 Subject: [PATCH 178/300] fix clearing CTX --- src/sha256.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sha256.c b/src/sha256.c index a91abe4..a3f17ed 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -194,7 +194,7 @@ sha256_finish (sha256_context *ctx, unsigned char output[32]) bswap32_buf (ctx->state, SHA256_DIGEST_SIZE >> 2); memcpy (output, ctx->state, SHA256_DIGEST_SIZE); - memset (&ctx, 0, sizeof (sha256_context)); + memset (ctx, 0, sizeof (sha256_context)); } const uint32_t initial_state[8] = From 94a65f0d996da2384ec146a1d4b4feb8934c1cf2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2012 08:55:09 +0900 Subject: [PATCH 179/300] Deprecate DnD --- ChangeLog | 5 +++++ src/configure | 10 +--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20f4403..d7c39a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ +2012-06-15 Niibe Yutaka + + * src/configure (--enable-pinpad): Deprecate DND. + 2012-06-14 Niibe Yutaka + Protection improvement. * src/openpgp.c (resetcode_s2k): New. (cmd_reset_user_password): Use resetcode_s2k. * src/openpgp-do.c (proc_resetting_code): Likewise. diff --git a/src/configure b/src/configure index a15b449..6252c61 100755 --- a/src/configure +++ b/src/configure @@ -50,8 +50,6 @@ for option; do debug=yes ;; --disable-debug) debug=no ;; - --enable-pinpad) - pinpad=yes ;; --enable-pinpad=*) pinpad=$optarg ;; --disable-pinpad) @@ -95,7 +93,7 @@ Configuration: STBEE FST_01 --enable-debug debug with virtual COM port [no] - --enable-pinpad={dnd,cir,dial} + --enable-pinpad={cir,dial} PIN entry support [no] --enable-certdo support CERT.3 data object [no] --enable-keygen support key generation [no] @@ -175,12 +173,6 @@ if test "$pinpad" = "no"; then PINPAD_DEFINE="#undef PINPAD_SUPPORT" PINPAD_MORE_DEFINE="" echo "PIN pad option disabled" -elif test "$pinpad" = "yes"; then - pinpad=dnd - PINPAD_MAKE_OPTION="ENABLE_PINPAD=dnd" - PINPAD_DEFINE="#define PINPAD_SUPPORT 1" - PINPAD_MORE_DEFINE="#define PINPAD_DND_SUPPORT 1" - echo "PIN pad option enabled (dnd)" else PINPAD_MAKE_OPTION="ENABLE_PINPAD=$pinpad" PINPAD_DEFINE="#define PINPAD_SUPPORT 1" From 2d5246e7fa26b82eeff8787ac281b97ed27b13f6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2012 08:56:57 +0900 Subject: [PATCH 180/300] protection improvements (2): Use ECB for DEK encryption, use IV, etc. --- ChangeLog | 18 ++++ NEWS | 21 +++-- polarssl-0.14.0/include/polarssl/aes.h | 2 + polarssl-0.14.0/library/aes.c | 2 + src/gnuk.h | 21 +++-- src/openpgp-do.c | 117 +++++++++++++++---------- src/random.c | 8 +- 7 files changed, 122 insertions(+), 67 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7c39a2..6fe635d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2012-06-15 Niibe Yutaka + More protection improvements. + * src/random.c (RANDOM_BYTES_LENGTH): It's 32 now (was: 16). + * src/gnuk.h (struct key_data_internal): Remove check, random, + magic. Add checksum. + (struct prvkey_data): Remove crm_encrypted. Add iv and + checksum_encrypted. + * src/openpgp-do.c (encrypt, decrypt): Add IV argument. + (encrypt_dek, decrypt_dek): New. It's in ECB mode. + (compute_key_data_checksum): New. + (gpg_do_load_prvkey): Handle initial vector and checksum. + Use decrypt_dek to decrypt DEK. Clear DEK after use. + (calc_check32):Remove. + (gpg_do_write_prvkey): Use encrypt_dek to encrypt DEK. + (gpg_do_chks_prvkey): Likewise. + + * polarssl-0.14.0/include/polarssl/aes.h (aes_crypt_cbc) + * polarssl-0.14.0/library/aes.c (aes_crypt_cbc): ifdef-out. + * src/configure (--enable-pinpad): Deprecate DND. 2012-06-14 Niibe Yutaka diff --git a/NEWS b/NEWS index 6b6a4e8..21b3f0b 100644 --- a/NEWS +++ b/NEWS @@ -6,16 +6,23 @@ Gnuk NEWS - User visible changes ** Key generation feature added Finally, key generation is supported. Note that it is very slow. It -will takes a few minutes to generate two keys. +will take a few minutes (or more) to generate two or three keys, when +you are unlucky. + +** DnD pinentry support is deprecated +Once, DnD pinentry was considered a great feature, but it found that +it is difficult to remember moves of folders. ** KDF (Key Derivation Function) is now SHA-256 -Data encryption key for private keys are computed by KDF (Key -Derivation Function, sometimes also is refered as string to key -function, S2K). It was SHA1 before, but it is replaced by SHA-256. +Keystring is now computed by SHA-256 (it was SHA1 before). -** Protection improvement (even when data is disclosed) -Even if PW1 and Reset-code is same, content of encripted DEK is -different now. +** Protection improvements (even when internal data is disclosed) +Three improvements. (1) Even if PW1 and Reset-code is same, content +of encripted DEK is different now. (2) DEK is now encrypted and +decrypted by keystring in ECB mode (it was just a kind of xor by +single block CFB mode). (3) Key data plus checksum are encrypted in +CFB mode with initial vector (it will be able to switch OCB mode +easily). * Major changes in Gnuk 0.19 diff --git a/polarssl-0.14.0/include/polarssl/aes.h b/polarssl-0.14.0/include/polarssl/aes.h index 5576680..04d47ab 100644 --- a/polarssl-0.14.0/include/polarssl/aes.h +++ b/polarssl-0.14.0/include/polarssl/aes.h @@ -83,6 +83,7 @@ int aes_crypt_ecb( aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); +#if 0 /** * \brief AES-CBC buffer encryption/decryption * Length should be a multiple of the block @@ -103,6 +104,7 @@ int aes_crypt_cbc( aes_context *ctx, unsigned char iv[16], const unsigned char *input, unsigned char *output ); +#endif /** * \brief AES-CFB128 buffer encryption/decryption. diff --git a/polarssl-0.14.0/library/aes.c b/polarssl-0.14.0/library/aes.c index ea4904c..58c1fb1 100644 --- a/polarssl-0.14.0/library/aes.c +++ b/polarssl-0.14.0/library/aes.c @@ -753,6 +753,7 @@ int aes_crypt_ecb( aes_context *ctx, return( 0 ); } +#if 0 /* * AES-CBC buffer encryption/decryption */ @@ -816,6 +817,7 @@ int aes_crypt_cbc( aes_context *ctx, return( 0 ); } +#endif /* * AES-CFB128 buffer encryption/decryption diff --git a/src/gnuk.h b/src/gnuk.h index c0fed78..76559ca 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -156,9 +156,9 @@ extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t le extern uint8_t ch_certificate_start; extern uint8_t random_bits_start; -#define KEY_MAGIC_LEN 8 #define KEY_CONTENT_LEN 256 /* p and q */ -#define GNUK_MAGIC "Gnuk KEY" +#define INITIAL_VECTOR_SIZE 16 +#define DATA_ENCRYPTION_KEY_SIZE 16 /* encrypted data content */ struct key_data { @@ -167,22 +167,21 @@ struct key_data { struct key_data_internal { uint8_t data[KEY_CONTENT_LEN]; /* p and q */ - uint32_t check; - uint32_t random; - char magic[KEY_MAGIC_LEN]; + uint8_t checksum[DATA_ENCRYPTION_KEY_SIZE]; }; -#define ADDITIONAL_DATA_SIZE 16 -#define DATA_ENCRYPTION_KEY_SIZE 16 struct prvkey_data { const uint8_t *key_addr; /* - * CRM: [C]heck, [R]andom, and [M]agic in struct key_data_internal - * + * IV: Initial Vector */ - uint8_t crm_encrypted[ADDITIONAL_DATA_SIZE]; + uint8_t iv[INITIAL_VECTOR_SIZE]; /* - * DEK: Data Encryption Key + * Checksum + */ + uint8_t checksum_encrypted[DATA_ENCRYPTION_KEY_SIZE]; + /* + * DEK (Data Encryption Key) encrypted */ uint8_t dek_encrypted_1[DATA_ENCRYPTION_KEY_SIZE]; /* For user */ uint8_t dek_encrypted_2[DATA_ENCRYPTION_KEY_SIZE]; /* For resetcode */ diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 07c564a..300b50f 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -572,40 +572,58 @@ proc_resetting_code (const uint8_t *data, int len) } static void -encrypt (const uint8_t *key_str, uint8_t *data, int len) +encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { aes_context aes; - uint8_t iv[16]; + uint8_t iv0[INITIAL_VECTOR_SIZE]; int iv_offset; DEBUG_INFO ("ENC\r\n"); DEBUG_BINARY (data, len); - aes_setkey_enc (&aes, key_str, 128); - memset (iv, 0, 16); + aes_setkey_enc (&aes, key, 128); + memcpy (iv0, iv, INITIAL_VECTOR_SIZE); iv_offset = 0; - aes_crypt_cfb128 (&aes, AES_ENCRYPT, len, &iv_offset, iv, data, data); + aes_crypt_cfb128 (&aes, AES_ENCRYPT, len, &iv_offset, iv0, data, data); } /* Signing, Decryption, and Authentication */ struct key_data kd[3]; static void -decrypt (const uint8_t *key_str, uint8_t *data, int len) +decrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { aes_context aes; - uint8_t iv[16]; + uint8_t iv0[INITIAL_VECTOR_SIZE]; int iv_offset; - aes_setkey_enc (&aes, key_str, 128); - memset (iv, 0, 16); + aes_setkey_enc (&aes, key, 128); /* This is setkey_enc, because of CFB. */ + memcpy (iv0, iv, INITIAL_VECTOR_SIZE); iv_offset = 0; - aes_crypt_cfb128 (&aes, AES_DECRYPT, len, &iv_offset, iv, data, data); + aes_crypt_cfb128 (&aes, AES_DECRYPT, len, &iv_offset, iv0, data, data); DEBUG_INFO ("DEC\r\n"); DEBUG_BINARY (data, len); } +static void +encrypt_dek (const uint8_t *key_string, uint8_t *dek) +{ + aes_context aes; + + aes_setkey_enc (&aes, key_string, 128); + aes_crypt_ecb (&aes, AES_ENCRYPT, dek, dek); +} + +static void +decrypt_dek (const uint8_t *key_string, uint8_t *dek) +{ + aes_context aes; + + aes_setkey_dec (&aes, key_string, 128); + aes_crypt_ecb (&aes, AES_DECRYPT, dek, dek); +} + static uint8_t get_do_ptr_nr_for_kk (enum kind_of_key kk) { @@ -627,6 +645,25 @@ gpg_do_clear_prvkey (enum kind_of_key kk) memset ((void *)&kd[kk], 0, sizeof (struct key_data)); } + +static int +compute_key_data_checksum (struct key_data_internal *kdi, int check_or_calc) +{ + unsigned int i; + uint32_t d[4] = { 0, 0, 0, 0 }; + + for (i = 0; i < KEY_CONTENT_LEN / sizeof (uint32_t); i++) + d[i&3] ^= *(uint32_t *)(&kdi->data[i*4]); + + if (check_or_calc == 0) /* store */ + { + memcpy (kdi->checksum, d, DATA_ENCRYPTION_KEY_SIZE); + return 0; + } + else /* check */ + return memcmp (kdi->checksum, d, DATA_ENCRYPTION_KEY_SIZE) == 0; +} + /* * Return 1 on success, * 0 if none, @@ -637,8 +674,9 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring) { uint8_t nr = get_do_ptr_nr_for_kk (kk); const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__]; - uint8_t *key_addr; + const uint8_t *key_addr; uint8_t dek[DATA_ENCRYPTION_KEY_SIZE]; + const uint8_t *iv; struct key_data_internal kdi; DEBUG_INFO ("Loading private key: "); @@ -647,38 +685,27 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring) if (do_data == NULL) return 0; - key_addr = *(uint8_t **)&(do_data)[1]; + key_addr = *(const uint8_t **)&(do_data)[1]; /* Possible unaligned access */ memcpy (kdi.data, key_addr, KEY_CONTENT_LEN); - memcpy (((uint8_t *)&kdi.check), do_data+5, ADDITIONAL_DATA_SIZE); + iv = do_data+5; + memcpy (kdi.checksum, iv + INITIAL_VECTOR_SIZE, DATA_ENCRYPTION_KEY_SIZE); - memcpy (dek, do_data+5+16*who, DATA_ENCRYPTION_KEY_SIZE); - decrypt (keystring, dek, DATA_ENCRYPTION_KEY_SIZE); + memcpy (dek, do_data+5+16*(who+1), DATA_ENCRYPTION_KEY_SIZE); + decrypt_dek (keystring, dek); - decrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal)); - if (memcmp (kdi.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0) + decrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal)); + memset (dek, 0, DATA_ENCRYPTION_KEY_SIZE); + if (!compute_key_data_checksum (&kdi, 1)) { DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n"); return -1; } - /* more sanity check??? */ memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN); DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN); return 1; } -static uint32_t -calc_check32 (const uint8_t *p, int len) -{ - uint32_t check = 0; - uint32_t *data = (uint32_t *)p; - int i; - - for (i = 0; i < len/4; i++) - check += data[i]; - - return check; -} static int8_t num_prv_keys; @@ -691,7 +718,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, int r; struct prvkey_data *pd; uint8_t *key_addr; - const uint8_t *dek; + const uint8_t *dek, *iv; const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__]; const uint8_t *ks_pw1; const uint8_t *ks_rc; @@ -738,18 +765,17 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, DEBUG_WORD ((uint32_t)key_addr); memcpy (kdi.data, key_data, KEY_CONTENT_LEN); - kdi.check = calc_check32 (key_data, KEY_CONTENT_LEN); - kdi.random = get_salt (); - memcpy (kdi.magic, GNUK_MAGIC, KEY_MAGIC_LEN); + compute_key_data_checksum (&kdi, 0); - dek = random_bytes_get (); /* 16-byte random bytes */ + dek = random_bytes_get (); /* 32-byte random bytes */ + iv = dek + DATA_ENCRYPTION_KEY_SIZE; memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE); memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE); memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE); ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); - encrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal)); + encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal)); r = flash_key_write (key_addr, kdi.data, modulus); if (modulus_allocated_here) @@ -763,7 +789,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, } pd->key_addr = key_addr; - memcpy (pd->crm_encrypted, (uint8_t *)&kdi.check, ADDITIONAL_DATA_SIZE); + memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE); + memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE); if (kk == GPG_KEY_FOR_SIGNING) { @@ -774,7 +801,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, ac_reset_other (); if (ks_pw1) - encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE); + encrypt_dek (ks_pw1+1, pd->dek_encrypted_1); else { uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; @@ -782,16 +809,16 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); - encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE); + encrypt_dek (ks123_pw1+1, pd->dek_encrypted_1); } if (ks_rc) - encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE); + encrypt_dek (ks_rc+1, pd->dek_encrypted_2); else memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); if (keystring_admin) - encrypt (keystring_admin, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE); + encrypt_dek (keystring_admin, pd->dek_encrypted_3); else memset (pd->dek_encrypted_3, 0, DATA_ENCRYPTION_KEY_SIZE); @@ -842,11 +869,11 @@ gpg_do_chks_prvkey (enum kind_of_key kk, return -1; memcpy (pd, &(do_data)[1], sizeof (struct prvkey_data)); - dek_p = ((uint8_t *)pd) + 4 + ADDITIONAL_DATA_SIZE - + DATA_ENCRYPTION_KEY_SIZE * (who_old - 1); + dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE + + DATA_ENCRYPTION_KEY_SIZE * who_old; memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE); - decrypt (old_ks, dek, DATA_ENCRYPTION_KEY_SIZE); - encrypt (new_ks, dek, DATA_ENCRYPTION_KEY_SIZE); + decrypt_dek (old_ks, dek); + encrypt_dek (new_ks, dek); dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE); diff --git a/src/random.c b/src/random.c index a2d5a79..200d471 100644 --- a/src/random.c +++ b/src/random.c @@ -1,7 +1,7 @@ /* * random.c -- get random bytes * - * Copyright (C) 2010, 2011 Free Software Initiative of Japan + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -26,7 +26,7 @@ #include "gnuk.h" #include "neug.h" -#define RANDOM_BYTES_LENGTH 16 +#define RANDOM_BYTES_LENGTH 32 static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)]; void @@ -43,7 +43,7 @@ random_init (void) } /* - * Return pointer to random 16-byte + * Return pointer to random 32-byte */ const uint8_t * random_bytes_get (void) @@ -53,7 +53,7 @@ random_bytes_get (void) } /* - * Free pointer to random 16-byte + * Free pointer to random 32-byte */ void random_bytes_free (const uint8_t *p) From abd64bc49595bc4828cb5a008d046c29a0513e78 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2012 13:26:27 +0900 Subject: [PATCH 181/300] clear random data after free --- ChangeLog | 2 ++ src/random.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6fe635d..da8f277 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-06-15 Niibe Yutaka + * src/random.c (random_bytes_free): Clear out random bytes. + More protection improvements. * src/random.c (RANDOM_BYTES_LENGTH): It's 32 now (was: 16). * src/gnuk.h (struct key_data_internal): Remove check, random, diff --git a/src/random.c b/src/random.c index 200d471..e52d785 100644 --- a/src/random.c +++ b/src/random.c @@ -58,7 +58,7 @@ random_bytes_get (void) void random_bytes_free (const uint8_t *p) { - (void)p; + memset (p, 0, RANDOM_BYTES_LENGTH); neug_flush (); } From fe58e86c6c0abc65a809b4c6611d14818f647758 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2012 13:27:16 +0900 Subject: [PATCH 182/300] 512 --- src/flash.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/flash.c b/src/flash.c index f9aa02c..d8ad658 100644 --- a/src/flash.c +++ b/src/flash.c @@ -55,9 +55,11 @@ * _keystore_pool * 1.5-KiB Key store (512-byte (p, q and N) key-store * 3) */ +#define KEY_SIZE 512 /* P, Q and N */ + #define FLASH_DATA_POOL_HEADER_SIZE 2 #define FLASH_DATA_POOL_SIZE (FLASH_PAGE_SIZE*2) -#define FLASH_KEYSTORE_SIZE (512*3) +#define FLASH_KEYSTORE_SIZE (KEY_SIZE*3) static const uint8_t *data_pool; extern uint8_t _keystore_pool; @@ -96,7 +98,7 @@ flash_init (void) /* Seek empty keystore */ p = &_keystore_pool; while (*p != 0xff || *(p+1) != 0xff) - p += 512; + p += KEY_SIZE; keystore = p; @@ -279,7 +281,7 @@ flash_key_alloc (void) if ((k - &_keystore_pool) >= FLASH_KEYSTORE_SIZE) return NULL; - keystore += 512; + keystore += KEY_SIZE; return k; } From e0282629e3708bc81df705757bfa45ba6b8a9e33 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 15 Jun 2012 13:30:07 +0900 Subject: [PATCH 183/300] fix --- src/gnuk.h | 3 ++- src/random.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gnuk.h b/src/gnuk.h index 76559ca..26762a2 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -135,6 +135,8 @@ 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); extern uint8_t *flash_key_alloc (void); +extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, + const uint8_t *modulus); extern void flash_keystore_release (void); extern void flash_set_data_pool_last (const uint8_t *p); extern void flash_clear_halfword (uint32_t addr); @@ -195,7 +197,6 @@ struct prvkey_data { extern void resetcode_s2k (const unsigned char *input, unsigned int ilen, unsigned char output[32]); -extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const uint8_t *modulus); #define KEYSTRING_PASSLEN_SIZE 1 #define KEYSTRING_SALT_SIZE 8 /* optional */ diff --git a/src/random.c b/src/random.c index e52d785..7f0b7bc 100644 --- a/src/random.c +++ b/src/random.c @@ -58,7 +58,8 @@ random_bytes_get (void) void random_bytes_free (const uint8_t *p) { - memset (p, 0, RANDOM_BYTES_LENGTH); + (void)p; + memset (random_word, 0, RANDOM_BYTES_LENGTH); neug_flush (); } From c61a63dbb675e8c0e508d6db54171263ac1cedcd Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 16 Jun 2012 14:33:22 +0900 Subject: [PATCH 184/300] external authenticate incompatible change to SHA256 --- ChangeLog | 9 +++++++++ NEWS | 11 ++++++++--- doc/firmware-update | 20 ++++++++++++-------- src/call-rsa.c | 2 +- src/openpgp.c | 16 +++++++--------- tool/gnuk_upgrade.py | 25 +++++++++++++------------ 6 files changed, 50 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index da8f277..93848bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-06-16 Niibe Yutaka + + Use SHA256 format for "external authenticate". + * tool/gnuk_upgrade.py (gpg_sign): SHA256 sign by "SCD PKAUTH". + (main): Not specify keygrip, but always use key for authentication. + * src/call-rsa.c (rsa_verify): It is SHA256 format (was: SHA1). + * src/openpgp.c (cmd_get_challenge): Don't add chip-id prefix. + (cmd_external_authenticate): Likewise. + 2012-06-15 Niibe Yutaka * src/random.c (random_bytes_free): Clear out random bytes. diff --git a/NEWS b/NEWS index 21b3f0b..c1c8e4f 100644 --- a/NEWS +++ b/NEWS @@ -5,14 +5,19 @@ Gnuk NEWS - User visible changes Released 2012-XX-XX, by NIIBE Yutaka ** Key generation feature added -Finally, key generation is supported. Note that it is very slow. It -will take a few minutes (or more) to generate two or three keys, when -you are unlucky. +Finally, key generation is supported. Note that it may be very slow. +It will take a few minutes (or more) to generate two or three keys, +when you are unlucky. ** DnD pinentry support is deprecated Once, DnD pinentry was considered a great feature, but it found that it is difficult to remember moves of folders. +** gnuk_upgrade.py assumes using another token for authentication +Use of another token for authentication is assumed now. This is +incompatible change. Note that when you upgrade a token of version +0.19 to 0.20 (or later), you need gnuk_upgrade.py of version 0.19. + ** KDF (Key Derivation Function) is now SHA-256 Keystring is now computed by SHA-256 (it was SHA1 before). diff --git a/doc/firmware-update b/doc/firmware-update index 19b0442..52ff93f 100644 --- a/doc/firmware-update +++ b/doc/firmware-update @@ -8,7 +8,6 @@ Note that updating firmware, all data objects and keys will be removed. There is _no way_ to preserve those data. - Preparation =========== @@ -96,9 +95,9 @@ Then, we can put the data of public key into token by:: Invoking firmware update ======================== -We specify the keygrip to authenticate, reGNUal binary, and Gnuk binary. +We specify reGNUal binary and Gnuk binary. - $ ../tool/gnuk_upgrade.py 5D6C89682D07CCFC034AF508420BF2276D8018ED ../regnual/regnual.bin gnuk.bin + $ ../tool/gnuk_upgrade.py ../regnual/regnual.bin gnuk.bin Two or more tokens @@ -107,9 +106,9 @@ Two or more tokens Currently, GnuPG doesn't support multiple devices connected to the host. -In order to update the firmware of a token TARGET, we use GnuPG to -authenticate with public key. If it is on another token AUTH, it is -somewhat complicated. +In order to update the firmware of a TARGET token, we use GnuPG to +authenticate with public key. It is assumed that you have another +AUTH token for this. This situation is somewhat complicated. What I do is: (1) Don't run PC/SC daemon:: @@ -120,9 +119,14 @@ What I do is: $ killall -9 scdaemon -(3) Connect the token of AUTH, and use it:: +(3) Insert the AUTH token to USB, and use it:: $ gpg --card-status -(4) Connect TARGET, and invoke gnuk_update.py +(4) Insert the TARGET token to USB (after scdaemon communicates AUTH + token), and invoke gnuk_upgrade.py. + In this situation, gnuk_upgrade.py tries to connect one of tokens, + but a connection to the AUTH token will fail because scdaemon is + connecting to that device, and will be expected to connect to the + TARGET token succesufully, instead. -- diff --git a/src/call-rsa.c b/src/call-rsa.c index 13fa819..5ea7854 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -196,7 +196,7 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) DEBUG_INFO ("RSA verify..."); - r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA1, 20, hash, sig); + r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA256, 32, hash, sig); rsa_free (&rsa_ctx); if (r < 0) diff --git a/src/openpgp.c b/src/openpgp.c index 43c089c..89b218b 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -50,7 +50,7 @@ #define INS_PUT_DATA 0xda #define INS_PUT_DATA_ODD 0xdb /* For key import */ -#define CHALLENGE_LEN 16 +#define CHALLENGE_LEN 32 static const uint8_t *challenge; /* Random bytes */ static const uint8_t @@ -938,9 +938,9 @@ cmd_external_authenticate (void) { const uint8_t *pubkey; const uint8_t *signature = apdu.cmd_apdu_data; - uint8_t *hash = apdu.cmd_apdu_data + 256; int len = apdu.cmd_apdu_data_len; uint8_t keyno = P2 (apdu); + int r; DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); @@ -958,13 +958,12 @@ cmd_external_authenticate (void) GPG_CONDITION_NOT_SATISFIED (); return; } - - memcpy (hash, unique_device_id (), 4); - memcpy (hash+4, challenge, CHALLENGE_LEN); + + r = rsa_verify (pubkey, challenge, signature); random_bytes_free (challenge); challenge = NULL; - if (rsa_verify (pubkey, hash, signature) < 0) + if (r < 0) { GPG_SECURITY_FAILURE (); return; @@ -984,9 +983,8 @@ cmd_get_challenge (void) random_bytes_free (challenge); challenge = random_bytes_get (); - memcpy (res_APDU, unique_device_id (), 4); - memcpy (res_APDU+4, challenge, CHALLENGE_LEN); - res_APDU_size = CHALLENGE_LEN + 4; + memcpy (res_APDU, challenge, CHALLENGE_LEN); + res_APDU_size = CHALLENGE_LEN; GPG_SUCCESS (); DEBUG_INFO ("GET CHALLENGE done.\r\n"); } diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index b03cdef..278278d 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -389,11 +389,13 @@ def to_string(t): from subprocess import check_output -def gpg_sign(keygrip, hash): +SHA256_OID_PREFIX="3031300d060960864801650304020105000420" + +def gpg_sign(hash): result = check_output(["gpg-connect-agent", - "SIGKEY %s" % keygrip, - "SETHASH --hash=sha1 %s" % hash, - "PKSIGN", "/bye"]) + "SCD SETDATA " + SHA256_OID_PREFIX + hash, + "SCD PKAUTH OPENPGP.3", + "/bye"]) signed = "" while True: i = result.find('%') @@ -405,8 +407,8 @@ def gpg_sign(keygrip, hash): signed += chr(int(hex_str,16)) result = result[i+3:] - pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26 - signed = signed[pos:-7] + pos = signed.index("D ") + 2 + signed = signed[pos:-4] # \nOK\n if len(signed) != 256: raise ValueError, binascii.hexlify(signed) return signed @@ -418,7 +420,7 @@ def crc32(bytestr): crc = binascii.crc32(bytestr) return UNSIGNED(crc) -def main(keygrip, data_regnual, data_upgrade): +def main(data_regnual, data_upgrade): l = len(data_regnual) if (l & 0x03) != 0: data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) @@ -440,7 +442,7 @@ def main(keygrip, data_regnual, data_upgrade): icc.icc_power_on() icc.cmd_select_openpgp() challenge = icc.cmd_get_challenge() - signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge))) + signed = gpg_sign(binascii.hexlify(to_string(challenge))) icc.cmd_external_authenticate(signed) icc.stop_gnuk() mem_info = icc.mem_info() @@ -477,9 +479,8 @@ def main(keygrip, data_regnual, data_upgrade): if __name__ == '__main__': - keygrip = sys.argv[1] - filename_regnual = sys.argv[2] - filename_upgrade = sys.argv[3] + filename_regnual = sys.argv[1] + filename_upgrade = sys.argv[2] f = open(filename_regnual) data_regnual = f.read() f.close() @@ -488,4 +489,4 @@ if __name__ == '__main__': data_upgrade = f.read() f.close() print "%s: %d" % (filename_upgrade, len(data_upgrade)) - main(keygrip, data_regnual, data_upgrade[4096:]) + main(data_regnual, data_upgrade[4096:]) From de51fc2fd4bfb5ab3e30fc8499de9adcd95be422 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 18 Jun 2012 12:24:54 +0900 Subject: [PATCH 185/300] LED display change --- ChangeLog | 23 ++ NEWS | 7 + src/flash.c | 2 +- src/gnuk.h | 15 +- src/main.c | 276 ++++++++++-------------- src/main.c.~HEAD~ | 519 ++++++++++++++++++++++++++++++++++++++++++++++ src/neug.c | 6 +- src/openpgp-do.c | 6 +- src/openpgp.c | 14 +- src/pin-cir.c | 6 +- src/pin-dial.c | 2 +- src/pin-dnd.c | 4 +- src/sys.c | 2 +- src/usb-icc.c | 3 +- src/usb-msc.c | 4 +- src/usb_ctrl.c | 1 - src/usb_desc.c | 2 +- src/usb_lld.c | 6 +- 18 files changed, 696 insertions(+), 202 deletions(-) create mode 100644 src/main.c.~HEAD~ diff --git a/ChangeLog b/ChangeLog index 93848bd..ee9265d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-06-18 Niibe Yutaka + + LED display output change. + * src/main.c (MAIN_TIMEOUT_INTERVAL): New. + (LED_TIMEOUT_INTERVAL, etc.): New values. + (main_mode, display_interaction): Remove. + (led_inverted, emit_led): New. + (display_status_code): Use emit_led. + (led_blink): Use LED_* for spec. + (main, fatal): New LED display output. + * src/gnuk.h (LED_ONESHOT, LED_TWOSHOTS, LED_SHOW_STATUS) + (LED_START_COMMAND, LED_FINISH_COMMAND, LED_FATAL): New semantics. + (main_thread): Remove. + * src/openpgp-do.c (gpg_do_keygen): Don't touch LED here. + * src/openpgp.c (get_pinpad_input): Call led_blink. + (cmd_pso, cmd_internal_authenticate): Don't touch LED here. + (GPGthread): Call led_blink. + * src/pin-cir.c (pinpad_getline): Change arg of led_blink. + * src/pin-dnd.c (pinpad_getline): Ditto. + * src/usb-icc.c (icc_handle_timeout): Ditto. + (icc_send_status): Call led_blink. + * src/usb_ctrl.c (gnuk_usb_event): Don't touch LED here. + 2012-06-16 Niibe Yutaka Use SHA256 format for "external authenticate". diff --git a/NEWS b/NEWS index c1c8e4f..a1ac945 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,13 @@ Gnuk NEWS - User visible changes Released 2012-XX-XX, by NIIBE Yutaka +** LED display output change +LED display output by Gnuk is now more reactive. It shows status code +when it gets GET_STATUS message of CCID. When you communicate Gnuk by +internal CCID driver of GnuPG (instead of PC/SC), and enable +'debug-disable-ticker' option in .gnupg/scdaemon.conf, it is more +silent now. + ** Key generation feature added Finally, key generation is supported. Note that it may be very slow. It will take a few minutes (or more) to generate two or three keys, diff --git a/src/flash.c b/src/flash.c index d8ad658..0f13b62 100644 --- a/src/flash.c +++ b/src/flash.c @@ -46,7 +46,7 @@ * .data * _bss_start * .bss - * _end + * _end * * ch_certificate_startp * <2048 bytes> diff --git a/src/gnuk.h b/src/gnuk.h index 26762a2..8b33400 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -315,7 +315,7 @@ extern uint8_t admin_authorized; /* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */ /* * Representation of 123-counters: - * 0: No record in flash memory + * 0: No record in flash memory * 1: 0xfe?? 0xffff * 2: 0xfe?? 0xc3c3 * 3: 0xfe?? 0x0000 @@ -366,13 +366,12 @@ extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *da 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_WAIT_MODE ((eventmask_t)16) -#define LED_FATAL_MODE ((eventmask_t)32) -extern Thread *main_thread; +#define LED_ONESHOT ((eventmask_t)1) +#define LED_TWOSHOTS ((eventmask_t)2) +#define LED_SHOW_STATUS ((eventmask_t)4) +#define LED_START_COMMAND ((eventmask_t)8) +#define LED_FINISH_COMMAND ((eventmask_t)16) +#define LED_FATAL ((eventmask_t)32) extern void led_blink (int spec); #if defined(PINPAD_SUPPORT) diff --git a/src/main.c b/src/main.c index 1bd2e99..35a7979 100644 --- a/src/main.c +++ b/src/main.c @@ -170,10 +170,12 @@ extern msg_t USBthread (void *arg); /* * main thread does 1-bit LED display output */ -#define LED_TIMEOUT_INTERVAL MS2ST(100) -#define LED_TIMEOUT_ZERO MS2ST(50) -#define LED_TIMEOUT_ONE MS2ST(200) -#define LED_TIMEOUT_STOP MS2ST(500) +#define MAIN_TIMEOUT_INTERVAL MS2ST(5000) + +#define LED_TIMEOUT_INTERVAL MS2ST(75) +#define LED_TIMEOUT_ZERO MS2ST(25) +#define LED_TIMEOUT_ONE MS2ST(100) +#define LED_TIMEOUT_STOP MS2ST(200) #define ID_OFFSET 22 @@ -194,7 +196,7 @@ device_initialize_once (void) for (i = 0; i < 4; i++) { uint8_t b = u[i]; - uint8_t nibble; + uint8_t nibble; nibble = (b >> 4); nibble += (nibble >= 10 ? ('A' - 10) : '0'); @@ -208,94 +210,64 @@ device_initialize_once (void) static volatile uint8_t fatal_code; -Thread *main_thread; - -#define GNUK_INIT 0 -#define GNUK_RUNNING 1 -#define GNUK_WAIT 2 -#define GNUK_FATAL 255 -/* - * 0 for initializing - * 1 for normal mode - * 2 for input waiting / under calculation - * 255 for fatal - */ -static uint8_t main_mode; - -static void display_interaction (void) -{ - eventmask_t m; - - set_led (1); - while (1) - { - m = chEvtWaitOne (ALL_EVENTS); - set_led (0); - 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 (1); - chThdSleep (MS2ST (50)); - set_led (0); - chThdSleep (MS2ST (50)); - break; - case LED_STATUS_MODE: - main_mode = GNUK_RUNNING; - return; - case LED_FATAL_MODE: - main_mode = GNUK_FATAL; - return; - default: - break; - } - set_led (1); - } -} +static Thread *main_thread; 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); + while (1) + { + 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*10); + } } -static void display_status_code (void) +static uint8_t led_inverted; + +static eventmask_t emit_led (int on_time, int off_time) +{ + eventmask_t m; + + set_led (!led_inverted); + m = chEvtWaitOneTimeout (ALL_EVENTS, on_time); + set_led (led_inverted); + if (m) return m; + if ((m = chEvtWaitOneTimeout (ALL_EVENTS, off_time))) + return m; + return 0; +} + +static eventmask_t display_status_code (void) { enum icc_state icc_state; + eventmask_t m; if (icc_state_p == NULL) icc_state = ICC_STATE_START; @@ -303,70 +275,47 @@ static void display_status_code (void) icc_state = *icc_state_p; if (icc_state == ICC_STATE_START) - { - set_led (1); - chThdSleep (LED_TIMEOUT_ONE); - set_led (0); - chThdSleep (LED_TIMEOUT_STOP * 3); - } + return emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP); 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 ((m = emit_led ((auth_status & AC_ADMIN_AUTHORIZED)? + LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, + LED_TIMEOUT_INTERVAL))) + return m; + if ((m = emit_led ((auth_status & AC_OTHER_AUTHORIZED)? + LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, + LED_TIMEOUT_INTERVAL))) + return m; + if ((m = emit_led ((auth_status & AC_PSO_CDS_AUTHORIZED)? + LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, + LED_TIMEOUT_INTERVAL))) + return m; 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); + if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_STOP * 2))) + return m; } else { - set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); - set_led (1); - chThdSleep (LED_TIMEOUT_STOP); - set_led (0); - chThdSleep (LED_TIMEOUT_INTERVAL); + if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL))) + return m; + + if ((m = emit_led (icc_state == ICC_STATE_RECEIVE? + LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, + LED_TIMEOUT_STOP))) + return m; } + + return 0; } } 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); + chEvtSignal (main_thread, spec); } @@ -379,7 +328,9 @@ led_blink (int spec) int main (int argc, char *argv[]) { +#ifdef DEBUG_MORE int count = 0; +#endif (void)argc; (void)argv; @@ -416,6 +367,7 @@ main (int argc, char *argv[]) msc_init (); #endif + while (1) { eventmask_t m; @@ -423,42 +375,42 @@ main (int argc, char *argv[]) if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) break; +#ifdef DEBUG_MORE count++; - m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL); +#endif + + m = chEvtWaitOneTimeout (ALL_EVENTS, MAIN_TIMEOUT_INTERVAL); + got_it: switch (m) { - case LED_STATUS_MODE: - main_mode = GNUK_RUNNING; + case LED_ONESHOT: + if ((m = emit_led (MS2ST (100), MAIN_TIMEOUT_INTERVAL))) goto got_it; break; - case LED_FATAL_MODE: - main_mode = GNUK_FATAL; + case LED_TWOSHOTS: + if ((m = emit_led (MS2ST (50), MS2ST (50)))) goto got_it; + if ((m = emit_led (MS2ST (50), MAIN_TIMEOUT_INTERVAL))) goto got_it; break; - case LED_WAIT_MODE: - main_mode = GNUK_WAIT; + case LED_SHOW_STATUS: + if ((m = display_status_code ())) goto got_it; break; - default: + case LED_START_COMMAND: + set_led (1); + led_inverted = 1; break; - } - - switch (main_mode) - { - case GNUK_FATAL: + case LED_FINISH_COMMAND: + led_inverted = 0; + set_led (0); + if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL))) + goto got_it; + break; + case LED_FATAL: display_fatal_code (); break; - case GNUK_INIT: - set_led (1); - chThdSleep (LED_TIMEOUT_ZERO); - set_led (0); - chThdSleep (LED_TIMEOUT_STOP * 3); - break; - case GNUK_WAIT: - display_interaction (); - break; - case GNUK_RUNNING: default: - display_status_code (); + if ((m = emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP))) + goto got_it; break; - } + } #ifdef DEBUG_MORE if (bDeviceState == CONFIGURED && (count % 10) == 0) @@ -496,12 +448,12 @@ main (int argc, char *argv[]) /* copy system service routines */ flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000); - /* Leave Gnuk to exec reGNUal */ + /* Leave Gnuk to exec reGNUal */ (*func) (*((void (**)(void))(&_regnual_start+4))); for (;;); } #else - /* Leave Gnuk to exec reGNUal */ + /* Leave Gnuk to exec reGNUal */ flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); #endif @@ -513,7 +465,7 @@ void fatal (uint8_t code) { fatal_code = code; - chEvtSignal (main_thread, LED_FATAL_MODE); + chEvtSignal (main_thread, LED_FATAL); _write ("fatal\r\n", 7); for (;;); } diff --git a/src/main.c.~HEAD~ b/src/main.c.~HEAD~ new file mode 100644 index 0000000..1bd2e99 --- /dev/null +++ b/src/main.c.~HEAD~ @@ -0,0 +1,519 @@ +/* + * main.c - main routine of Gnuk + * + * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + +#include "config.h" +#include "ch.h" +#include "hal.h" +#include "sys.h" +#include "gnuk.h" +#include "usb_lld.h" +#include "usb-cdc.h" + +#ifdef DEBUG +struct stdout { + Mutex m; + CondVar start_cnd; + CondVar finish_cnd; + const char *str; + int size; +}; + +static struct stdout stdout; + +static void +stdout_init (void) +{ + chMtxInit (&stdout.m); + chCondInit (&stdout.start_cnd); + chCondInit (&stdout.finish_cnd); + stdout.size = 0; + stdout.str = NULL; +} + +void +_write (const char *s, int size) +{ + if (size == 0) + return; + + chMtxLock (&stdout.m); + while (stdout.str) + chCondWait (&stdout.finish_cnd); + stdout.str = s; + stdout.size = size; + chCondSignal (&stdout.start_cnd); + chCondWait (&stdout.finish_cnd); + chMtxUnlock (); +} + +Thread *stdout_thread; +uint32_t count_in; +uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE]; + +static WORKING_AREA(waSTDOUTthread, 128); + +static msg_t +STDOUTthread (void *arg) +{ + (void)arg; + stdout_thread = chThdSelf (); + + again: + + while (1) + { + if (bDeviceState == CONFIGURED) + break; + + chThdSleepMilliseconds (100); + } + + while (1) + { + const char *p; + int len; + + if (bDeviceState != CONFIGURED) + break; + + chMtxLock (&stdout.m); + if (stdout.str == NULL) + chCondWait (&stdout.start_cnd); + + p = stdout.str; + len = stdout.size; + while (1) + { + int i; + + if (len == 0) + if (count_in != VIRTUAL_COM_PORT_DATA_SIZE) + break; + + if (len < VIRTUAL_COM_PORT_DATA_SIZE) + { + for (i = 0; i < len; i++) + buffer_in[i] = p[i]; + count_in = len; + len = 0; + } + else + { + for (i = 0; i < VIRTUAL_COM_PORT_DATA_SIZE; i++) + buffer_in[i] = p[i]; + len -= VIRTUAL_COM_PORT_DATA_SIZE; + count_in = VIRTUAL_COM_PORT_DATA_SIZE; + p += count_in; + } + + chEvtClear (EV_TX_READY); + + usb_lld_write (ENDP3, buffer_in, count_in); + + chEvtWaitOne (EV_TX_READY); + } + + stdout.str = NULL; + stdout.size = 0; + chCondBroadcast (&stdout.finish_cnd); + chMtxUnlock (); + } + + goto again; + return 0; +} + +void +EP3_IN_Callback (void) +{ + if (stdout_thread) + chEvtSignalI (stdout_thread, EV_TX_READY); +} + +void +EP5_OUT_Callback (void) +{ + usb_lld_rx_enable (ENDP5); +} +#else +void +_write (const char *s, int size) +{ + (void)s; + (void)size; +} +#endif + +static WORKING_AREA(waUSBthread, 128); +extern msg_t USBthread (void *arg); + +/* + * main thread does 1-bit LED display output + */ +#define LED_TIMEOUT_INTERVAL MS2ST(100) +#define LED_TIMEOUT_ZERO MS2ST(50) +#define LED_TIMEOUT_ONE MS2ST(200) +#define LED_TIMEOUT_STOP MS2ST(500) + + +#define ID_OFFSET 22 +static void +device_initialize_once (void) +{ + const uint8_t *p = &gnukStringSerial[ID_OFFSET]; + + if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff) + { + /* + * This is the first time invocation. + * Setup serial number by unique device ID. + */ + const uint8_t *u = unique_device_id (); + int i; + + for (i = 0; i < 4; i++) + { + uint8_t b = u[i]; + uint8_t nibble; + + nibble = (b >> 4); + nibble += (nibble >= 10 ? ('A' - 10) : '0'); + flash_put_data_internal (&p[i*4], nibble); + nibble = (b & 0x0f); + nibble += (nibble >= 10 ? ('A' - 10) : '0'); + flash_put_data_internal (&p[i*4+2], nibble); + } + } +} + +static volatile uint8_t fatal_code; + +Thread *main_thread; + +#define GNUK_INIT 0 +#define GNUK_RUNNING 1 +#define GNUK_WAIT 2 +#define GNUK_FATAL 255 +/* + * 0 for initializing + * 1 for normal mode + * 2 for input waiting / under calculation + * 255 for fatal + */ +static uint8_t main_mode; + +static void display_interaction (void) +{ + eventmask_t m; + + set_led (1); + while (1) + { + m = chEvtWaitOne (ALL_EVENTS); + set_led (0); + 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 (1); + chThdSleep (MS2ST (50)); + set_led (0); + chThdSleep (MS2ST (50)); + break; + case LED_STATUS_MODE: + main_mode = GNUK_RUNNING; + return; + case LED_FATAL_MODE: + main_mode = GNUK_FATAL; + return; + default: + break; + } + set_led (1); + } +} + +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) +{ + enum icc_state icc_state; + + if (icc_state_p == NULL) + icc_state = ICC_STATE_START; + else + icc_state = *icc_state_p; + + 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. + * + * NOTE: the main function is already a thread in the system on entry. + * See the hwinit1_common function. + */ +int +main (int argc, char *argv[]) +{ + int count = 0; + + (void)argc; + (void)argv; + + main_thread = chThdSelf (); + + flash_unlock (); + device_initialize_once (); + usb_lld_init (Config_Descriptor.Descriptor[7]); + random_init (); + + while (1) + { + if (bDeviceState != UNCONNECTED) + break; + + chThdSleepMilliseconds (250); + } + +#ifdef DEBUG + stdout_init (); + + /* + * Creates 'stdout' thread. + */ + chThdCreateStatic (waSTDOUTthread, sizeof(waSTDOUTthread), + NORMALPRIO, STDOUTthread, NULL); +#endif + + chThdCreateStatic (waUSBthread, sizeof(waUSBthread), + NORMALPRIO, USBthread, NULL); + +#ifdef PINPAD_DND_SUPPORT + msc_init (); +#endif + + while (1) + { + eventmask_t m; + + if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) + break; + + 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_WAIT_MODE: + main_mode = GNUK_WAIT; + break; + default: + break; + } + + switch (main_mode) + { + case GNUK_FATAL: + display_fatal_code (); + break; + case GNUK_INIT: + set_led (1); + chThdSleep (LED_TIMEOUT_ZERO); + set_led (0); + chThdSleep (LED_TIMEOUT_STOP * 3); + break; + case GNUK_WAIT: + display_interaction (); + break; + case GNUK_RUNNING: + default: + display_status_code (); + break; + } + +#ifdef DEBUG_MORE + if (bDeviceState == CONFIGURED && (count % 10) == 0) + { + DEBUG_SHORT (count / 10); + _write ("\r\nThis is ChibiOS 2.0.8 on STM32.\r\n" + "Testing USB driver.\n\n" + "Hello world\r\n\r\n", 35+21+15); + } +#endif + } + + set_led (1); + usb_lld_shutdown (); + /* Disable SysTick */ + SysTick->CTRL = 0; + /* Disable all interrupts */ + port_disable (); + /* Set vector */ + SCB->VTOR = (uint32_t)&_regnual_start; +#ifdef DFU_SUPPORT +#define FLASH_SYS_START_ADDR 0x08000000 +#define FLASH_SYS_END_ADDR (0x08000000+0x1000) + { + extern uint8_t _sys; + uint32_t addr; + handler *new_vector = (handler *)FLASH_SYS_START_ADDR; + void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10]; + + /* Kill DFU */ + for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR; + addr += FLASH_PAGE_SIZE) + flash_erase_page (addr); + + /* copy system service routines */ + flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000); + + /* Leave Gnuk to exec reGNUal */ + (*func) (*((void (**)(void))(&_regnual_start+4))); + for (;;); + } +#else + /* Leave Gnuk to exec reGNUal */ + flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); +#endif + + /* Never reached */ + return 0; +} + +void +fatal (uint8_t code) +{ + fatal_code = code; + chEvtSignal (main_thread, LED_FATAL_MODE); + _write ("fatal\r\n", 7); + for (;;); +} diff --git a/src/neug.c b/src/neug.c index be95ae9..5753094 100644 --- a/src/neug.c +++ b/src/neug.c @@ -32,15 +32,15 @@ static Thread *rng_thread; /* 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); /* diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 300b50f..d9c0406 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -807,7 +807,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); - sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, + sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); encrypt_dek (ks123_pw1+1, pd->dek_encrypted_1); } @@ -1036,7 +1036,7 @@ gpg_do_table[] = { / sizeof (struct do_table_entry)) /* - * Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc. + * Reading data from Flash ROM, initialize DO_PTR, PW_ERR_COUNTERS, etc. */ void gpg_data_scan (const uint8_t *p_start) @@ -1534,9 +1534,7 @@ gpg_do_keygen (uint8_t kk_byte) else keystring_admin = NULL; - chEvtSignal (main_thread, LED_WAIT_MODE); p_q_modulus = rsa_genkey (); - chEvtSignal (main_thread, LED_STATUS_MODE); if (p_q_modulus == NULL) { GPG_MEMORY_FAILURE (); diff --git a/src/openpgp.c b/src/openpgp.c index 89b218b..966d017 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -107,7 +107,7 @@ gpg_fini (void) } #if defined(PINPAD_SUPPORT) -/* +/* * Let user input PIN string. * Return length of the string. * The string itself is in PIN_INPUT_BUFFER. @@ -117,9 +117,9 @@ get_pinpad_input (int msg_code) { int r; - chEvtSignal (main_thread, LED_WAIT_MODE); + led_blink (LED_START_COMMAND); r = pinpad_getline (msg_code, MS2ST (8000)); - chEvtSignal (main_thread, LED_STATUS_MODE); + led_blink (LED_FINISH_COMMAND); return r; } #endif @@ -724,10 +724,8 @@ cmd_pso (void) DEBUG_SHORT (len); DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN); - chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_SIGNING]); - chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) { ac_reset_pso_cds (); @@ -752,10 +750,8 @@ cmd_pso (void) /* Skip padding 0x00 */ len--; - chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, &kd[GPG_KEY_FOR_DECRYPTION]); - chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) GPG_ERROR (); } @@ -799,10 +795,8 @@ cmd_internal_authenticate (void) return; } - chEvtSignal (main_thread, LED_WAIT_MODE); r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len, &kd[GPG_KEY_FOR_AUTHENTICATION]); - chEvtSignal (main_thread, LED_STATUS_MODE); if (r < 0) GPG_ERROR (); } @@ -1139,7 +1133,9 @@ GPGthread (void *arg) else if (m == EV_NOP) continue; + led_blink (LED_START_COMMAND); process_command_apdu (); + led_blink (LED_FINISH_COMMAND); done: chEvtSignal (icc_thread, EV_EXEC_FINISHED); } diff --git a/src/pin-cir.c b/src/pin-cir.c index 4bf1052..75c8f62 100644 --- a/src/pin-cir.c +++ b/src/pin-cir.c @@ -595,7 +595,7 @@ cir_getchar (systime_t timeout) static Thread *pin_thread; -/* +/* * Let user input PIN string. * Return length of the string. * The string itself is in PIN_INPUT_BUFFER. @@ -620,7 +620,7 @@ pinpad_getline (int msg_code, systime_t timeout) if (ch_is_backspace (ch)) { - led_blink (2); + led_blink (LED_TWOSHOTS); if (pin_input_len > 0) pin_input_len--; } @@ -628,7 +628,7 @@ pinpad_getline (int msg_code, systime_t timeout) break; else if (pin_input_len < MAX_PIN_CHARS) { - led_blink (0); + led_blink (LED_ONESHOT); pin_input_buffer[pin_input_len++] = ch; } } diff --git a/src/pin-dial.c b/src/pin-dial.c index 5fd471e..d1e49d5 100644 --- a/src/pin-dial.c +++ b/src/pin-dial.c @@ -51,7 +51,7 @@ uint8_t pin_input_len; #define OFF '\x00' #define ENTER '\x0a' -static struct led_pattern { uint8_t c, v; } led_pattern[] = +static struct led_pattern { uint8_t c, v; } led_pattern[] = { /* char : dp a b c d e f g */ { ENTER, 0xf8 }, /* |- : 1 1 1 1 1 0 0 0 (enter) */ diff --git a/src/pin-dnd.c b/src/pin-dnd.c index 08238e6..aa1e1e4 100644 --- a/src/pin-dnd.c +++ b/src/pin-dnd.c @@ -41,7 +41,7 @@ uint8_t pin_input_len; static Thread *pin_thread; -/* +/* * Let user input PIN string. * Return length of the string. * The string itself is in PIN_INPUT_BUFFER. @@ -71,7 +71,7 @@ pinpad_getline (int msg_code, systime_t timeout) msg = chThdSelf ()->p_u.rdymsg; chSysUnlock (); - led_blink (0); + led_blink (LED_ONESHOT); if (msg != 0) break; } diff --git a/src/sys.c b/src/sys.c index 0c1cc00..7e70df1 100644 --- a/src/sys.c +++ b/src/sys.c @@ -116,7 +116,7 @@ flash_erase_page (uint32_t addr) if (status == 0) { FLASH->CR |= FLASH_CR_PER; - FLASH->AR = addr; + FLASH->AR = addr; FLASH->CR |= FLASH_CR_STRT; status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT); diff --git a/src/usb-icc.c b/src/usb-icc.c index bb04104..d906548 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -803,6 +803,7 @@ icc_send_status (struct ccid *c) c->epi->tx_done = 1; usb_lld_write (c->epi->ep_num, icc_reply, ICC_MSG_HEADER_SIZE); + led_blink (LED_SHOW_STATUS); #ifdef DEBUG_MORE DEBUG_INFO ("St\r\n"); #endif @@ -1260,7 +1261,7 @@ icc_handle_timeout (struct ccid *c) { case ICC_STATE_EXECUTE: icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT); - led_blink (2); + led_blink (LED_ONESHOT); break; default: break; diff --git a/src/usb-msc.c b/src/usb-msc.c index 0a5ebac..cacef7a 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -372,7 +372,7 @@ void msc_handle_command (void) msc_send_result (buf, 12); return; case SCSI_START_STOP_UNIT: - if (CBW.CBWCB[4] == 0x00 /* stop */ + if (CBW.CBWCB[4] == 0x00 /* stop */ || CBW.CBWCB[4] == 0x02 /* eject */ || CBW.CBWCB[4] == 0x03 /* close */) { msc_scsi_stop (CBW.CBWCB[4]); @@ -380,7 +380,7 @@ void msc_handle_command (void) contingent_allegiance = 1; keep_contingent_allegiance = 1; } - /* CBW.CBWCB[4] == 0x01 *//* start */ + /* CBW.CBWCB[4] == 0x01 *//* start */ goto success; case SCSI_TEST_UNIT_READY: if (contingent_allegiance) diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 4609f01..49cb8d0 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -381,7 +381,6 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value) for (i = 0; i < NUM_INTERFACES; i++) gnuk_setup_endpoints_for_interface (i, 0); bDeviceState = CONFIGURED; - chEvtSignalI (main_thread, LED_STATUS_MODE); } else if (current_conf != value) { diff --git a/src/usb_desc.c b/src/usb_desc.c index 9cb5406..c6f1fa4 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -261,7 +261,7 @@ const uint8_t gnukStringSerial[] = { 18*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ /* FSIJ-0.19 */ - 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, + 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, '0', 0, '.', 0, '1', 0, '9', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/src/usb_lld.c b/src/usb_lld.c index 3827c32..df0c2f9 100644 --- a/src/usb_lld.c +++ b/src/usb_lld.c @@ -852,11 +852,11 @@ static void handle_setup0 (void) if (USB_SETUP_GET (ctrl_p->bmRequestType)) { uint32_t len = ctrl_p->wLength; - + /* Restrict the data length to be the one host asks for */ if (data_p->len > len) data_p->len = len; - + if ((data_p->len % USB_MAX_PACKET_SIZE) == 0) data_p->require_zlp = TRUE; else @@ -871,7 +871,7 @@ static void handle_setup0 (void) st103_set_tx_count (ENDP0, 0); st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); } - else + else { dev_p->state = OUT_DATA; st103_ep_set_rx_status (ENDP0, EP_RX_VALID); From 6a4d7fa108249492e8151b3e6ef07f5c29a63ffe Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 18 Jun 2012 12:44:37 +0900 Subject: [PATCH 186/300] LED display output --- src/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 35a7979..c95e8af 100644 --- a/src/main.c +++ b/src/main.c @@ -398,9 +398,10 @@ main (int argc, char *argv[]) led_inverted = 1; break; case LED_FINISH_COMMAND: + m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_STOP); led_inverted = 0; set_led (0); - if ((m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL))) + if (m) goto got_it; break; case LED_FATAL: From 3df59ca6f97a24b68642db7f5e109daee11686ed Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 18 Jun 2012 14:04:34 +0900 Subject: [PATCH 187/300] LED display output --- src/main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index c95e8af..404360a 100644 --- a/src/main.c +++ b/src/main.c @@ -328,9 +328,7 @@ led_blink (int spec) int main (int argc, char *argv[]) { -#ifdef DEBUG_MORE - int count = 0; -#endif + unsigned int count = 0; (void)argc; (void)argv; @@ -375,12 +373,9 @@ main (int argc, char *argv[]) if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) break; -#ifdef DEBUG_MORE - count++; -#endif - m = chEvtWaitOneTimeout (ALL_EVENTS, MAIN_TIMEOUT_INTERVAL); got_it: + count++; switch (m) { case LED_ONESHOT: @@ -391,6 +386,7 @@ main (int argc, char *argv[]) if ((m = emit_led (MS2ST (50), MAIN_TIMEOUT_INTERVAL))) goto got_it; break; case LED_SHOW_STATUS: + if ((count & 0x07) != 0) continue; if ((m = display_status_code ())) goto got_it; break; case LED_START_COMMAND: From cb8ee10292bda96603ce9bfc81b2e108879b382f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 18 Jun 2012 14:12:00 +0900 Subject: [PATCH 188/300] LED display output --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 404360a..a38e540 100644 --- a/src/main.c +++ b/src/main.c @@ -386,7 +386,7 @@ main (int argc, char *argv[]) if ((m = emit_led (MS2ST (50), MAIN_TIMEOUT_INTERVAL))) goto got_it; break; case LED_SHOW_STATUS: - if ((count & 0x07) != 0) continue; + if ((count & 0x07) != 0) continue; /* Display once for eight times */ if ((m = display_status_code ())) goto got_it; break; case LED_START_COMMAND: From b3c15ce93cde2ada3ee19e7702aab7505b95d6f0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 19 Jun 2012 10:19:26 +0900 Subject: [PATCH 189/300] version 0.20 --- ChangeLog | 8 ++++++- NEWS | 20 +++++++++--------- README | 38 +++++++++++++++++++--------------- src/usb_desc.c | 2 +- tool/dfuse.py | 2 +- tool/gnuk_put_binary.py | 2 +- tool/gnuk_put_binary_libusb.py | 5 ++--- tool/gnuk_upgrade.py | 5 ++--- tool/intel_hex.py | 2 +- 9 files changed, 46 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index ee9265d..8d66b32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-06-19 Niibe Yutaka + + * Version 0.20. + + * src/usb_desc.c (gnukStringSerial): Updated. + 2012-06-18 Niibe Yutaka LED display output change. @@ -6,7 +12,7 @@ (main_mode, display_interaction): Remove. (led_inverted, emit_led): New. (display_status_code): Use emit_led. - (led_blink): Use LED_* for spec. + (led_blink): Use LED_* for SPEC. (main, fatal): New LED display output. * src/gnuk.h (LED_ONESHOT, LED_TWOSHOTS, LED_SHOW_STATUS) (LED_START_COMMAND, LED_FINISH_COMMAND, LED_FATAL): New semantics. diff --git a/NEWS b/NEWS index a1ac945..fbcc3fb 100644 --- a/NEWS +++ b/NEWS @@ -1,19 +1,12 @@ Gnuk NEWS - User visible changes -* Major changes in Gnuk XXXX +* Major changes in Gnuk 0.20 - Released 2012-XX-XX, by NIIBE Yutaka - -** LED display output change -LED display output by Gnuk is now more reactive. It shows status code -when it gets GET_STATUS message of CCID. When you communicate Gnuk by -internal CCID driver of GnuPG (instead of PC/SC), and enable -'debug-disable-ticker' option in .gnupg/scdaemon.conf, it is more -silent now. + Released 2012-06-19, by NIIBE Yutaka ** Key generation feature added Finally, key generation is supported. Note that it may be very slow. -It will take a few minutes (or more) to generate two or three keys, +It may take a few minutes (or more) to generate two or three keys, when you are unlucky. ** DnD pinentry support is deprecated @@ -36,6 +29,13 @@ single block CFB mode). (3) Key data plus checksum are encrypted in CFB mode with initial vector (it will be able to switch OCB mode easily). +** LED display output change +LED display output by Gnuk is now more reactive. It shows status code +when it gets GET_STATUS message of CCID. When you communicate Gnuk by +internal CCID driver of GnuPG (instead of PC/SC), and enable +'debug-disable-ticker' option in .gnupg/scdaemon.conf, it is more +silent now. + * Major changes in Gnuk 0.19 diff --git a/README b/README index 3d5bc90..ab64525 100644 --- a/README +++ b/README @@ -1,15 +1,15 @@ -Gnuk - software for GnuPG USB Token +Gnuk - An Implementation of USB Cryptographic Token for GnuPG - Version 0.19 - 2012-06-06 + Version 0.20 + 2012-06-19 Niibe Yutaka Free Software Initiative of Japan What's Gnuk? ============ -Gnuk is software implementation of a USB token for GNU Privacy Guard. -Gnuk supports OpenPGP card protocol version 2, and it runs on +Gnuk is an implementation of USB cryptographic token for GNU Privacy +Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on STM32F103 processor. I wish that Gnuk will be a developer's soother who uses GnuPG. I have @@ -19,8 +19,8 @@ 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 am with a USB -Token by "Gnuk", always, everywhere. +son used to be with his NUK(R), always, everywhere. Now, I am with a +USB Cryptographic Token by "Gnuk", always, everywhere. FAQ @@ -113,9 +113,10 @@ Ac: STLink v2 is cheap one. See http://code.google.com/p/arm-utilities/ Release notes ============= -This is twentieth release of Gnuk. In this release, firmware upgrade -feature is added. While it is daily use, some features (including -firmware upgrade) are still considered experimental. +This is "version 1.0 release candidate" of Gnuk. In this release, key +generation feature is added. While it is daily use, some features +(including key generation and firmware upgrade) are still considered +experimental. Tested features are: @@ -137,12 +138,22 @@ Tested features are: but you can remove all keys to import again). * Key generation on device side +Original feature of Gnuk, tested (lightly): + + * Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal + It is known not-working well: * For some version of kernel and libccid, --enable-debug can't work well. Please make sure to disable DEBUG option if it doesn't work well. +It is known that the combination libccid 1.4.1 (or newer) with libusb +1.0.8 (or older) has a problem. It is possible for USB communication +to be failed, because of a bug in libusb implementation. Use libusbx +1.0.9 or newer, or don't use PC/SC, but use internal CCID driver of +GnuPG. + Targets ======= @@ -171,13 +182,6 @@ Another PIN-pad support is connecting rotary encoder, push switch and 7-segment LED display. Both of PIN verification and PIN modification are supported for this circuit extension. -Also, there is "DnDpinentry" support. This is using usual file -manager for pinentry. User does "drag and drop" folders and it will -be pin entry. This feature doesn't require any additional hardware. -See doc/settings-for-DnDpinentry for your desktop configuration. -However, this will be removed in future version, as it found it's -not that useful. - Note that you need pinpad support for GnuPG to use PIN-pad enabled Gnuk. The pinpad support for GnuPG is currently in the master branch of GnuPG git repository at git.gnupg.org, and it's under evaluation. diff --git a/src/usb_desc.c b/src/usb_desc.c index c6f1fa4..00642d5 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -262,7 +262,7 @@ const uint8_t gnukStringSerial[] = { USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ /* FSIJ-0.19 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '0', 0, '.', 0, '1', 0, '9', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '2', 0, '0', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/tool/dfuse.py b/tool/dfuse.py index 8239f6f..d95750e 100755 --- a/tool/dfuse.py +++ b/tool/dfuse.py @@ -94,7 +94,7 @@ STATE_DFU_ERROR = 0x0a def get_four_bytes (v): return [ v % 256, (v >> 8)%256, (v >> 16)%256, (v >> 24) ] -class DFU_STM32: +class DFU_STM32(object): def __init__(self, device, configuration, interface): """ __init__(device, configuration, interface) -> None diff --git a/tool/gnuk_put_binary.py b/tool/gnuk_put_binary.py index 63a5e60..a97a2d9 100755 --- a/tool/gnuk_put_binary.py +++ b/tool/gnuk_put_binary.py @@ -2,7 +2,7 @@ """ gnuk_put_binary.py - a tool to put binary to Gnuk Token -This tool is for importing certificate, updating random number, etc. +This tool is for importing certificate, writing serial number, etc. Copyright (C) 2011, 2012 Free Software Initiative of Japan Author: NIIBE Yutaka diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 4c056fc..5b1455f 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -2,7 +2,7 @@ """ gnuk_put_binary.py - a tool to put binary to Gnuk Token -This tool is for importing certificate, updating random number, etc. +This tool is for importing certificate, writing serial number, etc. Copyright (C) 2011, 2012 Free Software Initiative of Japan Author: NIIBE Yutaka @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -from intel_hex import * from struct import * import sys, time, os, binascii, string @@ -49,7 +48,7 @@ def iso7816_compose(ins, p1, p2, data, cls=0x00): return pack('>BBBBB', cls, ins, p1, p2, data_len) + data # This class only supports Gnuk (for now) -class gnuk_token: +class gnuk_token(object): def __init__(self, device, configuration, interface): """ __init__(device, configuration, interface) -> None diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 278278d..1ff2565 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -22,7 +22,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ -from intel_hex import * from struct import * import sys, time, os, binascii, string @@ -47,7 +46,7 @@ def iso7816_compose(ins, p1, p2, data, cls=0x00): else: return pack('>BBBBB', cls, ins, p1, p2, data_len) + data -class regnual: +class regnual(object): def __init__(self, dev): conf = dev.configurations[0] intf_alt = conf.interfaces[0] @@ -154,7 +153,7 @@ class regnual: pass # This class only supports Gnuk (for now) -class gnuk_token: +class gnuk_token(object): def __init__(self, device, configuration, interface): """ __init__(device, configuration, interface) -> None diff --git a/tool/intel_hex.py b/tool/intel_hex.py index a2b0e28..a31a123 100644 --- a/tool/intel_hex.py +++ b/tool/intel_hex.py @@ -9,7 +9,7 @@ You can use/distribute/modify/etc. this for any purpose. import binascii -class intel_hex: +class intel_hex(object): def __init__(self, filename): self.start_address = 0 self.address = 0 From 4290a2cc10082e17eee5261d04feb11b581091d4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 20 Jun 2012 14:44:20 +0900 Subject: [PATCH 190/300] ST-Link/V2 flash ROM writer --- ChangeLog | 7 + NEWS | 2 +- tool/asm-thumb/README | 2 + tool/asm-thumb/flash_write.S | 39 +++ tool/asm-thumb/opt_bytes_write.S | 29 ++ tool/stlinkv2.py | 475 +++++++++++++++++++++++++++++++ 6 files changed, 553 insertions(+), 1 deletion(-) create mode 100644 tool/asm-thumb/README create mode 100644 tool/asm-thumb/flash_write.S create mode 100644 tool/asm-thumb/opt_bytes_write.S create mode 100755 tool/stlinkv2.py diff --git a/ChangeLog b/ChangeLog index 8d66b32..28e258e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-06-20 Niibe Yutaka + + ST-Link/V2 flash ROM writer. + * tool/stlinkv2.py: New. + * tool/asm-thumb/opt_bytes_write.S: New. + * tool/asm-thumb/flash_write.S: New. + 2012-06-19 Niibe Yutaka * Version 0.20. diff --git a/NEWS b/NEWS index fbcc3fb..8607878 100644 --- a/NEWS +++ b/NEWS @@ -23,7 +23,7 @@ Keystring is now computed by SHA-256 (it was SHA1 before). ** Protection improvements (even when internal data is disclosed) Three improvements. (1) Even if PW1 and Reset-code is same, content -of encripted DEK is different now. (2) DEK is now encrypted and +of encrypted DEK is different now. (2) DEK is now encrypted and decrypted by keystring in ECB mode (it was just a kind of xor by single block CFB mode). (3) Key data plus checksum are encrypted in CFB mode with initial vector (it will be able to switch OCB mode diff --git a/tool/asm-thumb/README b/tool/asm-thumb/README new file mode 100644 index 0000000..e24b92a --- /dev/null +++ b/tool/asm-thumb/README @@ -0,0 +1,2 @@ +These assembler program are source code of program fragments in +stlinkv2.py. diff --git a/tool/asm-thumb/flash_write.S b/tool/asm-thumb/flash_write.S new file mode 100644 index 0000000..8f4b16c --- /dev/null +++ b/tool/asm-thumb/flash_write.S @@ -0,0 +1,39 @@ +/* ARM Thumb Assembler code */ +// arm-none-eabi-gcc -Wa,-amhls=flash_write.lst -c flash_write.S + +#define FLASH_CR_PG 0x0001 // == FLASH_SR_BSY +#define FLASH_CR_ERRORS 0x0014 // == PGERR | WRPRTERR +#define FLASH_SR_BSY 0x0001 + +#define FLASH_SR_OFFSET 0x0c +#define FLASH_CR_OFFSET 0x10 + +#define COUNT 0x1000 + + .cpu cortex-m3 + .thumb + movw r2, #COUNT + ldr r0, .SRC_ADDR + ldr r1, .TARGET_ADDR + ldr r4, .FLASH_BASE_ADDR + mov r5, #FLASH_CR_PG + mov r6, #FLASH_CR_ERRORS + mov r7, #0 + str r5, [r4, #FLASH_CR_OFFSET] +0: ldrh r3, [r0, r7] + strh r3, [r1, r7] +1: ldr r3, [r4, #FLASH_SR_OFFSET] + tst r3, r5 + bne 1b + tst r3, r6 + bne 2f + add r7, r7, #0x02 + cmp r7, r2 + bne 0b +2: mov r7, #0 + str r7, [r4, #FLASH_CR_OFFSET] + bkpt #0x00 + .align 2 +.FLASH_BASE_ADDR: .word 0x40022000 +.SRC_ADDR: .word 0x20000038 +.TARGET_ADDR: .word 0x08000000 diff --git a/tool/asm-thumb/opt_bytes_write.S b/tool/asm-thumb/opt_bytes_write.S new file mode 100644 index 0000000..dad89bb --- /dev/null +++ b/tool/asm-thumb/opt_bytes_write.S @@ -0,0 +1,29 @@ +/* ARM Thumb Assembler code */ +// arm-none-eabi-gcc -Wa,-amhls=opt_bytes_write.lst -c opt_bytes_write.S + +#define FLASH_CR_OPTPG 0x0010 +#define FLASH_SR_BSY 0x0001 + +#define FLASH_SR_OFFSET 0x0c +#define FLASH_CR_OFFSET 0x10 + +#define OB_RDP_UNLOCK 0x00a5 + + .cpu cortex-m3 + .thumb + movw r0, #OB_RDP_UNLOCK + ldr r1, .TARGET_ADDR + ldr r2, .FLASH_BASE_ADDR + mov r3, #FLASH_CR_OPTPG + mov r4, #FLASH_SR_BSY + str r3, [r2, #FLASH_CR_OFFSET] + strh r0, [r1] +1: ldr r0, [r2, #FLASH_SR_OFFSET] + tst r0, r4 + bne 1b + mov r0, #0 + str r0, [r2, #FLASH_CR_OFFSET] + bkpt #0x00 + .align 2 +.FLASH_BASE_ADDR: .word 0x40022000 +.TARGET_ADDR: .word 0x1FFFF800 diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py new file mode 100755 index 0000000..300bb1d --- /dev/null +++ b/tool/stlinkv2.py @@ -0,0 +1,475 @@ +#! /usr/bin/python + +""" +stlinkv2.py - a tool to control ST-Link/V2 + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +from struct import * +import sys, time + +# INPUT: binary file + +# Assumes only single ST-Link/V2 device is attached to computer. + +import usb + +GPIOA=0x40010800 +OPTION_BYTES_ADDR=0x1ffff800 +RDP_KEY=0x00a5 # Unlock readprotection +FLASH_BASE_ADDR=0x40022000 + +FLASH_KEYR= FLASH_BASE_ADDR+0x04 +FLASH_OPTKEYR= FLASH_BASE_ADDR+0x08 +FLASH_SR= FLASH_BASE_ADDR+0x0c +FLASH_CR= FLASH_BASE_ADDR+0x10 +FLASH_AR= FLASH_BASE_ADDR+0x14 +FLASH_OBR= FLASH_BASE_ADDR+0x1c + +FLASH_KEY1=0x45670123 +FLASH_KEY2=0xcdef89ab + +FLASH_SR_BSY= 0x0001 +FLASH_SR_PGERR= 0x0004 +FLASH_SR_WRPRTERR= 0x0010 +FLASH_SR_EOP= 0x0020 + +FLASH_CR_PG= 0x0001 +FLASH_CR_PER= 0x0002 +FLASH_CR_MER= 0x0004 +FLASH_CR_OPTPG= 0x0010 +FLASH_CR_OPTER= 0x0020 +FLASH_CR_STRT= 0x0040 +FLASH_CR_LOCK= 0x0080 +FLASH_CR_OPTWRE= 0x0200 + + +def uint32(v): + return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24) + +## HERE comes: "movw r2,#SIZE" instruction +prog_flash_write_body = "\x0A\x48" + "\x0B\x49" + \ + "\x08\x4C" + "\x01\x25" + "\x14\x26" + "\x00\x27" + "\x25\x61" + \ + "\xC3\x5B" + "\xCB\x53" + "\xE3\x68" + "\x2B\x42" + "\xFC\xD1" + \ + "\x33\x42" + "\x02\xD1" + "\x02\x37" + "\x97\x42" + "\xF5\xD1" + \ + "\x00\x27" + "\x27\x61" + "\x00\xBE" + "\x00\x20\x02\x40" + \ + "\x38\x00\x00\x20" +# .SRC_ADDR: 0x20000038 +## HERE comes: target_addr in 4-byte +# .TARGET_ADDR + +def gen_prog_flash_write(addr,size): + return pack(">12), (0xf2 | (size&0x0800)>>9), + (size & 0x00ff), (0x02 | ((size&0x0700) >> 4))) + \ + prog_flash_write_body + pack(">12), (0xf2 | (val&0x0800)>>9), + (val & 0x00ff), (0x00 | ((val&0x0700) >> 4))) + \ + prog_option_bytes_write_body + pack("= 10: + print "ERROR: option bytes write timeout" + break + + status = self.read_memory_u32(FLASH_SR) + self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) + if (status & FLASH_SR_EOP) == 0: + print "ERROR: option bytes write error" + + def option_bytes_erase(self): + self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) + self.write_memory_u32(FLASH_KEYR, FLASH_KEY2) + self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR) + + self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY1) + self.write_memory_u32(FLASH_OPTKEYR, FLASH_KEY2) + + self.write_memory_u32(FLASH_CR, FLASH_CR_OPTER) + self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER) + + i = 0 + while True: + status = self.read_memory_u32(FLASH_SR) + if (status & FLASH_SR_BSY) == 0: + break + i = i + 1 + if i >= 1000: + break + + self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) + if (status & FLASH_SR_EOP) == 0: + raise ValueError, "option bytes erase failed" + + def flash_write_internal(self, addr, data, off, size): + prog = gen_prog_flash_write(addr,size) + self.write_memory(SRAM_ADDRESS, prog+data[off:off+size]) + self.write_reg(15, SRAM_ADDRESS) + self.run() + i = 0 + while self.get_status() == 0x80: + time.sleep(0.050) + i = i + 1 + if i >= BLOCK_WRITE_TIMEOUT: + print "ERROR: flash write timeout" + break + status = self.read_memory_u32(FLASH_SR) + if (status & FLASH_SR_PGERR) != 0: + print "ERROR: write to a location that was not erased" + if (status & FLASH_SR_WRPRTERR) != 0: + print "ERROR: write to a location that was write protected" + + def flash_write(self, addr, data): + self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) + self.write_memory_u32(FLASH_KEYR, FLASH_KEY2) + self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR) + + off = 0 + while True: + if len(data[off:]) > BLOCK_SIZE: + size = BLOCK_SIZE + self.flash_write_internal(addr, data, off, size) + off = off + size + addr = addr + size + else: + size = len(data[off:]) + self.flash_write_internal(addr, data, off, size) + break + + self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) + + def flash_erase_all(self): + self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) + self.write_memory_u32(FLASH_KEYR, FLASH_KEY2) + self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR) + + self.write_memory_u32(FLASH_CR, FLASH_CR_MER) + self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER) + + i = 0 + while True: + status = self.read_memory_u32(FLASH_SR) + if (status & FLASH_SR_BSY) == 0: + break + i = i + 1 + time.sleep(0.050) + if i >= 100: + break + + self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) + + if (status & FLASH_SR_EOP) == 0: + raise ValueError, "flash erase all failed" + + def flash_erase_page(self, addr): + self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) + self.write_memory_u32(FLASH_KEYR, FLASH_KEY2) + + self.write_memory_u32(FLASH_SR, FLASH_SR_EOP | FLASH_SR_WRPRTERR | FLASH_SR_PGERR) + + self.write_memory_u32(FLASH_CR, FLASH_CR_PER) + self.write_memory_u32(FLASH_AR, addr) + self.write_memory_u32(FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER) + + i = 0 + while True: + status = self.read_memory_u32(FLASH_SR) + if (status & FLASH_SR_BSY) == 0: + break + i = i + 1 + if i >= 1000: + break + + self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) + + if (status & FLASH_SR_EOP) == 0: + raise ValueError, "flash page erase failed" + + def start(self): + mode = self.stl_mode() + if mode == 2: + return + elif mode != 1: + self.exit_from_dfu() + mode = self.stl_mode() + print "Change mode to: %04x" % mode + self.enter_swd() + s = self.get_status() + print "Status: %04x" % s + if self.stl_mode() != 2: + raise ValueError, "Failed to switch debug mode" + + +USB_VENDOR_ST=0x0483 # 0x0483 SGS Thomson Microelectronics +USB_VENDOR_STLINKV2=0x3748 # 0x3748 ST-LINK/V2 + +def stlinkv2_devices(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + if dev.idVendor != USB_VENDOR_ST: + continue + if dev.idProduct != USB_VENDOR_STLINKV2: + continue + yield dev + +def compare(data_original, data_in_device): + i = 0 + for d in data_original: + if ord(d) != data_in_device[i]: + raise ValueError, "verify failed at %08x" % i + i += 1 + +if __name__ == '__main__': + erase = False + if sys.argv[1] == '-e': + erase = True + sys.argv.pop(1) + + no_protect = False + if sys.argv[1] == '-n': + no_protect = True + sys.argv.pop(1) + + status_only = False + unlock = False + if sys.argv[1] == '-u': + unlock = True + sys.argv.pop(1) + elif sys.argv[1] == '-s': + status_only = True + else: + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + + for d in stlinkv2_devices(): + try: + stl = stlinkv2(d) + print "Device: ", d.filename + break + except: + pass + stl.start() + core_id = stl.core_id() + chip_id = stl.read_memory_u32(0xE0042000) + # FST-01 chip id: 0x20036410 + print "CORE: %08x, CHIP_ID: %08x" % (core_id, chip_id) + print "Flash ROM read protection:", + protection = stl.protection() + if protection: + print "ON" + if status_only: + print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board" + exit (0) + elif not unlock: + print "Please unlock flash ROM protection, at first. By invoking with -u option" + exit(1) + else: + print "off" + if status_only: + stl.reset_sys() + stl.run() + stl.exit_debug() + exit (0) + elif unlock: + print "No need to unlock. Protection is not enabled." + exit(1) + + print "status: %02x" % stl.get_status() + stl.enter_debug() + + if unlock: + stl.reset_sys() + stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) + print "Flash ROM read protection disabled. Reset the board, now." + exit(0) + + print "option bytes: %08x" % stl.option_bytes_read() + + if erase: + print "ERASE ALL" + stl.reset_sys() + stl.flash_erase_all() + time.sleep(0.100) + + print "WRITE" + stl.flash_write(0x08000000, data) + + print "VERIFY" + data_received = () + size = len(data) + off = 0 + while size > 0: + if size > 1024: + blk_size = 1024 + else: + blk_size = size + data_received = data_received + stl.read_memory(0x08000000+off, 1024) + size = size - blk_size + off = off + blk_size + compare(data, data_received) + + if not no_protect: + print "PROTECT" + stl.option_bytes_erase() + print "Flash ROM read protection enabled. Reset the board to enable protection." From c25d98bc58abb4a76953dfb63f5ba9305c9cc790 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 20 Jun 2012 17:31:27 +0900 Subject: [PATCH 191/300] modify stlinkv2.py. --- NEWS | 8 ++++++++ tool/stlinkv2.py | 35 +++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 8607878..5695ab8 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,13 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 1.0 + + Released 2012-0X-XX, by NIIBE Yutaka + +** New tool: stlinkv2.py +This tool is SWD flash ROM writer with ST-Link/V2. + + * Major changes in Gnuk 0.20 Released 2012-06-19, by NIIBE Yutaka diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 300bb1d..33288f6 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -183,25 +183,20 @@ class stlinkv2(object): v = self.execute_get("\xf2\x22\x00", 4) return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24) - # For FST-01-00 - def setup_led(self): + # For FST-01-00: LED on, USB off + def setup_gpio(self): apb2enr = self.read_memory_u32(0x40021018) apb2enr = apb2enr | 4 # Enable port A self.write_memory_u32(0x40021018, apb2enr) self.write_memory_u32(0x4002100c, 4) self.write_memory_u32(0x4002100c, 0) - self.write_memory_u32(GPIOA+0x0c, 0xffffffff) # ODR - self.write_memory_u32(GPIOA+0x04, 0x88888883) # CRH + self.write_memory_u32(GPIOA+0x0c, 0xfffffbff) # ODR + self.write_memory_u32(GPIOA+0x04, 0x88888383) # CRH + self.write_memory_u32(GPIOA+0x00, 0x88888888) # CRL - # For FST-01-00 - def blink_led(self): - self.write_memory_u32(GPIOA+0x0c, 0xfffffeff) # ODR - time.sleep(0.5) - self.write_memory_u32(GPIOA+0x0c, 0xffffffff) # ODR - time.sleep(0.5) - self.write_memory_u32(GPIOA+0x0c, 0xfffffeff) # ODR - time.sleep(0.5) - self.write_memory_u32(GPIOA+0x0c, 0xffffffff) # ODR + # For FST-01-00: LED off, USB off + def finish_gpio(self): + self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR def protection(self): return (self.read_memory_u32(FLASH_OBR) & 0x0002) != 0 @@ -389,6 +384,11 @@ if __name__ == '__main__': no_protect = True sys.argv.pop(1) + reset_after_successful_write = False + if sys.argv[1] == '-r': + reset_after_successful_write = True + sys.argv.pop(1) + status_only = False unlock = False if sys.argv[1] == '-u': @@ -419,7 +419,7 @@ if __name__ == '__main__': if protection: print "ON" if status_only: - print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board" + print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board to run." exit (0) elif not unlock: print "Please unlock flash ROM protection, at first. By invoking with -u option" @@ -452,8 +452,10 @@ if __name__ == '__main__': stl.flash_erase_all() time.sleep(0.100) + stl.setup_gpio() print "WRITE" stl.flash_write(0x08000000, data) + stl.finish_gpio() print "VERIFY" data_received = () @@ -473,3 +475,8 @@ if __name__ == '__main__': print "PROTECT" stl.option_bytes_erase() print "Flash ROM read protection enabled. Reset the board to enable protection." + + if reset_after_successful_write: + stl.reset_sys() + stl.run() + stl.exit_debug() From 6f203bc4ea54f7cee3b768d30bf5075675ab826f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 21 Jun 2012 19:40:41 +0900 Subject: [PATCH 192/300] Add blank_check.S --- ChangeLog | 4 ++++ tool/asm-thumb/blank_check.S | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tool/asm-thumb/blank_check.S diff --git a/ChangeLog b/ChangeLog index 28e258e..0ef87fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-21 Niibe Yutaka + + * tool/asm-thumb/blank_check.S: New. + 2012-06-20 Niibe Yutaka ST-Link/V2 flash ROM writer. diff --git a/tool/asm-thumb/blank_check.S b/tool/asm-thumb/blank_check.S new file mode 100644 index 0000000..bc421a5 --- /dev/null +++ b/tool/asm-thumb/blank_check.S @@ -0,0 +1,19 @@ +/* ARM Thumb Assembler code */ +// arm-none-eabi-gcc -Wa,-amhls=blank_check.lst -c blank_check.S + + .cpu cortex-m3 + .thumb + ldr r1, .START_ADDR + ldr r2, .END_ADDR +0: ldr r0, [r1] + add r0, r0, #1 + bne 1f + add r1, r1, #2 + cmp r1, r2 + bne 0b +1: bkpt #0x00 + // success: r0=0 + // fail: r0!=0 + .align 2 +.START_ADDR: .word 0x08000000 +.END_ADDR: .word 0x08020000 From fd9f46bcc7d7fed08e0b0d647044156a3258e36a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 22 Jun 2012 13:16:30 +0900 Subject: [PATCH 193/300] fix blank_check.S --- tool/asm-thumb/blank_check.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/asm-thumb/blank_check.S b/tool/asm-thumb/blank_check.S index bc421a5..567ef23 100644 --- a/tool/asm-thumb/blank_check.S +++ b/tool/asm-thumb/blank_check.S @@ -8,7 +8,7 @@ 0: ldr r0, [r1] add r0, r0, #1 bne 1f - add r1, r1, #2 + add r1, r1, #4 cmp r1, r2 bne 0b 1: bkpt #0x00 From 70efd3a1cdfc82021570368112fddebb9908e3a8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 22 Jun 2012 13:18:30 +0900 Subject: [PATCH 194/300] stlinkv2.py: Add blank check --- ChangeLog | 5 ++ tool/stlinkv2.py | 167 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 121 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ef87fe..b971efd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-06-22 Niibe Yutaka + + * tool/stlinkv2.py (stlinkv2.blank_check): Add blank check of + Flash ROM. + 2012-06-21 Niibe Yutaka * tool/asm-thumb/blank_check.S: New. diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 33288f6..ea78bcb 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -93,6 +93,15 @@ def gen_prog_option_bytes_write(addr,val): (val & 0x00ff), (0x00 | ((val&0x0700) >> 4))) + \ prog_option_bytes_write_body + pack("= 10: + print "ERROR: blank_check timeout" + break + + r0_value = self.read_reg(0) + return r0_value == 0 + def option_bytes_read(self): return self.read_memory_u32(OPTION_BYTES_ADDR) @@ -251,7 +276,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError, "option bytes erase failed" + raise ValueError("option bytes erase failed") def flash_write_internal(self, addr, data, off, size): prog = gen_prog_flash_write(addr,size) @@ -311,7 +336,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError, "flash erase all failed" + raise ValueError("flash erase all failed") def flash_erase_page(self, addr): self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) @@ -335,7 +360,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError, "flash page erase failed" + raise ValueError("flash page erase failed") def start(self): mode = self.stl_mode() @@ -344,12 +369,13 @@ class stlinkv2(object): elif mode != 1: self.exit_from_dfu() mode = self.stl_mode() - print "Change mode to: %04x" % mode + print "Change ST-Link/V2 mode to: %04x" % mode self.enter_swd() s = self.get_status() - print "Status: %04x" % s + if s != 0x0080: + raise ValueError("Status of core is not running") if self.stl_mode() != 2: - raise ValueError, "Failed to switch debug mode" + raise ValueError("Failed to switch debug mode") USB_VENDOR_ST=0x0483 # 0x0483 SGS Thomson Microelectronics @@ -370,45 +396,70 @@ def compare(data_original, data_in_device): i = 0 for d in data_original: if ord(d) != data_in_device[i]: - raise ValueError, "verify failed at %08x" % i + raise ValueError("verify failed at %08x" % i) i += 1 -if __name__ == '__main__': - erase = False - if sys.argv[1] == '-e': - erase = True - sys.argv.pop(1) - - no_protect = False - if sys.argv[1] == '-n': - no_protect = True - sys.argv.pop(1) - - reset_after_successful_write = False - if sys.argv[1] == '-r': - reset_after_successful_write = True - sys.argv.pop(1) - - status_only = False - unlock = False - if sys.argv[1] == '-u': - unlock = True - sys.argv.pop(1) - elif sys.argv[1] == '-s': - status_only = True - else: - filename = sys.argv[1] - f = open(filename) - data = f.read() - f.close() - +def open_stlinkv2(): for d in stlinkv2_devices(): try: stl = stlinkv2(d) - print "Device: ", d.filename - break + return stl except: pass + return None + +def help(): + print "stlinkv2.py [-h]: Show this help message" + print "stlinkv2.py [-e]: Erase flash ROM" + print "stlinkv2.py [-u]: Unlock flash ROM" + print "stlinkv2.py [-s]: Show status" + print "stlinkv2.py [-n] [-r] FILE: Write content of FILE to flash ROM" + print " -n: Don't enable read protection" + print " -r: Don't reset after write" + +if __name__ == '__main__': + show_help = False + erase = False + no_protect = False + reset_after_successful_write = False + status_only = False + unlock = False + data = None + + while len(sys.argv) > 1: + if sys.argv[1] == '-h': + sys.argv.pop(1) + break + elif sys.argv[1] == '-e': + sys.argv.pop(1) + erase = True + break + elif sys.argv[1] == '-u': + sys.argv.pop(1) + unlock = True + break + elif sys.argv[1] == '-s': + sys.argv.pop(1) + status_only = True + break + elif sys.argv[1] == '-n': + no_protect = True + elif sys.argv[1] == '-r': + reset_after_successful_write = True + else: + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + sys.argv.pop(1) + + if show_help or len(sys.argv) != 1: + help() + exit(1) + + stl = open_stlinkv2() + if not stl: + ValueError("No ST-Link/V2 device found") stl.start() core_id = stl.core_id() chip_id = stl.read_memory_u32(0xE0042000) @@ -418,14 +469,24 @@ if __name__ == '__main__': protection = stl.protection() if protection: print "ON" - if status_only: - print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board to run." - exit (0) - elif not unlock: - print "Please unlock flash ROM protection, at first. By invoking with -u option" - exit(1) else: print "off" + print "Option bytes: %08x" % stl.option_bytes_read() + + stl.enter_debug() + if stl.get_status() != 0x0081: + raise ValueError("status is not halt.") + + if protection: + if status_only: + print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board." + exit (0) + elif not unlock: + print "Please unlock flash ROM protection, at first. By invoking with -u option." + exit(1) + else: + blank = stl.blank_check() + print "Flash ROM blank check: %s" % blank if status_only: stl.reset_sys() stl.run() @@ -435,22 +496,26 @@ if __name__ == '__main__': print "No need to unlock. Protection is not enabled." exit(1) - print "status: %02x" % stl.get_status() - stl.enter_debug() - if unlock: stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) print "Flash ROM read protection disabled. Reset the board, now." exit(0) - print "option bytes: %08x" % stl.option_bytes_read() - if erase: + if blank: + print "No need to erase" + exit (0) + + if not blank: print "ERASE ALL" stl.reset_sys() stl.flash_erase_all() - time.sleep(0.100) + + if erase: + exit (0) + + time.sleep(0.100) stl.setup_gpio() print "WRITE" From d3f092a7360f238b82a94d25ae0f951febac3b84 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 22 Jun 2012 14:38:43 +0900 Subject: [PATCH 195/300] failure handling --- tool/stlinkv2.py | 181 +++++++++++++++++++++++++++++------------------ 1 file changed, 112 insertions(+), 69 deletions(-) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index ea78bcb..ab0d219 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -24,12 +24,13 @@ along with this program. If not, see . from struct import * import sys, time +import usb +from colorama import init as colorama_init, Fore, Back, Style # INPUT: binary file # Assumes only single ST-Link/V2 device is attached to computer. -import usb GPIOA=0x40010800 OPTION_BYTES_ADDR=0x1ffff800 @@ -107,7 +108,24 @@ SRAM_ADDRESS=0x20000000 BLOCK_SIZE=16384 # Should be less than (20KiB - 0x0038) BLOCK_WRITE_TIMEOUT=80 # Increase this when you increase BLOCK_SIZE -# This class only supports Gnuk (for now) + +class TimeOutError(Exception): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return repr(self.msg) + def __repr__(self): + return "TimeoutError(" + self.msg + ")" + +class OperationFailure(Exception): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return repr(self.msg) + def __repr__(self): + return "OperationFailure(" + self.msg + ")" + + class stlinkv2(object): def __init__(self, dev): self.__bulkout = 2 @@ -118,7 +136,7 @@ class stlinkv2(object): intf_alt = conf.interfaces[0] intf = intf_alt[0] if intf.interfaceClass != 0xff: # Vendor specific - raise ValueError("Wrong interface class") + raise ValueError("Wrong interface class.", intf.interfaceClass) self.__devhandle = dev.open() try: self.__devhandle.setConfiguration(conf) @@ -220,8 +238,7 @@ class stlinkv2(object): time.sleep(0.050) i = i + 1 if i >= 10: - print "ERROR: blank_check timeout" - break + raise TimeOutError("blank check") r0_value = self.read_reg(0) return r0_value == 0 @@ -246,13 +263,12 @@ class stlinkv2(object): time.sleep(0.050) i = i + 1 if i >= 10: - print "ERROR: option bytes write timeout" - break + raise TimeOutError("option bytes write") status = self.read_memory_u32(FLASH_SR) self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - print "ERROR: option bytes write error" + raise OperationFailure("option bytes write") def option_bytes_erase(self): self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) @@ -276,7 +292,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError("option bytes erase failed") + raise OperationError("option bytes erase") def flash_write_internal(self, addr, data, off, size): prog = gen_prog_flash_write(addr,size) @@ -288,13 +304,12 @@ class stlinkv2(object): time.sleep(0.050) i = i + 1 if i >= BLOCK_WRITE_TIMEOUT: - print "ERROR: flash write timeout" - break + raise TimeOutError("flash write") status = self.read_memory_u32(FLASH_SR) if (status & FLASH_SR_PGERR) != 0: - print "ERROR: write to a location that was not erased" + raise OperationFailure("flash write: write to not erased part") if (status & FLASH_SR_WRPRTERR) != 0: - print "ERROR: write to a location that was write protected" + raise OperationFailure("flash write: write to protected part") def flash_write(self, addr, data): self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) @@ -336,7 +351,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError("flash erase all failed") + raise OperationError("flash erase all") def flash_erase_page(self, addr): self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) @@ -360,7 +375,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise ValueError("flash page erase failed") + raise OperationError("flash page erase") def start(self): mode = self.stl_mode() @@ -373,9 +388,10 @@ class stlinkv2(object): self.enter_swd() s = self.get_status() if s != 0x0080: - raise ValueError("Status of core is not running") - if self.stl_mode() != 2: - raise ValueError("Failed to switch debug mode") + raise ValueError("Status of core is not running.", s) + mode = self.stl_mode() + if mode != 2: + raise ValueError("Failed to switch debug mode.", mode) USB_VENDOR_ST=0x0483 # 0x0483 SGS Thomson Microelectronics @@ -396,7 +412,7 @@ def compare(data_original, data_in_device): i = 0 for d in data_original: if ord(d) != data_in_device[i]: - raise ValueError("verify failed at %08x" % i) + raise ValueError("Verify failed at:", i) i += 1 def open_stlinkv2(): @@ -413,56 +429,26 @@ def help(): print "stlinkv2.py [-e]: Erase flash ROM" print "stlinkv2.py [-u]: Unlock flash ROM" print "stlinkv2.py [-s]: Show status" - print "stlinkv2.py [-n] [-r] FILE: Write content of FILE to flash ROM" + print "stlinkv2.py [-b] [-n] [-r] FILE: Write content of FILE to flash ROM" + print " -b: Enable blanck check" print " -n: Don't enable read protection" print " -r: Don't reset after write" -if __name__ == '__main__': - show_help = False - erase = False - no_protect = False - reset_after_successful_write = False - status_only = False - unlock = False - data = None - - while len(sys.argv) > 1: - if sys.argv[1] == '-h': - sys.argv.pop(1) - break - elif sys.argv[1] == '-e': - sys.argv.pop(1) - erase = True - break - elif sys.argv[1] == '-u': - sys.argv.pop(1) - unlock = True - break - elif sys.argv[1] == '-s': - sys.argv.pop(1) - status_only = True - break - elif sys.argv[1] == '-n': - no_protect = True - elif sys.argv[1] == '-r': - reset_after_successful_write = True - else: - filename = sys.argv[1] - f = open(filename) - data = f.read() - f.close() - sys.argv.pop(1) +def main(show_help, erase, no_protect, reset_after_successful_write, + skip_blank_check, status_only, unlock, data): if show_help or len(sys.argv) != 1: help() - exit(1) + return 1 stl = open_stlinkv2() if not stl: - ValueError("No ST-Link/V2 device found") + raise ValueError("No ST-Link/V2 device found.", None) + stl.start() core_id = stl.core_id() chip_id = stl.read_memory_u32(0xE0042000) + # FST-01 chip id: 0x20036410 print "CORE: %08x, CHIP_ID: %08x" % (core_id, chip_id) print "Flash ROM read protection:", @@ -474,38 +460,42 @@ if __name__ == '__main__': print "Option bytes: %08x" % stl.option_bytes_read() stl.enter_debug() - if stl.get_status() != 0x0081: - raise ValueError("status is not halt.") + status = stl.get_status() + if status != 0x0081: + raise ValueError("Status of core is not halt.", status) if protection: if status_only: - print "The MCU is now stopped. No way to run by STLink/V2. Please reset the board." - exit (0) + print "The MCU is now stopped." + return 0 elif not unlock: print "Please unlock flash ROM protection, at first. By invoking with -u option." - exit(1) + return 1 else: - blank = stl.blank_check() - print "Flash ROM blank check: %s" % blank + if not skip_blank_check: + blank = stl.blank_check() + print "Flash ROM blank check: %s" % blank + else: + blank = True if status_only: stl.reset_sys() stl.run() stl.exit_debug() - exit (0) + return 0 elif unlock: print "No need to unlock. Protection is not enabled." - exit(1) + return 1 if unlock: stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) print "Flash ROM read protection disabled. Reset the board, now." - exit(0) + return 0 if erase: if blank: print "No need to erase" - exit (0) + return 0 if not blank: print "ERASE ALL" @@ -513,7 +503,7 @@ if __name__ == '__main__': stl.flash_erase_all() if erase: - exit (0) + return 0 time.sleep(0.100) @@ -545,3 +535,56 @@ if __name__ == '__main__': stl.reset_sys() stl.run() stl.exit_debug() + + return 0 + +if __name__ == '__main__': + show_help = False + erase = False + no_protect = False + reset_after_successful_write = True + skip_blank_check=True + status_only = False + unlock = False + data = None + + while len(sys.argv) > 1: + if sys.argv[1] == '-h': + sys.argv.pop(1) + break + elif sys.argv[1] == '-e': + sys.argv.pop(1) + erase = True + break + elif sys.argv[1] == '-u': + sys.argv.pop(1) + unlock = True + break + elif sys.argv[1] == '-s': + sys.argv.pop(1) + status_only = True + skip_blank_check=False + break + elif sys.argv[1] == '-b': + skip_blank_check=False + elif sys.argv[1] == '-n': + no_protect = True + elif sys.argv[1] == '-r': + reset_after_successful_write = False + else: + filename = sys.argv[1] + f = open(filename) + data = f.read() + f.close() + sys.argv.pop(1) + + colorama_init() + + try: + r = main(show_help, erase, no_protect, reset_after_successful_write, + skip_blank_check, status_only, unlock, data) + if r == 0: + print Fore.WHITE + Back.BLUE + Style.BRIGHT + "SUCCESS" + Style.RESET_ALL + exit(r) + except Exception as e: + print Back.RED + Style.BRIGHT + repr(e) + Style.RESET_ALL From 5c5074c5c703e67d7d5f0747690b8993ff82746d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 22 Jun 2012 15:33:03 +0900 Subject: [PATCH 196/300] support FST-01 too --- tool/stlinkv2.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index ab0d219..ce46483 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -33,6 +33,7 @@ from colorama import init as colorama_init, Fore, Back, Style GPIOA=0x40010800 +GPIOB=0x40010C00 OPTION_BYTES_ADDR=0x1ffff800 RDP_KEY=0x00a5 # Unlock readprotection FLASH_BASE_ADDR=0x40022000 @@ -210,20 +211,24 @@ class stlinkv2(object): v = self.execute_get("\xf2\x22\x00", 4) return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24) - # For FST-01-00: LED on, USB off + # For FST-01-00 and FST-01: LED on, USB off def setup_gpio(self): apb2enr = self.read_memory_u32(0x40021018) - apb2enr = apb2enr | 4 # Enable port A - self.write_memory_u32(0x40021018, apb2enr) - self.write_memory_u32(0x4002100c, 4) + apb2enr = apb2enr | 4 | 8 # Enable port A and B + self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR + self.write_memory_u32(0x4002100c, 4|8) # RCC->APB2RSTR self.write_memory_u32(0x4002100c, 0) self.write_memory_u32(GPIOA+0x0c, 0xfffffbff) # ODR self.write_memory_u32(GPIOA+0x04, 0x88888383) # CRH self.write_memory_u32(GPIOA+0x00, 0x88888888) # CRL + self.write_memory_u32(GPIOB+0x0c, 0xffffffff) # ODR + self.write_memory_u32(GPIOB+0x04, 0x88888883) # CRH + self.write_memory_u32(GPIOB+0x00, 0x88888888) # CRL - # For FST-01-00: LED off, USB off + # For FST-01-00 and FST-01: LED off, USB off def finish_gpio(self): self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR + self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR def protection(self): return (self.read_memory_u32(FLASH_OBR) & 0x0002) != 0 From e6e11ddcb074a224627e8da1fcee6cb05c316fe7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 22 Jun 2012 17:00:35 +0900 Subject: [PATCH 197/300] It's not like UNIX tools. --- tool/stlinkv2.py | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index ce46483..6ec6cd8 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -435,12 +435,12 @@ def help(): print "stlinkv2.py [-u]: Unlock flash ROM" print "stlinkv2.py [-s]: Show status" print "stlinkv2.py [-b] [-n] [-r] FILE: Write content of FILE to flash ROM" - print " -b: Enable blanck check" - print " -n: Don't enable read protection" + print " -b: Blank check before write (auto erase when not blank)" + print " -n: Don't enable read protection after write" print " -r: Don't reset after write" -def main(show_help, erase, no_protect, reset_after_successful_write, +def main(show_help, erase_only, no_protect, reset_after_successful_write, skip_blank_check, status_only, unlock, data): if show_help or len(sys.argv) != 1: help() @@ -462,7 +462,12 @@ def main(show_help, erase, no_protect, reset_after_successful_write, print "ON" else: print "off" - print "Option bytes: %08x" % stl.option_bytes_read() + option_bytes = stl.option_bytes_read() + print "Option bytes: %08x" % option_bytes + if (option_bytes & 0xff) == RDP_KEY: + ob_protection_enable = False + else: + ob_protection_enable = True stl.enter_debug() status = stl.get_status() @@ -474,8 +479,7 @@ def main(show_help, erase, no_protect, reset_after_successful_write, print "The MCU is now stopped." return 0 elif not unlock: - print "Please unlock flash ROM protection, at first. By invoking with -u option." - return 1 + raise OperationFailure("Flash ROM is protected") else: if not skip_blank_check: blank = stl.blank_check() @@ -487,35 +491,36 @@ def main(show_help, erase, no_protect, reset_after_successful_write, stl.run() stl.exit_debug() return 0 - elif unlock: + elif unlock and not ob_protection_enable: print "No need to unlock. Protection is not enabled." return 1 + if erase_only: + if blank: + print "No need to erase" + return 0 + + stl.setup_gpio() + if unlock: stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) print "Flash ROM read protection disabled. Reset the board, now." return 0 - if erase: - if blank: - print "No need to erase" - return 0 - if not blank: print "ERASE ALL" stl.reset_sys() stl.flash_erase_all() - if erase: + if erase_only: + stl.finish_gpio() return 0 time.sleep(0.100) - stl.setup_gpio() print "WRITE" stl.flash_write(0x08000000, data) - stl.finish_gpio() print "VERIFY" data_received = () @@ -540,12 +545,14 @@ def main(show_help, erase, no_protect, reset_after_successful_write, stl.reset_sys() stl.run() stl.exit_debug() + else: + stl.finish_gpio() return 0 if __name__ == '__main__': show_help = False - erase = False + erase_only = False no_protect = False reset_after_successful_write = True skip_blank_check=True @@ -556,10 +563,12 @@ if __name__ == '__main__': while len(sys.argv) > 1: if sys.argv[1] == '-h': sys.argv.pop(1) + show_help = True break elif sys.argv[1] == '-e': sys.argv.pop(1) - erase = True + erase_only = True + skip_blank_check=False break elif sys.argv[1] == '-u': sys.argv.pop(1) @@ -586,7 +595,8 @@ if __name__ == '__main__': colorama_init() try: - r = main(show_help, erase, no_protect, reset_after_successful_write, + r = main(show_help, erase_only, no_protect, + reset_after_successful_write, skip_blank_check, status_only, unlock, data) if r == 0: print Fore.WHITE + Back.BLUE + Style.BRIGHT + "SUCCESS" + Style.RESET_ALL From 1118cd030a3f18b00d704ab68208d05e0616bebc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 25 Jun 2012 10:53:06 +0900 Subject: [PATCH 198/300] usb_strings.py --- ChangeLog | 4 +++ NEWS | 4 +++ tool/usb_strings.py | 60 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100755 tool/usb_strings.py diff --git a/ChangeLog b/ChangeLog index b971efd..c6c81b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-25 Niibe Yutaka + + * tool/usb_strings.py: New. + 2012-06-22 Niibe Yutaka * tool/stlinkv2.py (stlinkv2.blank_check): Add blank check of diff --git a/NEWS b/NEWS index 5695ab8..f3d1e29 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ Gnuk NEWS - User visible changes ** New tool: stlinkv2.py This tool is SWD flash ROM writer with ST-Link/V2. +** New tool: usb_strings.py +This tool is to dump USB strings, which include revision detail and config +options. + * Major changes in Gnuk 0.20 diff --git a/tool/usb_strings.py b/tool/usb_strings.py new file mode 100755 index 0000000..5d50c55 --- /dev/null +++ b/tool/usb_strings.py @@ -0,0 +1,60 @@ +#! /usr/bin/python + +""" +usb_strings.py - a tool to dump USB string + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +import usb, sys + +USB_VENDOR_FSIJ=0x234b +USB_PRODUCT_GNUK=0x0000 + +def gnuk_devices(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + if dev.idVendor != USB_VENDOR_FSIJ: + continue + if dev.idProduct != USB_PRODUCT_GNUK: + continue + yield dev + +title = [ '', 'Vendor', 'Product', 'Serial', 'Revision', 'Config', 'Sys' ] + +def main(n): + for dev in gnuk_devices(): + handle = dev.open() + print "Device: ", dev.filename + try: + for i in range(1,n): + str = handle.getString(i, 512) + print "%10s: %s" % (title[i], str) + except: + pass + del dev + +if __name__ == '__main__': + if len(sys.argv) > 1: + n = int(sys.argv[1]) + else: + n = 7 # Gnuk has seven strings + main(n) From a41476ab32c8ca74fed7bb82bafb2651179043b3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 26 Jun 2012 17:59:24 +0900 Subject: [PATCH 199/300] add test --- ChangeLog | 4 + test/README | 15 + test/features/000_empty_check.feature | 79 +++++ .../001_empty_check_passphrase.feature | 15 + test/features/002_get_data_static.feature | 27 ++ test/features/010_setup_passphrase.feature | 63 ++++ .../020_personalization_write.feature | 27 ++ .../features/021_personalization_read.feature | 27 ++ test/features/030_key_registration.feature | 18 + test/features/970_key_removal.feature | 39 +++ .../980_personalization_reset.feature | 27 ++ test/features/990_reset_passphrase.feature | 7 + test/features/steps.py | 76 ++++ test/generate_keys.py | 25 ++ test/gnuk.py | 329 ++++++++++++++++++ test/rsa-aut.key | 4 + test/rsa-dec.key | 4 + test/rsa-sig.key | 4 + test/rsa_keys.py | 52 +++ 19 files changed, 842 insertions(+) create mode 100644 test/README create mode 100644 test/features/000_empty_check.feature create mode 100644 test/features/001_empty_check_passphrase.feature create mode 100644 test/features/002_get_data_static.feature create mode 100644 test/features/010_setup_passphrase.feature create mode 100644 test/features/020_personalization_write.feature create mode 100644 test/features/021_personalization_read.feature create mode 100644 test/features/030_key_registration.feature create mode 100644 test/features/970_key_removal.feature create mode 100644 test/features/980_personalization_reset.feature create mode 100644 test/features/990_reset_passphrase.feature create mode 100644 test/features/steps.py create mode 100644 test/generate_keys.py create mode 100644 test/gnuk.py create mode 100644 test/rsa-aut.key create mode 100644 test/rsa-dec.key create mode 100644 test/rsa-sig.key create mode 100644 test/rsa_keys.py diff --git a/ChangeLog b/ChangeLog index c6c81b1..6118c5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-26 Niibe Yutaka + + * test: New. + 2012-06-25 Niibe Yutaka * tool/usb_strings.py: New. diff --git a/test/README b/test/README new file mode 100644 index 0000000..367ad44 --- /dev/null +++ b/test/README @@ -0,0 +1,15 @@ +This is functionality test suite for Gnuk. + +You need python-nose, python-freshen, and python-crypto as well as +python-usb. + + +Type: + + $ nosetests --with-freshen . + +or + + $ nosetests -v --with-freshen . + +to run the test suite. diff --git a/test/features/000_empty_check.feature b/test/features/000_empty_check.feature new file mode 100644 index 0000000..4f4d35e --- /dev/null +++ b/test/features/000_empty_check.feature @@ -0,0 +1,79 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no data, no keys) + + Scenario: data object Login + When requesting login data: 5e + Then you should get NULL + + Scenario: data object Name + When requesting name: 5b + Then you should get NULL + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get NULL + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get NULL + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get NULL + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x00 + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 + + Scenario: data object finger print 0 + When requesting finger print: c5 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object finger print 1 + When requesting finger print: c7 + Then you should get NULL + + Scenario: data object finger print 2 + When requesting finger print: c8 + Then you should get NULL + + Scenario: data object finger print 3 + When requesting finger print: c9 + Then you should get NULL + + Scenario: data object CA finger print 0 + When requesting finger print: c6 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object CA finger print 1 + When requesting finger print: ca + Then you should get NULL + + Scenario: data object CA finger print 2 + When requesting finger print: cb + Then you should get NULL + + Scenario: data object CA finger print 3 + When requesting finger print: cc + Then you should get NULL + + Scenario: data object date/time of key pair 0 + When requesting date/time of key pair: cd + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object date/time of key pair 1 + When requesting date/time of key pair: ce + Then you should get NULL + + Scenario: data object date/time of key pair 2 + When requesting date/time of key pair: cf + Then you should get NULL + + Scenario: data object date/time of key pair 3 + When requesting date/time of key pair: d0 + Then you should get NULL diff --git a/test/features/001_empty_check_passphrase.feature b/test/features/001_empty_check_passphrase.feature new file mode 100644 index 0000000..f026b08 --- /dev/null +++ b/test/features/001_empty_check_passphrase.feature @@ -0,0 +1,15 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no pass phrase) + + Scenario: verify PW1 factory setting (1) + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 factory setting (2) + Given cmd_verify with 2 and "123456" + Then it should get success + + Scenario: verify PW3 factory setting + Given cmd_verify with 3 and "12345678" + Then it should get success diff --git a/test/features/002_get_data_static.feature b/test/features/002_get_data_static.feature new file mode 100644 index 0000000..9de7425 --- /dev/null +++ b/test/features/002_get_data_static.feature @@ -0,0 +1,27 @@ +Feature: command GET DATA + In order to conform OpenPGP card 2.0 specification + A token should support all mandatory features of the specification + + Scenario: data object historical bytes + When requesting historical bytes: 5f52 + Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + + Scenario: data object extended capabilities + When requesting extended capabilities: c0 + Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + + Scenario: data object algorithm attributes 1 + When requesting algorithm attributes 1: c1 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 2 + When requesting algorithm attributes 2: c2 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 3 + When requesting algorighm attributes 3: c3 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object AID + When requesting AID: 4f + Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00 diff --git a/test/features/010_setup_passphrase.feature b/test/features/010_setup_passphrase.feature new file mode 100644 index 0000000..1ddcc23 --- /dev/null +++ b/test/features/010_setup_passphrase.feature @@ -0,0 +1,63 @@ +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW1 (admin-less mode) + Given cmd_change_reference_data with 1 and "123456user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) + Given cmd_verify with 1 and "user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) + Given cmd_verify with 2 and "user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "user pass phrase" + Then it should get success + + Scenario: setup reset code (in admin-less mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-less mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) again + Given cmd_verify with 3 and "new user pass phrase" + Then it should get success + + Scenario: setup PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "new user pass phraseadmin pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-full mode) + Given cmd_verify with 3 and "admin pass phrase" + Then it should get success + + Scenario: setup reset code (in admin-full mode) + Given cmd_put_data with d3 and "another reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-full mode) + Given cmd_reset_retry_counter with 0 and "another reset code 000another user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success diff --git a/test/features/020_personalization_write.feature b/test/features/020_personalization_write.feature new file mode 100644 index 0000000..2fdd387 --- /dev/null +++ b/test/features/020_personalization_write.feature @@ -0,0 +1,27 @@ +Feature: personalize token write + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + Given cmd_put_data with 5e and "gpg_user" + Then it should get success + + Scenario: data object Name + Given cmd_put_data with 5b and "GnuPG User" + Then it should get success + + Scenario: data object Language preference + Given cmd_put_data with 5f2d and "ja" + Then it should get success + + Scenario: data object Sex + Given cmd_put_data with 5f35 and "1" + Then it should get success + + Scenario: data object URL + Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" + Then it should get success + + Scenario: data object pw1 status bytes + Given cmd_put_data with c4 and "\x01" + Then it should get success diff --git a/test/features/021_personalization_read.feature b/test/features/021_personalization_read.feature new file mode 100644 index 0000000..5f0f972 --- /dev/null +++ b/test/features/021_personalization_read.feature @@ -0,0 +1,27 @@ +Feature: personalize token read + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + When requesting login data: 5e + Then you should get: gpg_user + + Scenario: data object Name + When requesting name: 5b + Then you should get: GnuPG User + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get: ja + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get: 1 + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get: http://www.fsij.org/gnuk/ + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 diff --git a/test/features/030_key_registration.feature b/test/features/030_key_registration.feature new file mode 100644 index 0000000..b71dc90 --- /dev/null +++ b/test/features/030_key_registration.feature @@ -0,0 +1,18 @@ +Feature: import keys to token + In order to use a token + A token should have keys + + Scenario: importing OPENPGP.1 key (sign) + Given a RSA key pair 0 + And importing it to the token as OPENPGP.1 + Then it should get success + + Scenario: importing OPENPGP.2 key (decrypt) + Given a RSA key pair 1 + And importing it to the token as OPENPGP.2 + Then it should get success + + Scenario: importing OPENPGP.3 key (authentication) + Given a RSA key pair 2 + And importing it to the token as OPENPGP.3 + Then it should get success diff --git a/test/features/970_key_removal.feature b/test/features/970_key_removal.feature new file mode 100644 index 0000000..5f89bc1 --- /dev/null +++ b/test/features/970_key_removal.feature @@ -0,0 +1,39 @@ +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success diff --git a/test/features/980_personalization_reset.feature b/test/features/980_personalization_reset.feature new file mode 100644 index 0000000..51a3430 --- /dev/null +++ b/test/features/980_personalization_reset.feature @@ -0,0 +1,27 @@ +Feature: removal of data objects + In order to use a token + A token should have personalized data + + Scenario: remove data object Login + Given cmd_put_data with 5e and "" + Then it should get success + + Scenario: remove data object Name + Given cmd_put_data with 5b and "" + Then it should get success + + Scenario: remove data object Language preference + Given cmd_put_data with 5f2d and "" + Then it should get success + + Scenario: remove data object Sex + Given cmd_put_data with 5f35 and "" + Then it should get success + + Scenario: remove data object URL + Given cmd_put_data with 5f50 and "" + Then it should get success + + Scenario: remove data object pw1 status bytes + Given cmd_put_data with c4 and "\x00" + Then it should get success diff --git a/test/features/990_reset_passphrase.feature b/test/features/990_reset_passphrase.feature new file mode 100644 index 0000000..853c515 --- /dev/null +++ b/test/features/990_reset_passphrase.feature @@ -0,0 +1,7 @@ +Feature: reset pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "admin pass phrase" + Then it should get success diff --git a/test/features/steps.py b/test/features/steps.py new file mode 100644 index 0000000..d9f27ca --- /dev/null +++ b/test/features/steps.py @@ -0,0 +1,76 @@ +from freshen import * +from freshen.checks import * +from nose.tools import assert_regexp_matches + +import ast + +import gnuk +import rsa_keys + +@Before +def ini(sc): + if not ftc.token: + ftc.token = gnuk.get_gnuk_device() + ftc.token.cmd_select_openpgp() + +@Given("cmd_verify with (.*) and \"(.*)\"") +def cmd_verify(who_str,pass_str): + who = int(who_str) + scc.result = ftc.token.cmd_verify(who, pass_str) + +@Given("cmd_change_reference_data with (.*) and \"(.*)\"") +def cmd_change_reference_data(who_str,pass_str): + who = int(who_str) + scc.result = ftc.token.cmd_change_reference_data(who, pass_str) + +@Given("cmd_put_data with (.*) and \"(.*)\"") +def cmd_put_data(tag_str,content_str): + tag = int(tag_str, 16) + tagh = tag >> 8 + tagl = tag & 0xff + scc.result = ftc.token.cmd_put_data(tagh, tagl, content_str) + +@Given("cmd_reset_retry_counter with (.*) and \"(.*)\"") +def cmd_reset_retry_counter(how_str, data): + how = int(how_str) + scc.result = ftc.token.cmd_reset_retry_counter(how, data) + +@Given("a RSA key pair (.*)") +def set_rsa_key(keyno_str): + scc.keyno = int(keyno_str) + +@Given("importing it to the token as OPENPGP.(.*)") +def import_key(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + t = rsa_keys.build_privkey_template(openpgp_keyno, scc.keyno) + scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t) + +@When("requesting (.+): ([0-9a-fA-F]+)") +def get_data(name, tag_str): + tag = int(tag_str, 16) + tagh = tag >> 8 + tagl = tag & 0xff + scc.result = ftc.token.cmd_get_data(tagh, tagl) + +@When("removing a key OPENPGP.(.*)") +def remove_key(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + t = rsa_keys.build_privkey_template_for_remove(openpgp_keyno) + scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t) + +@Then("you should get: (.*)") +def check_result(v): + value = ast.literal_eval("'" + v + "'") + assert_equal(scc.result, value) + +@Then("it should get success") +def check_success(): + assert_equal(scc.result, True) + +@Then("you should get NULL") +def check_null(): + assert_equal(scc.result, "") + +@Then("data should match: (.*)") +def check_regexp(re): + assert_regexp_matches(scc.result, re) diff --git a/test/generate_keys.py b/test/generate_keys.py new file mode 100644 index 0000000..8face41 --- /dev/null +++ b/test/generate_keys.py @@ -0,0 +1,25 @@ +from Crypto import Random +from Crypto.PublicKey import RSA +from binascii import hexlify + +def print_key_in_hex(k): + prv = k.exportKey(format='DER', pkcs=8) + n = prv[38:38+256] + e = prv[38+256+2:38+256+2+3] + p = prv[38+256+2+3+4+257+4:38+256+2+3+4+257+4+128] + q = prv[38+256+2+3+4+257+4+128+4:38+256+2+3+4+257+4+128+4+128] + n_str = hexlify(n) + e_str = hexlify(e) + p_str = hexlify(p) + q_str = hexlify(q) + if int(p_str, 16)*int(q_str, 16) != int(n_str, 16): + raise ValueError("wrong key", k) + print n_str + print e_str + print p_str + print q_str + +rng = Random.new().read +key = RSA.generate(2048, rng) + +print_key_in_hex(key) diff --git a/test/gnuk.py b/test/gnuk.py new file mode 100644 index 0000000..1ea47c2 --- /dev/null +++ b/test/gnuk.py @@ -0,0 +1,329 @@ +""" +gnuk.py - a library for Gnuk Token +This tool is for importing certificate, writing serial number, etc. + +Copyright (C) 2011, 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +from struct import * +import string + +# Assume only single CCID device is attached to computer, and it's Gnuk Token + +import usb + +# USB class, subclass, protocol +CCID_CLASS = 0x0B +CCID_SUBCLASS = 0x00 +CCID_PROTOCOL_0 = 0x00 + +def icc_compose(msg_type, data_len, slot, seq, param, data): + return pack('BBBB', cls, ins, p1, p2) + else: + return pack('>BBBBB', cls, ins, p1, p2, data_len) + data + +def list_to_string(l): + return string.join([chr(c) for c in l], '') + +class gnuk_token(object): + def __init__(self, device, configuration, interface): + """ + __init__(device, configuration, interface) -> None + Initialize the device. + device: usb.Device object. + configuration: configuration number. + interface: usb.Interface object representing the interface and altenate setting. + """ + if interface.interfaceClass != CCID_CLASS: + raise ValueError("Wrong interface class") + if interface.interfaceSubClass != CCID_SUBCLASS: + raise ValueError("Wrong interface sub class") + self.__devhandle = device.open() + try: + self.__devhandle.setConfiguration(configuration) + except: + pass + self.__devhandle.claimInterface(interface) + self.__devhandle.setAltInterface(interface) + + self.__intf = interface.interfaceNumber + self.__alt = interface.alternateSetting + self.__conf = configuration + + self.__bulkout = 1 + self.__bulkin = 0x81 + + self.__timeout = 10000 + self.__seq = 0 + + def reset_device(self): + try: + self.__devhandle.reset() + except: + pass + + def release_gnuk(self): + self.__devhandle.releaseInterface() + + def icc_get_result(self): + msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) + if len(msg) < 10: + print msg + raise ValueError("icc_get_result") + msg_type = msg[0] + data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) + slot = msg[5] + seq = msg[6] + status = msg[7] + error = msg[8] + chain = msg[9] + data = msg[10:] + # XXX: check msg_type, data_len, slot, seq, error + return (status, chain, data) + + def icc_get_status(self): + msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_power_on(self): + msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check status, chain + self.atr = list_to_string(data) # ATR + + def icc_power_off(self): + msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_send_data_block(self, data): + msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + return self.icc_get_result() + + def icc_send_cmd(self, data): + status, chain, data_rcv = self.icc_send_data_block(data) + if chain == 0: + return data_rcv + elif chain == 1: + d = data_rcv + while True: + msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data_rcv = self.icc_get_result() + # XXX: check status + d += data_rcv + if chain == 2: + break + elif chain == 3: + continue + else: + raise ValueError("icc_send_cmd chain") + return d + else: + raise ValueError("icc_send_cmd") + + def cmd_get_response(self, expected_len): + result = [] + while True: + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) + response = self.icc_send_cmd(cmd_data) + result += response[:-2] + sw = response[-2:] + if sw[0] == 0x90 and sw[1] == 0x00: + return list_to_string(result) + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + else: + expected_len = sw[1] + + def cmd_verify(self, who, passwd): + cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_read_binary(self, fileid): + cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_write_binary(self, fileid, data, is_update): + count = 0 + data_len = len(data) + if is_update: + ins = 0xd6 + else: + ins = 0xd0 + while count*256 < data_len: + if count == 0: + if len(data) < 128: + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10) + cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256]) + else: + if len(data[256*count:256*count+128]) < 128: + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10) + cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError("cmd_write_binary 0") + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("cmd_write_binary 0", "%02x%02x" % (sw[0], sw[1])) + if cmd_data1: + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError("cmd_write_binary", sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("cmd_write_binary", "%02x%02x" % (sw[0], sw[1])) + count += 1 + + def cmd_select_openpgp(self): + cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_get_data(self, tagh, tagl): + cmd_data = iso7816_compose(0xca, tagh, tagl, "") + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_change_reference_data(self, who, data): + cmd_data = iso7816_compose(0x24, 0x00, 0x80+who, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_put_data(self, tagh, tagl, content): + cmd_data = iso7816_compose(0xda, tagh, tagl, content) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_put_data_odd(self, tagh, tagl, content): + cmd_data0 = iso7816_compose(0xdb, tagh, tagl, content[:128], 0x10) + cmd_data1 = iso7816_compose(0xdb, tagh, tagl, content[128:]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_reset_retry_counter(self, how, data): + cmd_data = iso7816_compose(0x2c, how, 0x00, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + + +def compare(data_original, data_in_device): + i = 0 + for d in data_original: + if ord(d) != data_in_device[i]: + raise ValueError, "verify failed at %08x" % i + i += 1 + +def gnuk_devices(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + for config in dev.configurations: + for intf in config.interfaces: + for alt in intf: + if alt.interfaceClass == CCID_CLASS and \ + alt.interfaceSubClass == CCID_SUBCLASS and \ + alt.interfaceProtocol == CCID_PROTOCOL_0: + yield dev, config, alt + +def get_gnuk_device(): + icc = None + for (dev, config, intf) in gnuk_devices(): + try: + icc = gnuk_token(dev, config, intf) + print "Device: ", dev.filename + print "Configuration: ", config.value + print "Interface: ", intf.interfaceNumber + break + except: + pass + if not icc: + raise ValueError("No ICC present") + status = icc.icc_get_status() + if status == 0: + pass # It's ON already + elif status == 1: + icc.icc_power_on() + else: + raise ValueError("Unknown ICC status", status) + return icc diff --git a/test/rsa-aut.key b/test/rsa-aut.key new file mode 100644 index 0000000..cdf2d5e --- /dev/null +++ b/test/rsa-aut.key @@ -0,0 +1,4 @@ +9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9 +010001 +b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907 +dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf diff --git a/test/rsa-dec.key b/test/rsa-dec.key new file mode 100644 index 0000000..8c2aa47 --- /dev/null +++ b/test/rsa-dec.key @@ -0,0 +1,4 @@ +d392714c29738aac6372f2c8654a08c25a1299fed7004bd512cd2452b503ebad6301130816ac525ba528dc155be6347a5c70407fb4fbdaed751dfc0a7cd5e3910272ff236c4ed1ce5de6620b191a172e5b247347b8cab73a43d79221708755c959a2f83f486439da30917384554331532aabc8326db48866f8c91198834a86ab94679f6175db737bdf399e3f0b737dcb1f4208279d3e1cc694e78686785e4f363a377dec912b7c2f757b1422d866fb9fa85c96b83adfd6a223989a9a02988bdee81ad17eff6385e7b38cec8611fdf367ba4ac8e90d5f48ac7715c5f47aea06a4a37cdaa3029ce59d29bc66853bf6758ef4a7da5a5953f5e557a5a22f67c368c3 +010001 +dae085952c5beee38f25f09bc37a4ca2434c31f78055469d0d5f0bf3337e3a70ba6c91734f195b742e211a5fe283befdf66820008e6ef2c8ca54a91922838fce07d9e33a331ce20dac36803e777d5ee2195ed28d6a4045e28623a6a60b0661e45f7c4f84ae2b1dfad0cf1ec30605158323382a819e730c09a33fad704dd67501 +f774be43ea198aa2f089274e4fffd7d0092ee7b35a1d2f854cdb166f698caab72fdeb099e690e78438b2e043e452d4d2f19d7f44ba6b286642f0ce5204966ff98ecd9e3b448877324631365dc860797429b9414a21a7e166d504cace156588b9a145657eeb1afb43b8ff65d8d6d93cea2ba4ef8aab047885c4de64ffef0b49c3 diff --git a/test/rsa-sig.key b/test/rsa-sig.key new file mode 100644 index 0000000..c83179a --- /dev/null +++ b/test/rsa-sig.key @@ -0,0 +1,4 @@ +c6c877dfd3b441f8fb1b8dc504093a51c2efe4883fe0a6379205acc6e673709905e4d767ddf46143c535cc6d7f10b616f520d8346320ef69ff4a2c4f4a148edc65f7ad24ed7d4fe23bb862a0ae71f4f7904abac0397abf3213df91326b1a25554b3b18cf54584d8bf220169fc92b2aa511e8313983e72b4c9110b3a1aea087aebef95873865608e8faea9ef10e7f7f3a66ca8def2d499c3149c127491e0e4339fd6abe10bfc6c13e43d522004f1485767328eabe35d6ffa8df4c15f0fbcd4eb1c07cc6d85e275139ac69e2962273ae987236926dd6c1144fce3e7ae567fa58ea60620dfafc52f95299fea601739fce27ee71eea978d0074f21e7086f60ba8331 +010001 +cc365b5702714bf203e8c49b0b8afa8dad586e929cf5edca38ad07fa45efd5c2d89022d29f40283a57e50ca24c5f28c8e911a74faaf796f112e7e48195956f9a4df7668a5342523b27179cec958f363211ee11d0ec0e0e1b92ca007a61e8c9ac14e00229b9a7624850199e6667afa1a44db8f3c5de0a8eef0e6de050ac0ac633 +f931a3c12f0e3a5276f712b7706590ba02e14a97ff9b8ce3152af0fc4d9cdc690ea9bc4c82cb16c7d23136cbdab58fbec69880a88bca85c4214df01045082cbe9f4192e3e39c79896533c37dad9eb9e73c2643b9c0a704a4f93d81573537963d6b6e5140a24c702d9f26e06a2095de906daa8824172a6b39f563b7153907050b diff --git a/test/rsa_keys.py b/test/rsa_keys.py new file mode 100644 index 0000000..698fbe3 --- /dev/null +++ b/test/rsa_keys.py @@ -0,0 +1,52 @@ +from binascii import unhexlify + +def read_key_from_file(file): + f = open(file) + n_str = f.readline()[:-1] + e_str = f.readline()[:-1] + p_str = f.readline()[:-1] + q_str = f.readline()[:-1] + f.close() + e = int(e_str, 16) + p = int(p_str, 16) + q = int(q_str, 16) + n = int(n_str, 16) + if n != p * q: + raise ValueError("wrong key", p, q, n) + return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str)) + +key = [ None, None, None ] +key[0] = read_key_from_file('rsa-sig.key') +key[1] = read_key_from_file('rsa-dec.key') +key[2] = read_key_from_file('rsa-aut.key') + +def build_privkey_template(openpgp_keyno, keyno): + n_str = key[keyno][0] + e_str = '\x00' + key[keyno][1] + p_str = key[keyno][2] + q_str = key[keyno][3] + + if openpgp_keyno == 1: + keyspec = '\xb6' + elif openpgp_keyno == 2: + keyspec = '\xb8' + else: + keyspec = '\xa4' + + key_template = '\x91\x04'+ '\x92\x81\x80' + '\x93\x81\x80' + + exthdr = keyspec + '\x00' + '\x7f\x48' + '\x08' + key_template + + suffix = '\x5f\x48' + '\x82\x01\x04' + + t = '\x4d' + '\x82\01\16' + exthdr + suffix + e_str + p_str + q_str + return t + +def build_privkey_template_for_remove(openpgp_keyno): + if openpgp_keyno == 1: + keyspec = '\xb6' + elif openpgp_keyno == 2: + keyspec = '\xb8' + else: + keyspec = '\xa4' + return '\x4d\02' + keyspec + '\0x00' From 3c7a5bff61cf62b21f7a3262c5f15cf2821f7a40 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 08:06:39 +0900 Subject: [PATCH 200/300] fix string handling --- test/features/steps.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/features/steps.py b/test/features/steps.py index d9f27ca..9d2cc77 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -23,8 +23,9 @@ def cmd_change_reference_data(who_str,pass_str): who = int(who_str) scc.result = ftc.token.cmd_change_reference_data(who, pass_str) -@Given("cmd_put_data with (.*) and \"(.*)\"") -def cmd_put_data(tag_str,content_str): +@Given("cmd_put_data with (.*) and (\".*\")") +def cmd_put_data(tag_str,content_str_repr): + content_str = ast.literal_eval(content_str_repr) tag = int(tag_str, 16) tagh = tag >> 8 tagl = tag & 0xff From e11d81376c7a485add2899a7dc32bb3787bf5280 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 08:48:41 +0900 Subject: [PATCH 201/300] key fingerprint and timestamp --- test/features/030_key_registration.feature | 30 ++++++++++++++++++++++ test/features/steps.py | 17 ++++++++++++ test/rsa_keys.py | 19 ++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/test/features/030_key_registration.feature b/test/features/030_key_registration.feature index b71dc90..73f1c10 100644 --- a/test/features/030_key_registration.feature +++ b/test/features/030_key_registration.feature @@ -16,3 +16,33 @@ Feature: import keys to token Given a RSA key pair 2 And importing it to the token as OPENPGP.3 Then it should get success + + Scenario: setup data object Finger print sig + Given a fingerprint of OPENPGP.1 key + And put the data to c7 + Then it should get success + + Scenario: setup data object Finger print dec + Given a fingerprint of OPENPGP.2 key + And put the data to c8 + Then it should get success + + Scenario: setup data object Finger print aut + Given a fingerprint of OPENPGP.3 key + And put the data to c9 + Then it should get success + + Scenario: setup data object keygeneration data/time sig + Given a timestamp of OPENPGP.1 key + And put the data to ce + Then it should get success + + Scenario: setup data object keygeneration data/time dec + Given a timestamp of OPENPGP.2 key + And put the data to cf + Then it should get success + + Scenario: setup data object keygeneration data/time aut + Given a timestamp of OPENPGP.3 key + And put the data to d0 + Then it should get success diff --git a/test/features/steps.py b/test/features/steps.py index 9d2cc77..dfe798b 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -46,6 +46,23 @@ def import_key(openpgp_keyno_str): t = rsa_keys.build_privkey_template(openpgp_keyno, scc.keyno) scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t) +@Given("a fingerprint of OPENPGP.(.*) key") +def get_key_fpr(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + scc.result = rsa_keys.fpr[openpgp_keyno - 1] + +@Given("a timestamp of OPENPGP.(.*) key") +def get_key_timestamp(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + scc.result = rsa_keys.timestamp[openpgp_keyno - 1] + +@Given("put the data to (.*)") +def cmd_put_data_with_result(tag_str): + tag = int(tag_str, 16) + tagh = tag >> 8 + tagl = tag & 0xff + scc.result = ftc.token.cmd_put_data(tagh, tagl, scc.result) + @When("requesting (.+): ([0-9a-fA-F]+)") def get_data(name, tag_str): tag = int(tag_str, 16) diff --git a/test/rsa_keys.py b/test/rsa_keys.py index 698fbe3..b81f551 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -1,4 +1,7 @@ from binascii import unhexlify +from time import time +from struct import pack +from hashlib import sha1 def read_key_from_file(file): f = open(file) @@ -15,11 +18,27 @@ def read_key_from_file(file): raise ValueError("wrong key", p, q, n) return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str)) +def calc_fpr(n,e): + timestamp = int(time()) + timestamp_data = pack('>I', timestamp) + m_len = 6 + 2 + 256 + 2 + 4 + m = '\x99' + pack('>H', m_len) + '\x04' + timestamp_data + '\x01' + \ + pack('>H', 2048) + n + pack('>H', 17) + e + fpr = sha1(m).digest() + return (fpr, timestamp_data) + key = [ None, None, None ] +fpr = [ None, None, None ] +timestamp = [ None, None, None ] + key[0] = read_key_from_file('rsa-sig.key') key[1] = read_key_from_file('rsa-dec.key') key[2] = read_key_from_file('rsa-aut.key') +(fpr[0], timestamp[0]) = calc_fpr(key[0][0], key[0][1]) +(fpr[1], timestamp[1]) = calc_fpr(key[1][0], key[1][1]) +(fpr[2], timestamp[2]) = calc_fpr(key[2][0], key[2][1]) + def build_privkey_template(openpgp_keyno, keyno): n_str = key[keyno][0] e_str = '\x00' + key[keyno][1] From 1944a78443ec096bbd886f5b1a232218e0d9e4a6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 13:10:12 +0900 Subject: [PATCH 202/300] PW3 handling and signature counter --- ChangeLog | 10 ++++++++++ src/openpgp-do.c | 52 +++++++++++++++++++++++++++++------------------- src/openpgp.c | 12 ++++++++--- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6118c5a..d022e99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2012-06-27 Niibe Yutaka + + * src/openpgp.c (cmd_change_password): Support resetting to + factory setting of PW3. + + * src/openpgp-do.c (gpg_do_write_prvkey): Don't reset signagure + counter here. + (proc_key_import): But reset here. + Call ac_reset_* when key is imported. + 2012-06-26 Niibe Yutaka * test: New. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index d9c0406..34dc824 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -793,10 +793,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE); if (kk == GPG_KEY_FOR_SIGNING) - { - ac_reset_pso_cds (); - gpg_reset_digital_signature_counter (); - } + ac_reset_pso_cds (); else ac_reset_other (); @@ -924,11 +921,19 @@ proc_key_import (const uint8_t *data, int len) p += 1; if (*p == 0xb6) - kk = GPG_KEY_FOR_SIGNING; - else if (*p == 0xb8) - kk = GPG_KEY_FOR_DECRYPTION; - else /* 0xa4 */ - kk = GPG_KEY_FOR_AUTHENTICATION; + { + kk = GPG_KEY_FOR_SIGNING; + ac_reset_pso_cds (); + gpg_reset_digital_signature_counter (); + } + else + { + if (*p == 0xb8) + kk = GPG_KEY_FOR_DECRYPTION; + else /* 0xa4 */ + kk = GPG_KEY_FOR_AUTHENTICATION; + ac_reset_other (); + } if (len <= 22) { /* Deletion of the key */ @@ -948,6 +953,11 @@ proc_key_import (const uint8_t *data, int len) /* Delete PW1 and RC if any */ gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0); gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0); + + ac_reset_pso_cds (); + ac_reset_other (); + if (keystring_admin == NULL) + ac_reset_admin (); } return 1; @@ -1086,18 +1096,18 @@ gpg_data_scan (const uint8_t *p_start) } else switch (nr) - { - case NR_BOOL_PW1_LIFETIME: - pw1_lifetime_p = p - 1; - p++; - continue; - case NR_COUNTER_123: - p++; - if (second_byte <= PW_ERR_PW3) - pw_err_counter_p[second_byte] = p; - p += 2; - break; - } + { + case NR_BOOL_PW1_LIFETIME: + pw1_lifetime_p = p - 1; + p++; + continue; + case NR_COUNTER_123: + p++; + if (second_byte <= PW_ERR_PW3) + pw_err_counter_p[second_byte] = p; + p += 2; + break; + } } } diff --git a/src/openpgp.c b/src/openpgp.c index 966d017..7636518 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -220,8 +220,7 @@ cmd_change_password (void) uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */ uint8_t p2 = P2 (apdu); int len; - const uint8_t *pw; - const uint8_t *newpw; + uint8_t *pw, *newpw; int pw_len, newpw_len; int who = p2 - 0x80; int who_old; @@ -284,7 +283,14 @@ cmd_change_password (void) { newpw = pw + pw_len; newpw_len = len - pw_len; - gpg_set_pw3 (newpw, newpw_len); + if (newpw_len == 0 && admin_authorized == BY_ADMIN) + { + newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len); + gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0); + } + else + gpg_set_pw3 (newpw, newpw_len); who_old = admin_authorized; } } From 92d500d4b5a7d04f8932889a7d6fcb5bc8a7e271 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 14:14:15 +0900 Subject: [PATCH 203/300] bug fix flash write and flash access before that while flash GC --- ChangeLog | 4 ++++ src/openpgp-do.c | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d022e99..5747b88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-06-27 Niibe Yutaka + * src/openpgp-do.c (gpg_do_chks_prvkey): Call flash_do_release before + flash_do_write. + (gpg_do_write_prvkey): Bug fix when GC occurs. + * src/openpgp.c (cmd_change_password): Support resetting to factory setting of PW3. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 34dc824..baa589b 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -829,6 +829,13 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (++num_prv_keys == NUM_ALL_PRV_KEYS) /* All keys are registered. */ { + /* + * It is needed to read again after flash_do_write. + * Because GC for flash ROM could happen. + */ + ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); + ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); + /* Remove contents of keystrings from DO, but length */ if (ks_pw1) { @@ -865,7 +872,9 @@ gpg_do_chks_prvkey (enum kind_of_key kk, if (pd == NULL) return -1; - memcpy (pd, &(do_data)[1], sizeof (struct prvkey_data)); + memcpy (pd, &do_data[1], sizeof (struct prvkey_data)); + flash_do_release (do_data); + dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE + DATA_ENCRYPTION_KEY_SIZE * who_old; memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE); @@ -877,7 +886,6 @@ gpg_do_chks_prvkey (enum kind_of_key kk, p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); do_ptr[nr - NR_DO__FIRST__] = p; - flash_do_release (do_data); free (pd); if (p == NULL) return -1; From 839b0156a91874da67e0af9475a862370e1ec01b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 14:15:51 +0900 Subject: [PATCH 204/300] more tests --- ChangeLog | 3 + test/README | 6 +- test/features/030_key_registration.feature | 8 +++ test/features/100_compute_signature.feature | 31 +++++++++ test/features/101_decryption.feature | 16 +++++ test/features/steps.py | 41 ++++++++++++ test/gnuk.py | 36 ++++++++++ test/rsa_keys.py | 74 ++++++++++++++++++++- 8 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 test/features/100_compute_signature.feature create mode 100644 test/features/101_decryption.feature diff --git a/ChangeLog b/ChangeLog index 5747b88..7138295 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-06-27 Niibe Yutaka + * test/features/101_decryption.feature: New. + * test/features/100_compute_signature.feature: New. + * src/openpgp-do.c (gpg_do_chks_prvkey): Call flash_do_release before flash_do_write. (gpg_do_write_prvkey): Bug fix when GC occurs. diff --git a/test/README b/test/README index 367ad44..6ead706 100644 --- a/test/README +++ b/test/README @@ -1,7 +1,9 @@ This is functionality test suite for Gnuk. -You need python-nose, python-freshen, and python-crypto as well as -python-usb. +You need python-nose, python-freshen as well as python-usb. + +Besides, python-crypto is needed when you use generate_keys.py to +update *.key. Type: diff --git a/test/features/030_key_registration.feature b/test/features/030_key_registration.feature index 73f1c10..4381307 100644 --- a/test/features/030_key_registration.feature +++ b/test/features/030_key_registration.feature @@ -46,3 +46,11 @@ Feature: import keys to token Given a timestamp of OPENPGP.3 key And put the data to d0 Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success diff --git a/test/features/100_compute_signature.feature b/test/features/100_compute_signature.feature new file mode 100644 index 0000000..67fcbcc --- /dev/null +++ b/test/features/100_compute_signature.feature @@ -0,0 +1,31 @@ +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x02 diff --git a/test/features/101_decryption.feature b/test/features/101_decryption.feature new file mode 100644 index 0000000..1985dee --- /dev/null +++ b/test/features/101_decryption.feature @@ -0,0 +1,16 @@ +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + diff --git a/test/features/steps.py b/test/features/steps.py index dfe798b..00a5af7 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -1,6 +1,7 @@ from freshen import * from freshen.checks import * from nose.tools import assert_regexp_matches +from binascii import hexlify import ast @@ -63,6 +64,38 @@ def cmd_put_data_with_result(tag_str): tagl = tag & 0xff scc.result = ftc.token.cmd_put_data(tagh, tagl, scc.result) +@Given("a message (\".*\")") +def set_msg(content_str_repr): + msg = ast.literal_eval(content_str_repr) + scc.digestinfo = rsa_keys.compute_digestinfo(msg) + +@Given("let a token compute digital signature") +def compute_signature(): + scc.sig = int(hexlify(ftc.token.cmd_pso(0x9e, 0x9a, scc.digestinfo)),16) + +@Given("let a token authenticate") +def internal_authenticate(): + scc.sig = int(hexlify(ftc.token.cmd_internal_authenticate(scc.digestinfo)),16) + +@Given("compute digital signature on host with RSA key pair (.*)") +def compute_signature_on_host(keyno_str): + keyno = int(keyno_str) + scc.result = rsa_keys.compute_signature(keyno, scc.digestinfo) + +@Given("a plain text (\".*\")") +def set_plaintext(content_str_repr): + scc.plaintext = ast.literal_eval(content_str_repr) + +@Given("encrypt it on host with RSA key pair (.*)") +def encrypt_on_host(keyno_str): + keyno = int(keyno_str) + scc.ciphertext = rsa_keys.encrypt(keyno, scc.plaintext) + +@Given("let a token decrypt encrypted data") +def decrypt(): + scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext) + + @When("requesting (.+): ([0-9a-fA-F]+)") def get_data(name, tag_str): tag = int(tag_str, 16) @@ -92,3 +125,11 @@ def check_null(): @Then("data should match: (.*)") def check_regexp(re): assert_regexp_matches(scc.result, re) + +@Then("results should be same") +def check_signature(): + assert_equal(scc.sig, scc.result) + +@Then("decrypted data should be same as a plain text") +def check_decrypt(): + assert_equal(scc.plaintext, scc.result) diff --git a/test/gnuk.py b/test/gnuk.py index 1ea47c2..11a235f 100644 --- a/test/gnuk.py +++ b/test/gnuk.py @@ -284,6 +284,42 @@ class gnuk_token(object): raise ValueError("%02x%02x" % (sw[0], sw[1])) return True + def cmd_pso(self, p1, p2, data): + cmd_data = iso7816_compose(0x2a, p1, p2, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_pso_longdata(self, p1, p2, data): + cmd_data0 = iso7816_compose(0x2a, p1, p2, data[:128], 0x10) + cmd_data1 = iso7816_compose(0x2a, p1, p2, data[128:]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError(sw) + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_internal_authenticate(self, data): + cmd_data = iso7816_compose(0x88, 0, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) def compare(data_original, data_in_device): diff --git a/test/rsa_keys.py b/test/rsa_keys.py index b81f551..3df5a0d 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -1,7 +1,9 @@ -from binascii import unhexlify +from binascii import hexlify, unhexlify from time import time from struct import pack -from hashlib import sha1 +from hashlib import sha1, sha256 +import string +from os import urandom def read_key_from_file(file): f = open(file) @@ -16,7 +18,7 @@ def read_key_from_file(file): n = int(n_str, 16) if n != p * q: raise ValueError("wrong key", p, q, n) - return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str)) + return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str), e, p, q, n) def calc_fpr(n,e): timestamp = int(time()) @@ -69,3 +71,69 @@ def build_privkey_template_for_remove(openpgp_keyno): else: keyspec = '\xa4' return '\x4d\02' + keyspec + '\0x00' + +def compute_digestinfo(msg): + digest = sha256(msg).digest() + prefix = '\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20' + return prefix + digest + +# egcd and modinv are from wikibooks +# https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm + +def egcd(a, b): + if a == 0: + return (b, 0, 1) + else: + g, y, x = egcd(b % a, a) + return (g, x - (b // a) * y, y) + +def modinv(a, m): + g, x, y = egcd(a, m) + if g != 1: + raise Exception('modular inverse does not exist') + else: + return x % m + +def pkcs1_pad_for_sign(digestinfo): + byte_repr = '\x00' + '\x01' + string.ljust('', 256 - 19 - 32 - 3, '\xff') \ + + '\x00' + digestinfo + return int(hexlify(byte_repr), 16) + +def pkcs1_pad(msg): + padlen = 256 - 3 - len(msg) + byte_repr = '\x00' + '\x02' \ + + string.replace(urandom(padlen),'\x00','\x01') + '\x00' + msg + return int(hexlify(byte_repr), 16) + +def compute_signature(keyno, digestinfo): + e = key[keyno][4] + p = key[keyno][5] + q = key[keyno][6] + n = key[keyno][7] + p1 = p - 1 + q1 = q - 1 + h = p1 * q1 + d = modinv(e, h) + dp = d % p1 + dq = d % q1 + qp = modinv(q, p) + + input = pkcs1_pad_for_sign(digestinfo) + t1 = pow(input, dp, p) + t2 = pow(input, dq, q) + t = ((t1 - t2) * qp) % p + sig = t2 + t * q + return sig + +def integer_to_bytes(i): + s = hex(i)[2:] + s = s.rstrip('L') + if len(s) & 1: + s = '0' + s + return unhexlify(s) + +def encrypt(keyno, plaintext): + e = key[keyno][4] + n = key[keyno][7] + m = pkcs1_pad(plaintext) + return '\x00' + integer_to_bytes(pow(m, e, n)) From d564e4a3c10459beab735cfbce72cda70b424bae Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 27 Jun 2012 14:30:39 +0900 Subject: [PATCH 205/300] cleanup --- src/openpgp-do.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/openpgp-do.c b/src/openpgp-do.c index baa589b..ed5dd6a 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -724,6 +724,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, const uint8_t *ks_rc; struct key_data_internal kdi; int modulus_allocated_here = 0; + uint8_t ks_pw1_len = 0; + uint8_t ks_rc_len = 0; DEBUG_INFO ("Key import\r\n"); DEBUG_SHORT (key_len); @@ -798,7 +800,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, ac_reset_other (); if (ks_pw1) - encrypt_dek (ks_pw1+1, pd->dek_encrypted_1); + { + ks_pw1_len = ks_pw1[0]; + encrypt_dek (ks_pw1+1, pd->dek_encrypted_1); + } else { uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; @@ -810,7 +815,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, } if (ks_rc) - encrypt_dek (ks_rc+1, pd->dek_encrypted_2); + { + ks_rc_len = ks_rc[0]; + encrypt_dek (ks_rc+1, pd->dek_encrypted_2); + } else memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); @@ -829,25 +837,12 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (++num_prv_keys == NUM_ALL_PRV_KEYS) /* All keys are registered. */ { - /* - * It is needed to read again after flash_do_write. - * Because GC for flash ROM could happen. - */ - ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); - /* Remove contents of keystrings from DO, but length */ - if (ks_pw1) - { - uint8_t ks_pw1_len = ks_pw1[0]; - gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1); - } + if (ks_pw1_len) + gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1); - if (ks_rc) - { - uint8_t ks_rc_len = ks_rc[0]; - gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1); - } + if (ks_rc_len) + gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1); } return 0; From 0988474d87f050c7bd0e6fa7f7d0c7d9a5ee65fa Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 09:03:15 +0900 Subject: [PATCH 206/300] adding to gnuk.py --- ChangeLog | 6 ++++++ test/gnuk.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7138295..20086fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-06-28 Niibe Yutaka + + * test/gnuk.py (gnuk_token): New method: increment_seq. + (icc_send_cmd): Handle timeout. + (cmd_genkey): New. + 2012-06-27 Niibe Yutaka * test/features/101_decryption.feature: New. diff --git a/test/gnuk.py b/test/gnuk.py index 11a235f..d6564dd 100644 --- a/test/gnuk.py +++ b/test/gnuk.py @@ -77,6 +77,9 @@ class gnuk_token(object): self.__timeout = 10000 self.__seq = 0 + def increment_seq(self): + self.__seq = (self.__seq + 1) & 0xff + def reset_device(self): try: self.__devhandle.reset() @@ -105,7 +108,7 @@ class gnuk_token(object): def icc_get_status(self): msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check chain, data return status @@ -113,7 +116,7 @@ class gnuk_token(object): def icc_power_on(self): msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check status, chain self.atr = list_to_string(data) # ATR @@ -121,7 +124,7 @@ class gnuk_token(object): def icc_power_off(self): msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check chain, data return status @@ -129,19 +132,21 @@ class gnuk_token(object): def icc_send_data_block(self, data): msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() return self.icc_get_result() def icc_send_cmd(self, data): status, chain, data_rcv = self.icc_send_data_block(data) if chain == 0: + while status == 0x80: + status, chain, data_rcv = self.icc_get_result() return data_rcv elif chain == 1: d = data_rcv while True: msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data_rcv = self.icc_get_result() # XXX: check status d += data_rcv @@ -321,6 +326,24 @@ class gnuk_token(object): raise ValueError("%02x%02x" % (sw[0], sw[1])) return self.cmd_get_response(sw[1]) + def cmd_genkey(self, keyno): + if keyno == 1: + data = '\xb6\x00' + elif keyno == 2: + data = '\xb8\x00' + else: + data = '\xa4\x00' + cmd_data = iso7816_compose(0x47, 0x80, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + pk = self.cmd_get_response(sw[1]) + return (pk[9:9+256], pk[9+256+2:9+256+2+3]) + def compare(data_original, data_in_device): i = 0 From 9cc6de9e65bba72787b21f35883d58531ad4358e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 09:04:06 +0900 Subject: [PATCH 207/300] naming: make it clear for crypt --- test/rsa_keys.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rsa_keys.py b/test/rsa_keys.py index 3df5a0d..a130377 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -99,7 +99,7 @@ def pkcs1_pad_for_sign(digestinfo): + '\x00' + digestinfo return int(hexlify(byte_repr), 16) -def pkcs1_pad(msg): +def pkcs1_pad_for_crypt(msg): padlen = 256 - 3 - len(msg) byte_repr = '\x00' + '\x02' \ + string.replace(urandom(padlen),'\x00','\x01') + '\x00' + msg @@ -135,5 +135,5 @@ def integer_to_bytes(i): def encrypt(keyno, plaintext): e = key[keyno][4] n = key[keyno][7] - m = pkcs1_pad(plaintext) + m = pkcs1_pad_for_crypt(plaintext) return '\x00' + integer_to_bytes(pow(m, e, n)) From 19e677ae74ce46935dc14a9c53a6936951d84d80 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 09:30:16 +0900 Subject: [PATCH 208/300] add keygen test --- test/features/200_key_removal.feature | 40 +++++++++++++++++++++++++++ test/features/201_keygen.feature | 22 +++++++++++++++ test/features/steps.py | 21 ++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 test/features/200_key_removal.feature create mode 100644 test/features/201_keygen.feature diff --git a/test/features/200_key_removal.feature b/test/features/200_key_removal.feature new file mode 100644 index 0000000..2582c25 --- /dev/null +++ b/test/features/200_key_removal.feature @@ -0,0 +1,40 @@ +@keygen +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success diff --git a/test/features/201_keygen.feature b/test/features/201_keygen.feature new file mode 100644 index 0000000..472ccde --- /dev/null +++ b/test/features/201_keygen.feature @@ -0,0 +1,22 @@ +@keygen +Feature: key generation + In order to use a token + A token should have keys + + Scenario: generate OPENPGP.1 key (sign) + When generating a key of OPENPGP.1 + And put the first data to c7 + And put the second data to ce + Then it should get success + + Scenario: generate OPENPGP.2 key (decrypt) + When generating a key of OPENPGP.2 + And put the first data to c8 + And put the second data to cf + Then it should get success + + Scenario: generate OPENPGP.3 key (authentication) + When generating a key of OPENPGP.3 + And put the first data to c9 + And put the second data to d0 + Then it should get success diff --git a/test/features/steps.py b/test/features/steps.py index 00a5af7..030577e 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -109,6 +109,27 @@ def remove_key(openpgp_keyno_str): t = rsa_keys.build_privkey_template_for_remove(openpgp_keyno) scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t) +@When("generating a key of OPENPGP.(.*)") +def generate_key(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + pubkey_info = ftc.token.cmd_genkey(openpgp_keyno) + scc.data = rsa_keys.calc_fpr(pubkey_info[0], pubkey_info[1]) + +@When("put the first data to (.*)") +def cmd_put_data_first_with_result(tag_str): + tag = int(tag_str, 16) + tagh = tag >> 8 + tagl = tag & 0xff + scc.result = ftc.token.cmd_put_data(tagh, tagl, scc.data[0]) + +@When("put the second data to (.*)") +def cmd_put_data_second_with_result(tag_str): + tag = int(tag_str, 16) + tagh = tag >> 8 + tagl = tag & 0xff + result = ftc.token.cmd_put_data(tagh, tagl, scc.data[1]) + scc.result = (scc.result and result) + @Then("you should get: (.*)") def check_result(v): value = ast.literal_eval("'" + v + "'") From 3202b7d45cd99209b365fb4721e9a0eb6f1ee3df Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 11:06:36 +0900 Subject: [PATCH 209/300] add test for digital signature after keygen --- ChangeLog | 7 ++-- test/features/201_setup_passphrase.feature | 32 +++++++++++++++++ ...{201_keygen.feature => 202_keygen.feature} | 8 +++++ test/features/203_compute_signature.feature | 36 +++++++++++++++++++ test/features/steps.py | 9 +++++ test/gnuk.py | 16 +++++++++ test/rsa_keys.py | 7 ++++ 7 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 test/features/201_setup_passphrase.feature rename test/features/{201_keygen.feature => 202_keygen.feature} (71%) create mode 100644 test/features/203_compute_signature.feature diff --git a/ChangeLog b/ChangeLog index 20086fe..52511a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,11 @@ 2012-06-28 Niibe Yutaka * test/gnuk.py (gnuk_token): New method: increment_seq. - (icc_send_cmd): Handle timeout. - (cmd_genkey): New. + (gnuk_token.icc_send_cmd): Handle timeout. + (gnuk_token.cmd_genkey): New. + (gnuk_token.cmd_get_public_key): New. + + * test/rsa_keys.py (verify_signature): New. 2012-06-27 Niibe Yutaka diff --git a/test/features/201_setup_passphrase.feature b/test/features/201_setup_passphrase.feature new file mode 100644 index 0000000..554c169 --- /dev/null +++ b/test/features/201_setup_passphrase.feature @@ -0,0 +1,32 @@ +@keygen +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW1 (admin-full mode) + Given cmd_change_reference_data with 1 and "123456user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) + Given cmd_verify with 1 and "user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) + Given cmd_verify with 2 and "user pass phrase" + Then it should get success + + Scenario: setup reset code (in admin-full mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-full mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success diff --git a/test/features/201_keygen.feature b/test/features/202_keygen.feature similarity index 71% rename from test/features/201_keygen.feature rename to test/features/202_keygen.feature index 472ccde..53e6628 100644 --- a/test/features/201_keygen.feature +++ b/test/features/202_keygen.feature @@ -20,3 +20,11 @@ Feature: key generation And put the first data to c9 And put the second data to d0 Then it should get success + + Scenario: verify PW1 (1) after genkey + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) after genkey + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success diff --git a/test/features/203_compute_signature.feature b/test/features/203_compute_signature.feature new file mode 100644 index 0000000..d7bc959 --- /dev/null +++ b/test/features/203_compute_signature.feature @@ -0,0 +1,36 @@ +@keygen +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x02 diff --git a/test/features/steps.py b/test/features/steps.py index 030577e..dff6339 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -69,6 +69,15 @@ def set_msg(content_str_repr): msg = ast.literal_eval(content_str_repr) scc.digestinfo = rsa_keys.compute_digestinfo(msg) +@Given("a public key from token for OPENPGP.(.*)") +def get_public_key(openpgp_keyno_str): + openpgp_keyno = int(openpgp_keyno_str) + scc.pubkey_info = ftc.token.cmd_get_public_key(openpgp_keyno) + +@Given("verify signature") +def verify_signature(): + scc.result = rsa_keys.verify_signature(scc.pubkey_info, scc.digestinfo, scc.sig) + @Given("let a token compute digital signature") def compute_signature(): scc.sig = int(hexlify(ftc.token.cmd_pso(0x9e, 0x9a, scc.digestinfo)),16) diff --git a/test/gnuk.py b/test/gnuk.py index d6564dd..a334678 100644 --- a/test/gnuk.py +++ b/test/gnuk.py @@ -344,6 +344,22 @@ class gnuk_token(object): pk = self.cmd_get_response(sw[1]) return (pk[9:9+256], pk[9+256+2:9+256+2+3]) + def cmd_get_public_key(self, keyno): + if keyno == 1: + data = '\xb6\x00' + elif keyno == 2: + data = '\xb8\x00' + else: + data = '\xa4\x00' + cmd_data = iso7816_compose(0x47, 0x81, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + pk = self.cmd_get_response(sw[1]) + return (pk[9:9+256], pk[9+256+2:9+256+2+3]) + def compare(data_original, data_in_device): i = 0 diff --git a/test/rsa_keys.py b/test/rsa_keys.py index a130377..2193026 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -137,3 +137,10 @@ def encrypt(keyno, plaintext): n = key[keyno][7] m = pkcs1_pad_for_crypt(plaintext) return '\x00' + integer_to_bytes(pow(m, e, n)) + +def verify_signature(pubkey_info, digestinfo, sig): + n = int(hexlify(pubkey_info[0]), 16) + e = int(hexlify(pubkey_info[1]), 16) + di_pkcs1 = pow(sig,e,n) + m = pkcs1_pad_for_sign(digestinfo) + return di_pkcs1 == m From 2764bbb5a9fc62a827d3aabb5b336d750734b7a5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 12:01:37 +0900 Subject: [PATCH 210/300] decryption test after keygen --- ChangeLog | 11 +++++++++-- test/features/204_decryption.feature | 19 +++++++++++++++++++ test/features/steps.py | 6 +++++- test/rsa_keys.py | 6 ++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 test/features/204_decryption.feature diff --git a/ChangeLog b/ChangeLog index 52511a2..efa2412 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,19 @@ 2012-06-28 Niibe Yutaka + * test/features/204_decryption.feature: New. + * test/features/203_compute_signature.feature: New. + * test/features/202_keygen.feature: New. + * test/features/201_setup_passphrase.feature: New. + * test/features/200_key_removal.feature: New. + + * test/rsa_keys.py (verify_signature): New. + (encrypt_with_pubkey): New. + * test/gnuk.py (gnuk_token): New method: increment_seq. (gnuk_token.icc_send_cmd): Handle timeout. (gnuk_token.cmd_genkey): New. (gnuk_token.cmd_get_public_key): New. - * test/rsa_keys.py (verify_signature): New. - 2012-06-27 Niibe Yutaka * test/features/101_decryption.feature: New. diff --git a/test/features/204_decryption.feature b/test/features/204_decryption.feature new file mode 100644 index 0000000..e1cc98c --- /dev/null +++ b/test/features/204_decryption.feature @@ -0,0 +1,19 @@ +@keygen +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + diff --git a/test/features/steps.py b/test/features/steps.py index dff6339..d995ccf 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -95,11 +95,15 @@ def compute_signature_on_host(keyno_str): def set_plaintext(content_str_repr): scc.plaintext = ast.literal_eval(content_str_repr) -@Given("encrypt it on host with RSA key pair (.*)") +@Given("encrypt it on host with RSA key pair (.*)$") def encrypt_on_host(keyno_str): keyno = int(keyno_str) scc.ciphertext = rsa_keys.encrypt(keyno, scc.plaintext) +@Given("encrypt it on host$") +def encrypt_on_host_public_key(): + scc.ciphertext = rsa_keys.encrypt_with_pubkey(scc.pubkey_info, scc.plaintext) + @Given("let a token decrypt encrypted data") def decrypt(): scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext) diff --git a/test/rsa_keys.py b/test/rsa_keys.py index 2193026..fe210b2 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -138,6 +138,12 @@ def encrypt(keyno, plaintext): m = pkcs1_pad_for_crypt(plaintext) return '\x00' + integer_to_bytes(pow(m, e, n)) +def encrypt_with_pubkey(pubkey_info, plaintext): + n = int(hexlify(pubkey_info[0]), 16) + e = int(hexlify(pubkey_info[1]), 16) + m = pkcs1_pad_for_crypt(plaintext) + return '\x00' + integer_to_bytes(pow(m, e, n)) + def verify_signature(pubkey_info, digestinfo, sig): n = int(hexlify(pubkey_info[0]), 16) e = int(hexlify(pubkey_info[1]), 16) From 9f0b8ff4c3f409bf8a9069a1b8a63270e87040da Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 12:58:58 +0900 Subject: [PATCH 211/300] removal of ~ --- src/main.c.~HEAD~ | 519 ---------------------------------------------- 1 file changed, 519 deletions(-) delete mode 100644 src/main.c.~HEAD~ diff --git a/src/main.c.~HEAD~ b/src/main.c.~HEAD~ deleted file mode 100644 index 1bd2e99..0000000 --- a/src/main.c.~HEAD~ +++ /dev/null @@ -1,519 +0,0 @@ -/* - * main.c - main routine of Gnuk - * - * Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan - * Author: NIIBE Yutaka - * - * 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 . - * - */ - -#include "config.h" -#include "ch.h" -#include "hal.h" -#include "sys.h" -#include "gnuk.h" -#include "usb_lld.h" -#include "usb-cdc.h" - -#ifdef DEBUG -struct stdout { - Mutex m; - CondVar start_cnd; - CondVar finish_cnd; - const char *str; - int size; -}; - -static struct stdout stdout; - -static void -stdout_init (void) -{ - chMtxInit (&stdout.m); - chCondInit (&stdout.start_cnd); - chCondInit (&stdout.finish_cnd); - stdout.size = 0; - stdout.str = NULL; -} - -void -_write (const char *s, int size) -{ - if (size == 0) - return; - - chMtxLock (&stdout.m); - while (stdout.str) - chCondWait (&stdout.finish_cnd); - stdout.str = s; - stdout.size = size; - chCondSignal (&stdout.start_cnd); - chCondWait (&stdout.finish_cnd); - chMtxUnlock (); -} - -Thread *stdout_thread; -uint32_t count_in; -uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE]; - -static WORKING_AREA(waSTDOUTthread, 128); - -static msg_t -STDOUTthread (void *arg) -{ - (void)arg; - stdout_thread = chThdSelf (); - - again: - - while (1) - { - if (bDeviceState == CONFIGURED) - break; - - chThdSleepMilliseconds (100); - } - - while (1) - { - const char *p; - int len; - - if (bDeviceState != CONFIGURED) - break; - - chMtxLock (&stdout.m); - if (stdout.str == NULL) - chCondWait (&stdout.start_cnd); - - p = stdout.str; - len = stdout.size; - while (1) - { - int i; - - if (len == 0) - if (count_in != VIRTUAL_COM_PORT_DATA_SIZE) - break; - - if (len < VIRTUAL_COM_PORT_DATA_SIZE) - { - for (i = 0; i < len; i++) - buffer_in[i] = p[i]; - count_in = len; - len = 0; - } - else - { - for (i = 0; i < VIRTUAL_COM_PORT_DATA_SIZE; i++) - buffer_in[i] = p[i]; - len -= VIRTUAL_COM_PORT_DATA_SIZE; - count_in = VIRTUAL_COM_PORT_DATA_SIZE; - p += count_in; - } - - chEvtClear (EV_TX_READY); - - usb_lld_write (ENDP3, buffer_in, count_in); - - chEvtWaitOne (EV_TX_READY); - } - - stdout.str = NULL; - stdout.size = 0; - chCondBroadcast (&stdout.finish_cnd); - chMtxUnlock (); - } - - goto again; - return 0; -} - -void -EP3_IN_Callback (void) -{ - if (stdout_thread) - chEvtSignalI (stdout_thread, EV_TX_READY); -} - -void -EP5_OUT_Callback (void) -{ - usb_lld_rx_enable (ENDP5); -} -#else -void -_write (const char *s, int size) -{ - (void)s; - (void)size; -} -#endif - -static WORKING_AREA(waUSBthread, 128); -extern msg_t USBthread (void *arg); - -/* - * main thread does 1-bit LED display output - */ -#define LED_TIMEOUT_INTERVAL MS2ST(100) -#define LED_TIMEOUT_ZERO MS2ST(50) -#define LED_TIMEOUT_ONE MS2ST(200) -#define LED_TIMEOUT_STOP MS2ST(500) - - -#define ID_OFFSET 22 -static void -device_initialize_once (void) -{ - const uint8_t *p = &gnukStringSerial[ID_OFFSET]; - - if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff) - { - /* - * This is the first time invocation. - * Setup serial number by unique device ID. - */ - const uint8_t *u = unique_device_id (); - int i; - - for (i = 0; i < 4; i++) - { - uint8_t b = u[i]; - uint8_t nibble; - - nibble = (b >> 4); - nibble += (nibble >= 10 ? ('A' - 10) : '0'); - flash_put_data_internal (&p[i*4], nibble); - nibble = (b & 0x0f); - nibble += (nibble >= 10 ? ('A' - 10) : '0'); - flash_put_data_internal (&p[i*4+2], nibble); - } - } -} - -static volatile uint8_t fatal_code; - -Thread *main_thread; - -#define GNUK_INIT 0 -#define GNUK_RUNNING 1 -#define GNUK_WAIT 2 -#define GNUK_FATAL 255 -/* - * 0 for initializing - * 1 for normal mode - * 2 for input waiting / under calculation - * 255 for fatal - */ -static uint8_t main_mode; - -static void display_interaction (void) -{ - eventmask_t m; - - set_led (1); - while (1) - { - m = chEvtWaitOne (ALL_EVENTS); - set_led (0); - 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 (1); - chThdSleep (MS2ST (50)); - set_led (0); - chThdSleep (MS2ST (50)); - break; - case LED_STATUS_MODE: - main_mode = GNUK_RUNNING; - return; - case LED_FATAL_MODE: - main_mode = GNUK_FATAL; - return; - default: - break; - } - set_led (1); - } -} - -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) -{ - enum icc_state icc_state; - - if (icc_state_p == NULL) - icc_state = ICC_STATE_START; - else - icc_state = *icc_state_p; - - 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. - * - * NOTE: the main function is already a thread in the system on entry. - * See the hwinit1_common function. - */ -int -main (int argc, char *argv[]) -{ - int count = 0; - - (void)argc; - (void)argv; - - main_thread = chThdSelf (); - - flash_unlock (); - device_initialize_once (); - usb_lld_init (Config_Descriptor.Descriptor[7]); - random_init (); - - while (1) - { - if (bDeviceState != UNCONNECTED) - break; - - chThdSleepMilliseconds (250); - } - -#ifdef DEBUG - stdout_init (); - - /* - * Creates 'stdout' thread. - */ - chThdCreateStatic (waSTDOUTthread, sizeof(waSTDOUTthread), - NORMALPRIO, STDOUTthread, NULL); -#endif - - chThdCreateStatic (waUSBthread, sizeof(waUSBthread), - NORMALPRIO, USBthread, NULL); - -#ifdef PINPAD_DND_SUPPORT - msc_init (); -#endif - - while (1) - { - eventmask_t m; - - if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED) - break; - - 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_WAIT_MODE: - main_mode = GNUK_WAIT; - break; - default: - break; - } - - switch (main_mode) - { - case GNUK_FATAL: - display_fatal_code (); - break; - case GNUK_INIT: - set_led (1); - chThdSleep (LED_TIMEOUT_ZERO); - set_led (0); - chThdSleep (LED_TIMEOUT_STOP * 3); - break; - case GNUK_WAIT: - display_interaction (); - break; - case GNUK_RUNNING: - default: - display_status_code (); - break; - } - -#ifdef DEBUG_MORE - if (bDeviceState == CONFIGURED && (count % 10) == 0) - { - DEBUG_SHORT (count / 10); - _write ("\r\nThis is ChibiOS 2.0.8 on STM32.\r\n" - "Testing USB driver.\n\n" - "Hello world\r\n\r\n", 35+21+15); - } -#endif - } - - set_led (1); - usb_lld_shutdown (); - /* Disable SysTick */ - SysTick->CTRL = 0; - /* Disable all interrupts */ - port_disable (); - /* Set vector */ - SCB->VTOR = (uint32_t)&_regnual_start; -#ifdef DFU_SUPPORT -#define FLASH_SYS_START_ADDR 0x08000000 -#define FLASH_SYS_END_ADDR (0x08000000+0x1000) - { - extern uint8_t _sys; - uint32_t addr; - handler *new_vector = (handler *)FLASH_SYS_START_ADDR; - void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10]; - - /* Kill DFU */ - for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR; - addr += FLASH_PAGE_SIZE) - flash_erase_page (addr); - - /* copy system service routines */ - flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000); - - /* Leave Gnuk to exec reGNUal */ - (*func) (*((void (**)(void))(&_regnual_start+4))); - for (;;); - } -#else - /* Leave Gnuk to exec reGNUal */ - flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4))); -#endif - - /* Never reached */ - return 0; -} - -void -fatal (uint8_t code) -{ - fatal_code = code; - chEvtSignal (main_thread, LED_FATAL_MODE); - _write ("fatal\r\n", 7); - for (;;); -} From 09f22b114c7bc0d82edeb23b1776cf96bd73d6dd Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Jun 2012 14:19:05 +0900 Subject: [PATCH 212/300] update NEWS --- NEWS | 2 ++ test/README | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index f3d1e29..634a054 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ Gnuk NEWS - User visible changes Released 2012-0X-XX, by NIIBE Yutaka +** Test suite + ** New tool: stlinkv2.py This tool is SWD flash ROM writer with ST-Link/V2. diff --git a/test/README b/test/README index 6ead706..4c38942 100644 --- a/test/README +++ b/test/README @@ -3,15 +3,18 @@ This is functionality test suite for Gnuk. You need python-nose, python-freshen as well as python-usb. Besides, python-crypto is needed when you use generate_keys.py to -update *.key. +update contents of *.key. Type: - $ nosetests --with-freshen . + $ nosetests --with-freshen or - $ nosetests -v --with-freshen . + $ nosetests -v --with-freshen to run the test suite. + +To skip tests for key generation, add an option "--tag ~keygen". To +stop running tests after the first error or failure, add "--stop option". From 506761d823b41a426f3df7bacf8d0238ebad24dc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 29 Jun 2012 13:45:37 +0900 Subject: [PATCH 213/300] regnual cleanup --- .gitignore | 3 --- ChangeLog | 4 ++++ regnual/Makefile | 8 +++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e912801..aac6cef 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,6 @@ src/gnuk.elf src/gnuk.hex src/gnuk.map src/*.inc -regnual/sys.h regnual/regnual.bin regnual/regnual.hex regnual/regnual.elf -regnual/usb_lld.c -regnual/usb_lld.h diff --git a/ChangeLog b/ChangeLog index efa2412..44b4d81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-06-29 Niibe Yutaka + + * regnual/Makefile: Don't copy usb_lld.c. + 2012-06-28 Niibe Yutaka * test/features/204_decryption.feature: New. diff --git a/regnual/Makefile b/regnual/Makefile index 5e0036e..154877b 100644 --- a/regnual/Makefile +++ b/regnual/Makefile @@ -2,7 +2,6 @@ PROJECT = regnual -SRCS = regnual.c usb_lld.c sys.c OBJS = regnual.o usb_lld.o sys.o LDSCRIPT= regnual.ld @@ -23,7 +22,7 @@ MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd DEFS = -DFREE_STANDING CFLAGS = -O2 -g -CFLAGS += $(CWARN) -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS) +CFLAGS += $(CWARN) -I . -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS) LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT) @@ -38,8 +37,8 @@ regnual.hex: regnual.elf $(OBJCOPY) -Obinary regnual.elf regnual.bin $(OBJCOPY) -Oihex regnual.elf regnual.hex -usb_lld.c: ../src/usb_lld.c - cp -p ../src/usb_lld.c . +usb_lld.o: ../src/usb_lld.c + $(CC) $(CFLAGS) -c -o usb_lld.o ../src/usb_lld.c regnual.elf: $(OBJS) $(LDSCRIPT) $(CC) $(LDFLAGS) -o regnual.elf $(OBJS) @@ -48,4 +47,3 @@ clean: -rm -f $(OBJS) regnual.elf regnual.hex regnual.bin distclean: clean - -rm -f usb_lld.c From 6d8580f67ace00416d735085a0d9e8a7d0094fa2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 30 Jun 2012 07:49:40 +0900 Subject: [PATCH 214/300] s2k --- ChangeLog | 10 ++++++++++ NEWS | 4 ++++ src/ac.c | 6 +++--- src/gnuk.h | 4 ++-- src/openpgp-do.c | 11 +++++------ src/openpgp.c | 24 +++++++++++++++--------- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44b4d81..7764e85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2012-06-30 Niibe Yutaka + + * src/openpgp.c (s2k): New. + (resetcode_s2k): Remove. + (cmd_reset_user_password, cmd_change_password): Use s2k (was: + sha256 directly or resetcode_s2k). + * src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey): + Likewise. + * src/ac.c (verify_user_0, verify_admin): Likewise. + 2012-06-29 Niibe Yutaka * regnual/Makefile: Don't copy usb_lld.c. diff --git a/NEWS b/NEWS index 634a054..f175335 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ This tool is SWD flash ROM writer with ST-Link/V2. This tool is to dump USB strings, which include revision detail and config options. +** Protection improvement (even when internal data is disclosed) +Even if PW1 and PW3 is same, content of encrypted DEK is different +now. + * Major changes in Gnuk 0.20 diff --git a/src/ac.c b/src/ac.c index 2e530a0..715f027 100644 --- a/src/ac.c +++ b/src/ac.c @@ -1,7 +1,7 @@ /* * ac.c -- Check access condition * - * Copyright (C) 2010 Free Software Initiative of Japan + * Copyright (C) 2010, 2012 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -87,7 +87,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known, } success_one_step: - sha256 (pw, pw_len, keystring); + s2k (BY_USER, pw, pw_len, keystring); if (access == AC_PSO_CDS_AUTHORIZED) { r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring); @@ -280,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len) if (r <= 0) return r; - sha256 (pw, pw_len, keystring_md_pw3); + s2k (BY_ADMIN, pw, pw_len, keystring_md_pw3); auth_status |= AC_ADMIN_AUTHORIZED; return 1; } diff --git a/src/gnuk.h b/src/gnuk.h index 8b33400..4c2fb3b 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -194,8 +194,8 @@ struct prvkey_data { #define BY_RESETCODE 2 #define BY_ADMIN 3 -extern void resetcode_s2k (const unsigned char *input, unsigned int ilen, - unsigned char output[32]); +extern void s2k (int who, const unsigned char *input, unsigned int ilen, + unsigned char output[32]); #define KEYSTRING_PASSLEN_SIZE 1 diff --git a/src/openpgp-do.c b/src/openpgp-do.c index ed5dd6a..4299048 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -28,7 +28,6 @@ #include "sys.h" #include "gnuk.h" #include "openpgp.h" -#include "sha256.h" #include "polarssl/config.h" #include "polarssl/aes.h" @@ -543,7 +542,7 @@ proc_resetting_code (const uint8_t *data, int len) newpw_len = len; newpw = data; - resetcode_s2k (newpw, newpw_len, new_ks); + s2k (BY_RESETCODE, newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks); if (r <= -2) @@ -809,8 +808,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); - sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, - strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); + s2k (BY_USER, (uint8_t *)OPENPGP_CARD_INITIAL_PW1, + strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); encrypt_dek (ks123_pw1+1, pd->dek_encrypted_1); } @@ -1297,8 +1296,8 @@ copy_do (const struct do_table_entry *do_p, int with_tag) } case DO_PROC_READWRITE: { - int (*rw_func)(uint16_t, int, uint8_t *, int, int) - = (int (*)(uint16_t, int, uint8_t *, int, int))do_p->obj; + int (*rw_func)(uint16_t, int, const uint8_t *, int, int) + = (int (*)(uint16_t, int, const uint8_t *, int, int))do_p->obj; return rw_func (do_p->tag, with_tag, NULL, 0, 0); } diff --git a/src/openpgp.c b/src/openpgp.c index 7636518..d080deb 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -295,8 +295,8 @@ cmd_change_password (void) } } - sha256 (pw, pw_len, old_ks); - sha256 (newpw, newpw_len, new_ks); + s2k (who_old, pw, pw_len, old_ks); + s2k (who, newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (who_old, old_ks, who, new_ks); @@ -335,18 +335,24 @@ cmd_change_password (void) } +#define USER_S2K_MAGIC "\xffUSER\r\n" #define RESETCODE_S2K_MAGIC "\xffRESET\r\n" void -resetcode_s2k (const unsigned char *input, unsigned int ilen, - unsigned char output[32]) +s2k (int who, const unsigned char *input, unsigned int ilen, + unsigned char output[32]) { sha256_context ctx; sha256_start (&ctx); sha256_update (&ctx, input, ilen); - sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC, - sizeof (RESETCODE_S2K_MAGIC)); + if (who == BY_USER) + sha256_update (&ctx, (unsigned char *)USER_S2K_MAGIC, + sizeof (USER_S2K_MAGIC)); + else if (who == BY_RESETCODE) + sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC, + sizeof (RESETCODE_S2K_MAGIC)); + /* Not add any for BY_ADMIN */ sha256_finish (&ctx, output); } @@ -391,8 +397,8 @@ cmd_reset_user_password (void) pw_len = ks_rc[0]; newpw = pw + pw_len; newpw_len = len - pw_len; - resetcode_s2k (pw, pw_len, old_ks); - sha256 (newpw, newpw_len, new_ks); + s2k (BY_RESETCODE, pw, pw_len, old_ks); + s2k (BY_USER, newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks); if (r <= -2) @@ -443,7 +449,7 @@ cmd_reset_user_password (void) newpw_len = len; newpw = pw; - sha256 (newpw, newpw_len, new_ks); + s2k (BY_USER, newpw, newpw_len, new_ks); new_ks0[0] = newpw_len; r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks); if (r <= -2) From 33c3980e468f8110c3ba7dbcf68d8e9286f35392 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 2 Jul 2012 13:55:21 +0900 Subject: [PATCH 215/300] fix stlinkv2.py (for Windows) --- ChangeLog | 4 ++++ tool/stlinkv2.py | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7764e85..d9710d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-07-02 Niibe Yutaka + + * tool/stlinkv2.py (stlinkv2.__init__): Don't call setAltInterface. + 2012-06-30 Niibe Yutaka * src/openpgp.c (s2k): New. diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 6ec6cd8..32e2f4c 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -144,7 +144,10 @@ class stlinkv2(object): except: pass self.__devhandle.claimInterface(intf) - self.__devhandle.setAltInterface(intf) + # self.__devhandle.setAltInterface(intf) # This is not good for libusb-win32 + + def shutdown(self): + self.__devhandle.releaseInterface() def execute_get(self, cmd, res_len): self.__devhandle.bulkWrite(self.__bulkout, cmd, self.__timeout) @@ -548,6 +551,7 @@ def main(show_help, erase_only, no_protect, reset_after_successful_write, else: stl.finish_gpio() + stl.shutdown() return 0 if __name__ == '__main__': From 6f4c86833644ebfea6597d5606900da55f84cbf7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 2 Jul 2012 14:22:33 +0900 Subject: [PATCH 216/300] file open with rb --- tool/stlinkv2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 32e2f4c..a9df131 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -591,7 +591,7 @@ if __name__ == '__main__': reset_after_successful_write = False else: filename = sys.argv[1] - f = open(filename) + f = open(filename,'rb') data = f.read() f.close() sys.argv.pop(1) From 976e1234135f214c9c7bcabfb69726ebdd466273 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 2 Jul 2012 17:26:49 +0900 Subject: [PATCH 217/300] more change for stlinkv2 --- README | 4 ++-- tool/stlinkv2.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index ab64525..352aa84 100644 --- a/README +++ b/README @@ -87,7 +87,7 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of card/reader (problems are fixed in trunk). When your newly inserted token is not found by GnuPG, try killing scdaemon and let it to be invoked again. I do: - $ killall -9 scdaemon + $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye and confirm scdaemon doesn't exist, then, $ gpg-connect-agent learn /bye @@ -475,7 +475,7 @@ PyUSB (python-usb package in Debian). If scdaemon is running, please kill it, or you will get "Smartcard Exception" by "Sharing violation". - $ killall -9 scdaemon + $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye In case of PyUSB tool, you need to stop pcscd. diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index a9df131..e99c80e 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -604,6 +604,6 @@ if __name__ == '__main__': skip_blank_check, status_only, unlock, data) if r == 0: print Fore.WHITE + Back.BLUE + Style.BRIGHT + "SUCCESS" + Style.RESET_ALL - exit(r) + sys.exit(r) except Exception as e: print Back.RED + Style.BRIGHT + repr(e) + Style.RESET_ALL From 610573256e5e03b685d90677a07032d14c7e2d74 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 3 Jul 2012 09:38:18 +0900 Subject: [PATCH 218/300] add new tests --- ChangeLog | 9 ++++ test/features/040_passphrase_change.feature | 51 +++++++++++++++++++ test/features/203_passphrase_change.feature | 51 +++++++++++++++++++ ....feature => 210_compute_signature.feature} | 0 ...ryption.feature => 211_decryption.feature} | 0 5 files changed, 111 insertions(+) create mode 100644 test/features/040_passphrase_change.feature create mode 100644 test/features/203_passphrase_change.feature rename test/features/{203_compute_signature.feature => 210_compute_signature.feature} (100%) rename test/features/{204_decryption.feature => 211_decryption.feature} (100%) diff --git a/ChangeLog b/ChangeLog index d9710d0..9ab5218 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-07-03 Niibe Yutaka + + * test/features/040_passphrase_change.feature: New. + * test/features/203_passphrase_change.feature: New. + * test/features/210_compute_signature.feature: Rename (was: + 203_compute_signature.feature) + * test/features/211_decryption.feature: Rename (was: + 204_decryption.feature) + 2012-07-02 Niibe Yutaka * tool/stlinkv2.py (stlinkv2.__init__): Don't call setAltInterface. diff --git a/test/features/040_passphrase_change.feature b/test/features/040_passphrase_change.feature new file mode 100644 index 0000000..1acb5e7 --- /dev/null +++ b/test/features/040_passphrase_change.feature @@ -0,0 +1,51 @@ +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: setup reset code again (in admin-full mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-full mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: change PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-full mode) + Given cmd_verify with 3 and "another admin pass phrase" + Then it should get success + + Scenario: reset pass phrase by admin (in admin-full mode) + Given cmd_reset_retry_counter with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success diff --git a/test/features/203_passphrase_change.feature b/test/features/203_passphrase_change.feature new file mode 100644 index 0000000..1acb5e7 --- /dev/null +++ b/test/features/203_passphrase_change.feature @@ -0,0 +1,51 @@ +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: setup reset code again (in admin-full mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-full mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: change PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-full mode) + Given cmd_verify with 3 and "another admin pass phrase" + Then it should get success + + Scenario: reset pass phrase by admin (in admin-full mode) + Given cmd_reset_retry_counter with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success diff --git a/test/features/203_compute_signature.feature b/test/features/210_compute_signature.feature similarity index 100% rename from test/features/203_compute_signature.feature rename to test/features/210_compute_signature.feature diff --git a/test/features/204_decryption.feature b/test/features/211_decryption.feature similarity index 100% rename from test/features/204_decryption.feature rename to test/features/211_decryption.feature From 315bef463935d5e729d1386a514aaf46f74d2998 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 3 Jul 2012 18:33:39 +0900 Subject: [PATCH 219/300] Bug fix for PW1 --- src/openpgp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openpgp.c b/src/openpgp.c index d080deb..81111a8 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -429,6 +429,7 @@ cmd_reset_user_password (void) else { DEBUG_INFO ("done.\r\n"); + gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); ac_reset_pso_cds (); ac_reset_other (); gpg_pw_reset_err_counter (PW_ERR_RC); @@ -475,6 +476,7 @@ cmd_reset_user_password (void) else { DEBUG_INFO ("done.\r\n"); + gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); ac_reset_pso_cds (); ac_reset_other (); gpg_pw_reset_err_counter (PW_ERR_PW1); From 628c03634b06b0000d06bd4b42ca75525b48b91d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 3 Jul 2012 18:36:24 +0900 Subject: [PATCH 220/300] Bug fix against flash GC --- src/gnuk.h | 2 +- src/openpgp-do.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gnuk.h b/src/gnuk.h index 4c2fb3b..b539159 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -306,7 +306,7 @@ extern uint8_t admin_authorized; /* * Representation of Boolean object: * 0: No record in flash memory - * 1: 0xc?00 + * 1: 0xf000 */ #define NR_BOOL_PW1_LIFETIME 0xf0 /* diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 4299048..f75a2c6 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -877,6 +877,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk, dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old); memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE); + do_ptr[nr - NR_DO__FIRST__] = NULL; p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); do_ptr[nr - NR_DO__FIRST__] = p; @@ -1398,6 +1399,7 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len) GPG_MEMORY_FAILURE (); else { + *do_data_p = NULL; *do_data_p = flash_do_write (nr, data, len); if (*do_data_p) GPG_SUCCESS (); @@ -1512,6 +1514,7 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size) if (data != NULL) { + *do_data_p = NULL; *do_data_p = flash_do_write (nr, data, size); if (*do_data_p == NULL) flash_warning ("DO WRITE ERROR"); From 9ef97836c9ee4832b84267c17bd7d7ab0a91d688 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 3 Jul 2012 19:01:50 +0900 Subject: [PATCH 221/300] Bug fix for changing PW3 --- src/ac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ac.c b/src/ac.c index 715f027..ec87c22 100644 --- a/src/ac.c +++ b/src/ac.c @@ -202,7 +202,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known) return 0; pw_len = pw3_keystring[0]; - if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len) + if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len > buf_len) goto failure; salt = &pw3_keystring[1]; From 324b648de8dfe70eb903108408090586305b4ce0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 3 Jul 2012 19:32:15 +0900 Subject: [PATCH 222/300] test update --- test/features/040_passphrase_change.feature | 20 +++++++++++++++++ test/features/201_setup_passphrase.feature | 6 +++--- test/features/202_keygen.feature | 8 +++---- test/features/203_passphrase_change.feature | 24 +++++++++++++++++++-- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/test/features/040_passphrase_change.feature b/test/features/040_passphrase_change.feature index 1acb5e7..b4ebe14 100644 --- a/test/features/040_passphrase_change.feature +++ b/test/features/040_passphrase_change.feature @@ -49,3 +49,23 @@ Feature: setup pass phrase Scenario: verify PW1 (2) again Given cmd_verify with 2 and "new user pass phrase" Then it should get success + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: change PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-full mode) + Given cmd_verify with 3 and "admin pass phrase" + Then it should get success diff --git a/test/features/201_setup_passphrase.feature b/test/features/201_setup_passphrase.feature index 554c169..dd223cb 100644 --- a/test/features/201_setup_passphrase.feature +++ b/test/features/201_setup_passphrase.feature @@ -20,13 +20,13 @@ Feature: setup pass phrase Then it should get success Scenario: reset pass phrase by reset code (in admin-full mode) - Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase" Then it should get success Scenario: verify PW1 (1) again - Given cmd_verify with 1 and "new user pass phrase" + Given cmd_verify with 1 and "another user pass phrase" Then it should get success Scenario: verify PW1 (2) again - Given cmd_verify with 2 and "new user pass phrase" + Given cmd_verify with 2 and "another user pass phrase" Then it should get success diff --git a/test/features/202_keygen.feature b/test/features/202_keygen.feature index 53e6628..b9c69a3 100644 --- a/test/features/202_keygen.feature +++ b/test/features/202_keygen.feature @@ -21,10 +21,10 @@ Feature: key generation And put the second data to d0 Then it should get success - Scenario: verify PW1 (1) after genkey - Given cmd_verify with 1 and "new user pass phrase" + Scenario: verify PW1 (1) after keygen + Given cmd_verify with 1 and "another user pass phrase" Then it should get success - Scenario: verify PW1 (2) after genkey - Given cmd_verify with 2 and "new user pass phrase" + Scenario: verify PW1 (2) after keygen + Given cmd_verify with 2 and "another user pass phrase" Then it should get success diff --git a/test/features/203_passphrase_change.feature b/test/features/203_passphrase_change.feature index 1acb5e7..ea8450d 100644 --- a/test/features/203_passphrase_change.feature +++ b/test/features/203_passphrase_change.feature @@ -15,11 +15,11 @@ Feature: setup pass phrase Then it should get success Scenario: setup reset code again (in admin-full mode) - Given cmd_put_data with d3 and "example reset code 000" + Given cmd_put_data with d3 and "example reset code 111" Then it should get success Scenario: reset pass phrase by reset code (in admin-full mode) - Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase" Then it should get success Scenario: verify PW1 (1) again @@ -49,3 +49,23 @@ Feature: setup pass phrase Scenario: verify PW1 (2) again Given cmd_verify with 2 and "new user pass phrase" Then it should get success + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: change PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-full mode) + Given cmd_verify with 3 and "admin pass phrase" + Then it should get success From ffba0e015808bf2cdee27c40205d27304f908cfc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 4 Jul 2012 06:00:14 +0900 Subject: [PATCH 223/300] changelog --- ChangeLog | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9ab5218..3026b18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2012-07-04 Niibe Yutaka + + Bug fixes. + * src/ac.c (verify_admin_0): Compare PW_LEN and BUF_LEN. + + * src/openpgp-do.c (gpg_do_chks_prvkey): Set do_ptr to NULL before + calling flash_do_write (which might cause GC). + (gpg_do_put_data, gpg_do_write_simple): Likewise. + + * src/openpgp.c (cmd_reset_user_password): Write to + DO_KEYSTRING_PW1. + 2012-07-03 Niibe Yutaka * test/features/040_passphrase_change.feature: New. From e78206e1cd62cdf0139cca35841735e0b4cd112e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jul 2012 08:56:42 +0900 Subject: [PATCH 224/300] fix resetting ADMIN pass phrase in admi-less mode --- ChangeLog | 8 ++++++++ src/ac.c | 2 ++ src/openpgp-do.c | 2 +- src/openpgp.c | 12 ++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3026b18..5b5ebf0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2012-07-05 Niibe Yutaka + + * src/openpgp.c (cmd_change_password): Call ac_reset_admin when + admin-less mode. + (cmd_reset_user_password): Likewise. + + * src/ac.c (ac_reset_admin, ac_fini): Clear ADMIN_AUTHORIZED. + 2012-07-04 Niibe Yutaka Bug fixes. diff --git a/src/ac.c b/src/ac.c index ec87c22..fa7b518 100644 --- a/src/ac.c +++ b/src/ac.c @@ -290,6 +290,7 @@ ac_reset_admin (void) { memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE); auth_status &= ~AC_ADMIN_AUTHORIZED; + admin_authorized = 0; } void @@ -300,4 +301,5 @@ ac_fini (void) gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION); gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION); auth_status = AC_NONE_AUTHORIZED; + admin_authorized = 0; } diff --git a/src/openpgp-do.c b/src/openpgp-do.c index f75a2c6..567e089 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -959,7 +959,7 @@ proc_key_import (const uint8_t *data, int len) ac_reset_pso_cds (); ac_reset_other (); - if (keystring_admin == NULL) + if (admin_authorized == BY_USER) ac_reset_admin (); } diff --git a/src/openpgp.c b/src/openpgp.c index 81111a8..bc03b44 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -315,6 +315,8 @@ cmd_change_password (void) gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n"); GPG_SUCCESS (); } @@ -323,6 +325,8 @@ cmd_change_password (void) gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n"); GPG_SUCCESS (); } @@ -422,6 +426,8 @@ cmd_reset_user_password (void) KEYSTRING_SIZE_PW1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); gpg_pw_reset_err_counter (PW_ERR_RC); gpg_pw_reset_err_counter (PW_ERR_PW1); GPG_SUCCESS (); @@ -432,6 +438,8 @@ cmd_reset_user_password (void) gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); gpg_pw_reset_err_counter (PW_ERR_RC); gpg_pw_reset_err_counter (PW_ERR_PW1); GPG_SUCCESS (); @@ -470,6 +478,8 @@ cmd_reset_user_password (void) KEYSTRING_SIZE_PW1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); gpg_pw_reset_err_counter (PW_ERR_PW1); GPG_SUCCESS (); } @@ -479,6 +489,8 @@ cmd_reset_user_password (void) gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); ac_reset_pso_cds (); ac_reset_other (); + if (admin_authorized == BY_USER) + ac_reset_admin (); gpg_pw_reset_err_counter (PW_ERR_PW1); GPG_SUCCESS (); } From 6f97e8a7c42025567214e3faaf20cc7eade53963 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jul 2012 09:12:04 +0900 Subject: [PATCH 225/300] Bug fix for s2k call --- ChangeLog | 3 +++ src/ac.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5b5ebf0..9b1750e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ * src/ac.c (ac_reset_admin, ac_fini): Clear ADMIN_AUTHORIZED. + Bug fix. + * src/ac.c (verify_admin): Call s2k with ADMIN_AUTHORIZED. + 2012-07-04 Niibe Yutaka Bug fixes. diff --git a/src/ac.c b/src/ac.c index fa7b518..86679ff 100644 --- a/src/ac.c +++ b/src/ac.c @@ -280,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len) if (r <= 0) return r; - s2k (BY_ADMIN, pw, pw_len, keystring_md_pw3); + s2k (admin_authorized, pw, pw_len, keystring_md_pw3); auth_status |= AC_ADMIN_AUTHORIZED; return 1; } From fe31219d94cbe36f8c99dc9f61d0399a0aca0e06 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jul 2012 09:13:32 +0900 Subject: [PATCH 226/300] fix title --- test/features/040_passphrase_change.feature | 2 +- test/features/203_passphrase_change.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/features/040_passphrase_change.feature b/test/features/040_passphrase_change.feature index b4ebe14..3aaf750 100644 --- a/test/features/040_passphrase_change.feature +++ b/test/features/040_passphrase_change.feature @@ -1,4 +1,4 @@ -Feature: setup pass phrase +Feature: change pass phrase In order to conform OpenPGP card 2.0 specification A token should support pass phrase: PW1, PW3 and reset code diff --git a/test/features/203_passphrase_change.feature b/test/features/203_passphrase_change.feature index ea8450d..e392f0b 100644 --- a/test/features/203_passphrase_change.feature +++ b/test/features/203_passphrase_change.feature @@ -1,4 +1,4 @@ -Feature: setup pass phrase +Feature: change pass phrase In order to conform OpenPGP card 2.0 specification A token should support pass phrase: PW1, PW3 and reset code From f88e7af3cee5a3d97539d5463b7cb00999a1dd43 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jul 2012 09:26:58 +0900 Subject: [PATCH 227/300] add more tests --- ChangeLog | 6 ++ test/features/370_key_removal.feature | 39 +++++++++ .../380_personalization_reset.feature | 27 +++++++ test/features/390_reset_passphrase.feature | 7 ++ test/features/400_empty_check.feature | 79 +++++++++++++++++++ .../401_empty_check_passphrase.feature | 15 ++++ test/features/402_get_data_static.feature | 27 +++++++ test/features/410_setup_passphrase.feature | 55 +++++++++++++ .../420_personalization_write.feature | 27 +++++++ .../features/421_personalization_read.feature | 27 +++++++ test/features/430_key_registration.feature | 56 +++++++++++++ test/features/440_passphrase_change.feature | 51 ++++++++++++ test/features/500_compute_signature.feature | 31 ++++++++ test/features/501_decryption.feature | 16 ++++ test/features/600_key_removal.feature | 44 +++++++++++ test/features/601_setup_passphrase.feature | 40 ++++++++++ test/features/602_keygen.feature | 30 +++++++ test/features/603_passphrase_change.feature | 67 ++++++++++++++++ test/features/610_compute_signature.feature | 36 +++++++++ test/features/611_decryption.feature | 19 +++++ test/features/970_key_removal.feature | 4 + test/features/990_reset_passphrase.feature | 6 +- 22 files changed, 706 insertions(+), 3 deletions(-) create mode 100644 test/features/370_key_removal.feature create mode 100644 test/features/380_personalization_reset.feature create mode 100644 test/features/390_reset_passphrase.feature create mode 100644 test/features/400_empty_check.feature create mode 100644 test/features/401_empty_check_passphrase.feature create mode 100644 test/features/402_get_data_static.feature create mode 100644 test/features/410_setup_passphrase.feature create mode 100644 test/features/420_personalization_write.feature create mode 100644 test/features/421_personalization_read.feature create mode 100644 test/features/430_key_registration.feature create mode 100644 test/features/440_passphrase_change.feature create mode 100644 test/features/500_compute_signature.feature create mode 100644 test/features/501_decryption.feature create mode 100644 test/features/600_key_removal.feature create mode 100644 test/features/601_setup_passphrase.feature create mode 100644 test/features/602_keygen.feature create mode 100644 test/features/603_passphrase_change.feature create mode 100644 test/features/610_compute_signature.feature create mode 100644 test/features/611_decryption.feature diff --git a/ChangeLog b/ChangeLog index 9b1750e..db283fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2012-07-05 Niibe Yutaka + More tests. + * test/*: Add tests for admin-less mode. + * test/features/990_reset_passphrase.feature: This is now for + admin-less mode. + * test/features/970_key_removal.feature: Ditto. + * src/openpgp.c (cmd_change_password): Call ac_reset_admin when admin-less mode. (cmd_reset_user_password): Likewise. diff --git a/test/features/370_key_removal.feature b/test/features/370_key_removal.feature new file mode 100644 index 0000000..5f89bc1 --- /dev/null +++ b/test/features/370_key_removal.feature @@ -0,0 +1,39 @@ +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success diff --git a/test/features/380_personalization_reset.feature b/test/features/380_personalization_reset.feature new file mode 100644 index 0000000..51a3430 --- /dev/null +++ b/test/features/380_personalization_reset.feature @@ -0,0 +1,27 @@ +Feature: removal of data objects + In order to use a token + A token should have personalized data + + Scenario: remove data object Login + Given cmd_put_data with 5e and "" + Then it should get success + + Scenario: remove data object Name + Given cmd_put_data with 5b and "" + Then it should get success + + Scenario: remove data object Language preference + Given cmd_put_data with 5f2d and "" + Then it should get success + + Scenario: remove data object Sex + Given cmd_put_data with 5f35 and "" + Then it should get success + + Scenario: remove data object URL + Given cmd_put_data with 5f50 and "" + Then it should get success + + Scenario: remove data object pw1 status bytes + Given cmd_put_data with c4 and "\x00" + Then it should get success diff --git a/test/features/390_reset_passphrase.feature b/test/features/390_reset_passphrase.feature new file mode 100644 index 0000000..853c515 --- /dev/null +++ b/test/features/390_reset_passphrase.feature @@ -0,0 +1,7 @@ +Feature: reset pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW3 (admin-full mode) + Given cmd_change_reference_data with 3 and "admin pass phrase" + Then it should get success diff --git a/test/features/400_empty_check.feature b/test/features/400_empty_check.feature new file mode 100644 index 0000000..4f4d35e --- /dev/null +++ b/test/features/400_empty_check.feature @@ -0,0 +1,79 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no data, no keys) + + Scenario: data object Login + When requesting login data: 5e + Then you should get NULL + + Scenario: data object Name + When requesting name: 5b + Then you should get NULL + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get NULL + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get NULL + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get NULL + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x00 + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 + + Scenario: data object finger print 0 + When requesting finger print: c5 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object finger print 1 + When requesting finger print: c7 + Then you should get NULL + + Scenario: data object finger print 2 + When requesting finger print: c8 + Then you should get NULL + + Scenario: data object finger print 3 + When requesting finger print: c9 + Then you should get NULL + + Scenario: data object CA finger print 0 + When requesting finger print: c6 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object CA finger print 1 + When requesting finger print: ca + Then you should get NULL + + Scenario: data object CA finger print 2 + When requesting finger print: cb + Then you should get NULL + + Scenario: data object CA finger print 3 + When requesting finger print: cc + Then you should get NULL + + Scenario: data object date/time of key pair 0 + When requesting date/time of key pair: cd + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object date/time of key pair 1 + When requesting date/time of key pair: ce + Then you should get NULL + + Scenario: data object date/time of key pair 2 + When requesting date/time of key pair: cf + Then you should get NULL + + Scenario: data object date/time of key pair 3 + When requesting date/time of key pair: d0 + Then you should get NULL diff --git a/test/features/401_empty_check_passphrase.feature b/test/features/401_empty_check_passphrase.feature new file mode 100644 index 0000000..f026b08 --- /dev/null +++ b/test/features/401_empty_check_passphrase.feature @@ -0,0 +1,15 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no pass phrase) + + Scenario: verify PW1 factory setting (1) + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 factory setting (2) + Given cmd_verify with 2 and "123456" + Then it should get success + + Scenario: verify PW3 factory setting + Given cmd_verify with 3 and "12345678" + Then it should get success diff --git a/test/features/402_get_data_static.feature b/test/features/402_get_data_static.feature new file mode 100644 index 0000000..9de7425 --- /dev/null +++ b/test/features/402_get_data_static.feature @@ -0,0 +1,27 @@ +Feature: command GET DATA + In order to conform OpenPGP card 2.0 specification + A token should support all mandatory features of the specification + + Scenario: data object historical bytes + When requesting historical bytes: 5f52 + Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + + Scenario: data object extended capabilities + When requesting extended capabilities: c0 + Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + + Scenario: data object algorithm attributes 1 + When requesting algorithm attributes 1: c1 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 2 + When requesting algorithm attributes 2: c2 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 3 + When requesting algorighm attributes 3: c3 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object AID + When requesting AID: 4f + Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00 diff --git a/test/features/410_setup_passphrase.feature b/test/features/410_setup_passphrase.feature new file mode 100644 index 0000000..5ac2543 --- /dev/null +++ b/test/features/410_setup_passphrase.feature @@ -0,0 +1,55 @@ +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW1 (admin-less mode) + Given cmd_change_reference_data with 1 and "123456user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) + Given cmd_verify with 1 and "user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) + Given cmd_verify with 2 and "user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "user pass phrase" + Then it should get success + + Scenario: setup reset code (in admin-less mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-less mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) again + Given cmd_verify with 3 and "new user pass phrase" + Then it should get success + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) again + Given cmd_verify with 3 and "another user pass phrase" + Then it should get success diff --git a/test/features/420_personalization_write.feature b/test/features/420_personalization_write.feature new file mode 100644 index 0000000..2fdd387 --- /dev/null +++ b/test/features/420_personalization_write.feature @@ -0,0 +1,27 @@ +Feature: personalize token write + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + Given cmd_put_data with 5e and "gpg_user" + Then it should get success + + Scenario: data object Name + Given cmd_put_data with 5b and "GnuPG User" + Then it should get success + + Scenario: data object Language preference + Given cmd_put_data with 5f2d and "ja" + Then it should get success + + Scenario: data object Sex + Given cmd_put_data with 5f35 and "1" + Then it should get success + + Scenario: data object URL + Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" + Then it should get success + + Scenario: data object pw1 status bytes + Given cmd_put_data with c4 and "\x01" + Then it should get success diff --git a/test/features/421_personalization_read.feature b/test/features/421_personalization_read.feature new file mode 100644 index 0000000..5f0f972 --- /dev/null +++ b/test/features/421_personalization_read.feature @@ -0,0 +1,27 @@ +Feature: personalize token read + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + When requesting login data: 5e + Then you should get: gpg_user + + Scenario: data object Name + When requesting name: 5b + Then you should get: GnuPG User + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get: ja + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get: 1 + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get: http://www.fsij.org/gnuk/ + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 diff --git a/test/features/430_key_registration.feature b/test/features/430_key_registration.feature new file mode 100644 index 0000000..4381307 --- /dev/null +++ b/test/features/430_key_registration.feature @@ -0,0 +1,56 @@ +Feature: import keys to token + In order to use a token + A token should have keys + + Scenario: importing OPENPGP.1 key (sign) + Given a RSA key pair 0 + And importing it to the token as OPENPGP.1 + Then it should get success + + Scenario: importing OPENPGP.2 key (decrypt) + Given a RSA key pair 1 + And importing it to the token as OPENPGP.2 + Then it should get success + + Scenario: importing OPENPGP.3 key (authentication) + Given a RSA key pair 2 + And importing it to the token as OPENPGP.3 + Then it should get success + + Scenario: setup data object Finger print sig + Given a fingerprint of OPENPGP.1 key + And put the data to c7 + Then it should get success + + Scenario: setup data object Finger print dec + Given a fingerprint of OPENPGP.2 key + And put the data to c8 + Then it should get success + + Scenario: setup data object Finger print aut + Given a fingerprint of OPENPGP.3 key + And put the data to c9 + Then it should get success + + Scenario: setup data object keygeneration data/time sig + Given a timestamp of OPENPGP.1 key + And put the data to ce + Then it should get success + + Scenario: setup data object keygeneration data/time dec + Given a timestamp of OPENPGP.2 key + And put the data to cf + Then it should get success + + Scenario: setup data object keygeneration data/time aut + Given a timestamp of OPENPGP.3 key + And put the data to d0 + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success diff --git a/test/features/440_passphrase_change.feature b/test/features/440_passphrase_change.feature new file mode 100644 index 0000000..9f567e6 --- /dev/null +++ b/test/features/440_passphrase_change.feature @@ -0,0 +1,51 @@ +Feature: change pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: change PW1 (in admin-less mode) + Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: setup reset code again (in admin-less mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-less mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "another user pass phrase" + Then it should get success diff --git a/test/features/500_compute_signature.feature b/test/features/500_compute_signature.feature new file mode 100644 index 0000000..67fcbcc --- /dev/null +++ b/test/features/500_compute_signature.feature @@ -0,0 +1,31 @@ +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x02 diff --git a/test/features/501_decryption.feature b/test/features/501_decryption.feature new file mode 100644 index 0000000..1985dee --- /dev/null +++ b/test/features/501_decryption.feature @@ -0,0 +1,16 @@ +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + diff --git a/test/features/600_key_removal.feature b/test/features/600_key_removal.feature new file mode 100644 index 0000000..2bcf353 --- /dev/null +++ b/test/features/600_key_removal.feature @@ -0,0 +1,44 @@ +@keygen +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "12345678" + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success diff --git a/test/features/601_setup_passphrase.feature b/test/features/601_setup_passphrase.feature new file mode 100644 index 0000000..476c2b0 --- /dev/null +++ b/test/features/601_setup_passphrase.feature @@ -0,0 +1,40 @@ +@keygen +Feature: setup pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: setup PW1 (admin-less mode) + Given cmd_change_reference_data with 1 and "123456user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) + Given cmd_verify with 1 and "user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) + Given cmd_verify with 2 and "user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "user pass phrase" + Then it should get success + + Scenario: setup reset code (in admin-less mode) + Given cmd_put_data with d3 and "example reset code 000" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-less mode) + Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) again + Given cmd_verify with 3 and "another user pass phrase" + Then it should get success diff --git a/test/features/602_keygen.feature b/test/features/602_keygen.feature new file mode 100644 index 0000000..b9c69a3 --- /dev/null +++ b/test/features/602_keygen.feature @@ -0,0 +1,30 @@ +@keygen +Feature: key generation + In order to use a token + A token should have keys + + Scenario: generate OPENPGP.1 key (sign) + When generating a key of OPENPGP.1 + And put the first data to c7 + And put the second data to ce + Then it should get success + + Scenario: generate OPENPGP.2 key (decrypt) + When generating a key of OPENPGP.2 + And put the first data to c8 + And put the second data to cf + Then it should get success + + Scenario: generate OPENPGP.3 key (authentication) + When generating a key of OPENPGP.3 + And put the first data to c9 + And put the second data to d0 + Then it should get success + + Scenario: verify PW1 (1) after keygen + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) after keygen + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success diff --git a/test/features/603_passphrase_change.feature b/test/features/603_passphrase_change.feature new file mode 100644 index 0000000..accb4b8 --- /dev/null +++ b/test/features/603_passphrase_change.feature @@ -0,0 +1,67 @@ +Feature: change pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG" + Then it should get success + + Scenario: setup reset code again (in admin-less mode) + Given cmd_put_data with d3 and "example reset code 111" + Then it should get success + + Scenario: reset pass phrase by reset code (in admin-less mode) + Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "new user pass phrase" + Then it should get success + + Scenario: reset pass phrase by admin (in admin-less mode) + Given cmd_reset_retry_counter with 2 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "new user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "new user pass phrase" + Then it should get success + + Scenario: change PW1 + Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase" + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "another user pass phrase" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "another user pass phrase" + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "another user pass phrase" + Then it should get success diff --git a/test/features/610_compute_signature.feature b/test/features/610_compute_signature.feature new file mode 100644 index 0000000..d7bc959 --- /dev/null +++ b/test/features/610_compute_signature.feature @@ -0,0 +1,36 @@ +@keygen +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x02 diff --git a/test/features/611_decryption.feature b/test/features/611_decryption.feature new file mode 100644 index 0000000..e1cc98c --- /dev/null +++ b/test/features/611_decryption.feature @@ -0,0 +1,19 @@ +@keygen +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + diff --git a/test/features/970_key_removal.feature b/test/features/970_key_removal.feature index 5f89bc1..a8c50b1 100644 --- a/test/features/970_key_removal.feature +++ b/test/features/970_key_removal.feature @@ -14,6 +14,10 @@ Feature: key removal When removing a key OPENPGP.3 Then it should get success + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "12345678" + Then it should get success + Scenario: remove data object Finger print sig Given cmd_put_data with c7 and "" Then it should get success diff --git a/test/features/990_reset_passphrase.feature b/test/features/990_reset_passphrase.feature index 853c515..78edf9a 100644 --- a/test/features/990_reset_passphrase.feature +++ b/test/features/990_reset_passphrase.feature @@ -1,7 +1,7 @@ -Feature: reset pass phrase +Feature: confirm factory setting pass phrase In order to conform OpenPGP card 2.0 specification A token should support pass phrase: PW1, PW3 and reset code - Scenario: setup PW3 (admin-full mode) - Given cmd_change_reference_data with 3 and "admin pass phrase" + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "12345678" Then it should get success From a796e9f14544491211a83adae63001029362fe97 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 5 Jul 2012 09:32:46 +0900 Subject: [PATCH 228/300] RSA change --- ChangeLog | 5 +++++ polarssl-0.14.0/library/rsa.c | 2 ++ src/call-rsa.c | 27 ++++----------------------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index db283fa..44b7562 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2012-07-05 Niibe Yutaka + * src/call-rsa.c (rsa_sign, rsa_decrypt): Don't need to setup N. + + * polarssl-0.14.0/library/rsa.c (rsa_check_pubkey) + (rsa_check_privkey): Ifdef-out. + More tests. * test/*: Add tests for admin-less mode. * test/features/990_reset_passphrase.feature: This is now for diff --git a/polarssl-0.14.0/library/rsa.c b/polarssl-0.14.0/library/rsa.c index 943ef84..e135e57 100644 --- a/polarssl-0.14.0/library/rsa.c +++ b/polarssl-0.14.0/library/rsa.c @@ -131,6 +131,7 @@ cleanup: #endif +#if 0 /* * Check a public RSA key */ @@ -199,6 +200,7 @@ cleanup: mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL ); return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret ); } +#endif /* * Do an RSA public key operation diff --git a/src/call-rsa.c b/src/call-rsa.c index 5ea7854..1772e29 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -50,7 +50,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2); +#if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); +#endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); @@ -61,17 +63,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA sign..."); -#if 0 - if ((r = rsa_check_privkey (&rsa_ctx)) == 0) - DEBUG_INFO ("ok..."); - else - { - DEBUG_INFO ("failed.\r\n"); - DEBUG_SHORT (r); - rsa_free (&rsa_ctx); - return r; - } -#endif r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW, msg_len, raw_message, temp); @@ -142,7 +133,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], KEY_CONTENT_LEN / 2); +#if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); +#endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); @@ -153,18 +146,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA decrypt ..."); -#if 0 - /* This consume some memory */ - if ((r = rsa_check_privkey (&rsa_ctx)) == 0) - DEBUG_INFO ("ok..."); - else - { - DEBUG_INFO ("failed.\r\n"); - DEBUG_SHORT (r); - rsa_free (&rsa_ctx); - return r; - } -#endif r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len, input, output, MAX_RES_APDU_DATA_SIZE); From 9ad6c6461d4885c20edfec955fd61194b3fdf7e0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 6 Jul 2012 08:26:20 +0900 Subject: [PATCH 229/300] SPI flash support starts for FST-01 --- ChangeLog | 5 +++++ boards/FST_01/board.h | 6 +++++- tool/stlinkv2.py | 11 +++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44b7562..7fcd9d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-07-06 Niibe Yutaka + + * boards/FST_01/board.h (VAL_GPIOACRL): Change for SPI flash. + * tool/stlinkv2.py (stlinkv2.setup_gpio): Likewise. + 2012-07-05 Niibe Yutaka * src/call-rsa.c (rsa_sign, rsa_decrypt): Don't need to setup N. diff --git a/boards/FST_01/board.h b/boards/FST_01/board.h index cf911a3..7b78e93 100644 --- a/boards/FST_01/board.h +++ b/boards/FST_01/board.h @@ -97,12 +97,16 @@ * PA0 - input with pull-up (TIM2_CH1) * PA1 - input with pull-down (TIM2_CH2) * PA2 - input with pull-up (TIM2_CH3) + * PA4 - Push pull output (SPI1_NSS) + * PA5 - Alternate Push pull output (SPI1_SCK) + * PA6 - Alternate Push pull output (SPI1_MISO) + * PA7 - Alternate Push pull output (SPI1_MOSI) * 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_GPIOACRL 0xBBB38888 /* PA7...PA0 */ #define VAL_GPIOACRH 0x88888388 /* PA15...PA8 */ #define VAL_GPIOAODR 0xFFFFFFFD diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index e99c80e..ff0e676 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -217,19 +217,22 @@ class stlinkv2(object): # For FST-01-00 and FST-01: LED on, USB off def setup_gpio(self): apb2enr = self.read_memory_u32(0x40021018) - apb2enr = apb2enr | 4 | 8 # Enable port A and B - self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR - self.write_memory_u32(0x4002100c, 4|8) # RCC->APB2RSTR + apb2enr = apb2enr | 4 | 8 | 0x1000 # Enable port A, port B, and SPI1 + self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR + self.write_memory_u32(0x4002100c, 4|8|0x1000) # RCC->APB2RSTR self.write_memory_u32(0x4002100c, 0) self.write_memory_u32(GPIOA+0x0c, 0xfffffbff) # ODR self.write_memory_u32(GPIOA+0x04, 0x88888383) # CRH - self.write_memory_u32(GPIOA+0x00, 0x88888888) # CRL + self.write_memory_u32(GPIOA+0x00, 0xBBB38888) # CRL self.write_memory_u32(GPIOB+0x0c, 0xffffffff) # ODR self.write_memory_u32(GPIOB+0x04, 0x88888883) # CRH self.write_memory_u32(GPIOB+0x00, 0x88888888) # CRL # For FST-01-00 and FST-01: LED off, USB off def finish_gpio(self): + apb2enr = self.read_memory_u32(0x40021018) + apb2enr = apb2enr & ~(4 | 8 | 0x1000) + self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR From ee4f3806c2f47e3eefb3f63c249493693e3ff5f9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 6 Jul 2012 10:03:10 +0900 Subject: [PATCH 230/300] Add SPI flash ROM support for tool/stlinkv2.py --- ChangeLog | 3 +++ tool/stlinkv2.py | 67 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7fcd9d5..7da509a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,9 @@ * boards/FST_01/board.h (VAL_GPIOACRL): Change for SPI flash. * tool/stlinkv2.py (stlinkv2.setup_gpio): Likewise. + (stlinkv2.spi_flash_init, stlinkv2.spi_flash_select) + (stlinkv2.spi_flash_sendbyte, stlinkv2.spi_flash_read_id): New. + (main): Add SPI flash ROM id check. 2012-07-05 Niibe Yutaka diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index ff0e676..bbb902f 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -63,6 +63,8 @@ FLASH_CR_LOCK= 0x0080 FLASH_CR_OPTWRE= 0x0200 +SPI1= 0x40013000 + def uint32(v): return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24) @@ -236,6 +238,53 @@ class stlinkv2(object): self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR + def spi_flash_init(self): + self.write_memory_u32(SPI1+0x00, 0x0004); # CR1 <= MSTR + i2scfgr = self.read_memory_u32(SPI1+0x1c) # I2SCFGR + i2scfgr = i2scfgr & 0xf7ff # + self.write_memory_u32(SPI1+0x1c, i2scfgr); # I2SCFGR <= SPI mode + self.write_memory_u32(SPI1+0x10, 7); # CRCPR <= 7 + self.write_memory_u32(SPI1+0x04, 0x04); # CR2 <= SSOE + self.write_memory_u32(SPI1+0x00, 0x0044); # CR1 <= MSTR | SPE + + def spi_flash_select(self, enable): + if enable: + self.write_memory_u32(GPIOA+0x0c, 0xffffffef) # ODR + else: + self.write_memory_u32(GPIOA+0x0c, 0xffffffff) # ODR + + def spi_flash_sendbyte(self, v): + i = 0 + while True: + status = self.read_memory_u32(SPI1+0x08) # SR + if status & 0x02 != 0: # TXE (Data Empty) + break + time.sleep(0.01) + i = i + 1 + if i > 10: + raise TimeOutError('spi_flash_sendbyte') + self.write_memory_u32(SPI1+0x0c, v) # DR + i = 0 + while True: + status = self.read_memory_u32(SPI1+0x08) # SR + if status & 0x01 != 0: # RXNE (Data Not Empty) + break + time.sleep(0.01) + i = i + 1 + if i > 10: + raise TimeOutError('spi_flash_sendbyte') + v = self.read_memory_u32(SPI1+0x0c) # DR + return v + + def spi_flash_read_id(self): + self.spi_flash_select(True) + self.spi_flash_sendbyte(0x9f) + t0 = self.spi_flash_sendbyte(0xa5) + t1 = self.spi_flash_sendbyte(0xa5) + t2 = self.spi_flash_sendbyte(0xa5) + self.spi_flash_select(False) + return (t0 << 16) | (t1 << 8) | t2 + def protection(self): return (self.read_memory_u32(FLASH_OBR) & 0x0002) != 0 @@ -440,13 +489,15 @@ def help(): print "stlinkv2.py [-e]: Erase flash ROM" print "stlinkv2.py [-u]: Unlock flash ROM" print "stlinkv2.py [-s]: Show status" - print "stlinkv2.py [-b] [-n] [-r] FILE: Write content of FILE to flash ROM" + print "stlinkv2.py [-b] [-n] [-r] [-i] FILE: Write content of FILE to flash ROM" print " -b: Blank check before write (auto erase when not blank)" print " -n: Don't enable read protection after write" print " -r: Don't reset after write" + print " -i: Don't test SPI flash" -def main(show_help, erase_only, no_protect, reset_after_successful_write, +def main(show_help, erase_only, no_protect, spi_flash_check, + reset_after_successful_write, skip_blank_check, status_only, unlock, data): if show_help or len(sys.argv) != 1: help() @@ -514,6 +565,13 @@ def main(show_help, erase_only, no_protect, reset_after_successful_write, print "Flash ROM read protection disabled. Reset the board, now." return 0 + if spi_flash_check: + stl.spi_flash_init() + id = stl.spi_flash_read_id() + print "SPI Flash ROM ID: %06x" % id + if id != 0xbf254a: + raise ValueError("bad spi flash ROM ID") + if not blank: print "ERASE ALL" stl.reset_sys() @@ -566,6 +624,7 @@ if __name__ == '__main__': status_only = False unlock = False data = None + spi_flash_check = True while len(sys.argv) > 1: if sys.argv[1] == '-h': @@ -592,6 +651,8 @@ if __name__ == '__main__': no_protect = True elif sys.argv[1] == '-r': reset_after_successful_write = False + elif sys.argv[1] == '-i': + spi_flash_check = False else: filename = sys.argv[1] f = open(filename,'rb') @@ -602,7 +663,7 @@ if __name__ == '__main__': colorama_init() try: - r = main(show_help, erase_only, no_protect, + r = main(show_help, erase_only, no_protect, spi_flash_check, reset_after_successful_write, skip_blank_check, status_only, unlock, data) if r == 0: From 965dace0a4fb37f5f07c3ad2bc1641cf687cd15a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 6 Jul 2012 10:21:58 +0900 Subject: [PATCH 231/300] version 0.21 --- ChangeLog | 3 +++ NEWS | 5 +++-- README | 20 ++++++++++++-------- src/usb_desc.c | 2 +- test/README | 4 ++-- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7da509a..471a751 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-07-06 Niibe Yutaka + * Version 0.21. + * src/usb_desc.c (gnukStringSerial): Updated. + * boards/FST_01/board.h (VAL_GPIOACRL): Change for SPI flash. * tool/stlinkv2.py (stlinkv2.setup_gpio): Likewise. (stlinkv2.spi_flash_init, stlinkv2.spi_flash_select) diff --git a/NEWS b/NEWS index f175335..dbb278d 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,11 @@ Gnuk NEWS - User visible changes -* Major changes in Gnuk 1.0 +* Major changes in Gnuk 0.21 - Released 2012-0X-XX, by NIIBE Yutaka + Released 2012-07-06, by NIIBE Yutaka ** Test suite +A functinality test suite is added under test/ directory. ** New tool: stlinkv2.py This tool is SWD flash ROM writer with ST-Link/V2. diff --git a/README b/README index 352aa84..856de64 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - An Implementation of USB Cryptographic Token for GnuPG - Version 0.20 - 2012-06-19 + Version 0.21 + 2012-07-06 Niibe Yutaka Free Software Initiative of Japan @@ -106,15 +106,15 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: "GPG Password Agent" and "SSH Key Agent". Qc: Do you know a good SWD debugger to connect FST-01 or something? -Ac: STLink v2 is cheap one. See http://code.google.com/p/arm-utilities/ - for a control program. +Ac: STLink v2 is cheap one. We have a tool/stlinkv2.py as flash ROM +writer. Release notes ============= -This is "version 1.0 release candidate" of Gnuk. In this release, key -generation feature is added. While it is daily use, some features +This is another "version 1.0 release candidate" of Gnuk. In this +release, a test suite is added. While it is daily use, some features (including key generation and firmware upgrade) are still considered experimental. @@ -138,7 +138,7 @@ Tested features are: but you can remove all keys to import again). * Key generation on device side -Original feature of Gnuk, tested (lightly): +Original feature of Gnuk, tested lightly: * Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal @@ -554,11 +554,15 @@ This entry has been added into libccid 1.4.1 already ([r5425]). Testing Gnuk ------------ -Try following to see Gnuk runs: +Type following command to see Gnuk runs: $ gpg --card-status +Besides, there is a functinality test under test/ directory. See +test/README. + + Personalize the Token and import keys ------------------------------------- diff --git a/src/usb_desc.c b/src/usb_desc.c index 00642d5..ed90d99 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -262,7 +262,7 @@ const uint8_t gnukStringSerial[] = { USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ /* FSIJ-0.19 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '0', 0, '.', 0, '2', 0, '0', 0, /* Version number of Gnuk */ + '0', 0, '.', 0, '2', 0, '1', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/test/README b/test/README index 4c38942..ddcde9c 100644 --- a/test/README +++ b/test/README @@ -1,4 +1,4 @@ -This is functionality test suite for Gnuk. +This is a functionality test suite for Gnuk. You need python-nose, python-freshen as well as python-usb. @@ -17,4 +17,4 @@ or to run the test suite. To skip tests for key generation, add an option "--tag ~keygen". To -stop running tests after the first error or failure, add "--stop option". +stop running tests after the first error or failure, add "--stop" option. From a5fddc691d315ede7e7349e2e19b3a5820e35b8a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 09:26:10 +0900 Subject: [PATCH 232/300] fix decryption test case --- ChangeLog | 5 +++++ test/rsa_keys.py | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 471a751..3c8efd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-07-09 Niibe Yutaka + + * test/rsa_keys.py (integer_to_bytes_256): Rename from + integer_to_bytes and it should be exactly 256-byte long. + 2012-07-06 Niibe Yutaka * Version 0.21. diff --git a/test/rsa_keys.py b/test/rsa_keys.py index fe210b2..02b057d 100644 --- a/test/rsa_keys.py +++ b/test/rsa_keys.py @@ -125,24 +125,24 @@ def compute_signature(keyno, digestinfo): sig = t2 + t * q return sig -def integer_to_bytes(i): +def integer_to_bytes_256(i): s = hex(i)[2:] s = s.rstrip('L') if len(s) & 1: s = '0' + s - return unhexlify(s) + return string.rjust(unhexlify(s), 256, '\x00') def encrypt(keyno, plaintext): e = key[keyno][4] n = key[keyno][7] m = pkcs1_pad_for_crypt(plaintext) - return '\x00' + integer_to_bytes(pow(m, e, n)) + return '\x00' + integer_to_bytes_256(pow(m, e, n)) def encrypt_with_pubkey(pubkey_info, plaintext): n = int(hexlify(pubkey_info[0]), 16) e = int(hexlify(pubkey_info[1]), 16) m = pkcs1_pad_for_crypt(plaintext) - return '\x00' + integer_to_bytes(pow(m, e, n)) + return '\x00' + integer_to_bytes_256(pow(m, e, n)) def verify_signature(pubkey_info, digestinfo, sig): n = int(hexlify(pubkey_info[0]), 16) From 29b68186bfdfe6343c27447397c4e764a07c9a13 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 09:27:38 +0900 Subject: [PATCH 233/300] fix stlinkv2 for FST-01's LED --- ChangeLog | 2 ++ boards/FST_01/board.h | 3 +-- tool/stlinkv2.py | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c8efd1..a1ade4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-07-09 Niibe Yutaka + * tool/stlinkv2.py (stlinkv2.setup_gpio): Fix GPIOB_CRL. + * test/rsa_keys.py (integer_to_bytes_256): Rename from integer_to_bytes and it should be exactly 256-byte long. diff --git a/boards/FST_01/board.h b/boards/FST_01/board.h index 7b78e93..eafad06 100644 --- a/boards/FST_01/board.h +++ b/boards/FST_01/board.h @@ -101,10 +101,9 @@ * PA5 - Alternate Push pull output (SPI1_SCK) * PA6 - Alternate Push pull output (SPI1_MISO) * PA7 - Alternate Push pull output (SPI1_MOSI) + * PA10 - Push pull output (USB 1:ON 0:OFF) * 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 0xBBB38888 /* PA7...PA0 */ #define VAL_GPIOACRH 0x88888388 /* PA15...PA8 */ diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index bbb902f..8597ab7 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -227,8 +227,8 @@ class stlinkv2(object): self.write_memory_u32(GPIOA+0x04, 0x88888383) # CRH self.write_memory_u32(GPIOA+0x00, 0xBBB38888) # CRL self.write_memory_u32(GPIOB+0x0c, 0xffffffff) # ODR - self.write_memory_u32(GPIOB+0x04, 0x88888883) # CRH - self.write_memory_u32(GPIOB+0x00, 0x88888888) # CRL + self.write_memory_u32(GPIOB+0x04, 0x88888888) # CRH + self.write_memory_u32(GPIOB+0x00, 0x88888883) # CRL # For FST-01-00 and FST-01: LED off, USB off def finish_gpio(self): From 51435e7dbace1d0f2258a8292708588a755734b9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 09:29:00 +0900 Subject: [PATCH 234/300] return error sooner for decryption --- ChangeLog | 3 +++ src/openpgp.c | 13 +++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a1ade4d..b6e8581 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-07-09 Niibe Yutaka + * src/openpgp.c (cmd_pso): For decryption, return error sooner for + invalid data. + * tool/stlinkv2.py (stlinkv2.setup_gpio): Fix GPIOB_CRL. * test/rsa_keys.py (integer_to_bytes_256): Rename from diff --git a/src/openpgp.c b/src/openpgp.c index bc03b44..439db4e 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -776,10 +776,15 @@ cmd_pso (void) /* Skip padding 0x00 */ len--; - r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, - &kd[GPG_KEY_FOR_DECRYPTION]); - if (r < 0) - GPG_ERROR (); + if (len != KEY_CONTENT_LEN) + GPG_CONDITION_NOT_SATISFIED (); + else + { + r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len, + &kd[GPG_KEY_FOR_DECRYPTION]); + if (r < 0) + GPG_ERROR (); + } } else { From cbed6b49c7e294c0c5cb8594fa0375126aa08629 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 10:19:01 +0900 Subject: [PATCH 235/300] LED off for -u --- tool/stlinkv2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 8597ab7..3d88634 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -562,6 +562,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check, if unlock: stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) + stl.finish_gpio() print "Flash ROM read protection disabled. Reset the board, now." return 0 From f38f33daded617f28cc6bb849cd9e1b7074df987 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 12:58:03 +0900 Subject: [PATCH 236/300] bug fix for finish_gpio --- tool/stlinkv2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 3d88634..1fc42c6 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -232,11 +232,11 @@ class stlinkv2(object): # For FST-01-00 and FST-01: LED off, USB off def finish_gpio(self): + self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR + self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR apb2enr = self.read_memory_u32(0x40021018) apb2enr = apb2enr & ~(4 | 8 | 0x1000) self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR - self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR - self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR def spi_flash_init(self): self.write_memory_u32(SPI1+0x00, 0x0004); # CR1 <= MSTR From 99d7e8d3961b9e83149655dc904ede7fc81f30ee Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 9 Jul 2012 15:16:56 +0900 Subject: [PATCH 237/300] reset is not needed as writ_prvkey does so --- src/openpgp-do.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 567e089..10a6412 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -926,7 +926,6 @@ proc_key_import (const uint8_t *data, int len) if (*p == 0xb6) { kk = GPG_KEY_FOR_SIGNING; - ac_reset_pso_cds (); gpg_reset_digital_signature_counter (); } else @@ -935,7 +934,6 @@ proc_key_import (const uint8_t *data, int len) kk = GPG_KEY_FOR_DECRYPTION; else /* 0xa4 */ kk = GPG_KEY_FOR_AUTHENTICATION; - ac_reset_other (); } if (len <= 22) From e80c8f1e8e2011c4c41e994a66bc9b0d8097e440 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 08:50:32 +0900 Subject: [PATCH 238/300] USB disconnect tool/stlinkv2.py --- ChangeLog | 4 ++++ tool/stlinkv2.py | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6e8581..7e7d938 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-07-10 Niibe Yutaka + + * tool/stlinkv2.py (stlinkv2.usb_disconnect): New. + 2012-07-09 Niibe Yutaka * src/openpgp.c (cmd_pso): For decryption, return error sooner for diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index 1fc42c6..d2af143 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -216,23 +216,27 @@ class stlinkv2(object): v = self.execute_get("\xf2\x22\x00", 4) return v[0] + (v[1]<<8) + (v[2]<<16) + (v[3]<<24) - # For FST-01-00 and FST-01: LED on, USB off + # For FST-01-00 and FST-01: LED on, USB connect def setup_gpio(self): apb2enr = self.read_memory_u32(0x40021018) apb2enr = apb2enr | 4 | 8 | 0x1000 # Enable port A, port B, and SPI1 self.write_memory_u32(0x40021018, apb2enr) # RCC->APB2ENR self.write_memory_u32(0x4002100c, 4|8|0x1000) # RCC->APB2RSTR self.write_memory_u32(0x4002100c, 0) - self.write_memory_u32(GPIOA+0x0c, 0xfffffbff) # ODR + self.write_memory_u32(GPIOA+0x0c, 0xffffffff) # ODR self.write_memory_u32(GPIOA+0x04, 0x88888383) # CRH self.write_memory_u32(GPIOA+0x00, 0xBBB38888) # CRL self.write_memory_u32(GPIOB+0x0c, 0xffffffff) # ODR self.write_memory_u32(GPIOB+0x04, 0x88888888) # CRH self.write_memory_u32(GPIOB+0x00, 0x88888883) # CRL - # For FST-01-00 and FST-01: LED off, USB off + # For FST-01-00 and FST-01: LED on, USB disconnect + def usb_disconnect(self): + self.write_memory_u32(GPIOA+0x0c, 0xfffffbff) # ODR + + # For FST-01-00 and FST-01: LED off, USB connect def finish_gpio(self): - self.write_memory_u32(GPIOA+0x0c, 0xfffffaff) # ODR + self.write_memory_u32(GPIOA+0x0c, 0xfffffeff) # ODR self.write_memory_u32(GPIOB+0x0c, 0xfffffffe) # ODR apb2enr = self.read_memory_u32(0x40021018) apb2enr = apb2enr & ~(4 | 8 | 0x1000) @@ -562,6 +566,8 @@ def main(show_help, erase_only, no_protect, spi_flash_check, if unlock: stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) + stl.usb_disconnect() + time.sleep(0.100) stl.finish_gpio() print "Flash ROM read protection disabled. Reset the board, now." return 0 @@ -579,6 +585,8 @@ def main(show_help, erase_only, no_protect, spi_flash_check, stl.flash_erase_all() if erase_only: + stl.usb_disconnect() + time.sleep(0.100) stl.finish_gpio() return 0 @@ -607,6 +615,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check, print "Flash ROM read protection enabled. Reset the board to enable protection." if reset_after_successful_write: + stl.usb_disconnect() stl.reset_sys() stl.run() stl.exit_debug() From 144dd88a078a8e2b4df03e773a7051caee207ed9 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 08:51:38 +0900 Subject: [PATCH 239/300] Bug fix for keygen --- ChangeLog | 5 +++++ src/openpgp-do.c | 32 +++++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e7d938..e95790d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2012-07-10 Niibe Yutaka + * src/openpgp-do.c (gpg_do_write_prvkey): Don't call ac_reset_* + here. + (proc_key_import): But call ac_reset_* here. + (gpg_do_keygen): Load private key for signing. + * tool/stlinkv2.py (stlinkv2.usb_disconnect): New. 2012-07-09 Niibe Yutaka diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 10a6412..2be5aed 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -793,11 +793,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE); memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE); - if (kk == GPG_KEY_FOR_SIGNING) - ac_reset_pso_cds (); - else - ac_reset_other (); - if (ks_pw1) { ks_pw1_len = ks_pw1[0]; @@ -926,6 +921,7 @@ proc_key_import (const uint8_t *data, int len) if (*p == 0xb6) { kk = GPG_KEY_FOR_SIGNING; + ac_reset_pso_cds (); gpg_reset_digital_signature_counter (); } else @@ -934,6 +930,7 @@ proc_key_import (const uint8_t *data, int len) kk = GPG_KEY_FOR_DECRYPTION; else /* 0xa4 */ kk = GPG_KEY_FOR_AUTHENTICATION; + ac_reset_other (); } if (len <= 22) @@ -1570,26 +1567,27 @@ gpg_do_keygen (uint8_t kk_byte) if (kk == GPG_KEY_FOR_SIGNING) { - /* Authintication has been reset within gpg_do_write_prvkey. */ - /* But GnuPG expects it's ready for signing. */ - /* Thus, we call verify_pso_cds here. */ const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); - const uint8_t *pw; - int pw_len; + uint8_t keystring[KEYSTRING_MD_SIZE]; + const uint8_t *ks; + + /* GnuPG expects it's ready for signing. */ + /* Don't call ac_reset_pso_cds here, but load the private key */ if (ks_pw1) - { - pw = ks_pw1+1; - pw_len = ks_pw1[0]; - } + ks = ks_pw1+1; else { - pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; - pw_len = strlen (OPENPGP_CARD_INITIAL_PW3); + const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; + + s2k (BY_USER, pw, strlen (OPENPGP_CARD_INITIAL_PW3), keystring); + ks = keystring; } - verify_pso_cds (pw, pw_len); + gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, ks); } + else + ac_reset_other (); gpg_do_public_key (kk_byte); } From 63df97a2e02c001aca9b59d4afffaf05580e5003 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 08:55:48 +0900 Subject: [PATCH 240/300] Add tests --- ChangeLog | 4 ++++ test/features/202_keygen.feature | 7 +++++++ test/features/602_keygen.feature | 7 +++++++ 3 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index e95790d..8913c7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-07-10 Niibe Yutaka + * test/features/202_keygen.feature: Add PSO signature test after + keygen. + * test/features/602_keygen.feature: Ditto. + * src/openpgp-do.c (gpg_do_write_prvkey): Don't call ac_reset_* here. (proc_key_import): But call ac_reset_* here. diff --git a/test/features/202_keygen.feature b/test/features/202_keygen.feature index b9c69a3..dcecf32 100644 --- a/test/features/202_keygen.feature +++ b/test/features/202_keygen.feature @@ -21,6 +21,13 @@ Feature: key generation And put the second data to d0 Then it should get success + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "GnuPG assumes that PW1 keeps valid after keygen." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + Scenario: verify PW1 (1) after keygen Given cmd_verify with 1 and "another user pass phrase" Then it should get success diff --git a/test/features/602_keygen.feature b/test/features/602_keygen.feature index b9c69a3..dcecf32 100644 --- a/test/features/602_keygen.feature +++ b/test/features/602_keygen.feature @@ -21,6 +21,13 @@ Feature: key generation And put the second data to d0 Then it should get success + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "GnuPG assumes that PW1 keeps valid after keygen." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + Scenario: verify PW1 (1) after keygen Given cmd_verify with 1 and "another user pass phrase" Then it should get success From 6de9c113295cd83756260c88790e6e5cdf143954 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 10:36:15 +0900 Subject: [PATCH 241/300] test: fix signature counter --- test/features/210_compute_signature.feature | 2 +- test/features/610_compute_signature.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/features/210_compute_signature.feature b/test/features/210_compute_signature.feature index d7bc959..9491b78 100644 --- a/test/features/210_compute_signature.feature +++ b/test/features/210_compute_signature.feature @@ -33,4 +33,4 @@ Feature: compute digital signature Scenario: data object ds counter When requesting ds counter: 93 - Then you should get: \x00\x00\x02 + Then you should get: \x00\x00\x03 diff --git a/test/features/610_compute_signature.feature b/test/features/610_compute_signature.feature index d7bc959..9491b78 100644 --- a/test/features/610_compute_signature.feature +++ b/test/features/610_compute_signature.feature @@ -33,4 +33,4 @@ Feature: compute digital signature Scenario: data object ds counter When requesting ds counter: 93 - Then you should get: \x00\x00\x02 + Then you should get: \x00\x00\x03 From 8be278be17873badfbb6fa1b50c53a2e8ac6adb3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 13:21:27 +0900 Subject: [PATCH 242/300] not PW3 but PW1 --- src/openpgp-do.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 2be5aed..4194213 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -800,12 +800,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, } else { - uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; + uint8_t ks[KEYSTRING_MD_SIZE]; - ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1); - s2k (BY_USER, (uint8_t *)OPENPGP_CARD_INITIAL_PW1, - strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1); - encrypt_dek (ks123_pw1+1, pd->dek_encrypted_1); + s2k (BY_USER, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1, + strlen (OPENPGP_CARD_INITIAL_PW1), ks); + encrypt_dek (ks, pd->dek_encrypted_1); } if (ks_rc) @@ -1580,7 +1579,7 @@ gpg_do_keygen (uint8_t kk_byte) { const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1; - s2k (BY_USER, pw, strlen (OPENPGP_CARD_INITIAL_PW3), keystring); + s2k (BY_USER, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring); ks = keystring; } From 5d3e6c2b29f17cfd98597b50654c3efafacbac5e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 14:16:53 +0900 Subject: [PATCH 243/300] initial PW1 123456 test cases --- ChangeLog | 3 + test/features/770_key_removal.feature | 43 ++++++++++ .../780_personalization_reset.feature | 27 +++++++ test/features/790_reset_passphrase.feature | 7 ++ test/features/800_empty_check.feature | 79 +++++++++++++++++++ .../801_empty_check_passphrase.feature | 15 ++++ test/features/802_get_data_static.feature | 27 +++++++ test/features/810_setup_passphrase.feature | 15 ++++ .../820_personalization_write.feature | 27 +++++++ .../features/821_personalization_read.feature | 27 +++++++ test/features/830_key_registration.feature | 56 +++++++++++++ test/features/850_compute_signature.feature | 31 ++++++++ test/features/851_decryption.feature | 16 ++++ test/features/860_key_removal.feature | 48 +++++++++++ test/features/862_keygen.feature | 37 +++++++++ test/features/870_compute_signature.feature | 36 +++++++++ test/features/871_decryption.feature | 19 +++++ 17 files changed, 513 insertions(+) create mode 100644 test/features/770_key_removal.feature create mode 100644 test/features/780_personalization_reset.feature create mode 100644 test/features/790_reset_passphrase.feature create mode 100644 test/features/800_empty_check.feature create mode 100644 test/features/801_empty_check_passphrase.feature create mode 100644 test/features/802_get_data_static.feature create mode 100644 test/features/810_setup_passphrase.feature create mode 100644 test/features/820_personalization_write.feature create mode 100644 test/features/821_personalization_read.feature create mode 100644 test/features/830_key_registration.feature create mode 100644 test/features/850_compute_signature.feature create mode 100644 test/features/851_decryption.feature create mode 100644 test/features/860_key_removal.feature create mode 100644 test/features/862_keygen.feature create mode 100644 test/features/870_compute_signature.feature create mode 100644 test/features/871_decryption.feature diff --git a/ChangeLog b/ChangeLog index 8913c7f..13b410f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,12 @@ 2012-07-10 Niibe Yutaka + * test/features/*: Add test cases for PW1/PW3 of factory settings. + * test/features/202_keygen.feature: Add PSO signature test after keygen. * test/features/602_keygen.feature: Ditto. + Bug fix. * src/openpgp-do.c (gpg_do_write_prvkey): Don't call ac_reset_* here. (proc_key_import): But call ac_reset_* here. diff --git a/test/features/770_key_removal.feature b/test/features/770_key_removal.feature new file mode 100644 index 0000000..a8c50b1 --- /dev/null +++ b/test/features/770_key_removal.feature @@ -0,0 +1,43 @@ +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "12345678" + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success diff --git a/test/features/780_personalization_reset.feature b/test/features/780_personalization_reset.feature new file mode 100644 index 0000000..51a3430 --- /dev/null +++ b/test/features/780_personalization_reset.feature @@ -0,0 +1,27 @@ +Feature: removal of data objects + In order to use a token + A token should have personalized data + + Scenario: remove data object Login + Given cmd_put_data with 5e and "" + Then it should get success + + Scenario: remove data object Name + Given cmd_put_data with 5b and "" + Then it should get success + + Scenario: remove data object Language preference + Given cmd_put_data with 5f2d and "" + Then it should get success + + Scenario: remove data object Sex + Given cmd_put_data with 5f35 and "" + Then it should get success + + Scenario: remove data object URL + Given cmd_put_data with 5f50 and "" + Then it should get success + + Scenario: remove data object pw1 status bytes + Given cmd_put_data with c4 and "\x00" + Then it should get success diff --git a/test/features/790_reset_passphrase.feature b/test/features/790_reset_passphrase.feature new file mode 100644 index 0000000..78edf9a --- /dev/null +++ b/test/features/790_reset_passphrase.feature @@ -0,0 +1,7 @@ +Feature: confirm factory setting pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: verify PW3 (admin-less mode) + Given cmd_verify with 3 and "12345678" + Then it should get success diff --git a/test/features/800_empty_check.feature b/test/features/800_empty_check.feature new file mode 100644 index 0000000..4f4d35e --- /dev/null +++ b/test/features/800_empty_check.feature @@ -0,0 +1,79 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no data, no keys) + + Scenario: data object Login + When requesting login data: 5e + Then you should get NULL + + Scenario: data object Name + When requesting name: 5b + Then you should get NULL + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get NULL + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get NULL + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get NULL + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x00 + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03 + + Scenario: data object finger print 0 + When requesting finger print: c5 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object finger print 1 + When requesting finger print: c7 + Then you should get NULL + + Scenario: data object finger print 2 + When requesting finger print: c8 + Then you should get NULL + + Scenario: data object finger print 3 + When requesting finger print: c9 + Then you should get NULL + + Scenario: data object CA finger print 0 + When requesting finger print: c6 + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object CA finger print 1 + When requesting finger print: ca + Then you should get NULL + + Scenario: data object CA finger print 2 + When requesting finger print: cb + Then you should get NULL + + Scenario: data object CA finger print 3 + When requesting finger print: cc + Then you should get NULL + + Scenario: data object date/time of key pair 0 + When requesting date/time of key pair: cd + Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 + + Scenario: data object date/time of key pair 1 + When requesting date/time of key pair: ce + Then you should get NULL + + Scenario: data object date/time of key pair 2 + When requesting date/time of key pair: cf + Then you should get NULL + + Scenario: data object date/time of key pair 3 + When requesting date/time of key pair: d0 + Then you should get NULL diff --git a/test/features/801_empty_check_passphrase.feature b/test/features/801_empty_check_passphrase.feature new file mode 100644 index 0000000..f026b08 --- /dev/null +++ b/test/features/801_empty_check_passphrase.feature @@ -0,0 +1,15 @@ +Feature: confirm empty token + In order to start tests + A token should be empty (no pass phrase) + + Scenario: verify PW1 factory setting (1) + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 factory setting (2) + Given cmd_verify with 2 and "123456" + Then it should get success + + Scenario: verify PW3 factory setting + Given cmd_verify with 3 and "12345678" + Then it should get success diff --git a/test/features/802_get_data_static.feature b/test/features/802_get_data_static.feature new file mode 100644 index 0000000..9de7425 --- /dev/null +++ b/test/features/802_get_data_static.feature @@ -0,0 +1,27 @@ +Feature: command GET DATA + In order to conform OpenPGP card 2.0 specification + A token should support all mandatory features of the specification + + Scenario: data object historical bytes + When requesting historical bytes: 5f52 + Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00 + + Scenario: data object extended capabilities + When requesting extended capabilities: c0 + Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + + Scenario: data object algorithm attributes 1 + When requesting algorithm attributes 1: c1 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 2 + When requesting algorithm attributes 2: c2 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object algorithm attributes 3 + When requesting algorighm attributes 3: c3 + Then you should get: \x01\x08\x00\x00\x20\x00 + + Scenario: data object AID + When requesting AID: 4f + Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00 diff --git a/test/features/810_setup_passphrase.feature b/test/features/810_setup_passphrase.feature new file mode 100644 index 0000000..d3b086d --- /dev/null +++ b/test/features/810_setup_passphrase.feature @@ -0,0 +1,15 @@ +Feature: check pass phrase + In order to conform OpenPGP card 2.0 specification + A token should support pass phrase: PW1, PW3 and reset code + + Scenario: verify PW1 (1) + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 (2) + Given cmd_verify with 2 and "123456" + Then it should get success + + Scenario: verify PW3 + Given cmd_verify with 3 and "12345678" + Then it should get success diff --git a/test/features/820_personalization_write.feature b/test/features/820_personalization_write.feature new file mode 100644 index 0000000..2fdd387 --- /dev/null +++ b/test/features/820_personalization_write.feature @@ -0,0 +1,27 @@ +Feature: personalize token write + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + Given cmd_put_data with 5e and "gpg_user" + Then it should get success + + Scenario: data object Name + Given cmd_put_data with 5b and "GnuPG User" + Then it should get success + + Scenario: data object Language preference + Given cmd_put_data with 5f2d and "ja" + Then it should get success + + Scenario: data object Sex + Given cmd_put_data with 5f35 and "1" + Then it should get success + + Scenario: data object URL + Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/" + Then it should get success + + Scenario: data object pw1 status bytes + Given cmd_put_data with c4 and "\x01" + Then it should get success diff --git a/test/features/821_personalization_read.feature b/test/features/821_personalization_read.feature new file mode 100644 index 0000000..5f0f972 --- /dev/null +++ b/test/features/821_personalization_read.feature @@ -0,0 +1,27 @@ +Feature: personalize token read + In order to use a token + A token should be personalized with name, sex, url, etc. + + Scenario: data object Login + When requesting login data: 5e + Then you should get: gpg_user + + Scenario: data object Name + When requesting name: 5b + Then you should get: GnuPG User + + Scenario: data object Language preference + When requesting anguage preference: 5f2d + Then you should get: ja + + Scenario: data object Sex + When requesting sex: 5f35 + Then you should get: 1 + + Scenario: data object URL + When requesting URL: 5f50 + Then you should get: http://www.fsij.org/gnuk/ + + Scenario: data object pw1 status bytes + When requesting pw1 status bytes: c4 + Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03 diff --git a/test/features/830_key_registration.feature b/test/features/830_key_registration.feature new file mode 100644 index 0000000..24246af --- /dev/null +++ b/test/features/830_key_registration.feature @@ -0,0 +1,56 @@ +Feature: import keys to token + In order to use a token + A token should have keys + + Scenario: importing OPENPGP.1 key (sign) + Given a RSA key pair 0 + And importing it to the token as OPENPGP.1 + Then it should get success + + Scenario: importing OPENPGP.2 key (decrypt) + Given a RSA key pair 1 + And importing it to the token as OPENPGP.2 + Then it should get success + + Scenario: importing OPENPGP.3 key (authentication) + Given a RSA key pair 2 + And importing it to the token as OPENPGP.3 + Then it should get success + + Scenario: setup data object Finger print sig + Given a fingerprint of OPENPGP.1 key + And put the data to c7 + Then it should get success + + Scenario: setup data object Finger print dec + Given a fingerprint of OPENPGP.2 key + And put the data to c8 + Then it should get success + + Scenario: setup data object Finger print aut + Given a fingerprint of OPENPGP.3 key + And put the data to c9 + Then it should get success + + Scenario: setup data object keygeneration data/time sig + Given a timestamp of OPENPGP.1 key + And put the data to ce + Then it should get success + + Scenario: setup data object keygeneration data/time dec + Given a timestamp of OPENPGP.2 key + And put the data to cf + Then it should get success + + Scenario: setup data object keygeneration data/time aut + Given a timestamp of OPENPGP.3 key + And put the data to d0 + Then it should get success + + Scenario: verify PW1 (1) again + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 (2) again + Given cmd_verify with 2 and "123456" + Then it should get success diff --git a/test/features/850_compute_signature.feature b/test/features/850_compute_signature.feature new file mode 100644 index 0000000..67fcbcc --- /dev/null +++ b/test/features/850_compute_signature.feature @@ -0,0 +1,31 @@ +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token compute digital signature + And compute digital signature on host with RSA key pair 0 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And let a token authenticate + And compute digital signature on host with RSA key pair 2 + Then results should be same + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x02 diff --git a/test/features/851_decryption.feature b/test/features/851_decryption.feature new file mode 100644 index 0000000..1985dee --- /dev/null +++ b/test/features/851_decryption.feature @@ -0,0 +1,16 @@ +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And encrypt it on host with RSA key pair 1 + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + diff --git a/test/features/860_key_removal.feature b/test/features/860_key_removal.feature new file mode 100644 index 0000000..ad4db98 --- /dev/null +++ b/test/features/860_key_removal.feature @@ -0,0 +1,48 @@ +@keygen +Feature: key removal + In order to use a token + A token should have keys + + Scenario: remove OPENPGP.1 key (sign) + When removing a key OPENPGP.1 + Then it should get success + + Scenario: remove OPENPGP.2 key (decrypt) + When removing a key OPENPGP.2 + Then it should get success + + Scenario: remove OPENPGP.3 key (authentication) + When removing a key OPENPGP.3 + Then it should get success + + Scenario: remove data object Finger print sig + Given cmd_put_data with c7 and "" + Then it should get success + + Scenario: remove data object Finger print dec + Given cmd_put_data with c8 and "" + Then it should get success + + Scenario: remove data object Finger print aut + Given cmd_put_data with c9 and "" + Then it should get success + + Scenario: remove data object keygeneration data/time sig + Given cmd_put_data with ce and "" + Then it should get success + + Scenario: remove data object keygeneration data/time dec + Given cmd_put_data with cf and "" + Then it should get success + + Scenario: remove data object keygeneration data/time aut + Given cmd_put_data with d0 and "" + Then it should get success + + Scenario: verify PW1 + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW2 + Given cmd_verify with 2 and "123456" + Then it should get success diff --git a/test/features/862_keygen.feature b/test/features/862_keygen.feature new file mode 100644 index 0000000..9cbde5b --- /dev/null +++ b/test/features/862_keygen.feature @@ -0,0 +1,37 @@ +@keygen +Feature: key generation + In order to use a token + A token should have keys + + Scenario: generate OPENPGP.1 key (sign) + When generating a key of OPENPGP.1 + And put the first data to c7 + And put the second data to ce + Then it should get success + + Scenario: generate OPENPGP.2 key (decrypt) + When generating a key of OPENPGP.2 + And put the first data to c8 + And put the second data to cf + Then it should get success + + Scenario: generate OPENPGP.3 key (authentication) + When generating a key of OPENPGP.3 + And put the first data to c9 + And put the second data to d0 + Then it should get success + + Scenario: compute digital signature by OPENPGP.1 key + Given a message "GnuPG assumes that PW1 keeps valid after keygen." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: verify PW1 (1) after keygen + Given cmd_verify with 1 and "123456" + Then it should get success + + Scenario: verify PW1 (2) after keygen + Given cmd_verify with 2 and "123456" + Then it should get success diff --git a/test/features/870_compute_signature.feature b/test/features/870_compute_signature.feature new file mode 100644 index 0000000..9491b78 --- /dev/null +++ b/test/features/870_compute_signature.feature @@ -0,0 +1,36 @@ +@keygen +Feature: compute digital signature + In order to use a token + A token should compute digital signature properly + + Scenario: compute digital signature by OPENPGP.1 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.1 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.1 + And let a token compute digital signature + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (1) + Given a message "This is a test message." + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: compute digital signature by OPENPGP.3 key (2) + Given a message "This is another test message.\nMultiple lines.\n" + And a public key from token for OPENPGP.3 + And let a token authenticate + And verify signature + Then it should get success + + Scenario: data object ds counter + When requesting ds counter: 93 + Then you should get: \x00\x00\x03 diff --git a/test/features/871_decryption.feature b/test/features/871_decryption.feature new file mode 100644 index 0000000..e1cc98c --- /dev/null +++ b/test/features/871_decryption.feature @@ -0,0 +1,19 @@ +@keygen +Feature: decryption + In order to use a token + A token should decrypt encrypted data + + Scenario: decrypt by OPENPGP.2 key (1) + Given a plain text "This is a test message." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + + Scenario: decrypt by OPENPGP.2 key (2) + Given a plain text "RSA decryption is as easy as pie." + And a public key from token for OPENPGP.2 + And encrypt it on host + And let a token decrypt encrypted data + Then decrypted data should be same as a plain text + From d3fb62b437e5d7873cafd457e3f9294515da37c6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 17:03:50 +0900 Subject: [PATCH 244/300] no keygen test cases --- test/features/210_compute_signature.feature | 2 +- test/features/610_compute_signature.feature | 2 +- test/features/870_compute_signature.feature | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/features/210_compute_signature.feature b/test/features/210_compute_signature.feature index 9491b78..7d9398b 100644 --- a/test/features/210_compute_signature.feature +++ b/test/features/210_compute_signature.feature @@ -33,4 +33,4 @@ Feature: compute digital signature Scenario: data object ds counter When requesting ds counter: 93 - Then you should get: \x00\x00\x03 + Then data should match: \x00\x00(\x02|\x03) diff --git a/test/features/610_compute_signature.feature b/test/features/610_compute_signature.feature index 9491b78..7d9398b 100644 --- a/test/features/610_compute_signature.feature +++ b/test/features/610_compute_signature.feature @@ -33,4 +33,4 @@ Feature: compute digital signature Scenario: data object ds counter When requesting ds counter: 93 - Then you should get: \x00\x00\x03 + Then data should match: \x00\x00(\x02|\x03) diff --git a/test/features/870_compute_signature.feature b/test/features/870_compute_signature.feature index 9491b78..7d9398b 100644 --- a/test/features/870_compute_signature.feature +++ b/test/features/870_compute_signature.feature @@ -33,4 +33,4 @@ Feature: compute digital signature Scenario: data object ds counter When requesting ds counter: 93 - Then you should get: \x00\x00\x03 + Then data should match: \x00\x00(\x02|\x03) From 1927f8a1ec12e0ab1f457ce3e2fe9d5f2dded9a6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 10 Jul 2012 17:04:14 +0900 Subject: [PATCH 245/300] update doc/ --- doc/HACKING | 2 +- doc/NOTES | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/HACKING b/doc/HACKING index 5087246..fc5be9a 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -1,4 +1,4 @@ -* Random Number Generator +* [DONE] Random Number Generator RNG is needed for Data Encryption Key to encrypt private key (P and Q). It is important to collect enough entropy. Perhaps, it would diff --git a/doc/NOTES b/doc/NOTES index ad39233..7b4a052 100644 --- a/doc/NOTES +++ b/doc/NOTES @@ -77,7 +77,8 @@ KEYPTR <---encrypted----><--- plain ----> key_addr 4-byte -additional_data_encrypted 16-byte +initial_vector (random) 16-byte +checksum_encrypted 16-byte dek_encrypted_by_keystring_pw1 16-byte dek_encrypted_by_keystring_rc 16-byte dek_encrypted_by_keystring_pw3 16-byte @@ -85,6 +86,4 @@ dek_encrypted_by_keystring_pw3 16-byte ... decrypted to [ P ][ Q ] -check 4-byte -random 4-byte -magic[] 8-byte +checksum 16-byte From 814f6b63299c801259ef254594f61ccba7ad3a7d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jul 2012 13:04:39 +0900 Subject: [PATCH 246/300] update README --- README | 65 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/README b/README index 856de64..f2b7957 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - An Implementation of USB Cryptographic Token for GnuPG - Version 0.21 - 2012-07-06 + Version 1.0 + 2012-08-XX Niibe Yutaka Free Software Initiative of Japan @@ -30,11 +30,7 @@ Q0: How Gnuk USB Token is superior than other solutions (OpenPGP card 2.0, GPF Crypto Stick, etc.) ? http://www.g10code.de/p-card.html http://www.privacyfoundation.de/crypto_stick/ -A0: IMRHO, not quite, since there is no ready-to-use out-of-box Gnuk - product yet. (It is welcome for me that some vendor will - manufacture Gnuk USB Token. Even I can help design of hardware, - if needed.) - Good points for Gnuk are: +A0: Good points of Gnuk are: * If you have skill of electronics and like DIY, you can build Gnuk Token cheaper (see Q8-A8). * You can study Gnuk to modify and to enhance. For example, you @@ -60,7 +56,7 @@ A3: Orthodox choice is Olimex STM32-H103. 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 - 2.0.14-2 (in sid). With older versions, you can only sign with SHA1. + 2.0.18-2. With older versions, you can only sign with SHA1. See: http://www.fsij.org/gnuk/gnupg2-fixes-needed Q5: What's version of pcscd and libccid are you using? @@ -83,13 +79,18 @@ A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build http://www.fsij.org/gnuk/jtag_dongle_ftdi2232 Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up? + A9: GnuPG's SCDaemon has problems for handling insertion/removal of - card/reader (problems are fixed in trunk). When your newly - inserted token is not found by GnuPG, try killing scdaemon and let - it to be invoked again. I do: - $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye + card/reader (problems are fixed in trunk, and backported to 2.0 + branch, it will be 2.0.20). When your newly inserted token is not + found by GnuPG, try killing scdaemon and let it to be invoked + again. I do: + + $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye + and confirm scdaemon doesn't exist, then, - $ gpg-connect-agent learn /bye + + $ gpg-connect-agent learn /bye Qa: With GNOME 2, 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 @@ -107,16 +108,16 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: Qc: Do you know a good SWD debugger to connect FST-01 or something? Ac: STLink v2 is cheap one. We have a tool/stlinkv2.py as flash ROM -writer. +writer program. Release notes ============= -This is another "version 1.0 release candidate" of Gnuk. In this -release, a test suite is added. While it is daily use, some features -(including key generation and firmware upgrade) are still considered -experimental. +This is version 1.0 release of Gnuk, after a year and eleven months +development. While it is daily use for a year or so, some newly +introduced features (including key generation and firmware upgrade) +should be considered experimental. Tested features are: @@ -133,13 +134,16 @@ Tested features are: * Changing value of password status bytes (0x00C4): forcesig * Verify with pin pad * Modify with pin pad - * Card holder certificate - * Removal of keys (Overriding key import is not supported, + * Card holder certificate (read) + * Removal of keys + (Overriding key import is not supported, but you can remove all keys to import again). * Key generation on device side -Original feature of Gnuk, tested lightly: +Original features of Gnuk, tested lightly: + * OpenPGP card serial number setup + * Card holder certificate (write by UPDATE BINARY) * Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal It is known not-working well: @@ -148,11 +152,11 @@ It is known not-working well: work well. Please make sure to disable DEBUG option if it doesn't work well. -It is known that the combination libccid 1.4.1 (or newer) with libusb -1.0.8 (or older) has a problem. It is possible for USB communication -to be failed, because of a bug in libusb implementation. Use libusbx -1.0.9 or newer, or don't use PC/SC, but use internal CCID driver of -GnuPG. +It is known that the combination of libccid 1.4.1 (or newer) with +libusb 1.0.8 (or older) has a minor problem. It is rare but it is +possible for USB communication to be failed, because of a bug in +libusb implementation. Use libusbx 1.0.9 or newer, or don't use +PC/SC, but use internal CCID driver of GnuPG. Targets @@ -288,15 +292,16 @@ respect users' freedom for computing. Please ask FSIJ for the license. Otherwise, companies which want to distribute Gnuk devices, please use -your own USB vendor ID and product ID. Note that please replace -"FSIJ" in the string gnukStringSerial (usb_desc.c) to yours, when you -modify Gnuk. +your own USB vendor ID and product ID. Please replace "FSIJ" in the +string gnukStringSerial (usb_desc.c) to yours, when you modify Gnuk. Host Requirements ================= -For GNU/Linux, libccid version >= 1.3.11 is recommended. +For GNU/Linux, PC/SC service is an option, you can use GnuPG's +internal CCID driver instead. If you chose using PC/SC service, +libccid version >= 1.3.11 is recommended for GNU/Linux. I think that it should not be requirment but the kernel version of my use is: Linux version 2.6.32-5-686 (Debian 2.6.32-18) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-2) ) #1 SMP Sat Jul 24 02:27:10 UTC 2010 From 9ffa68355d7bc41638fda932687061b0d369c17b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jul 2012 13:12:51 +0900 Subject: [PATCH 247/300] update README for gcc-arm-embedded toolchain --- README | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README b/README index f2b7957..2d1ed0c 100644 --- a/README +++ b/README @@ -317,7 +317,7 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target. See http://github.com/esden/summon-arm-toolchain/ (which includes fix of binutils-2.21.1) for preparation of GNU Toolchain for -'arm-none-eabi' target. +'arm-none-eabi' target. This is for GCC 4.5. # Note that we need to link correct C library (for string functions). # For this purpose, Makefile.in contains following line: @@ -333,6 +333,13 @@ of binutils-2.21.1) for preparation of GNU Toolchain for # -mno-thumb-interwork option. This means that you should not # link C library which contains ARM (not Thumb) code. +Recently, there is "gcc-arm-embedded" project. See: + + https://launchpad.net/gcc-arm-embedded/ + +It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd +need "-O3 -s" instead of "-O2". + Change directory to `src': From 92be182e8a2f8ba607039361c48ad961781d2cd4 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jul 2012 13:24:15 +0900 Subject: [PATCH 248/300] update README for gcc-arm-embedded toolchain --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 2d1ed0c..b617cb6 100644 --- a/README +++ b/README @@ -338,7 +338,7 @@ Recently, there is "gcc-arm-embedded" project. See: https://launchpad.net/gcc-arm-embedded/ It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd -need "-O3 -s" instead of "-O2". +need "-O3 -s" instead of "-O2" and it will be slightly better. Change directory to `src': From 63979416f6d52302d3e0f02b17a9a0802bb28eb6 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 20 Jul 2012 16:00:41 +0900 Subject: [PATCH 249/300] fix tests for CERTDO --- ChangeLog | 7 +++++++ test/features/002_get_data_static.feature | 2 +- test/features/402_get_data_static.feature | 2 +- test/features/802_get_data_static.feature | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13b410f..90b3e68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-07-20 Niibe Yutaka + + * test/features/002_get_data_static.feature: Support CERTDO enabled + Gnuk for the test of extended capabilities. + * test/features/802_get_data_static.feature: Ditto. + * test/features/402_get_data_static.feature: Ditto. + 2012-07-10 Niibe Yutaka * test/features/*: Add test cases for PW1/PW3 of factory settings. diff --git a/test/features/002_get_data_static.feature b/test/features/002_get_data_static.feature index 9de7425..63d31c7 100644 --- a/test/features/002_get_data_static.feature +++ b/test/features/002_get_data_static.feature @@ -8,7 +8,7 @@ Feature: command GET DATA Scenario: data object extended capabilities When requesting extended capabilities: c0 - Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + Then data should match: \x30\x00\x00\x00[\x00\x08]\x00\x00\xff\x01\x00 Scenario: data object algorithm attributes 1 When requesting algorithm attributes 1: c1 diff --git a/test/features/402_get_data_static.feature b/test/features/402_get_data_static.feature index 9de7425..63d31c7 100644 --- a/test/features/402_get_data_static.feature +++ b/test/features/402_get_data_static.feature @@ -8,7 +8,7 @@ Feature: command GET DATA Scenario: data object extended capabilities When requesting extended capabilities: c0 - Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + Then data should match: \x30\x00\x00\x00[\x00\x08]\x00\x00\xff\x01\x00 Scenario: data object algorithm attributes 1 When requesting algorithm attributes 1: c1 diff --git a/test/features/802_get_data_static.feature b/test/features/802_get_data_static.feature index 9de7425..63d31c7 100644 --- a/test/features/802_get_data_static.feature +++ b/test/features/802_get_data_static.feature @@ -8,7 +8,7 @@ Feature: command GET DATA Scenario: data object extended capabilities When requesting extended capabilities: c0 - Then you should get: \x30\x00\x00\x00\x00\x00\x00\xff\x01\x00 + Then data should match: \x30\x00\x00\x00[\x00\x08]\x00\x00\xff\x01\x00 Scenario: data object algorithm attributes 1 When requesting algorithm attributes 1: c1 From c488bed21551c4deb5149fb40f7eb0ef93966a4e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 21 Jul 2012 08:32:53 +0900 Subject: [PATCH 250/300] move old documents to doc/note --- README | 4 ++-- doc/{ => note}/DEMO | 0 doc/{ => note}/DEMO-2 | 0 doc/{ => note}/HACKING | 0 doc/{ => note}/NOTES | 0 doc/{ => note}/firmware-update | 0 doc/{ => note}/settings-for-DnDpinentry | 0 7 files changed, 2 insertions(+), 2 deletions(-) rename doc/{ => note}/DEMO (100%) rename doc/{ => note}/DEMO-2 (100%) rename doc/{ => note}/HACKING (100%) rename doc/{ => note}/NOTES (100%) rename doc/{ => note}/firmware-update (100%) rename doc/{ => note}/settings-for-DnDpinentry (100%) diff --git a/README b/README index b617cb6..b80aaaa 100644 --- a/README +++ b/README @@ -594,7 +594,7 @@ RSA), you can import them. Gnuk supports key generation, but this feature is young and should be considered experimental. -For detail, please see doc/DEMO and doc/DEMO-2. +For detail, please see doc/note/DEMO and doc/note/DEMO-2. Note that it make sense to preserve your keys on your computer so that you can import the keys (again) to (possibly another) Gnuk Token. In @@ -656,7 +656,7 @@ linux/Documentation/usb/usbmon.txt Firmware update =============== -See doc/firmware-update. +See doc/note/firmware-update. Read-only Git Repository diff --git a/doc/DEMO b/doc/note/DEMO similarity index 100% rename from doc/DEMO rename to doc/note/DEMO diff --git a/doc/DEMO-2 b/doc/note/DEMO-2 similarity index 100% rename from doc/DEMO-2 rename to doc/note/DEMO-2 diff --git a/doc/HACKING b/doc/note/HACKING similarity index 100% rename from doc/HACKING rename to doc/note/HACKING diff --git a/doc/NOTES b/doc/note/NOTES similarity index 100% rename from doc/NOTES rename to doc/note/NOTES diff --git a/doc/firmware-update b/doc/note/firmware-update similarity index 100% rename from doc/firmware-update rename to doc/note/firmware-update diff --git a/doc/settings-for-DnDpinentry b/doc/note/settings-for-DnDpinentry similarity index 100% rename from doc/settings-for-DnDpinentry rename to doc/note/settings-for-DnDpinentry From add6fa8b67a789b9cc58cce67743845945389f45 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 21 Jul 2012 08:33:31 +0900 Subject: [PATCH 251/300] add document in Sphinx --- doc/Makefile | 153 +++++++++++++++++++++++++++++++ doc/conf.py | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 22 +++++ 3 files changed, 421 insertions(+) create mode 100644 doc/Makefile create mode 100644 doc/conf.py create mode 100644 doc/index.rst diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..7140903 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GnukDocumentation.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GnukDocumentation.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/GnukDocumentation" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GnukDocumentation" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000..9221b32 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +# +# Gnuk Documentation documentation build configuration file, created by +# sphinx-quickstart on Wed Jul 4 15:29:05 2012. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Gnuk Documentation' +copyright = u'2012, Niibe Yutaka' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GnukDocumentationdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'GnukDocumentation.tex', u'Gnuk Documentation Documentation', + u'Niibe Yutaka', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gnukdocumentation', u'Gnuk Documentation Documentation', + [u'Niibe Yutaka'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'GnukDocumentation', u'Gnuk Documentation Documentation', + u'Niibe Yutaka', 'GnukDocumentation', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..30416e3 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,22 @@ +.. Gnuk Documentation documentation master file, created by + sphinx-quickstart on Wed Jul 4 15:29:05 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Gnuk Documentation's documentation! +============================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + From df5b7f31a32197a9c82a7fa3e9cf70dc777161f1 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 21 Jul 2012 09:26:51 +0900 Subject: [PATCH 252/300] doc --- .gitignore | 1 + ChangeLog | 6 +++++ doc/Makefile | 2 +- doc/development.rst | 60 +++++++++++++++++++++++++++++++++++++++++++++ doc/intro.rst | 45 ++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 doc/development.rst create mode 100644 doc/intro.rst diff --git a/.gitignore b/.gitignore index aac6cef..8233be1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ src/*.inc regnual/regnual.bin regnual/regnual.hex regnual/regnual.elf +doc/_build diff --git a/ChangeLog b/ChangeLog index 90b3e68..53520c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-07-21 Niibe Yutaka + + Documentation by Sphinx. + * doc/Makefile: New. + * doc/note: Old notes are moved here. + 2012-07-20 Niibe Yutaka * test/features/002_get_data_static.feature: Support CERTDO enabled diff --git a/doc/Makefile b/doc/Makefile index 7140903..14d3b22 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build -PAPER = +PAPER = a4 BUILDDIR = _build # Internal variables. diff --git a/doc/development.rst b/doc/development.rst new file mode 100644 index 0000000..df3d30f --- /dev/null +++ b/doc/development.rst @@ -0,0 +1,60 @@ +Development Environment +======================= + + +Hardware +-------- + +JTAG debugger or SWD debugger is required. + + +GNU Toolchain +------------- + +You need GNU toolchain and newlib for 'arm-none-eabi' target. + +See http://github.com/esden/summon-arm-toolchain/ (which includes fix +of binutils-2.21.1) for preparation of GNU Toolchain for +'arm-none-eabi' target. This is for GCC 4.5. + +Note that we need to link correct C library (for string functions). +For this purpose, our src/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 it is needed for the configuration of +patch-gcc-config-arm-t-arm-elf.diff in summon-arm-toolchain in practice. + +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. + +Recently, there is "gcc-arm-embedded" project. See: +https://launchpad.net/gcc-arm-embedded/ + +It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd +need "-O3 -s" instead of "-O2" and it will be slightly better. + + + +Building Gnuk +------------- + +Change directory to ``src``: + + $ cd gnuk-VERSION/src + +Then, run ``configure``: + + $ ./configure --vidpid= + +Here, you need to specify USB vendor ID and product ID. For FSIJ's, +it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and +product ID' above. + +Type: + + $ make + +Then, we will have "gnuk.elf". diff --git a/doc/intro.rst b/doc/intro.rst new file mode 100644 index 0000000..63933b4 --- /dev/null +++ b/doc/intro.rst @@ -0,0 +1,45 @@ +Introduction +============ + + +What's Gnuk? +------------ + +Gnuk is an implementation of USB cryptographic token for GNU Privacy +Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on +STM32F103 processor. + + +Cryptographic token and feature of Gnuk +--------------------------------------- + +Cryptographic token is a store of private keys and it computes cryptographic functions on the device. + + +Development Environment +----------------------- + +See :doc:`development` for development environment for Gnuk. It builds on Free Software. + + +Prerequisites +------------- + +* GNU Privacy Guard (GnuPG) + +* libusb + +* [Optional] PC/SC lite (pcscd, libccid) + +* SSH: openssh + +* Web: scute, firefox + + +Usage +----- + +* Sign with GnuPG +* Decrypt with GnuPG +* Use with OpenSSH +* Use with Firefox for X.509 client certificate authentication From 5e9a35c8816d88cd7a2d94a78f7f5d7ae5441c7c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 21 Jul 2012 09:27:08 +0900 Subject: [PATCH 253/300] doc --- doc/index.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 30416e3..17d08f7 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,14 +3,16 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to Gnuk Documentation's documentation! -============================================== +Gnuk Documentation +================== Contents: .. toctree:: :maxdepth: 2 + intro.rst + development.rst Indices and tables From 71eaffc0ee091d194676fa90743745001454d586 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 21 Jul 2012 09:33:28 +0900 Subject: [PATCH 254/300] version 1.0 --- ChangeLog | 3 +++ README | 4 ++-- src/usb_desc.c | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 53520c1..614c1cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-07-21 Niibe Yutaka + * Version 1.0. + * src/usb_desc.c (gnukStringSerial): Updated. + Documentation by Sphinx. * doc/Makefile: New. * doc/note: Old notes are moved here. diff --git a/README b/README index b80aaaa..f0f649d 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - An Implementation of USB Cryptographic Token for GnuPG Version 1.0 - 2012-08-XX + 2012-07-21 Niibe Yutaka Free Software Initiative of Japan @@ -338,7 +338,7 @@ Recently, there is "gcc-arm-embedded" project. See: https://launchpad.net/gcc-arm-embedded/ It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd -need "-O3 -s" instead of "-O2" and it will be slightly better. +need "-O3 -Os" instead of "-O2" and it will be slightly better. Change directory to `src': diff --git a/src/usb_desc.c b/src/usb_desc.c index ed90d99..3d37dbd 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -258,11 +258,11 @@ static const uint8_t gnukStringLangID[] = { #include "usb-strings.c.inc" const uint8_t gnukStringSerial[] = { - 18*2+2, /* bLength */ + 17*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ - /* FSIJ-0.19 */ + /* FSIJ-1.0 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '0', 0, '.', 0, '2', 0, '1', 0, /* Version number of Gnuk */ + '1', 0, '.', 0, '0', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From b49390de7a4e05ec16e5ba0b858fd891036936eb Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 26 Jul 2012 18:53:59 +0900 Subject: [PATCH 255/300] add an entry in NEWS --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index dbb278d..9990f58 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 1.0 + + Released 2012-07-21, by NIIBE Yutaka + +This is bug fixes only release. + + * Major changes in Gnuk 0.21 Released 2012-07-06, by NIIBE Yutaka From 61ec9b7ed71e9516f579c90e588403d3cc0a1d22 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Aug 2012 17:11:42 +0900 Subject: [PATCH 256/300] add doc --- doc/development.rst | 24 +++++++++++++++++++++++- doc/intro.rst | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/doc/development.rst b/doc/development.rst index df3d30f..cb0c259 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -5,7 +5,29 @@ Development Environment Hardware -------- -JTAG debugger or SWD debugger is required. +For development, it is highly recommended to have JTAG debugger or SWD +debugger. + +For boards with DFU (Device Firmware Upgrade) feature, such as DfuSe, +it is possible to develop with that. But it should be considered +*experimental* environment, and it should not be used for usual +purpose. That's because it is basically impossible for DfuSe +implementations to disable reading-out from flash ROM. It means +that your secret will be readily extracted by DfuSe. + +For JTAG debugger, Olimex JTAG-Tiny is good and supported well. For +SWD debugger, ST-Link/V2 would be good, and it is supported by +the tool of tool/stlinkv2.py. + + +OpenOCD +------- + +For JTAG debugger or SWD debugger, we can use OpenOCD. + +Note that ST-Link/V2 is *not* supported by OpenOCD 0.5.0. It will be +supported by version 0.6 or later, as current development version +supports it. GNU Toolchain diff --git a/doc/intro.rst b/doc/intro.rst index 63933b4..792018b 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -13,17 +13,41 @@ STM32F103 processor. Cryptographic token and feature of Gnuk --------------------------------------- -Cryptographic token is a store of private keys and it computes cryptographic functions on the device. +Cryptographic token is a store of private keys and it computes cryptographic +functions on the device. + +The idea is to separate important secrets to independent device, +from where nobody can extract them. Development Environment ----------------------- -See :doc:`development` for development environment for Gnuk. It builds on Free Software. +See :doc:`development` for development environment for Gnuk. +Gnuk is developed on the environment where there are only Free Software. -Prerequisites -------------- +Target boards for running Gnuk +------------------------------ + +Hardware requirement for Gnuk is the micro controller STM32F103. +In version 1.0, Gnuk supports following boards. + +* FST-01 (Flying Stone Tiny ZERO-ONE) + +* Olimex STM32-H103 + +* CQ STARM + +* STBee + +* STBee Mini + +* STM32 part of STM8S Discovery Kit + + +Host prerequisites for using Gnuk Token +--------------------------------------- * GNU Privacy Guard (GnuPG) @@ -36,8 +60,8 @@ Prerequisites * Web: scute, firefox -Usage ------ +Usages +------ * Sign with GnuPG * Decrypt with GnuPG From 7575dda42a7c690542fcc7882012bcf11b1ed282 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 2 Aug 2012 17:44:08 +0900 Subject: [PATCH 257/300] Add test for USB version string --- test/features/991_version_string.feature | 8 ++++++++ test/features/steps.py | 3 +++ test/gnuk.py | 3 +++ 3 files changed, 14 insertions(+) create mode 100644 test/features/991_version_string.feature diff --git a/test/features/991_version_string.feature b/test/features/991_version_string.feature new file mode 100644 index 0000000..9a10d4c --- /dev/null +++ b/test/features/991_version_string.feature @@ -0,0 +1,8 @@ +@usb +Feature: examine USB version string + In order to work as Gnuk Token + A token should support version string + + Scenario: USB version string + Given USB version string of the token + Then data should match: ([a-zA-Z0-9]*)-([.0-9]+)-[0-9A-F]+ diff --git a/test/features/steps.py b/test/features/steps.py index d995ccf..70e3046 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -108,6 +108,9 @@ def encrypt_on_host_public_key(): def decrypt(): scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext) +@Given("USB version string of the token") +def usb_version_string(): + scc.result = ftc.token.get_string(3) @When("requesting (.+): ([0-9a-fA-F]+)") def get_data(name, tag_str): diff --git a/test/gnuk.py b/test/gnuk.py index a334678..13a9320 100644 --- a/test/gnuk.py +++ b/test/gnuk.py @@ -77,6 +77,9 @@ class gnuk_token(object): self.__timeout = 10000 self.__seq = 0 + def get_string(self, num): + return self.__devhandle.getString(num, 512) + def increment_seq(self): self.__seq = (self.__seq + 1) & 0xff From eb0e913eee8642ced5d25a47263523ccc7237cb7 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 3 Aug 2012 10:53:04 +0900 Subject: [PATCH 258/300] Add doc --- doc/generating-2048-RSA-key.rst | 228 ++++++++++++++++++ doc/gnuk-keytocard-noremoval.rst | 177 ++++++++++++++ doc/gnuk-keytocard.rst | 183 ++++++++++++++ doc/gnuk-personalization.rst | 118 +++++++++ doc/gnuk-token-initial-configuration.rst | 34 +++ doc/images/gnuk-sticker.png | Bin 0 -> 21955 bytes doc/index.rst | 8 + doc/stop-scdaemon.rst | 37 +++ doc/udev-rules.rst | 48 ++++ ...using-gnuk-token-with-another-computer.rst | 173 +++++++++++++ 10 files changed, 1006 insertions(+) create mode 100644 doc/generating-2048-RSA-key.rst create mode 100644 doc/gnuk-keytocard-noremoval.rst create mode 100644 doc/gnuk-keytocard.rst create mode 100644 doc/gnuk-personalization.rst create mode 100644 doc/gnuk-token-initial-configuration.rst create mode 100644 doc/images/gnuk-sticker.png create mode 100644 doc/stop-scdaemon.rst create mode 100644 doc/udev-rules.rst create mode 100644 doc/using-gnuk-token-with-another-computer.rst diff --git a/doc/generating-2048-RSA-key.rst b/doc/generating-2048-RSA-key.rst new file mode 100644 index 0000000..81633f4 --- /dev/null +++ b/doc/generating-2048-RSA-key.rst @@ -0,0 +1,228 @@ +============================ +Generating 2048-bit RSA keys +============================ + +This document describes how I generate 2048-bit RSA keys. + +.. BREAK + +Here is the log to generate signature key and encryption subkey. + +I invoke GnuPG with ``--gen-key`` option. :: + + $ gpg --gen-key + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + +and GnuPG asks kind of key. Select ``RSA and RSA``. :: + + Please select what kind of key you want: + (1) RSA and RSA (default) + (2) DSA and Elgamal + (3) DSA (sign only) + (4) RSA (sign only) + Your selection? 1 + RSA keys may be between 1024 and 4096 bits long. + +and select 2048-bit (as Gnuk Token only suppurt this). :: + + What keysize do you want? (2048) + Requested keysize is 2048 bits + +and select expiration of the key. :: + + Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years + Key is valid for? (0) 0 + Key does not expire at all + +Confirm key types, bitsize and expiration. :: + + Is this correct? (y/N) y + +Then enter user ID. :: + + You need a user ID to identify your key; the software constructs the user ID + from the Real Name, Comment and Email Address in this form: + "Heinrich Heine (Der Dichter) " + + Real name: Niibe Yutaka + Email address: gniibe@fsij.org + Comment: + You selected this USER-ID: + "Niibe Yutaka " + + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o + +and enter passphrase for this **key on PC**. :: + + You need a Passphrase to protect your secret key. + + +Then, GnuPG generate keys. It takes some time. :: + + We need to generate a lot of random bytes. It is a good idea to perform + some other action (type on the keyboard, move the mouse, utilize the + disks) during the prime generation; this gives the random number + generator a better chance to gain enough entropy. + ...+++++ + +++++ + We need to generate a lot of random bytes. It is a good idea to perform + some other action (type on the keyboard, move the mouse, utilize the + disks) during the prime generation; this gives the random number + generator a better chance to gain enough entropy. + ..+++++ + + Not enough random bytes available. Please do some other work to give + the OS a chance to collect more entropy! (Need 15 more bytes) + ...+++++ + gpg: key 28C0CD7C marked as ultimately trusted + public and secret key created and signed. + + gpg: checking the trustdb + gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model + gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u + pub 2048R/28C0CD7C 2011-05-24 + Key fingerprint = 0B4D C763 D57B ADBB 1870 A978 BDEE 4A35 28C0 CD7C + uid Niibe Yutaka + sub 2048R/F01E19B7 2011-05-24 + $ + +Done. + +Then, I create authentication subkey. Authentication subkey is not that common, but very useful (say, for SSH authentication). As it is not that common, we need ``--expert`` option for GnuPG. :: + + $ gpg --expert --edit-key 28C0CD7C + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Secret key is available. + + pub 2048R/28C0CD7C created: 2011-05-24 expires: never usage: SC + trust: ultimate validity: ultimate + sub 2048R/F01E19B7 created: 2011-05-24 expires: never usage: E + [ultimate] (1). Niibe Yutaka + + gpg> + +Here, I enter ``addkey`` command. Then, I enter the passphrase of **key on PC**, I specified above. :: + + gpg> addkey + Key is protected. + + You need a passphrase to unlock the secret key for + user: "Niibe Yutaka " + 2048-bit RSA key, ID 28C0CD7C, created 2011-05-24 + + gpg: gpg-agent is not available in this session + +GnuPG askes kind of key. I select ``RSA (set your own capabilities)``. :: + + Please select what kind of key you want: + (3) DSA (sign only) + (4) RSA (sign only) + (5) Elgamal (encrypt only) + (6) RSA (encrypt only) + (7) DSA (set your own capabilities) + (8) RSA (set your own capabilities) + Your selection? 8 + +And select ``Authenticate`` for the capabilities for this key. Initially, it's ``Sign`` and ``Encrypt``. I need to deselect ``Sign`` and ``Encryp``, and select ``Authenticate``. To do that, I enter ``s``, ``a``, and ``e``. :: + + Possible actions for a RSA key: Sign Encrypt Authenticate + Current allowed actions: Sign Encrypt + + (S) Toggle the sign capability + (E) Toggle the encrypt capability + (A) Toggle the authenticate capability + (Q) Finished + + Your selection? s + + Possible actions for a RSA key: Sign Encrypt Authenticate + Current allowed actions: Encrypt + + (S) Toggle the sign capability + (E) Toggle the encrypt capability + (A) Toggle the authenticate capability + (Q) Finished + + Your selection? a + + Possible actions for a RSA key: Sign Encrypt Authenticate + Current allowed actions: Encrypt Authenticate + + (S) Toggle the sign capability + (E) Toggle the encrypt capability + (A) Toggle the authenticate capability + (Q) Finished + + Your selection? e + + Possible actions for a RSA key: Sign Encrypt Authenticate + Current allowed actions: Authenticate + + (S) Toggle the sign capability + (E) Toggle the encrypt capability + (A) Toggle the authenticate capability + (Q) Finished + +OK, I set the capability of ``Authenticate``. I enter ``q`` to finish setting capabilities. :: + + Your selection? q + +GnuPG asks bitsize and expiration, I enter 2048 for bitsize and no expiration. Then, I confirm that I really create the key. :: + + RSA keys may be between 1024 and 4096 bits long. + What keysize do you want? (2048) + Requested keysize is 2048 bits + Please specify how long the key should be valid. + 0 = key does not expire + = key expires in n days + w = key expires in n weeks + m = key expires in n months + y = key expires in n years + Key is valid for? (0) 0 + Key does not expire at all + Is this correct? (y/N) y + Really create? (y/N) y + +Then, GnuPG generate the key. :: + + We need to generate a lot of random bytes. It is a good idea to perform + some other action (type on the keyboard, move the mouse, utilize the + disks) during the prime generation; this gives the random number + generator a better chance to gain enough entropy. + .......+++++ + +++++ + + pub 2048R/28C0CD7C created: 2011-05-24 expires: never usage: SC + trust: ultimate validity: ultimate + sub 2048R/F01E19B7 created: 2011-05-24 expires: never usage: E + sub 2048R/B8929606 created: 2011-05-24 expires: never usage: A + [ultimate] (1). Niibe Yutaka + + gpg> + +I save the key. :: + + gpg> save + $ + +Now, we have three keys (one primary key for signature and certification, subkey for encryption, and another subkey for authentication). + + +Publishing public key +===================== + +I make a file for my public key by ``--export`` option of GnuPG. :: + + $ gpg --armor --output gniibe.asc --export 4CA7BABE + +and put it at: http://www.gniibe.org/gniibe.asc diff --git a/doc/gnuk-keytocard-noremoval.rst b/doc/gnuk-keytocard-noremoval.rst new file mode 100644 index 0000000..0e3abb9 --- /dev/null +++ b/doc/gnuk-keytocard-noremoval.rst @@ -0,0 +1,177 @@ +============================================= +Key import from PC to Gnuk Token (no removal) +============================================= + +This document describes how I put my **keys on PC** to the Token without removing keys from PC. + +The difference is just not-to-save changes after key imports. + +.. BREAK + +After personalization, I put my keys into the Token. + +Here is the log. + +I invoke GnuPG with my key (4ca7babe) and with ``--homedir`` option to specify the directory which contains my secret keys. :: + + $ gpg --homedir=/home/gniibe/tmp/gnuk-testing-dir --edit-key 4ca7babe + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Secret key is available. + + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: ultimate validity: ultimate + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ultimate] (1). NIIBE Yutaka + + +Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``. +To enable ``keytocard`` command, I type ``toggle`` command. :: + + gpg> toggle + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + ssb 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +Firstly, I import my primary key into Gnuk Token. +I type ``keytocard`` command, answer ``y`` to confirm keyimport, +and type ``1`` to say it's signature key. :: + + gpg> keytocard + Really move the primary key? (y/N) y + gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00' + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (1) Signature key + (3) Authentication key + Your selection? 1 + +Then, GnuPG asks two passwords. One is the passphrase of **keys on PC** and another is the password of **Gnuk Token**. Note that the password of the token and the password of the keys on PC are different things, although they can be same. + +I enter these passwords. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 4CA7BABE, created 2010-10-15 + + gpg: writing new key + gpg: 3 Admin PIN attempts remaining before card is permanently locked + + Please enter the Admin PIN + Enter Admin PIN: + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +The primary key is now on the Token and GnuPG says its card-no (F517 00000001) , where F517 is the vendor ID of FSIJ. + +Secondly, I import my subkey of encryption. I select key number '1'. :: + + gpg> key 1 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +You can see that the subkey is marked by '*'. +I type ``keytocard`` command to import this subkey to Gnuk Token. I select ``2`` as it's encryption key. :: + + gpg> keytocard + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (2) Encryption key + Your selection? 2 + +Then, GnuPG asks the passphrase of **keys on PC** again. I enter. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 084239CF, created 2010-10-15 + + gpg: writing new key + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +The sub key is now on the Token and GnuPG says its card-no for it. + +I type ``key 1`` to deselect key number '1'. :: + + gpg> key 1 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +Thirdly, I select sub key of suthentication which has key number '2'. :: + + gpg> key 2 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +You can see that the subkey number '2' is marked by '*'. +I type ``keytocard`` command to import this subkey to Gnuk Token. I select ``3`` as it's authentication key. :: + + gpg> keytocard + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (3) Authentication key + Your selection? 3 + +Then, GnuPG asks the passphrase of **keys on PC** again. I enter. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 5BB065DC, created 2010-10-22 + + gpg: writing new key + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/5BB065DC created: 2010-10-22 expires: never + card-no: F517 00000001 + (1) NIIBE Yutaka + +The sub key is now on the Token and GnuPG says its card-no for it. + +Lastly, I quit GnuPG. Note that I **don't** save changes. :: + + gpg> quit + Save changes? (y/N) n + Quit without saving? (y/N) y + $ + +All keys are imported to Gnuk Token now. diff --git a/doc/gnuk-keytocard.rst b/doc/gnuk-keytocard.rst new file mode 100644 index 0000000..e223c16 --- /dev/null +++ b/doc/gnuk-keytocard.rst @@ -0,0 +1,183 @@ +================================ +Key import from PC to Gnuk Token +================================ + +This document describes how I put my **keys on PC** to the Token, and remove keys from PC. + +Note that there is **no ways** to export keys from the Token, so please be careful. + +.. BREAK + +If you want to import same keys to multiple Tokens, please copy ``.gnupg`` directory before. In my case, I do something like following: :: + + $ cp -a .gnupg tmp/gnuk-testing-dir + +See `another document`_ to import keys to the Token from copied directory. + +.. _another document: gnuk-keytocard-noremoval + +After personalization, I put my keys into the Token. + +Here is the log. + +I invoke GnuPG with my key (4ca7babe). :: + + $ gpg --edit-key 4ca7babe + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Secret key is available. + + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: ultimate validity: ultimate + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ultimate] (1). NIIBE Yutaka + + +Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``. +To enable ``keytocard`` command, I type ``toggle`` command. :: + + gpg> toggle + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + ssb 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +Firstly, I import my primary key into Gnuk Token. +I type ``keytocard`` command, answer ``y`` to confirm keyimport, +and type ``1`` to say it's signature key. :: + + gpg> keytocard + Really move the primary key? (y/N) y + gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00' + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (1) Signature key + (3) Authentication key + Your selection? 1 + +Then, GnuPG asks two passwords. One is the passphrase of **keys on PC** and another is the password of **Gnuk Token**. Note that the password of the token and the password of the keys on PC are different things, although they can be same. + +I enter these passwords. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 4CA7BABE, created 2010-10-15 + + gpg: writing new key + gpg: 3 Admin PIN attempts remaining before card is permanently locked + + Please enter the Admin PIN + Enter Admin PIN: + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +The primary key is now on the Token and GnuPG says its card-no (F517 00000001) , where F517 is the vendor ID of FSIJ. + +Secondly, I import my subkey of encryption. I select key number '1'. :: + + gpg> key 1 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/084239CF created: 2010-10-15 expires: never + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +You can see that the subkey is marked by '*'. +I type ``keytocard`` command to import this subkey to Gnuk Token. I select ``2`` as it's encryption key. :: + + gpg> keytocard + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (2) Encryption key + Your selection? 2 + +Then, GnuPG asks the passphrase of **keys on PC** again. I enter. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 084239CF, created 2010-10-15 + + gpg: writing new key + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +The sub key is now on the Token and GnuPG says its card-no for it. + +I type ``key 1`` to deselect key number '1'. :: + + gpg> key 1 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +Thirdly, I select sub key of suthentication which has key number '2'. :: + + gpg> key 2 + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/5BB065DC created: 2010-10-22 expires: never + (1) NIIBE Yutaka + +You can see that the subkey number '2' is marked by '*'. +I type ``keytocard`` command to import this subkey to Gnuk Token. I select ``3`` as it's authentication key. :: + + gpg> keytocard + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + + Please select where to store the key: + (3) Authentication key + Your selection? 3 + +Then, GnuPG asks the passphrase of **keys on PC** again. I enter. :: + + You need a passphrase to unlock the secret key for + user: "NIIBE Yutaka " + 2048-bit RSA key, ID 5BB065DC, created 2010-10-22 + + gpg: writing new key + + sec 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb* 2048R/5BB065DC created: 2010-10-22 expires: never + card-no: F517 00000001 + (1) NIIBE Yutaka + +The sub key is now on the Token and GnuPG says its card-no for it. + +Lastly, I save changes of **keys on PC** and quit GnuPG. :: + + gpg> save + $ + +All secret keys are imported to Gnuk Token now. On PC, only references (card-no) to the Token remain. diff --git a/doc/gnuk-personalization.rst b/doc/gnuk-personalization.rst new file mode 100644 index 0000000..7aab551 --- /dev/null +++ b/doc/gnuk-personalization.rst @@ -0,0 +1,118 @@ +============================= +Personalization of Gnuk Token +============================= + + +Personalize your Gnuk Token +=========================== + +Invoke GnuPG with the option ``--card-edit``. :: + + $ gpg --card-edit + gpg: detected reader `FSIJ Gnuk (0.12-34006E06) 00 00' + Application ID ...: D276000124010200F517000000010000 + Version ..........: 2.0 + Manufacturer .....: FSIJ + Serial number ....: 00000001 + Name of cardholder: [not set] + Language prefs ...: [not set] + Sex ..............: unspecified + URL of public key : [not set] + Login data .......: [not set] + Signature PIN ....: forced + Key attributes ...: 2048R 2048R 2048R + Max. PIN lengths .: 127 127 127 + PIN retry counter : 3 3 3 + Signature counter : 0 + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + General key info..: [none] + +It shows the status of the card (as same as the output of ``gpg --card-status``). It shows token's name and its USB serial string (0.12-34006E06) from PC/SC-lite. + +Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``. + +Firstly, I change PIN of card user from factory setting (of "123456"). Note that, only changing PIN of user enables "admin less mode" of Gnuk. Admin password will become same one of user's. :: + + gpg/card> passwd + gpg: OpenPGP card no. D276000124010200F517000000010000 detected + + Please enter the PIN + Enter PIN: 123456 + + New PIN + Enter New PIN: + + New PIN + Repeat this PIN: + PIN changed. + +Secondly, enabling admin command, I put name of mine. Note that I input user's PIN (which I set above) here, because it is "admin less mode". :: + + gpg/card> admin + Admin commands are allowed + + gpg/card> name + Cardholder's surname: Niibe + Cardholder's given name: Yutaka + gpg: 3 Admin PIN attempts remaining before card is permanently locked + + Please enter the Admin PIN + Enter Admin PIN: + +Thirdly, I put some other informations, such as language, sex, login, and URL. URL specifies the place where I put my public keys. :: + + gpg/card> lang + Language preferences: ja + + gpg/card> sex + Sex ((M)ale, (F)emale or space): m + + gpg/card> url + URL to retrieve public key: http://www.gniibe.org/gniibe.asc + + gpg/card> login + Login data (account name): gniibe + +Since I don't force PIN input everytime, toggle it to non-force-pin-for-signature. :: + + gpg/card> forcesig + +Lastly, I setup reset code. This is optional. :: + + gpg/card> passwd + gpg: OpenPGP card no. D276000124010200F517000000010000 detected + + 1 - change PIN + 2 - unblock PIN + 3 - change Admin PIN + 4 - set the Reset Code + Q - quit + + Your selection? 4 + gpg: 3 Admin PIN attempts remaining before card is permanently locked + + Please enter the Admin PIN + Enter Admin PIN: + + New Reset Code + Enter New PIN: + + New Reset Code + Repeat this PIN: + Reset Code set. + + 1 - change PIN + 2 - unblock PIN + 3 - change Admin PIN + 4 - set the Reset Code + Q - quit + + Your selection? q + +Then, I quit. :: + + gpg/card> quit + +That's all. diff --git a/doc/gnuk-token-initial-configuration.rst b/doc/gnuk-token-initial-configuration.rst new file mode 100644 index 0000000..d2a5c9a --- /dev/null +++ b/doc/gnuk-token-initial-configuration.rst @@ -0,0 +1,34 @@ +=================================== +Initial Configuration of Gnuk Token +=================================== + +Conditions +========== + +I assume you are using GNU/Linux. + + +Preparation +=========== + +We need to kill ``scdaemon`` before configuring Gnuk Token. :: + + $ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye + + +Serial Number (optional) +======================== + +In the file ``GNUK_SERIAL_NUMBER``, each line has email and 6-byte serial number. + +The tool ``../tool/gnuk_put_binary.py`` examines environment variable of ``EMAIL``, and writes serial number to Gnuk Token. :: + + $ ../tool/gnuk_put_binary.py -s ../GNUK_SERIAL_NUMBER + Writing serial number + Token: FSIJ Gnuk (0.12-38FF6A06) 00 00 + ATR: 3B DA 11 FF 81 B1 FE 55 1F 03 00 31 84 73 80 01 40 00 90 00 24 + + +The tool ``../tool/gnuk_put_binary.py`` is for PC/SC Lite. Use +``../tool/gnuk_put_binary_libusb.py`` instead, if you don't use +PC/SC Lite but use libusb directly. diff --git a/doc/images/gnuk-sticker.png b/doc/images/gnuk-sticker.png new file mode 100644 index 0000000000000000000000000000000000000000..511c783fd1e6f68f409f5f21441777645dbafd96 GIT binary patch literal 21955 zcmeAS@N?(olHy`uVBq!ia0y~yVEDnnz>q1x#=yYfUTw6Ffq{W7$=luKKNxUEe80oM zz`$AH5n0T@z~BMKZYQ(tK!Rljj_EM{3=ultCNnUERC~HOhE&{oJGV4Og@w-TDz-9W5D?hW!^6$ZooreF;ZJ<<+1uOOyYbB% z&&kJn7)?z2WUb5B{X2dz>jA{5q=1l;7Z>)`Hq5&9>+9`po_R8B*v=g~bm&mf@-5lR z*R5L^`1`R*{=H49r>7k_Ik{iXw&us%|Hu2@-n)B}v!g?yX^oYb-kmL(kKGb(80hQk zuV1x&wq5Oo1qYiO)6c)VySu#q=bXcer}tK$J^S@*^<~3`7a0lX=1iJ2Y0|Bj__(;ZxU=uYuO3+1#=H6^PZK2I?QU$( ze|yXRKg+qf%3RA=G|hI}KHn(y07H5CgMWWlhp&$lt^IFTTT)_T((vZZrcIlSJn!=! zIJGKtb=cYnc?)iCZfTzViG~Go1#f#UkU$6h`W5$G;Yu4=9v&ZJZQ!j6C@9TAQ*!k;zefhb0$@^>D|D>CI zcz#~qrs9vpj{5({dh7pB{gNT2?>~=)g@u)Iy8e8d%6BpWfgqsxGH~OD4I3C-mZx1y z0RskC*VNS1r>mx4J@|Oy_c<$9HZ|?pvt<3mhs&=X*u3e|<;#~FD?hvS&$E-AVYD=U z|NT1VoSZjr-@Z|?-F2*c;>4LVS88sk`1s@FzI_h&_g%Zz%+6d_CvEoT4(F8V<~Vc*8V!VHjbngFWRUu$enDqT!w|L`?8z)X&3OaCRO=YpN@<(4Io%rOOoW#T|u8fR~ zOifM3!otA7pFa<5%k`dqZx834eQ)2_|F<(pKDH_}csY}w-``(fU#Y$f+`M6fiOa36 zmoF%kx?9L({bOS&Ee+~d(Rgur`HzZ={o?ZfKR!O*f8f#4$H#i*&u2U+*_m?k++6E2 z1|y?Qn>KA)B!B%*OkkiN-;F(%YR{^F-umjh`1*mzj~6daPHN~BuKp@z%ywf-=0m6Y zdZisNeb#IdDJYgUS`usR+5heN!eDjr>0-JwO6}&K*Vkora&B(c)@oqoKGt`4r*OpH zTgTHsCM{UgGes^XF)?xBg__rk7Bw|BF{Pb+EGjB0YIs{xYSye-vzUUwAXHvoU0qvS zoBP9e`?5DT4At(wd2+J$_qVsqGBQ`LT)EoV)O6?0ojb3NyPsFp_C7azN=Qh^>^<*y zExY*Z!1;M!KU-ocXcD}xTe%{}&duIMR)ZKlO-_wuJqB!mTzVi1VFMt2{HT>AtgNF_sQqr=rTJqu4 zQt$Qg`>R6tp4_cfvFFjFM@b93#cOMsnH8*m|9-EWnwpuZC%$5Z!m^)>7Ikr%aqVTh zkg!rzdzoMC28J6O65ri1PH$MUWQWDW1x=5Vp5-$$2M33SIs^y1ySuwz3jg>yAt50t zDaGa8>ZU{2|1UNUv74Xq?9!zJo6{Q`j~+enB>$R(^6B8FMyqf(a)Y0_6UMvp}5AW)0CrV2?R@z$c-m+y)&z{RtLcDRz`nsx1 zUoG>OH%fWr@?d^FpKR5CISm~h4FRz`S6s9+R=vG+^z7MdVIbFB+Lk+AZ`!o@dN=u^ z#9-le=9(WLp7m}qF-Sf(L2+{$V`t~ajgNlph=_=&le@R?>Bp|_#tsg<{fn9+?ds-C zn>H)zYu&SFW@ct)4gmo*H8C;@>h710wM@Ts>B#q3(JNc0&zw0c>gLZC@2!;?nVql+^I4NUlFmQI++>Pf^htJHfmrHAPUe)MvMl z(F^zDnlNcmAEVy(MNAW>hlfs`$hfQIr+OL05@@qT)!iASE9mwC`D`Q!0R`4bw;law_hNh-PixwsQjc4cP_I~W_fBwXY z6C518s;$v2AHV+n``!K@L)p8Styx#KKKAD)FJ7}|1&2-TthsZihyVSSduzpt6|2Jj z*2l-!|K}EG5TAaqnVo;#->>F3G`^&sR`Z=@&dhkIwl+5Q z&p%aOW6_uV24@rKL6W^ej?pXV%bu{i?{KVb-jP6Q_tQSeKWi zwByQ!j9VcEbMuz3S+oB9Lx!TFtSlKm1^x947A#;Wd2wM~?Eboj=H}L;3mgy3G~QkA z{ir%5C@65^Mu1>^VGt{(fKRtnPQ^|BuLs2r0cQi#(eXR!4P3 z6@`ZI@IHO|^hv{$Cy$a2ewX;V`}NC{r|QnT{9l}DAZ5X;bz^`1-(QQ}J!fxyrFAc0 za%E~G>(i%8mwt^@d~<87u=>BB>@V)#zFGOmr9rA^>eR1aEMy#_qT=QqX3UV4udGZG znm$#vt@vR8PgGw+iywncT%~0@vxul5b8+U%Ra))LA|f^aVgeagtX#SBpIHW8DpxVgJu1YFnl zbzhzPYt+Q6grcRys`Q)inrzRq3! zpPl_$FRP=Y!^|tgLL~y4bs*n(5sRHnt@*yB03o zxpSxGXG`5XN;-RFWkN!yPHj|n7ZTE{_ForY|Kh^I=2G*0H#c8j6S;ZWtN-3MT(#%t z-LJpDtv4h@cx!f##w^qR@R*oD#ydL-|NVJ-`oM<7$!fi_r~mvv+-{zK=um@oxnAt9 zTImNxsVOEV47|L#xx&Iq7DmR6lO{cSbjHUa{Q3chP|<>NdE2TN7xKM7?%c&E`|2Iv z9P90spJy63w7Xwk7QD=0S%H;y^0fH#mzONwjNde0#fJezJ+Jq@>W7^aKYT@z&NO)2GbgdGT6Wdi82%X7)Zw z6`PpY zwD}XA+w<=J`W~NfYRbOa-(Q*E-Q8XJ`I+y>{>6(gFY%nLcHr*rCAlj%JkwEiy=H3S zp(yU^x+v)8jTI|2w3zhco;-W@yuSL5qO+RM41>m(o6PF=%#L0kw`jZW(#H{-k6kZ6 zFPCtHBR@a?{i^NLXYkMYr6y;yqw@1n?oW}Wv&=;WAB7yUtS;4C4CpY$`u0Em*yJeSSWF z$*U)?e(hy%o-}###EG-Ge*9V&`}#Gvh1It=FCQ?Jyt%R1eS6-4soLuP_jaq_E7xCj z-ouS;NBR3>y%Pi;Y`_2S&*m*#e(muS6B9eRc)@}tOO||j-1q)@`Qu|>UpMrh2X_a) zzwcH%!OQCzcIoWwi4z3{LucFc+*XGlEzwJIz8 z)r%L89zA0E@q2%Tpb%4!un>-a?BQpFCAn4-a85&$p}CkS}kLcjwX3 z%gY!U8O8PE_Vd;Jn=>UO$cbxR$0vsncNdq87tQP`&%^~7WbF2ozHVk;bl!k9Fj)EY z`=32KVlrPIa!R1=+JZK)YKyyeziACJRcVA7po5m zUcNBVH!NtYV+vD~sHO*a?-|>s#()-WVj^$6Erlxjvr5q~%ZKi!7GD3=3RP_D5)>g)# zAStP+C8a9cNv;^3XfSPm-OV9)5l~+pmVD-}`*{RMF{&6;%)XsBwEx z=Wn?3^{yA9qB4C`L=HU7%F4=Qtf_N!OjJ}*P0hTy=H~X>!Mt-;uUofv?b5APrMI`m z?kag1w7q#%k8`_OzFkp^%fn8s885|u?9~tQ>^#EeH^U(R-j$UO>*Ji;xn@myEtS<| zXkcKPdvlV>M-5HJdwVMX*=TTV*q(oTTe7>5so&w7FXl0PE|@ZX@_q?N-)Sb2eUa*) zeX^YDzrOnUdAWb%kt1i$TnSkay}j=5GC$SIoA*DrUKe9!RaF%gT~M5EzP;{m!}s^` zdv}#`d-(tV6M4nNEQ?EAH7m~1(R1aBjw41q(%&Ah>uzmb`Yk1eN8YYLK|wt|J3F2I z$+LeypRWpS*s`UuaiU;A;KT_NW_YmFR#+T(YL=Olz>t!9cE-b}tRmv^d#hdw9eB*j zZePhXW%^__HCEQ+{qlA^1s0N$GiNqTnF8w62Lw9Cw5qCpf6va!`19w!eY?vTFI{@| zN=nKh^5*O7>*JX#D{pVlzr!ISI`Q%8lQU;d47#AwVQF9g{M_2;#-^s=<$bcuT3U}D zKYrYJ=~6>O{eRXaORiisHEsO!r}p>1U)&E0IvUQNy}L2_vYJEKwF?)nOsRr~CV+YU(|FsHmu@DAeI}{>-0Gu2WtVIPNnSo-}RRG(COwgJFMv zGoL%h%+@0lS%2Nx&}`d=4V#&NeVuKP_^;-{q1M&m=jSjwIp5z?`EQQk0h8(pYP)N9 zFHtLYJIppCi%+eJX5CZsrvd!H6Tt- z`140)1^xHWu5H&>(7(UDf4B94hXV4&o+p2Q&%e*a#r5{KwH4FRql${>=P|anK0i0t zid97H-{c7pP$F5s#;iRXxOl3O{?qYXJ=ZRd~;u3y1JTCPT$7HL_|Zk z_Sct-%4s%>g5FD6h&s6U<=n4(#?$#tZ0km=t9x3{iq+U%SlGO|cyro;D=WRH<=pu2 z_?W&{%(^XGdUz6&l2TLi`9YOX%|9NSnu_o5rfRFansb`f#AM5sFJEUaFn#rTndcaF`e{>wLc`P?i+1fgusXb7 z-oAoi%9N0~U)1~9^wgIx2#De7kuuGlwOn2L%&|k4CTMC_{`&GU*&%LU@bY!Bjhi+t zS<=GN(D`lRI?~VD~9UTJ&CrmFddUaEH#R?B!Ur)xA)RQhw5~~`E zo0^S{E?xdvV`}Q_>w8xI`_W4Y%;wwE&fdA(_~gltion_jTRzQN;E{3Z$O#WOwi`P> z{`eTYoFO!{v^4jvy!pRfN>)}je{LEpSpIx`+&urp;lMygIe)%(!MRyMD}qNVY=54FrRew}|uXVF4XBWWRH$%_k%-JhR(V*F5ot&nBMv}x=ZC(0M!I1aPxplSG(b1o_YivEs_~}r1NJx;DHuJBq(w0SsT7K>`h$^!=+K~1`EcF3X7<^$nJ+J2AGNh~^^te8 zPuSE}eSg<0ePD0(bbWRfhM6;0uH@os=;4{3o#dn?%o)Zdv}U5;^-R_6kCGZrPo3J^ z&D_(YqdRpeyM5;}42+=(B58XII!TmF28p+j6;*)|Qkx98@@ z#)gJA9&XRSZ&&1UDg5As>F#PVb#=eL+t+Z+u`d7jr(68Y^U~hd)}1^1_!1HlGFGhP zv#I#-z%k^?_S=zBQ4ud*Fih8v-}U5i@ZZAw`)YriSxVm6QTX{;^!5gRdAph)eXx6JT(0cXwaD z^y;5IVq#A!XIqz_lMxqRkbJyP_UxH`cmG{jc(`5Omg(F)+u~*FV%U-hZ?Q$@q}@1LF?ZfD+G%`a?;?L(C-tL8E-qe(8mr z{qr;VSVa|+y#2oF@Vorm7d1t++}f6FarcB?%!lvwU%75<%e}qLy1e1cnKe3vS)c!B zq@;Qt-G6<3{JxlNYhJy5QT*iDwcX#>#X1xj3C=NXU1mSey8Kzsbny#|T)V}7{R++h z|L^bb@0ywiE-XCU_Vef89lsM35)u}y^YPJ^Oo#LH^z?3TXWqH9va;0j;-u-* zCr_Tp$i&3Nly*K%&Fm0pP~k&`L%*DDb>97RYp#oa+4KD!E9=?0-nWFjJq?>KojiH7 z^0t|Rwzl@_4IAE_TfJ)4A|-u(7B)7vb91>hG)|m8eS*P%o=v5YFtg9BCr?ZNRNS50 zzi9paC7rXR1Oy6xe|vND>i5V0ZZ6n*LG>Dc&6yc5FCXt!eyfu?uRK*lLqqdpMZ?~` zix*Fx{3I_TG$n1>(%OGKKYp%_-JLByVdl&k8EI@9T3Q+}UQd=>y~QN*)CmSIE-o%3 zqlP_u_UzeWvQkA|*SD@9MlW)?x29&=+`6*iHDE%{{P3V6TdI%=+o1@{sqBaUKwxq zy`MaB;>^f^fa-&~HS@2nSO30p*E6&H`}?Y=Px|!uJ^S8$;p^k}{`#`=9jp1$9W#z= z>#{Cdq@;ZL(yDuUAfUYX9jke(-SjJy96i0f{LYcBe={_TQV*`s}4M-rInRsWOO9Nr+J|iQ%Hfl?XJ|* z|Nb`g_*7PYe%7#T*|KF#ObeDSU8<_?KJC+|`|Gl^va&8Mog=eg)v8rm8aGxth>P55 zdcCE(cZx{+;x#;b>T3VjRazE2IWbLlwwdRzcQxHzUAwGSuJ}^BX6@UzU%z-TiVIKv zC7)htxv@egW=F=wR_+5ElaKe?*GBz+{38$)4;@jAfiiJ>Dn2UN$#HP)D%UsqRQ+6C z?Zz)B&=i2{)8q5oXH~3ra$H!qF8aqmEzPUvE2mD`x34ZT@>cyv_xaoF<}Yt+IENgKe02}z}4vr50>!Mzu~W?S0&D|ef|3NYwi^*PMq47!I+Vek#XXb5z|br z3`a&iofA)=oTzK^E-fuBjg0){G-2Y;Fy`e=zoQ-XRF^JbXlb{vcDvOx&$|3k%aZqE z&6_rLd6hEl*)rwFzS~B)6T1{SUH1RJy}iBt{?6d7`m=v|UA=PUN?nRn#`}AFtGDNz{LyiHTkh>|?mirA z*REYV+az&XXkyl_Ei0#8>;HVS?A4W(lXqG!Sh{qjX2zlGmo8lj3St5c#hpF-`rjTt zK0ZF**-UM1M^YUNOG^tkZd_TH6de5Gqo_#TnU*aJl{e<49NLm`aa-={umio)&(Ht= zYd&G}?LKl9E|Q&kOd6osr@D_?E$^_sgq?pPxQyICA91jTsUL zE=^+jxMFp7me;1F*pQHlAKl^(5jQ?RFD!gw>^OhwPRoI@|Bv3j?w|Jhiwg5o zPfyd|U-I&`1Z$v#VbYHeWp5j7tIOWYSqc>t6%}P&>-l)}l7jZHzo$+L&fmIj-MV#M zTo)EP|NgdY*?|Veckjx|TqgH+F%=aR743VTB-G}|vTAX1~T}WWb1I?{w zt$OiX*6PaP#ktX&wrpolJ3r6z^39nu8NR=CX0e)UVUoFM`SN9Kd+Pn0zPlVfoP1(} zS#Cq!-(O!hZ)KgPAHS`~Ph%MOEEhwJIy?)2AN&?aLk)l&haVeW>;G^W8fq ze(zkc$oc&3)zfFs?&S>>5D{gxwY9bVRD1o+9%eQki3_VlH>8|=baZcZeRW)D=%t*@ z3kw>Vqqnnlb$554K6S)=ZFH1b_OjKdZPv@lJ^4M?IQ`q3dA2j}U#{=1THhKcs~zSu zb5nt0!Mi(+%qFL%9cBbgXaoc?U0Y{c5im(A)z8n(ElaE5%ZoPNeft^~CQer4<9ouY zqU#%X;mYx|PmP#n{o1rrK~G=(>N#(3&%+lUJ$m%$Q;`sFRG3>$%F?AOQajf4=y-cK zf+n_qRc2~h`c+yke#xPq`C<0Nz|Co$od@3Be0^=XJC;BH@UX7#jK%85cXxmI5V|_6?w*)#PVV(JEC2rZ`o)8FFKDb_ zzF{+G-mk#ND_)jfzg{Wz%A)Q|<>AAJ4^N)daB}kAJ$`cpY{eSgF2BFKJN^8Mz%wi} zS{)W&P<_TMp7!d>(eCBG%2Ri(=@Cz9=e6S>~Pg$9I;7mXNQzW252B)hk!7JbB7!mi1f?4J|FLqMc`29OB~Q=K1lw zXlclLamc$NvhJ6NXlNYYkz;NyEv=sK{!N`au_iOIq~y!jN}GgNSC)D&_h0|Nkd@`m z&d>k${%D##%jx-?=Jt65mpfH+WfIGxTnV>VD{$E4UD?clg@W6^RmwH zZkr?|w|)hOhp%ejw4x%F+!n5oETQF1)45V=Yiny$Qx{}jUgmrCipRYbyQ~s&a&p!z zI>b@5>fq&!Qb)(LPmK;LfLc^0T6?t^`D%1MPCT#K*U4G%_t(qI&(C?jvl9~+7kl=6 z^8S@8*DhjuadYwvhOb|EczJnV)yLG;vGdtfsr;+!7T1ruvReGW(@SQZ_H5Tb7qi#fJ+E-TUieL`=L7Kl=Lm`g&oZhLe+*`&bq_ec8oycUS4_YilGQH~m`w zYn!X+Kew%$4%=>64@Sef%5NRepVSad88KLttRowKF|?G*+&kby#tq zyryQFr*_WD)vH&ZKFyq#mXK_o{=LH8`Z>!61C zwQC3B>)+n7tg)CJe*ROf)EqXyz;IBB&*aws?c2NC;u>07IyyQm6?+~fd7gQ&c#)Iy z;lrLEd{Z404zY%<;GZ>Z-tM=BbPppcH zjg6;HY3P@~zkhja@vF&u_Plv>C&t0eEo|Es5ed_*TU-A9^*md`+xtuY{Nv+GF0||b zfr#kq@eesHEiElGGZUWq2u%qUHHlcUPw*;J;jb?9~U@aN}> ziiL#-rfA-~x7@EY?q+Wq=bIZFb7wDC5ANu2HIZ7w<~P%#@ZX=z%M8-e)zz}H3Z|xt z3)S@R+?q7iwWcyPH8r*AV7jU*XmpaH|M=sJsg;(UQqMj%=*RD?(bQ34mD#kpv7@7- z<4cJGNR_?(i8E);=x8N1U4QZK%a0Pz^V$+i)N~H9vf6&Wc|F?Gv(Tcg?ZD^fj*jK; zuKce(b5@mUPyYRfhtHmEp*`9{RY@7Wg@xpu!_%KcZP?q}+m z8GW*i_5UpE>rROzJU+%N-NwV%Cu?1l@~1*gYx_P)%c3V9ftUVeoc$5IyX-9&&zk>* zo37|?FaHMMYj-9-q6Km=r)GjOOAU{r&yt zPcni=YCe7Lbc>7e`KGO@sHR@EXOoed)!cdgej+a{SWHVFM4#QeNwu9>MC8d+&qJz; zy1L4f=kosf`TSrr@4^dbmiu#ZnqFj?ZK|B9JL%A|wk4?-#T9$6O%2gJ`SNmY&73(d z=i~QReZ94HgTbR+EBd=~bV|8(C%$_7_OUZddErJ4L$79beyNmv{x#9t^X@KitlSMuPR<&dwZLi zNy={;XLrVrA7^G1{xS*Fa9Qia$S`qYVBpG?Pioaq&R90T)opQO@Q#?w%tE;tw}b=* zrGC8->~uPRGV#;;*3X+(J~(^s+_`5T_lZ4dV)}i0x_c#B==XVd z>-4Lc4?+$+f0mYZ>^SqwmztU%KYlHie}9+x*7owESGTtQ+qeJKi8CsOoR1c*IkRkQ z$gvfH%I@3p{Ws}u*|O^XysV;r`N{8Mbb6T!SM@nhXuuu$w^ zYU(VD*yjZnb6Qvu-rRV2*t(Rdt1Brv|1MMBT`nFUe|8z!-(Np}VhRbpdiC|Dq-fBD zy&vDk1uIrw{T>|r{YqH8P35O6D<330xUw>M`8<1dLqSVRpWvQbPKzsgdwP0JO&T&U z@7cS%R9W;uPHz33+J*bhxORI;pU=EpQ{y*(UEO}&Xpi#kesir#H*H9$)7PE z#iv0-8k2;MiTL|IJ0yBtOZZ7su6rx1)!q9SFJ9cZWeSV6?|i;9b6!4v{FF84=BBEz zZ*Dr|yjkq--p6o$-raq*pHkkw&j+nwb7VZJmC^CiS4v7ss;leK`|!*A?r+&}bbkH1 z=<>&G0@Bjr)91yNH_dkHcmHjxAG0H4;(q&$Z?3ez+*DmY>HO`T#)2oV3JMAee*9_t zvA4bL-;a+QO?Xx)#P6*-J1hHoM0nQ@6DfHM*SI)GN5@8&;Oon3W1^ypigI)cet+u} zULD5RE#^D>*-K8J`F5qRj&%AI3vj(lwrST3J!VXZ7}+P$dh$#i!&rqy9T|N!~{C}%Z7*#Q^S^si2w;}gTV z+;6U(tW3=R@13qDD^{o6-liLEW6KzS-?rMVk7du^ic#&Z%$5L9nL5#tGV(?O2WxWKR>6R{S|gutZi1w zw%pqrlfUOBTw3Bex$LbH(>Cwvr%Y259pi4NruurZOmAwM`|DD7S63GcYX!)o*Vi?) zw=aKwXXgRXsM~zY;J>xOVIaU(_U6Wx%(GGomOsx**Vil9*(p7GdV1CO-#@_zPj4?atWC$mxe}h`ONrmT3^{ctUg9d;`!O=O)VuaFJ66nLr_Ei zc|l0%YOy7Unzn24##a13W%6d#x5cxzJ*Zr<5tvEvnscdb)nx95db*7Z0CYX{L7WmQylsO-)UWOXbGv)7Q^iv}DN&4ZjZ}{q9M@ zueuf~1-UzgsLW+`%$^p0^vlbXLt(*}f2|B&?r&eucjU;CW6PF%zq69I0)>=?_3qu@ z-+KRA6u0k8&AbT$va(WKD^^UIcI+6_VmDrSyA+SF#}_x{oSZaO`}$huoZRYfb8I9H z%=0fUs;xe7>C&|@|NcEYSesApOaJt5UfbWjf3+{~cv*LdY4;}8yZj6yB2%W?*R$QZ z>)!wE1H+m%QQO~LAr$9)57}$k!F?^nU%jqO>vp{=VAp z@4bIzN$K^*F)yE$`2L=p+}V2G@_E?wGC9Nm zRAydI*m-K2s;a8$)XYn|(c3Z)KV=FFD=XvUJM)~4ZP_y2C<({q=yPHizd-jZyS1d1Hh0Tj!w{qp`>;#4_`S0K4WO}k>IWj6oeE$6TbLLYM z$AjM9>$s-HiQehsdH@<=-Lz?a|M$JB{l_13P74xsb9Q!D*X=do{dv#j*p(}{ZXIOo z==t+!=Ng_L9~708j5huH?biJ0*_oMErDr4@!o&UjBO^DRck=!4MaF7NZuG~?r!vep zyLM00`S?9uEl%ft`>Zdrvf0lLt;o*F$;mmgGPnNit*zM)AC{K?J3W1U3@5j6`kp2J zHOULz`{iucteLT{YLQcO5x<;G#Rj#vb@gQ{*v{SE`1s6B#O$Xk@WI5Ts$IU_rJ`g1|$Rrk+d+Xh;a-FV@`g9qB- z4M&dbuwZ5V#3ZhF=Fs!{-AkIn3p{5p4B6(#eXK+3)uE?FJ6l^1Tv#Zq9u>hb*LwHP zP9tVBqfHw!?n-_5ZeM!pJpYTkw~sE3-u~+Q<%<_DUcAO8XS=KZ|G(M;7cLw-c8qPp zgyIh#EBjD_WX&$^hJX}JlOwOIXs{3|bxNzaZ5|sm>xv?WH846o>)@4n+xjWn@ z_|cb_c6PQ^A^T;wGQ{qwczJ2IdBgtyN4xXyO;FgoMCIc7>GS5ziwj_|srvHb;_-fm zkdTm&D5->ujEoiQ{;fSfE$Up<7KNtIcXob$9=~TrZKF)!`sf*;Huxc@2j}Kmm)q5> zsQV4-|Ml=3xO3-DOtf^ywVoYGN1i@9>ODPfKU<%SWzmz9!WX~KHamNJcXj!J8xecf zFh$8fc)#Cs*R`jor|Y-3b^Wh>{^ZFM5piZuPfg96H;;%eT^w8*EcB~3IvTvNY>s8| zw;Yd-7ta@;56;pmG;L{}`0cuh=b=K|LwQbw9Yp<^6-Y$E2Nup-@p&!5B z-`!oV|KWDNo!#Z--S@5}-rg3w``cUQoSZpxj`gdX?sA=ZpuhsO5+@-yH~;<~O98QO ze<}k6Cd~Z#w0n`#s@~In%CX`bK>1haY|fPX{ku((v)|^K+udg&f~U zM@r7u*X5luB_;j%apq;qd}ntFtb$6?K5^p2 zi7QtwdOv@{gc&oY9_3g90&`@RG0k7Irl)6%N#(g6F>cAr)ef=q%h~nxvGvJXm%X`Z zoN#s3)z$0cQeQE5bggL0IoQ<7{r4}U{eEV4IU9lhu6~ujzrDTvB<0yrFYhHmjD{&E zCMbUU*3i_{)RZ8#c-pjS(>57RnD_6gcb%PpoL^sXaF*7A-rn9G6O$QSm5ZW+K=U|u zH3>D3v_L~qMLw>ER)%LzpFXXv$94!b7&e(P{{G(T_xIVqy%E&EHH&K%XqU&k%kE#k z%Un%S_x<$As!qnDb{0$L)i1x7{l2@q{C!-A$cIl)PfzFMToUQ|`dVmzcinxE-!n5E ze0+R*G#s-^{^Z}E6tqTBamo7~pwzfNp4oTytQi?uOrZ8gRn?<-|72Ag8x<85mI--l z>^?ks;y>T6mTAozAD<&HkGXtaCMBA>fHG2P5zx7m7Dc^4<1TMo!Df)bop1(H+k1 zRTW!uxn=C@9<^wERb7#=P}pqOpTHh@`@A`e7yro2-}1l8!^7i5|BG6O-;L^Olbjq& zoI*tJ-3wk`_L}X^K3Rc)$Zr#N#O$ef8I+-6kihWr-1qo}7k?jUZqkd{QPAizlV4u% zR~;yFVn0 z+O+Aw#l`LX{nF|`O>_bUO|5or2-vdkY^iIhW8JJ-Qc_-C2exEhUUqevfJg33FEc~oVl_^k+riFGyy+TQuwI8-WJ(U{ccx2UntuVyQ}0~jQCz1E-o(a%02S+wYc~t(IXGlU1xj}&d&P#JN*oUTi=&&-#)JV{rmJ&EzQg< zCP&Bb?>duTZQiVGe0Yb2(CiBl3!DC|-(U7t%8=>9$C+klPj+UCT?$xGyW{$r$h}nu z8eVO`e(BPckRT==o-bctFW%{MdYW!jN6^cHGcztO_M9bY*xAK3{rBG{pG8i-f3|Fz zu|(^6;H~ZX*Uw!Mxv??%wweF=S>~07hKiZh_NylF*Z%YInPn#Wyn422_A{UK=eM+F z)<)gDB_(z3Z>ed?3buPMY98#|85tQF>5!Kf6H{YzVc*{7=7g${QWjR*%1=KGKiclA zW?!*l#cF9uMlP}+Z21>ySq{r~(g*@vbyi9JCYHg z)$fkYF5*+ZwB7`5jXQSi%n#6DQ0ME#X&1k2VVbj0@#EEVGmX>z&d*cf+F4nA@%#4e z`FC%f;Nak^`)6Y}Pcl68`o)cl7cZVEX^?T@K;zoz>;LR7|9i&FJ_)?RYU(tmz`%07f>v$GQ%vOcA!2;8^nSO53* zLTBGr)6Ta4f4`e%-?{6#rpMyvUz6JN7cN`~@a<(;UHj9isk?H|DsG>^?%wY1?(VIo z2KE2;RIXdM#3|N!R>c2|75sCAp<7QuJ4UZ9b@&lzQ}1VT=-Jt+Q>IL9EPH!vtMKxa z=d(<2Z_B;Q)gxtE{_f7s16#Ax&;R<(EGe0pDJt5~>^xmhPL82H*xdMcn_tnV<^F<# z4lywov2`n7ATMR{`}16ZI#%x z_Y*xK>Qc}acy?5`j^NG~|pClv{)rnI?#J|6j)vT;~FLz;8=dcq3SQkb{&6+uLCV0oz#*GcVy?giW-MeJ{zIO|yJkQUwt&WN|_MSGMTdTp=ri~}_ za$Dr44IWIdnDa{lU$nMXR#sLvEK57910FV?dbYsSbnDiwTN?`>KRfgB6H`%;#cN_S ztV&N#I>l0!dVHnl+jLXY(9qCO1>3n#Zi9E6Ug5pMe(#0J2T(*@x-^U3-ovwVTDos6 zSMu?5GYm6@GLr&gcvx6t_y2pp-@)a`Y;#Rbm&MPE7=?w4i`m%^+_-UQQRwPlmv4Y} zcm@ZZ=y`LHdD6bAGd*iw$LL+yTRq>-wwg&zO-$_3lnqPlG&EPvN?mrjGbl2$t}gak zUs_^f;?MP$GfWFoQy+PsJ*jBNFsokY*FVtwse>nH|MABY4@oUz>AY|%X>WCP1&`E` z8o$q{z&lz#Hf8Kl_hWE%RgqY{X3d@$uP%yI+itS zbab*Ny_-07>fE_=&(_3)w@Q~fFTQ%9w6wRkx3{qc1Xw<@R$O1FGRw;33uwtvL)qJ1 zUQp9N`s4TV0)?%Y7B7z9 zHzlQ2=M_^x=+z4sE-2WQ%F3SP&g1HLR}(YsHTCfH^!4>+H8JtXVFd3*zI!10yitSGGIyc9%*zHpI<$@i>?RWUgzk}wR zh3o(O&-du9($y6f4xF_Bw4-@Lhx_8SN8BEM?&P%6?*0+w>(h}R6S4#}2(}cmxim&W zSJ&KJylwIU#Vd znI$qJA|k@2IV>rAi`0&}vYc+atG|P`+-BF!*;fnN7u2w0$AbsY&o}<5QM&M7yXKdO ztgI|=N}8LitNY}4$)=pI7CTnVoayS?+PWkpCwAJh)WpP0n<=2S*i^>G#{Yjlf6?4f z@bEz6Y%|8czh1ubo2T>gqG_GfTK+$`xnEvbSX=$z<>dzt9z2*OfBbg!p%zZzhR@H- z-`&|MtfBK~C-;P!pP*S0raL=}A00V4`M@90+Ua?*pC8Y)a5Tvm7k@M>Au;ji`%e!K zcZ(YuIusS<j@*t)9hWxK|i)x3hS+UD$?uzf(x3@XB z^U1Na@z1v`e&*vD|FmCO;lZ1m$NL+#!}(-)Rf~K0`g)u=!5}2Ocu`OggRHExv#;-h zJv+bvzr{PX9{ zo2;x2Jv^CWi3tg5%T{xLdGYY!#f{1ad3P=?b#7xQDq6B+&60PwZ)_|p`}~|)-hR@@ z;Ha&y?(D2APWb`$n%zF5Kf4}thbpC)CpR5_TZ*0lW&*Xe_v-tbFQ&St7 zm|i{-6)Jk}7a>vb?#{Wn=6MX9oEI-@YC3p%#oU>$f8^`3g^XX`{(imw?r!GEYHOoR zb0iA>{fV!?yMyu0{`!|e9vl-U2uRMH!;_L)`*YH4?^m`{rZReYWo31BHEiA5+}z6g z;OW-1vl|l6{BTV@J1f5K=3eO?m7kAv{{Ei*FGeS_=)r+2D-RrKoUFck$CW=8M~^PK zyL|KJNtg8ZGq|};o3`Y*Q^=Kdv8ML#>Sd$2_g>6?Fr`nHo#(}Ud5h9lcXk#(&#IFF z&BM96CVYM6+AXHbv@ZVpXX^q64*vCX+w?Q#?Do|C{Z;zls`e$n(!akxSzfbnY?(YYi@7JqW{$*wDQJ6Sc`K*qV7O36E#dTnTV_ck`o}p^u3VWT^US8NFU84; z)n@LFFYj#Ae75HuxV!u3&*S}|D2;jflGCPMPC!74ODD!6T>*9;<3%Qf?@{*I2nU^dR6Bid{1TCWb{x0@xzq+>ftco>J zTPr?3I@&NLBr7XQs^HI$X}Zzd7+hUhSy@>p?R&M#(_g*v20P!HxV>q-37IQbty;#W z6X&yQ!_{s4?{9AY|L600dxzK8^77WLvtNI{`g5B6eCPIt2M=ynjn<2g+cBZ? zVqnzPS65D+;)>Y)?aj^mb}_tjhpM!_xf)>pT6sAYFhpJoSwEfGdMdtuu4=#wf4`CpT-xqWPW}& zHP>HPSj2kwy4c*D8Kug~+}yUd36GC;i;L?p)YO>eNEo;M+`n<-)T#UICQO?)K|$lh zEYs|}yE2216&Yqsm_B{A_UHQ0P+i@^I)Bj28!KzW^5;F0d#jn%)Z*j)gDxHKU%B$k zu7wY;H%-~L`t8ljmp2Eir`2p#HT?Mcvy`-X_P2N*p>^4HQt~?t{{H^|>-GBmOvn3w z|Bm0mprQ@}*Z=KkX5YPg_ipCT&wS^-dCD5Ib5nZ%di{cTb3jK}T>j${bmX|Zo0}Vx zy8k3jw}=~8S6^SpSpRQl$;(Si9lpN<&3{Mz{@l_sfyqKsQzhc;tzEve=Wo;wj<_*d zed5FeS6Bc4egE$60}YJAY8KYavu63us#*VO{^I2McHh4B9Psw{_d9oriBJCD4A#0cy6wXea`D=b44Y#9JeiA)_wZ@e&g$&3xx$$RYR|y;xasX z+}&;25`)*Ev4vyDdKzx;D7>|WnSDm#pO4398W%t7sQbHW)vQ^kP94zSuM-s#`P3zm zF)t-0apCIUZ_A9+a_-rb=@>UII)A%Uc(!@`KAwt-88dz7^I2G)Jl!wJd}h9V!hts4 z9`6UYe|yKUO{GM$@yd+Y08U-SE?&+yo{{_5)E zeScr;FYuSoed{@y!Q8y`>&M59kB^(@?Wve}bKko9dfwLge$3)&cPtiJ=HGty{P}bC zBS()OKYslBza3jjUVnPZEv^^CQBln=Z?lUX;rzV6uh;MY$8>I<>fc?TKi%8^{{v&h)~t7TDnB=@3_khYOP6!&(}&JN zZ|h%&6@1v7?y$cOv?4qD_hYjVy_gSQ_m*}?zQ1+#?%v$!kNt~Rc-#u$lY8^_?rL$( zz~BFDC(NBYZ{BqFH+L+{-)&4j&@JBBn1A0$Kj775UjF)DAs>EvdMetzzHy`cy^wI@ zfdl*h*ZrFEWxe>7h|8CRgpG|Fyr=*9^X?Agx_J946OE25m!22xmsS7j8tmh<@7k1o zHJ)Cl&ajx}DmAt3dr(_*ZN0qhu6OTe?@&>xv8_{HoOX7f`hk@Ri@smJvE$R*m8l2r z+_`q`2unvFA8&6z`!b)GcPf7tB^>RVs9gRgA%@|Qh}g5IqN0qFlA4;4k!PM?UjF^f z&)@G4Y)G6o%{ZNDd;WZ@uOAd2Jh-sf{q(d&{thlrqj~QfdQ^RU{fZSU9(-<0J$-`3 z(Bj9nwHE>&yto*?-Yl1ijdzyO(W{~rUtZkWI$gi*T?KkV%?B`|JT>o*O`UYg&MO{uda#A z)#?r0vek3tg`1meYiep{oZk#u+qJ2|x}1rbnYr=vbN$#|HIffLd%pehsi@&RyO+1; zFHzAg;L~-UF1g6Llds`0v!cwTU%ROCtO^#GI;Oa*M1J+NAK=-baZq)aC-X2 zjfRE|%a?E8u952@ZGC0B$Hq-rm)#8X?d<*?ZeOCJpr&SHqqy+Z<1M+b-`v@hdiDSE zwnv$ludS6feHHDPkalfR>qNoLex_IKYCHH#zrSPU_M5{HwN2$Wu`zu8wYBwkYJ-D? z&rX>$Lqb$F!_mNO+m=7`R!;ksmbq(k=gI3$t&;oq?p>)VC^Flex%}N6>+erEHw!MmC;JS(f6YESyH0<)o~p{5yQeeONt^l1eDs_>X3vY~;sOr0 z#HUYTSRE#7ZIcL*L>zh5uXD21c4 z-rLhq_;f2bJO8~sGb1F}c$s#UN}H^xt$uKJc00d)O+w%Og@>=7SML4z;A2;}xA%V8 z`8)RSZ*yAw)=f=s%gqxloJXeAJma|-6TQ8!W5WgpHeM-%gaZw`?AN!ktt@=^^5w&a z4;5eTRc-P~^P)nP8oLNybEdB07M7t(8 z+}-c)?k;7n`u;EfS?TH(D^_c38NHr4GoD+`+uM5gGT+9P!PnQxS_*C0pzwN%=j5=p zpForHCMHv+H2BZoS2uC?tXnrEq>S_nPQAV!pDiM5{q0q1`uDd#nwtLnoo}ChZMBy< z7ytiT;kTFhet*~G7$Nd1dI<-+rRS@Com{4sL7??gSw~m(+_rC^QQ;xA{67|2(U!XM1;47#TOddDGLgXV0qRAD^5&JG*Jt z-s$1b&uND-JbZY5o~t|a?d|t>Y%I~-kazcf{rS1kr94it|Np6+^?%R2p3mJKv{p9Z z#s<*(Vcr{iZl2HoUzc!yUo$(uT#8or-!)I3Pj)hWeSPwR?Z)Z<{(gVvoABw${rdRL zZJn?FufMdgdG_oDntijpRy##B=UzH;CFFyv?i+5AYZ)5r}ZK{@U5SydQoR*Zi5Te?MxDM(N+*lTH3x^6t?R5t%Y&%9I99VUG*5m!|g1`S~6A z^i$}D!5SZ~oF6~e##DaODR_PDH5Cs>?2{%XC1r^GI@sJWP3)xje9Pj~)8gw^K0K`L zQ1hpqziC!_==r$@TLSo>zPMQW`p;j__Z^Fr9=r%l+O_Op+LabxL9quWUh{rkSgCJq z^5x=Ue))#e)A{B06t`FEy*v_R(e~ukRb}^gca#75*M2xXy;k=`giu_ zmm3n#&N@4b^~I}6r&6xCyI)?TF3-vhHo~-_+6IJp_ zrPGa{gJD;hti^^{YqeLu-tRAezprw#V9AvdZ`0Yl(trLwKc60V;A`!DmsYN0!s=$Z zyGlAguD#63wDyY|_X?jG8)|m8yMGmZl4aGmE_Ufs_r5i|qLse720J?KpZ@W&XR7t8 zo7bm=u6FCcx0QQG@$)}F)%|Du_S-CQtS53q!UG4j3U3Lm73MiJj8gyCJvi8Wdb+dI zj0J}h52u}bbGhB8fsHRk$6RDpc{(O(GkKL5=A>mo|@{IzYpM8D5Kap8L^y{zE z9G%JSc8Q0&M4j7>gx6kOeZ1%9)^3+pcUMC(rSk8dldHa|h${U4#+s7)^r`mjifdor z`(L`?l>AEmGTxgE_@8#g3=RY!g zDn5RAc({EHTio*tlI2cLK0ZD?A4T_8u`XFQ$)+T2n%B1EOGi6i?%K0w(V|66D^@7{ zU%x`(|MW>p|IN*|ZQ8VnX_mRVFte?#^Wpcd=Qn|d8~?;?kg@=cT5@|Uw_H5{9wv;C zQnZgXHv%7tIqg4Fj))bef;Et1FArVfNQ54qIn9j&dMM)t6Q>B?IiN|2)}?}nU`J>6 z3WPDIgAS-n%xnqZo%8zf=9-_Mo~{nRoEPQkSy)(D$S~hOs|bAF=Q-%Hp9R;ZP64fa zX!y^}5HIkPd1Bdq1_lPz64!{5l*E!$tK_28#FA77BLhQ2T>}$cBZCk_b1MTQD?>AF z14}CdgS3CI#Zffm=BH$)RpQnlzBqU_0|P@U$cEywbgQJq;#A$zqD+Rg%$!s!eSQ6m z{M=Oi^t{Z>q*VR#{Gx3A^73*$2wyM1C|$oevm{l&C_leMKQ}cuUq2 + +It says, there is no key info related to this token on your PC (``[none]``). + +Fetch the public key from URL specified in the Token. :: + + gpg/card> fetch + gpg: requesting key 4CA7BABE from http server www.gniibe.org + gpg: key 4CA7BABE: public key "NIIBE Yutaka " imported + gpg: no ultimately trusted keys found + gpg: Total number processed: 1 + gpg: imported: 1 (RSA: 1) + + gpg/card> + +Good. The public key is now in ``.gnupg``. We can examine by ``gpg --list-keys``. + +However, the secret key reference (to the token) is not in ``.gnupg`` yet. + +It will be generated when I do ``--card-status`` by GnuPG with correspoinding public key in ``.gnupg``, or just type return at the ``gpg/card>`` prompt. :: + + gpg/card> + + Application ID ...: D276000124010200F517000000010000 + Version ..........: 2.0 + Manufacturer .....: FSIJ + Serial number ....: 00000001 + Name of cardholder: Yutaka Niibe + Language prefs ...: ja + Sex ..............: male + URL of public key : http://www.gniibe.org/gniibe.asc + Login data .......: gniibe + Signature PIN ....: not forced + Key attributes ...: 2048R 2048R 2048R + Max. PIN lengths .: 127 127 127 + PIN retry counter : 3 3 3 + Signature counter : 6 + Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE + created ....: 2010-10-15 06:46:33 + Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF + created ....: 2010-10-15 06:46:33 + Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC + created ....: 2010-10-22 06:06:36 + General key info..: + pub 2048R/4CA7BABE 2010-10-15 NIIBE Yutaka + sec> 2048R/4CA7BABE created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb> 2048R/084239CF created: 2010-10-15 expires: never + card-no: F517 00000001 + ssb> 2048R/5BB065DC created: 2010-10-22 expires: never + card-no: F517 00000001 + + gpg/card> + +OK, now I can use the Token on this computer. + + +Update trustdb for the key on Gnuk Token +======================================== + +Yes, I can use the Token by the public key and the secret key reference to the card. More, I need to update the trustdb. + +To do that I do: :: + + $ gpg --edit-key 4ca7babe + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Secret key is available. + + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: unknown validity: unknown + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ unknown] (1). NIIBE Yutaka + [ unknown] (2) NIIBE Yutaka + + gpg> + +See, the key is ``unknown`` state. Add trust for that. :: + + gpg> trust + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: unknown validity: unknown + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ unknown] (1). NIIBE Yutaka + [ unknown] (2) NIIBE Yutaka + + Please decide how far you trust this user to correctly verify other users' keys + (by looking at passports, checking fingerprints from different sources, etc.) + + 1 = I don't know or won't say + 2 = I do NOT trust + 3 = I trust marginally + 4 = I trust fully + 5 = I trust ultimately + m = back to the main menu + + Your decision? 5 + Do you really want to set this key to ultimate trust? (y/N) y + + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: ultimate validity: unknown + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ unknown] (1). NIIBE Yutaka + [ unknown] (2) NIIBE Yutaka + Please note that the shown key validity is not necessarily correct + unless you restart the program. + + $ + +Next time I invoke GnuPG, it will be ``ultimate`` key. Let's see: :: + + $ gpg --edit-key 4ca7babe + gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Secret key is available. + + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC + trust: ultimate validity: ultimate + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A + [ultimate] (1). NIIBE Yutaka + [ultimate] (2) NIIBE Yutaka + + gpg> quit + $ From 0d36a588040be23fb51803edea532d3afa64e4ca Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 3 Aug 2012 11:06:44 +0900 Subject: [PATCH 259/300] Add more doc --- doc/conf.py | 8 ++++---- doc/gnome3-gpg-settings.rst | 30 +++++++++++++++++++++++++++ doc/gpg-settings.rst | 41 +++++++++++++++++++++++++++++++++++++ doc/index.rst | 5 +++++ 4 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 doc/gnome3-gpg-settings.rst create mode 100644 doc/gpg-settings.rst diff --git a/doc/conf.py b/doc/conf.py index 9221b32..fd2eead 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -41,7 +41,7 @@ master_doc = 'index' # General information about the project. project = u'Gnuk Documentation' -copyright = u'2012, Niibe Yutaka' +copyright = u'2012, NIIBE Yutaka' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -184,7 +184,7 @@ latex_elements = { # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'GnukDocumentation.tex', u'Gnuk Documentation Documentation', - u'Niibe Yutaka', 'manual'), + u'NIIBE Yutaka', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -214,7 +214,7 @@ latex_documents = [ # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'gnukdocumentation', u'Gnuk Documentation Documentation', - [u'Niibe Yutaka'], 1) + [u'NIIBE Yutaka'], 1) ] # If true, show URL addresses after external links. @@ -228,7 +228,7 @@ man_pages = [ # dir menu entry, description, category) texinfo_documents = [ ('index', 'GnukDocumentation', u'Gnuk Documentation Documentation', - u'Niibe Yutaka', 'GnukDocumentation', 'One line description of project.', + u'NIIBE Yutaka', 'GnukDocumentation', 'One line description of project.', 'Miscellaneous'), ] diff --git a/doc/gnome3-gpg-settings.rst b/doc/gnome3-gpg-settings.rst new file mode 100644 index 0000000..f6bb312 --- /dev/null +++ b/doc/gnome3-gpg-settings.rst @@ -0,0 +1,30 @@ +========================== +GnuPG settings for GNOME 3 +========================== + +In the article `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH. + +It was for GNOME 2. The old days was good, we just disabled GNOME-keyrings interference to SSH and customizing our desktop was easy for GNU and UNIX users. + +.. _GnuPG settings: gpg-settings + + +GNOME keyrings in GNOME 3 +========================= + +It seems that it is more integrated into the desktop. It is difficult to kill it. It would be possible to kill it simply, but then, I can't use, say, wi-fi access (which needs to access "secrets") any more. + +We can't use GNOME configuration tool to disable interference by GNOME keyrings any more. It seems that desktop should not have customization these days. + + +GNOME-SESSION-PROPERTIES +======================== + +After struggling some ours, I figured out it is GNOME-SESSION-PROPERTIES to disable the interference. Invoking:: + + $ gnome-session-properties + +and at the tab of "Startup Programs", I removed radio check buttons for "GPG Password Agent" and "SSH Key Agent". + + +Now, I use gpg-agent for GnuPG Agent and SSH agent with Gnuk Token. diff --git a/doc/gpg-settings.rst b/doc/gpg-settings.rst new file mode 100644 index 0000000..d573995 --- /dev/null +++ b/doc/gpg-settings.rst @@ -0,0 +1,41 @@ +.. -*- coding: utf-8 -*- + +============== +GnuPG settings +============== + +Here is my GnuPG settings. + +.gnupg/gpg.conf +=============== + +I create ``.gnupg/gpg.conf`` file with the following content. :: + + use-agent + personal-digest-preferences SHA256 + cert-digest-algo SHA256 + default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed + + default-key 0x4ca7babe + + +Let gpg-agent manage SSH key +============================ + +I deactivate seahose-agent. Also, I deactivate gnome-keyring managing SSH key. :: + + $ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false + +Then, I create ``.gnupg/gpg-agent.conf`` file with the following content. :: + + enable-ssh-support + + +References +========== + +* `Creating a new GPG key`_ +* `Use OpenPGP Keys for OpenSSH, how to use gpg with ssh`_ + +.. _Creating a new GPG key: http://keyring.debian.org/creating-key.html +.. _Use OpenPGP Keys for OpenSSH, how to use gpg with ssh: http://www.programmierecke.net/howto/gpg-ssh.html diff --git a/doc/index.rst b/doc/index.rst index f9e125a..174dd47 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -2,6 +2,9 @@ sphinx-quickstart on Wed Jul 4 15:29:05 2012. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. + Copyright (C) 2012 NIIBE Yutaka + Copyright (C) 2012 Free Software Initiative of Japan + This document is licensed under a CC-BY-SA 3.0 Unported License Gnuk Documentation ================== @@ -21,6 +24,8 @@ Contents: gnuk-keytocard.rst gnuk-keytocard-noremoval.rst using-gnuk-token-with-another-computer.rst + gpg-settings.rst + gnome3-gpg-settings.rst Indices and tables From f39380d3aa686eec1fb8616c2dd259e8d2f75d30 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 3 Aug 2012 11:20:13 +0900 Subject: [PATCH 260/300] version 1.0.1 --- ChangeLog | 11 +++++++++++ NEWS | 9 +++++++++ README | 38 ++++++++++++++++++++------------------ src/main.c | 2 +- src/usb_desc.c | 4 ++-- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 614c1cd..7195dae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-08-03 Niibe Yutaka + + * Version 1.0.1. + * src/usb_desc.c (gnukStringSerial): Updated. + * src/main.c (ID_OFFSET): Fix. + +2012-08-02 Niibe Yutaka + + * test/gnuk.py (gnuk_token.get_string): New. + * test/features/991_version_string.feature: New. + 2012-07-21 Niibe Yutaka * Version 1.0. diff --git a/NEWS b/NEWS index 9990f58..016c370 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,14 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 1.0.1 + + Released 2012-08-03, by NIIBE Yutaka + +** USB SerialNumber String +In 1.0, it has a bug for USB SerialNumber String. It has been fixed +in 1.0.1. + + * Major changes in Gnuk 1.0 Released 2012-07-21, by NIIBE Yutaka diff --git a/README b/README index f0f649d..3b3da45 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Gnuk - An Implementation of USB Cryptographic Token for GnuPG - Version 1.0 - 2012-07-21 + Version 1.0.1 + 2012-08-03 Niibe Yutaka Free Software Initiative of Japan @@ -14,9 +14,9 @@ STM32F103 processor. I wish that Gnuk will be a developer's soother who uses GnuPG. I have been nervous of storing secret key(s) on usual secondary storage. -There is a solution with OpenPGP card, but it is not the choice for me -to bring a card reader all the time. With Gnuk, this issue will be -solved by a USB token which is small enough. +There is a solution with OpenPGP card, but it is not the choice for +me, as card reader is not common device. With Gnuk, this issue will +be solved by a USB token. Please look at the graphics of "gnuk.svg" for the software name. My son used to be with his NUK(R), always, everywhere. Now, I am with a @@ -35,7 +35,7 @@ A0: Good points of Gnuk are: Gnuk Token cheaper (see Q8-A8). * You can study Gnuk to modify and to enhance. For example, you can implement your own authentication method with some sensor - such as acceleration sensor. + such as an acceleration sensor. * It is "of Free Software"; Gnuk is distributed under GPLv3+, "by Free Software"; Gnuk development requires only Free Software (GNU Toolchain, Python, etc.), @@ -51,8 +51,8 @@ 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. + FST-01 (Flying Stone Tiny 01) will be soon available for sale, + and 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 @@ -63,12 +63,13 @@ Q5: What's version of pcscd and libccid are you using? A5: In Debian GNU/Linux system, I use pcscd 1.5.5-4 and libccid 1.3.11-2, which is in squeeze. Note that you need to edit /etc/libccid_Info.plist when using libccid (< 1.4.1). + Note that pcscd and libccid are optional, you can use Gnuk without them. Q6: What kinds of hardware is required for development? -A6: You need a target board plus a JTAG debugger. If you just want to - test Gnuk for target boards with DfuSe, JTAG debugger is not - the requirement. Note that for real use, you need JTAG debugger - to enable flash ROM protection. +A6: You need a target board plus a JTAG/SWD debugger. If you just + want to test Gnuk for target boards with DfuSe, JTAG debugger is + not the requirement. Note that for real use, you need JTAG/SWD + debugger to enable flash ROM protection. Q7: How much does it cost? A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so. @@ -107,17 +108,18 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: "GPG Password Agent" and "SSH Key Agent". Qc: Do you know a good SWD debugger to connect FST-01 or something? -Ac: STLink v2 is cheap one. We have a tool/stlinkv2.py as flash ROM -writer program. +Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM + writer program. Release notes ============= -This is version 1.0 release of Gnuk, after a year and eleven months -development. While it is daily use for a year or so, some newly -introduced features (including key generation and firmware upgrade) -should be considered experimental. +This is a minor release in version 1.0 series of Gnuk. + +While it is daily use for more than a year, some newly introduced +features (including key generation and firmware upgrade) should be +considered experimental. Tested features are: diff --git a/src/main.c b/src/main.c index a38e540..701af2b 100644 --- a/src/main.c +++ b/src/main.c @@ -178,7 +178,7 @@ extern msg_t USBthread (void *arg); #define LED_TIMEOUT_STOP MS2ST(200) -#define ID_OFFSET 22 +#define ID_OFFSET 24 static void device_initialize_once (void) { diff --git a/src/usb_desc.c b/src/usb_desc.c index 3d37dbd..81b00b5 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -258,11 +258,11 @@ static const uint8_t gnukStringLangID[] = { #include "usb-strings.c.inc" const uint8_t gnukStringSerial[] = { - 17*2+2, /* bLength */ + 19*2+2, /* bLength */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ /* FSIJ-1.0 */ 'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0, - '1', 0, '.', 0, '0', 0, /* Version number of Gnuk */ + '1', 0, '.', 0, '0', 0, '.', 0, '1', 0, /* Version number of Gnuk */ '-', 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From 39bee2ee01df637a1194e89e6964cf295b9b2834 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 29 Aug 2012 13:16:27 +0900 Subject: [PATCH 261/300] Fix by Henry Hu --- ChangeLog | 5 +++++ tool/hub_ctrl.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7195dae..17ab183 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-08-29 Niibe Yutaka + + * tool/hub_ctrl.py (__main__): Fix to busnum (was: bunum). + Thanks to Henry Hu. + 2012-08-03 Niibe Yutaka * Version 1.0.1. diff --git a/tool/hub_ctrl.py b/tool/hub_ctrl.py index 721b7d1..684b3bd 100755 --- a/tool/hub_ctrl.py +++ b/tool/hub_ctrl.py @@ -167,7 +167,7 @@ if __name__ == '__main__': option = sys.argv[1] sys.argv.pop(1) if option == '-h': - if bunum != None or devnum != None: + if busnum != None or devnum != None: exit_with_usage(sys.argv[0]) hub = int(sys.argv[1]) sys.argv.pop(1) From 6b5fc04c0d936ef5ecf83d8aa5ce5c85601599de Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 12 Sep 2012 14:16:40 +0900 Subject: [PATCH 262/300] fix sha256 --- ChangeLog | 7 +++++++ src/sha256.c | 3 +-- src/sha256.h | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17ab183..8cb5d48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-09-12 Niibe Yutaka + + * src/sha256.c: Include . + + * src/sha256.h (SHA256_DIGEST_SIZE, SHA256_BLOCK_SIZE): Move + from sha256.c. + 2012-08-29 Niibe Yutaka * tool/hub_ctrl.py (__main__): Fix to busnum (was: bunum). diff --git a/src/sha256.c b/src/sha256.c index a3f17ed..0be2a1f 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -46,11 +46,10 @@ */ #include +#include #include #include "sha256.h" -#define SHA256_DIGEST_SIZE 32 -#define SHA256_BLOCK_SIZE 64 #define SHA256_MASK (SHA256_BLOCK_SIZE - 1) static void bswap32_buf (uint32_t *p, int n) diff --git a/src/sha256.h b/src/sha256.h index d52fb77..5591eb2 100644 --- a/src/sha256.h +++ b/src/sha256.h @@ -1,3 +1,6 @@ +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + typedef struct { uint32_t total[2]; From e8f773d2f6bd8d347b65cdb467ef1b4d2ef85aa5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 18 Sep 2012 15:32:12 +0900 Subject: [PATCH 263/300] fix stlinkv2.py --- ChangeLog | 7 +++++++ doc/note/firmware-update | 8 +++----- tool/stlinkv2.py | 9 ++++++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8cb5d48..8261f7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-09-18 Niibe Yutaka + + * tool/stlinkv2.py (stlinkv2.option_bytes_erase) + (stlinkv2.flash_erase_all, stlinkv2.flash_erase_page): : Fix + OperationFailure (was OperationError). + (main): Call option_bytes_erase if it's not 0xff. + 2012-09-12 Niibe Yutaka * src/sha256.c: Include . diff --git a/doc/note/firmware-update b/doc/note/firmware-update index 52ff93f..686bae7 100644 --- a/doc/note/firmware-update +++ b/doc/note/firmware-update @@ -38,14 +38,12 @@ We can examine key information of gpg-agent by "KEYINFO" command. Here is my example:: $ gpg-connect-agent "KEYINFO --list" /bye - S KEYINFO 4970A0D537CA2EF7CE6A106E47AD89B0EFB684C8 D - - - - - S KEYINFO 65F67E742101C7FE6D5B33FCEFCF4F65EAF0688C T D276000124010200F517000000010000 OPENPGP.2 - - - - S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - - - S KEYINFO 7D180C0C2A991B25204110A92F5F92A5A509845B D - - - - - S KEYINFO 101DE7B639FE29F4636BDEECF442A9273AFA6565 T D276000124010200F517000000010000 OPENPGP.1 - - - + S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - - OK -I have two local keys (in my PC) and three keys in my token. +I have three keys in my token. With the script below, I extract public key of the keygrip 5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin:: @@ -63,7 +61,7 @@ Here is the script, get_public_key.py:: result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"]) key = "" while True: - i = result.find('%') + i = result.find('%') if i < 0: key += result break diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index d2af143..a14a986 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -356,7 +356,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise OperationError("option bytes erase") + raise OperationFailure("option bytes erase") def flash_write_internal(self, addr, data, off, size): prog = gen_prog_flash_write(addr,size) @@ -415,7 +415,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise OperationError("flash erase all") + raise OperationFailure("flash erase all") def flash_erase_page(self, addr): self.write_memory_u32(FLASH_KEYR, FLASH_KEY1) @@ -439,7 +439,7 @@ class stlinkv2(object): self.write_memory_u32(FLASH_CR, FLASH_CR_LOCK) if (status & FLASH_SR_EOP) == 0: - raise OperationError("flash page erase") + raise OperationFailure("flash page erase") def start(self): mode = self.stl_mode() @@ -564,6 +564,9 @@ def main(show_help, erase_only, no_protect, spi_flash_check, stl.setup_gpio() if unlock: + if option_bytes != 0xff: + stl.reset_sys() + stl.option_bytes_erase() stl.reset_sys() stl.option_bytes_write(OPTION_BYTES_ADDR,RDP_KEY) stl.usb_disconnect() From 23a9fe3bdc8e836b0a4bf77fd5343d7682e3c2de Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 25 Sep 2012 09:00:10 +0900 Subject: [PATCH 264/300] stlinkv2 fixes --- ChangeLog | 5 +++++ tool/stlinkv2.py | 14 ++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8261f7c..9816961 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-09-25 Niibe Yutaka + + * tool/stlinkv2.py (main): Print out option bytes value. + Call reset_sys before blank_check. + 2012-09-18 Niibe Yutaka * tool/stlinkv2.py (stlinkv2.option_bytes_erase) diff --git a/tool/stlinkv2.py b/tool/stlinkv2.py index a14a986..8a2023f 100755 --- a/tool/stlinkv2.py +++ b/tool/stlinkv2.py @@ -523,12 +523,13 @@ def main(show_help, erase_only, no_protect, spi_flash_check, print "ON" else: print "off" - option_bytes = stl.option_bytes_read() - print "Option bytes: %08x" % option_bytes - if (option_bytes & 0xff) == RDP_KEY: - ob_protection_enable = False - else: - ob_protection_enable = True + + option_bytes = stl.option_bytes_read() + print "Option bytes: %08x" % option_bytes + if (option_bytes & 0xff) == RDP_KEY: + ob_protection_enable = False + else: + ob_protection_enable = True stl.enter_debug() status = stl.get_status() @@ -543,6 +544,7 @@ def main(show_help, erase_only, no_protect, spi_flash_check, raise OperationFailure("Flash ROM is protected") else: if not skip_blank_check: + stl.reset_sys() blank = stl.blank_check() print "Flash ROM blank check: %s" % blank else: From db2d897c3f6baff8680e62aa2840d56f8590c4f3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sat, 13 Oct 2012 08:40:37 +0900 Subject: [PATCH 265/300] Update README and fix for STBEE_MINI --- ChangeLog | 5 +++++ README | 9 ++++----- boards/STBEE_MINI/board.c | 9 +++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9816961..79bd872 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-10-13 Niibe Yutaka + + * boards/STBEE_MINI/board.c [!DFU_SUPPORT] (hwinit1): Don't run + when "user switch" is pushed. This is for JTAG/SWD debugger. + 2012-09-25 Niibe Yutaka * tool/stlinkv2.py (main): Print out option bytes value. diff --git a/README b/README index 3b3da45..256ea99 100644 --- a/README +++ b/README @@ -261,9 +261,8 @@ please contact Niibe, so that it is listed to the file in the official release of the source code. When you are modifing Gnuk and installing the binary to device, you -should replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to -yours, so that the device will say it's modified version by device -serial number. +should replace the vendor string to yours, so that users can see it's +not by original vendor, and it is modified version. FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices with Gnuk under one of following conditions: @@ -294,8 +293,8 @@ respect users' freedom for computing. Please ask FSIJ for the license. Otherwise, companies which want to distribute Gnuk devices, please use -your own USB vendor ID and product ID. Please replace "FSIJ" in the -string gnukStringSerial (usb_desc.c) to yours, when you modify Gnuk. +your own USB vendor ID and product ID. Please replace vendor string +and possibly product string to yours, when you modify Gnuk. Host Requirements diff --git a/boards/STBEE_MINI/board.c b/boards/STBEE_MINI/board.c index 2d3e0a1..c51d347 100644 --- a/boards/STBEE_MINI/board.c +++ b/boards/STBEE_MINI/board.c @@ -9,6 +9,15 @@ hwinit1 (void) { hwinit1_common (); +#if !defined(DFU_SUPPORT) + if (palReadPad (IOPORT3, GPIOC_BUTTON) == 0) + /* + * Since LEDs are connected to JTMS/SWDIO and JTDI pin, + * we can't use LED to let know users in this state. + */ + for (;;); /* Wait for JTAG debugger connection */ +#endif + #if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT) palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */ while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0) From 2e7d93a556a1398fcc13a4a5d1a02b10f6e7e5b3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 26 Oct 2012 11:05:33 +0900 Subject: [PATCH 266/300] change the product string --- ChangeLog | 6 ++++++ GNUK_USB_DEVICE_ID | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 79bd872..2dde9bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-10-26 Niibe Yutaka + + * GNUK_USB_DEVICE_ID (Product_STRING): It's considered better not + to include vendor name. Change the name to "Gnuk Token" (was: + FSIJ USB Token). + 2012-10-13 Niibe Yutaka * boards/STBEE_MINI/board.c [!DFU_SUPPORT] (hwinit1): Don't run diff --git a/GNUK_USB_DEVICE_ID b/GNUK_USB_DEVICE_ID index f019651..65a3b25 100644 --- a/GNUK_USB_DEVICE_ID +++ b/GNUK_USB_DEVICE_ID @@ -1,3 +1,3 @@ # VID:PID bcdDev Product_STRING Vender_STRING -234b:0000 0200 FSIJ USB Token Free Software Initiative of Japan +234b:0000 0200 Gnuk Token Free Software Initiative of Japan ########## ## ########## ################# From d7c6b95ba1ea1298ea0bb2b46d994d48c2c3e8d5 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 31 Oct 2012 16:23:19 +0900 Subject: [PATCH 267/300] add tool/get_raw_public_key.py --- ChangeLog | 4 ++++ tool/get_raw_public_key.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100755 tool/get_raw_public_key.py diff --git a/ChangeLog b/ChangeLog index 2dde9bf..cbd7d26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-10-31 Niibe Yutaka + + * tool/get_raw_public_key.py: New. + 2012-10-26 Niibe Yutaka * GNUK_USB_DEVICE_ID (Product_STRING): It's considered better not diff --git a/tool/get_raw_public_key.py b/tool/get_raw_public_key.py new file mode 100755 index 0000000..fb1272f --- /dev/null +++ b/tool/get_raw_public_key.py @@ -0,0 +1,32 @@ +#! /usr/bin/python + +import sys, binascii +from subprocess import check_output + +def get_gpg_public_key(keygrip): + result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"]) + key = "" + while True: + i = result.find('%') + if i < 0: + key += result + break + hex_str = result[i+1:i+3] + key += result[0:i] + key += chr(int(hex_str,16)) + result = result[i+3:] + + pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too + pos_last = key.index(")(1:e3:") + key = key[pos:pos_last] + if len(key) != 256: + raise ValueError, binascii.hexlify(key) + return key + +if __name__ == '__main__': + keygrip = sys.argv[1] + k = get_gpg_public_key(keygrip) + shorthand = keygrip[0:8] + ".bin" + f = open(shorthand,"w") + f.write(k) + f.close() From 254c521c6fd50e307e96bb2aa44e671c39580635 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 1 Nov 2012 09:18:55 +0900 Subject: [PATCH 268/300] tool/gnuk_upgrade.py: Support non-smartcard auth --- ChangeLog | 6 ++++++ tool/gnuk_upgrade.py | 38 +++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbd7d26..2176b6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-11-01 Niibe Yutaka + + * tool/gnuk_upgrade.py (main): New option '-k' to specify keygrip + for non-smartcard key. + (gpg_sign): Support non-smartcard key. + 2012-10-31 Niibe Yutaka * tool/get_raw_public_key.py: New. diff --git a/tool/gnuk_upgrade.py b/tool/gnuk_upgrade.py index 1ff2565..ea63177 100755 --- a/tool/gnuk_upgrade.py +++ b/tool/gnuk_upgrade.py @@ -25,7 +25,7 @@ along with this program. If not, see . from struct import * import sys, time, os, binascii, string -# INPUT: binary file +# INPUT: binary files (regnual_image, upgrade_firmware_image) # Assume only single CCID device is attached to computer, and it's Gnuk Token @@ -390,11 +390,18 @@ from subprocess import check_output SHA256_OID_PREFIX="3031300d060960864801650304020105000420" -def gpg_sign(hash): - result = check_output(["gpg-connect-agent", - "SCD SETDATA " + SHA256_OID_PREFIX + hash, - "SCD PKAUTH OPENPGP.3", - "/bye"]) +# When user specify KEYGRIP, use it. Or else, connect to SCD directly. +def gpg_sign(keygrip, hash): + if keygrip: + result = check_output(["gpg-connect-agent", + "SIGKEY %s" % keygrip, + "SETHASH --hash=sha256 %s" % hash, + "PKSIGN --hash=sha256", "/bye"]) + else: + result = check_output(["gpg-connect-agent", + "SCD SETDATA " + SHA256_OID_PREFIX + hash, + "SCD PKAUTH OPENPGP.3", + "/bye"]) signed = "" while True: i = result.find('%') @@ -406,8 +413,12 @@ def gpg_sign(hash): signed += chr(int(hex_str,16)) result = result[i+3:] - pos = signed.index("D ") + 2 - signed = signed[pos:-4] # \nOK\n + if keygrip: + pos = signed.index("D (7:sig-val(3:rsa(1:s256:") + 26 + signed = signed[pos:-7] + else: + pos = signed.index("D ") + 2 + signed = signed[pos:-4] # \nOK\n if len(signed) != 256: raise ValueError, binascii.hexlify(signed) return signed @@ -419,7 +430,7 @@ def crc32(bytestr): crc = binascii.crc32(bytestr) return UNSIGNED(crc) -def main(data_regnual, data_upgrade): +def main(keygrip, data_regnual, data_upgrade): l = len(data_regnual) if (l & 0x03) != 0: data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) @@ -441,7 +452,7 @@ def main(data_regnual, data_upgrade): icc.icc_power_on() icc.cmd_select_openpgp() challenge = icc.cmd_get_challenge() - signed = gpg_sign(binascii.hexlify(to_string(challenge))) + signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge))) icc.cmd_external_authenticate(signed) icc.stop_gnuk() mem_info = icc.mem_info() @@ -478,6 +489,11 @@ def main(data_regnual, data_upgrade): if __name__ == '__main__': + keygrip = None + if sys.argv[1] == '-k': + sys.argv.pop(1) + keygrip = sys.argv[1] + sys.argv.pop(1) filename_regnual = sys.argv[1] filename_upgrade = sys.argv[2] f = open(filename_regnual) @@ -488,4 +504,4 @@ if __name__ == '__main__': data_upgrade = f.read() f.close() print "%s: %d" % (filename_upgrade, len(data_upgrade)) - main(data_regnual, data_upgrade[4096:]) + main(keygrip, data_regnual, data_upgrade[4096:]) From b9772265cf5876fcac8a6ccf7d5088198dae6530 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 7 Nov 2012 11:30:00 +0900 Subject: [PATCH 269/300] proper bError value for time extension --- ChangeLog | 8 +++++ src/usb-icc.c | 83 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2176b6d..8116617 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2012-11-07 Niibe Yutaka + + * src/usb-icc.c (icc_send_data_block_internal): New. + (icc_send_data_block_time_extension): New. + (icc_handle_timeout): Use icc_send_data_block_time_extension. + (icc_send_data_block): Only one argument. + (USBthread): Follow the change. + 2012-11-01 Niibe Yutaka * tool/gnuk_upgrade.py (main): New option '-k' to specify keygrip diff --git a/src/usb-icc.c b/src/usb-icc.c index d906548..8cd0ebc 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -827,36 +827,7 @@ icc_power_off (struct ccid *c) } static void -icc_send_data_block_0x9000 (struct ccid *c) -{ - uint8_t p[ICC_MSG_HEADER_SIZE+2]; - size_t len = 2; - - p[0] = ICC_DATA_BLOCK_RET; - p[1] = len & 0xFF; - p[2] = (len >> 8)& 0xFF; - p[3] = (len >> 16)& 0xFF; - p[4] = (len >> 24)& 0xFF; - p[5] = 0x00; /* Slot */ - p[ICC_MSG_SEQ_OFFSET] = c->a->seq; - p[ICC_MSG_STATUS_OFFSET] = 0; - p[ICC_MSG_ERROR_OFFSET] = 0; - p[ICC_MSG_CHAIN_OFFSET] = 0; - p[ICC_MSG_CHAIN_OFFSET+1] = 0x90; - p[ICC_MSG_CHAIN_OFFSET+2] = 0x00; - - usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len); - c->epi->buf = NULL; - c->epi->tx_done = 1; - - usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len); -#ifdef DEBUG_MORE - DEBUG_INFO ("DATA\r\n"); -#endif -} - -static void -icc_send_data_block (struct ccid *c, uint8_t status) +icc_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error) { int tx_size = USB_LL_BUF_SIZE; uint8_t p[ICC_MSG_HEADER_SIZE]; @@ -875,7 +846,7 @@ icc_send_data_block (struct ccid *c, uint8_t status) p[5] = 0x00; /* Slot */ p[ICC_MSG_SEQ_OFFSET] = c->a->seq; p[ICC_MSG_STATUS_OFFSET] = status; - p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_ERROR_OFFSET] = error; p[ICC_MSG_CHAIN_OFFSET] = 0; usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE); @@ -933,6 +904,50 @@ icc_send_data_block (struct ccid *c, uint8_t status) #endif } +static void +icc_send_data_block (struct ccid *c) +{ + icc_send_data_block_internal (c, 0, 0); +} + +static void +icc_send_data_block_time_extension (struct ccid *c) +{ + icc_send_data_block_internal (c, ICC_CMD_STATUS_TIMEEXT, 1); +} + +static void +icc_send_data_block_0x9000 (struct ccid *c) +{ + uint8_t p[ICC_MSG_HEADER_SIZE+2]; + size_t len = 2; + + p[0] = ICC_DATA_BLOCK_RET; + p[1] = len & 0xFF; + p[2] = (len >> 8)& 0xFF; + p[3] = (len >> 16)& 0xFF; + p[4] = (len >> 24)& 0xFF; + p[5] = 0x00; /* Slot */ + p[ICC_MSG_SEQ_OFFSET] = c->a->seq; + p[ICC_MSG_STATUS_OFFSET] = 0; + p[ICC_MSG_ERROR_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET] = 0; + p[ICC_MSG_CHAIN_OFFSET+1] = 0x90; + p[ICC_MSG_CHAIN_OFFSET+2] = 0x00; + + usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len); + c->epi->buf = NULL; + c->epi->tx_done = 1; + + usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len); +#ifdef DEBUG_MORE + DEBUG_INFO ("DATA\r\n"); +#endif +} + +/* + * Reply to the host for "GET RESPONSE". + */ static void icc_send_data_block_gr (struct ccid *c, size_t chunk_len) { @@ -1260,7 +1275,7 @@ icc_handle_timeout (struct ccid *c) switch (c->icc_state) { case ICC_STATE_EXECUTE: - icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT); + icc_send_data_block_time_extension (c); led_blink (LED_ONESHOT); break; default: @@ -1311,7 +1326,7 @@ USBthread (void *arg) c->sw1sw2[0] = 0x90; c->sw1sw2[1] = 0x00; c->state = APDU_STATE_RESULT; - icc_send_data_block (c, 0); + icc_send_data_block (c); c->icc_state = ICC_STATE_EXITED; break; } @@ -1323,7 +1338,7 @@ USBthread (void *arg) if (c->a->res_apdu_data_len <= c->a->expected_res_size) { c->state = APDU_STATE_RESULT; - icc_send_data_block (c, 0); + icc_send_data_block (c); c->icc_state = ICC_STATE_WAIT; } else From f6df7701f9c64c0f4fba1251e52d8a4ce094c664 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 12 Nov 2012 10:44:44 +0900 Subject: [PATCH 270/300] add explanation for gnuk-personalization.rst --- doc/__update_web | 3 +++ doc/gnuk-personalization.rst | 24 +++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 doc/__update_web diff --git a/doc/__update_web b/doc/__update_web new file mode 100644 index 0000000..c52612d --- /dev/null +++ b/doc/__update_web @@ -0,0 +1,3 @@ +cd _build +rsync -rntpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/ +rsync -rtpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/ diff --git a/doc/gnuk-personalization.rst b/doc/gnuk-personalization.rst index 7aab551..3c1bc46 100644 --- a/doc/gnuk-personalization.rst +++ b/doc/gnuk-personalization.rst @@ -33,7 +33,22 @@ It shows the status of the card (as same as the output of ``gpg --card-status``) Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``. -Firstly, I change PIN of card user from factory setting (of "123456"). Note that, only changing PIN of user enables "admin less mode" of Gnuk. Admin password will become same one of user's. :: +In the OpenPGPcard specification, there are two passwords: one is +user-password and another is admin-password. In the specification, +user-password is refered as PW1, and admin-password is refered as PW3. + +Note that people sometimes use different words than "password" to +refer same thing, in GnuPG and its applications. For example, the +output explained above includes the word "PIN" (Personal +Identification Number), and the helper program for input is named +"pinentry". Note that it is OK (and recommended) to include +characters other than digits for the case of OpenPGPcard. + +Besides, some people sometimes prefer the word "passphrase" to +"password", as it can encourage to have longer string, but it means +same thing and it just refer user-password or admin-password. + +Firstly, I change PIN of card user from factory setting (of "123456"). Note that, by only changing user's PIN, it enables "admin less mode" of Gnuk. "Admin less mode" means that admin password will become same one of user's. That is, PW1 = PW3. Note that *the length of PIN should be more than (or equals to) 8* for "admin less mode". :: gpg/card> passwd gpg: OpenPGP card no. D276000124010200F517000000010000 detected @@ -48,6 +63,13 @@ Firstly, I change PIN of card user from factory setting (of "123456"). Note tha Repeat this PIN: PIN changed. +The "admin less mode" is Gnuk only feature, not defined in the +OpenPGPcard specification. By using "admin less mode", there will be +only a sigle password to memorize, and it will be easier if a token +is used by an individual. + +(If you want normal way ("admin full mode" in Gnuk's term), that is, user-password *and* admin-password independently, please change admin-password at first. Then, the token works as same as OpenPGPcard specification with regards to PW1 and PW3.) + Secondly, enabling admin command, I put name of mine. Note that I input user's PIN (which I set above) here, because it is "admin less mode". :: gpg/card> admin From 70846e8b812cf8076cd9e94a66082c5ed48ae6bc Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 12 Nov 2012 10:49:27 +0900 Subject: [PATCH 271/300] add explanation for gnuk-personalization.rst --- doc/gnuk-personalization.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/gnuk-personalization.rst b/doc/gnuk-personalization.rst index 3c1bc46..51d737c 100644 --- a/doc/gnuk-personalization.rst +++ b/doc/gnuk-personalization.rst @@ -64,8 +64,8 @@ Firstly, I change PIN of card user from factory setting (of "123456"). Note tha PIN changed. The "admin less mode" is Gnuk only feature, not defined in the -OpenPGPcard specification. By using "admin less mode", there will be -only a sigle password to memorize, and it will be easier if a token +OpenPGPcard specification. By using "admin less mode", it will be +only a sigle password for user to memorize, and it will be easier if a token is used by an individual. (If you want normal way ("admin full mode" in Gnuk's term), that is, user-password *and* admin-password independently, please change admin-password at first. Then, the token works as same as OpenPGPcard specification with regards to PW1 and PW3.) From f9b43a67ee5c009e7f6e84f010ae209b1b68764d Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 5 Dec 2012 14:27:15 +0900 Subject: [PATCH 272/300] Add tool/gnuk_remove_keys_libusb.py --- ChangeLog | 5 + tool/gnuk_remove_keys_libusb.py | 70 +++++++++ tool/gnuk_token.py | 251 ++++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100755 tool/gnuk_remove_keys_libusb.py create mode 100644 tool/gnuk_token.py diff --git a/ChangeLog b/ChangeLog index 8116617..151f1c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-12-05 Niibe Yutaka + + * tool/gnuk_remove_keys_libusb.py: New. + * tool/gnuk_token.py: New. + 2012-11-07 Niibe Yutaka * src/usb-icc.c (icc_send_data_block_internal): New. diff --git a/tool/gnuk_remove_keys_libusb.py b/tool/gnuk_remove_keys_libusb.py new file mode 100755 index 0000000..5692670 --- /dev/null +++ b/tool/gnuk_remove_keys_libusb.py @@ -0,0 +1,70 @@ +#! /usr/bin/python + +""" +gnuk_remove_keys_libusb.py - a tool to remove keys in Gnuk Token + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +import sys, os, string + +from gnuk_token import * + +# Assume only single CCID device is attached to computer and it's Gnuk Token + +DEFAULT_PW3 = "12345678" +BY_ADMIN = 3 + +def main(passwd): + gnuk = None + for (dev, config, intf) in gnuk_devices(): + try: + gnuk = gnuk_token(dev, config, intf) + print "Device: ", dev.filename + print "Configuration: ", config.value + print "Interface: ", intf.interfaceNumber + break + except: + pass + if gnuk.icc_get_status() == 2: + raise ValueError, "No ICC present" + elif gnuk.icc_get_status() == 1: + gnuk.icc_power_on() + gnuk.cmd_verify(BY_ADMIN, passwd) + gnuk.cmd_select_openpgp() + gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG + gnuk.cmd_put_data_remove(0x00, 0xcd) # KGTIME_SIG + gnuk.cmd_put_data_key_import_remove(1) + gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC + gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_DEC + gnuk.cmd_put_data_key_import_remove(2) + gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT + gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_AUT + gnuk.cmd_put_data_key_import_remove(3) + gnuk.icc_power_off() + return 0 + + +if __name__ == '__main__': + passwd = DEFAULT_PW3 + if sys.argv[1] == '-p': + from getpass import getpass + passwd = getpass("Admin password: ") + sys.argv.pop(1) + main(passwd) diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py new file mode 100644 index 0000000..5dedefd --- /dev/null +++ b/tool/gnuk_token.py @@ -0,0 +1,251 @@ +""" +gnuk_token.py - a library for Gnuk Token + +Copyright (C) 2011, 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +# USB class, subclass, protocol +CCID_CLASS = 0x0B +CCID_SUBCLASS = 0x00 +CCID_PROTOCOL_0 = 0x00 + +def icc_compose(msg_type, data_len, slot, seq, param, data): + return pack('BBBB', cls, ins, p1, p2) + else: + return pack('>BBBBB', cls, ins, p1, p2, data_len) + data + +# This class only supports Gnuk (for now) +class gnuk_token(object): + def __init__(self, device, configuration, interface): + """ + __init__(device, configuration, interface) -> None + Initialize the device. + device: usb.Device object. + configuration: configuration number. + interface: usb.Interface object representing the interface and altenate setting. + """ + if interface.interfaceClass != CCID_CLASS: + raise ValueError, "Wrong interface class" + if interface.interfaceSubClass != CCID_SUBCLASS: + raise ValueError, "Wrong interface sub class" + self.__devhandle = device.open() + try: + self.__devhandle.setConfiguration(configuration) + except: + pass + self.__devhandle.claimInterface(interface) + self.__devhandle.setAltInterface(interface) + + self.__intf = interface.interfaceNumber + self.__alt = interface.alternateSetting + self.__conf = configuration + + self.__bulkout = 1 + self.__bulkin = 0x81 + + self.__timeout = 10000 + self.__seq = 0 + + def icc_get_result(self): + msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) + if len(msg) < 10: + print msg + raise ValueError, "icc_get_result" + msg_type = msg[0] + data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) + slot = msg[5] + seq = msg[6] + status = msg[7] + error = msg[8] + chain = msg[9] + data = msg[10:] + # XXX: check msg_type, data_len, slot, seq, error + return (status, chain, data) + + def icc_get_status(self): + msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_power_on(self): + msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check status, chain + return data # ATR + + def icc_power_off(self): + msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data = self.icc_get_result() + # XXX: check chain, data + return status + + def icc_send_data_block(self, data): + msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + return self.icc_get_result() + + def icc_send_cmd(self, data): + status, chain, data_rcv = self.icc_send_data_block(data) + if chain == 0: + return data_rcv + elif chain == 1: + d = data_rcv + while True: + msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") + self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) + self.__seq += 1 + status, chain, data_rcv = self.icc_get_result() + # XXX: check status + d += data_rcv + if chain == 2: + break + elif chain == 3: + continue + else: + raise ValueError, "icc_send_cmd chain" + return d + else: + raise ValueError, "icc_send_cmd" + + def cmd_get_response(self, expected_len): + result = [] + while True: + cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) + response = self.icc_send_cmd(cmd_data) + result += response[:-2] + sw = response[-2:] + if sw[0] == 0x90 and sw[1] == 0x00: + return result + elif sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + else: + expected_len = sw[1] + + def cmd_verify(self, who, passwd): + cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, sw + + def cmd_read_binary(self, fileid): + cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_write_binary(self, fileid, data, is_update): + count = 0 + data_len = len(data) + if is_update: + ins = 0xd6 + else: + ins = 0xd0 + while count*256 < data_len: + if count == 0: + if len(data) < 128: + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10) + cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256]) + else: + if len(data[256*count:256*count+128]) < 128: + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128]) + cmd_data1 = None + else: + cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10) + cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError, "cmd_write_binary 0" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_write_binary 0" + if cmd_data1: + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError, "cmd_write_binary 1" + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, "cmd_write_binary 1" + count += 1 + + def cmd_select_openpgp(self): + cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + + def cmd_get_data(self, tagh, tagl): + cmd_data = iso7816_compose(0xca, tagh, tagl, "") + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError, sw + if sw[0] != 0x61: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_put_data_remove(self, tagh, tagl): + cmd_data = iso7816_compose(0xda, tagh, tagl, "") + sw = self.icc_send_cmd(cmd_data) + if sw[0] != 0x90 and sw[1] != 0x00: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + + def cmd_put_data_key_import_remove(self, keyno): + if keyno == 1: + keyspec = "\xb6\x00" # SIG + elif keyno == 2: + keyspec = "\xb8\x00" # DEC + else: + keyspec = "\xa4\x00" # AUT + cmd_data = iso7816_compose(0xdb, 0x3f, 0xff, "\x4d\x02" + keyspec) + sw = self.icc_send_cmd(cmd_data) + if sw[0] != 0x90 and sw[1] != 0x00: + raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + +def gnuk_devices(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + for config in dev.configurations: + for intf in config.interfaces: + for alt in intf: + if alt.interfaceClass == CCID_CLASS and \ + alt.interfaceSubClass == CCID_SUBCLASS and \ + alt.interfaceProtocol == CCID_PROTOCOL_0: + yield dev, config, alt From ee5b6a2a822dd8fe1d4f2ffaa9122d34d273e140 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 12 Dec 2012 15:30:40 +0900 Subject: [PATCH 273/300] fix tool/gnuk_remove_keys* --- ChangeLog | 9 +++++++++ doc/development.rst | 2 +- doc/gnuk-keytocard-noremoval.rst | 2 +- doc/gnuk-keytocard.rst | 2 +- tool/gnuk_remove_keys.py | 8 ++++---- tool/gnuk_remove_keys_libusb.py | 8 ++++---- tool/gnuk_token.py | 3 +++ 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 151f1c9..75feef4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-12-12 Niibe Yutaka + + * tool/gnuk_token.py: Add module imports. + + * tool/gnuk_remove_keys.py (main): Fix data object number + for KGTIME_SIG, KGTIME_DEC and KGTIME_AUT. + + * tool/gnuk_remove_keys_libusb.py (main): Likewise. + 2012-12-05 Niibe Yutaka * tool/gnuk_remove_keys_libusb.py: New. diff --git a/doc/development.rst b/doc/development.rst index cb0c259..2e67a5a 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -56,7 +56,7 @@ Recently, there is "gcc-arm-embedded" project. See: https://launchpad.net/gcc-arm-embedded/ It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd -need "-O3 -s" instead of "-O2" and it will be slightly better. +need "-O3 -Os" instead of "-O2" and it will be slightly better. diff --git a/doc/gnuk-keytocard-noremoval.rst b/doc/gnuk-keytocard-noremoval.rst index 0e3abb9..f350376 100644 --- a/doc/gnuk-keytocard-noremoval.rst +++ b/doc/gnuk-keytocard-noremoval.rst @@ -126,7 +126,7 @@ I type ``key 1`` to deselect key number '1'. :: ssb 2048R/5BB065DC created: 2010-10-22 expires: never (1) NIIBE Yutaka -Thirdly, I select sub key of suthentication which has key number '2'. :: +Thirdly, I select sub key of authentication which has key number '2'. :: gpg> key 2 diff --git a/doc/gnuk-keytocard.rst b/doc/gnuk-keytocard.rst index e223c16..2c49292 100644 --- a/doc/gnuk-keytocard.rst +++ b/doc/gnuk-keytocard.rst @@ -134,7 +134,7 @@ I type ``key 1`` to deselect key number '1'. :: ssb 2048R/5BB065DC created: 2010-10-22 expires: never (1) NIIBE Yutaka -Thirdly, I select sub key of suthentication which has key number '2'. :: +Thirdly, I select sub key of authentication which has key number '2'. :: gpg> key 2 diff --git a/tool/gnuk_remove_keys.py b/tool/gnuk_remove_keys.py index dfdd07c..b8e0690 100755 --- a/tool/gnuk_remove_keys.py +++ b/tool/gnuk_remove_keys.py @@ -90,13 +90,13 @@ def main(passwd): gnuk.cmd_verify(BY_ADMIN, passwd) gnuk.cmd_select_openpgp() gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG - gnuk.cmd_put_data_remove(0x00, 0xcd) # KGTIME_SIG + gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG gnuk.cmd_put_data_key_import_remove(1) gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC - gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_DEC + gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_DEC gnuk.cmd_put_data_key_import_remove(2) gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT - gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_AUT + gnuk.cmd_put_data_remove(0x00, 0xd0) # KGTIME_AUT gnuk.cmd_put_data_key_import_remove(3) gnuk.connection.disconnect() @@ -105,7 +105,7 @@ def main(passwd): if __name__ == '__main__': passwd = DEFAULT_PW3 - if sys.argv[1] == '-p': + if len(sys.argv) > 1 and sys.argv[1] == '-p': from getpass import getpass passwd = getpass("Admin password: ") sys.argv.pop(1) diff --git a/tool/gnuk_remove_keys_libusb.py b/tool/gnuk_remove_keys_libusb.py index 5692670..d04b432 100755 --- a/tool/gnuk_remove_keys_libusb.py +++ b/tool/gnuk_remove_keys_libusb.py @@ -49,13 +49,13 @@ def main(passwd): gnuk.cmd_verify(BY_ADMIN, passwd) gnuk.cmd_select_openpgp() gnuk.cmd_put_data_remove(0x00, 0xc7) # FP_SIG - gnuk.cmd_put_data_remove(0x00, 0xcd) # KGTIME_SIG + gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_SIG gnuk.cmd_put_data_key_import_remove(1) gnuk.cmd_put_data_remove(0x00, 0xc8) # FP_DEC - gnuk.cmd_put_data_remove(0x00, 0xce) # KGTIME_DEC + gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_DEC gnuk.cmd_put_data_key_import_remove(2) gnuk.cmd_put_data_remove(0x00, 0xc9) # FP_AUT - gnuk.cmd_put_data_remove(0x00, 0xcf) # KGTIME_AUT + gnuk.cmd_put_data_remove(0x00, 0xd0) # KGTIME_AUT gnuk.cmd_put_data_key_import_remove(3) gnuk.icc_power_off() return 0 @@ -63,7 +63,7 @@ def main(passwd): if __name__ == '__main__': passwd = DEFAULT_PW3 - if sys.argv[1] == '-p': + if len(sys.argv) > 1 and sys.argv[1] == '-p': from getpass import getpass passwd = getpass("Admin password: ") sys.argv.pop(1) diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index 5dedefd..95541e5 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -20,6 +20,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +from struct import * +import usb + # USB class, subclass, protocol CCID_CLASS = 0x0B CCID_SUBCLASS = 0x00 From d72a0b78930beeedce863214c8617d3075d7e019 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 14 Dec 2012 09:53:16 +0900 Subject: [PATCH 274/300] fix src/openpgp-do.c --- ChangeLog | 5 +++++ src/openpgp-do.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75feef4..733083f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-12-13 Niibe Yutaka + + * src/openpgp-do.c (gpg_do_put_data): Add GPG_SUCCESS for + completeness (it worked because of lower layer goodness). + 2012-12-12 Niibe Yutaka * tool/gnuk_token.py: Add module imports. diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 4194213..fa5625e 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1381,8 +1381,11 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len) flash_do_release (*do_data_p); if (len == 0) - /* make DO empty */ - *do_data_p = NULL; + { + /* make DO empty */ + *do_data_p = NULL; + GPG_SUCCESS (); + } else if (len > 255) GPG_MEMORY_FAILURE (); else From 12bd1161a4318446ccb57c20897cb3e00e5ecd3e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 14 Dec 2012 10:31:46 +0900 Subject: [PATCH 275/300] password length check for adminlessmode --- ChangeLog | 5 +++++ src/openpgp.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/ChangeLog b/ChangeLog index 733083f..f005323 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-12-14 Niibe Yutaka + + * src/openpgp.c (cmd_change_password): Check password length + for admin less mode. + 2012-12-13 Niibe Yutaka * src/openpgp-do.c (gpg_do_put_data): Add GPG_SUCCESS for diff --git a/src/openpgp.c b/src/openpgp.c index 439db4e..bdeef21 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -29,6 +29,8 @@ #include "openpgp.h" #include "sha256.h" +#define ADMIN_PASSWD_MINLEN 8 + #define CLS(a) a.cmd_apdu_head[0] #define INS(a) a.cmd_apdu_head[1] #define P1(a) a.cmd_apdu_head[2] @@ -259,8 +261,18 @@ cmd_change_password (void) } else { + const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3); + newpw = pw + pw_len; newpw_len = len - pw_len; + + /* Check length of password for admin-less mode. */ + if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN) + { + DEBUG_INFO ("new password length is too short."); + GPG_CONDITION_NOT_SATISFIED (); + return; + } } } else /* PW3 (0x83) */ From deccb981add007678abe9ee89a8e15b65e56875f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 10:04:45 +0900 Subject: [PATCH 276/300] minor: fix style --- src/openpgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openpgp.c b/src/openpgp.c index bdeef21..7888e80 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -236,7 +236,7 @@ cmd_change_password (void) if (p1 != 0) { - GPG_FUNCTION_NOT_SUPPORTED(); + GPG_FUNCTION_NOT_SUPPORTED (); return; } From 40e234b799632fb9f5799de34297a85b841cce55 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 10:44:50 +0900 Subject: [PATCH 277/300] Use tool/gnuk_token.py --- ChangeLog | 23 ++ test/features/steps.py | 2 +- test/gnuk.py | 407 --------------------------------- test/gnuk_token.py | 1 + tool/gnuk_put_binary_libusb.py | 248 ++------------------ tool/gnuk_token.py | 214 +++++++++++++++-- 6 files changed, 229 insertions(+), 666 deletions(-) delete mode 100644 test/gnuk.py create mode 120000 test/gnuk_token.py diff --git a/ChangeLog b/ChangeLog index f005323..ccc17a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-12-19 Niibe Yutaka + + * test/features/steps.py: Use tool/gnuk_token.py. + + * tool/gnuk_put_binary_libusb.py: Use gnuk_token.py. + (main): Follow the API change. + + * tool/gnuk_token.py (list_to_string): New. + (gnuk_token.get_string, gnuk_token.increment_seq) + (gnuk_token.reset_device, gnuk_token.release_gnuk): New. + (gnuk_token.icc_power_on): Set self.atr and it's now string. + (gnuk_token.icc_send_cmd): Handle time extension. + (gnuk_token.cmd_get_response): Return string (was: list). + (gnuk_token.cmd_get_data): Return "" when success. + (gnuk_token.cmd_change_reference_data, gnuk_token.cmd_put_data) + (gnuk_token.cmd_put_data_odd) + (gnuk_token.cmd_reset_retry_counter, gnuk_token.cmd_pso) + (gnuk_token.cmd_pso_longdata) + (gnuk_token.cmd_internal_authenticate, gnuk_token.cmd_genkey) + (gnuk_token.cmd_get_public_key): New. + (compare): New. + (get_gnuk_device): New. + 2012-12-14 Niibe Yutaka * src/openpgp.c (cmd_change_password): Check password length diff --git a/test/features/steps.py b/test/features/steps.py index 70e3046..dc915e2 100644 --- a/test/features/steps.py +++ b/test/features/steps.py @@ -5,7 +5,7 @@ from binascii import hexlify import ast -import gnuk +import gnuk_token as gnuk import rsa_keys @Before diff --git a/test/gnuk.py b/test/gnuk.py deleted file mode 100644 index 13a9320..0000000 --- a/test/gnuk.py +++ /dev/null @@ -1,407 +0,0 @@ -""" -gnuk.py - a library for Gnuk Token -This tool is for importing certificate, writing serial number, etc. - -Copyright (C) 2011, 2012 Free Software Initiative of Japan -Author: NIIBE Yutaka - -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 . -""" - -from struct import * -import string - -# Assume only single CCID device is attached to computer, and it's Gnuk Token - -import usb - -# USB class, subclass, protocol -CCID_CLASS = 0x0B -CCID_SUBCLASS = 0x00 -CCID_PROTOCOL_0 = 0x00 - -def icc_compose(msg_type, data_len, slot, seq, param, data): - return pack('BBBB', cls, ins, p1, p2) - else: - return pack('>BBBBB', cls, ins, p1, p2, data_len) + data - -def list_to_string(l): - return string.join([chr(c) for c in l], '') - -class gnuk_token(object): - def __init__(self, device, configuration, interface): - """ - __init__(device, configuration, interface) -> None - Initialize the device. - device: usb.Device object. - configuration: configuration number. - interface: usb.Interface object representing the interface and altenate setting. - """ - if interface.interfaceClass != CCID_CLASS: - raise ValueError("Wrong interface class") - if interface.interfaceSubClass != CCID_SUBCLASS: - raise ValueError("Wrong interface sub class") - self.__devhandle = device.open() - try: - self.__devhandle.setConfiguration(configuration) - except: - pass - self.__devhandle.claimInterface(interface) - self.__devhandle.setAltInterface(interface) - - self.__intf = interface.interfaceNumber - self.__alt = interface.alternateSetting - self.__conf = configuration - - self.__bulkout = 1 - self.__bulkin = 0x81 - - self.__timeout = 10000 - self.__seq = 0 - - def get_string(self, num): - return self.__devhandle.getString(num, 512) - - def increment_seq(self): - self.__seq = (self.__seq + 1) & 0xff - - def reset_device(self): - try: - self.__devhandle.reset() - except: - pass - - def release_gnuk(self): - self.__devhandle.releaseInterface() - - def icc_get_result(self): - msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) - if len(msg) < 10: - print msg - raise ValueError("icc_get_result") - msg_type = msg[0] - data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) - slot = msg[5] - seq = msg[6] - status = msg[7] - error = msg[8] - chain = msg[9] - data = msg[10:] - # XXX: check msg_type, data_len, slot, seq, error - return (status, chain, data) - - def icc_get_status(self): - msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.increment_seq() - status, chain, data = self.icc_get_result() - # XXX: check chain, data - return status - - def icc_power_on(self): - msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.increment_seq() - status, chain, data = self.icc_get_result() - # XXX: check status, chain - self.atr = list_to_string(data) # ATR - - def icc_power_off(self): - msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.increment_seq() - status, chain, data = self.icc_get_result() - # XXX: check chain, data - return status - - def icc_send_data_block(self, data): - msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.increment_seq() - return self.icc_get_result() - - def icc_send_cmd(self, data): - status, chain, data_rcv = self.icc_send_data_block(data) - if chain == 0: - while status == 0x80: - status, chain, data_rcv = self.icc_get_result() - return data_rcv - elif chain == 1: - d = data_rcv - while True: - msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.increment_seq() - status, chain, data_rcv = self.icc_get_result() - # XXX: check status - d += data_rcv - if chain == 2: - break - elif chain == 3: - continue - else: - raise ValueError("icc_send_cmd chain") - return d - else: - raise ValueError("icc_send_cmd") - - def cmd_get_response(self, expected_len): - result = [] - while True: - cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) - response = self.icc_send_cmd(cmd_data) - result += response[:-2] - sw = response[-2:] - if sw[0] == 0x90 and sw[1] == 0x00: - return list_to_string(result) - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - else: - expected_len = sw[1] - - def cmd_verify(self, who, passwd): - cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_read_binary(self, fileid): - cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_write_binary(self, fileid, data, is_update): - count = 0 - data_len = len(data) - if is_update: - ins = 0xd6 - else: - ins = 0xd0 - while count*256 < data_len: - if count == 0: - if len(data) < 128: - cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10) - cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256]) - else: - if len(data[256*count:256*count+128]) < 128: - cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) - sw = self.icc_send_cmd(cmd_data0) - if len(sw) != 2: - raise ValueError("cmd_write_binary 0") - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("cmd_write_binary 0", "%02x%02x" % (sw[0], sw[1])) - if cmd_data1: - sw = self.icc_send_cmd(cmd_data1) - if len(sw) != 2: - raise ValueError("cmd_write_binary", sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("cmd_write_binary", "%02x%02x" % (sw[0], sw[1])) - count += 1 - - def cmd_select_openpgp(self): - cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_get_data(self, tagh, tagl): - cmd_data = iso7816_compose(0xca, tagh, tagl, "") - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if sw[0] == 0x90 and sw[1] == 0x00: - return "" - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_change_reference_data(self, who, data): - cmd_data = iso7816_compose(0x24, 0x00, 0x80+who, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_put_data(self, tagh, tagl, content): - cmd_data = iso7816_compose(0xda, tagh, tagl, content) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_put_data_odd(self, tagh, tagl, content): - cmd_data0 = iso7816_compose(0xdb, tagh, tagl, content[:128], 0x10) - cmd_data1 = iso7816_compose(0xdb, tagh, tagl, content[128:]) - sw = self.icc_send_cmd(cmd_data0) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - sw = self.icc_send_cmd(cmd_data1) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_reset_retry_counter(self, how, data): - cmd_data = iso7816_compose(0x2c, how, 0x00, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return True - - def cmd_pso(self, p1, p2, data): - cmd_data = iso7816_compose(0x2a, p1, p2, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if sw[0] == 0x90 and sw[1] == 0x00: - return "" - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_pso_longdata(self, p1, p2, data): - cmd_data0 = iso7816_compose(0x2a, p1, p2, data[:128], 0x10) - cmd_data1 = iso7816_compose(0x2a, p1, p2, data[128:]) - sw = self.icc_send_cmd(cmd_data0) - if len(sw) != 2: - raise ValueError(sw) - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError("%02x%02x" % (sw[0], sw[1])) - sw = self.icc_send_cmd(cmd_data1) - if len(sw) != 2: - raise ValueError(sw) - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_internal_authenticate(self, data): - cmd_data = iso7816_compose(0x88, 0, 0, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if sw[0] == 0x90 and sw[1] == 0x00: - return "" - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_genkey(self, keyno): - if keyno == 1: - data = '\xb6\x00' - elif keyno == 2: - data = '\xb8\x00' - else: - data = '\xa4\x00' - cmd_data = iso7816_compose(0x47, 0x80, 0, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - if sw[0] == 0x90 and sw[1] == 0x00: - return "" - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - pk = self.cmd_get_response(sw[1]) - return (pk[9:9+256], pk[9+256+2:9+256+2+3]) - - def cmd_get_public_key(self, keyno): - if keyno == 1: - data = '\xb6\x00' - elif keyno == 2: - data = '\xb8\x00' - else: - data = '\xa4\x00' - cmd_data = iso7816_compose(0x47, 0x81, 0, data) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError(sw) - elif sw[0] != 0x61: - raise ValueError("%02x%02x" % (sw[0], sw[1])) - pk = self.cmd_get_response(sw[1]) - return (pk[9:9+256], pk[9+256+2:9+256+2+3]) - - -def compare(data_original, data_in_device): - i = 0 - for d in data_original: - if ord(d) != data_in_device[i]: - raise ValueError, "verify failed at %08x" % i - i += 1 - -def gnuk_devices(): - busses = usb.busses() - for bus in busses: - devices = bus.devices - for dev in devices: - for config in dev.configurations: - for intf in config.interfaces: - for alt in intf: - if alt.interfaceClass == CCID_CLASS and \ - alt.interfaceSubClass == CCID_SUBCLASS and \ - alt.interfaceProtocol == CCID_PROTOCOL_0: - yield dev, config, alt - -def get_gnuk_device(): - icc = None - for (dev, config, intf) in gnuk_devices(): - try: - icc = gnuk_token(dev, config, intf) - print "Device: ", dev.filename - print "Configuration: ", config.value - print "Interface: ", intf.interfaceNumber - break - except: - pass - if not icc: - raise ValueError("No ICC present") - status = icc.icc_get_status() - if status == 0: - pass # It's ON already - elif status == 1: - icc.icc_power_on() - else: - raise ValueError("Unknown ICC status", status) - return icc diff --git a/test/gnuk_token.py b/test/gnuk_token.py new file mode 120000 index 0000000..c89e721 --- /dev/null +++ b/test/gnuk_token.py @@ -0,0 +1 @@ +../tool/gnuk_token.py \ No newline at end of file diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 5b1455f..057a4b9 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -25,266 +25,46 @@ along with this program. If not, see . from struct import * import sys, time, os, binascii, string +from gnuk_token import * # INPUT: binary file # Assume only single CCID device is attached to computer, and it's Gnuk Token -import usb - -# USB class, subclass, protocol -CCID_CLASS = 0x0B -CCID_SUBCLASS = 0x00 -CCID_PROTOCOL_0 = 0x00 - -def icc_compose(msg_type, data_len, slot, seq, param, data): - return pack('BBBB', cls, ins, p1, p2) - else: - return pack('>BBBBB', cls, ins, p1, p2, data_len) + data - -# This class only supports Gnuk (for now) -class gnuk_token(object): - def __init__(self, device, configuration, interface): - """ - __init__(device, configuration, interface) -> None - Initialize the device. - device: usb.Device object. - configuration: configuration number. - interface: usb.Interface object representing the interface and altenate setting. - """ - if interface.interfaceClass != CCID_CLASS: - raise ValueError, "Wrong interface class" - if interface.interfaceSubClass != CCID_SUBCLASS: - raise ValueError, "Wrong interface sub class" - self.__devhandle = device.open() - try: - self.__devhandle.setConfiguration(configuration) - except: - pass - self.__devhandle.claimInterface(interface) - self.__devhandle.setAltInterface(interface) - - self.__intf = interface.interfaceNumber - self.__alt = interface.alternateSetting - self.__conf = configuration - - self.__bulkout = 1 - self.__bulkin = 0x81 - - self.__timeout = 10000 - self.__seq = 0 - - def icc_get_result(self): - msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) - if len(msg) < 10: - print msg - raise ValueError, "icc_get_result" - msg_type = msg[0] - data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) - slot = msg[5] - seq = msg[6] - status = msg[7] - error = msg[8] - chain = msg[9] - data = msg[10:] - # XXX: check msg_type, data_len, slot, seq, error - return (status, chain, data) - - def icc_get_status(self): - msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 - status, chain, data = self.icc_get_result() - # XXX: check chain, data - return status - - def icc_power_on(self): - msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 - status, chain, data = self.icc_get_result() - # XXX: check status, chain - return data # ATR - - def icc_power_off(self): - msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 - status, chain, data = self.icc_get_result() - # XXX: check chain, data - return status - - def icc_send_data_block(self, data): - msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 - return self.icc_get_result() - - def icc_send_cmd(self, data): - status, chain, data_rcv = self.icc_send_data_block(data) - if chain == 0: - return data_rcv - elif chain == 1: - d = data_rcv - while True: - msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") - self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 - status, chain, data_rcv = self.icc_get_result() - # XXX: check status - d += data_rcv - if chain == 2: - break - elif chain == 3: - continue - else: - raise ValueError, "icc_send_cmd chain" - return d - else: - raise ValueError, "icc_send_cmd" - - def cmd_get_response(self, expected_len): - result = [] - while True: - cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len) - response = self.icc_send_cmd(cmd_data) - result += response[:-2] - sw = response[-2:] - if sw[0] == 0x90 and sw[1] == 0x00: - return result - elif sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) - else: - expected_len = sw[1] - - def cmd_verify(self, who, passwd): - cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, sw - - def cmd_read_binary(self, fileid): - cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - - def cmd_write_binary(self, fileid, data, is_update): - count = 0 - data_len = len(data) - if is_update: - ins = 0xd6 - else: - ins = 0xd0 - while count*256 < data_len: - if count == 0: - if len(data) < 128: - cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(ins, 0x80+fileid, 0x00, data[:128], 0x10) - cmd_data1 = iso7816_compose(ins, 0x80+fileid, 0x00, data[128:256]) - else: - if len(data[256*count:256*count+128]) < 128: - cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128]) - cmd_data1 = None - else: - cmd_data0 = iso7816_compose(ins, count, 0x00, data[256*count:256*count+128], 0x10) - cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) - sw = self.icc_send_cmd(cmd_data0) - if len(sw) != 2: - raise ValueError, "cmd_write_binary 0" - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 0" - if cmd_data1: - sw = self.icc_send_cmd(cmd_data1) - if len(sw) != 2: - raise ValueError, "cmd_write_binary 1" - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 1" - count += 1 - - def cmd_select_openpgp(self): - cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01") - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) - - def cmd_get_data(self, tagh, tagl): - cmd_data = iso7816_compose(0xca, tagh, tagl, "") - sw = self.icc_send_cmd(cmd_data) - if len(sw) != 2: - raise ValueError, sw - if sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) - return self.cmd_get_response(sw[1]) - -def compare(data_original, data_in_device): - i = 0 - for d in data_original: - if ord(d) != data_in_device[i]: - raise ValueError, "verify failed at %08x" % i - i += 1 - -def gnuk_devices(): - busses = usb.busses() - for bus in busses: - devices = bus.devices - for dev in devices: - for config in dev.configurations: - for intf in config.interfaces: - for alt in intf: - if alt.interfaceClass == CCID_CLASS and \ - alt.interfaceSubClass == CCID_SUBCLASS and \ - alt.interfaceProtocol == CCID_PROTOCOL_0: - yield dev, config, alt - DEFAULT_PW3 = "12345678" BY_ADMIN = 3 def main(fileid, is_update, data, passwd): - icc = None + gnuk = None for (dev, config, intf) in gnuk_devices(): try: - icc = gnuk_token(dev, config, intf) + gnuk = gnuk_token(dev, config, intf) print "Device: ", dev.filename print "Configuration: ", config.value print "Interface: ", intf.interfaceNumber break except: pass - if icc.icc_get_status() == 2: + if gnuk.icc_get_status() == 2: raise ValueError, "No ICC present" - elif icc.icc_get_status() == 1: - icc.icc_power_on() - icc.cmd_verify(BY_ADMIN, passwd) - icc.cmd_write_binary(fileid, data, is_update) - icc.cmd_select_openpgp() + elif gnuk.icc_get_status() == 1: + gnuk.icc_power_on() + gnuk.cmd_verify(BY_ADMIN, passwd) + gnuk.cmd_write_binary(fileid, data, is_update) + gnuk.cmd_select_openpgp() if fileid == 0: - data_in_device = icc.cmd_get_data(0x00, 0x4f) + data_in_device = gnuk.cmd_get_data(0x00, 0x4f) for d in data_in_device: - print "%02x" % d, + print "%02x" % ord(d), print compare(data, data_in_device[8:]) elif fileid >= 1 and fileid <= 4: - data_in_device = icc.cmd_read_binary(fileid) + data_in_device = gnuk.cmd_read_binary(fileid) compare(data, data_in_device) else: - data_in_device = icc.cmd_get_data(0x7f, 0x21) + data_in_device = gnuk.cmd_get_data(0x7f, 0x21) compare(data, data_in_device) - icc.icc_power_off() + gnuk.icc_power_off() return 0 if __name__ == '__main__': diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index 95541e5..d1ce053 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -21,6 +21,7 @@ along with this program. If not, see . """ from struct import * +import string import usb # USB class, subclass, protocol @@ -38,6 +39,9 @@ def iso7816_compose(ins, p1, p2, data, cls=0x00): else: return pack('>BBBBB', cls, ins, p1, p2, data_len) + data +def list_to_string(l): + return string.join([chr(c) for c in l], '') + # This class only supports Gnuk (for now) class gnuk_token(object): def __init__(self, device, configuration, interface): @@ -49,9 +53,9 @@ class gnuk_token(object): interface: usb.Interface object representing the interface and altenate setting. """ if interface.interfaceClass != CCID_CLASS: - raise ValueError, "Wrong interface class" + raise ValueError("Wrong interface class") if interface.interfaceSubClass != CCID_SUBCLASS: - raise ValueError, "Wrong interface sub class" + raise ValueError("Wrong interface sub class") self.__devhandle = device.open() try: self.__devhandle.setConfiguration(configuration) @@ -70,11 +74,26 @@ class gnuk_token(object): self.__timeout = 10000 self.__seq = 0 + def get_string(self, num): + return self.__devhandle.getString(num, 512) + + def increment_seq(self): + self.__seq = (self.__seq + 1) & 0xff + + def reset_device(self): + try: + self.__devhandle.reset() + except: + pass + + def release_gnuk(self): + self.__devhandle.releaseInterface() + def icc_get_result(self): msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) if len(msg) < 10: print msg - raise ValueError, "icc_get_result" + raise ValueError("icc_get_result") msg_type = msg[0] data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24) slot = msg[5] @@ -89,7 +108,7 @@ class gnuk_token(object): def icc_get_status(self): msg = icc_compose(0x65, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check chain, data return status @@ -97,15 +116,16 @@ class gnuk_token(object): def icc_power_on(self): msg = icc_compose(0x62, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check status, chain - return data # ATR + self.atr = list_to_string(data) # ATR + return self.atr def icc_power_off(self): msg = icc_compose(0x63, 0, 0, self.__seq, 0, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data = self.icc_get_result() # XXX: check chain, data return status @@ -113,19 +133,21 @@ class gnuk_token(object): def icc_send_data_block(self, data): msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data) self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() return self.icc_get_result() def icc_send_cmd(self, data): status, chain, data_rcv = self.icc_send_data_block(data) if chain == 0: + while status == 0x80: + status, chain, data_rcv = self.icc_get_result() return data_rcv elif chain == 1: d = data_rcv while True: msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "") self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout) - self.__seq += 1 + self.increment_seq() status, chain, data_rcv = self.icc_get_result() # XXX: check status d += data_rcv @@ -134,10 +156,10 @@ class gnuk_token(object): elif chain == 3: continue else: - raise ValueError, "icc_send_cmd chain" + raise ValueError("icc_send_cmd chain") return d else: - raise ValueError, "icc_send_cmd" + raise ValueError("icc_send_cmd") def cmd_get_response(self, expected_len): result = [] @@ -147,9 +169,9 @@ class gnuk_token(object): result += response[:-2] sw = response[-2:] if sw[0] == 0x90 and sw[1] == 0x00: - return result + return list_to_string(result) elif sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + raise ValueError("%02x%02x" % (sw[0], sw[1])) else: expected_len = sw[1] @@ -157,17 +179,18 @@ class gnuk_token(object): cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, sw + raise ValueError(sw) if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, sw + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True def cmd_read_binary(self, fileid): cmd_data = iso7816_compose(0xb0, 0x80+fileid, 0x00, '') sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: - raise ValueError, sw + raise ValueError(sw) if sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + raise ValueError("%02x%02x" % (sw[0], sw[1])) return self.cmd_get_response(sw[1]) def cmd_write_binary(self, fileid, data, is_update): @@ -194,15 +217,15 @@ class gnuk_token(object): cmd_data1 = iso7816_compose(ins, count, 0x00, data[256*count+128:256*(count+1)]) sw = self.icc_send_cmd(cmd_data0) if len(sw) != 2: - raise ValueError, "cmd_write_binary 0" + raise ValueError("cmd_write_binary 0") if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 0" + raise ValueError("cmd_write_binary 0", "%02x%02x" % (sw[0], sw[1])) if cmd_data1: sw = self.icc_send_cmd(cmd_data1) if len(sw) != 2: - raise ValueError, "cmd_write_binary 1" + raise ValueError("cmd_write_binary 1", sw) if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, "cmd_write_binary 1" + raise ValueError("cmd_write_binary 1", "%02x%02x" % (sw[0], sw[1])) count += 1 def cmd_select_openpgp(self): @@ -211,17 +234,133 @@ class gnuk_token(object): if len(sw) != 2: raise ValueError, sw if not (sw[0] == 0x90 and sw[1] == 0x00): - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True def cmd_get_data(self, tagh, tagl): cmd_data = iso7816_compose(0xca, tagh, tagl, "") sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: raise ValueError, sw - if sw[0] != 0x61: - raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) return self.cmd_get_response(sw[1]) + def cmd_change_reference_data(self, who, data): + cmd_data = iso7816_compose(0x24, 0x00, 0x80+who, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_put_data(self, tagh, tagl, content): + cmd_data = iso7816_compose(0xda, tagh, tagl, content) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_put_data_odd(self, tagh, tagl, content): + cmd_data0 = iso7816_compose(0xdb, tagh, tagl, content[:128], 0x10) + cmd_data1 = iso7816_compose(0xdb, tagh, tagl, content[128:]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_reset_retry_counter(self, how, data): + cmd_data = iso7816_compose(0x2c, how, 0x00, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return True + + def cmd_pso(self, p1, p2, data): + cmd_data = iso7816_compose(0x2a, p1, p2, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_pso_longdata(self, p1, p2, data): + cmd_data0 = iso7816_compose(0x2a, p1, p2, data[:128], 0x10) + cmd_data1 = iso7816_compose(0x2a, p1, p2, data[128:]) + sw = self.icc_send_cmd(cmd_data0) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + sw = self.icc_send_cmd(cmd_data1) + if len(sw) != 2: + raise ValueError(sw) + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_internal_authenticate(self, data): + cmd_data = iso7816_compose(0x88, 0, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_genkey(self, keyno): + if keyno == 1: + data = '\xb6\x00' + elif keyno == 2: + data = '\xb8\x00' + else: + data = '\xa4\x00' + cmd_data = iso7816_compose(0x47, 0x80, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] == 0x90 and sw[1] == 0x00: + return "" + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + pk = self.cmd_get_response(sw[1]) + return (pk[9:9+256], pk[9+256+2:9+256+2+3]) + + def cmd_get_public_key(self, keyno): + if keyno == 1: + data = '\xb6\x00' + elif keyno == 2: + data = '\xb8\x00' + else: + data = '\xa4\x00' + cmd_data = iso7816_compose(0x47, 0x81, 0, data) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + elif sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + pk = self.cmd_get_response(sw[1]) + return (pk[9:9+256], pk[9+256+2:9+256+2+3]) + def cmd_put_data_remove(self, tagh, tagl): cmd_data = iso7816_compose(0xda, tagh, tagl, "") sw = self.icc_send_cmd(cmd_data) @@ -240,6 +379,11 @@ class gnuk_token(object): if sw[0] != 0x90 and sw[1] != 0x00: raise ValueError, ("%02x%02x" % (sw[0], sw[1])) +def compare(data_original, data_in_device): + if data_original == data_in_device: + return True + raise ValueError("verify failed") + def gnuk_devices(): busses = usb.busses() for bus in busses: @@ -252,3 +396,25 @@ def gnuk_devices(): alt.interfaceSubClass == CCID_SUBCLASS and \ alt.interfaceProtocol == CCID_PROTOCOL_0: yield dev, config, alt + +def get_gnuk_device(): + icc = None + for (dev, config, intf) in gnuk_devices(): + try: + icc = gnuk_token(dev, config, intf) + print "Device: ", dev.filename + print "Configuration: ", config.value + print "Interface: ", intf.interfaceNumber + break + except: + pass + if not icc: + raise ValueError("No ICC present") + status = icc.icc_get_status() + if status == 0: + pass # It's ON already + elif status == 1: + icc.icc_power_on() + else: + raise ValueError("Unknown ICC status", status) + return icc From 1a2560531db8c0b1f8375bf21eb077f5767923d8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 11:19:17 +0900 Subject: [PATCH 278/300] fix --- ChangeLog | 2 ++ tool/gnuk_put_binary_libusb.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ccc17a0..18c86bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2012-12-19 Niibe Yutaka + * test/gnuk.py: Remove. + * test/features/steps.py: Use tool/gnuk_token.py. * tool/gnuk_put_binary_libusb.py: Use gnuk_token.py. diff --git a/tool/gnuk_put_binary_libusb.py b/tool/gnuk_put_binary_libusb.py index 057a4b9..3899c4c 100755 --- a/tool/gnuk_put_binary_libusb.py +++ b/tool/gnuk_put_binary_libusb.py @@ -57,7 +57,7 @@ def main(fileid, is_update, data, passwd): for d in data_in_device: print "%02x" % ord(d), print - compare(data, data_in_device[8:]) + compare(data + '\x00\x00', data_in_device[8:]) elif fileid >= 1 and fileid <= 4: data_in_device = gnuk.cmd_read_binary(fileid) compare(data, data_in_device) From fe6337f9888f7a3d4dbed4c5568a8ba898c39a35 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 12:57:36 +0900 Subject: [PATCH 279/300] new methods for gnuk_token.py --- ChangeLog | 8 +++++ tool/gnuk_token.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/ChangeLog b/ChangeLog index 18c86bf..8731d7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2012-12-19 Niibe Yutaka + * tool/gnuk_token.py (gnuk_token.stop_gnuk, gnuk_token.mem_info) + (gnuk_token.download, gnuk_token.execute) + (gnuk_token.cmd_get_challenge) + (gnuk_token.cmd_external_authenticate): New. + (gnuk_devices_by_vidpid): New. + +2012-12-18 Niibe Yutaka + * test/gnuk.py: Remove. * test/features/steps.py: Use tool/gnuk_token.py. diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index d1ce053..15e84b7 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -89,6 +89,50 @@ class gnuk_token(object): def release_gnuk(self): self.__devhandle.releaseInterface() + def stop_gnuk(self): + self.__devhandle.releaseInterface() + self.__devhandle.setConfiguration(0) + return + + def mem_info(self): + mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0, + value = 0, index = 0, buffer = 8, + timeout = 10) + start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0] + end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4] + return (start, end) + + def download(self, start, data): + addr = start + addr_end = (start + len(data)) & 0xffffff00 + i = (addr - 0x20000000) / 0x100 + j = 0 + print "start %08x" % addr + print "end %08x" % addr_end + while addr < addr_end: + print "# %08x: %d : %d" % (addr, i, 256) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = i, index = 0, + buffer = data[j*256:j*256+256], + timeout = 10) + i = i+1 + j = j+1 + addr = addr + 256 + residue = len(data) % 256 + if residue != 0: + print "# %08x: %d : %d" % (addr, i, residue) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = i, index = 0, + buffer = data[j*256:], + timeout = 10) + + def execute(self, last_addr): + i = (last_addr - 0x20000000) / 0x100 + o = (last_addr - 0x20000000) % 0x100 + self.__devhandle.controlMsg(requestType = 0x40, request = 2, + value = i, index = o, buffer = None, + timeout = 10) + def icc_get_result(self): msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout) if len(msg) < 10: @@ -379,6 +423,30 @@ class gnuk_token(object): if sw[0] != 0x90 and sw[1] != 0x00: raise ValueError, ("%02x%02x" % (sw[0], sw[1])) + def cmd_get_challenge(self): + cmd_data = iso7816_compose(0x84, 0x00, 0x00, '') + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if sw[0] != 0x61: + raise ValueError("%02x%02x" % (sw[0], sw[1])) + return self.cmd_get_response(sw[1]) + + def cmd_external_authenticate(self, signed): + cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[0:128], cls=0x10) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[128:]) + sw = self.icc_send_cmd(cmd_data) + if len(sw) != 2: + raise ValueError(sw) + if not (sw[0] == 0x90 and sw[1] == 0x00): + raise ValueError("%02x%02x" % (sw[0], sw[1])) + + def compare(data_original, data_in_device): if data_original == data_in_device: return True @@ -397,6 +465,20 @@ def gnuk_devices(): alt.interfaceProtocol == CCID_PROTOCOL_0: yield dev, config, alt +USB_VENDOR_FSIJ=0x234b +USB_PRODUCT_GNUK=0x0000 + +def gnuk_devices_by_vidpid(): + busses = usb.busses() + for bus in busses: + devices = bus.devices + for dev in devices: + if dev.idVendor != USB_VENDOR_FSIJ: + continue + if dev.idProduct != USB_PRODUCT_GNUK: + continue + yield dev + def get_gnuk_device(): icc = None for (dev, config, intf) in gnuk_devices(): From 22d0cb689a42c454a4c8d0f2c99f887fc59d6d00 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 13:13:52 +0900 Subject: [PATCH 280/300] add regnual class --- ChangeLog | 1 + tool/gnuk_token.py | 106 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8731d7c..3f1b2fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ (gnuk_token.cmd_get_challenge) (gnuk_token.cmd_external_authenticate): New. (gnuk_devices_by_vidpid): New. + (regnual): New. 2012-12-18 Niibe Yutaka diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index 15e84b7..78de09d 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -447,6 +447,112 @@ class gnuk_token(object): raise ValueError("%02x%02x" % (sw[0], sw[1])) +class regnual(object): + def __init__(self, dev): + conf = dev.configurations[0] + intf_alt = conf.interfaces[0] + intf = intf_alt[0] + if intf.interfaceClass != 0xff: + raise ValueError("Wrong interface class") + self.__devhandle = dev.open() + try: + self.__devhandle.setConfiguration(conf) + except: + pass + self.__devhandle.claimInterface(intf) + self.__devhandle.setAltInterface(intf) + + def mem_info(self): + mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0, + value = 0, index = 0, buffer = 8, + timeout = 10000) + start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0] + end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4] + return (start, end) + + def download(self, start, data): + addr = start + addr_end = (start + len(data)) & 0xffffff00 + i = (addr - 0x08000000) / 0x100 + j = 0 + print "start %08x" % addr + print "end %08x" % addr_end + while addr < addr_end: + print "# %08x: %d: %d : %d" % (addr, i, j, 256) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = 0, index = 0, + buffer = data[j*256:j*256+256], + timeout = 10000) + crc32code = crc32(data[j*256:j*256+256]) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" + self.__devhandle.controlMsg(requestType = 0x40, request = 3, + value = i, index = 0, + buffer = None, + timeout = 10000) + time.sleep(0.010) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "failure" + i = i+1 + j = j+1 + addr = addr + 256 + residue = len(data) % 256 + if residue != 0: + print "# %08x: %d : %d" % (addr, i, residue) + self.__devhandle.controlMsg(requestType = 0x40, request = 1, + value = 0, index = 0, + buffer = data[j*256:], + timeout = 10000) + crc32code = crc32(data[j*256:].ljust(256,chr(255))) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if (crc32code ^ r_value) != 0xffffffff: + print "failure" + self.__devhandle.controlMsg(requestType = 0x40, request = 3, + value = i, index = 0, + buffer = None, + timeout = 10000) + time.sleep(0.010) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "failure" + + def protect(self): + self.__devhandle.controlMsg(requestType = 0x40, request = 4, + value = 0, index = 0, buffer = None, + timeout = 10000) + time.sleep(0.100) + res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2, + value = 0, index = 0, buffer = 4, + timeout = 10000) + r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0] + if r_value == 0: + print "protection failure" + + def finish(self): + self.__devhandle.controlMsg(requestType = 0x40, request = 5, + value = 0, index = 0, buffer = None, + timeout = 10000) + + def reset_device(self): + try: + self.__devhandle.reset() + except: + pass + def compare(data_original, data_in_device): if data_original == data_in_device: return True From 4bfe0875834a630e33c0d89054a90183aa47e5b2 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 15:53:07 +0900 Subject: [PATCH 281/300] add test/factory_upgrade.py --- ChangeLog | 4 ++ src/Makefile.in | 2 +- test/factory_upgrade.py | 111 ++++++++++++++++++++++++++++++++++++++++ tool/gnuk_token.py | 13 ++++- 4 files changed, 127 insertions(+), 3 deletions(-) create mode 100755 test/factory_upgrade.py diff --git a/ChangeLog b/ChangeLog index 3f1b2fb..5050e14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2012-12-19 Niibe Yutaka + * test/factory_upgrade.py: New. + + * src/Makefile.in (USE_OPT): -O3 and -Os (was: -O2). + * tool/gnuk_token.py (gnuk_token.stop_gnuk, gnuk_token.mem_info) (gnuk_token.download, gnuk_token.execute) (gnuk_token.cmd_get_challenge) diff --git a/src/Makefile.in b/src/Makefile.in index 3f73460..3f5a094 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -11,7 +11,7 @@ BOARD_DIR=@BOARD_DIR@ # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 + USE_OPT = -O3 -Os -ggdb -fomit-frame-pointer -falign-functions=16 endif # C++ specific options here (added to USE_OPT). diff --git a/test/factory_upgrade.py b/test/factory_upgrade.py new file mode 100755 index 0000000..2234a92 --- /dev/null +++ b/test/factory_upgrade.py @@ -0,0 +1,111 @@ +#! /usr/bin/python + +""" +factory_upgrade.py - a tool to install another firmware for Gnuk Token + which is just shipped from factory + +Copyright (C) 2012 Free Software Initiative of Japan +Author: NIIBE Yutaka + +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 . +""" + +from gnuk_token import * +import sys, binascii, time, os + +DEFAULT_PW3 = "12345678" +BY_ADMIN = 3 + +KEYNO_FOR_AUTH=2 + +def main(passwd, data_regnual, data_upgrade): + l = len(data_regnual) + if (l & 0x03) != 0: + data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0)) + crc32code = crc32(data_regnual) + print "CRC32: %04x\n" % crc32code + data_regnual += pack(' 1 and sys.argv[1] == '-p': + from getpass import getpass + passwd = getpass("Admin password: ") + sys.argv.pop(1) + filename_regnual = sys.argv[1] + filename_upgrade = sys.argv[2] + f = open(filename_regnual) + data_regnual = f.read() + f.close() + print "%s: %d" % (filename_regnual, len(data_regnual)) + f = open(filename_upgrade) + data_upgrade = f.read() + f.close() + print "%s: %d" % (filename_upgrade, len(data_upgrade)) + # First 4096-byte in data_upgrade is SYS, so, skip it. + main(passwd, data_regnual, data_upgrade[4096:]) diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index 78de09d..f60e6aa 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -21,8 +21,8 @@ along with this program. If not, see . """ from struct import * -import string -import usb +import string, binascii +import usb, time # USB class, subclass, protocol CCID_CLASS = 0x0B @@ -606,3 +606,12 @@ def get_gnuk_device(): else: raise ValueError("Unknown ICC status", status) return icc + +SHA256_OID_PREFIX="3031300d060960864801650304020105000420" + +def UNSIGNED(n): + return n & 0xffffffff + +def crc32(bytestr): + crc = binascii.crc32(bytestr) + return UNSIGNED(crc) From 500b12b60dc22866e656ed1c6cd9505a2d1147d0 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 19 Dec 2012 16:07:33 +0900 Subject: [PATCH 282/300] update NEWS --- NEWS | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/NEWS b/NEWS index 016c370..da6293b 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,37 @@ Gnuk NEWS - User visible changes +* Major changes in Gnuk 1.0.2 + + Released 2012-12-??, by NIIBE Yutaka + +** Product string is now "Gnuk Token" (was: "FSIJ USB Token") +Since the USB ID Repository suggests not including vendor name +in product string, we changed the product string. + +** New tool (experimental): test/factory_upgrade.py +This is the tool to install new firmware to Gnuk Token, provided +that it's just shipped from factory (and nothing changed). It +authenticate as admin by factory setting, register a public key +for firmware upgrade, and then, does firmware upgrade. + +** tool/gnuk_upgrade.py supports '-k' option +It now supports RSA key on the host PC (not the one on the Token). + +** New tool: tool/get_raw_public_key.py +This is a script to dump raw data of RSA public key, which is useful +to register to Gnuk Token as a firmware upgrade key. + +** New tool: tool/gnuk_remove_keys_libusb.py +This tool is libusb version of gnuk_remove_keys.py. Besides, a bug in +gnuk_remove_keys.py was fixed. + +** CCID protocol fix +When time extension is requested by Gnuk Token to host PC, argument +field was 0, which was wrong (but it works for most PC/SC +implementations and GnuPG internal driver). Now it's 1, which means +1*BWT. + + * Major changes in Gnuk 1.0.1 Released 2012-08-03, by NIIBE Yutaka From ad9a901e1b17681cc57bcf85e133e1770c3e6c6c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 25 Dec 2012 14:47:08 +0900 Subject: [PATCH 283/300] upgrade_by_passwd.py --- ChangeLog | 10 ++- NEWS | 2 +- tool/rsa.py | 70 +++++++++++++++++++ tool/rsa_example.key | 4 ++ .../upgrade_by_passwd.py | 12 ++-- 5 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 tool/rsa.py create mode 100644 tool/rsa_example.key rename test/factory_upgrade.py => tool/upgrade_by_passwd.py (91%) diff --git a/ChangeLog b/ChangeLog index 5050e14..2dc97b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ -2012-12-19 Niibe Yutaka +2012-12-25 Niibe Yutaka - * test/factory_upgrade.py: New. + * tool/rsa.py: New. + + * tool/rsa_example.key: New. Example RSA key information. + + * tool/upgrade_by_passwd.py: New. + +2012-12-19 Niibe Yutaka * src/Makefile.in (USE_OPT): -O3 and -Os (was: -O2). diff --git a/NEWS b/NEWS index da6293b..94dddc2 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ Gnuk NEWS - User visible changes Since the USB ID Repository suggests not including vendor name in product string, we changed the product string. -** New tool (experimental): test/factory_upgrade.py +** New tool (experimental): test/upgrade_by_passwd.py This is the tool to install new firmware to Gnuk Token, provided that it's just shipped from factory (and nothing changed). It authenticate as admin by factory setting, register a public key diff --git a/tool/rsa.py b/tool/rsa.py new file mode 100644 index 0000000..00371f9 --- /dev/null +++ b/tool/rsa.py @@ -0,0 +1,70 @@ +from binascii import hexlify, unhexlify +import string +from os import urandom + +def read_key_from_file(file): + f = open(file) + n_str = f.readline()[:-1] + e_str = f.readline()[:-1] + p_str = f.readline()[:-1] + q_str = f.readline()[:-1] + f.close() + e = int(e_str, 16) + p = int(p_str, 16) + q = int(q_str, 16) + n = int(n_str, 16) + if n != p * q: + raise ValueError("wrong key", p, q, n) + return (unhexlify(n_str), unhexlify(e_str), unhexlify(p_str), unhexlify(q_str), e, p, q, n) + +# egcd and modinv are from wikibooks +# https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm + +def egcd(a, b): + if a == 0: + return (b, 0, 1) + else: + g, y, x = egcd(b % a, a) + return (g, x - (b // a) * y, y) + +def modinv(a, m): + g, x, y = egcd(a, m) + if g != 1: + raise Exception('modular inverse does not exist') + else: + return x % m + +def pkcs1_pad_for_sign(digestinfo): + byte_repr = '\x00' + '\x01' + string.ljust('', 256 - 19 - 32 - 3, '\xff') \ + + '\x00' + digestinfo + return int(hexlify(byte_repr), 16) + +def compute_signature(key, digestinfo): + e = key[4] + p = key[5] + q = key[6] + n = key[7] + p1 = p - 1 + q1 = q - 1 + h = p1 * q1 + d = modinv(e, h) + dp = d % p1 + dq = d % q1 + qp = modinv(q, p) + + input = pkcs1_pad_for_sign(digestinfo) + t1 = pow(input, dp, p) + t2 = pow(input, dq, q) + t = ((t1 - t2) * qp) % p + sig = t2 + t * q + return sig + +def integer_to_bytes_256(i): + s = hex(i)[2:] + s = s.rstrip('L') + if len(s) & 1: + s = '0' + s + return string.rjust(unhexlify(s), 256, '\x00') + +def get_raw_pubkey(key): + return key[0] diff --git a/tool/rsa_example.key b/tool/rsa_example.key new file mode 100644 index 0000000..cdf2d5e --- /dev/null +++ b/tool/rsa_example.key @@ -0,0 +1,4 @@ +9cf7192b51a574d1ad3ccb08ba09b87f228573893eee355529ff243e90fd4b86f79a82097cc7922c0485bed1616b1656a9b0b19ef78ea8ec34c384019adc5d5bf4db2d2a0a2d9cf14277bdcb7056f48b81214e3f7f7742231e29673966f9b1106862112cc798dba8d4a138bb5abfc6d4c12d53a5d39b2f783da916da20852ee139bbafda61d429caf2a4f30847ce7e7ae32ab4061e27dd9e4d00d60910249db8d8559dd85f7ca59659ef400c8f6318700f4e97f0c6f4165de80641490433c88da8682befe68eb311f54af2b07d97ac74edb5399cf054764211694fbb8d1d333f3269f235abe025067f811ff83a2224826219b309ea3e6c968f42b3e52f245dc9 +010001 +b5ab7b159220b18e363258f61ebde08bae83d6ce2dbfe4adc143628c527887acde9de09bf9b49f438019004d71855f30c2d69b6c29bb9882ab641b3387409fe9199464a7faa4b5230c56d9e17cd9ed074bc00180ebed62bae3af28e6ff2ac2654ad968834c5d5c88f8d9d3cc5e167b10453b049d4e454a5761fb0ac717185907 +dd2fffa9814296156a6926cd17b65564187e424dcadce9b032246ad7e46448bb0f9e0ff3c64f987424b1a40bc694e2e9ac4fb1930d163582d7acf20653a1c44b97846c1c5fd8a7b19bb225fb39c30e25410483deaf8c2538d222b748c4d8103b11cec04f666a5c0dbcbf5d5f625f158f65746c3fafe6418145f7cffa5fadeeaf diff --git a/test/factory_upgrade.py b/tool/upgrade_by_passwd.py similarity index 91% rename from test/factory_upgrade.py rename to tool/upgrade_by_passwd.py index 2234a92..92c9e8d 100755 --- a/test/factory_upgrade.py +++ b/tool/upgrade_by_passwd.py @@ -1,8 +1,8 @@ #! /usr/bin/python """ -factory_upgrade.py - a tool to install another firmware for Gnuk Token - which is just shipped from factory +upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token + which is just shipped from factory Copyright (C) 2012 Free Software Initiative of Japan Author: NIIBE Yutaka @@ -25,6 +25,7 @@ along with this program. If not, see . from gnuk_token import * import sys, binascii, time, os +import rsa DEFAULT_PW3 = "12345678" BY_ADMIN = 3 @@ -39,7 +40,8 @@ def main(passwd, data_regnual, data_upgrade): print "CRC32: %04x\n" % crc32code data_regnual += pack(' 1 and sys.argv[1] == '-p': from getpass import getpass From 90a11859dc7f77df554ea2580780ad873807590f Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 26 Dec 2012 11:11:18 +0900 Subject: [PATCH 284/300] update doc (partially) --- doc/development.rst | 39 ++++------ doc/generating-2048-RSA-key.rst | 124 ++++++++++++++++++++++---------- doc/stop-scdaemon.rst | 4 +- doc/udev-rules.rst | 39 +++++----- 4 files changed, 124 insertions(+), 82 deletions(-) diff --git a/doc/development.rst b/doc/development.rst index 2e67a5a..065b986 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -5,10 +5,9 @@ Development Environment Hardware -------- -For development, it is highly recommended to have JTAG debugger or SWD -debugger. +For development, it is highly recommended to have JTAG/SWD debugger. -For boards with DFU (Device Firmware Upgrade) feature, such as DfuSe, +For boards with DFU (Device Firmware Upgrade) feature (such as DfuSe), it is possible to develop with that. But it should be considered *experimental* environment, and it should not be used for usual purpose. That's because it is basically impossible for DfuSe @@ -17,17 +16,16 @@ that your secret will be readily extracted by DfuSe. For JTAG debugger, Olimex JTAG-Tiny is good and supported well. For SWD debugger, ST-Link/V2 would be good, and it is supported by -the tool of tool/stlinkv2.py. +tool/stlinkv2.py. OpenOCD ------- -For JTAG debugger or SWD debugger, we can use OpenOCD. +For JTAG/SWD debugger, we can use OpenOCD. -Note that ST-Link/V2 is *not* supported by OpenOCD 0.5.0. It will be -supported by version 0.6 or later, as current development version -supports it. +Note that ST-Link/V2 is *not* supported by OpenOCD 0.5.0. It is +supported by version 0.6 or later. GNU Toolchain @@ -35,9 +33,11 @@ GNU Toolchain You need GNU toolchain and newlib for 'arm-none-eabi' target. -See http://github.com/esden/summon-arm-toolchain/ (which includes fix -of binutils-2.21.1) for preparation of GNU Toolchain for -'arm-none-eabi' target. This is for GCC 4.5. +There is "gcc-arm-embedded" project. See: +https://launchpad.net/gcc-arm-embedded/ + +It is based on GCC 4.6. You'd need "-O3 -Os" instead of "-O2" and it +will be slightly better. Note that we need to link correct C library (for string functions). For this purpose, our src/Makefile.in contains following line: @@ -45,20 +45,9 @@ For this purpose, our src/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 it is needed for the configuration of +-mfix-cortex-m3-ldrd), but it was needed for the configuration of patch-gcc-config-arm-t-arm-elf.diff in summon-arm-toolchain in practice. -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. - -Recently, there is "gcc-arm-embedded" project. See: -https://launchpad.net/gcc-arm-embedded/ - -It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd -need "-O3 -Os" instead of "-O2" and it will be slightly better. - - Building Gnuk ------------- @@ -72,8 +61,8 @@ Then, run ``configure``: $ ./configure --vidpid= Here, you need to specify USB vendor ID and product ID. For FSIJ's, -it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and -product ID' above. +it's: --vidpid=234b:0000 . Please read the section 'USB vendor ID and +product ID' in README. Type: diff --git a/doc/generating-2048-RSA-key.rst b/doc/generating-2048-RSA-key.rst index 81633f4..129f580 100644 --- a/doc/generating-2048-RSA-key.rst +++ b/doc/generating-2048-RSA-key.rst @@ -2,11 +2,45 @@ Generating 2048-bit RSA keys ============================ -This document describes how I generate 2048-bit RSA keys. +In this section, we describe how to generate 2048-bit RSA keys. -.. BREAK -Here is the log to generate signature key and encryption subkey. +Key length of RSA +================= + +In 2005, NIST (National Institute of Standards and Technology, USA) +has issued the first revision of NIST Special Publication 800-57, +"Recommendation for Key Management". + +In 800-57, NIST advises that 1024-bit RSA keys will no longer be +viable after 2010 and advises moving to 2048-bit RSA keys. NIST +advises that 2048-bit keys should be viable until 2030. + +As of 2010, GnuPG's default for generating RSA key is 2048-bit. + +Some people have preference on RSA 4096-bit keys, considering +"longer is better". + +However, "longer is better" is not always true. When it's long, it +requires more computational resource, memory and storage, and it +consumes more power for nomal usages. These days, many people has +enough computational resource, that would be true, but less is better +for power consumption. + +For security, the key length is a single factor. We had and will have +algorithm issues, too. It is true that it's difficult to update +our public keys, but this problem wouldn't be solved by just have +longer keys. + +We deliberately support only RSA 2048-bit keys for Gnuk, considering +device computation power and host software constraints. + +Thus, the key size is 2048-bit in the examples below. + +Generating keys on host PC +========================== + +Here is the example session to generate main key and a subkey for encryption. I invoke GnuPG with ``--gen-key`` option. :: @@ -25,7 +59,7 @@ and GnuPG asks kind of key. Select ``RSA and RSA``. :: Your selection? 1 RSA keys may be between 1024 and 4096 bits long. -and select 2048-bit (as Gnuk Token only suppurt this). :: +and select 2048-bit (as Gnuk Token only supports this). :: What keysize do you want? (2048) Requested keysize is 2048 bits @@ -59,7 +93,12 @@ Then enter user ID. :: Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o -and enter passphrase for this **key on PC**. :: +and enter passphrase for this **key on host PC**. +Note that this is a passphrase for the key on host PC. +It is different thing to the password of Gnuk Token. + +We enter two same inputs two times +(once for passphrase input, and another for confirmation). :: You need a Passphrase to protect your secret key. @@ -86,43 +125,47 @@ Then, GnuPG generate keys. It takes some time. :: gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model - gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u - pub 2048R/28C0CD7C 2011-05-24 - Key fingerprint = 0B4D C763 D57B ADBB 1870 A978 BDEE 4A35 28C0 CD7C + pub 2048R/4CA7BABE 2010-10-15 + Key fingerprint = 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE uid Niibe Yutaka - sub 2048R/F01E19B7 2011-05-24 + sub 2048R/084239CF 2010-10-15 $ Done. -Then, I create authentication subkey. Authentication subkey is not that common, but very useful (say, for SSH authentication). As it is not that common, we need ``--expert`` option for GnuPG. :: +Then, we create authentication subkey. Authentication subkey is not that common, but very useful (for SSH authentication). As it is not that common, we need ``--expert`` option for GnuPG. :: - $ gpg --expert --edit-key 28C0CD7C + $ gpg --expert --edit-key 4CA7BABE gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. - pub 2048R/28C0CD7C created: 2011-05-24 expires: never usage: SC + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC trust: ultimate validity: ultimate - sub 2048R/F01E19B7 created: 2011-05-24 expires: never usage: E + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E [ultimate] (1). Niibe Yutaka gpg> -Here, I enter ``addkey`` command. Then, I enter the passphrase of **key on PC**, I specified above. :: +Here, it displays that there are main key and a subkey. +It prompts sub-command with ``gpg>`` . + +Here, we enter ``addkey`` sub-command. +Then, we enter the passphrase of **key on host PC**. +It's the one we entered above as . :: gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Niibe Yutaka " - 2048-bit RSA key, ID 28C0CD7C, created 2011-05-24 + 2048-bit RSA key, ID 4CA7BABE, created 2010-10-15 gpg: gpg-agent is not available in this session -GnuPG askes kind of key. I select ``RSA (set your own capabilities)``. :: +GnuPG asks kind of key. We select ``RSA (set your own capabilities)``. :: Please select what kind of key you want: (3) DSA (sign only) @@ -133,7 +176,7 @@ GnuPG askes kind of key. I select ``RSA (set your own capabilities)``. :: (8) RSA (set your own capabilities) Your selection? 8 -And select ``Authenticate`` for the capabilities for this key. Initially, it's ``Sign`` and ``Encrypt``. I need to deselect ``Sign`` and ``Encryp``, and select ``Authenticate``. To do that, I enter ``s``, ``a``, and ``e``. :: +And select ``Authenticate`` for the capabilities for this key. Initially, it's ``Sign`` and ``Encrypt``. I need to deselect ``Sign`` and ``Encryp``, and select ``Authenticate``. To do that, I enter ``s``, ``e``, and ``a``. :: Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Sign Encrypt @@ -153,31 +196,33 @@ And select ``Authenticate`` for the capabilities for this key. Initially, it's (A) Toggle the authenticate capability (Q) Finished - Your selection? a - - Possible actions for a RSA key: Sign Encrypt Authenticate - Current allowed actions: Encrypt Authenticate - - (S) Toggle the sign capability - (E) Toggle the encrypt capability - (A) Toggle the authenticate capability - (Q) Finished - Your selection? e Possible actions for a RSA key: Sign Encrypt Authenticate - Current allowed actions: Authenticate + Current allowed actions: (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished + + Your selection? a + + Possible actions for a RSA key: Sign Encrypt Authenticate + Current allowed actions: Authenticate + + (S) Toggle the sign capability + (E) Toggle the encrypt capability + (A) Toggle the authenticate capability + (Q) Finished -OK, I set the capability of ``Authenticate``. I enter ``q`` to finish setting capabilities. :: +OK, we set the capability of ``Authenticate``. +We enter ``q`` to finish setting capabilities. :: Your selection? q -GnuPG asks bitsize and expiration, I enter 2048 for bitsize and no expiration. Then, I confirm that I really create the key. :: +GnuPG asks bitsize and expiration, we enter 2048 for bitsize and no expiration. +Then, we confirm that we really create the key. :: RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) @@ -202,15 +247,15 @@ Then, GnuPG generate the key. :: .......+++++ +++++ - pub 2048R/28C0CD7C created: 2011-05-24 expires: never usage: SC + pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC trust: ultimate validity: ultimate - sub 2048R/F01E19B7 created: 2011-05-24 expires: never usage: E - sub 2048R/B8929606 created: 2011-05-24 expires: never usage: A + sub 2048R/084239CF created: 2010-10-15 expires: never usage: E + sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A [ultimate] (1). Niibe Yutaka gpg> -I save the key. :: +We save the key (to the storage of the host PC. :: gpg> save $ @@ -221,8 +266,13 @@ Now, we have three keys (one primary key for signature and certification, subkey Publishing public key ===================== -I make a file for my public key by ``--export`` option of GnuPG. :: +We make a file for the public key by ``--export`` option of GnuPG. :: - $ gpg --armor --output gniibe.asc --export 4CA7BABE + $ gpg --armor --output .asc --export -and put it at: http://www.gniibe.org/gniibe.asc +We can publish the file by web server. Or we can publish it +to a keyserver, by invoking GnuPG with ``--send-keys`` option. :: + + $ gpg --keyserver pool.sks-keyservers.net --send-keys + +Here, pool.sks-keyservers.net is a keyserver, widely used. diff --git a/doc/stop-scdaemon.rst b/doc/stop-scdaemon.rst index 05a55c6..7a4dbbd 100644 --- a/doc/stop-scdaemon.rst +++ b/doc/stop-scdaemon.rst @@ -6,8 +6,8 @@ There is a daemon named ``scdaemon`` behind gpg-agent, which handles communication to smartcard/token. Ideally, we don't need to care about ``scdaemon``, and it should -everything automatically. But, there are some cases (because of -bugs), where we need to talk to the daemon directly, in practice. +handle everything automatically. But, there are some cases (because +of bugs), where we need to talk to the daemon directly, in practice. How to communicate SCDAEMON diff --git a/doc/udev-rules.rst b/doc/udev-rules.rst index 44d9750..7f8ad26 100644 --- a/doc/udev-rules.rst +++ b/doc/udev-rules.rst @@ -7,11 +7,13 @@ needed for permissions. Note that this is not needed for the case of PC/SC Lite, as it has its own device configuration. -Patching 60-gnupg.rules -======================= +udev rules for Gnuk Token +========================= -In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules. -This would be the place we need to change:: +In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules, +when you install "gnupg" package. This is the place we need to change. +We add lines for Gnuk Token to give a desktop user the permission to +use the device. We specify USB ID of Gnuk Token (by FSIJ):: --- /lib/udev/rules.d/60-gnupg.rules.orig 2012-06-24 21:51:26.000000000 +0900 +++ /lib/udev/rules.d/60-gnupg.rules 2012-07-13 17:18:55.149587687 +0900 @@ -24,25 +26,26 @@ This would be the place we need to change:: + LABEL="gnupg_rules_end" +When we install "gnupg2" package only (with no "gnupg" package), +there will be no udev rules (there is a bug report #543217 for this issue). +In this case, we need something like this in /etc/udev/rules.d/60-gnuk.rules:: + + SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \ + ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg" + +Usually, udev daemon automatically handles for the changes of configuration +files. If not, please let the daemon reload rules:: + + # udevadm control --reload-rules -Have a another configuration for reGNUal -======================================== - -For reGNUal (upgrade feature of Gnuk), -I also have a file /etc/udev/rules.d/92-gnuk.rules:: - - # For updating firmware, permission settings are needed. - - SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \ - ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd" -Configuration for ST-Link/V2 -============================ +udev rules for ST-Link/V2 +========================= -This is for development, but I also have a file -/etc/udev/rules.d/10-stlink.rules:: +We need to have a udev rule for ST-Link/V2. It's like:: ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", GROUP="tape", MODE="664", SYMLINK+="stlink" +I have this in the file /etc/udev/rules.d/10-stlink.rules. From 78b642507b0c6b051c4d516487c8b815d1dd2d5c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 26 Dec 2012 14:08:49 +0900 Subject: [PATCH 285/300] change the order of sections --- doc/generating-2048-RSA-key.rst | 30 ++++++++++++++++++++++++++++-- doc/index.rst | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/doc/generating-2048-RSA-key.rst b/doc/generating-2048-RSA-key.rst index 129f580..3164c54 100644 --- a/doc/generating-2048-RSA-key.rst +++ b/doc/generating-2048-RSA-key.rst @@ -270,9 +270,35 @@ We make a file for the public key by ``--export`` option of GnuPG. :: $ gpg --armor --output .asc --export -We can publish the file by web server. Or we can publish it +We can publish the file by web server. Or we can publish the key to a keyserver, by invoking GnuPG with ``--send-keys`` option. :: $ gpg --keyserver pool.sks-keyservers.net --send-keys -Here, pool.sks-keyservers.net is a keyserver, widely used. +Here, pool.sks-keyservers.net is a keyserver, which is widely used. + + +Backup the private key +====================== + +There are some ways to back up private key, such that backup .gnupg +directory entirely, use of paperkey. Here we describe backup by ASCII +file. ASCII file is good, because it has less risk on transfer. +Binary file has a risk to be modified on transfer. + +Note that the key on host PC is protected by passphrase (which +is in the example above). Using the key +from the backup needs this passphrase. It is common that +people will forget passphrase for backup. Never forget it. +You have been warned. + +To make ASCII backup for private key, +invokde GnuPG with ``--armor`` option and ``--export-secret-keys`` +specifying the key identifier. :: + + $ gpg --armor --output .asc --export-secret-keys + +From the backup, +we can recover privet key by invoking GnuPG with ``--import`` option. :: + + $ gpg --import .asc diff --git a/doc/index.rst b/doc/index.rst index 174dd47..cbf8207 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -18,9 +18,9 @@ Contents: development.rst stop-scdaemon.rst udev-rules.rst - generating-2048-RSA-key.rst gnuk-token-initial-configuration.rst gnuk-personalization.rst + generating-2048-RSA-key.rst gnuk-keytocard.rst gnuk-keytocard-noremoval.rst using-gnuk-token-with-another-computer.rst From 77d06fb30147ac8ed84cc03f560f766a8c08dae3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 Jan 2013 12:16:50 +0900 Subject: [PATCH 286/300] tool/pinpadtest: add fixed length input --- ChangeLog | 4 ++++ tool/pinpadtest.py | 30 +++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2dc97b3..f8f2bd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-01-11 Niibe Yutaka + + * tool/pinpadtest.py: Add fixed length input. + 2012-12-25 Niibe Yutaka * tool/rsa.py: New. diff --git a/tool/pinpadtest.py b/tool/pinpadtest.py index 1993d69..0009fed 100755 --- a/tool/pinpadtest.py +++ b/tool/pinpadtest.py @@ -51,7 +51,7 @@ def confirm_pin_setting(single_step): return 0x03 # bConfirmPIN: old PIN and new PIN twice class Card(object): - def __init__(self, add_a_byte, pinmin, pinmax): + def __init__(self, add_a_byte, pinmin, pinmax, fixed): cardtype = AnyCardType() cardrequest = CardRequest(timeout=10, cardType=cardtype) cardservice = cardrequest.waitforcard() @@ -61,6 +61,7 @@ class Card(object): self.another_byte = add_a_byte self.pinmin = pinmin self.pinmax = pinmax + self.fixed = fixed def get_features(self): p = self.connection.control(CM_IOCTL_GET_FEATURE_REQUEST, []) @@ -101,7 +102,7 @@ class Card(object): pin_verify = [ 0x00, # bTimeOut 0x00, # bTimeOut2 0x82, # bmFormatString: Byte, pos=0, left, ASCII. - 0x00, # bmPINBlockString + self.fixed, # bmPINBlockString 0x00, # bmPINLengthFormat self.pinmax, # wPINMaxExtraDigit Low (PINmax) self.pinmin, # wPINMaxExtraDigit High (PINmin) @@ -114,7 +115,10 @@ class Card(object): 0x00, # bTeoPrologue[1] 0x00 # bTeoPrologue[2] ] - apdu += self.possibly_add_dummy_byte() + if self.fixed > 0: + apdu += str.ljust('', self.fixed, '\xff') + else: + apdu += self.possibly_add_dummy_byte() pin_verify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.verify_ioctl,pin_verify) sw1 = data[0] @@ -128,10 +132,10 @@ class Card(object): pin_modify = [ 0x00, # bTimerOut 0x00, # bTimerOut2 0x82, # bmFormatString: Byte, pos=0, left, ASCII. - 0x00, # bmPINBlockString + self.fixed, # bmPINBlockString 0x00, # bmPINLengthFormat 0x00, # bInsertionOffsetOld - 0x00, # bInsertionOffsetNew + self.fixed, # bInsertionOffsetNew self.pinmax, # wPINMaxExtraDigit Low (PINmax) self.pinmin, # wPINMaxExtraDigit High (PINmin) confirm_pin_setting(single_step), @@ -146,7 +150,10 @@ class Card(object): 0x00, # bTeoPrologue[1] 0x00 # bTeoPrologue[2] ] - apdu += self.possibly_add_dummy_byte() + if self.fixed > 0: + apdu += str.ljust('', 2*self.fixed, '\xff') + else: + apdu += self.possibly_add_dummy_byte() pin_modify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.modify_ioctl,pin_modify) sw1 = data[0] @@ -191,8 +198,8 @@ class Card(object): self.send_modify_pinpad(apdu, is_exchange, "cmd_change_reference_data_pinpad") -def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps): - card = Card(add_a_byte, pinmin, pinmax) +def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed): + card = Card(add_a_byte, pinmin, pinmax, fixed) card.connection.connect() print "Reader/Token:", card.connection.getReader() @@ -280,6 +287,7 @@ def print_usage(): print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)" print "\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)" print " options:" + print "\t--fixed N:\tUse fixed length input" print "\t--admin:\tby administrator\t\t\t[False]" print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]" print "\t--pinmin:\tspecify minimum length of PIN\t\t[6]" @@ -302,6 +310,7 @@ if __name__ == '__main__': pinmin = PIN_MIN_DEFAULT pinmax = PIN_MAX_DEFAULT change_by_two_steps = False + fixed=0 while len(sys.argv) >= 2: option = sys.argv[1] sys.argv.pop(1) @@ -319,6 +328,9 @@ if __name__ == '__main__': change_by_two_steps = True elif option == '--add': add_a_byte = True + elif option == '--fixed': + fixed = int(sys.argv[1]) + sys.argv.pop(1) elif option == '--pinmin': pinmin = int(sys.argv[1]) sys.argv.pop(1) @@ -337,7 +349,7 @@ if __name__ == '__main__': exit(0) else: raise ValueError, option - main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps) + main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed) # Failure # 67 00: Wrong length; no further indication From 9b71d70b73d2f40b95c8047db1e03b010e6b983e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 11 Jan 2013 13:21:38 +0900 Subject: [PATCH 287/300] fix pinpadtest.py --- tool/pinpadtest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tool/pinpadtest.py b/tool/pinpadtest.py index 0009fed..523e335 100755 --- a/tool/pinpadtest.py +++ b/tool/pinpadtest.py @@ -113,12 +113,13 @@ class Card(object): 0x00, # bMsgIndex 0x00, # bTeoPrologue[0] 0x00, # bTeoPrologue[1] - 0x00 # bTeoPrologue[2] ] if self.fixed > 0: - apdu += str.ljust('', self.fixed, '\xff') + apdu += [ self.fixed ] + apdu += [ 255 ] * self.fixed else: apdu += self.possibly_add_dummy_byte() + pin_verify += [ len(apdu) ] # bTeoPrologue[2] pin_verify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.verify_ioctl,pin_verify) sw1 = data[0] @@ -148,12 +149,13 @@ class Card(object): 0x02, # bMsgIndex3 0x00, # bTeoPrologue[0] 0x00, # bTeoPrologue[1] - 0x00 # bTeoPrologue[2] ] if self.fixed > 0: - apdu += str.ljust('', 2*self.fixed, '\xff') + apdu += [ 2*self.fixed ] + apdu += [ 255 ] * (2*self.fixed) else: apdu += self.possibly_add_dummy_byte() + pin_modify += [ len(apdu) ] # bTeoPrologue[2] pin_modify += [ len(apdu), 0, 0, 0 ] + apdu data = self.connection.control(self.modify_ioctl,pin_modify) sw1 = data[0] From 32094099dd4105874398ef0f6c5b4afbe5e23c88 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sun, 20 Jan 2013 18:01:24 +0900 Subject: [PATCH 288/300] add tool/gpg-agent.py --- tool/gpg-agent.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tool/gpg-agent.py diff --git a/tool/gpg-agent.py b/tool/gpg-agent.py new file mode 100644 index 0000000..ae8528b --- /dev/null +++ b/tool/gpg-agent.py @@ -0,0 +1,84 @@ +import platform, os, socket +IS_WINDOWS=(platform.system() == 'Windows') + +BUFLEN=1024 + +class gpg_agent(object): + def __init__(self): + if IS_WINDOWS: + home = os.getenv("HOME") + comm_port = os.path.join(home, "gnupg", "S.gpg-agent") + # + f = open(comm_port, "rb", 0) + infostr = f.read() + f.close() + # + info = infostr.split('\n', 1) + port = int(info[0]) + nonce = info[1] + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("localhost", port)) + s.send(nonce) + else: + infostr = os.getenv("GPG_AGENT_INFO") + info = infostr.split(':', 2) + path = info[0] + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + s.connect(path) + self.sock = s + self.buf_remained = "" + + def read_line(self): + line = "" + if self.buf_remained != "": + chunk = self.buf_remained + else: + chunk = self.sock.recv(BUFLEN) + while True: + pos = chunk.index('\n') + if pos >= 0: + self.buf_remained = chunk[pos+1:] + line = line + chunk[0:pos] + return line + else: + line = line + chunk + chunk = self.sock.recv(BUFLEN) + + def send_command(self, cmd): + self.sock.send(cmd) + + def get_response(self): + response = "" + while True: + while True: + l = self.read_line() + if l[0] != '#': + break + if l[0] == 'D': + response += l[2:] + elif l[0] == 'O' and l[1] == 'K': + if response != "": + return response + else: + return True + elif l[0] == 'E' and l[1] == 'R' and l[2] == 'R': + return False + else: # XXX: S, INQUIRE, END + return False + + def close(self): + self.sock.send('BYE\n') + bye = self.read_line() + self.sock.close() + return bye # "OK closing connection" + +# Test +g = gpg_agent() +print g.read_line() +g.send_command("KEYINFO --list --data\n") +print g.get_response() +g.send_command("READKEY 5D6C89682D07CCFC034AF508420BF2276D8018ED\n") +r = g.get_response() +import binascii +print binascii.hexlify(r) +print g.close() From ea2191105f64765f8c85437606191d67aaa09a56 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sun, 20 Jan 2013 20:40:19 +0900 Subject: [PATCH 289/300] improve gpg-agent.py --- tool/gpg-agent.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tool/gpg-agent.py b/tool/gpg-agent.py index ae8528b..accda44 100644 --- a/tool/gpg-agent.py +++ b/tool/gpg-agent.py @@ -27,6 +27,7 @@ class gpg_agent(object): s.connect(path) self.sock = s self.buf_remained = "" + self.response = None def read_line(self): line = "" @@ -44,23 +45,21 @@ class gpg_agent(object): line = line + chunk chunk = self.sock.recv(BUFLEN) + def get_response(self): + return self.response + def send_command(self, cmd): self.sock.send(cmd) - - def get_response(self): - response = "" + self.response = "" while True: while True: l = self.read_line() if l[0] != '#': break if l[0] == 'D': - response += l[2:] + self.response += l[2:] elif l[0] == 'O' and l[1] == 'K': - if response != "": - return response - else: - return True + return True elif l[0] == 'E' and l[1] == 'R' and l[2] == 'R': return False else: # XXX: S, INQUIRE, END @@ -75,9 +74,9 @@ class gpg_agent(object): # Test g = gpg_agent() print g.read_line() -g.send_command("KEYINFO --list --data\n") +print g.send_command("KEYINFO --list --data\n") print g.get_response() -g.send_command("READKEY 5D6C89682D07CCFC034AF508420BF2276D8018ED\n") +print g.send_command("READKEY 5D6C89682D07CCFC034AF508420BF2276D8018ED\n") r = g.get_response() import binascii print binascii.hexlify(r) From a302585602ccfc321703403698942331130d3214 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sun, 20 Jan 2013 20:40:34 +0900 Subject: [PATCH 290/300] move --- tool/{gpg-agent.py => gpg_agent.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tool/{gpg-agent.py => gpg_agent.py} (100%) diff --git a/tool/gpg-agent.py b/tool/gpg_agent.py similarity index 100% rename from tool/gpg-agent.py rename to tool/gpg_agent.py From de7f9f641702d9fe17b77800f9cfa60cc48e345c Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sun, 20 Jan 2013 21:17:43 +0900 Subject: [PATCH 291/300] improve --- tool/gpg_agent.py | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/tool/gpg_agent.py b/tool/gpg_agent.py index accda44..a8440f3 100644 --- a/tool/gpg_agent.py +++ b/tool/gpg_agent.py @@ -46,7 +46,18 @@ class gpg_agent(object): chunk = self.sock.recv(BUFLEN) def get_response(self): - return self.response + r = self.response + result = "" + while True: + i = r.find('%') + if i < 0: + result += r + break + hex_str = r[i+1:i+3] + result += r[0:i] + result += chr(int(hex_str,16)) + r = r[i+3:] + return result def send_command(self, cmd): self.sock.send(cmd) @@ -72,12 +83,19 @@ class gpg_agent(object): return bye # "OK closing connection" # Test -g = gpg_agent() -print g.read_line() -print g.send_command("KEYINFO --list --data\n") -print g.get_response() -print g.send_command("READKEY 5D6C89682D07CCFC034AF508420BF2276D8018ED\n") -r = g.get_response() -import binascii -print binascii.hexlify(r) -print g.close() +if __name__ == '__main__': + g = gpg_agent() + print g.read_line() + print g.send_command("KEYINFO --list --data\n") + kl_str = g.get_response() + kl_str = kl_str[0:-1] + kl = kl_str.split('\n') + import re + kl_o3 = [kg for kg in kl if re.search("OPENPGP\\.3", kg)] + print kl_o3 + kg = kl_o3[0].split(' ')[0] + print g.send_command("READKEY %s\n" % kg) + r = g.get_response() + import binascii + print binascii.hexlify(r) + print g.close() From 220d5c0307489ba3ea7f75e4b7ed3e329b0431af Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Sun, 20 Jan 2013 21:18:21 +0900 Subject: [PATCH 292/300] Add tool/pageant_proxy_to_gpg.py --- tool/pageant_proxy_to_gpg.py | 172 +++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 tool/pageant_proxy_to_gpg.py diff --git a/tool/pageant_proxy_to_gpg.py b/tool/pageant_proxy_to_gpg.py new file mode 100644 index 0000000..4bd09c9 --- /dev/null +++ b/tool/pageant_proxy_to_gpg.py @@ -0,0 +1,172 @@ +import os, sys, re, hashlib, binascii +from struct import * +from gpg_agent imort gpg_agent + +# Assume it's only OPENPGP.3 key + +def debug(str): + print "DEBUG: ", str + sys.stdout.flush() + +def get_keylist(keyinfo_result): + kl_str = keyinfo_result[0:-1] # Chop last newline + kl = kl_str.split('\n') + # filter by "OPENPGP.3", and only keygrip + return [kg.split(' ')[0] for kg in kl if re.search("OPENPGP\\.3", kg)] + +g = gpg_agent() +g.read_line() # Greeting message + +g.send_command('KEYINFO --list --data\n') +keyinfo_result = g.get_response() +kl = get_keylist(keyinfo_result) +print kl + +keygrip = kl[0] + +g.send_command('READKEY %s\n' % keygrip) +key = g.get_response +pos = key.index("(10:public-key(3:rsa(1:n257:") + 28 +pos_last = key.index(")(1:e3:") +n = key[pos:pos_last] +e = key[pos_last+7:pos_last+10] +if len(n) != 257: + raise ValueError(keygrip) +print binascii.hexlify(n) +print binascii.hexlify(e) + +ssh_rsa_public_blob = "\x00\x00\x00\x07ssh-rsa" + \ + "\x00\x00\x00\x03" + e + "\x00\x00\x01\x01" + n + +ssh_key_comment = "key_on_gpg" # XXX: get login from card? + +import win32con, win32api, win32gui, ctypes, ctypes.wintypes + +class COPYDATA(ctypes.Structure): + _fields_ = [ ('dwData', ctypes.wintypes.LPARAM), + ('cbData', ctypes.wintypes.DWORD), + ('lpData', ctypes.c_void_p) ] + +P_COPYDATA = ctypes.POINTER(COPYDATA) + +class SSH_MSG_HEAD(ctypes.BigEndianStructure): + _pack_ = 1 + _fields_ = [ ('msg_len', ctypes.c_uint32), + ('msg_type', ctypes.c_byte) ] + +P_SSH_MSG_HEAD = ctypes.POINTER(SSH_MSG_HEAD) + +class SSH_MSG_ID_ANSWER_HEAD(ctypes.BigEndianStructure): + _pack_ = 1 + _fields_ = [ ('msg_len', ctypes.c_uint32), + ('msg_type', ctypes.c_byte), + ('keys', ctypes.c_uint32)] + +P_SSH_MSG_ID_ANSWER = ctypes.POINTER(SSH_MSG_ID_ANSWER_HEAD) + +class SSH_MSG_SIGN_RESPONSE_HEAD(ctypes.BigEndianStructure): + _pack_ = 1 + _fields_ = [ ('msg_len', ctypes.c_uint32), + ('msg_type', ctypes.c_byte), + ('sig_len', ctypes.c_uint32)] + +P_SSH_MSG_SIGN_RESPONSE = ctypes.POINTER(SSH_MSG_SIGN_RESPONSE_HEAD) + + +FILE_MAP_ALL_ACCESS=0x000F001F + +class windows_ipc_listener(object): + def __init__(self): + message_map = { win32con.WM_COPYDATA: self.OnCopyData } + wc = win32gui.WNDCLASS() + wc.lpfnWndProc = message_map + wc.lpszClassName = 'Pageant' + hinst = wc.hInstance = win32api.GetModuleHandle(None) + classAtom = win32gui.RegisterClass(wc) + self.hwnd = win32gui.CreateWindow ( + classAtom, + "Pageant", + 0, + 0, + 0, + win32con.CW_USEDEFAULT, + win32con.CW_USEDEFAULT, + 0, + 0, + hinst, + None + ) + debug("created: window=%08x" % self.hwnd) + + def OnCopyData(self, hwnd, msg, wparam, lparam): + debug("WM_COPYDATA message") + debug(" window=%08x" % hwnd) + debug(" msg =%08x" % msg) + debug(" wparam=%08x" % wparam) + pCDS = ctypes.cast(lparam, P_COPYDATA) + debug(" dwData=%08x" % (pCDS.contents.dwData & 0xffffffff)) + debug(" len=%d" % pCDS.contents.cbData) + mapname = ctypes.string_at(pCDS.contents.lpData) + debug(" mapname='%s'" % ctypes.string_at(pCDS.contents.lpData)) + hMapObject = ctypes.windll.kernel32.OpenFileMappingA(FILE_MAP_ALL_ACCESS, 0, mapname) + if hMapObject == 0: + debug("error on OpenFileMapping") + return 0 + pBuf = ctypes.windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, 0) + if pBuf == 0: + ctypes.windll.kernel32.CloseHandle(hMapObject) + debug("error on MapViewOfFile") + return 0 + pSshMsg = ctypes.cast(pBuf, P_SSH_MSG_HEAD) + debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) + debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) + if pSshMsg.contents.msg_type == 11: # SSH2_AGENT_REQUEST_IDENTITIES + blob_len = len(ssh_rsa_public_blob) + cmnt_len = len(ssh_key_comment) + pAns = ctypes.cast(pBuf, P_SSH_MSG_ID_ANSWER) + pAns.contents.msg_len = 1+4+4+blob_len+4+cmnt_len + pAns.contents.msg_type = 12 # SSH2_AGENT_IDENTITIES_ANSWER + pAns.contents.keys = 1 + ctypes.memmove(pBuf+4+1+4, pack('>I', blob_len), 4) + ctypes.memmove(pBuf+4+1+4+4, ssh_rsa_public_blob, blob_len) + ctypes.memmove(pBuf+4+1+4+4+blob_len, pack('>I', cmnt_len), 4) + ctypes.memmove(pBuf+4+1+4+4+blob_len+4, ssh_key_comment, cmnt_len) + + debug("answer is:") + debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) + debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) + elif pSshMsg.contents.msg_type == 13: # SSH2_AGENT_SIGN_REQUEST + req_blob_len = unpack(">I", ctypes.string_at(pBuf+5, 4))[0] + req_blob = ctypes.string_at(pBuf+5+4, req_blob_len) + req_data_len = unpack(">I", ctypes.string_at(pBuf+5+4+req_blob_len,4))[0] + req_data = ctypes.string_at(pBuf+5+4+req_blob_len+4,req_data_len) + debug(" blob_len=%d" % req_blob_len) + debug(" data_len=%d" % req_data_len) + hash = hashlib.sha1(req_data).hexdigest() + debug(" hash=%s" % hash) + g.send_command('SIGKEY %s\n' % keygrip) + g.send_command('SETHASH --hash=sha1 %s\n' % hash) + g.send_command('PKSIGN\n') + signature = g.get_response() + pos = signature.index("(7:sig-val(3:rsa(1:s256:") + 24 + signature = "\x00\x00\x00\x07" + "ssh-rsa" + "\x00\x00\x01\x00" + signature[pos:pos+256] + siglen = len(signature) + debug("sig_len=%d" % siglen) + debug("sig=%s" % binascii.hexlify(signature)) + pRes = ctypes.cast(pBuf, P_SSH_MSG_SIGN_RESPONSE) + pRes.contents.msg_len = 1+4+siglen + pRes.contents.msg_type = 14 # SSH2_AGENT_SIGN_RESPONSE + pRes.contents.sig_len = siglen + ctypes.memmove(pBuf+4+1+4, signature, siglen) + debug("answer is:") + debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) + debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) + else: + exit(0) + ctypes.windll.kernel32.UnmapViewOfFile(pBuf) + ctypes.windll.kernel32.CloseHandle(hMapObject) + debug(" ssh_msg: done") + return 1 + +l = windows_ipc_listener() +win32gui.PumpMessages() From 3ad9373163bb6bf5bafbf3931fb1c990b535bdc8 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 21 Jan 2013 09:22:21 +0900 Subject: [PATCH 293/300] fix gpg_agent.py --- ChangeLog | 4 ++++ tool/gpg_agent.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f8f2bd5..7f91840 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-01-20 Niibe Yutaka + + * tool/gpg_agent.py: New. + 2013-01-11 Niibe Yutaka * tool/pinpadtest.py: Add fixed length input. diff --git a/tool/gpg_agent.py b/tool/gpg_agent.py index a8440f3..8a35ccb 100644 --- a/tool/gpg_agent.py +++ b/tool/gpg_agent.py @@ -36,7 +36,7 @@ class gpg_agent(object): else: chunk = self.sock.recv(BUFLEN) while True: - pos = chunk.index('\n') + pos = chunk.find('\n') if pos >= 0: self.buf_remained = chunk[pos+1:] line = line + chunk[0:pos] From 6b6913c676e1b94521cdcff8ff2d114730bf483e Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 21 Jan 2013 10:31:18 +0900 Subject: [PATCH 294/300] add tool/sexp.py --- ChangeLog | 4 ++++ tool/sexp.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tool/sexp.py diff --git a/ChangeLog b/ChangeLog index 7f91840..ecb14f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-01-21 Niibe Yutaka + + * tool/sexp.py: New. + 2013-01-20 Niibe Yutaka * tool/gpg_agent.py: New. diff --git a/tool/sexp.py b/tool/sexp.py new file mode 100644 index 0000000..a705054 --- /dev/null +++ b/tool/sexp.py @@ -0,0 +1,65 @@ +# SEXP (S-expressions) Basic Transport Support +# +# See: http://people.csail.mit.edu/rivest/sexp.html +# + +import re + +WHITESPACE='[ \n\t\v\r\f]+' +re_ws = re.compile(WHITESPACE) +DIGITS='[0-9]+' +re_digit = re.compile(DIGITS) + +def skip_whitespace(string, pos): + m = re_ws.match(string, pos) + if m: + return m.start() + else: + return pos + +def sexp_match(string, ch, pos): + pos = skip_whitespace(string,pos) + if string[pos] == ch: + return pos+1 + else: + raise ValueError("expect '%s'" % ch) + +def sexp_parse_simple_string(string, pos): + pos = skip_whitespace(string,pos) + m = re_digit.match(string, pos) + if m: + length = int(string[m.start():m.end()],10) + pos = sexp_match(string, ':', m.end()) + return (string[pos:pos+length], pos+length) + else: + raise ValueError('expect digit') + +def sexp_parse_list(string,pos): + l = [] + while True: + pos = skip_whitespace(string,pos) + if string[pos] == ')': + return (l, pos) + else: + (sexp, pos) = sexp_parse(string,pos) + l.append(sexp) + +def sexp_parse(string, pos=0): + pos = skip_whitespace(string,pos) + if string[pos] == '(': + (l, pos) = sexp_parse_list(string,pos+1) + pos = sexp_match(string, ')', pos) + return (l, pos) + elif string[pos] == '[': + pos = skip_whitespace(string,pos) + (dsp, pos) = sexp_parse_simple_string(string,pos+1) + pos = sexp_match(string, ']', pos) + pos = skip_whitespace(string,pos) + (ss, pos) = sexp_parse_simple_string(string, pos) + return ((dsp, ss), pos) + else: + return sexp_parse_simple_string(string, pos) + +def sexp(string): + (sexp, pos) = sexp_parse(string) + return sexp From 8c91d2ef2e92fb821beebe702fc6aa5dea3bd77b Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 21 Jan 2013 12:09:33 +0900 Subject: [PATCH 295/300] Use APPDATA for HOME equivalent --- tool/gpg_agent.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tool/gpg_agent.py b/tool/gpg_agent.py index 8a35ccb..46036d1 100644 --- a/tool/gpg_agent.py +++ b/tool/gpg_agent.py @@ -7,6 +7,8 @@ class gpg_agent(object): def __init__(self): if IS_WINDOWS: home = os.getenv("HOME") + if not home: + home = os.getenv("APPDATA") comm_port = os.path.join(home, "gnupg", "S.gpg-agent") # f = open(comm_port, "rb", 0) From 7e8dd12654f2b03b0e21d02f74a29800ad98ea35 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 21 Jan 2013 12:10:25 +0900 Subject: [PATCH 296/300] New tool/pageant_proxy_to_gpg.py --- ChangeLog | 1 + tool/pageant_proxy_to_gpg.py | 61 +++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index ecb14f5..255bf93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2013-01-21 Niibe Yutaka + * tool/pageant_proxy_to_gpg.py: New. * tool/sexp.py: New. 2013-01-20 Niibe Yutaka diff --git a/tool/pageant_proxy_to_gpg.py b/tool/pageant_proxy_to_gpg.py index 4bd09c9..23d2873 100644 --- a/tool/pageant_proxy_to_gpg.py +++ b/tool/pageant_proxy_to_gpg.py @@ -1,47 +1,57 @@ import os, sys, re, hashlib, binascii from struct import * -from gpg_agent imort gpg_agent +from gpg_agent import gpg_agent +from sexp import sexp -# Assume it's only OPENPGP.3 key +# Assume it's only OPENPGP.3 key and it's 2048-bit -def debug(str): - print "DEBUG: ", str +def debug(string): + print "DEBUG: %s" % string sys.stdout.flush() -def get_keylist(keyinfo_result): +def get_keygrip_list(keyinfo_result): kl_str = keyinfo_result[0:-1] # Chop last newline kl = kl_str.split('\n') # filter by "OPENPGP.3", and only keygrip return [kg.split(' ')[0] for kg in kl if re.search("OPENPGP\\.3", kg)] +# Connect GPG-Agent, and get list of KEYGRIPs. g = gpg_agent() g.read_line() # Greeting message g.send_command('KEYINFO --list --data\n') keyinfo_result = g.get_response() -kl = get_keylist(keyinfo_result) -print kl +keygrip_list = get_keygrip_list(keyinfo_result) -keygrip = kl[0] +debug(keygrip_list) -g.send_command('READKEY %s\n' % keygrip) -key = g.get_response -pos = key.index("(10:public-key(3:rsa(1:n257:") + 28 -pos_last = key.index(")(1:e3:") -n = key[pos:pos_last] -e = key[pos_last+7:pos_last+10] -if len(n) != 257: - raise ValueError(keygrip) -print binascii.hexlify(n) -print binascii.hexlify(e) +keylist = [] +# For each KEYGRIP, get its PUBLIC-KEY. +for kg in keygrip_list: + g.send_command('READKEY %s\n' % kg) + key = sexp(g.get_response()) + # [ "public-key" [ "rsa" [ "n" MODULUS ] [ "e" EXPONENT] ] ] + n = key[1][1][1] + e = key[1][2][1] + debug(binascii.hexlify(n)) + debug(binascii.hexlify(e)) + keylist.append([n, e, kg]) + +# FIXME: should handle all keys, not only a single key +# FIXME: should support different key size +n = keylist[0][0] +e = keylist[0][1] +keygrip = keylist[0][2] ssh_rsa_public_blob = "\x00\x00\x00\x07ssh-rsa" + \ "\x00\x00\x00\x03" + e + "\x00\x00\x01\x01" + n -ssh_key_comment = "key_on_gpg" # XXX: get login from card? +ssh_key_comment = "key_on_gpg" # XXX: get login from card for comment? import win32con, win32api, win32gui, ctypes, ctypes.wintypes + +# For WM_COPYDATA structure class COPYDATA(ctypes.Structure): _fields_ = [ ('dwData', ctypes.wintypes.LPARAM), ('cbData', ctypes.wintypes.DWORD), @@ -147,17 +157,18 @@ class windows_ipc_listener(object): g.send_command('SIGKEY %s\n' % keygrip) g.send_command('SETHASH --hash=sha1 %s\n' % hash) g.send_command('PKSIGN\n') - signature = g.get_response() - pos = signature.index("(7:sig-val(3:rsa(1:s256:") + 24 - signature = "\x00\x00\x00\x07" + "ssh-rsa" + "\x00\x00\x01\x00" + signature[pos:pos+256] - siglen = len(signature) + sig = sexp(g.get_response()) + # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ] + sig = sig[1][1][1] + sig = "\x00\x00\x00\x07" + "ssh-rsa" + "\x00\x00\x01\x00" + sig # FIXME: should support different key size + siglen = len(sig) debug("sig_len=%d" % siglen) - debug("sig=%s" % binascii.hexlify(signature)) + debug("sig=%s" % binascii.hexlify(sig)) pRes = ctypes.cast(pBuf, P_SSH_MSG_SIGN_RESPONSE) pRes.contents.msg_len = 1+4+siglen pRes.contents.msg_type = 14 # SSH2_AGENT_SIGN_RESPONSE pRes.contents.sig_len = siglen - ctypes.memmove(pBuf+4+1+4, signature, siglen) + ctypes.memmove(pBuf+4+1+4, sig, siglen) debug("answer is:") debug(" ssh_msg_len: %d" % pSshMsg.contents.msg_len) debug(" ssh_msg_type: %d" % pSshMsg.contents.msg_type) From eae955b15e11a4951f42a6de734bcfe90bf535c3 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Tue, 22 Jan 2013 21:08:55 +0900 Subject: [PATCH 297/300] try VEGA ALPHA specific change --- ChangeLog | 7 +++++++ tool/pinpadtest.py | 26 +++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 255bf93..c185584 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-01-22 Niibe Yutaka + + * tool/pinpadtest.py (Card.cmd_vega_alpha_disable_empty_verify): + New. + (main): call cmd_vega_alpha_disable_empty_verify if it's + COVADIS_VEGA_ALPHA. + 2013-01-21 Niibe Yutaka * tool/pageant_proxy_to_gpg.py: New. diff --git a/tool/pinpadtest.py b/tool/pinpadtest.py index 523e335..735c9f8 100755 --- a/tool/pinpadtest.py +++ b/tool/pinpadtest.py @@ -33,6 +33,7 @@ from smartcard.util import toHexString from getpass import getpass CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400) +CM_IOCTL_VENDOR_IFD_EXCHANGE = (0x42000000 + 1) FEATURE_VERIFY_PIN_DIRECT = 0x06 FEATURE_MODIFY_PIN_DIRECT = 0x07 @@ -97,6 +98,15 @@ class Card(object): else: return [] + def cmd_vega_alpha_disable_empty_verify(self): + apdu = [ 0xB5, # -| + 0x01, # | Pre-command parameters + 0x00, # -| + 0x03, # retry counter value (fixed value) + 0x00 # enable 3s timeout + ] + data = self.connection.control(CM_IOCTL_VENDOR_IFD_EXCHANGE, apdu) + def cmd_verify_pinpad(self, who): apdu = [0x00, 0x20, 0x00, 0x80+who ] pin_verify = [ 0x00, # bTimeOut @@ -200,13 +210,27 @@ class Card(object): self.send_modify_pinpad(apdu, is_exchange, "cmd_change_reference_data_pinpad") +COVADIS_VEGA_ALPHA="COVADIS VEGA-ALPHA (000000F5) 00 00" +# We need to set ifdDriverOptions in /etc/libccid_Info.plist: +# +# ifdDriverOptions +# 0x0001 +# +# 1: DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED +# the CCID Exchange command is allowed. You can use it through +# SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, ...) + def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps, fixed): card = Card(add_a_byte, pinmin, pinmax, fixed) card.connection.connect() - print "Reader/Token:", card.connection.getReader() + ident = card.connection.getReader() + print "Reader/Token:", ident print "ATR:", toHexString( card.connection.getATR() ) + if ident == COVADIS_VEGA_ALPHA: + card.cmd_vega_alpha_disable_empty_verify() + card.get_features() card.cmd_select_openpgp() From 9dde59867d564393797d2e645fc24dfbacab4eca Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 28 Jan 2013 12:10:14 +0900 Subject: [PATCH 298/300] Implement VERIFY with empty data --- ChangeLog | 5 +++++ src/gnuk.h | 1 + src/openpgp-do.c | 11 +++++++++++ src/openpgp.c | 21 +++++++++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/ChangeLog b/ChangeLog index c185584..5ad3a1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-01-28 Niibe Yutaka + + * src/openpgp-do.c (gpg_pw_get_retry_counter): New. + * src/openpgp.c (cmd_verify): Implement VERIFY with empty data. + 2013-01-22 Niibe Yutaka * tool/pinpadtest.py (Card.cmd_vega_alpha_disable_empty_verify): diff --git a/src/gnuk.h b/src/gnuk.h index b539159..46a7418 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -94,6 +94,7 @@ extern volatile uint8_t auth_status; #define PW_ERR_PW1 0 #define PW_ERR_RC 1 #define PW_ERR_PW3 2 +extern int gpg_pw_get_retry_counter (int who); extern int gpg_pw_locked (uint8_t which); extern void gpg_pw_reset_err_counter (uint8_t which); extern void gpg_pw_increment_err_counter (uint8_t which); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index fa5625e..759069e 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -41,6 +41,17 @@ gpg_pw_get_err_counter (uint8_t which) return flash_cnt123_get_value (pw_err_counter_p[which]); } +int +gpg_pw_get_retry_counter (int who) +{ + if (who == 0x81 || who == 0x82) + return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW1); + else if (who == 0x83) + return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW3); + else + return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_RC); +} + int gpg_pw_locked (uint8_t which) { diff --git a/src/openpgp.c b/src/openpgp.c index 7888e80..eb63e86 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -140,6 +140,27 @@ cmd_verify (void) len = apdu.cmd_apdu_data_len; pw = apdu.cmd_apdu_data; + if (len == 0) + { /* This is to examine status. */ + if (p2 == 0x81) + r = ac_check_status (AC_PSO_CDS_AUTHORIZED); + else if (p2 == 0x82) + r = ac_check_status (AC_OTHER_AUTHORIZED); + else + r = ac_check_status (AC_ADMIN_AUTHORIZED); + + if (r) + GPG_SUCCESS (); /* If authentication done already, return success. */ + else + { /* If not, return retry counter, encoded. */ + r = gpg_pw_get_retry_counter (p2); + set_res_sw (0x63, 0xc0 | (r&0f)); + } + + return; + } + + /* This is real authentication. */ if (p2 == 0x81) r = verify_pso_cds (pw, len); else if (p2 == 0x82) From 62b4369d2c6d7c8593d5d7043e2492f624574fbb Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Wed, 30 Jan 2013 16:50:19 +0900 Subject: [PATCH 299/300] minor change to external_authenticate --- ChangeLog | 9 +++++++++ src/openpgp.c | 2 +- tool/gnuk_token.py | 6 +++--- tool/upgrade_by_passwd.py | 5 +++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ad3a1c..76bc4b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2013-01-30 Niibe Yutaka + + * src/openpgp.c (cmd_external_authenticate): Fix off-by-one error. + + * tool/gnuk_token.py (gnuk_token.cmd_external_authenticate): Add + KEYNO to the arguments. + + * tool/upgrade_by_passwd.py (main): Explicitly say it's KEYNO. + 2013-01-28 Niibe Yutaka * src/openpgp-do.c (gpg_pw_get_retry_counter): New. diff --git a/src/openpgp.c b/src/openpgp.c index eb63e86..af686a9 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -1002,7 +1002,7 @@ cmd_external_authenticate (void) DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n"); - if (keyno > 4) + if (keyno >= 4) { GPG_CONDITION_NOT_SATISFIED (); return; diff --git a/tool/gnuk_token.py b/tool/gnuk_token.py index f60e6aa..2de473f 100644 --- a/tool/gnuk_token.py +++ b/tool/gnuk_token.py @@ -432,14 +432,14 @@ class gnuk_token(object): raise ValueError("%02x%02x" % (sw[0], sw[1])) return self.cmd_get_response(sw[1]) - def cmd_external_authenticate(self, signed): - cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[0:128], cls=0x10) + def cmd_external_authenticate(self, keyno, signed): + cmd_data = iso7816_compose(0x82, 0x00, keyno, signed[0:128], cls=0x10) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: raise ValueError(sw) if not (sw[0] == 0x90 and sw[1] == 0x00): raise ValueError("%02x%02x" % (sw[0], sw[1])) - cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[128:]) + cmd_data = iso7816_compose(0x82, 0x00, keyno, signed[128:]) sw = self.icc_send_cmd(cmd_data) if len(sw) != 2: raise ValueError(sw) diff --git a/tool/upgrade_by_passwd.py b/tool/upgrade_by_passwd.py index 92c9e8d..4ef0f0f 100755 --- a/tool/upgrade_by_passwd.py +++ b/tool/upgrade_by_passwd.py @@ -45,14 +45,15 @@ def main(passwd, data_regnual, data_upgrade): gnuk = get_gnuk_device() gnuk.cmd_verify(BY_ADMIN, passwd) - gnuk.cmd_write_binary(1, rsa_raw_pubkey, False) + keyno = 0 + gnuk.cmd_write_binary(1+keyno, rsa_raw_pubkey, False) gnuk.cmd_select_openpgp() challenge = gnuk.cmd_get_challenge() digestinfo = binascii.unhexlify(SHA256_OID_PREFIX) + challenge signed = rsa.compute_signature(rsa_key, digestinfo) signed_bytes = rsa.integer_to_bytes_256(signed) - gnuk.cmd_external_authenticate(signed_bytes) + gnuk.cmd_external_authenticate(keyno, signed_bytes) gnuk.stop_gnuk() mem_info = gnuk.mem_info() print "%08x:%08x" % mem_info From c12f331217b669a73f4a8566f111c4ef68ffdf27 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Mon, 4 Feb 2013 16:40:26 +0900 Subject: [PATCH 300/300] fix typo in openpgp.c --- src/openpgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openpgp.c b/src/openpgp.c index af686a9..867e722 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -154,7 +154,7 @@ cmd_verify (void) else { /* If not, return retry counter, encoded. */ r = gpg_pw_get_retry_counter (p2); - set_res_sw (0x63, 0xc0 | (r&0f)); + set_res_sw (0x63, 0xc0 | (r&0x0f)); } return;