Compare commits
60 Commits
release/0.
...
extended-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48d89973c6 | ||
|
|
60c1fe47ce | ||
|
|
c53afe1f96 | ||
|
|
3074058ff7 | ||
|
|
a0c8cf2ff4 | ||
|
|
c0ab2ae830 | ||
|
|
a08669dfcd | ||
|
|
4a75aa47df | ||
|
|
1145fe0ad8 | ||
|
|
e2a4be1444 | ||
|
|
b4d36a429f | ||
|
|
a955cbec2f | ||
|
|
828b8f5768 | ||
|
|
d9be456fed | ||
|
|
5a9194d136 | ||
|
|
f58233aa5d | ||
|
|
ec409fe8a4 | ||
|
|
231c50d9b5 | ||
|
|
696de23b52 | ||
|
|
b113e6fa7b | ||
|
|
9dcb59f6aa | ||
|
|
351ce68729 | ||
|
|
142dbabfd8 | ||
|
|
1e94b262af | ||
|
|
268c41634a | ||
|
|
bc71c39ea4 | ||
|
|
0232c0a595 | ||
|
|
62520ed0f4 | ||
|
|
2c91633f59 | ||
|
|
1ac7e20fb0 | ||
|
|
e790bb783c | ||
|
|
f45b7a5439 | ||
|
|
6337371016 | ||
|
|
ed7e904aef | ||
|
|
de39c484d0 | ||
|
|
ec7a2db43a | ||
|
|
f3a3808608 | ||
|
|
b2856d162e | ||
|
|
447139f74d | ||
|
|
683253b2eb | ||
|
|
4749062338 | ||
|
|
2181c1a428 | ||
|
|
48f552b69b | ||
|
|
6aca64b664 | ||
|
|
3ec2df97b9 | ||
|
|
94f2c25c3b | ||
|
|
b1bb1354f8 | ||
|
|
1ef7813a53 | ||
|
|
9528867c2a | ||
|
|
241f62238d | ||
|
|
dee75314fc | ||
|
|
8bf1019df7 | ||
|
|
e0b70894db | ||
|
|
8c930952f2 | ||
|
|
09748fc046 | ||
|
|
450807e8bf | ||
|
|
ede8bdc2c0 | ||
|
|
4e1126f88c | ||
|
|
c620b73202 | ||
|
|
2d07cd6f0d |
15
AUTHORS
15
AUTHORS
@@ -6,6 +6,14 @@ Kaz Kojima:
|
|||||||
|
|
||||||
NIIBE Yutaka:
|
NIIBE Yutaka:
|
||||||
Founder of the project.
|
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:
|
Added STBee support:
|
||||||
boards/STBEE/board.c
|
boards/STBEE/board.c
|
||||||
boards/STBEE/board.h
|
boards/STBEE/board.h
|
||||||
@@ -28,6 +36,9 @@ NIIBE Yutaka:
|
|||||||
tool/intel_hex.py
|
tool/intel_hex.py
|
||||||
Wrote a tool for Gnuk:
|
Wrote a tool for Gnuk:
|
||||||
tool/gnuk_put_binary.py
|
tool/gnuk_put_binary.py
|
||||||
|
tool/gnuk_put_binary_libusb.py
|
||||||
|
Wrote a tool for USB Hub:
|
||||||
|
tool/hub_ctrl.py
|
||||||
Wrote:
|
Wrote:
|
||||||
gnuk.svg
|
gnuk.svg
|
||||||
src/configure
|
src/configure
|
||||||
@@ -49,5 +60,9 @@ NIIBE Yutaka:
|
|||||||
src/random.c
|
src/random.c
|
||||||
src/pin-cir.c
|
src/pin-cir.c
|
||||||
src/pin-dial.c
|
src/pin-dial.c
|
||||||
|
src/pin-dnd.c
|
||||||
|
src/usb_msc.c
|
||||||
|
src/usb_msc.h
|
||||||
|
src/neug.c
|
||||||
*
|
*
|
||||||
and others.
|
and others.
|
||||||
|
|||||||
301
ChangeLog
301
ChangeLog
@@ -1,3 +1,304 @@
|
|||||||
|
2011-12-28 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/openpgp-do.c (extended_capabilities) [CERTDO_SUPPORT]:
|
||||||
|
conditionalize.
|
||||||
|
|
||||||
|
2011-12-21 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
* boards/FST_01/board.c: Likewise.
|
||||||
|
|
||||||
|
2011-12-13 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/usb-icc.c: Not include "usb_desc.h".
|
||||||
|
|
||||||
|
* src/usb_endp.c (EP5_OUT_Callback): Fix minor bug.
|
||||||
|
|
||||||
|
2011-12-07 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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
|
||||||
|
information to gpg_thread using memory of cmd_APDU.
|
||||||
|
|
||||||
|
2011-12-01 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* 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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/openpgp.c (cmd_put_data) [PINPAD_SUPPORT]: Support pinpad
|
||||||
|
input (for reset code).
|
||||||
|
|
||||||
|
2011-11-24 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* Version 0.15.
|
||||||
|
* src/usb_desc.c (gnukStringSerial): Updated.
|
||||||
|
|
||||||
|
2011-11-22 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* tool/dfuse.py (DFU_STM32.download, DFU_STM32.verify): Support
|
||||||
|
unaligned write and hole.
|
||||||
|
|
||||||
|
2011-11-14 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* boards/FST_01/{mcuconf.h,board.h,board.c}: New.
|
||||||
|
|
||||||
|
2011-11-01 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/pin-dial.c (pinpad_getline): New.
|
||||||
|
(pin_main): Remove.
|
||||||
|
|
||||||
|
* boards/STBEE_MINI/board.h (TIMx): Define.
|
||||||
|
boards/STBEE/board.h (TIMx): Ditto.
|
||||||
|
boards/STM8S_DISCOVERY/board.h: Ditto.
|
||||||
|
|
||||||
|
* src/pin-cir.c (pinpad_getline): New.
|
||||||
|
(cir_timer_interrupt, cir_ext_interrupt): Use TIMx.
|
||||||
|
(cir_key_is_backspace, cir_key_is_enter, pin_main, pindisp):
|
||||||
|
Remove.
|
||||||
|
(cir_codetable_dell_mr425, cir_codetable_aquos)
|
||||||
|
(cir_codetable_regza, cir_codetable_bravia, ch_is_backspace)
|
||||||
|
(ch_is_enter, find_char_codetable, hex, cir_getchar): New.
|
||||||
|
(cir_timer_interrupt): Don't filter out ADDRESS.
|
||||||
|
|
||||||
|
* src/openpgp.c (get_pinpad_input): Don't invoke thread,
|
||||||
|
but just call pinpad_getline.
|
||||||
|
|
||||||
|
* src/main.c (display_interaction, display_fatal_code)
|
||||||
|
(display_status_code, led_blink): New.
|
||||||
|
(main): Call display_* routine.
|
||||||
|
(fatal): Notify main thread.
|
||||||
|
* src/usb_prop.c (gnuk_device_SetConfiguration): Notify main
|
||||||
|
thread.
|
||||||
|
|
||||||
|
* src/pin-cir.c (pindisp): Remove.
|
||||||
|
|
||||||
|
* boards/FST_01_00: New (for 8MHz FST-01).
|
||||||
|
|
||||||
|
* src/ac.c (calc_md): Fix comparison.
|
||||||
|
|
||||||
|
* src/call-rsa.c (RSA_SIGNATURE_LENGTH): Use KEY_CONTENT_LEN.
|
||||||
|
(rsa_sign, rsa_decrypt): Likewise.
|
||||||
|
(modulus_calc): Don't assume it's 2048-bit.
|
||||||
|
|
||||||
|
* src/ac.c (verify_user_0): Fix for non-initialized PW1.
|
||||||
|
|
||||||
|
* src/Makefile.in (MCFLAGS): Override MCFLAGS option for newer
|
||||||
|
GCC of summon-arm-toolchain to add -mfix-cortex-m3-ldrd.
|
||||||
|
NOTE: This should not be needed (as -mcpu=cortex-m3 defaults
|
||||||
|
to -mfix-cortex-m3-ldrd for GCC-proper), but it is needed
|
||||||
|
to select arm-none-eabi/lib/thumb2/libc.a correctly.
|
||||||
|
|
||||||
|
2011-10-14 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/gnuk.ld.in (__main_stack_size__): It's 1KB (was 512 byte).
|
||||||
|
|
||||||
|
2011-10-07 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* Version 0.14.
|
||||||
|
* src/usb_desc.c (gnukStringSerial): Updated.
|
||||||
|
|
||||||
|
* src/random.c (random_init): Call neug_prng_reseed.
|
||||||
|
|
||||||
|
2011-10-06 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/Makefile.in (random_bits): Remove.
|
||||||
|
|
||||||
|
* src/openpgp.c (GPGthread): Remove unused event message.
|
||||||
|
|
||||||
|
* src/main.c (main): Call random_init.
|
||||||
|
|
||||||
|
* src/gnuk.ld.in (__process_stack_size__): Fix.
|
||||||
|
(.gnuk_random): Removed.
|
||||||
|
|
||||||
|
* src/flash.c (flash_erase_binary, flash_write_binary): Remove
|
||||||
|
support of random_byte in flash ROM.
|
||||||
|
|
||||||
|
* src/neug.c (adccb): Use old API (was: chEvtSignalFlagsI).
|
||||||
|
(adccb_err): Remove.
|
||||||
|
(rng_gen, rng): Add the last argument adccb for adcStartConversion:
|
||||||
|
This is old API of ADC driver.
|
||||||
|
(adcgrpcfg): Remove callbacks, add CONT and SWSTART: This is old
|
||||||
|
API of ADC driver.
|
||||||
|
(adccb): Remove the first argument: This is old API of ADC driver.
|
||||||
|
(neug_wait_full): New.
|
||||||
|
|
||||||
|
* ChibiOS_2.0.8/os/hal/platforms/STM32/adc_lld.h (ADC_SAMPLE_1P5):
|
||||||
|
Add (from new API).
|
||||||
|
|
||||||
|
* src/random.c (random_init): New.
|
||||||
|
(random_bytes_get, random_bytes_free, get_salt): Use NeuG.
|
||||||
|
|
||||||
|
* src/Makefile.in (CSRC): Add neug.c.
|
||||||
|
|
||||||
|
* src/neug.c: New. Verbatim copy of NeuG/src/random.c.
|
||||||
|
|
||||||
|
* boards/common/mcuconf-common.h (USE_STM32_ADC1): TRUE for NewG RNG.
|
||||||
|
* src/chconf.h (CH_USE_SEMAPHORES): TRUE as ADC driver requires it.
|
||||||
|
* src/halconf.h (CH_HAL_USE_ADC); TRUE for NewG RNG.
|
||||||
|
|
||||||
|
2011-07-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* boards/OLIMEX_STM32_H103/board.h (BOARD_NAME): Fixed.
|
||||||
|
|
||||||
|
* boards/STBEE_MINI/mcuconf.h: Added missing include of
|
||||||
|
mcuconf-common.h.
|
||||||
|
|
||||||
|
2011-07-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* ChibiOS_2.0.8/os/ports/GCC/ARMCMx/chcore_v7m.c
|
||||||
|
(_port_irq_epilogue, _port_switch_from_isr): Apply a patch of 2.2.6.
|
||||||
|
|
||||||
|
* ChibiOS_2.0.8/os/hal/platforms/STM32/adc_lld.h: Apply a patch of
|
||||||
|
ADC from the branch of ChibiOS_2.0.X.
|
||||||
|
|
||||||
|
2011-06-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* Version 0.13.
|
||||||
|
* src/usb_desc.c (gnukStringSerial): Updated.
|
||||||
|
|
||||||
|
2011-06-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
|
||||||
|
(MULADDC_1024_CORE, MULADDC_1024_LOOP): New.
|
||||||
|
* polarssl-0.14.0/library/bignum.c (mpi_mul_hlp): Use
|
||||||
|
MULADDC_1024_LOOP.
|
||||||
|
|
||||||
|
2011-05-31 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
|
||||||
|
(MULADDC_HUIT, MULADDC_INIT, MULADDC_CORE, MULADDC_STOP): Tweak.
|
||||||
|
|
||||||
|
2011-05-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* tool/gnuk_put_binary.py (main): Confirm Serial ID is written
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
* src/openpgp.c (cmd_write_binary): Fix FILE_EF_SERIAL comparison.
|
||||||
|
|
||||||
|
* src/gnuk.ld.in (.gnuk_random, .gnuk_ch_certificate): Put LONG to
|
||||||
|
have CONTENTS.
|
||||||
|
|
||||||
|
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
|
||||||
|
(MULADDC_HUIT): New.
|
||||||
|
|
||||||
|
2011-05-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* polarssl-0.14.0/include/polarssl/bn_mul.h [__arm__]
|
||||||
|
(MULADDC_INIT): Add ADDS instruction to clear of carry flag.
|
||||||
|
(MULADDC_CORE): Tune to 6 instructions and less registers.
|
||||||
|
(MULADDC_STOP): Add ADC instruction to save carry flag.
|
||||||
|
|
||||||
|
2011-05-25 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* tool/hub_ctrl.py: New. Port of original C implementation.
|
||||||
|
|
||||||
|
2011-05-16 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/main.c (main): Call flash_unlock at the beginning.
|
||||||
|
(device_initialize_once): Don't call flash_unlock here.
|
||||||
|
* src/flash.c (flash_init): Likewise.
|
||||||
|
|
||||||
|
* src/openpgp.c (cmd_select_file): Don't use write_res_apdu.
|
||||||
|
(set_res_apdu): Rename from write_res_apdu. Just SW1 and SW2.
|
||||||
|
|
||||||
2011-05-13 NIIBE Yutaka <gniibe@fsij.org>
|
2011-05-13 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* Version 0.12.
|
* Version 0.12.
|
||||||
|
|||||||
@@ -62,6 +62,20 @@
|
|||||||
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
|
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
|
||||||
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
|
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Sampling rates
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */
|
||||||
|
#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver pre-compile time settings. */
|
/* Driver pre-compile time settings. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
@@ -238,26 +252,51 @@ typedef struct {
|
|||||||
/* Driver macros. */
|
/* Driver macros. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Number of channels in a conversion sequence.
|
||||||
|
*/
|
||||||
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
|
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
|
||||||
|
|
||||||
#define ADC_SQR3_SQ0_N(n) ((n) << 0)
|
#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
|
||||||
#define ADC_SQR3_SQ1_N(n) ((n) << 5)
|
#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
|
||||||
#define ADC_SQR3_SQ2_N(n) ((n) << 10)
|
#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
|
||||||
#define ADC_SQR3_SQ3_N(n) ((n) << 15)
|
#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
|
||||||
#define ADC_SQR3_SQ4_N(n) ((n) << 20)
|
#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
|
||||||
#define ADC_SQR3_SQ5_N(n) ((n) << 25)
|
#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
|
||||||
|
|
||||||
#define ADC_SQR2_SQ6_N(n) ((n) << 0)
|
#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
|
||||||
#define ADC_SQR2_SQ7_N(n) ((n) << 5)
|
#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
|
||||||
#define ADC_SQR2_SQ8_N(n) ((n) << 10)
|
#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
|
||||||
#define ADC_SQR2_SQ9_N(n) ((n) << 15)
|
#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
|
||||||
#define ADC_SQR2_SQ10_N(n) ((n) << 20)
|
#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
|
||||||
#define ADC_SQR2_SQ11_N(n) ((n) << 25)
|
#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
|
||||||
|
|
||||||
#define ADC_SQR1_SQ13_N(n) ((n) << 0)
|
#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
|
||||||
#define ADC_SQR1_SQ14_N(n) ((n) << 5)
|
#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
|
||||||
#define ADC_SQR1_SQ15_N(n) ((n) << 10)
|
#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
|
||||||
#define ADC_SQR1_SQ16_N(n) ((n) << 15)
|
#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
|
||||||
|
|
||||||
|
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
|
||||||
|
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
|
||||||
|
|
||||||
|
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
|
||||||
|
sampling time. */
|
||||||
|
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
|
||||||
|
sampling time. */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ void SVCallVector(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reschedule verification and setup after an IRQ.
|
* @brief Exception exit redirection to _port_switch_from_isr().
|
||||||
*/
|
*/
|
||||||
void _port_irq_epilogue(void) {
|
void _port_irq_epilogue(void) {
|
||||||
|
|
||||||
port_lock_from_isr();
|
port_lock_from_isr();
|
||||||
if ((SCB_ICSR & ICSR_RETTOBASE) && chSchIsRescRequiredExI()) {
|
if ((SCB_ICSR & ICSR_RETTOBASE)) {
|
||||||
register struct extctx *ctxp;
|
register struct extctx *ctxp;
|
||||||
|
|
||||||
/* Adding an artificial exception return context, there is no need to
|
/* Adding an artificial exception return context, there is no need to
|
||||||
@@ -126,7 +126,6 @@ void _port_irq_epilogue(void) {
|
|||||||
order to keep the rest of the context switching atomic.*/
|
order to keep the rest of the context switching atomic.*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* ISR exit without context switching.*/
|
|
||||||
port_unlock_from_isr();
|
port_unlock_from_isr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +138,8 @@ __attribute__((naked))
|
|||||||
#endif
|
#endif
|
||||||
void _port_switch_from_isr(void) {
|
void _port_switch_from_isr(void) {
|
||||||
|
|
||||||
chSchDoRescheduleI();
|
if (chSchIsRescRequiredExI())
|
||||||
|
chSchDoRescheduleI();
|
||||||
asm volatile ("svc #0");
|
asm volatile ("svc #0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
101
NEWS
101
NEWS
@@ -1,5 +1,106 @@
|
|||||||
Gnuk NEWS - User visible changes
|
Gnuk NEWS - User visible changes
|
||||||
|
|
||||||
|
* Major changes in Gnuk 0.17
|
||||||
|
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
|
||||||
|
** 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
|
||||||
|
|
||||||
|
** 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.
|
||||||
|
|
||||||
|
** 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
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
Note that only four controllers (of Dell, Sharp, Sony, and Toshiba)
|
||||||
|
are supported and tested.
|
||||||
|
|
||||||
|
** It is possible for users to keep using OPENPGP_CARD_INITIAL_PW1
|
||||||
|
With a bug fix of verify_user_0, it's now possible. Although it's not
|
||||||
|
recommended.
|
||||||
|
|
||||||
|
** Important bug fix and a workaround
|
||||||
|
In version 0.14, __main_stack_size__ (for interrupt handler) was too
|
||||||
|
small for some cases. This is fixed in 0.15.
|
||||||
|
|
||||||
|
In src/Makefile.in, added -mfix-cortex-m3-ldrd for correctly linking C
|
||||||
|
library for thumb2. This is needed for newer summon-arm-toolchain.
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Gnuk 0.14
|
||||||
|
|
||||||
|
Released 2011-10-07, by NIIBE Yutaka
|
||||||
|
|
||||||
|
** Random number generator change
|
||||||
|
NeuG, Gniibe's True RNG implementation for STM32F103, has been
|
||||||
|
integrated to Gnuk. It is not needed to put random number bytes
|
||||||
|
(generated by host) to Token any more.
|
||||||
|
|
||||||
|
|
||||||
|
* Major changes in Gnuk 0.13
|
||||||
|
|
||||||
|
Released 2011-06-15, by NIIBE Yutaka
|
||||||
|
|
||||||
|
** Improved RSA routine.
|
||||||
|
About 20% speed improvement.
|
||||||
|
|
||||||
|
** New tool: hub_ctrl.
|
||||||
|
It is a Python implementation ported from original C implementation.
|
||||||
|
It is useful for development of USB target if you have a good hub.
|
||||||
|
You can power off/on the port to reset Gnuk Token.
|
||||||
|
|
||||||
|
|
||||||
* Major changes in Gnuk 0.12
|
* Major changes in Gnuk 0.12
|
||||||
|
|
||||||
Released 2011-05-13, by NIIBE Yutaka
|
Released 2011-05-13, by NIIBE Yutaka
|
||||||
|
|||||||
151
README
151
README
@@ -1,7 +1,7 @@
|
|||||||
Gnuk - software for GnuPG USB Token
|
Gnuk - software for GnuPG USB Token
|
||||||
|
|
||||||
Version 0.12
|
Version 0.16
|
||||||
2011-05-13
|
2011-12-14
|
||||||
Niibe Yutaka
|
Niibe Yutaka
|
||||||
Free Software Initiative of Japan
|
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 is software implementation of a USB token for GNU Privacy Guard.
|
||||||
Gnuk supports OpenPGP card protocol version 2, and it runs on STM32
|
Gnuk supports OpenPGP card protocol version 2, and it runs on
|
||||||
processor.
|
STM32F103 processor.
|
||||||
|
|
||||||
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
|
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.
|
been nervous of storing secret key(s) on usual secondary storage.
|
||||||
@@ -19,15 +19,15 @@ me to bring a card reader all the time. With Gnuk, this issue will be
|
|||||||
solved by a USB token which is small enough.
|
solved by a USB token which is small enough.
|
||||||
|
|
||||||
Please look at the graphics of "gnuk.svg" for the software name. My
|
Please look at the graphics of "gnuk.svg" for the software name. My
|
||||||
son used to be with his NUK(R), always, everywhere. I will be with a
|
son used to be with his NUK(R), always, everywhere. I am with a USB
|
||||||
USB Token by "Gnuk" everywhere.
|
Token by "Gnuk", always, everywhere.
|
||||||
|
|
||||||
|
|
||||||
FAQ
|
FAQ
|
||||||
===
|
===
|
||||||
|
|
||||||
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
|
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
|
||||||
card 2.0, GPF Crypto Stick, etc) ?
|
card 2.0, GPF Crypto Stick, etc.) ?
|
||||||
http://www.g10code.de/p-card.html
|
http://www.g10code.de/p-card.html
|
||||||
http://www.privacyfoundation.de/crypto_stick/
|
http://www.privacyfoundation.de/crypto_stick/
|
||||||
A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
|
A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
|
||||||
@@ -44,16 +44,18 @@ A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
|
|||||||
(GNU Toolchain, Python, etc.),
|
(GNU Toolchain, Python, etc.),
|
||||||
"for Free Software"; Gnuk supports GnuPG.
|
"for Free Software"; Gnuk supports GnuPG.
|
||||||
|
|
||||||
Q1: What's kind of key algorithm is supported?
|
Q1: What kind of key algorithm is supported?
|
||||||
A1: Gnuk only supports 2048-bit RSA.
|
A1: Gnuk only supports 2048-bit RSA.
|
||||||
|
|
||||||
Q2: How long does it take for digital signing?
|
Q2: How long does it take for digital signing?
|
||||||
A2: It takes two seconds or so.
|
A2: It takes a second and a half or so.
|
||||||
|
|
||||||
Q3: What's your recommendation for target board?
|
Q3: What's your recommendation for target board?
|
||||||
A3: Orthodox choice is Olimex STM32-H103.
|
A3: Orthodox choice is Olimex STM32-H103.
|
||||||
If you have skill of electronics and like DIY, STM32 part of STM8S
|
If you have skill of electronics and like DIY, STM32 part of STM8S
|
||||||
Discovery Kit might be the best choice.
|
Discovery Kit might be the best choice.
|
||||||
|
Currently FST-01 (Flying Stone Tiny 01) is under development,
|
||||||
|
it will be the best choice, hopefully.
|
||||||
|
|
||||||
Q4: What's version of GnuPG are you using?
|
Q4: What's version of GnuPG are you using?
|
||||||
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
|
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
|
||||||
@@ -88,17 +90,28 @@ A9: GnuPG's SCDaemon has problems for handling insertion/removal of
|
|||||||
and confirm scdaemon doesn't exist, then,
|
and confirm scdaemon doesn't exist, then,
|
||||||
$ gpg-connect-agent learn /bye
|
$ gpg-connect-agent learn /bye
|
||||||
|
|
||||||
|
Qa: With GNOME, I can't use Gnuk Token for SSH. How can we use it for SSH?
|
||||||
|
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
|
||||||
|
gpg-agant for the role of ssh-agent. For gnome-keyring please do:
|
||||||
|
|
||||||
|
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||||
|
|
||||||
|
Qb: With GNOME 3, I can't use Gnuk Token at all. Why?
|
||||||
|
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
|
||||||
|
|
||||||
|
$ gnome-session-properties
|
||||||
|
|
||||||
|
and at the tab of "Startup Programs", disable check buttons for
|
||||||
|
"GPG Password Agent" and "SSH Key Agent".
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Release notes
|
Release notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is thirteenth 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.
|
usages and it is considered stable, it is still somewhat experimental.
|
||||||
|
|
||||||
Note that you need to write random bits after installation of gnuk
|
|
||||||
executable to the chip. This procedure is required to share a single
|
|
||||||
executable among multiple devices.
|
|
||||||
|
|
||||||
Tested features are:
|
Tested features are:
|
||||||
|
|
||||||
* Personalization of the card
|
* Personalization of the card
|
||||||
@@ -121,22 +134,23 @@ It is known not-working well:
|
|||||||
work well. Please disable DEBUG option if it doesn't work well.
|
work well. Please disable DEBUG option if it doesn't work well.
|
||||||
|
|
||||||
* Card holder certificate
|
* Card holder certificate
|
||||||
It is implemented in Gnuk side. But its size matters (>
|
It is implemented in Gnuk side. But its large size matters
|
||||||
1KB). GnuPG cannot handle a data object of large size with
|
(> 1KB). Some versions of GnuPG cannot handle a data object
|
||||||
PC/SC backend. Specifically, handle_transmit function in
|
of large size with PC/SC backend. Specifically,
|
||||||
pcsc-wrapper.c uses the buffer of size 1024-byte.
|
handle_transmit function in pcsc-wrapper.c uses the buffer
|
||||||
|
of size 1024-byte.
|
||||||
|
|
||||||
Not supported feature(s):
|
Not supported feature(s):
|
||||||
|
|
||||||
* Overriding key import. You need to remove all keys first.
|
* Overriding key import. You need to remove all keys first.
|
||||||
* Key generation
|
* Key generation on device side
|
||||||
|
|
||||||
|
|
||||||
Targets
|
Targets
|
||||||
=======
|
=======
|
||||||
|
|
||||||
We use Olimex STM32-H103 board. We also use STM32 part of STM8S
|
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We
|
||||||
Discovery Kit.
|
also use STM32 part of STM8S Discovery Kit.
|
||||||
|
|
||||||
With DfuSe support, CQ STARM, STBee, and STBee Mini are also our
|
With DfuSe support, CQ STARM, STBee, and STBee Mini are also our
|
||||||
targets. But those targets with DfuSe are basically not for normal
|
targets. But those targets with DfuSe are basically not for normal
|
||||||
@@ -159,6 +173,16 @@ Another PIN-pad support is connecting rotary encoder, push switch and
|
|||||||
7-segment LED display. Both of PIN verification and PIN modification
|
7-segment LED display. Both of PIN verification and PIN modification
|
||||||
are supported for this circuit extension.
|
are supported for this circuit extension.
|
||||||
|
|
||||||
|
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
|
Souce code
|
||||||
==========
|
==========
|
||||||
@@ -179,8 +203,8 @@ The author(s) of Gnuk expect users of Gnuk will be able to access the
|
|||||||
source code of Gnuk, so that users can study the code and can modify
|
source code of Gnuk, so that users can study the code and can modify
|
||||||
if needed. This doesn't mean person who has a USB Token by Gnuk
|
if needed. This doesn't mean person who has a USB Token by Gnuk
|
||||||
should be able to acess everything on the Token, regardless of its
|
should be able to acess everything on the Token, regardless of its
|
||||||
protections. Private keys, random bytes, and other information should
|
protections. Private keys, and other information should be protected
|
||||||
be protected properly.
|
properly.
|
||||||
|
|
||||||
|
|
||||||
External source code
|
External source code
|
||||||
@@ -200,6 +224,9 @@ Gnuk is distributed with external source code.
|
|||||||
We use PolarSSL for RSA computation, AES encryption/decryption
|
We use PolarSSL for RSA computation, AES encryption/decryption
|
||||||
and SHA-1 computation.
|
and SHA-1 computation.
|
||||||
|
|
||||||
|
The file include/polarssl/bn_mul.h is heavily modified for ARM
|
||||||
|
Cortex-M3.
|
||||||
|
|
||||||
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
|
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
|
||||||
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
|
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
|
||||||
|
|
||||||
@@ -229,8 +256,24 @@ How to compile
|
|||||||
|
|
||||||
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||||
|
|
||||||
See http://github.com/esden/summon-arm-toolchain/ for preparation of
|
See http://github.com/esden/summon-arm-toolchain/ (which includes fix
|
||||||
GNU Toolchain for 'arm-none-eabi' target.
|
of binutils-2.21.1) for preparation of GNU Toolchain for
|
||||||
|
'arm-none-eabi' target.
|
||||||
|
|
||||||
|
# Note that we need to link correct C library (for string functions).
|
||||||
|
# For this purpose, Makefile.in contains following line:
|
||||||
|
#
|
||||||
|
# MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
|
||||||
|
#
|
||||||
|
# This should not be needed (as -mcpu=cortex-m3 means
|
||||||
|
# -mfix-cortex-m3-ldrd), but in practice it is needed for
|
||||||
|
# the configuration of patch-gcc-config-arm-t-arm-elf.diff in
|
||||||
|
# summon-arm-toolchain.
|
||||||
|
#
|
||||||
|
# In ChibiOS_2.0.8/os/ports/GCC/ARM/rules.mk, it specifies
|
||||||
|
# -mno-thumb-interwork option. This means that you should not
|
||||||
|
# link C library which contains ARM (not Thumb) code.
|
||||||
|
|
||||||
|
|
||||||
Change directory to `src':
|
Change directory to `src':
|
||||||
|
|
||||||
@@ -267,6 +310,36 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
|||||||
$
|
$
|
||||||
|
|
||||||
|
|
||||||
|
Flying Stone Tiny 01
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
If you are using Flying Stone Tiny 01, you need a SWD writer. I am
|
||||||
|
using revision 946 of Simon Qian's Versaloon.
|
||||||
|
|
||||||
|
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
|
||||||
|
|
||||||
|
For OpenOCD, we need unofficial patch.
|
||||||
|
|
||||||
|
See the article of Versaloon Forum:
|
||||||
|
|
||||||
|
http://www.versaloon.com/bbs/viewtopic.php?p=16179
|
||||||
|
|
||||||
|
|
||||||
|
Type following to invoke OpenOCD:
|
||||||
|
|
||||||
|
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
|
||||||
|
|
||||||
|
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||||
|
|
||||||
|
$ telnet localhost 4444
|
||||||
|
> reset halt
|
||||||
|
> flash write_image erase gnuk.elf
|
||||||
|
> reset
|
||||||
|
> exit
|
||||||
|
$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STM8S Discovery Kit
|
STM8S Discovery Kit
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@@ -338,19 +411,7 @@ How to configure
|
|||||||
You need python and pyscard (python-pyscard package in Debian) or
|
You need python and pyscard (python-pyscard package in Debian) or
|
||||||
PyUSB (python-usb package in Debian).
|
PyUSB (python-usb package in Debian).
|
||||||
|
|
||||||
(1) In the 'src' directory, type
|
(1) [pyscard] Stop scdaemon
|
||||||
|
|
||||||
$ make random_bits
|
|
||||||
|
|
||||||
In this process, it takes time for the command of
|
|
||||||
|
|
||||||
dd if=/dev/random bs=1 of=random_bits count=1024
|
|
||||||
|
|
||||||
Don't just wait, but do some other works on your PC.
|
|
||||||
/dev/random needs entropy to finish.
|
|
||||||
|
|
||||||
|
|
||||||
(2) [pyscard] Stop scdaemon
|
|
||||||
[PyUSB] Stop the pcsc daemon.
|
[PyUSB] Stop the pcsc daemon.
|
||||||
|
|
||||||
If scdaemon is running, please kill it, or you will get "Smartcard
|
If scdaemon is running, please kill it, or you will get "Smartcard
|
||||||
@@ -363,17 +424,7 @@ In case of PyUSB tool, you need to stop pcscd.
|
|||||||
# /etc/init.d/pcscd stop
|
# /etc/init.d/pcscd stop
|
||||||
|
|
||||||
|
|
||||||
(3) Write the random bits to the device
|
(2) [Optional] Write fixed serial number
|
||||||
|
|
||||||
Connect your board to USB port of your PC. And invoke gnuk_put_binary.py:
|
|
||||||
|
|
||||||
$ ../tool/gnuk_put_binary.py -r random_bits
|
|
||||||
random_bits: 1024
|
|
||||||
Updating random bits
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
(4) [Optional] Write fixed serial number
|
|
||||||
|
|
||||||
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
|
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
|
||||||
|
|
||||||
@@ -381,7 +432,7 @@ If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
|
|||||||
Writing serial number
|
Writing serial number
|
||||||
...
|
...
|
||||||
|
|
||||||
(5) [Optional] Write card holder certificate
|
(3) [Optional] Write card holder certificate
|
||||||
|
|
||||||
If you have card holder certificate binary file, you can do:
|
If you have card holder certificate binary file, you can do:
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
#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_INT_SIZE 8
|
||||||
|
|
||||||
#define VIRTUAL_COM_PORT_SIZ_DEVICE_DESC 18
|
#define VIRTUAL_COM_PORT_SIZ_DEVICE_DESC 18
|
||||||
|
|||||||
107
boards/FST_01/board.c
Normal file
107
boards/FST_01/board.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#include "../common/hwinit.c"
|
||||||
|
|
||||||
|
void
|
||||||
|
hwinit0 (void)
|
||||||
|
{
|
||||||
|
hwinit0_common ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hwinit1 (void)
|
||||||
|
{
|
||||||
|
hwinit1_common ();
|
||||||
|
|
||||||
|
#if defined(PINPAD_CIR_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_CIR_SUPPORT)
|
||||||
|
void
|
||||||
|
cir_ext_disable (void)
|
||||||
|
{
|
||||||
|
EXTI->PR = EXTI_PR_PR2;
|
||||||
|
EXTI->IMR &= ~EXTI_IMR_MR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cir_ext_enable (void)
|
||||||
|
{
|
||||||
|
EXTI->IMR |= EXTI_IMR_MR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void cir_ext_interrupt (void);
|
||||||
|
extern void cir_timer_interrupt (void);
|
||||||
|
|
||||||
|
CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
||||||
|
{
|
||||||
|
CH_IRQ_PROLOGUE ();
|
||||||
|
chSysLockFromIsr ();
|
||||||
|
|
||||||
|
cir_ext_interrupt ();
|
||||||
|
|
||||||
|
chSysUnlockFromIsr ();
|
||||||
|
CH_IRQ_EPILOGUE ();
|
||||||
|
}
|
||||||
|
|
||||||
|
CH_IRQ_HANDLER (TIM2_IRQHandler)
|
||||||
|
{
|
||||||
|
CH_IRQ_PROLOGUE();
|
||||||
|
chSysLockFromIsr();
|
||||||
|
|
||||||
|
cir_timer_interrupt ();
|
||||||
|
|
||||||
|
chSysUnlockFromIsr();
|
||||||
|
CH_IRQ_EPILOGUE();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
138
boards/FST_01/board.h
Normal file
138
boards/FST_01/board.h
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A special exception to the GPL can be applied should you wish to distribute
|
||||||
|
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||||
|
the source code for any proprietary components. See the file exception.txt
|
||||||
|
for full details of how and when the exception can be applied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BOARD_H_
|
||||||
|
#define _BOARD_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup for the FST-01 board.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board identifier.
|
||||||
|
*/
|
||||||
|
#define BOARD_FST_01
|
||||||
|
#define BOARD_NAME "FST-01"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board frequencies.
|
||||||
|
*/
|
||||||
|
#define STM32_LSECLK 32768
|
||||||
|
#define STM32_HSECLK 12000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
|
||||||
|
* native STM32 HAL.
|
||||||
|
*/
|
||||||
|
#define STM32F10X_MD
|
||||||
|
#define CPU_WITH_NO_GPIOE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IO pins assignments.
|
||||||
|
*/
|
||||||
|
#define GPIOB_LED 0
|
||||||
|
#define GPIOA_USB_ENABLE 10
|
||||||
|
#define GPIOA_SPI1NSS 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O ports initial setup, this configuration is established soon after reset
|
||||||
|
* in the initialization code.
|
||||||
|
*
|
||||||
|
* The digits have the following meaning:
|
||||||
|
* 0 - Analog input.
|
||||||
|
* 1 - Push Pull output 10MHz.
|
||||||
|
* 2 - Push Pull output 2MHz.
|
||||||
|
* 3 - Push Pull output 50MHz.
|
||||||
|
* 4 - Digital input.
|
||||||
|
* 5 - Open Drain output 10MHz.
|
||||||
|
* 6 - Open Drain output 2MHz.
|
||||||
|
* 7 - Open Drain output 50MHz.
|
||||||
|
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
|
||||||
|
* 9 - Alternate Push Pull output 10MHz.
|
||||||
|
* A - Alternate Push Pull output 2MHz.
|
||||||
|
* B - Alternate Push Pull output 50MHz.
|
||||||
|
* C - Reserved.
|
||||||
|
* D - Alternate Open Drain output 10MHz.
|
||||||
|
* E - Alternate Open Drain output 2MHz.
|
||||||
|
* F - Alternate Open Drain output 50MHz.
|
||||||
|
* Please refer to the STM32 Reference Manual for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port A setup.
|
||||||
|
* PA0 - input with pull-up (TIM2_CH1)
|
||||||
|
* PA1 - input with pull-down (TIM2_CH2)
|
||||||
|
* PA2 - input with pull-up (TIM2_CH3)
|
||||||
|
* PA11 - input with pull-up (USBDM)
|
||||||
|
* PA12 - input with pull-up (USBDP)
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
* PA10 - Push pull output (USB 1:ON 0:OFF)
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
|
||||||
|
#define VAL_GPIOACRH 0x88888388 /* PA15...PA8 */
|
||||||
|
#define VAL_GPIOAODR 0xFFFFFFFD
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port B setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
* PB0 - Push pull output (LED 1:ON 0:OFF)
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOBCRL 0x88888883 /* PB7...PB0 */
|
||||||
|
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
|
||||||
|
#define VAL_GPIOBODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port C setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
|
||||||
|
#define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */
|
||||||
|
#define VAL_GPIOCODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port D setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
* PD0 - Normal input (XTAL).
|
||||||
|
* PD1 - Normal input (XTAL).
|
||||||
|
*/
|
||||||
|
#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
|
||||||
|
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
|
||||||
|
#define VAL_GPIODODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port E setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
|
||||||
|
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
|
||||||
|
#define VAL_GPIOEODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
#endif /* _BOARD_H_ */
|
||||||
15
boards/FST_01/mcuconf.h
Normal file
15
boards/FST_01/mcuconf.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* HAL driver system settings.
|
||||||
|
*/
|
||||||
|
#define STM32_SW STM32_SW_PLL
|
||||||
|
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||||
|
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||||
|
#define STM32_PLLMUL_VALUE 6
|
||||||
|
#define STM32_HPRE STM32_HPRE_DIV1
|
||||||
|
#define STM32_PPRE1 STM32_PPRE1_DIV2
|
||||||
|
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||||
|
#define STM32_ADCPRE STM32_ADCPRE_DIV4
|
||||||
|
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||||
|
#define STM32_MCO STM32_MCO_NOCLOCK
|
||||||
|
|
||||||
|
#include "mcuconf-common.h"
|
||||||
36
boards/FST_01_00/board.c
Normal file
36
boards/FST_01_00/board.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#include "../common/hwinit.c"
|
||||||
|
|
||||||
|
void
|
||||||
|
hwinit0 (void)
|
||||||
|
{
|
||||||
|
hwinit0_common ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hwinit1 (void)
|
||||||
|
{
|
||||||
|
hwinit1_common ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
USB_Cable_Config (int NewState)
|
||||||
|
{
|
||||||
|
if (NewState != DISABLE)
|
||||||
|
palSetPad (IOPORT1, GPIOA_USB_ENABLE);
|
||||||
|
else
|
||||||
|
palClearPad (IOPORT1, GPIOA_USB_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_led (int value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
palSetPad (IOPORT1, GPIOA_LED);
|
||||||
|
else
|
||||||
|
palClearPad (IOPORT1, GPIOA_LED);
|
||||||
|
}
|
||||||
129
boards/FST_01_00/board.h
Normal file
129
boards/FST_01_00/board.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||||
|
|
||||||
|
This file is part of ChibiOS/RT.
|
||||||
|
|
||||||
|
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A special exception to the GPL can be applied should you wish to distribute
|
||||||
|
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||||
|
the source code for any proprietary components. See the file exception.txt
|
||||||
|
for full details of how and when the exception can be applied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BOARD_H_
|
||||||
|
#define _BOARD_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup for the FST-01 board (experimental version 00).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board identifier.
|
||||||
|
*/
|
||||||
|
#define BOARD_FST_01
|
||||||
|
#define BOARD_NAME "FST-01-00"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Board frequencies.
|
||||||
|
*/
|
||||||
|
#define STM32_LSECLK 32768
|
||||||
|
#define STM32_HSECLK 8000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
|
||||||
|
* native STM32 HAL.
|
||||||
|
*/
|
||||||
|
#define STM32F10X_MD
|
||||||
|
#define CPU_WITH_NO_GPIOE 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IO pins assignments.
|
||||||
|
*/
|
||||||
|
#define GPIOA_LED 8
|
||||||
|
#define GPIOA_USB_ENABLE 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I/O ports initial setup, this configuration is established soon after reset
|
||||||
|
* in the initialization code.
|
||||||
|
*
|
||||||
|
* The digits have the following meaning:
|
||||||
|
* 0 - Analog input.
|
||||||
|
* 1 - Push Pull output 10MHz.
|
||||||
|
* 2 - Push Pull output 2MHz.
|
||||||
|
* 3 - Push Pull output 50MHz.
|
||||||
|
* 4 - Digital input.
|
||||||
|
* 5 - Open Drain output 10MHz.
|
||||||
|
* 6 - Open Drain output 2MHz.
|
||||||
|
* 7 - Open Drain output 50MHz.
|
||||||
|
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
|
||||||
|
* 9 - Alternate Push Pull output 10MHz.
|
||||||
|
* A - Alternate Push Pull output 2MHz.
|
||||||
|
* B - Alternate Push Pull output 50MHz.
|
||||||
|
* C - Reserved.
|
||||||
|
* D - Alternate Open Drain output 10MHz.
|
||||||
|
* E - Alternate Open Drain output 2MHz.
|
||||||
|
* F - Alternate Open Drain output 50MHz.
|
||||||
|
* Please refer to the STM32 Reference Manual for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port A setup.
|
||||||
|
* PA11 - input with pull-up (USBDM)
|
||||||
|
* PA12 - input with pull-up (USBDP)
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
* PA8 - Push pull output (LED 1:ON 0:OFF)
|
||||||
|
* PA10 - Push pull output (USB 1:ON 0:OFF)
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
|
||||||
|
#define VAL_GPIOACRH 0x88888383 /* PA15...PA8 */
|
||||||
|
#define VAL_GPIOAODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port B setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
|
||||||
|
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
|
||||||
|
#define VAL_GPIOBODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port C setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
|
||||||
|
#define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */
|
||||||
|
#define VAL_GPIOCODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port D setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
* PD0 - Normal input (XTAL).
|
||||||
|
* PD1 - Normal input (XTAL).
|
||||||
|
*/
|
||||||
|
#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
|
||||||
|
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
|
||||||
|
#define VAL_GPIODODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Port E setup.
|
||||||
|
* Everything input with pull-up except:
|
||||||
|
*/
|
||||||
|
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
|
||||||
|
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
|
||||||
|
#define VAL_GPIOEODR 0xFFFFFFFF
|
||||||
|
|
||||||
|
#endif /* _BOARD_H_ */
|
||||||
15
boards/FST_01_00/mcuconf.h
Normal file
15
boards/FST_01_00/mcuconf.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* HAL driver system settings.
|
||||||
|
*/
|
||||||
|
#define STM32_SW STM32_SW_PLL
|
||||||
|
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||||
|
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||||
|
#define STM32_PLLMUL_VALUE 9
|
||||||
|
#define STM32_HPRE STM32_HPRE_DIV1
|
||||||
|
#define STM32_PPRE1 STM32_PPRE1_DIV2
|
||||||
|
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||||
|
#define STM32_ADCPRE STM32_ADCPRE_DIV4
|
||||||
|
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||||
|
#define STM32_MCO STM32_MCO_NOCLOCK
|
||||||
|
|
||||||
|
#include "mcuconf-common.h"
|
||||||
@@ -28,14 +28,14 @@
|
|||||||
#define _BOARD_H_
|
#define _BOARD_H_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup for the Olimex STM32-P103 proto board.
|
* Setup for the Olimex STM32-H103 proto board.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Board identifier.
|
* Board identifier.
|
||||||
*/
|
*/
|
||||||
#define BOARD_OLIMEX_STM32_P103
|
#define BOARD_OLIMEX_STM32_H103
|
||||||
#define BOARD_NAME "Olimex STM32-P103"
|
#define BOARD_NAME "Olimex STM32-H103"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Board frequencies.
|
* Board frequencies.
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ hwinit1 (void)
|
|||||||
{
|
{
|
||||||
hwinit1_common ();
|
hwinit1_common ();
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
/* EXTI0 <= PB0 */
|
/* EXTI0 <= PB0 */
|
||||||
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
|
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
|
||||||
@@ -69,7 +68,6 @@ hwinit1 (void)
|
|||||||
/* Generate UEV to upload PSC and ARR */
|
/* Generate UEV to upload PSC and ARR */
|
||||||
TIM4->EGR = TIM_EGR_UG;
|
TIM4->EGR = TIM_EGR_UG;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -90,7 +88,6 @@ set_led (int value)
|
|||||||
palSetPad (IOPORT4, GPIOD_LED1);
|
palSetPad (IOPORT4, GPIOD_LED1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
void
|
void
|
||||||
cir_ext_disable (void)
|
cir_ext_disable (void)
|
||||||
@@ -156,4 +153,3 @@ CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
|||||||
CH_IRQ_EPILOGUE ();
|
CH_IRQ_EPILOGUE ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -38,8 +38,12 @@
|
|||||||
#define BOARD_STBEE
|
#define BOARD_STBEE
|
||||||
#define BOARD_NAME "STBee"
|
#define BOARD_NAME "STBee"
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
|
||||||
#define HAVE_7SEGLED 1
|
#define HAVE_7SEGLED 1
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -85,7 +89,7 @@
|
|||||||
* Please refer to the STM32 Reference Manual for details.
|
* 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.
|
* Port A setup.
|
||||||
* PA6 - (TIM3_CH1) input with pull-up
|
* PA6 - (TIM3_CH1) input with pull-up
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ hwinit1 (void)
|
|||||||
{
|
{
|
||||||
hwinit1_common ();
|
hwinit1_common ();
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT)
|
||||||
palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */
|
palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */
|
||||||
while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0)
|
while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0)
|
||||||
; /* Wait for JTAG debugger connection */
|
; /* Wait for JTAG debugger connection */
|
||||||
palWritePort(IOPORT2, 0xffff); /* All set */
|
palWritePort(IOPORT2, 0xffff); /* All set */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
/* EXTI0 <= PB0 */
|
/* EXTI0 <= PB0 */
|
||||||
@@ -73,7 +74,6 @@ hwinit1 (void)
|
|||||||
TIM4->ARR = 31;
|
TIM4->ARR = 31;
|
||||||
/* Generate UEV to upload PSC and ARR */
|
/* Generate UEV to upload PSC and ARR */
|
||||||
TIM4->EGR = TIM_EGR_UG;
|
TIM4->EGR = TIM_EGR_UG;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
|
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
|
||||||
@@ -101,7 +101,6 @@ set_led (int value)
|
|||||||
palSetPad (IOPORT1, GPIOA_LED1);
|
palSetPad (IOPORT1, GPIOA_LED1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
void
|
void
|
||||||
cir_ext_disable (void)
|
cir_ext_disable (void)
|
||||||
@@ -167,4 +166,3 @@ CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
|||||||
CH_IRQ_EPILOGUE ();
|
CH_IRQ_EPILOGUE ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -39,8 +39,12 @@
|
|||||||
#define BOARD_NAME "STBee Mini"
|
#define BOARD_NAME "STBee Mini"
|
||||||
#define CPU_WITH_NO_GPIOE 1
|
#define CPU_WITH_NO_GPIOE 1
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
|
||||||
#define HAVE_7SEGLED 1
|
#define HAVE_7SEGLED 1
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -88,7 +92,7 @@
|
|||||||
* Please refer to the STM32 Reference Manual for details.
|
* 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.
|
* Port A setup.
|
||||||
* PA6 - (TIM3_CH1) input with pull-up
|
* PA6 - (TIM3_CH1) input with pull-up
|
||||||
|
|||||||
@@ -10,3 +10,5 @@
|
|||||||
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||||
#define STM32_ADCPRE STM32_ADCPRE_DIV4
|
#define STM32_ADCPRE STM32_ADCPRE_DIV4
|
||||||
#define STM32_MCO STM32_MCO_NOCLOCK
|
#define STM32_MCO STM32_MCO_NOCLOCK
|
||||||
|
|
||||||
|
#include "mcuconf-common.h"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ hwinit1 (void)
|
|||||||
{
|
{
|
||||||
hwinit1_common ();
|
hwinit1_common ();
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
/* EXTI5 <= PB5 */
|
/* EXTI5 <= PB5 */
|
||||||
AFIO->EXTICR[1] = AFIO_EXTICR2_EXTI5_PB;
|
AFIO->EXTICR[1] = AFIO_EXTICR2_EXTI5_PB;
|
||||||
EXTI->IMR = 0;
|
EXTI->IMR = 0;
|
||||||
@@ -62,7 +62,7 @@ set_led (int value)
|
|||||||
palClearPad (IOPORT1, GPIOA_LED);
|
palClearPad (IOPORT1, GPIOA_LED);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
void
|
void
|
||||||
cir_ext_disable (void)
|
cir_ext_disable (void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,6 +56,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GPIOA_LED 8
|
#define GPIOA_LED 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I/O ports initial setup, this configuration is established soon after reset
|
* I/O ports initial setup, this configuration is established soon after reset
|
||||||
* in the initialization code.
|
* in the initialization code.
|
||||||
@@ -91,7 +96,7 @@
|
|||||||
#define VAL_GPIOACRH 0x88888883 /* PA15...PA8 */
|
#define VAL_GPIOACRH 0x88888883 /* PA15...PA8 */
|
||||||
#define VAL_GPIOAODR 0xFFFFFFFF
|
#define VAL_GPIOAODR 0xFFFFFFFF
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
/*
|
/*
|
||||||
* Port B setup.
|
* Port B setup.
|
||||||
* Everything input with pull-up except:
|
* Everything input with pull-up except:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
/*
|
/*
|
||||||
* ADC driver system settings.
|
* ADC driver system settings.
|
||||||
*/
|
*/
|
||||||
#define USE_STM32_ADC1 FALSE
|
#define USE_STM32_ADC1 TRUE
|
||||||
#define STM32_ADC1_DMA_PRIORITY 3
|
#define STM32_ADC1_DMA_PRIORITY 3
|
||||||
#define STM32_ADC1_IRQ_PRIORITY 5
|
#define STM32_ADC1_IRQ_PRIORITY 5
|
||||||
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
|
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
|
||||||
|
|||||||
34
doc/settings-for-DnDpinentry
Normal file
34
doc/settings-for-DnDpinentry
Normal file
@@ -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
|
||||||
|
---------------
|
||||||
@@ -495,27 +495,130 @@
|
|||||||
#endif /* TriCore */
|
#endif /* TriCore */
|
||||||
|
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
|
#define MULADDC_1024_CORE \
|
||||||
|
"ldmia %0!, { r5, r6, r7 } \n" \
|
||||||
|
"ldmia %1, { r8, r9, r10 } \n" \
|
||||||
|
"umull r11, r12, %2, r5 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r8, r8, r11 \n" \
|
||||||
|
"umull r11, r12, %2, r6 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r9, r9, r11 \n" \
|
||||||
|
"umull r11, r12, %2, r7 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r10, r10, r11 \n" \
|
||||||
|
"stmia %1!, { r8, r9, r10 } \n"
|
||||||
|
|
||||||
#define MULADDC_INIT \
|
#define MULADDC_1024_LOOP \
|
||||||
asm( "ldr r0, %0 " :: "m" (s)); \
|
asm( "tst %4, #0xfe0 \n" \
|
||||||
asm( "ldr r1, %0 " :: "m" (d)); \
|
"beq 0f \n" \
|
||||||
asm( "ldr r2, %0 " :: "m" (c)); \
|
"1: sub %4, %4, #32 \n" \
|
||||||
asm( "ldr r3, %0 " :: "m" (b));
|
"ldmia %0!, { r5, r6, r7 } \n" \
|
||||||
|
"ldmia %1, { r8, r9, r10 } \n" \
|
||||||
|
"umull r11, r12, %2, r5 \n" \
|
||||||
|
"adds r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r8, r8, r11 \n" \
|
||||||
|
"umull r11, r12, %2, r6 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r9, r9, r11 \n" \
|
||||||
|
"umull r11, r12, %2, r7 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r10, r10, r11 \n" \
|
||||||
|
"stmia %1!, { r8, r9, r10 } \n" \
|
||||||
|
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||||
|
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||||
|
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||||
|
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||||
|
MULADDC_1024_CORE \
|
||||||
|
"ldmia %0!, { r5, r6 } \n" \
|
||||||
|
"ldmia %1, { r8, r9 } \n" \
|
||||||
|
"umull r11, r12, %2, r5 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r8, r8, r11 \n" \
|
||||||
|
"umull r11, r12, %2, r6 \n" \
|
||||||
|
"adcs r11, r11, %3 \n" \
|
||||||
|
"adc %3, r12, #0 \n" \
|
||||||
|
"adds r9, r9, r11 \n" \
|
||||||
|
"stmia %1!, { r8, r9 } \n" \
|
||||||
|
"adc %3, %3, #0 \n" \
|
||||||
|
"tst %4, #0xfe0 \n" \
|
||||||
|
"bne 1b \n" \
|
||||||
|
"0:" \
|
||||||
|
: "=r" (s), "=r" (d), "=r" (b), "=r" (c), "=r" (i) \
|
||||||
|
: "0" (s), "1" (d), "2" (b), "3" (c), "4" (i) \
|
||||||
|
: "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory", "cc" );
|
||||||
|
|
||||||
#define MULADDC_CORE \
|
/* Just for reference (dead code) */
|
||||||
asm( "ldr r4, [r0], #4 " ); \
|
#define MULADDC_HUIT \
|
||||||
asm( "mov r5, #0 " ); \
|
"ldmia %0!, { r4, r5 } \n" \
|
||||||
asm( "ldr r6, [r1] " ); \
|
"ldmia %1, { r8, r9 } \n" \
|
||||||
asm( "umlal r2, r5, r3, r4 " ); \
|
"umull r6, r7, %2, r4 \n" \
|
||||||
asm( "adds r7, r6, r2 " ); \
|
"adcs r6, r6, %3 \n" \
|
||||||
asm( "adc r2, r5, #0 " ); \
|
"adc %3, r7, #0 \n" \
|
||||||
asm( "str r7, [r1], #4 " );
|
"adds r8, r8, r6 \n" \
|
||||||
|
"umull r6, r7, %2, r5 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r9, r9, r6 \n" \
|
||||||
|
"stmia %1!, { r8, r9 } \n" \
|
||||||
|
"ldmia %0!, { r4, r5 } \n" \
|
||||||
|
"ldmia %1, { r8, r9 } \n" \
|
||||||
|
"umull r6, r7, %2, r4 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r8, r8, r6 \n" \
|
||||||
|
"umull r6, r7, %2, r5 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r9, r9, r6 \n" \
|
||||||
|
"stmia %1!, { r8, r9 } \n" \
|
||||||
|
"ldmia %0!, { r4, r5 } \n" \
|
||||||
|
"ldmia %1, { r8, r9 } \n" \
|
||||||
|
"umull r6, r7, %2, r4 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r8, r8, r6 \n" \
|
||||||
|
"umull r6, r7, %2, r5 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r9, r9, r6 \n" \
|
||||||
|
"stmia %1!, { r8, r9 } \n" \
|
||||||
|
"ldmia %0!, { r4, r5 } \n" \
|
||||||
|
"ldmia %1, { r8, r9 } \n" \
|
||||||
|
"umull r6, r7, %2, r4 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r8, r8, r6 \n" \
|
||||||
|
"umull r6, r7, %2, r5 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r9, r9, r6 \n" \
|
||||||
|
"stmia %1!, { r8, r9 } \n"
|
||||||
|
|
||||||
#define MULADDC_STOP \
|
#define MULADDC_INIT \
|
||||||
asm( "str r2, %0 " : "=m" (c)); \
|
asm( "adds %0, #0 \n"
|
||||||
asm( "str r1, %0 " : "=m" (d)); \
|
|
||||||
asm( "str r0, %0 " : "=m" (s) :: \
|
#define MULADDC_CORE \
|
||||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
|
"ldr r5, [%1] \n" \
|
||||||
|
"ldr r4, [%0], #4 \n" \
|
||||||
|
"umull r6, r7, %2, r4 \n" \
|
||||||
|
"adcs r6, r6, %3 \n" \
|
||||||
|
"adc %3, r7, #0 \n" \
|
||||||
|
"adds r5, r5, r6 \n" \
|
||||||
|
"str r5, [%1], #4 \n"
|
||||||
|
|
||||||
|
#define MULADDC_STOP \
|
||||||
|
"adc %3, %3, #0 " \
|
||||||
|
: "=r" (s), "=r" (d), "=r" (b), "=r" (c) \
|
||||||
|
: "0" (s), "1" (d), "2" (b), "3" (c) \
|
||||||
|
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc" );
|
||||||
|
|
||||||
#endif /* ARMv3 */
|
#endif /* ARMv3 */
|
||||||
|
|
||||||
|
|||||||
@@ -894,7 +894,16 @@ static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
|
|||||||
{
|
{
|
||||||
t_int c = 0, t = 0;
|
t_int c = 0, t = 0;
|
||||||
|
|
||||||
#if defined(MULADDC_HUIT)
|
#if defined(MULADDC_1024_LOOP)
|
||||||
|
MULADDC_1024_LOOP
|
||||||
|
|
||||||
|
for( ; i > 0; i-- )
|
||||||
|
{
|
||||||
|
MULADDC_INIT
|
||||||
|
MULADDC_CORE
|
||||||
|
MULADDC_STOP
|
||||||
|
}
|
||||||
|
#elif defined(MULADDC_HUIT)
|
||||||
for( ; i >= 8; i -= 8 )
|
for( ; i >= 8; i -= 8 )
|
||||||
{
|
{
|
||||||
MULADDC_INIT
|
MULADDC_INIT
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ CSRC = $(PORTSRC) \
|
|||||||
main.c usb_lld.c \
|
main.c usb_lld.c \
|
||||||
usb_desc.c usb_prop.c \
|
usb_desc.c usb_prop.c \
|
||||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \
|
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \
|
||||||
random.c
|
random.c neug.c
|
||||||
|
|
||||||
ifneq ($(ENABLE_DEBUG),)
|
ifneq ($(ENABLE_DEBUG),)
|
||||||
CSRC += debug.c
|
CSRC += debug.c
|
||||||
@@ -101,6 +101,10 @@ ifneq ($(ENABLE_PINPAD),)
|
|||||||
CSRC += pin-$(ENABLE_PINPAD).c
|
CSRC += pin-$(ENABLE_PINPAD).c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ENABLE_PINPAD),dnd)
|
||||||
|
CSRC += usb_msc.c
|
||||||
|
endif
|
||||||
|
|
||||||
# List ASM source files here
|
# List ASM source files here
|
||||||
ASMSRC = $(PORTASM) \
|
ASMSRC = $(PORTASM) \
|
||||||
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s
|
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s
|
||||||
@@ -205,9 +209,7 @@ ifeq ($(USE_FWLIB),yes)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
|
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
|
||||||
|
MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
|
||||||
random_bits:
|
|
||||||
dd if=/dev/random bs=1 of=random_bits count=1024
|
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
-rm -f Makefile gnuk.ld config.h random_bits
|
-rm -f Makefile gnuk.ld config.h
|
||||||
|
|||||||
65
src/ac.c
65
src/ac.c
@@ -57,11 +57,11 @@ ac_reset_other (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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)
|
const uint8_t *ks_pw1)
|
||||||
{
|
{
|
||||||
int pw_len;
|
int pw_len;
|
||||||
int r;
|
int r1, r2;
|
||||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||||
|
|
||||||
if (gpg_pw_locked (PW_ERR_PW1))
|
if (gpg_pw_locked (PW_ERR_PW1))
|
||||||
@@ -75,7 +75,7 @@ verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
|||||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|
||||||
goto failure;
|
goto failure;
|
||||||
else
|
else
|
||||||
goto success;
|
goto success_one_step;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pw_len = ks_pw1[0];
|
pw_len = ks_pw1[0];
|
||||||
@@ -88,15 +88,28 @@ verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
success_one_step:
|
||||||
sha1 (pw, pw_len, keystring);
|
sha1 (pw, pw_len, keystring);
|
||||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring))
|
if (access == AC_PSO_CDS_AUTHORIZED)
|
||||||
< 0)
|
{
|
||||||
goto failure;
|
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||||
else if (r == 0)
|
r2 = 0;
|
||||||
if (memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 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;
|
goto failure;
|
||||||
|
|
||||||
success:
|
|
||||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||||
return pw_len;
|
return pw_len;
|
||||||
}
|
}
|
||||||
@@ -113,7 +126,7 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
DEBUG_INFO ("verify_pso_cds\r\n");
|
DEBUG_INFO ("verify_pso_cds\r\n");
|
||||||
DEBUG_BYTE (pw_len);
|
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)
|
if (r > 0)
|
||||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||||
return r;
|
return r;
|
||||||
@@ -122,29 +135,16 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
int
|
int
|
||||||
verify_other (const uint8_t *pw, int pw_len)
|
verify_other (const uint8_t *pw, int pw_len)
|
||||||
{
|
{
|
||||||
int r1, r2;
|
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
int r;
|
||||||
|
|
||||||
DEBUG_INFO ("verify_other\r\n");
|
DEBUG_INFO ("verify_other\r\n");
|
||||||
|
DEBUG_BYTE (pw_len);
|
||||||
|
|
||||||
if (gpg_pw_locked (PW_ERR_PW1))
|
r = verify_user_0 (AC_OTHER_AUTHORIZED, pw, pw_len, pw_len, ks_pw1);
|
||||||
return 0;
|
if (r > 0)
|
||||||
|
auth_status |= AC_OTHER_AUTHORIZED;
|
||||||
sha1 (pw, pw_len, keystring);
|
return r;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -172,7 +172,7 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
|||||||
count -= pw_len + 8;
|
count -= pw_len + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count < 8)
|
if (count <= 8)
|
||||||
sha1_update (&sha1_ctx, salt, count);
|
sha1_update (&sha1_ctx, salt, count);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -230,7 +230,8 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
|||||||
|
|
||||||
if (ks_pw1 != NULL)
|
if (ks_pw1 != NULL)
|
||||||
{ /* empty PW3, but PW1 exists */
|
{ /* 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)
|
if (r > 0)
|
||||||
admin_authorized = BY_USER;
|
admin_authorized = BY_USER;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -28,7 +28,9 @@
|
|||||||
#include "polarssl/config.h"
|
#include "polarssl/config.h"
|
||||||
#include "polarssl/rsa.h"
|
#include "polarssl/rsa.h"
|
||||||
|
|
||||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
#define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
|
||||||
|
/* 256 byte == 2048-bit */
|
||||||
|
/* 128 byte == 1024-bit */
|
||||||
|
|
||||||
static rsa_context rsa_ctx;
|
static rsa_context rsa_ctx;
|
||||||
|
|
||||||
@@ -43,10 +45,10 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
|||||||
mpi_init (&P1, &Q1, &H, NULL);
|
mpi_init (&P1, &Q1, &H, NULL);
|
||||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||||
|
|
||||||
rsa_ctx.len = 2048 / 8;
|
rsa_ctx.len = KEY_CONTENT_LEN;
|
||||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||||
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
|
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
|
||||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], rsa_ctx.len / 2);
|
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2);
|
||||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||||
@@ -90,23 +92,25 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LEN: length in byte
|
||||||
|
*/
|
||||||
const uint8_t *
|
const uint8_t *
|
||||||
modulus_calc (const uint8_t *p, int len)
|
modulus_calc (const uint8_t *p, int len)
|
||||||
{
|
{
|
||||||
mpi P, Q, N;
|
mpi P, Q, N;
|
||||||
uint8_t *modulus;
|
uint8_t *modulus;
|
||||||
|
|
||||||
(void)len; /* 2048-bit assumed */
|
modulus = malloc (len);
|
||||||
modulus = malloc (2048 / 8);
|
|
||||||
if (modulus == NULL)
|
if (modulus == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
mpi_init (&P, &Q, &N, NULL);
|
mpi_init (&P, &Q, &N, NULL);
|
||||||
mpi_read_binary (&P, p, 2048 / 8 / 2);
|
mpi_read_binary (&P, p, len / 2);
|
||||||
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
|
mpi_read_binary (&Q, p + len / 2, len / 2);
|
||||||
mpi_mul_mpi (&N, &P, &Q);
|
mpi_mul_mpi (&N, &P, &Q);
|
||||||
|
|
||||||
mpi_write_binary (&N, modulus, 2048 / 8);
|
mpi_write_binary (&N, modulus, len);
|
||||||
mpi_free (&P, &Q, &N, NULL);
|
mpi_free (&P, &Q, &N, NULL);
|
||||||
return modulus;
|
return modulus;
|
||||||
}
|
}
|
||||||
@@ -135,8 +139,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
|||||||
DEBUG_WORD (msg_len);
|
DEBUG_WORD (msg_len);
|
||||||
|
|
||||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||||
mpi_read_binary (&rsa_ctx.P, &kd->data[0], 2048 / 8 / 2);
|
mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2);
|
||||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], 2048 / 8 / 2);
|
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
|
||||||
|
KEY_CONTENT_LEN / 2);
|
||||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#define CH_OPTIMIZE_SPEED TRUE
|
#define CH_OPTIMIZE_SPEED TRUE
|
||||||
#define CH_USE_REGISTRY TRUE
|
#define CH_USE_REGISTRY TRUE
|
||||||
#define CH_USE_WAITEXIT TRUE
|
#define CH_USE_WAITEXIT TRUE
|
||||||
#define CH_USE_SEMAPHORES FALSE
|
#define CH_USE_SEMAPHORES TRUE
|
||||||
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
||||||
#define CH_USE_SEMSW FALSE
|
#define CH_USE_SEMSW FALSE
|
||||||
#define CH_USE_MUTEXES TRUE
|
#define CH_USE_MUTEXES TRUE
|
||||||
|
|||||||
@@ -5,3 +5,4 @@
|
|||||||
@DFU_DEFINE@
|
@DFU_DEFINE@
|
||||||
@PINPAD_DEFINE@
|
@PINPAD_DEFINE@
|
||||||
@PINPAD_MORE_DEFINE@
|
@PINPAD_MORE_DEFINE@
|
||||||
|
@CERTDO_DEFINE@
|
||||||
|
|||||||
46
src/configure
vendored
46
src/configure
vendored
@@ -26,12 +26,7 @@ verbose=no
|
|||||||
with_dfu=default
|
with_dfu=default
|
||||||
debug=no
|
debug=no
|
||||||
pinpad=no
|
pinpad=no
|
||||||
|
certdo=no
|
||||||
# check /dev/random
|
|
||||||
if test ! -e /dev/random; then
|
|
||||||
echo "/dev/random is required." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Process each option
|
# Process each option
|
||||||
for option; do
|
for option; do
|
||||||
@@ -57,6 +52,10 @@ for option; do
|
|||||||
pinpad=$optarg ;;
|
pinpad=$optarg ;;
|
||||||
--disable-pinpad)
|
--disable-pinpad)
|
||||||
pinpad=no ;;
|
pinpad=no ;;
|
||||||
|
--enable-certdo)
|
||||||
|
certdo=yes ;;
|
||||||
|
--disable-certdo)
|
||||||
|
certdo=no ;;
|
||||||
--with-dfu)
|
--with-dfu)
|
||||||
with_dfu=yes ;;
|
with_dfu=yes ;;
|
||||||
--without-dfu)
|
--without-dfu)
|
||||||
@@ -86,8 +85,9 @@ Configuration:
|
|||||||
STM8S_DISCOVERY
|
STM8S_DISCOVERY
|
||||||
STBEE
|
STBEE
|
||||||
--enable-debug debug with virtual COM port [no]
|
--enable-debug debug with virtual COM port [no]
|
||||||
--enable-pinpad={cir,dial}
|
--enable-pinpad={dnd,cir,dial}
|
||||||
PIN input device support [no]
|
PIN entry support [no]
|
||||||
|
--enable-certdo support CERT.3 data object [no]
|
||||||
--with-dfu build image for DFU [<target specific>]
|
--with-dfu build image for DFU [<target specific>]
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
@@ -159,10 +159,10 @@ if test "$pinpad" = "no"; then
|
|||||||
PINPAD_MORE_DEFINE=""
|
PINPAD_MORE_DEFINE=""
|
||||||
echo "PIN pad option disabled"
|
echo "PIN pad option disabled"
|
||||||
elif test "$pinpad" = "yes"; then
|
elif test "$pinpad" = "yes"; then
|
||||||
PINPAD_MAKE_OPTION="ENABLE_PINPAD=cir"
|
PINPAD_MAKE_OPTION="ENABLE_PINPAD=dnd"
|
||||||
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
||||||
PINPAD_MORE_DEFINE="#define PINPAD_CIR_SUPPORT 1"
|
PINPAD_MORE_DEFINE="#define PINPAD_DND_SUPPORT 1"
|
||||||
echo "PIN pad option enabled (cir)"
|
echo "PIN pad option enabled (dnd)"
|
||||||
else
|
else
|
||||||
PINPAD_MAKE_OPTION="ENABLE_PINPAD=$pinpad"
|
PINPAD_MAKE_OPTION="ENABLE_PINPAD=$pinpad"
|
||||||
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
||||||
@@ -170,16 +170,34 @@ else
|
|||||||
echo "PIN pad option enabled ($pinpad)"
|
echo "PIN pad option enabled ($pinpad)"
|
||||||
fi
|
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%" \
|
sed -e "s%@BOARD_DIR@%$BOARD_DIR%" \
|
||||||
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
|
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
|
||||||
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
|
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
|
||||||
< Makefile.in > Makefile
|
< Makefile.in > Makefile
|
||||||
sed -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
|
if test "$certdo" = "yes"; then
|
||||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
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
|
< 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/" \
|
sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
|
||||||
|
-e "s/@DFU_DEFINE@/$DFU_DEFINE/" \
|
||||||
-e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \
|
-e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \
|
||||||
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_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
|
< config.h.in > config.h
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
33
src/flash.c
33
src/flash.c
@@ -147,8 +147,6 @@ flash_erase_page (uint32_t addr)
|
|||||||
* .bss
|
* .bss
|
||||||
* _end
|
* _end
|
||||||
* <alignment to page>
|
* <alignment to page>
|
||||||
* random_bits_start
|
|
||||||
* <one page>
|
|
||||||
* ch_certificate_startp
|
* ch_certificate_startp
|
||||||
* <2048 bytes>
|
* <2048 bytes>
|
||||||
* _data_pool
|
* _data_pool
|
||||||
@@ -206,7 +204,6 @@ flash_init (void)
|
|||||||
|
|
||||||
keystore = p;
|
keystore = p;
|
||||||
|
|
||||||
flash_unlock ();
|
|
||||||
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +581,7 @@ flash_cnt123_clear (const uint8_t **addr_p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CERTDO_SUPPORT)
|
||||||
static int
|
static int
|
||||||
flash_check_blank (const uint8_t *page, int size)
|
flash_check_blank (const uint8_t *page, int size)
|
||||||
{
|
{
|
||||||
@@ -595,17 +593,16 @@ flash_check_blank (const uint8_t *page, int size)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FLASH_CH_CERTIFICATE_SIZE 2048
|
#define FLASH_CH_CERTIFICATE_SIZE 2048
|
||||||
int
|
int
|
||||||
flash_erase_binary (uint8_t file_id)
|
flash_erase_binary (uint8_t file_id)
|
||||||
{
|
{
|
||||||
const uint8_t *p;
|
#if defined(CERTDO_SUPPORT)
|
||||||
|
|
||||||
if (file_id == FILEID_CH_CERTIFICATE)
|
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)
|
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
|
||||||
{
|
{
|
||||||
flash_erase_page ((uint32_t)p);
|
flash_erase_page ((uint32_t)p);
|
||||||
@@ -614,18 +611,12 @@ flash_erase_binary (uint8_t file_id)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (file_id == FILEID_RANDOM)
|
|
||||||
{
|
|
||||||
p = &random_bits_start;
|
|
||||||
|
|
||||||
if (flash_check_blank (p, FLASH_PAGE_SIZE) == 0)
|
|
||||||
flash_erase_page ((uint32_t)p);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#else
|
||||||
|
(void)file_id;
|
||||||
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,17 +628,15 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
|||||||
uint16_t maxsize;
|
uint16_t maxsize;
|
||||||
const uint8_t *p;
|
const uint8_t *p;
|
||||||
|
|
||||||
|
#if defined(CERTDO_SUPPORT)
|
||||||
if (file_id == FILEID_CH_CERTIFICATE)
|
if (file_id == FILEID_CH_CERTIFICATE)
|
||||||
{
|
{
|
||||||
maxsize = FLASH_CH_CERTIFICATE_SIZE;
|
maxsize = FLASH_CH_CERTIFICATE_SIZE;
|
||||||
p = &ch_certificate_start;
|
p = &ch_certificate_start;
|
||||||
}
|
}
|
||||||
else if (file_id == FILEID_RANDOM)
|
else
|
||||||
{
|
#endif
|
||||||
maxsize = FLASH_PAGE_SIZE;
|
if (file_id == FILEID_SERIAL_NO)
|
||||||
p = &random_bits_start;
|
|
||||||
}
|
|
||||||
else if (file_id == FILEID_SERIAL_NO)
|
|
||||||
{
|
{
|
||||||
maxsize = 6;
|
maxsize = 6;
|
||||||
p = &openpgpcard_aid[8];
|
p = &openpgpcard_aid[8];
|
||||||
|
|||||||
41
src/gnuk.h
41
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 */
|
#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) */
|
/* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
|
||||||
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */
|
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */
|
||||||
/* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */
|
/* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */
|
||||||
@@ -79,8 +86,8 @@ extern void gpg_pw_increment_err_counter (uint8_t which);
|
|||||||
extern int ac_check_status (uint8_t ac_flag);
|
extern int ac_check_status (uint8_t ac_flag);
|
||||||
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
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_other (const uint8_t *pw, int pw_len);
|
||||||
extern int verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
extern int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
|
||||||
const uint8_t *ks_pw1);
|
int pw_len_known, const uint8_t *ks_pw1);
|
||||||
extern int verify_admin (const uint8_t *pw, int pw_len);
|
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);
|
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known);
|
||||||
|
|
||||||
@@ -90,8 +97,7 @@ extern void ac_reset_admin (void);
|
|||||||
extern void ac_fini (void);
|
extern void ac_fini (void);
|
||||||
|
|
||||||
|
|
||||||
extern void write_res_apdu (const uint8_t *p, int len,
|
extern void set_res_apdu (uint8_t sw1, uint8_t sw2);
|
||||||
uint8_t sw1, uint8_t sw2);
|
|
||||||
extern uint16_t data_objects_number_of_bytes;
|
extern uint16_t data_objects_number_of_bytes;
|
||||||
|
|
||||||
extern void gpg_data_scan (const uint8_t *p);
|
extern void gpg_data_scan (const uint8_t *p);
|
||||||
@@ -108,6 +114,7 @@ enum kind_of_key {
|
|||||||
GPG_KEY_FOR_AUTHENTICATION,
|
GPG_KEY_FOR_AUTHENTICATION,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void flash_unlock (void);
|
||||||
extern const uint8_t *flash_init (void);
|
extern const uint8_t *flash_init (void);
|
||||||
extern void flash_do_release (const uint8_t *);
|
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 const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||||
@@ -292,6 +299,7 @@ extern uint8_t admin_authorized;
|
|||||||
|
|
||||||
#define SIZE_PW_STATUS_BYTES 7
|
#define SIZE_PW_STATUS_BYTES 7
|
||||||
|
|
||||||
|
extern void random_init (void);
|
||||||
/* 16-byte random bytes */
|
/* 16-byte random bytes */
|
||||||
extern const uint8_t *random_bytes_get (void);
|
extern const uint8_t *random_bytes_get (void);
|
||||||
extern void random_bytes_free (const uint8_t *);
|
extern void random_bytes_free (const uint8_t *);
|
||||||
@@ -332,14 +340,30 @@ extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *da
|
|||||||
extern const unsigned char *unique_device_id (void);
|
extern const unsigned char *unique_device_id (void);
|
||||||
extern const uint8_t gnukStringSerial[];
|
extern const uint8_t gnukStringSerial[];
|
||||||
|
|
||||||
|
#define LED_ONESHOT_SHORT ((eventmask_t)1)
|
||||||
|
#define LED_ONESHOT_LONG ((eventmask_t)2)
|
||||||
|
#define LED_TWOSHOT ((eventmask_t)4)
|
||||||
|
#define LED_STATUS_MODE ((eventmask_t)8)
|
||||||
|
#define LED_INPUT_MODE ((eventmask_t)16)
|
||||||
|
#define LED_FATAL_MODE ((eventmask_t)32)
|
||||||
|
extern Thread *main_thread;
|
||||||
|
extern void led_blink (int spec);
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
# if defined(PINPAD_CIR_SUPPORT)
|
||||||
extern void cir_ext_disable (void);
|
extern void cir_ext_disable (void);
|
||||||
extern void cir_ext_enable (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_disable (void);
|
||||||
extern void dial_sw_enable (void);
|
extern void dial_sw_enable (void);
|
||||||
#endif
|
# 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);
|
||||||
|
extern void msc_scsi_stop (uint8_t code);
|
||||||
|
# endif
|
||||||
#define PIN_INPUT_CURRENT 1
|
#define PIN_INPUT_CURRENT 1
|
||||||
#define PIN_INPUT_NEW 2
|
#define PIN_INPUT_NEW 2
|
||||||
#define PIN_INPUT_CONFIRM 3
|
#define PIN_INPUT_CONFIRM 3
|
||||||
@@ -347,5 +371,6 @@ extern void dial_sw_enable (void);
|
|||||||
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
extern uint8_t pin_input_len;
|
extern uint8_t pin_input_len;
|
||||||
|
|
||||||
extern msg_t pin_main (void *arg);
|
extern int pinpad_getline (int msg_code, systime_t timeout);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,7 +28,8 @@
|
|||||||
* ST32F103 memory setup.
|
* ST32F103 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0400;
|
__main_stack_size__ = 0x0400;
|
||||||
__stacks_total_size__ = __main_stack_size__;
|
__process_stack_size__ = 0x0200;
|
||||||
|
__stacks_total_size__ = __main_stack_size__ + __process_stack_size__;
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
@@ -114,21 +115,16 @@ SECTIONS
|
|||||||
PROVIDE(end = .);
|
PROVIDE(end = .);
|
||||||
_end = .;
|
_end = .;
|
||||||
|
|
||||||
.gnuk_random :
|
@CERTDO_SUPPORT_START@
|
||||||
{
|
|
||||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
|
||||||
random_bits_start = .;
|
|
||||||
. += 1;
|
|
||||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
|
||||||
} > flash =0xffffffff
|
|
||||||
|
|
||||||
.gnuk_ch_certificate :
|
.gnuk_ch_certificate :
|
||||||
{
|
{
|
||||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||||
ch_certificate_start = .;
|
ch_certificate_start = .;
|
||||||
|
LONG(0xffffffff);
|
||||||
. += 1920;
|
. += 1920;
|
||||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||||
} > flash =0xffffffff
|
} > flash =0xffffffff
|
||||||
|
@CERTDO_SUPPORT_END@
|
||||||
|
|
||||||
.gnuk_flash :
|
.gnuk_flash :
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "mcuconf.h"
|
#include "mcuconf.h"
|
||||||
|
|
||||||
#define CH_HAL_USE_PAL TRUE
|
#define CH_HAL_USE_PAL TRUE
|
||||||
#define CH_HAL_USE_ADC FALSE
|
#define CH_HAL_USE_ADC TRUE
|
||||||
#define CH_HAL_USE_CAN FALSE
|
#define CH_HAL_USE_CAN FALSE
|
||||||
#define CH_HAL_USE_MAC FALSE
|
#define CH_HAL_USE_MAC FALSE
|
||||||
#define CH_HAL_USE_PWM FALSE
|
#define CH_HAL_USE_PWM FALSE
|
||||||
|
|||||||
296
src/main.c
296
src/main.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* main.c - main routine of Gnuk
|
* main.c - main routine of Gnuk
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -106,10 +106,14 @@ STDOUTthread (void *arg)
|
|||||||
|
|
||||||
p = stdout.str;
|
p = stdout.str;
|
||||||
len = stdout.size;
|
len = stdout.size;
|
||||||
while (len > 0)
|
while (1)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
if (count_in != VIRTUAL_COM_PORT_DATA_SIZE)
|
||||||
|
break;
|
||||||
|
|
||||||
if (len < VIRTUAL_COM_PORT_DATA_SIZE)
|
if (len < VIRTUAL_COM_PORT_DATA_SIZE)
|
||||||
{
|
{
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
@@ -172,7 +176,6 @@ device_initialize_once (void)
|
|||||||
|
|
||||||
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
|
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
|
||||||
{
|
{
|
||||||
extern void flash_unlock (void);
|
|
||||||
/*
|
/*
|
||||||
* This is the first time invocation.
|
* This is the first time invocation.
|
||||||
* Setup serial number by unique device ID.
|
* Setup serial number by unique device ID.
|
||||||
@@ -180,7 +183,6 @@ device_initialize_once (void)
|
|||||||
const uint8_t *u = unique_device_id ();
|
const uint8_t *u = unique_device_id ();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
flash_unlock ();
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
uint8_t b = u[i];
|
uint8_t b = u[i];
|
||||||
@@ -198,6 +200,161 @@ device_initialize_once (void)
|
|||||||
|
|
||||||
static volatile uint8_t fatal_code;
|
static volatile uint8_t fatal_code;
|
||||||
|
|
||||||
|
Thread *main_thread;
|
||||||
|
|
||||||
|
#define GNUK_INIT 0
|
||||||
|
#define GNUK_RUNNING 1
|
||||||
|
#define GNUK_INPUT_WAIT 2
|
||||||
|
#define GNUK_FATAL 255
|
||||||
|
/*
|
||||||
|
* 0 for initializing
|
||||||
|
* 1 for normal mode
|
||||||
|
* 2 for input waiting
|
||||||
|
* 255 for fatal
|
||||||
|
*/
|
||||||
|
static uint8_t main_mode;
|
||||||
|
|
||||||
|
static void display_interaction (void)
|
||||||
|
{
|
||||||
|
eventmask_t m;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
m = chEvtWaitOne (ALL_EVENTS);
|
||||||
|
set_led (1);
|
||||||
|
switch (m)
|
||||||
|
{
|
||||||
|
case LED_ONESHOT_SHORT:
|
||||||
|
chThdSleep (MS2ST (100));
|
||||||
|
break;
|
||||||
|
case LED_ONESHOT_LONG:
|
||||||
|
chThdSleep (MS2ST (400));
|
||||||
|
break;
|
||||||
|
case LED_TWOSHOT:
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
break;
|
||||||
|
case LED_STATUS_MODE:
|
||||||
|
chThdSleep (MS2ST (400));
|
||||||
|
set_led (0);
|
||||||
|
return;
|
||||||
|
case LED_FATAL_MODE:
|
||||||
|
main_mode = GNUK_FATAL;
|
||||||
|
set_led (0);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_led (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_fatal_code (void)
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (1);
|
||||||
|
if (fatal_code & 1)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if (fatal_code & 2)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_status_code (void)
|
||||||
|
{
|
||||||
|
if (icc_state == ICC_STATE_START)
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* GPGthread running */
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
|
||||||
|
if (icc_state == ICC_STATE_WAIT)
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP * 2);
|
||||||
|
}
|
||||||
|
else if (icc_state == ICC_STATE_RECEIVE)
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
led_blink (int spec)
|
||||||
|
{
|
||||||
|
if (spec == 0)
|
||||||
|
chEvtSignal (main_thread, LED_ONESHOT_SHORT);
|
||||||
|
else if (spec == 1)
|
||||||
|
chEvtSignal (main_thread, LED_ONESHOT_LONG);
|
||||||
|
else
|
||||||
|
chEvtSignal (main_thread, LED_TWOSHOT);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry point.
|
* Entry point.
|
||||||
*
|
*
|
||||||
@@ -212,9 +369,13 @@ main (int argc, char **argv)
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
|
main_thread = chThdSelf ();
|
||||||
|
|
||||||
|
flash_unlock ();
|
||||||
device_initialize_once ();
|
device_initialize_once ();
|
||||||
usb_lld_init ();
|
usb_lld_init ();
|
||||||
USB_Init();
|
USB_Init ();
|
||||||
|
random_init ();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
stdout_init ();
|
stdout_init ();
|
||||||
@@ -229,107 +390,53 @@ main (int argc, char **argv)
|
|||||||
chThdCreateStatic (waUSBthread, sizeof(waUSBthread),
|
chThdCreateStatic (waUSBthread, sizeof(waUSBthread),
|
||||||
NORMALPRIO, USBthread, NULL);
|
NORMALPRIO, USBthread, NULL);
|
||||||
|
|
||||||
|
#ifdef PINPAD_DND_SUPPORT
|
||||||
|
msc_init ();
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
eventmask_t m;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL);
|
||||||
if (fatal_code != 0)
|
switch (m)
|
||||||
{
|
{
|
||||||
|
case LED_STATUS_MODE:
|
||||||
|
main_mode = GNUK_RUNNING;
|
||||||
|
break;
|
||||||
|
case LED_FATAL_MODE:
|
||||||
|
main_mode = GNUK_FATAL;
|
||||||
|
break;
|
||||||
|
case LED_INPUT_MODE:
|
||||||
|
main_mode = GNUK_INPUT_WAIT;
|
||||||
set_led (1);
|
set_led (1);
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
chThdSleep (MS2ST (400));
|
||||||
set_led (0);
|
set_led (0);
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
break;
|
||||||
set_led (1);
|
default:
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
break;
|
||||||
set_led (0);
|
}
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (1);
|
|
||||||
if (fatal_code & 1)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if (fatal_code & 2)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bDeviceState != CONFIGURED)
|
switch (main_mode)
|
||||||
{
|
{
|
||||||
|
case GNUK_FATAL:
|
||||||
|
display_fatal_code ();
|
||||||
|
break;
|
||||||
|
case GNUK_INIT:
|
||||||
set_led (1);
|
set_led (1);
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
set_led (0);
|
set_led (0);
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||||
}
|
break;
|
||||||
else
|
case GNUK_INPUT_WAIT:
|
||||||
/* Device configured */
|
display_interaction ();
|
||||||
if (icc_state == ICC_STATE_START)
|
break;
|
||||||
{
|
case GNUK_RUNNING:
|
||||||
set_led (1);
|
default:
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
display_status_code ();
|
||||||
set_led (0);
|
break;
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
/* GPGthread running */
|
|
||||||
{
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
|
|
||||||
if (icc_state == ICC_STATE_WAIT)
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 2);
|
|
||||||
}
|
|
||||||
else if (icc_state == ICC_STATE_RECEIVE)
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_MORE
|
#ifdef DEBUG_MORE
|
||||||
if (bDeviceState == CONFIGURED && (count % 10) == 0)
|
if (bDeviceState == CONFIGURED && (count % 10) == 0)
|
||||||
@@ -349,6 +456,7 @@ void
|
|||||||
fatal (uint8_t code)
|
fatal (uint8_t code)
|
||||||
{
|
{
|
||||||
fatal_code = code;
|
fatal_code = code;
|
||||||
|
chEvtSignal (main_thread, LED_FATAL_MODE);
|
||||||
_write ("fatal\r\n", 7);
|
_write ("fatal\r\n", 7);
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|||||||
453
src/neug.c
Normal file
453
src/neug.c
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
/*
|
||||||
|
* neug.c - random number generation (from NeuG/src/random.c)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of NeuG, a Random Number Generator
|
||||||
|
* implementation (for STM32F103).
|
||||||
|
*
|
||||||
|
* NeuG is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
static Thread *rng_thread;
|
||||||
|
#define ADC_DATA_AVAILABLE ((eventmask_t)1)
|
||||||
|
|
||||||
|
/* Total number of channels to be sampled by a single ADC operation.*/
|
||||||
|
#define ADC_GRP1_NUM_CHANNELS 2
|
||||||
|
|
||||||
|
/* Depth of the conversion buffer, channels are sampled one time each.*/
|
||||||
|
#define ADC_GRP1_BUF_DEPTH 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ADC samples buffer.
|
||||||
|
*/
|
||||||
|
static adcsample_t samp[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
|
||||||
|
|
||||||
|
static void adccb (adcsample_t *buffer, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ADC conversion group.
|
||||||
|
* Mode: Linear buffer, 4 samples of 2 channels, SW triggered.
|
||||||
|
* Channels: Vref (1.5 cycles sample time, violating the spec.)
|
||||||
|
* Sensor (1.5 cycles sample time, violating the spec.)
|
||||||
|
*/
|
||||||
|
static const ADCConversionGroup adcgrpcfg = {
|
||||||
|
FALSE,
|
||||||
|
ADC_GRP1_NUM_CHANNELS,
|
||||||
|
0,
|
||||||
|
ADC_CR2_EXTSEL_SWSTART | ADC_CR2_TSVREFE | ADC_CR2_CONT,
|
||||||
|
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_1P5) | ADC_SMPR1_SMP_VREF(ADC_SAMPLE_1P5),
|
||||||
|
0,
|
||||||
|
ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),
|
||||||
|
0,
|
||||||
|
ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) | ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ADC end conversion callback.
|
||||||
|
*/
|
||||||
|
static void adccb (adcsample_t *buffer, size_t n)
|
||||||
|
{
|
||||||
|
ADCDriver *adcp = &ADCD1;
|
||||||
|
|
||||||
|
(void) buffer; (void) n;
|
||||||
|
if (adcp->ad_state == ADC_COMPLETE)
|
||||||
|
chEvtSignalI (rng_thread, ADC_DATA_AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TinyMT routines.
|
||||||
|
*
|
||||||
|
* See
|
||||||
|
* "Tiny Mersenne Twister (TinyMT): A small-sized variant of Mersenne Twister"
|
||||||
|
* by Mutsuo Saito and Makoto Matsumoto
|
||||||
|
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Use the first example of TinyMT */
|
||||||
|
#define TMT_MAT1 0x8f7011ee
|
||||||
|
#define TMT_MAT2 0xfc78ff1f
|
||||||
|
#define TMT_TMAT 0x3793fdff
|
||||||
|
|
||||||
|
static uint32_t tmt[4];
|
||||||
|
|
||||||
|
static void tmt_one_step (void);
|
||||||
|
|
||||||
|
#define TMT_INIT_MIN_LOOP 8
|
||||||
|
#define TMT_INIT_PRE_LOOP 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TinyMT initialize function.
|
||||||
|
*/
|
||||||
|
static void tmt_init (uint32_t seed)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tmt[0] = seed;
|
||||||
|
tmt[1] = TMT_MAT1;
|
||||||
|
tmt[2] = TMT_MAT2;
|
||||||
|
tmt[3] = TMT_TMAT;
|
||||||
|
|
||||||
|
for (i = 1; i < TMT_INIT_MIN_LOOP; i++)
|
||||||
|
tmt[i & 3] ^= i + UINT32_C(1812433253) * (tmt[(i - 1) & 3]
|
||||||
|
^ (tmt[(i - 1) & 3] >> 30));
|
||||||
|
|
||||||
|
if ((tmt[0] & 0x7fffffff) == 0 && tmt[1] == 0 && tmt[2] == 0 && tmt[3] == 0)
|
||||||
|
{ /* Prevent all zero */
|
||||||
|
tmt[0] = 'T';
|
||||||
|
tmt[1] = 'I';
|
||||||
|
tmt[2] = 'N';
|
||||||
|
tmt[3] = 'Y';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < TMT_INIT_PRE_LOOP; i++)
|
||||||
|
tmt_one_step ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TinyMT one step function, call this every time before tmt_value.
|
||||||
|
*/
|
||||||
|
static void tmt_one_step (void)
|
||||||
|
{
|
||||||
|
uint32_t x, y;
|
||||||
|
|
||||||
|
y = tmt[3];
|
||||||
|
x = (tmt[0] & 0x7fffffff) ^ tmt[1] ^ tmt[2];
|
||||||
|
x ^= (x << 1);
|
||||||
|
y ^= (y >> 1) ^ x;
|
||||||
|
tmt[0] = tmt[1];
|
||||||
|
tmt[1] = tmt[2];
|
||||||
|
tmt[2] = x ^ (y << 10);
|
||||||
|
tmt[3] = y;
|
||||||
|
if ((y & 1))
|
||||||
|
{
|
||||||
|
tmt[1] ^= TMT_MAT1;
|
||||||
|
tmt[2] ^= TMT_MAT2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a random word (32-bit).
|
||||||
|
*/
|
||||||
|
static uint32_t tmt_value (void)
|
||||||
|
{
|
||||||
|
uint32_t t0, t1;
|
||||||
|
|
||||||
|
t0 = tmt[3];
|
||||||
|
t1 = tmt[0] + (tmt[2] >> 8);
|
||||||
|
t0 ^= t1;
|
||||||
|
if ((t1 & 1))
|
||||||
|
t0 ^= TMT_TMAT;
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8 parallel CRC-16 shift registers, with randomly rotated feedback */
|
||||||
|
#define EPOOL_SIZE 16
|
||||||
|
static uint8_t epool[EPOOL_SIZE]; /* Big-endian */
|
||||||
|
static uint8_t ep_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Magic number seven.
|
||||||
|
*
|
||||||
|
* We did an experiment of measuring entropy of ADC output with MUST.
|
||||||
|
* The entropy of a byte by raw sampling of LSBs has more than 6.0 bit/byte.
|
||||||
|
* So, it is considered OK to get 4-byte from 7-byte (6x7 = 42 > 32).
|
||||||
|
*/
|
||||||
|
#define NUM_NOISE_INPUTS 7
|
||||||
|
|
||||||
|
#define SHIFT_RIGHT(f) ((f)>>1)
|
||||||
|
|
||||||
|
static void ep_add (uint8_t entropy_bits, uint8_t another_random_bit)
|
||||||
|
{
|
||||||
|
uint8_t v = epool[ep_count];
|
||||||
|
|
||||||
|
/* CRC-16-CCITT's Polynomial is: x^16 + x^12 + x^5 + 1 */
|
||||||
|
epool[(ep_count - 12)& 0x0f] ^= v;
|
||||||
|
epool[(ep_count - 5)& 0x0f] ^= v;
|
||||||
|
epool[ep_count] = SHIFT_RIGHT (v) ^ entropy_bits;
|
||||||
|
|
||||||
|
if ((v&1) || another_random_bit)
|
||||||
|
epool[ep_count] ^= 0xff;
|
||||||
|
|
||||||
|
ep_count = (ep_count + 1) & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FNV_INIT 2166136261U
|
||||||
|
#define FNV_PRIME 16777619
|
||||||
|
|
||||||
|
static uint32_t fnv32_hash (const uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
uint32_t v = FNV_INIT;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
v ^= buf[i];
|
||||||
|
v *= FNV_PRIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PROBABILITY_50_BY_TICK() ((SysTick->VAL & 0x02) != 0)
|
||||||
|
|
||||||
|
static uint32_t ep_output (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t buf[NUM_NOISE_INPUTS];
|
||||||
|
uint8_t *p = buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NUM_NOISE_INPUTS is seven.
|
||||||
|
*
|
||||||
|
* There are sixteen bytes in the CRC-16 buffer. We use seven
|
||||||
|
* outputs of CRC-16 buffer for final output. There are two parts;
|
||||||
|
* former 4 outputs which will be used directly, and latter 3
|
||||||
|
* outputs which will be used with feedback loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* At some probability, use latter 3 outputs of CRC-16 buffer */
|
||||||
|
for (i = NUM_NOISE_INPUTS - 1; i >= 4; i--)
|
||||||
|
if (PROBABILITY_50_BY_TICK ())
|
||||||
|
*p++ = epool[(ep_count+i) & 0x0f] ^ epool[(ep_count+i-4) & 0x0f];
|
||||||
|
|
||||||
|
/* Use former 4 outputs of CRC-16 buffer */
|
||||||
|
for (i = 3; i >= 0; i--)
|
||||||
|
*p++ = epool[(ep_count+i) & 0x0f];
|
||||||
|
|
||||||
|
return fnv32_hash (buf, p - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ring buffer, filled by generator, consumed by neug_get routine.
|
||||||
|
*/
|
||||||
|
struct rng_rb {
|
||||||
|
uint32_t *buf;
|
||||||
|
Mutex m;
|
||||||
|
CondVar data_available;
|
||||||
|
CondVar space_available;
|
||||||
|
uint8_t head, tail;
|
||||||
|
uint8_t size;
|
||||||
|
unsigned int full :1;
|
||||||
|
unsigned int empty :1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rb_init (struct rng_rb *rb, uint32_t *p, uint8_t size)
|
||||||
|
{
|
||||||
|
rb->buf = p;
|
||||||
|
rb->size = size;
|
||||||
|
chMtxInit (&rb->m);
|
||||||
|
chCondInit (&rb->data_available);
|
||||||
|
chCondInit (&rb->space_available);
|
||||||
|
rb->head = rb->tail = 0;
|
||||||
|
rb->full = 0;
|
||||||
|
rb->empty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rb_add (struct rng_rb *rb, uint32_t v)
|
||||||
|
{
|
||||||
|
rb->buf[rb->tail++] = v;
|
||||||
|
if (rb->tail == rb->size)
|
||||||
|
rb->tail = 0;
|
||||||
|
if (rb->tail == rb->head)
|
||||||
|
rb->full = 1;
|
||||||
|
rb->empty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t rb_del (struct rng_rb *rb)
|
||||||
|
{
|
||||||
|
uint32_t v = rb->buf[rb->head++];
|
||||||
|
|
||||||
|
if (rb->head == rb->size)
|
||||||
|
rb->head = 0;
|
||||||
|
if (rb->head == rb->tail)
|
||||||
|
rb->empty = 1;
|
||||||
|
rb->full = 0;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Random number generation from ADC sampling.
|
||||||
|
* @param RB: Pointer to ring buffer structure
|
||||||
|
* @return -1 when failure, 0 otherwise.
|
||||||
|
* @note Called holding the mutex, with RB->full == 0.
|
||||||
|
* Keep generating until RB->full == 1.
|
||||||
|
*/
|
||||||
|
static int rng_gen (struct rng_rb *rb)
|
||||||
|
{
|
||||||
|
static uint8_t round = 0;
|
||||||
|
uint8_t b;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
chEvtWaitOne (ADC_DATA_AVAILABLE);
|
||||||
|
|
||||||
|
/* Got, ADC sampling data */
|
||||||
|
round++;
|
||||||
|
b = (((samp[0] & 0x01) << 0) | ((samp[1] & 0x01) << 1)
|
||||||
|
| ((samp[2] & 0x01) << 2) | ((samp[3] & 0x01) << 3)
|
||||||
|
| ((samp[4] & 0x01) << 4) | ((samp[5] & 0x01) << 5)
|
||||||
|
| ((samp[6] & 0x01) << 6) | ((samp[7] & 0x01) << 7));
|
||||||
|
|
||||||
|
adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH, adccb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put a random byte to entropy pool.
|
||||||
|
*/
|
||||||
|
ep_add (b, PROBABILITY_50_BY_TICK ());
|
||||||
|
|
||||||
|
if ((round % NUM_NOISE_INPUTS) == 0)
|
||||||
|
{ /* We have enough entropy in the pool. */
|
||||||
|
uint32_t v = ep_output (); /* Get the random bits from the pool. */
|
||||||
|
|
||||||
|
/* Mix the random bits from the pool with the output of PRNG. */
|
||||||
|
tmt_one_step ();
|
||||||
|
v ^= tmt_value ();
|
||||||
|
|
||||||
|
/* We got the final random bits, add it to the ring buffer. */
|
||||||
|
rb_add (rb, v);
|
||||||
|
round = 0;
|
||||||
|
if (rb->full)
|
||||||
|
/* fully generated */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Random number generation thread.
|
||||||
|
*/
|
||||||
|
static msg_t rng (void *arg)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = (struct rng_rb *)arg;
|
||||||
|
|
||||||
|
rng_thread = chThdSelf ();
|
||||||
|
|
||||||
|
adcStart (&ADCD1, NULL);
|
||||||
|
adcStartConversion (&ADCD1, &adcgrpcfg, samp, ADC_GRP1_BUF_DEPTH, adccb);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
chMtxLock (&rb->m);
|
||||||
|
while (rb->full)
|
||||||
|
chCondWait (&rb->space_available);
|
||||||
|
rng_gen (rb);
|
||||||
|
chCondSignal (&rb->data_available);
|
||||||
|
chMtxUnlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rng_rb the_ring_buffer;
|
||||||
|
static WORKING_AREA(wa_rng, 128);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize NeuG.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
neug_init (uint32_t *buf, uint8_t size)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
|
||||||
|
tmt_init (0);
|
||||||
|
rb_init (rb, buf, size);
|
||||||
|
chThdCreateStatic (wa_rng, sizeof (wa_rng), NORMALPRIO, rng, rb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @breif Flush random bytes.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
neug_flush (void)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
|
||||||
|
chMtxLock (&rb->m);
|
||||||
|
while (!rb->empty)
|
||||||
|
(void)rb_del (rb);
|
||||||
|
chCondSignal (&rb->space_available);
|
||||||
|
chMtxUnlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @breif Set seed to PRNG
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
neug_prng_reseed (void)
|
||||||
|
{
|
||||||
|
uint32_t seed = ep_output ();
|
||||||
|
|
||||||
|
tmt_init (seed);
|
||||||
|
neug_flush ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakes up RNG thread to generate random numbers.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
neug_kick_filling (void)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
|
||||||
|
chMtxLock (&rb->m);
|
||||||
|
if (!rb->full)
|
||||||
|
chCondSignal (&rb->space_available);
|
||||||
|
chMtxUnlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get random word (32-bit) from NeuG.
|
||||||
|
* @detail With NEUG_KICK_FILLING, it wakes up RNG thread.
|
||||||
|
* With NEUG_NO_KICK, it doesn't wake up RNG thread automatically,
|
||||||
|
* it is needed to call neug_kick_filling later.
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
neug_get (int kick)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
|
chMtxLock (&rb->m);
|
||||||
|
while (rb->empty)
|
||||||
|
chCondWait (&rb->data_available);
|
||||||
|
v = rb_del (rb);
|
||||||
|
if (kick)
|
||||||
|
chCondSignal (&rb->space_available);
|
||||||
|
chMtxUnlock ();
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
neug_wait_full (void)
|
||||||
|
{
|
||||||
|
struct rng_rb *rb = &the_ring_buffer;
|
||||||
|
|
||||||
|
chMtxLock (&rb->m);
|
||||||
|
while (!rb->full)
|
||||||
|
chCondWait (&rb->data_available);
|
||||||
|
chMtxUnlock ();
|
||||||
|
}
|
||||||
11
src/neug.h
Normal file
11
src/neug.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#define NEUG_NO_KICK 0
|
||||||
|
#define NEUG_KICK_FILLING 1
|
||||||
|
|
||||||
|
#define NEUG_PRE_LOOP 16
|
||||||
|
|
||||||
|
void neug_init (uint32_t *buf, uint8_t size);
|
||||||
|
void neug_prng_reseed (void);
|
||||||
|
uint32_t neug_get (int kick);
|
||||||
|
void neug_kick_filling (void);
|
||||||
|
void neug_flush (void);
|
||||||
|
void neug_wait_full (void);
|
||||||
@@ -98,14 +98,18 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
|
|||||||
*/
|
*/
|
||||||
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
|
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
|
||||||
0x00, 0x00, /* Max get challenge */
|
0x00, 0x00, /* Max get challenge */
|
||||||
|
#ifdef CERTDO_SUPPORT
|
||||||
0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/
|
0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/
|
||||||
|
#else
|
||||||
|
0x00, 0x00,
|
||||||
|
#endif
|
||||||
/* Max. length of command data */
|
/* Max. length of command data */
|
||||||
(MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff),
|
(MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff),
|
||||||
/* Max. length of response data */
|
/* Max. length of response data */
|
||||||
#if 0
|
#ifdef CERTDO_SUPPORT
|
||||||
(MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff),
|
|
||||||
#else
|
|
||||||
0x08, 0x00, /* the case of cardholder ceritificate */
|
0x08, 0x00, /* the case of cardholder ceritificate */
|
||||||
|
#else
|
||||||
|
(MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -627,6 +631,9 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
|||||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||||
struct key_data_internal kdi;
|
struct key_data_internal kdi;
|
||||||
|
|
||||||
|
DEBUG_INFO ("Loading private key: ");
|
||||||
|
DEBUG_BYTE (kk);
|
||||||
|
|
||||||
if (do_data == NULL)
|
if (do_data == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -646,6 +653,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
|||||||
/* more sanity check??? */
|
/* more sanity check??? */
|
||||||
|
|
||||||
memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN);
|
memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN);
|
||||||
|
DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,6 +1245,7 @@ copy_do (const struct do_table_entry *do_p, int with_tag)
|
|||||||
void
|
void
|
||||||
gpg_do_get_data (uint16_t tag, int with_tag)
|
gpg_do_get_data (uint16_t tag, int with_tag)
|
||||||
{
|
{
|
||||||
|
#if defined(CERTDO_SUPPORT)
|
||||||
if (tag == GPG_DO_CH_CERTIFICATE)
|
if (tag == GPG_DO_CH_CERTIFICATE)
|
||||||
{
|
{
|
||||||
res_APDU_pointer = &ch_certificate_start;
|
res_APDU_pointer = &ch_certificate_start;
|
||||||
@@ -1251,6 +1260,7 @@ gpg_do_get_data (uint16_t tag, int with_tag)
|
|||||||
res_APDU_size += 4 + 2;
|
res_APDU_size += 4 + 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
const struct do_table_entry *do_p = get_do_entry (tag);
|
const struct do_table_entry *do_p = get_do_entry (tag);
|
||||||
|
|
||||||
|
|||||||
281
src/openpgp.c
281
src/openpgp.c
@@ -62,13 +62,11 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
set_res_apdu (uint8_t sw1, uint8_t sw2)
|
||||||
{
|
{
|
||||||
res_APDU_size = 2 + len;
|
res_APDU_size = 2;
|
||||||
if (len)
|
res_APDU[0] = sw1;
|
||||||
memcpy (res_APDU, p, len);
|
res_APDU[1] = sw2;
|
||||||
res_APDU[len] = sw1;
|
|
||||||
res_APDU[len+1] = sw2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FILE_NONE 0
|
#define FILE_NONE 0
|
||||||
@@ -99,24 +97,19 @@ gpg_fini (void)
|
|||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
/*
|
/*
|
||||||
* Invoke the thread PIN_MAIN, and let user input PIN string.
|
* Let user input PIN string.
|
||||||
* Return length of the string.
|
* Return length of the string.
|
||||||
* The string itself is in PIN_INPUT_BUFFER.
|
* The string itself is in PIN_INPUT_BUFFER.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_pinpad_input (int msg_code)
|
get_pinpad_input (int msg_code)
|
||||||
{
|
{
|
||||||
Thread *t;
|
int r;
|
||||||
|
|
||||||
t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
|
chEvtSignal (main_thread, LED_INPUT_MODE);
|
||||||
NORMALPRIO, pin_main, (void *)msg_code);
|
r = pinpad_getline (msg_code, MS2ST (8000));
|
||||||
if (t == NULL)
|
chEvtSignal (main_thread, LED_STATUS_MODE);
|
||||||
return -1;
|
return r;
|
||||||
else
|
|
||||||
{
|
|
||||||
chThdWait (t);
|
|
||||||
return pin_input_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -132,32 +125,14 @@ cmd_verify (void)
|
|||||||
DEBUG_INFO (" - VERIFY\r\n");
|
DEBUG_INFO (" - VERIFY\r\n");
|
||||||
DEBUG_BYTE (p2);
|
DEBUG_BYTE (p2);
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
len = cmd_APDU[4];
|
||||||
if (cmd_APDU_size == 4)
|
if (len == 0) /* extended length */
|
||||||
/* Verification with pinpad */
|
|
||||||
{
|
{
|
||||||
len = get_pinpad_input (PIN_INPUT_CURRENT);
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
if (len < 0)
|
data_start = 7;
|
||||||
{
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pw = &cmd_APDU[data_start];
|
||||||
|
|
||||||
if (p2 == 0x81)
|
if (p2 == 0x81)
|
||||||
r = verify_pso_cds (pw, len);
|
r = verify_pso_cds (pw, len);
|
||||||
@@ -238,6 +213,7 @@ cmd_change_password (void)
|
|||||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||||
uint8_t *new_ks = &new_ks0[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 p2 = cmd_APDU[3];
|
||||||
int len;
|
int len;
|
||||||
const uint8_t *pw;
|
const uint8_t *pw;
|
||||||
@@ -249,62 +225,25 @@ cmd_change_password (void)
|
|||||||
DEBUG_INFO ("Change PW\r\n");
|
DEBUG_INFO ("Change PW\r\n");
|
||||||
DEBUG_BYTE (who);
|
DEBUG_BYTE (who);
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
len = cmd_APDU[4];
|
||||||
if (cmd_APDU_size == 4)
|
pw = &cmd_APDU[5];
|
||||||
/* Modification with pinpad */
|
if (len == 0) /* extended length */
|
||||||
{
|
{
|
||||||
pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
if (pw_len < 0)
|
pw += 2;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
if (p1 != 0)
|
||||||
{
|
{
|
||||||
len = cmd_APDU[4];
|
GPG_FUNCTION_NOT_SUPPORTED();
|
||||||
pw = &cmd_APDU[5];
|
return;
|
||||||
if (len == 0) /* extended length */
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
pw += 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (who == BY_USER) /* PW1 */
|
if (who == BY_USER) /* PW1 */
|
||||||
{
|
{
|
||||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
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)
|
if (pw_len < 0)
|
||||||
{
|
{
|
||||||
@@ -402,60 +341,12 @@ cmd_reset_user_password (void)
|
|||||||
DEBUG_INFO ("Reset PW1\r\n");
|
DEBUG_INFO ("Reset PW1\r\n");
|
||||||
DEBUG_BYTE (p1);
|
DEBUG_BYTE (p1);
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
len = cmd_APDU[4];
|
||||||
if (cmd_APDU_size == 4)
|
pw = &cmd_APDU[5];
|
||||||
/* Modification with pinpad */
|
if (len == 0) /* extended length */
|
||||||
{
|
{
|
||||||
if (p1 == 0x00) /* by User with Reseting Code */
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
{
|
pw += 2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p1 == 0x00) /* by User with Reseting Code */
|
if (p1 == 0x00) /* by User with Reseting Code */
|
||||||
@@ -579,8 +470,9 @@ cmd_put_data (void)
|
|||||||
GPG_NO_RECORD();
|
GPG_NO_RECORD();
|
||||||
|
|
||||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||||
len = cmd_APDU_size - 5;
|
|
||||||
data = &cmd_APDU[5];
|
data = &cmd_APDU[5];
|
||||||
|
|
||||||
|
len = cmd_APDU_size - 5;
|
||||||
if (len >= 256)
|
if (len >= 256)
|
||||||
/* extended Lc */
|
/* extended Lc */
|
||||||
{
|
{
|
||||||
@@ -678,10 +570,14 @@ cmd_select_file (void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_res_apdu (select_file_TOP_result,
|
int len = sizeof (select_file_TOP_result);
|
||||||
sizeof (select_file_TOP_result), 0x90, 0x00);
|
|
||||||
|
res_APDU_size = 2 + len;
|
||||||
|
memcpy (res_APDU, select_file_TOP_result, len);
|
||||||
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
||||||
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
||||||
|
res_APDU[len] = 0x90;
|
||||||
|
res_APDU[len+1] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_selection = FILE_MF;
|
file_selection = FILE_MF;
|
||||||
@@ -724,6 +620,7 @@ cmd_pso (void)
|
|||||||
|
|
||||||
DEBUG_INFO (" - PSO: ");
|
DEBUG_INFO (" - PSO: ");
|
||||||
DEBUG_WORD ((uint32_t)&r);
|
DEBUG_WORD ((uint32_t)&r);
|
||||||
|
DEBUG_BINARY (cmd_APDU, cmd_APDU_size);
|
||||||
|
|
||||||
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
|
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
|
||||||
{
|
{
|
||||||
@@ -749,6 +646,7 @@ cmd_pso (void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
|
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
|
||||||
|
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
||||||
|
|
||||||
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
|
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
|
||||||
&kd[GPG_KEY_FOR_SIGNING]);
|
&kd[GPG_KEY_FOR_SIGNING]);
|
||||||
@@ -765,6 +663,7 @@ cmd_pso (void)
|
|||||||
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
||||||
{
|
{
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
|
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||||
|
|
||||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||||
{
|
{
|
||||||
@@ -946,7 +845,7 @@ cmd_write_binary (void)
|
|||||||
{
|
{
|
||||||
if (file_selection != FILE_EF_CH_CERTIFICATE
|
if (file_selection != FILE_EF_CH_CERTIFICATE
|
||||||
&& file_selection != FILE_EF_RANDOM
|
&& file_selection != FILE_EF_RANDOM
|
||||||
&& file_selection != FILEID_SERIAL_NO)
|
&& file_selection != FILE_EF_SERIAL)
|
||||||
{
|
{
|
||||||
GPG_COMMAND_NOT_ALLOWED ();
|
GPG_COMMAND_NOT_ALLOWED ();
|
||||||
return;
|
return;
|
||||||
@@ -1026,18 +925,102 @@ GPGthread (void *arg)
|
|||||||
|
|
||||||
while (!chThdShouldTerminate ())
|
while (!chThdShouldTerminate ())
|
||||||
{
|
{
|
||||||
eventmask_t m;
|
eventmask_t m = chEvtWaitOne (ALL_EVENTS);
|
||||||
|
#if defined(PINPAD_SUPPORT)
|
||||||
m = chEvtWaitOne (ALL_EVENTS);
|
int len, pw_len, newpw_len;
|
||||||
|
#endif
|
||||||
|
|
||||||
DEBUG_INFO ("GPG!: ");
|
DEBUG_INFO ("GPG!: ");
|
||||||
DEBUG_WORD ((uint32_t)&m);
|
|
||||||
|
|
||||||
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)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((bConfirmPIN & 2)) /* Require old PIN */
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pw_len = 0;
|
||||||
|
|
||||||
|
newpw_len = get_pinpad_input (PIN_INPUT_NEW);
|
||||||
|
if (newpw_len < 0)
|
||||||
|
{
|
||||||
|
GPG_ERROR ();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memcpy (p, pin_input_buffer, newpw_len);
|
||||||
|
|
||||||
|
if ((bConfirmPIN & 1)) /* New PIN twice */
|
||||||
|
{
|
||||||
|
len = get_pinpad_input (PIN_INPUT_CONFIRM);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
GPG_ERROR ();
|
||||||
|
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;
|
||||||
|
icc_data_size = 5 + len;
|
||||||
|
#else
|
||||||
|
GPG_ERROR ();
|
||||||
|
goto done;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (m == EV_NOP)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (icc_data_size != 0)
|
if (icc_data_size != 0)
|
||||||
{
|
{
|
||||||
process_command_apdu ();
|
process_command_apdu ();
|
||||||
|
done:
|
||||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
|
#define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81)
|
||||||
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
|
#define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82)
|
||||||
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
|
#define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83)
|
||||||
#define GPG_COMMAND_NOT_ALLOWED() write_res_apdu (NULL, 0, 0x69, 0x86)
|
#define GPG_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85)
|
||||||
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
|
#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86)
|
||||||
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
|
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81)
|
||||||
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
|
#define GPG_NO_FILE() set_res_apdu (0x6a, 0x82)
|
||||||
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
|
#define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88)
|
||||||
#define GPG_ERROR() write_res_apdu (NULL, 0, 0x6f, 0x00)
|
#define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00)
|
||||||
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 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)
|
||||||
|
|||||||
683
src/pin-cir.c
683
src/pin-cir.c
@@ -27,13 +27,41 @@
|
|||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG
|
||||||
#define DEBUG_CIR 1
|
#define DEBUG_CIR 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
uint8_t pin_input_len;
|
uint8_t pin_input_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported/tested TV controllers:
|
||||||
|
*
|
||||||
|
* Controller of Toshiba REGZA
|
||||||
|
* Controller of Sony BRAVIA
|
||||||
|
* Controller of Sharp AQUOS
|
||||||
|
* Dell Wireless Travel Remote MR425
|
||||||
|
*
|
||||||
|
* The code supports RC-5 protocol in fact, but I don't have any
|
||||||
|
* controller at hand which I can test with, so I don't have any data
|
||||||
|
* for controller of RC-5.
|
||||||
|
*
|
||||||
|
* Current code assumes following mapping:
|
||||||
|
*
|
||||||
|
* --------------------------------------
|
||||||
|
* Protocol Controller
|
||||||
|
* --------------------------------------
|
||||||
|
* RC-6 Dell MR425
|
||||||
|
* NEC Toshiba REGZA
|
||||||
|
* Sharp Sharp AQUOS
|
||||||
|
* Sony Sony BRAVIA
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* In future, when I will have other controllers, this mapping will be
|
||||||
|
* (should be) configurable, at compile time at least, preferably at
|
||||||
|
* runtime.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Philips RC-5 Protocol: 14-bit (MSB first)
|
* Philips RC-5 Protocol: 14-bit (MSB first)
|
||||||
*
|
*
|
||||||
@@ -69,18 +97,26 @@ uint8_t pin_input_len;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PB0 / TIM3_CH3
|
* The implementation note of CIR signal decoding (on STM32).
|
||||||
|
*
|
||||||
|
* (1) Use EXTI interrupt to detect the first edge of signal.
|
||||||
|
* (2) Use Timer (with PWM input mode) to measure timings of square wave.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer settings.
|
||||||
|
*
|
||||||
|
* See THE reference manual (RM0008) section 15.3.6 PWM input mode.
|
||||||
*
|
*
|
||||||
* 72MHz
|
* 72MHz
|
||||||
*
|
|
||||||
* Prescaler = 72
|
* Prescaler = 72
|
||||||
*
|
*
|
||||||
* 1us
|
* 1us
|
||||||
*
|
*
|
||||||
*
|
* TIMx_CR1
|
||||||
* TIM3_CR1
|
* CKD = 00 (tDTS = tCK_INT)
|
||||||
* CKD = 10 (sampling x4)
|
* ARPE = 1 (buffered)
|
||||||
* ARPE = 0 (not buffered)
|
|
||||||
* CMS = 00 (up counter)
|
* CMS = 00 (up counter)
|
||||||
* DIR = 0 (up counter)
|
* DIR = 0 (up counter)
|
||||||
* OPM = 0 (up counter)
|
* OPM = 0 (up counter)
|
||||||
@@ -88,13 +124,13 @@ uint8_t pin_input_len;
|
|||||||
* UDIS = 0 (UEV (update event) enabled)
|
* UDIS = 0 (UEV (update event) enabled)
|
||||||
* CEN = 1 (counter enable)
|
* CEN = 1 (counter enable)
|
||||||
*
|
*
|
||||||
* TIM3_CR2
|
* TIMx_CR2
|
||||||
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
|
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
|
||||||
* MMS = 000 (TRGO at Reset)
|
* MMS = 000 (TRGO at Reset)
|
||||||
* CCDS = 0 (DMA on capture)
|
* CCDS = 0 (DMA on capture)
|
||||||
* RSVD = 000
|
* RSVD = 000
|
||||||
*
|
*
|
||||||
* TIM3_SMCR
|
* TIMx_SMCR
|
||||||
* ETP = 0
|
* ETP = 0
|
||||||
* ECE = 0
|
* ECE = 0
|
||||||
* ETPS = 00
|
* ETPS = 00
|
||||||
@@ -104,61 +140,37 @@ uint8_t pin_input_len;
|
|||||||
* RSVD = 0
|
* RSVD = 0
|
||||||
* SMS = 100 (Reset-mode)
|
* SMS = 100 (Reset-mode)
|
||||||
*
|
*
|
||||||
* TIM3_DIER
|
* TIMx_DIER
|
||||||
*
|
*
|
||||||
* TIM3_SR
|
* TIMx_SR
|
||||||
*
|
*
|
||||||
* TIM3_EGR
|
* TIMx_EGR
|
||||||
*
|
*
|
||||||
* TIM3_CCMR1
|
* TIMx_CCMR1
|
||||||
* CC1S = 01 (TI1 selected)
|
* CC1S = 01 (TI1 selected)
|
||||||
* CC2S = 10 (TI1 selected)
|
* CC2S = 10 (TI1 selected)
|
||||||
|
* IC1F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||||
|
* IC2F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||||
*
|
*
|
||||||
* TIM3_CCMR2
|
* TIMx_CCMR2
|
||||||
*
|
*
|
||||||
* TIM3_CCER
|
* TIMx_CCER
|
||||||
* CC2P = 1 (polarity = falling edge: TI1FP1)
|
* CC2P = 1 (polarity = falling edge: TI1FP1)
|
||||||
* CC2E = 1
|
* CC2E = 1
|
||||||
* CC1P = 0 (polarity = rising edge: TI1FP1)
|
* CC1P = 0 (polarity = rising edge: TI1FP1)
|
||||||
* CC1E = 1
|
* CC1E = 1
|
||||||
*
|
*
|
||||||
* TIM3_CNT
|
* TIMx_CNT
|
||||||
* TIM3_PSC = 71
|
* TIMx_PSC = 71
|
||||||
* TIM3_ARR = 18000
|
* TIMx_ARR = 18000
|
||||||
*
|
*
|
||||||
* TIM3_CCR1 period
|
* TIMx_CCR1 period
|
||||||
* TIM3_CCR2 duty
|
* TIMx_CCR2 duty
|
||||||
*
|
*
|
||||||
* TIM3_DCR
|
* TIMx_DCR
|
||||||
* TIM3_DMAR
|
* TIMx_DMAR
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PINDISP_TIMEOUT_INTERVAL0 MS2ST(25)
|
|
||||||
#define PINDISP_TIMEOUT_INTERVAL1 MS2ST(300)
|
|
||||||
|
|
||||||
static void
|
|
||||||
pindisp (uint8_t c)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_7SEGLED)
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'G':
|
|
||||||
palWritePort (IOPORT2, 0xa1ff);
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
palWritePort (IOPORT2, 0x98ff);
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
palWritePort (IOPORT2, 0x7fff);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
palWritePort (IOPORT2, 0xffff);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)c;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
#if defined(DEBUG_CIR)
|
||||||
static uint16_t intr_ext;
|
static uint16_t intr_ext;
|
||||||
static uint16_t intr_trg;
|
static uint16_t intr_trg;
|
||||||
@@ -179,14 +191,6 @@ static uint8_t cir_proto;
|
|||||||
#define CIR_PROTO_NEC 5
|
#define CIR_PROTO_NEC 5
|
||||||
#define CIR_PROTO_SHARP 6
|
#define CIR_PROTO_SHARP 6
|
||||||
|
|
||||||
#define CIR_KEY_RC6_ENTER 0x0d /* Mute */
|
|
||||||
#define CIR_KEY_RC6_BACKSPACE 0xa4 /* <= */
|
|
||||||
#define CIR_KEY_NEC_ENTER 0x3d /* 'kettei' */
|
|
||||||
#define CIR_KEY_NEC_BACKSPACE 0x3b /* 'modoru' */
|
|
||||||
#define CIR_KEY_SONY_ENTER 0x65 /* 'kettei' */
|
|
||||||
#define CIR_KEY_SONY_BACKSPACE 0xa3 /* 'modoru' */
|
|
||||||
#define CIR_KEY_SHARP_ENTER 0x0252 /* 'kettei' */
|
|
||||||
#define CIR_KEY_SHARP_BACKSPACE 0xe4 /* 'modoru' */
|
|
||||||
|
|
||||||
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
|
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
|
||||||
static uint8_t cir_data_zero;
|
static uint8_t cir_data_zero;
|
||||||
@@ -196,6 +200,388 @@ static uint8_t cir_seq;
|
|||||||
static systime_t cir_input_last;
|
static systime_t cir_input_last;
|
||||||
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
|
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
|
||||||
|
|
||||||
|
static void
|
||||||
|
cir_init (void)
|
||||||
|
{
|
||||||
|
cir_data = 0;
|
||||||
|
cir_seq = 0;
|
||||||
|
/* Don't touch cir_proto here */
|
||||||
|
cir_ext_enable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define CH_RETURN 0x0d
|
||||||
|
#define CH_BACKSPACE 0x08
|
||||||
|
|
||||||
|
struct codetable {
|
||||||
|
uint16_t cir_code;
|
||||||
|
uint8_t char_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NOTE: no way to input '0' */
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_dell_mr425[] = {
|
||||||
|
{0x10, '7' }, /* Speaker Louder */
|
||||||
|
{0x11, '8' }, /* Speaker Quieter */
|
||||||
|
{0x0d, '9' }, /* Speaker Mute */
|
||||||
|
{0xce, 'a' }, /* Black triangle UP */
|
||||||
|
{0xcf, 'b' }, /* Black triangle DOWN */
|
||||||
|
{0x58, 'c' }, /* White triangle UP */
|
||||||
|
{0x5a, 'd' }, /* White triangle LEFT */
|
||||||
|
{0x5c, CH_RETURN }, /* Check */
|
||||||
|
{0x5b, 'e' }, /* White triangle RIGHT */
|
||||||
|
{0xa4, CH_BACKSPACE }, /* Back */
|
||||||
|
{0x59, 'f' }, /* White triangle DOWN */
|
||||||
|
{0x2f, '1' }, /* Rewind */
|
||||||
|
{0x2c, '2' }, /* Play / Pause */
|
||||||
|
{0x2e, '3' }, /* Forward */
|
||||||
|
{0x21, '4' }, /* Skip backward */
|
||||||
|
{0x31, '5' }, /* Stop */
|
||||||
|
{0x20, '6' }, /* Skip forward */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CIR_ADDR_SHARP_AQUOS 0x028f
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_aquos[] = {
|
||||||
|
{ 0x0116, ' ' }, /* Power */
|
||||||
|
{ 0x025e, '0' }, /* d */
|
||||||
|
{ 0x024e, '1' }, /* 1 */
|
||||||
|
{ 0x024f, '2' }, /* 2 */
|
||||||
|
{ 0x0250, '3' }, /* 3 */
|
||||||
|
{ 0x0251, '4' }, /* 4 */
|
||||||
|
{ 0x0252, '5' }, /* 5 */
|
||||||
|
{ 0x0253, '6' }, /* 6 */
|
||||||
|
{ 0x0254, '7' }, /* 7 */
|
||||||
|
{ 0x0255, '8' }, /* 8 */
|
||||||
|
{ 0x0256, '9' }, /* 9 */
|
||||||
|
{ 0x0257, 'a' }, /* 10/0 */
|
||||||
|
{ 0x0258, 'b' }, /* 11 */
|
||||||
|
{ 0x0259, 'c' }, /* 12 */
|
||||||
|
{ 0x0111, 'd' }, /* Ch ^ */
|
||||||
|
{ 0x0112, 'e' }, /* Ch v */
|
||||||
|
{ 0x0114, 'f' }, /* Vol + */
|
||||||
|
{ 0x0115, 'g' }, /* Vol - */
|
||||||
|
{ 0x0117, 'h' }, /* Mute */
|
||||||
|
{ 0x0280, 'i' }, /* BLUE */
|
||||||
|
{ 0x0281, 'j' }, /* RED */
|
||||||
|
{ 0x0282, 'k' }, /* GREEN */
|
||||||
|
{ 0x0283, 'l' }, /* YELLOW */
|
||||||
|
{ 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */
|
||||||
|
{ 0x01d5, 'n' }, /* DISPLAY SIZE */
|
||||||
|
{ 0x0157, 'o' }, /* UP */
|
||||||
|
{ 0x01d7, 'p' }, /* LEFT */
|
||||||
|
{ 0x01d8, 'q' }, /* RIGHT */
|
||||||
|
{ 0x0120, 'r' }, /* DOWN */
|
||||||
|
{ 0x0152, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0x01e4, CH_BACKSPACE }, /* Back (modoru) */
|
||||||
|
{ 0x01f5, 's' }, /* Quit (shuuryou) */
|
||||||
|
{ 0x0b03, 't' }, /* Rewind (hayamodoshi) */
|
||||||
|
{ 0x0b01, 'u' }, /* Play (saisei) */
|
||||||
|
{ 0x0b04, 'v' }, /* Forward (hayaokuri) */
|
||||||
|
{ 0x0b02, 'w' }, /* Stop (teishi) */
|
||||||
|
{ 0x028a, 'x' }, /* BS */
|
||||||
|
{ 0x028b, 'y' }, /* CS */
|
||||||
|
{ 0x025f, 'z' }, /* Program information (bangumi jouhou) */
|
||||||
|
{ 0x0260, '\\' }, /* Program table (bangumi hyou) */
|
||||||
|
{ 0x0118, '|' }, /* Sound channel (onsei kirikae) */
|
||||||
|
{ 0x028e, '[' }, /* Ground Analog (chijou A) */
|
||||||
|
{ 0x0289, ']' }, /* Ground Digital (chijou D) */
|
||||||
|
|
||||||
|
{ 0x0b07, '\"' }, /* Feature select (kinou sentaku) */
|
||||||
|
{ 0x026b, '.' }, /* TV/Radio/Data (terebi/rajio/data) */
|
||||||
|
{ 0x025a, ',' }, /* 3 code input (3 keta nyuuryoku) */
|
||||||
|
{ 0x0267, ':' }, /* subtitle (jimaku) */
|
||||||
|
{ 0x0159, ';' }, /* hold (seishi) */
|
||||||
|
|
||||||
|
{ 0x01c4, 'A' }, /* Menu */
|
||||||
|
{ 0x011a, 'B' }, /* Off timer */
|
||||||
|
{ 0x0121, 'C' }, /* CATV */
|
||||||
|
{ 0x0b05, 'D' }, /* Record */
|
||||||
|
{ 0x0b06, 'E' }, /* Recording stop */
|
||||||
|
{ 0x0113, 'F' }, /* Inputs (nyuuryoku kirikae) */
|
||||||
|
{ 0x0275, 'G' }, /* other programs (ura bangumi) */
|
||||||
|
{ 0x0266, 'H' }, /* signal control (eizou kirikae) */
|
||||||
|
{ 0x01e7, 'I' }, /* AV position */
|
||||||
|
{ 0x027f, 'J' }, /* i.LINK */
|
||||||
|
{ 0x0b00, 'K' }, /* Recorder power */
|
||||||
|
{ 0x028f, 'L' }, /* as you like it (okonomi senkyoku) */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CIR_ADDR_TOSHIBA_REGZA 0xbf40
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_regza[] = {
|
||||||
|
{ 0x12, ' ' }, /* Power */
|
||||||
|
{ 0x14, '0' }, /* d (data) */
|
||||||
|
{ 0x01, '1' }, /* 1 */
|
||||||
|
{ 0x02, '2' }, /* 2 */
|
||||||
|
{ 0x03, '3' }, /* 3 */
|
||||||
|
{ 0x04, '4' }, /* 4 */
|
||||||
|
{ 0x05, '5' }, /* 5 */
|
||||||
|
{ 0x06, '6' }, /* 6 */
|
||||||
|
{ 0x07, '7' }, /* 7 */
|
||||||
|
{ 0x08, '8' }, /* 8 */
|
||||||
|
{ 0x09, '9' }, /* 9 */
|
||||||
|
{ 0x0a, 'a' }, /* 10 */
|
||||||
|
{ 0x0b, 'b' }, /* 11 */
|
||||||
|
{ 0x0c, 'c' }, /* 12 */
|
||||||
|
{ 0x1b, 'd' }, /* Ch ^ */
|
||||||
|
{ 0x1f, 'e' }, /* Ch v */
|
||||||
|
{ 0x1a, 'f' }, /* Vol + */
|
||||||
|
{ 0x1e, 'g' }, /* Vol - */
|
||||||
|
{ 0x10, 'h' }, /* Mute */
|
||||||
|
{ 0x73, 'i' }, /* BLUE */
|
||||||
|
{ 0x74, 'j' }, /* RED */
|
||||||
|
{ 0x75, 'k' }, /* GREEN */
|
||||||
|
{ 0x76, 'l' }, /* YELLOW */
|
||||||
|
{ 0x1c, 'm' }, /* Display control */
|
||||||
|
{ 0x2b, 'n' }, /* Display size */
|
||||||
|
{ 0x3e, 'o' }, /* UP */
|
||||||
|
{ 0x5f, 'p' }, /* LEFT */
|
||||||
|
{ 0x5b, 'q' }, /* RIGHT */
|
||||||
|
{ 0x3f, 'r' }, /* DOWN */
|
||||||
|
{ 0x3d, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0x3b, CH_BACKSPACE }, /* Back (modoru) */
|
||||||
|
{ 0x3c, 's' }, /* Quit (shuuryou) */
|
||||||
|
{ 0x2c, 't' }, /* << (Rewind) */
|
||||||
|
{ 0x2d, 'u' }, /* >/|| (Play/Stop) */
|
||||||
|
{ 0x2e, 'v' }, /* >> (Forward) */
|
||||||
|
{ 0x2b, 'w' }, /* Stop (teishi) */
|
||||||
|
{ 0x7c, 'x' }, /* BS */
|
||||||
|
{ 0x7d, 'y' }, /* CS */
|
||||||
|
{ 0x71, 'z' }, /* Program information (bangumi setsumei) */
|
||||||
|
{ 0x77, '\\' }, /* Mini program table (mini bangumihyou) */
|
||||||
|
{ 0x13, '|' }, /* Sound (onta kirikae) */
|
||||||
|
{ 0x7a, '[' }, /* Ground Digital (chideji) */
|
||||||
|
{ 0x7b, ']' }, /* Ground Analog (chiana) */
|
||||||
|
|
||||||
|
{ 0xd0, '\"' }, /* Settings Menu (settei menu) */
|
||||||
|
{ 0x6d, '.' }, /* Radio/Data (rajio/data) */
|
||||||
|
{ 0x60, ',' }, /* CH 10-key input (search) */
|
||||||
|
{ 0x52, ':' }, /* subtitle (jimaku) */
|
||||||
|
{ 0x50, ';' }, /* hold (seishi) */
|
||||||
|
|
||||||
|
{ 0x3a, 'A' }, /* Input- (nyuuryokukirikae-) */
|
||||||
|
{ 0x0f, 'B' }, /* Input+ (nyuuryokukirikae+) */
|
||||||
|
{ 0x29, 'C' }, /* Two screens (nigamen) */
|
||||||
|
{ 0x25, 'D' }, /* Broadband */
|
||||||
|
{ 0x27, 'E' }, /* |<< Skip backward */
|
||||||
|
{ 0x26, 'F' }, /* >>| Skip forward */
|
||||||
|
{ 0x61, '!' }, /* 1 NHK1 */
|
||||||
|
{ 0x62, '@' }, /* 2 NHK2 */
|
||||||
|
{ 0x63, '#' }, /* 3 NHKh */
|
||||||
|
{ 0x64, '$' }, /* 4 BS Nihon TV */
|
||||||
|
{ 0x65, '%' }, /* 5 BS Asahi */
|
||||||
|
{ 0x66, '^' }, /* 6 BS-i */
|
||||||
|
{ 0x67, '&' }, /* 7 BSJ */
|
||||||
|
{ 0x68, '*' }, /* 8 BS Fuji */
|
||||||
|
{ 0x69, '(' }, /* 9 WOW */
|
||||||
|
{ 0x6a, ')' }, /* 10 Star */
|
||||||
|
{ 0x6b, '-' }, /* 11 BS11 */
|
||||||
|
{ 0x6c, '+' }, /* 12 TwellV */
|
||||||
|
{ 0x27, '=' }, /* Quick (Delete) */
|
||||||
|
{ 0x34, '<' }, /* REGZA link */
|
||||||
|
{ 0x6e, '>' }, /* Program Table */
|
||||||
|
{ 0x20, '/' }, /* ^^ */
|
||||||
|
{ 0x22, '\'' }, /* << */
|
||||||
|
{ 0x23, '?' }, /* >> */
|
||||||
|
{ 0x21, '_' }, /* vv */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_bravia[] = {
|
||||||
|
{ 0x15, ' ' }, /* Power */
|
||||||
|
{ 0x95, '0' }, /* d (16-bit: 0x4b) */
|
||||||
|
{ 0x00, '1' }, /* 1 */
|
||||||
|
{ 0x01, '2' }, /* 2 */
|
||||||
|
{ 0x02, '3' }, /* 3 */
|
||||||
|
{ 0x03, '4' }, /* 4 */
|
||||||
|
{ 0x04, '5' }, /* 5 */
|
||||||
|
{ 0x05, '6' }, /* 6 */
|
||||||
|
{ 0x06, '7' }, /* 7 */
|
||||||
|
{ 0x07, '8' }, /* 8 */
|
||||||
|
{ 0x08, '9' }, /* 9 */
|
||||||
|
{ 0x09, 'a' }, /* 10 */
|
||||||
|
{ 0x0a, 'b' }, /* 11 */
|
||||||
|
{ 0x0b, 'c' }, /* 12 */
|
||||||
|
{ 0x10, 'd' }, /* CH+ */
|
||||||
|
{ 0x11, 'd' }, /* CH- */
|
||||||
|
{ 0x12, 'f' }, /* Vol+ */
|
||||||
|
{ 0x13, 'g' }, /* Vol- */
|
||||||
|
{ 0x14, 'h' }, /* Mute */
|
||||||
|
{ 0xa4, 'i' }, /* BLUE (16-bit: 0x4b) */
|
||||||
|
{ 0xa5, 'j' }, /* RED (16-bit: 0x4b) */
|
||||||
|
{ 0xa6, 'k' }, /* GREEN (16-bit: 0x4b) */
|
||||||
|
{ 0xa7, 'l' }, /* YELLOW (16-bit: 0x4b) */
|
||||||
|
{ 0x3a, 'm' }, /* DISPLAY control (gamen hyouji) */
|
||||||
|
{ 0x3d, 'n' }, /* Display Wide (waido kirikae) */
|
||||||
|
{ 0x74, 'o' }, /* UP */
|
||||||
|
{ 0x75, 'p' }, /* DOWN */
|
||||||
|
{ 0x33, 'q' }, /* RIGHT */
|
||||||
|
{ 0x34, 'r' }, /* LEFT */
|
||||||
|
{ 0x65, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0xa3, CH_BACKSPACE }, /* Back (modoru) (16-bit: 0x4b) */
|
||||||
|
{ 0xac, 's' }, /* BS (16-bit: 0x4b) */
|
||||||
|
{ 0xab, 't' }, /* CS (16-bit: 0x4b) */
|
||||||
|
{ 0x5b, 'u' }, /* Program table (bangumi hyou) (16-bit: 0x52) */
|
||||||
|
{ 0x17, 'v' }, /* Sound channel (onsei kirikae) */
|
||||||
|
{ 0xa8, 'w' }, /* subtitle (jimaku) (16-bit: 0x4b) */
|
||||||
|
{ 0x5c, 'x' }, /* hold (memo) */
|
||||||
|
{ 0xb6, 'y' }, /* Tool (16-bit: 0x4b) */
|
||||||
|
{ 0x8c, 'z' }, /* 10 key input (10ki-) (16-bit: 0x4b) */
|
||||||
|
{ 0x60, '!' }, /* Menu */
|
||||||
|
{ 0xae, '@' }, /* Analog (16-bit: 0x4b) */
|
||||||
|
{ 0xb2, '#' }, /* Digital (16-bit: 0x4b) */
|
||||||
|
{ 0x25, '$' }, /* Input (nyuuryoku kirikae) */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
ch_is_backspace (int ch)
|
||||||
|
{
|
||||||
|
return ch == CH_BACKSPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ch_is_enter (int ch)
|
||||||
|
{
|
||||||
|
return ch == CH_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* liner search is good enough for this small amount of data */
|
||||||
|
static uint8_t
|
||||||
|
find_char_codetable (uint32_t cir_code, const struct codetable *ctp)
|
||||||
|
{
|
||||||
|
while (ctp->cir_code != 0x0000 || ctp->char_code != 0x00)
|
||||||
|
if (ctp->cir_code == cir_code)
|
||||||
|
return ctp->char_code;
|
||||||
|
else
|
||||||
|
ctp++;
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
return cir_code & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hex (int x)
|
||||||
|
{
|
||||||
|
if (x < 10)
|
||||||
|
return x + '0';
|
||||||
|
else
|
||||||
|
return (x - 10) + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cir_getchar (systime_t timeout)
|
||||||
|
{
|
||||||
|
uint16_t cir_addr;
|
||||||
|
eventmask_t m;
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
uint16_t *p;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
cirinput_p = cirinput;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chEvtClear (ALL_EVENTS);
|
||||||
|
cir_init ();
|
||||||
|
|
||||||
|
m = chEvtWaitOneTimeout (ALL_EVENTS, timeout);
|
||||||
|
if (m == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
DEBUG_INFO ("****\r\n");
|
||||||
|
DEBUG_SHORT (intr_ext);
|
||||||
|
DEBUG_SHORT (intr_trg);
|
||||||
|
DEBUG_SHORT (intr_ovf);
|
||||||
|
DEBUG_INFO ("----\r\n");
|
||||||
|
for (p = cirinput; p < cirinput_p; p++)
|
||||||
|
DEBUG_SHORT (*p);
|
||||||
|
DEBUG_INFO ("====\r\n");
|
||||||
|
|
||||||
|
cirinput_p = cirinput;
|
||||||
|
|
||||||
|
DEBUG_INFO ("**** CIR data:");
|
||||||
|
DEBUG_WORD (cir_data);
|
||||||
|
if (cir_seq > 48)
|
||||||
|
DEBUG_SHORT (cir_data_more);
|
||||||
|
DEBUG_BYTE (cir_seq);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (cir_proto)
|
||||||
|
{
|
||||||
|
case CIR_PROTO_RC5:
|
||||||
|
cir_data &= 0x003f;
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_RC6:
|
||||||
|
cir_addr = cir_data >> 8; /* in case of cir_seq == 16. 32??? */
|
||||||
|
cir_data &= 0x00ff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_dell_mr425);
|
||||||
|
case CIR_PROTO_NEC:
|
||||||
|
cir_addr = cir_data&0xffff;
|
||||||
|
if (cir_addr == CIR_ADDR_TOSHIBA_REGZA)
|
||||||
|
{
|
||||||
|
cir_data = (cir_data >> 16) & 0x00ff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_regza);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_SHARP:
|
||||||
|
cir_addr = cir_data&0x0fff;
|
||||||
|
if (cir_addr == CIR_ADDR_SHARP_AQUOS)
|
||||||
|
{
|
||||||
|
cir_data = (cir_data>>16)&0x0fff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_aquos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_SONY:
|
||||||
|
/* Remove ADDRESS bits and filter COMMAND bits */
|
||||||
|
if (cir_seq == 1 + 12)
|
||||||
|
{
|
||||||
|
cir_addr = cir_data >> 7;
|
||||||
|
cir_data = cir_data & 0x007f;
|
||||||
|
/* ADDRESS = 0x01 (5-bit) */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cir_addr = cir_data >> 8;
|
||||||
|
cir_data = cir_data & 0x00ff;
|
||||||
|
/* ADDRESS = 0x4b or 0x52 (7-bit) */
|
||||||
|
}
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_bravia);
|
||||||
|
err:
|
||||||
|
default:
|
||||||
|
/* encode debug information */
|
||||||
|
pin_input_len = 16;
|
||||||
|
pin_input_buffer[0] = hex (cir_proto >> 4);
|
||||||
|
pin_input_buffer[1] = hex (cir_proto & 0x0f);
|
||||||
|
pin_input_buffer[2] = ':';
|
||||||
|
pin_input_buffer[3] = hex ((cir_data >> 28) & 0x0f);
|
||||||
|
pin_input_buffer[4] = hex ((cir_data >> 24) & 0x0f);
|
||||||
|
pin_input_buffer[5] = hex ((cir_data >> 20) & 0x0f);
|
||||||
|
pin_input_buffer[6] = hex ((cir_data >> 16) & 0x0f);
|
||||||
|
pin_input_buffer[7] = hex ((cir_data >> 12) & 0x0f);
|
||||||
|
pin_input_buffer[8] = hex ((cir_data >> 8) & 0x0f);
|
||||||
|
pin_input_buffer[9] = hex ((cir_data >> 4) & 0x0f);
|
||||||
|
pin_input_buffer[10] = hex (cir_data & 0x0f);
|
||||||
|
pin_input_buffer[11] = ':';
|
||||||
|
pin_input_buffer[12] = hex ((cir_data_more >> 12) & 0x0f);
|
||||||
|
pin_input_buffer[13] = hex ((cir_data_more >> 8) & 0x0f);
|
||||||
|
pin_input_buffer[14] = hex ((cir_data_more >> 4) & 0x0f);
|
||||||
|
pin_input_buffer[15] = hex (cir_data_more & 0x0f);
|
||||||
|
return CH_RETURN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RC-5 protocol doesn't have a start bit, while any other protocols
|
* RC-5 protocol doesn't have a start bit, while any other protocols
|
||||||
* have the one.
|
* have the one.
|
||||||
@@ -207,125 +593,56 @@ static systime_t cir_input_last;
|
|||||||
#define CIR_BIT_PERIOD 1500
|
#define CIR_BIT_PERIOD 1500
|
||||||
#define CIR_BIT_SIRC_PERIOD_ON 1000
|
#define CIR_BIT_SIRC_PERIOD_ON 1000
|
||||||
|
|
||||||
static void
|
|
||||||
cir_init (void)
|
|
||||||
{
|
|
||||||
cir_data = 0;
|
|
||||||
cir_seq = 0;
|
|
||||||
/* Don't touch cir_proto here */
|
|
||||||
cir_ext_enable ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Thread *pin_thread;
|
static Thread *pin_thread;
|
||||||
|
|
||||||
static int
|
/*
|
||||||
cir_key_is_backspace (void)
|
* Let user input PIN string.
|
||||||
|
* Return length of the string.
|
||||||
|
* The string itself is in PIN_INPUT_BUFFER.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
pinpad_getline (int msg_code, systime_t timeout)
|
||||||
{
|
{
|
||||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_BACKSPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cir_key_is_enter (void)
|
|
||||||
{
|
|
||||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_ENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_t
|
|
||||||
pin_main (void *arg)
|
|
||||||
{
|
|
||||||
uint8_t s = 0;
|
|
||||||
int msg_code = (int)arg;
|
|
||||||
|
|
||||||
(void)msg_code;
|
(void)msg_code;
|
||||||
|
|
||||||
pin_thread = chThdSelf ();
|
pin_thread = chThdSelf ();
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
DEBUG_INFO (">>>\r\n");
|
||||||
cirinput_p = cirinput;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pin_input_len = 0;
|
pin_input_len = 0;
|
||||||
chEvtClear (ALL_EVENTS);
|
while (1)
|
||||||
cir_init ();
|
|
||||||
|
|
||||||
while (!chThdShouldTerminate ())
|
|
||||||
{
|
{
|
||||||
eventmask_t m;
|
int ch;
|
||||||
|
|
||||||
m = chEvtWaitOneTimeout (ALL_EVENTS, PINDISP_TIMEOUT_INTERVAL1);
|
ch = cir_getchar (timeout);
|
||||||
|
if (ch < 0)
|
||||||
|
return 0; /* timeout */
|
||||||
|
|
||||||
if (m)
|
if (ch_is_backspace (ch))
|
||||||
{
|
{
|
||||||
#if defined(DEBUG_CIR)
|
led_blink (2);
|
||||||
uint16_t *p;
|
if (pin_input_len > 0)
|
||||||
|
pin_input_len--;
|
||||||
DEBUG_INFO ("****\r\n");
|
|
||||||
DEBUG_SHORT (intr_ext);
|
|
||||||
DEBUG_SHORT (intr_trg);
|
|
||||||
DEBUG_SHORT (intr_ovf);
|
|
||||||
DEBUG_INFO ("----\r\n");
|
|
||||||
for (p = cirinput; p < cirinput_p; p++)
|
|
||||||
DEBUG_SHORT (*p);
|
|
||||||
DEBUG_INFO ("====\r\n");
|
|
||||||
|
|
||||||
cirinput_p = cirinput;
|
|
||||||
#endif
|
|
||||||
DEBUG_INFO ("**** CIR data:");
|
|
||||||
DEBUG_WORD (cir_data);
|
|
||||||
if (cir_seq > 48)
|
|
||||||
{
|
|
||||||
DEBUG_SHORT (cir_data_more);
|
|
||||||
}
|
|
||||||
DEBUG_BYTE (cir_seq);
|
|
||||||
|
|
||||||
if (cir_key_is_backspace ())
|
|
||||||
{
|
|
||||||
if (pin_input_len > 0)
|
|
||||||
pin_input_len--;
|
|
||||||
}
|
|
||||||
else if (cir_key_is_enter ())
|
|
||||||
{
|
|
||||||
pindisp (' ');
|
|
||||||
chThdExit (0);
|
|
||||||
}
|
|
||||||
else if (pin_input_len < MAX_PIN_CHARS)
|
|
||||||
pin_input_buffer[pin_input_len++] = (uint8_t)cir_data;
|
|
||||||
|
|
||||||
cir_init ();
|
|
||||||
}
|
}
|
||||||
|
else if (ch_is_enter (ch))
|
||||||
switch (s++)
|
break;
|
||||||
|
else if (pin_input_len < MAX_PIN_CHARS)
|
||||||
{
|
{
|
||||||
case 0:
|
led_blink (0);
|
||||||
pindisp ('G');
|
pin_input_buffer[pin_input_len++] = ch;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pindisp ('P');
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
pindisp ('G');
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
pindisp ('.');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pindisp (' ');
|
|
||||||
s = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chThdSleep (PINDISP_TIMEOUT_INTERVAL0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cir_ext_disable ();
|
cir_ext_disable ();
|
||||||
return 0;
|
|
||||||
|
return pin_input_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt handler of EXTI.
|
||||||
|
* @note This handler will be invoked at the beginning of signal.
|
||||||
|
* Setup timer to measure period and duty using PWM input mode.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cir_ext_interrupt (void)
|
cir_ext_interrupt (void)
|
||||||
{
|
{
|
||||||
@@ -340,29 +657,33 @@ cir_ext_interrupt (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
TIMx->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
||||||
/* Enable Timer */
|
/* Enable Timer */
|
||||||
TIM3->SR &= ~(TIM_SR_UIF
|
TIMx->SR &= ~(TIM_SR_UIF
|
||||||
| TIM_SR_CC1IF | TIM_SR_CC2IF
|
| TIM_SR_CC1IF | TIM_SR_CC2IF
|
||||||
| TIM_SR_TIF
|
| TIM_SR_TIF
|
||||||
| TIM_SR_CC1OF | TIM_SR_CC2OF);
|
| TIM_SR_CC1OF | TIM_SR_CC2OF);
|
||||||
TIM3->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
||||||
TIM3->CR1 |= TIM_CR1_CEN;
|
TIMx->CR1 |= TIM_CR1_CEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
|
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
|
||||||
* CIR_BIT_PERIOD_RC6 * 3 / 2)
|
* CIR_BIT_PERIOD_RC6 * 3 / 2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt handler of timer.
|
||||||
|
* @note Timer is PWM input mode, this handler will be invoked on each cycle
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cir_timer_interrupt (void)
|
cir_timer_interrupt (void)
|
||||||
{
|
{
|
||||||
uint16_t period, on, off;
|
uint16_t period, on, off;
|
||||||
|
|
||||||
period = TIM3->CCR1;
|
period = TIMx->CCR1;
|
||||||
on = TIM3->CCR2;
|
on = TIMx->CCR2;
|
||||||
off = period - on;
|
off = period - on;
|
||||||
|
|
||||||
if ((TIM3->SR & TIM_SR_TIF))
|
if ((TIMx->SR & TIM_SR_TIF))
|
||||||
{
|
{
|
||||||
if (cir_seq == 0)
|
if (cir_seq == 0)
|
||||||
{
|
{
|
||||||
@@ -477,23 +798,23 @@ cir_timer_interrupt (void)
|
|||||||
intr_trg++;
|
intr_trg++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV */
|
TIMx->EGR = TIM_EGR_UG; /* Generate UEV */
|
||||||
TIM3->SR &= ~TIM_SR_TIF;
|
TIMx->SR &= ~TIM_SR_TIF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* overflow occurred */
|
/* overflow occurred */
|
||||||
{
|
{
|
||||||
systime_t now = chTimeNow ();
|
systime_t now = chTimeNow ();
|
||||||
|
|
||||||
TIM3->SR &= ~TIM_SR_UIF;
|
TIMx->SR &= ~TIM_SR_UIF;
|
||||||
|
|
||||||
if (on > 0)
|
if (on > 0)
|
||||||
{
|
{
|
||||||
uint8_t ignore_input = 0;
|
uint8_t ignore_input = 0;
|
||||||
|
|
||||||
/* Disable the timer */
|
/* Disable the timer */
|
||||||
TIM3->CR1 &= ~TIM_CR1_CEN;
|
TIMx->CR1 &= ~TIM_CR1_CEN;
|
||||||
TIM3->DIER = 0;
|
TIMx->DIER = 0;
|
||||||
|
|
||||||
if (cir_seq == 12 || cir_seq == 15)
|
if (cir_seq == 12 || cir_seq == 15)
|
||||||
{
|
{
|
||||||
@@ -536,14 +857,9 @@ cir_timer_interrupt (void)
|
|||||||
cir_input_last = now;
|
cir_input_last = now;
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
/* Remove ADDRESS bits and filter COMMAND bits */
|
|
||||||
else if (cir_proto == CIR_PROTO_SONY)
|
else if (cir_proto == CIR_PROTO_SONY)
|
||||||
{
|
{
|
||||||
if (cir_seq == 1 + 12)
|
if (cir_seq != 1 + 12 && cir_seq != 1 + 15)
|
||||||
cir_data = cir_data & 0x007f;
|
|
||||||
else if (cir_seq == 1 + 15)
|
|
||||||
cir_data = cir_data & 0x00ff;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_OTHER)
|
else if (cir_proto == CIR_PROTO_OTHER)
|
||||||
@@ -551,10 +867,7 @@ cir_timer_interrupt (void)
|
|||||||
if (cir_seq == 1 + 32)
|
if (cir_seq == 1 + 32)
|
||||||
{
|
{
|
||||||
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
|
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
|
||||||
{
|
cir_proto = CIR_PROTO_NEC;
|
||||||
cir_proto = CIR_PROTO_NEC;
|
|
||||||
cir_data = (cir_data >> 16) & 0x00ff;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
@@ -569,10 +882,7 @@ cir_timer_interrupt (void)
|
|||||||
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
|
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
|
||||||
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
|
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
|
||||||
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
|
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
|
||||||
{
|
cir_proto = CIR_PROTO_SHARP;
|
||||||
cir_proto = CIR_PROTO_SHARP;
|
|
||||||
cir_data = (cir_data >> 16) & 0x0fff;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
@@ -581,16 +891,12 @@ cir_timer_interrupt (void)
|
|||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_RC6)
|
else if (cir_proto == CIR_PROTO_RC6)
|
||||||
{
|
{
|
||||||
if (cir_seq == 16 || cir_seq == 32)
|
if (cir_seq != 16 && cir_seq != 32)
|
||||||
cir_data &= 0x00ff;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_RC5)
|
else if (cir_proto == CIR_PROTO_RC5)
|
||||||
{
|
{
|
||||||
if (cir_seq == 14)
|
if (cir_seq != 14)
|
||||||
cir_data &= 0x003f;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -603,7 +909,8 @@ cir_timer_interrupt (void)
|
|||||||
{
|
{
|
||||||
cir_input_last = now;
|
cir_input_last = now;
|
||||||
/* Notify thread */
|
/* Notify thread */
|
||||||
chEvtSignal (pin_thread, (eventmask_t)1);
|
if (pin_thread)
|
||||||
|
chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
#if defined(DEBUG_CIR)
|
||||||
|
|||||||
@@ -117,21 +117,19 @@ blink_dp (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Thread *pin_thread;
|
static Thread *pin_thread;
|
||||||
#define EV_SW_PUSH (eventmask_t)1
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dial_sw_interrupt (void)
|
dial_sw_interrupt (void)
|
||||||
{
|
{
|
||||||
dial_sw_disable ();
|
dial_sw_disable ();
|
||||||
chEvtSignalI (pin_thread, EV_SW_PUSH);
|
chEvtSignalI (pin_thread, EV_PINPAD_INPUT_DONE);
|
||||||
palClearPad (IOPORT1, GPIOA_LED2);
|
palClearPad (IOPORT1, GPIOA_LED2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
msg_t
|
int
|
||||||
pin_main (void *arg)
|
pinpad_getline (int msg_code, systime_t timeout)
|
||||||
{
|
{
|
||||||
int msg_code = (int)arg;
|
|
||||||
uint16_t count, count_prev;
|
uint16_t count, count_prev;
|
||||||
uint8_t input_mode;
|
uint8_t input_mode;
|
||||||
uint8_t sw_push_count;
|
uint8_t sw_push_count;
|
||||||
@@ -150,7 +148,7 @@ pin_main (void *arg)
|
|||||||
sw_push_count = 0;
|
sw_push_count = 0;
|
||||||
sw_event = 0;
|
sw_event = 0;
|
||||||
|
|
||||||
while (!chThdShouldTerminate ())
|
while (1)
|
||||||
{
|
{
|
||||||
eventmask_t m;
|
eventmask_t m;
|
||||||
|
|
||||||
@@ -158,7 +156,7 @@ pin_main (void *arg)
|
|||||||
dial_sw_enable ();
|
dial_sw_enable ();
|
||||||
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_DISP_BLINK_INTERVAL0);
|
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)
|
if (palReadPad (IOPORT2, GPIOB_BUTTON) == 0)
|
||||||
sw_push_count++;
|
sw_push_count++;
|
||||||
@@ -218,5 +216,5 @@ pin_main (void *arg)
|
|||||||
led_disp (OFF);
|
led_disp (OFF);
|
||||||
TIM4->CR1 &= ~TIM_CR1_CEN;
|
TIM4->CR1 &= ~TIM_CR1_CEN;
|
||||||
dial_sw_disable ();
|
dial_sw_disable ();
|
||||||
return 0;
|
return pin_input_len;
|
||||||
}
|
}
|
||||||
|
|||||||
372
src/pin-dnd.c
Normal file
372
src/pin-dnd.c
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
/*
|
||||||
|
* pin-dnd.c -- PIN input support (Drag and Drop with File Manager)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
*
|
||||||
|
* Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
(void)timeout;
|
||||||
|
|
||||||
|
DEBUG_INFO (">>>\r\n");
|
||||||
|
|
||||||
|
pin_input_len = 0;
|
||||||
|
|
||||||
|
msc_media_insert_change (1);
|
||||||
|
|
||||||
|
memset (folders, 0, sizeof folders);
|
||||||
|
memcpy (folders, &folder_ini, sizeof folder_ini);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
chSysLock ();
|
||||||
|
pin_thread = chThdSelf ();
|
||||||
|
chSchGoSleepS (THD_STATE_SUSPENDED);
|
||||||
|
msg = chThdSelf ()->p_u.rdymsg;
|
||||||
|
chSysUnlock ();
|
||||||
|
|
||||||
|
led_blink (0);
|
||||||
|
if (msg != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msc_media_insert_change (0);
|
||||||
|
|
||||||
|
if (msg == 1)
|
||||||
|
return pin_input_len;
|
||||||
|
else
|
||||||
|
return -1; /* cancel */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pinpad_input (void)
|
||||||
|
{
|
||||||
|
chSysLock ();
|
||||||
|
pin_thread->p_u.rdymsg = 0;
|
||||||
|
chSchReadyI (pin_thread);
|
||||||
|
chSysUnlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pinpad_finish_entry (int cancel)
|
||||||
|
{
|
||||||
|
chSysLock ();
|
||||||
|
if (cancel)
|
||||||
|
pin_thread->p_u.rdymsg = 2;
|
||||||
|
else
|
||||||
|
pin_thread->p_u.rdymsg = 1;
|
||||||
|
chSchReadyI (pin_thread);
|
||||||
|
chSysUnlock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TOTAL_SECTOR 68
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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[] = {
|
||||||
|
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) */
|
||||||
|
TOTAL_SECTOR, 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: DNDpinentry */
|
||||||
|
'D', 'n', 'D', 'p', 'i', 'n', 'e', 'n', 't', 'r', 'y',
|
||||||
|
|
||||||
|
0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, /* FAT12 */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
/* "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,
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t the_sector[512];
|
||||||
|
|
||||||
|
#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 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
*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:
|
||||||
|
*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:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
*sector_p = the_sector;
|
||||||
|
build_directory_sector (the_sector, LBA_TO_FOLDER_INDEX (lba));
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
*sector_p = the_sector;
|
||||||
|
memset (the_sector, 0, 512);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void parse_directory_sector (const uint8_t *p, uint8_t index)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t child;
|
||||||
|
int input = 0;
|
||||||
|
int num_children = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
; /* it can be 255 : root_dir */
|
||||||
|
else
|
||||||
|
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 >= 'A' && *p <= 'G')
|
||||||
|
{
|
||||||
|
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 (0);
|
||||||
|
else if (input)
|
||||||
|
pinpad_input ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
(void)size;
|
||||||
|
|
||||||
|
if (!media_available)
|
||||||
|
return SCSI_ERROR_NOT_READY;
|
||||||
|
|
||||||
|
if (lba >= TOTAL_SECTOR)
|
||||||
|
return SCSI_ERROR_ILLEAGAL_REQUEST;
|
||||||
|
|
||||||
|
if (lba == 1)
|
||||||
|
return 0; /* updating FAT, just ignore */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
msc_scsi_stop (uint8_t code)
|
||||||
|
{
|
||||||
|
(void)code;
|
||||||
|
pinpad_finish_entry (1);
|
||||||
|
}
|
||||||
57
src/random.c
57
src/random.c
@@ -24,6 +24,23 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
|
#include "neug.h"
|
||||||
|
|
||||||
|
#define RANDOM_BYTES_LENGTH 16
|
||||||
|
static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
|
||||||
|
|
||||||
|
void
|
||||||
|
random_init (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
|
||||||
|
|
||||||
|
for (i = 0; i < NEUG_PRE_LOOP; i++)
|
||||||
|
(void)neug_get (NEUG_KICK_FILLING);
|
||||||
|
|
||||||
|
neug_prng_reseed ();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return pointer to random 16-byte
|
* Return pointer to random 16-byte
|
||||||
@@ -31,25 +48,8 @@
|
|||||||
const uint8_t *
|
const uint8_t *
|
||||||
random_bytes_get (void)
|
random_bytes_get (void)
|
||||||
{
|
{
|
||||||
uint32_t addr, addr0;
|
neug_wait_full ();
|
||||||
|
return (const uint8_t *)random_word;
|
||||||
addr = (uint32_t)&random_bits_start + ((hardclock () << 4) & 0x3f0);
|
|
||||||
addr0 = addr;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (*(uint32_t *)addr != 0 && *(uint32_t *)addr != 0xffffffff)
|
|
||||||
break;
|
|
||||||
|
|
||||||
addr += 16;
|
|
||||||
if (addr >= ((uint32_t)&random_bits_start) + 1024)
|
|
||||||
addr = ((uint32_t)&random_bits_start);
|
|
||||||
|
|
||||||
if (addr == addr0)
|
|
||||||
fatal (FATAL_RANDOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (const uint8_t *)addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -58,11 +58,8 @@ random_bytes_get (void)
|
|||||||
void
|
void
|
||||||
random_bytes_free (const uint8_t *p)
|
random_bytes_free (const uint8_t *p)
|
||||||
{
|
{
|
||||||
int i;
|
(void)p;
|
||||||
uint32_t addr = (uint32_t)p;
|
neug_flush ();
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
flash_clear_halfword (addr+i*2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -71,15 +68,5 @@ random_bytes_free (const uint8_t *p)
|
|||||||
uint32_t
|
uint32_t
|
||||||
get_salt (void)
|
get_salt (void)
|
||||||
{
|
{
|
||||||
const uint8_t *u = unique_device_id (); /* 12-byte unique id */
|
return neug_get (NEUG_KICK_FILLING);
|
||||||
uint32_t r = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
r <<= 8;
|
|
||||||
r |= u[hardclock () % 12];
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
#include "usb_lib.h"
|
#include "usb_lib.h"
|
||||||
#include "usb_desc.h"
|
|
||||||
#include "usb_mem.h"
|
#include "usb_mem.h"
|
||||||
#include "hw_config.h"
|
#include "hw_config.h"
|
||||||
#include "usb_istr.h"
|
#include "usb_istr.h"
|
||||||
@@ -170,12 +169,31 @@ void
|
|||||||
EP2_OUT_Callback (void)
|
EP2_OUT_Callback (void)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
struct icc_header *icc_header;
|
||||||
|
int data_len_so_far;
|
||||||
|
int data_len;
|
||||||
|
|
||||||
len = USB_SIL_Read (EP2_OUT, icc_next_p);
|
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);
|
SetEPRxValid (ENDP2);
|
||||||
if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE)
|
if ((icc_next_p - icc_buffer) >= USB_BUF_SIZE)
|
||||||
/* No room to receive any more */
|
/* No room to receive any more */
|
||||||
@@ -187,27 +205,18 @@ EP2_OUT_Callback (void)
|
|||||||
* (and discard the whole block)
|
* (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 */
|
else /* Finished */
|
||||||
{
|
{
|
||||||
struct icc_header *icc_header;
|
icc_data_size = data_len_so_far;
|
||||||
int data_len;
|
icc_seq = icc_header->seq; /* NOTE: We're little endian */
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (icc_data_size != data_len)
|
if (icc_data_size != data_len)
|
||||||
{
|
{
|
||||||
@@ -374,7 +383,7 @@ icc_power_off (void)
|
|||||||
if (gpg_thread)
|
if (gpg_thread)
|
||||||
{
|
{
|
||||||
chThdTerminate (gpg_thread);
|
chThdTerminate (gpg_thread);
|
||||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
chEvtSignal (gpg_thread, EV_NOP);
|
||||||
chThdWait (gpg_thread);
|
chThdWait (gpg_thread);
|
||||||
gpg_thread = NULL;
|
gpg_thread = NULL;
|
||||||
}
|
}
|
||||||
@@ -497,7 +506,7 @@ icc_handle_data (void)
|
|||||||
{
|
{
|
||||||
if (icc_header->param == 0)
|
if (icc_header->param == 0)
|
||||||
{ /* Give this message to GPG thread */
|
{ /* Give this message to GPG thread */
|
||||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
|
||||||
next_state = ICC_STATE_EXECUTE;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
else if (icc_header->param == 1)
|
else if (icc_header->param == 1)
|
||||||
@@ -524,7 +533,15 @@ icc_handle_data (void)
|
|||||||
cmd_APDU[2] = icc_buffer[27];
|
cmd_APDU[2] = icc_buffer[27];
|
||||||
cmd_APDU[3] = icc_buffer[28];
|
cmd_APDU[3] = icc_buffer[28];
|
||||||
icc_data_size = 4;
|
icc_data_size = 4;
|
||||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
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;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
else if (icc_buffer[10] == 0x01) /* PIN Modification */
|
else if (icc_buffer[10] == 0x01) /* PIN Modification */
|
||||||
@@ -540,7 +557,18 @@ icc_handle_data (void)
|
|||||||
cmd_APDU[2] = icc_buffer[29 + num_msgs];
|
cmd_APDU[2] = icc_buffer[29 + num_msgs];
|
||||||
cmd_APDU[3] = icc_buffer[30 + num_msgs];
|
cmd_APDU[3] = icc_buffer[30 + num_msgs];
|
||||||
icc_data_size = 4;
|
icc_data_size = 4;
|
||||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
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;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -572,7 +600,7 @@ icc_handle_data (void)
|
|||||||
icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE;
|
icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE;
|
||||||
icc_chain_p = NULL;
|
icc_chain_p = NULL;
|
||||||
next_state = ICC_STATE_EXECUTE;
|
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. */
|
else /* icc_header->param == 3 is not supported. */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,10 +8,14 @@
|
|||||||
#ifndef __USB_CONF_H
|
#ifndef __USB_CONF_H
|
||||||
#define __USB_CONF_H
|
#define __USB_CONF_H
|
||||||
|
|
||||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
#ifdef PINPAD_DND_SUPPORT
|
||||||
#define EP_NUM (6)
|
# define EP_NUM (8)
|
||||||
#else
|
#else
|
||||||
#define EP_NUM (3)
|
# ifdef ENABLE_VIRTUAL_COM_PORT
|
||||||
|
# define EP_NUM (6)
|
||||||
|
# else
|
||||||
|
# define EP_NUM (3)
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BTABLE_ADDRESS (0x00)
|
#define BTABLE_ADDRESS (0x00)
|
||||||
@@ -28,9 +32,14 @@
|
|||||||
/* EP3 */
|
/* EP3 */
|
||||||
#define ENDP3_TXADDR (0x140)
|
#define ENDP3_TXADDR (0x140)
|
||||||
/* EP4 */
|
/* EP4 */
|
||||||
#define ENDP4_TXADDR (0x180)
|
#define ENDP4_TXADDR (0x150)
|
||||||
/* EP5 */
|
/* 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 )
|
#define IMR_MSK (CNTR_CTRM | CNTR_SOFM | CNTR_RESETM )
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
static const uint8_t gnukDeviceDescriptor[] = {
|
static const uint8_t gnukDeviceDescriptor[] = {
|
||||||
18, /* bLength */
|
18, /* bLength */
|
||||||
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
0x00, 0x02, /* bcdUSB = 2.00 */
|
0x10, 0x01, /* bcdUSB = 1.1 */
|
||||||
0x00, /* bDeviceClass: 0 means deferred to interface */
|
0x00, /* bDeviceClass: 0 means deferred to interface */
|
||||||
0x00, /* bDeviceSubClass */
|
0x00, /* bDeviceSubClass */
|
||||||
0x00, /* bDeviceProtocol */
|
0x00, /* bDeviceProtocol */
|
||||||
@@ -29,14 +29,29 @@ static const uint8_t gnukDeviceDescriptor[] = {
|
|||||||
0x01 /* bNumConfigurations */
|
0x01 /* bNumConfigurations */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ICC_TOTAL_LENGTH (9+9+54+7+7)
|
||||||
|
#define ICC_NUM_INTERFACES 1
|
||||||
|
|
||||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||||
#define W_TOTAL_LENGTH (9+9+54+7+7+9+5+5+4+5+7+9+7+7)
|
#define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
|
||||||
#define NUM_INTERFACES 3 /* two for CDC, one for GPG */
|
#define VCOM_NUM_INTERFACES 2
|
||||||
#else
|
#else
|
||||||
#define W_TOTAL_LENGTH (9+9+54+7+7)
|
#define VCOM_TOTAL_LENGTH 0
|
||||||
#define NUM_INTERFACES 1 /* GPG only */
|
#define VCOM_NUM_INTERFACES 0
|
||||||
#endif
|
#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 */
|
/* Configuation Descriptor */
|
||||||
static const uint8_t gnukConfigDescriptor[] = {
|
static const uint8_t gnukConfigDescriptor[] = {
|
||||||
9, /* bLength: Configuation Descriptor size */
|
9, /* bLength: Configuation Descriptor size */
|
||||||
@@ -105,7 +120,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
|||||||
0xff, /* bClassEnvelope: */
|
0xff, /* bClassEnvelope: */
|
||||||
0, 0, /* wLCDLayout: FIXED VALUE */
|
0, 0, /* wLCDLayout: FIXED VALUE */
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
#if defined(PINPAD_CIR_SUPPORT)
|
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
|
||||||
1, /* bPinSupport: with PIN pad (verify) */
|
1, /* bPinSupport: with PIN pad (verify) */
|
||||||
#elif defined(PINPAD_DIAL_SUPPORT)
|
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||||
3, /* bPinSupport: with PIN pad (verify, modify) */
|
3, /* bPinSupport: with PIN pad (verify, modify) */
|
||||||
@@ -193,7 +208,40 @@ static const uint8_t gnukConfigDescriptor[] = {
|
|||||||
0x83, /* bEndpointAddress: (IN3) */
|
0x83, /* bEndpointAddress: (IN3) */
|
||||||
0x02, /* bmAttributes: Bulk */
|
0x02, /* bmAttributes: Bulk */
|
||||||
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -227,7 +275,7 @@ static const uint8_t gnukStringProduct[] = {
|
|||||||
const uint8_t gnukStringSerial[] = {
|
const uint8_t gnukStringSerial[] = {
|
||||||
13*2+2, /* bLength */
|
13*2+2, /* bLength */
|
||||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
'0', 0, '.', 0, '1', 0, '2', 0, /* Version number of Gnuk */
|
'0', 0, '.', 0, '1', 0, '6', 0, /* Version number of Gnuk */
|
||||||
'-', 0,
|
'-', 0,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ EP3_IN_Callback(void)
|
|||||||
void
|
void
|
||||||
EP5_OUT_Callback(void)
|
EP5_OUT_Callback(void)
|
||||||
{
|
{
|
||||||
SetEPRxValid (ENDP3);
|
SetEPRxValid (ENDP5);
|
||||||
}
|
}
|
||||||
|
|||||||
567
src/usb_msc.c
Normal file
567
src/usb_msc.c
Normal file
@@ -0,0 +1,567 @@
|
|||||||
|
/*
|
||||||
|
* usb_msc.c -- USB Mass Storage Class protocol handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
*
|
||||||
|
* Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
if (n < ENDP_MAX_SIZE)
|
||||||
|
SetEPRxCount (ENDP7, n);
|
||||||
|
else
|
||||||
|
SetEPRxCount (ENDP7, ENDP_MAX_SIZE);
|
||||||
|
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_RESET : RDY_OK;
|
||||||
|
chSchReadyI (tp);
|
||||||
|
chSysUnlockFromIsr ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
if (available)
|
||||||
|
{
|
||||||
|
set_scsi_sense_data (0x06, 0x28); /* UNIT_ATTENTION */
|
||||||
|
keep_contingent_allegiance = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_scsi_sense_data (0x02, 0x3a); /* NOT_READY */
|
||||||
|
keep_contingent_allegiance = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSW.dCSWSignature = MSC_CSW_SIGNATURE;
|
||||||
|
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_command (void)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
uint32_t nblocks, secsize;
|
||||||
|
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;
|
||||||
|
if (msg != RDY_TIMEOUT)
|
||||||
|
{
|
||||||
|
chSysLock ();
|
||||||
|
usb_stall_receive ();
|
||||||
|
chSysUnlock ();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ep7_out.rxcnt;
|
||||||
|
|
||||||
|
if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
|
||||||
|
{
|
||||||
|
msc_state = MSC_ERROR;
|
||||||
|
chSysLock ();
|
||||||
|
usb_stall_receive ();
|
||||||
|
chSysUnlock ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
/* After the error is reported, clear it, if it's . */
|
||||||
|
if (!keep_contingent_allegiance)
|
||||||
|
{
|
||||||
|
contingent_allegiance = 0;
|
||||||
|
set_scsi_sense_data (0x00, 0x00);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
|
||||||
|
CSW.dCSWDataResidue = 0;
|
||||||
|
msc_send_result (NULL, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
success:
|
||||||
|
case SCSI_SYNCHRONIZE_CACHE:
|
||||||
|
case SCSI_VERIFY10:
|
||||||
|
case SCSI_ALLOW_MEDIUM_REMOVAL:
|
||||||
|
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
|
||||||
|
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength;
|
||||||
|
msc_send_result (NULL, 0);
|
||||||
|
return;
|
||||||
|
case SCSI_MODE_SENSE6:
|
||||||
|
buf[0] = 0x03;
|
||||||
|
buf[1] = buf[2] = buf[3] = 0;
|
||||||
|
msc_send_result (buf, 4);
|
||||||
|
return;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msc_state = MSC_ERROR;
|
||||||
|
chSysLock ();
|
||||||
|
usb_stall_transmit ();
|
||||||
|
usb_stall_receive ();
|
||||||
|
chSysUnlock ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ((r = msc_scsi_read (lba, &p)) == 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ((r = msc_scsi_write (lba, buf, 512)) == 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msc_send_result (NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static msg_t
|
||||||
|
msc_main (void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
/* Initially, it starts with no media */
|
||||||
|
msc_media_insert_change (0);
|
||||||
|
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);
|
||||||
|
}
|
||||||
52
src/usb_msc.h
Normal file
52
src/usb_msc.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#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));
|
||||||
|
|
||||||
|
#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;
|
||||||
137
src/usb_prop.c
137
src/usb_prop.c
@@ -36,6 +36,10 @@
|
|||||||
#include "usb-cdc-vport.c"
|
#include "usb-cdc-vport.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PINPAD_DND_SUPPORT
|
||||||
|
#include "usb_msc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gnuk_device_init (void)
|
gnuk_device_init (void)
|
||||||
@@ -108,6 +112,20 @@ gnuk_device_reset (void)
|
|||||||
SetEPTxStatus (ENDP5, EP_TX_DIS);
|
SetEPTxStatus (ENDP5, EP_TX_DIS);
|
||||||
#endif
|
#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 */
|
/* Set this device to response on default address */
|
||||||
SetDeviceAddress (0);
|
SetDeviceAddress (0);
|
||||||
|
|
||||||
@@ -120,8 +138,14 @@ gnuk_device_SetConfiguration (void)
|
|||||||
DEVICE_INFO *pInfo = &Device_Info;
|
DEVICE_INFO *pInfo = &Device_Info;
|
||||||
|
|
||||||
if (pInfo->Current_Configuration != 0)
|
if (pInfo->Current_Configuration != 0)
|
||||||
/* Device configured */
|
{ /* Device configured */
|
||||||
bDeviceState = CONFIGURED;
|
extern void *main_thread;
|
||||||
|
extern void chEvtSignalI (void *, unsigned long);
|
||||||
|
#define LED_STATUS_MODE (8)
|
||||||
|
|
||||||
|
bDeviceState = CONFIGURED;
|
||||||
|
chEvtSignalI (main_thread, LED_STATUS_MODE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -147,6 +171,21 @@ gnuk_device_SetInterface (void)
|
|||||||
ClearDTOG_TX (ENDP3);
|
ClearDTOG_TX (ENDP3);
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
static void
|
||||||
@@ -194,10 +233,18 @@ gnuk_device_GetStringDescriptor (uint16_t Length)
|
|||||||
(PONE_DESCRIPTOR)&String_Descriptor[wValue0]);
|
(PONE_DESCRIPTOR)&String_Descriptor[wValue0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
#ifdef PINPAD_DND_SUPPORT
|
||||||
#define NUM_INTERFACES 3 /* two for CDC, one for CCID */
|
# 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
|
#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
|
#endif
|
||||||
|
|
||||||
static RESULT
|
static RESULT
|
||||||
@@ -241,11 +288,26 @@ gnuk_data_rates (uint16_t len)
|
|||||||
return (uint8_t *)data_rate_table;
|
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
|
static RESULT
|
||||||
gnuk_setup_with_data (uint8_t RequestNo)
|
gnuk_setup_with_data (uint8_t RequestNo)
|
||||||
{
|
{
|
||||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */
|
||||||
if (pInformation->USBwIndex0 == 0) /* Interface */
|
if (pInformation->USBwIndex0 == 0)
|
||||||
{
|
{
|
||||||
if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
if (RequestNo == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
||||||
{
|
{
|
||||||
@@ -264,23 +326,41 @@ gnuk_setup_with_data (uint8_t RequestNo)
|
|||||||
else
|
else
|
||||||
return USB_UNSUPPORT;
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
else
|
#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
|
||||||
|
else if (pInformation->USBwIndex0 == 1)
|
||||||
|
# endif
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_VIRTUAL_COM_PORT)
|
if (RequestNo == MSC_GET_MAX_LUN_COMMAND)
|
||||||
return Virtual_Com_Port_Data_Setup (RequestNo);
|
{
|
||||||
#else
|
pInformation->Ctrl_Info.CopyData = msc_lun_info;
|
||||||
return USB_UNSUPPORT;
|
pInformation->Ctrl_Info.Usb_wOffset = 0;
|
||||||
#endif
|
msc_lun_info (0);
|
||||||
|
return USB_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
|
#elif defined(ENABLE_VIRTUAL_COM_PORT)
|
||||||
|
else if (pInformation->USBwIndex0 == 1)
|
||||||
|
return Virtual_Com_Port_Data_Setup (RequestNo);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return USB_UNSUPPORT;
|
||||||
else
|
else
|
||||||
return USB_UNSUPPORT;
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static RESULT
|
static RESULT
|
||||||
gnuk_setup_with_nodata (uint8_t RequestNo)
|
gnuk_setup_with_nodata (uint8_t RequestNo)
|
||||||
{
|
{
|
||||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) /* Interface */
|
||||||
if (pInformation->USBwIndex0 == 0) /* Interface */
|
if (pInformation->USBwIndex0 == 0)
|
||||||
{
|
{
|
||||||
if (RequestNo == USB_CCID_REQ_ABORT)
|
if (RequestNo == USB_CCID_REQ_ABORT)
|
||||||
/* wValue: bSeq, bSlot */
|
/* wValue: bSeq, bSlot */
|
||||||
@@ -289,14 +369,29 @@ gnuk_setup_with_nodata (uint8_t RequestNo)
|
|||||||
else
|
else
|
||||||
return USB_UNSUPPORT;
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
else
|
#if defined(PINPAD_DND_SUPPORT)
|
||||||
|
# if defined(ENABLE_VIRTUAL_COM_PORT)
|
||||||
|
else if (pInformation->USBwIndex0 == 1)
|
||||||
|
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)
|
if (RequestNo == MSC_MASS_STORAGE_RESET_COMMAND)
|
||||||
return Virtual_Com_Port_NoData_Setup (RequestNo);
|
{
|
||||||
#else
|
/* Should call resetting MSC thread, something like msc_reset() */
|
||||||
return USB_UNSUPPORT;
|
return USB_SUCCESS;
|
||||||
#endif
|
}
|
||||||
|
else
|
||||||
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
|
#elif defined(ENABLE_VIRTUAL_COM_PORT)
|
||||||
|
else if (pInformation->USBwIndex0 == 1)
|
||||||
|
return Virtual_Com_Port_NoData_Setup (RequestNo);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return USB_UNSUPPORT;
|
||||||
else
|
else
|
||||||
return USB_UNSUPPORT;
|
return USB_UNSUPPORT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor.
|
dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor.
|
||||||
"SE" in DfuSe stands for "STmicroelectronics Extention".
|
"SE" in DfuSe stands for "STmicroelectronics Extention".
|
||||||
|
|
||||||
Copyright (C) 2010 Free Software Initiative of Japan
|
Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -208,10 +208,23 @@ class DFU_STM32:
|
|||||||
# First, erase pages
|
# First, erase pages
|
||||||
sys.stdout.write("Erasing: ")
|
sys.stdout.write("Erasing: ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
last_addr = 0
|
||||||
for start_addr in sorted(ih.memory.keys()):
|
for start_addr in sorted(ih.memory.keys()):
|
||||||
data = ih.memory[start_addr]
|
data = ih.memory[start_addr]
|
||||||
end_addr = start_addr + len(data)
|
end_addr = start_addr + len(data)
|
||||||
addr = start_addr & 0xfffffc00
|
addr = start_addr & 0xfffffc00
|
||||||
|
if not last_addr == 0:
|
||||||
|
i = 0
|
||||||
|
if last_addr > addr:
|
||||||
|
addr = last_addr
|
||||||
|
else:
|
||||||
|
while last_addr < addr:
|
||||||
|
self.dfuse_erase(last_addr)
|
||||||
|
if i & 0x03 == 0x03:
|
||||||
|
sys.stdout.write(".")
|
||||||
|
sys.stdout.flush()
|
||||||
|
last_addr += 1024
|
||||||
|
i += 1
|
||||||
i = 0
|
i = 0
|
||||||
while addr < end_addr:
|
while addr < end_addr:
|
||||||
self.dfuse_erase(addr)
|
self.dfuse_erase(addr)
|
||||||
@@ -220,20 +233,32 @@ class DFU_STM32:
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
addr += 1024
|
addr += 1024
|
||||||
i += 1
|
i += 1
|
||||||
|
last_addr = addr
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
# Then, write pages
|
# Then, write pages
|
||||||
sys.stdout.write("Writing: ")
|
sys.stdout.write("Writing: ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
last_addr = 0
|
||||||
for start_addr in sorted(ih.memory.keys()):
|
for start_addr in sorted(ih.memory.keys()):
|
||||||
data = ih.memory[start_addr]
|
data = ih.memory[start_addr]
|
||||||
end_addr = start_addr + len(data)
|
end_addr = start_addr + len(data)
|
||||||
addr = start_addr & 0xfffffc00
|
addr = start_addr & 0xfffffc00
|
||||||
# XXX: data should be 1-KiB aligned
|
if not last_addr == 0:
|
||||||
if addr != start_addr:
|
i = 0
|
||||||
raise ValueError, "padding is not supported yet"
|
while last_addr < addr:
|
||||||
self.dfuse_set_address_pointer(addr)
|
if i & 0x03 == 0x03:
|
||||||
|
sys.stdout.write(".")
|
||||||
|
sys.stdout.flush()
|
||||||
|
last_addr += 1024
|
||||||
|
i += 1
|
||||||
i = 0
|
i = 0
|
||||||
|
if addr != start_addr:
|
||||||
|
self.dfuse_set_address_pointer(start_addr)
|
||||||
|
self.dfuse_write_memory(data[0:(addr + 1024 - start_addr)])
|
||||||
|
data = data[(addr + 1024 - start_addr):]
|
||||||
|
addr += 1024
|
||||||
|
self.dfuse_set_address_pointer(addr)
|
||||||
while addr < end_addr:
|
while addr < end_addr:
|
||||||
self.dfuse_write_memory(data[i*1024:(i+1)*1024])
|
self.dfuse_write_memory(data[i*1024:(i+1)*1024])
|
||||||
if i & 0x03 == 0x03:
|
if i & 0x03 == 0x03:
|
||||||
@@ -241,6 +266,7 @@ class DFU_STM32:
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
addr += 1024
|
addr += 1024
|
||||||
i += 1
|
i += 1
|
||||||
|
last_addr = addr
|
||||||
if self.__protocol == DFU_STM32PROTOCOL_0:
|
if self.__protocol == DFU_STM32PROTOCOL_0:
|
||||||
# 0-length write at the end
|
# 0-length write at the end
|
||||||
self.ll_download_block(self.__blocknum, None)
|
self.ll_download_block(self.__blocknum, None)
|
||||||
@@ -268,13 +294,33 @@ class DFU_STM32:
|
|||||||
# Read pages
|
# Read pages
|
||||||
sys.stdout.write("Reading: ")
|
sys.stdout.write("Reading: ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
last_addr = 0
|
||||||
for start_addr in sorted(ih.memory.keys()):
|
for start_addr in sorted(ih.memory.keys()):
|
||||||
data = ih.memory[start_addr]
|
data = ih.memory[start_addr]
|
||||||
end_addr = start_addr + len(data)
|
end_addr = start_addr + len(data)
|
||||||
addr = start_addr & 0xfffffc00
|
addr = start_addr & 0xfffffc00
|
||||||
# XXX: data should be 1-KiB aligned
|
if not last_addr == 0:
|
||||||
|
i = 0
|
||||||
|
while last_addr < addr:
|
||||||
|
if i & 0x03 == 0x03:
|
||||||
|
sys.stdout.write(".")
|
||||||
|
sys.stdout.flush()
|
||||||
|
last_addr += 1024
|
||||||
|
i += 1
|
||||||
if addr != start_addr:
|
if addr != start_addr:
|
||||||
raise ValueError, "padding is not supported yet"
|
self.dfuse_set_address_pointer(addr)
|
||||||
|
self.ll_clear_status()
|
||||||
|
self.ll_clear_status()
|
||||||
|
block = self.dfuse_read_memory()
|
||||||
|
j = 0
|
||||||
|
for c in data[0:(addr + 1024 - start_addr)]:
|
||||||
|
if (ord(c)&0xff) != block[j + start_addr - addr]:
|
||||||
|
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
|
||||||
|
j += 1
|
||||||
|
data = data[(addr + 1024 - start_addr):]
|
||||||
|
addr += 1024
|
||||||
|
self.ll_clear_status()
|
||||||
|
self.ll_clear_status()
|
||||||
self.dfuse_set_address_pointer(addr)
|
self.dfuse_set_address_pointer(addr)
|
||||||
self.ll_clear_status()
|
self.ll_clear_status()
|
||||||
self.ll_clear_status()
|
self.ll_clear_status()
|
||||||
@@ -291,6 +337,7 @@ class DFU_STM32:
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
addr += 1024
|
addr += 1024
|
||||||
i += 1
|
i += 1
|
||||||
|
last_addr = addr
|
||||||
self.ll_clear_status()
|
self.ll_clear_status()
|
||||||
self.ll_clear_status()
|
self.ll_clear_status()
|
||||||
self.ll_clear_status()
|
self.ll_clear_status()
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class GnukToken(object):
|
|||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def cmd_select_openpgp(self):
|
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)
|
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||||
raise ValueError, "cmd_select_openpgp"
|
raise ValueError, "cmd_select_openpgp"
|
||||||
@@ -107,6 +107,13 @@ def main(fileid, is_update, data, passwd):
|
|||||||
gnuk.cmd_select_openpgp()
|
gnuk.cmd_select_openpgp()
|
||||||
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
|
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
|
||||||
compare(data[:-2], data_in_device)
|
compare(data[:-2], data_in_device)
|
||||||
|
elif fileid == 2:
|
||||||
|
gnuk.cmd_select_openpgp()
|
||||||
|
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
|
||||||
|
for d in data_in_device:
|
||||||
|
print "%02x" % d,
|
||||||
|
print
|
||||||
|
compare(data, data_in_device[8:])
|
||||||
|
|
||||||
gnuk.connection.disconnect()
|
gnuk.connection.disconnect()
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class gnuk_token:
|
|||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def cmd_select_openpgp(self):
|
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)
|
sw = self.icc_send_cmd(cmd_data)
|
||||||
if len(sw) != 2:
|
if len(sw) != 2:
|
||||||
raise ValueError, "cmd_select_openpgp"
|
raise ValueError, "cmd_select_openpgp"
|
||||||
|
|||||||
256
tool/hub_ctrl.py
Executable file
256
tool/hub_ctrl.py
Executable file
@@ -0,0 +1,256 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
"""
|
||||||
|
hub_ctrl.py - a tool to control port power/led of USB hub
|
||||||
|
|
||||||
|
Copyright (C) 2006, 2011 Free Software Initiative of Japan
|
||||||
|
|
||||||
|
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
|
||||||
|
Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import usb
|
||||||
|
|
||||||
|
USB_RT_HUB = (usb.TYPE_CLASS | usb.RECIP_DEVICE)
|
||||||
|
USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
|
||||||
|
USB_PORT_FEAT_RESET = 4
|
||||||
|
USB_PORT_FEAT_POWER = 8
|
||||||
|
USB_PORT_FEAT_INDICATOR = 22
|
||||||
|
USB_DIR_IN = 0x80 # device to host
|
||||||
|
|
||||||
|
COMMAND_SET_NONE = 0
|
||||||
|
COMMAND_SET_LED = 1
|
||||||
|
COMMAND_SET_POWER = 2
|
||||||
|
|
||||||
|
HUB_LED_GREEN = 2
|
||||||
|
|
||||||
|
def find_hubs(listing, verbose, busnum=None, devnum=None, hub=None):
|
||||||
|
number_of_hubs_with_feature = 0
|
||||||
|
hubs = []
|
||||||
|
busses = usb.busses()
|
||||||
|
if not busses:
|
||||||
|
raise ValueError, "can't access USB"
|
||||||
|
|
||||||
|
for bus in busses:
|
||||||
|
devices = bus.devices
|
||||||
|
for dev in devices:
|
||||||
|
if dev.deviceClass != usb.CLASS_HUB:
|
||||||
|
continue
|
||||||
|
|
||||||
|
printout_enable = 0
|
||||||
|
if (listing
|
||||||
|
or (verbose
|
||||||
|
and ((bus.dirname == busnum and dev.devnum == devnumd)
|
||||||
|
or hub == number_of_hubs_with_feature))):
|
||||||
|
printout_enable = 1
|
||||||
|
|
||||||
|
uh = dev.open()
|
||||||
|
|
||||||
|
desc = None
|
||||||
|
try:
|
||||||
|
# Get USB Hub descriptor
|
||||||
|
desc = uh.controlMsg(requestType = USB_DIR_IN | USB_RT_HUB,
|
||||||
|
request = usb.REQ_GET_DESCRIPTOR,
|
||||||
|
value = usb.DT_HUB << 8,
|
||||||
|
index = 0, buffer = 1024, timeout = 1000)
|
||||||
|
finally:
|
||||||
|
del uh
|
||||||
|
|
||||||
|
if not desc:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# desc[3] is lower byte of wHubCharacteristics
|
||||||
|
if (desc[3] & 0x80) == 0 and (desc[3] & 0x03) >= 2:
|
||||||
|
# Hub doesn't have features of controling port power/indicator
|
||||||
|
continue
|
||||||
|
|
||||||
|
if printout_enable:
|
||||||
|
print "Hub #%d at %s:%03d" % (number_of_hubs_with_feature,
|
||||||
|
bus.dirname, dev.devnum)
|
||||||
|
if (desc[3] & 0x03) == 0:
|
||||||
|
print " INFO: ganged power switching."
|
||||||
|
elif (desc[3] & 0x03) == 1:
|
||||||
|
print " INFO: individual power switching."
|
||||||
|
elif (desc[3] & 0x03) == 2 or (desc[3] & 0x03) == 3:
|
||||||
|
print " WARN: no power switching."
|
||||||
|
|
||||||
|
if (desc[3] & 0x80) == 0:
|
||||||
|
print " WARN: Port indicators are NOT supported."
|
||||||
|
|
||||||
|
hubs.append({ 'busnum' : bus.dirname, 'devnum' : dev.devnum,
|
||||||
|
'indicator_support' : (desc[3] & 0x80) == 0x80,
|
||||||
|
'dev' : dev, 'num_ports' : desc[2] })
|
||||||
|
number_of_hubs_with_feature += 1
|
||||||
|
|
||||||
|
return hubs
|
||||||
|
|
||||||
|
def hub_port_status(handle, num_ports):
|
||||||
|
print " Hub Port Status:"
|
||||||
|
for i in range(num_ports):
|
||||||
|
port = i + 1
|
||||||
|
status = handle.controlMsg(requestType = USB_RT_PORT | usb.ENDPOINT_IN,
|
||||||
|
request = usb.REQ_GET_STATUS,
|
||||||
|
value = 0,
|
||||||
|
index = port, buffer = 4,
|
||||||
|
timeout = 1000)
|
||||||
|
|
||||||
|
print " Port %d: %02x%02x.%02x%02x" % (port, status[3], status[2],
|
||||||
|
status[1], status[0]),
|
||||||
|
if status[1] & 0x10:
|
||||||
|
print " indicator",
|
||||||
|
if status[1] & 0x08:
|
||||||
|
print " test" ,
|
||||||
|
if status[1] & 0x04:
|
||||||
|
print " highspeed",
|
||||||
|
if status[1] & 0x02:
|
||||||
|
print " lowspeed",
|
||||||
|
if status[1] & 0x01:
|
||||||
|
print " power",
|
||||||
|
|
||||||
|
if status[0] & 0x10:
|
||||||
|
print " RESET",
|
||||||
|
if status[0] & 0x08:
|
||||||
|
print " oc",
|
||||||
|
if status[0] & 0x04:
|
||||||
|
print " suspend",
|
||||||
|
if status[0] & 0x02:
|
||||||
|
print " enable",
|
||||||
|
if status[0] & 0x01:
|
||||||
|
print " connect",
|
||||||
|
|
||||||
|
print
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
COMMAND_SET_NONE = 0
|
||||||
|
COMMAND_SET_LED = 1
|
||||||
|
COMMAND_SET_POWER = 2
|
||||||
|
HUB_LED_GREEN = 2
|
||||||
|
|
||||||
|
def usage(progname):
|
||||||
|
print >> sys.stderr, """Usage: %s [{-h HUBNUM | -b BUSNUM -d DEVNUM}]
|
||||||
|
[-P PORT] [{-p [VALUE]|-l [VALUE]}]
|
||||||
|
""" % progname
|
||||||
|
|
||||||
|
def exit_with_usage(progname):
|
||||||
|
usage(progname)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
busnum = None
|
||||||
|
devnum = None
|
||||||
|
listing = False
|
||||||
|
verbose = False
|
||||||
|
hub = None
|
||||||
|
port = 1
|
||||||
|
cmd = COMMAND_SET_NONE
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
listing = True
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
while len(sys.argv) >= 2:
|
||||||
|
option = sys.argv[1]
|
||||||
|
sys.argv.pop(1)
|
||||||
|
if option == '-h':
|
||||||
|
if bunum != None or devnum != None:
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
hub = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
elif option == '-b':
|
||||||
|
busnum = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
elif option == '-d':
|
||||||
|
devnum = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
elif option == '-P':
|
||||||
|
port = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
elif option == '-l':
|
||||||
|
if cmd != COMMAND_SET_NONE:
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
value = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
else:
|
||||||
|
value = HUB_LED_GREEN
|
||||||
|
cmd = COMMAND_SET_LED
|
||||||
|
elif option == '-p':
|
||||||
|
if cmd != COMMAND_SET_NONE:
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
value = int(sys.argv[1])
|
||||||
|
sys.argv.pop(1)
|
||||||
|
else:
|
||||||
|
value = 0
|
||||||
|
cmd = COMMAND_SET_POWER
|
||||||
|
elif option == '-v':
|
||||||
|
verbose = True
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
listing = True
|
||||||
|
else:
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
except:
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
|
||||||
|
if ((busnum != None and devnum == None)
|
||||||
|
or (busnum == None and devnum != None)):
|
||||||
|
exit_with_usage(sys.argv[0])
|
||||||
|
|
||||||
|
if hub == None and busnum == None:
|
||||||
|
hub = 0 # Default hub = 0
|
||||||
|
|
||||||
|
if cmd == COMMAND_SET_NONE:
|
||||||
|
cmd = COMMAND_SET_POWER
|
||||||
|
|
||||||
|
hubs = find_hubs(listing, verbose, busnum, devnum, hub)
|
||||||
|
if len(hubs) == 0:
|
||||||
|
print >> sys.stderr, "No hubs found."
|
||||||
|
exit(1)
|
||||||
|
if listing:
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
if hub == None:
|
||||||
|
for h in hubs:
|
||||||
|
if h['busnum'] == busnum and h['devnum'] == devnum:
|
||||||
|
dev_hub = h['dev']
|
||||||
|
nports = h['num_ports']
|
||||||
|
else:
|
||||||
|
dev_hub = hubs[hub]['dev']
|
||||||
|
nports = hubs[hub]['num_ports']
|
||||||
|
|
||||||
|
uh = dev_hub.open()
|
||||||
|
if cmd == COMMAND_SET_POWER:
|
||||||
|
feature = USB_PORT_FEAT_POWER
|
||||||
|
index = port
|
||||||
|
if value:
|
||||||
|
request = usb.REQ_SET_FEATURE
|
||||||
|
else:
|
||||||
|
request = usb.REQ_CLEAR_FEATURE
|
||||||
|
else:
|
||||||
|
request = usb.REQ_SET_FEATURE
|
||||||
|
feature = USB_PORT_FEAT_INDICATOR
|
||||||
|
index = (value << 8) | port
|
||||||
|
if verbose:
|
||||||
|
print "Send control message (REQUEST=%d, FEATURE=%d, INDEX=%d) " % (request, feature, index)
|
||||||
|
|
||||||
|
uh.controlMsg(requestType = USB_RT_PORT, request = request, value = feature,
|
||||||
|
index = index, buffer = None, timeout = 1000)
|
||||||
|
if verbose:
|
||||||
|
hub_port_status(uh,nports)
|
||||||
|
|
||||||
|
del uh
|
||||||
291
tool/pinpad-test.py
Executable file
291
tool/pinpad-test.py
Executable file
@@ -0,0 +1,291 @@
|
|||||||
|
#! /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 <gniibe@fsij.org>
|
||||||
|
|
||||||
|
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
|
||||||
|
Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
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, pinmax):
|
||||||
|
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
|
||||||
|
self.pinmax = pinmax
|
||||||
|
|
||||||
|
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 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:
|
||||||
|
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
|
||||||
|
self.pinmax, # 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, apdu, single_step, 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
|
||||||
|
self.pinmax, # wPINMaxExtraDigit Low (PINmax)
|
||||||
|
1, # wPINMaxExtraDigit High (PINmin)
|
||||||
|
confirm_pin_setting(single_step),
|
||||||
|
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))
|
||||||
|
|
||||||
|
# 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
|
||||||
|
else:
|
||||||
|
apdu = [0x00, 0x2c, 0x00, 0x81] # BY_USER with resetcode
|
||||||
|
self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad")
|
||||||
|
|
||||||
|
# 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")
|
||||||
|
|
||||||
|
# "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 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(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(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
|
||||||
|
card.connection.disconnect()
|
||||||
|
|
||||||
|
print "OK."
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def print_usage():
|
||||||
|
print "pinpad-test: testing pinentry of PC/SC card reader"
|
||||||
|
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 "
|
||||||
|
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
|
||||||
|
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 == '--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, pinmax, change_by_two_steps)
|
||||||
|
|
||||||
|
# 69 82: Security status not satisfied: pin doesn't match
|
||||||
|
# 69 85: Conditions of use not satisfied
|
||||||
|
# 6b 00: Wrong parameters P1-P2
|
||||||
Reference in New Issue
Block a user