Compare commits
77 Commits
release/0.
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
c254c9d558 | ||
|
|
b146a8aa6d | ||
|
|
c04e5d816c | ||
|
|
82fc1c7e93 | ||
|
|
0f4fac869c | ||
|
|
112a9f51c2 | ||
|
|
96de962cfc | ||
|
|
c196992c76 | ||
|
|
571e7af387 | ||
|
|
74b21d307c | ||
|
|
d5e2950f46 | ||
|
|
f20f05df8d | ||
|
|
58d9f554d1 | ||
|
|
fdaee50acb | ||
|
|
995961a593 | ||
|
|
2fbdeb8d89 | ||
|
|
189f17c93c | ||
|
|
a32381c815 | ||
|
|
f62253e63f | ||
|
|
93a7515bcd | ||
|
|
661c8e63dc | ||
|
|
0b5f579510 | ||
|
|
582612ddc7 | ||
|
|
0ef47be2da | ||
|
|
af1067688e | ||
|
|
782b41f47c | ||
|
|
8e765327b2 | ||
|
|
96dc883954 | ||
|
|
fdbeb8c84d | ||
|
|
6c5ee62d61 | ||
|
|
f58d639440 | ||
|
|
79c9ad9fd4 | ||
|
|
a9ea672cf3 | ||
|
|
05a8fa7951 | ||
|
|
de4ff17bc9 | ||
|
|
9ca92ad02a | ||
|
|
4f2f93d806 | ||
|
|
b08651f86b | ||
|
|
57fb94e900 | ||
|
|
96a6e80eb0 | ||
|
|
6c79434549 | ||
|
|
81368495d7 |
250
ChangeLog
250
ChangeLog
@@ -1,3 +1,253 @@
|
||||
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>
|
||||
|
||||
* Version 0.12.
|
||||
|
||||
2011-05-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso, cmd_internal_authenticate)
|
||||
(cmd_update_binary, cmd_write_binary): Don't check pw locked.
|
||||
|
||||
* tool/dfuse.py (DFU_STM32.verify): Add missing colon.
|
||||
* tool/dfuse.py (get_device): Restrict to STMicro DfuSe.
|
||||
|
||||
* tool/gnuk_put_binary.py (main): Add -p option to enter password.
|
||||
|
||||
* src/ac.c (verify_user_0): New.
|
||||
(verify_pso_cds, verify_admin_0): Use verify_user_0.
|
||||
* src/openpgp.c (cmd_change_password): Use verify_user_0.
|
||||
|
||||
* src/random.c (get_salt): Rename from get_random.
|
||||
(random_bytes_get, random_bytes_free): It's 16-byte.
|
||||
|
||||
* src/ac.c (verify_admin_0): Use PW_ERR_PW1 counter when
|
||||
authenticated by PW1.
|
||||
|
||||
2011-05-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ac.c (verify_pso_cds, verify_other): Fail (with no counter
|
||||
update) if key is not registered yet.
|
||||
(verify_admin_0): Compare to OPENPGP_CARD_INITIAL_PW3 when empty
|
||||
PW3 and non-empty PW1 but signing key is not registered yet.
|
||||
|
||||
* tool/gnuk_put_binary.py: New implementation by pyscard.
|
||||
|
||||
* src/main.c (device_initialize_once): New.
|
||||
* src/usb_prop.c (gnukStringSerial): Move to...
|
||||
* src/usb_desc.c (gnukStringSerial): here. Bump version to 0.12.
|
||||
Fill by 0xff.
|
||||
* src/usb_prop.c (gnuk_device_init)
|
||||
(gnuk_device_GetStringDescriptor): Don't use RAM for
|
||||
gnukStringSerial, use ROM like other string descriptor.
|
||||
* src/usb_desc.c (String_Descriptor): Add gnukStringSerial.
|
||||
|
||||
* src/openpgp-do.c (gpg_get_pw1_lifetime): Make static.
|
||||
(gpg_do_load_prvkey, gpg_do_write_prvkey): Use kdi.
|
||||
(gpg_increment_digital_signature_counter): Call gpg_get_pw1_lifetime.
|
||||
* src/openpgp.c (cmd_pso): Follow the change.
|
||||
* src/flash.c (keystore_pool): Remove. Use &_keystore_pool.
|
||||
* src/ac.c (auth_status): Don't assign 0 as it's automatically
|
||||
cleared.
|
||||
|
||||
2011-05-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_pw_locked): Rename from gpg_passwd_locked.
|
||||
(gpg_pw_get_err_counter): Rename from gpg_get_pw_err_counter.
|
||||
(gpg_pw_reset_err_counter): Rename from gpg_reset_pw_err_counter.
|
||||
(gpg_pw_increment_err_counter): Rename from gpg_increment_err_counter.
|
||||
* src/ac.c, src/openpgp.c, src/gnuk.h: Follow the change.
|
||||
|
||||
Bug fixes.
|
||||
* src/openpgp.c (cmd_reset_user_password, cmd_change_password)
|
||||
* src/openpgp-do.c (proc_resetting_code): Fix check of return value.
|
||||
* src/ac.c (ac_fini): Clear keystring_md_pw3.
|
||||
|
||||
Prevent observation of PW3 is emptiness by PW3's error counter.
|
||||
Support verify_admin by PW1 when PW3 is empty.
|
||||
* src/ac.c (admin_authorized): New.
|
||||
(verify_admin_0): Set admin_authorized.
|
||||
* src/openpgp-do.c (proc_resetting_code): Use admin_authorized.
|
||||
(gpg_do_write_prvkey): Clear dek_encrypted_3 when keystring_admin
|
||||
is NULL.
|
||||
(proc_key_import): Checking admin_authorized, set keystring_admin.
|
||||
* src/openpgp.c (cmd_reset_user_password): Use admin_authorized.
|
||||
|
||||
2011-04-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* gnuk.svg: Updated.
|
||||
|
||||
2011-04-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* Version 0.11.
|
||||
|
||||
@@ -62,6 +62,20 @@
|
||||
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
|
||||
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
|
||||
|
||||
/**
|
||||
* @name Sampling rates
|
||||
* @{
|
||||
*/
|
||||
#define ADC_SAMPLE_1P5 0 /**< @brief 1.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_7P5 1 /**< @brief 7.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_13P5 2 /**< @brief 13.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_28P5 3 /**< @brief 28.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_41P5 4 /**< @brief 41.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_55P5 5 /**< @brief 55.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_71P5 6 /**< @brief 71.5 cycles sampling time. */
|
||||
#define ADC_SAMPLE_239P5 7 /**< @brief 239.5 cycles sampling time. */
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
@@ -238,26 +252,51 @@ typedef struct {
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Number of channels in a conversion sequence.
|
||||
*/
|
||||
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
|
||||
|
||||
#define ADC_SQR3_SQ0_N(n) ((n) << 0)
|
||||
#define ADC_SQR3_SQ1_N(n) ((n) << 5)
|
||||
#define ADC_SQR3_SQ2_N(n) ((n) << 10)
|
||||
#define ADC_SQR3_SQ3_N(n) ((n) << 15)
|
||||
#define ADC_SQR3_SQ4_N(n) ((n) << 20)
|
||||
#define ADC_SQR3_SQ5_N(n) ((n) << 25)
|
||||
#define ADC_SQR3_SQ1_N(n) ((n) << 0) /**< @brief 1st channel in seq. */
|
||||
#define ADC_SQR3_SQ2_N(n) ((n) << 5) /**< @brief 2nd channel in seq. */
|
||||
#define ADC_SQR3_SQ3_N(n) ((n) << 10) /**< @brief 3rd channel in seq. */
|
||||
#define ADC_SQR3_SQ4_N(n) ((n) << 15) /**< @brief 4th channel in seq. */
|
||||
#define ADC_SQR3_SQ5_N(n) ((n) << 20) /**< @brief 5th channel in seq. */
|
||||
#define ADC_SQR3_SQ6_N(n) ((n) << 25) /**< @brief 6th channel in seq. */
|
||||
|
||||
#define ADC_SQR2_SQ6_N(n) ((n) << 0)
|
||||
#define ADC_SQR2_SQ7_N(n) ((n) << 5)
|
||||
#define ADC_SQR2_SQ8_N(n) ((n) << 10)
|
||||
#define ADC_SQR2_SQ9_N(n) ((n) << 15)
|
||||
#define ADC_SQR2_SQ10_N(n) ((n) << 20)
|
||||
#define ADC_SQR2_SQ11_N(n) ((n) << 25)
|
||||
#define ADC_SQR2_SQ7_N(n) ((n) << 0) /**< @brief 7th channel in seq. */
|
||||
#define ADC_SQR2_SQ8_N(n) ((n) << 5) /**< @brief 8th channel in seq. */
|
||||
#define ADC_SQR2_SQ9_N(n) ((n) << 10) /**< @brief 9th channel in seq. */
|
||||
#define ADC_SQR2_SQ10_N(n) ((n) << 15) /**< @brief 10th channel in seq.*/
|
||||
#define ADC_SQR2_SQ11_N(n) ((n) << 20) /**< @brief 11th channel in seq.*/
|
||||
#define ADC_SQR2_SQ12_N(n) ((n) << 25) /**< @brief 12th channel in seq.*/
|
||||
|
||||
#define ADC_SQR1_SQ13_N(n) ((n) << 0)
|
||||
#define ADC_SQR1_SQ14_N(n) ((n) << 5)
|
||||
#define ADC_SQR1_SQ15_N(n) ((n) << 10)
|
||||
#define ADC_SQR1_SQ16_N(n) ((n) << 15)
|
||||
#define ADC_SQR1_SQ13_N(n) ((n) << 0) /**< @brief 13th channel in seq.*/
|
||||
#define ADC_SQR1_SQ14_N(n) ((n) << 5) /**< @brief 14th channel in seq.*/
|
||||
#define ADC_SQR1_SQ15_N(n) ((n) << 10) /**< @brief 15th channel in seq.*/
|
||||
#define ADC_SQR1_SQ16_N(n) ((n) << 15) /**< @brief 16th channel in seq.*/
|
||||
|
||||
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0) /**< @brief AN0 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3) /**< @brief AN1 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6) /**< @brief AN2 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN3(n) ((n) << 9) /**< @brief AN3 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN4(n) ((n) << 12) /**< @brief AN4 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN5(n) ((n) << 15) /**< @brief AN5 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN6(n) ((n) << 18) /**< @brief AN6 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN7(n) ((n) << 21) /**< @brief AN7 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN8(n) ((n) << 24) /**< @brief AN8 sampling time. */
|
||||
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27) /**< @brief AN9 sampling time. */
|
||||
|
||||
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0) /**< @brief AN10 sampling time. */
|
||||
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3) /**< @brief AN11 sampling time. */
|
||||
#define ADC_SMPR1_SMP_AN12(n) ((n) << 6) /**< @brief AN12 sampling time. */
|
||||
#define ADC_SMPR1_SMP_AN13(n) ((n) << 9) /**< @brief AN13 sampling time. */
|
||||
#define ADC_SMPR1_SMP_AN14(n) ((n) << 12) /**< @brief AN14 sampling time. */
|
||||
#define ADC_SMPR1_SMP_AN15(n) ((n) << 15) /**< @brief AN15 sampling time. */
|
||||
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18) /**< @brief Temperature Sensor
|
||||
sampling time. */
|
||||
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21) /**< @brief Voltage Reference
|
||||
sampling time. */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
|
||||
@@ -107,12 +107,12 @@ void SVCallVector(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reschedule verification and setup after an IRQ.
|
||||
* @brief Exception exit redirection to _port_switch_from_isr().
|
||||
*/
|
||||
void _port_irq_epilogue(void) {
|
||||
|
||||
port_lock_from_isr();
|
||||
if ((SCB_ICSR & ICSR_RETTOBASE) && chSchIsRescRequiredExI()) {
|
||||
if ((SCB_ICSR & ICSR_RETTOBASE)) {
|
||||
register struct extctx *ctxp;
|
||||
|
||||
/* Adding an artificial exception return context, there is no need to
|
||||
@@ -126,7 +126,6 @@ void _port_irq_epilogue(void) {
|
||||
order to keep the rest of the context switching atomic.*/
|
||||
return;
|
||||
}
|
||||
/* ISR exit without context switching.*/
|
||||
port_unlock_from_isr();
|
||||
}
|
||||
|
||||
@@ -139,7 +138,8 @@ __attribute__((naked))
|
||||
#endif
|
||||
void _port_switch_from_isr(void) {
|
||||
|
||||
chSchDoRescheduleI();
|
||||
if (chSchIsRescRequiredExI())
|
||||
chSchDoRescheduleI();
|
||||
asm volatile ("svc #0");
|
||||
}
|
||||
|
||||
|
||||
BIN
FSIJ-s.png
Normal file
BIN
FSIJ-s.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
95
NEWS
95
NEWS
@@ -1,5 +1,100 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
* Major changes in Gnuk 0.15
|
||||
|
||||
Released 2011-11-24, by NIIBE Yutaka
|
||||
|
||||
** New targets: FST_01 and FST_01_00
|
||||
Flying Stone Technology's open hardware, Flying Stone Tiny 01 is
|
||||
supported.
|
||||
|
||||
** Flash writing tool for "DfuSe" is improved
|
||||
Now, it support holes and unaligned blocks in hex file.
|
||||
|
||||
** Experimental PIN-pad support (by TV controller) change
|
||||
Now, Gnuk has codetables for conversion from CIR code to ASCII code.
|
||||
Note that only four controllers (of Dell, Sharp, Sony, and Toshiba)
|
||||
are supported and tested.
|
||||
|
||||
** It is possible for users to keep using OPENPGP_CARD_INITIAL_PW1
|
||||
With a bug fix of verify_user_0, it's now possible. Although it's not
|
||||
recommended.
|
||||
|
||||
** Important bug fix and a workaround
|
||||
In version 0.14, __main_stack_size__ (for interrupt handler) was too
|
||||
small for some cases. This is fixed in 0.15.
|
||||
|
||||
In src/Makefile.in, added -mfix-cortex-m3-ldrd for correctly linking C
|
||||
library for thumb2. This is needed for newer summon-arm-toolchain.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.14
|
||||
|
||||
Released 2011-10-07, by NIIBE Yutaka
|
||||
|
||||
** Random number generator change
|
||||
NeuG, Gniibe's True RNG implementation for STM32F103, has been
|
||||
integrated to Gnuk. It is not needed to put random number bytes
|
||||
(generated by host) to Token any more.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.13
|
||||
|
||||
Released 2011-06-15, by NIIBE Yutaka
|
||||
|
||||
** Improved RSA routine.
|
||||
About 20% speed improvement.
|
||||
|
||||
** New tool: hub_ctrl.
|
||||
It is a Python implementation ported from original C implementation.
|
||||
It is useful for development of USB target if you have a good hub.
|
||||
You can power off/on the port to reset Gnuk Token.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.12
|
||||
|
||||
Released 2011-05-13, by NIIBE Yutaka
|
||||
|
||||
** Admin-less mode is supported.
|
||||
The OpenPGP card specification assumes existence of a security officer
|
||||
(admin), who has privilege to manage the card. On the other hand,
|
||||
many use cases of Gnuk are admin == user.
|
||||
|
||||
Thus, Gnuk now supports "admin-less" mode. In this mode, user can get
|
||||
privilege with the password of PW1.
|
||||
|
||||
At the initialization of the card, Gnuk becomes compatible mode by
|
||||
setting PW3. Without setting PW3, it becomes "admin-less" mode
|
||||
by setting PW1.
|
||||
|
||||
** Important two bug fixes.
|
||||
Gnuk (<= 0.11) has a bug which makes possible for attacker to change
|
||||
user password to unknown state without knowing original password (when
|
||||
no keys are loaded yet). No, attacker could not steal your identity
|
||||
(cannot sign or decrypt), but it would be possible to disturb you.
|
||||
|
||||
Gnuk (<= 0.11) has a bug which makes possible for attacker to guess
|
||||
admin password easily. When admin password is not set (the default
|
||||
value of factory setting), failure of VERIFY doesn't increment error
|
||||
counter in older versions. Observing no increment of error counter,
|
||||
attacker could know that admin password is the one of factory setting.
|
||||
|
||||
** tool/gnuk_put_binary.py now uses pyscard.
|
||||
Instead of PyUSB, it uses Python binding of PC/SC. PyUSB version is
|
||||
still available as tool/gnuk_put_binary_libusb.py.
|
||||
|
||||
** Logo for Gnuk is updated.
|
||||
|
||||
** Gnuk Sticker SVG is available.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.11
|
||||
|
||||
Released 2011-04-15, by NIIBE Yutaka
|
||||
|
||||
This is bug fixes only release.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.10
|
||||
|
||||
Released 2011-02-10, by NIIBE Yutaka
|
||||
|
||||
278
README
278
README
@@ -1,7 +1,7 @@
|
||||
Gnuk - software for GPG USB Token
|
||||
Gnuk - software for GnuPG USB Token
|
||||
|
||||
Version 0.11
|
||||
2011-04-15
|
||||
Version 0.15
|
||||
2011-11-24
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
@@ -19,45 +19,112 @@ me to bring a card reader all the time. With Gnuk, this issue will be
|
||||
solved by a USB token which is small enough.
|
||||
|
||||
Please look at the graphics of "gnuk.svg" for the software name. My
|
||||
son used to be with his NUK(R), always, everywhere. I will be with a
|
||||
USB Token by Gnuk everywhere.
|
||||
son used to be with his NUK(R), always, everywhere. I am with a USB
|
||||
Token by "Gnuk", always, everywhere.
|
||||
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
|
||||
card 2.0, GPF Crypto Stick, etc.) ?
|
||||
http://www.g10code.de/p-card.html
|
||||
http://www.privacyfoundation.de/crypto_stick/
|
||||
A0: IMRHO, not quite. There is no ready-to-use out-of-box product.
|
||||
(It is welcome for me that some vendor will manufacture Gnuk USB
|
||||
Token. Even I can help design of hardware, if needed.)
|
||||
Good points are:
|
||||
* If you have skill of electronics and like DIY, you can build
|
||||
Gnuk Token cheaper (see Q8-A8).
|
||||
* You can study Gnuk to modify and to enhance. For example, you
|
||||
can implement your own authentication method with some sensor
|
||||
such as acceleration sensor.
|
||||
* It is "of Free Software"; Gnuk is distributed under GPLv3+,
|
||||
"by Free Software"; Gnuk development requires only Free Software
|
||||
(GNU Toolchain, Python, etc.),
|
||||
"for Free Software"; Gnuk supports GnuPG.
|
||||
|
||||
Q1: What kind of key algorithm is supported?
|
||||
A1: Gnuk only supports 2048-bit RSA.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so.
|
||||
|
||||
Q3: What's your recommendation for target board?
|
||||
A3: Orthodox choice is Olimex STM32-H103.
|
||||
If you have skill of electronics and like DIY, STM32 part of STM8S
|
||||
Discovery Kit might be the best choice.
|
||||
Currently FST-01 (Flying Stone Tiny 01) is under development,
|
||||
it will be the best choice, hopefully.
|
||||
|
||||
Q4: What's version of GnuPG are you using?
|
||||
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
|
||||
2.0.14-2 (in sid). With older versions, you can only sign with SHA1.
|
||||
See: http://www.fsij.org/gnuk/gnupg2-fixes-needed
|
||||
|
||||
Q5: What's version of pcscd and libccid are you using?
|
||||
A5: In Debian GNU/Linux system, I use pcscd 1.5.5-4 and libccid 1.3.11-2,
|
||||
which is in squeeze. Note that you need to edit /etc/libccid_Info.plist
|
||||
when using libccid (< 1.4.1).
|
||||
|
||||
Q6: What kinds of hardware is required for development?
|
||||
A6: You need a target board plus a JTAG debugger. If you just want to
|
||||
test Gnuk for target boards with DfuSe, JTAG debugger is not
|
||||
the requirement. Note that for real use, you need JTAG debugger
|
||||
to enable flash ROM protection.
|
||||
|
||||
Q7: How much does it cost?
|
||||
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
|
||||
|
||||
Q8: How much does it cost for DIY version?
|
||||
A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build
|
||||
your own JTAG debugger using FTDI2232 module (1450 JPY), see:
|
||||
http://www.fsij.org/gnuk/jtag_dongle_ftdi2232
|
||||
|
||||
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
|
||||
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
|
||||
card/reader (problems are fixed in trunk). When your newly
|
||||
inserted token is not found by GnuPG, try killing scdaemon and let
|
||||
it to be invoked again. I do:
|
||||
$ killall -9 scdaemon
|
||||
and confirm scdaemon doesn't exist, then,
|
||||
$ gpg-connect-agent learn /bye
|
||||
|
||||
Qa: With GNOME, I can't use Gnuk Token for SSH. How can we use it for SSH?
|
||||
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
|
||||
gpg-agant for the role of ssh-agent. For gnome-keyring please do:
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
Qb: With GNOME 3, I can't use Gnuk Token at all. Why?
|
||||
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
|
||||
|
||||
$ gnome-session-properties
|
||||
|
||||
and at the tab of "Startup Programs", disable check buttons for "GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
|
||||
|
||||
Release notes
|
||||
=============
|
||||
|
||||
This is twelfth release of Gnuk. While it works well for specific
|
||||
This is sixteenth release of Gnuk. While it works well for specific
|
||||
usages and it is considered stable, it is still somewhat experimental.
|
||||
Note that you need to write random bits after installation of gnuk
|
||||
executable to the chip. This procedure is required to share a single
|
||||
executable among multiple devices.
|
||||
|
||||
Tested features are:
|
||||
|
||||
* Personalization of the card
|
||||
|
||||
* Changing Login name, URL, Name, Sex, Language, etc.
|
||||
|
||||
* Password handling (PW1, RC, PW3)
|
||||
|
||||
* Key import for three types:
|
||||
|
||||
* key for digital signing
|
||||
|
||||
* key for decryption
|
||||
|
||||
* key for authentication
|
||||
|
||||
* PSO: Digital Signature
|
||||
|
||||
* PSO: Decipher
|
||||
|
||||
* INTERNAL AUTHENTICATE
|
||||
|
||||
* Changing value of password status bytes (0x00C4)
|
||||
|
||||
* Changing value of password status bytes (0x00C4): forcesig
|
||||
* Verify with pin pad
|
||||
|
||||
* Modify with pin pad
|
||||
|
||||
It is known not-working well:
|
||||
@@ -66,28 +133,29 @@ It is known not-working well:
|
||||
work well. Please disable DEBUG option if it doesn't work well.
|
||||
|
||||
* Card holder certificate
|
||||
It is implemented in Gnuk side. But its size matters (>
|
||||
1KB). GnuPG cannot handle a data object of large size with
|
||||
PC/SC backend. Specifically, handle_transmit function in
|
||||
pcsc-wrapper.c uses the buffer of size 1024-byte.
|
||||
It is implemented in Gnuk side. But its large size matters
|
||||
(> 1KB). Some versions of GnuPG cannot handle a data object
|
||||
of large size with PC/SC backend. Specifically,
|
||||
handle_transmit function in pcsc-wrapper.c uses the buffer
|
||||
of size 1024-byte.
|
||||
|
||||
Not supported feature(s):
|
||||
|
||||
* Overriding key import. You need to remove all keys first.
|
||||
* Key generation on device side
|
||||
|
||||
* Key generation
|
||||
|
||||
Targets
|
||||
=======
|
||||
|
||||
We use Olimex STM32-H103 board. We also use STM32 part of STM8S
|
||||
Discovery Kit.
|
||||
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We
|
||||
also use STM32 part of STM8S Discovery Kit.
|
||||
|
||||
With DfuSe support, CQ STARM, STBee, and STBee Mini are also our
|
||||
targets. But those targets with DfuSe are basically not for normal
|
||||
use but for experiments, because it would be impossible for DfuSe to
|
||||
disable read from flash. For real use, please consider killing DfuSe
|
||||
and enable read protect using JTAG debugger.
|
||||
and enable read protection using JTAG debugger.
|
||||
|
||||
I think that it could run on Olimex STM32-P103, or other boards with
|
||||
STM32F103. Besides, we are porting it to STM32 Primer 2.
|
||||
@@ -124,8 +192,8 @@ The author(s) of Gnuk expect users of Gnuk will be able to access the
|
||||
source code of Gnuk, so that users can study the code and can modify
|
||||
if needed. This doesn't mean person who has a USB Token by Gnuk
|
||||
should be able to acess everything on the Token, regardless of its
|
||||
protections. Private keys, random bytes, and other information should
|
||||
be protected properly.
|
||||
protections. Private keys, and other information should be protected
|
||||
properly.
|
||||
|
||||
|
||||
External source code
|
||||
@@ -145,6 +213,9 @@ Gnuk is distributed with external source code.
|
||||
We use PolarSSL for RSA computation, AES encryption/decryption
|
||||
and SHA-1 computation.
|
||||
|
||||
The file include/polarssl/bn_mul.h is heavily modified for ARM
|
||||
Cortex-M3.
|
||||
|
||||
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
|
||||
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
|
||||
|
||||
@@ -174,8 +245,24 @@ How to compile
|
||||
|
||||
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
|
||||
See http://github.com/esden/summon-arm-toolchain/ for preparation of
|
||||
GNU Toolchain for 'arm-none-eabi' target.
|
||||
See http://github.com/esden/summon-arm-toolchain/ (which includes fix
|
||||
of binutils-2.21.1) for preparation of GNU Toolchain for
|
||||
'arm-none-eabi' target.
|
||||
|
||||
# Note that we need to link correct C library (for string functions).
|
||||
# For this purpose, Makefile.in contains following line:
|
||||
#
|
||||
# MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
|
||||
#
|
||||
# This should not be needed (as -mcpu=cortex-m3 means
|
||||
# -mfix-cortex-m3-ldrd), but in practice it is needed for
|
||||
# the configuration of patch-gcc-config-arm-t-arm-elf.diff in
|
||||
# summon-arm-toolchain.
|
||||
#
|
||||
# In ChibiOS_2.0.8/os/ports/GCC/ARM/rules.mk, it specifies
|
||||
# -mno-thumb-interwork option. This means that you should not
|
||||
# link C library which contains ARM (not Thumb) code.
|
||||
|
||||
|
||||
Change directory to `src':
|
||||
|
||||
@@ -212,6 +299,36 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
$
|
||||
|
||||
|
||||
Flying Stone Tiny 01
|
||||
--------------------
|
||||
|
||||
If you are using Flying Stone Tiny 01, you need a SWD writer. I am
|
||||
using revision 946 of Simon Qian's Versaloon.
|
||||
|
||||
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
|
||||
|
||||
For OpenOCD, we need unofficial patch.
|
||||
|
||||
See the article of Versaloon Forum:
|
||||
|
||||
http://www.versaloon.com/bbs/viewtopic.php?p=16179
|
||||
|
||||
|
||||
Type following to invoke OpenOCD:
|
||||
|
||||
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
|
||||
|
||||
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> flash write_image erase gnuk.elf
|
||||
> reset
|
||||
> exit
|
||||
$
|
||||
|
||||
|
||||
|
||||
STM8S Discovery Kit
|
||||
-------------------
|
||||
|
||||
@@ -280,45 +397,35 @@ accessing by JTAG debugger is recommended.
|
||||
How to configure
|
||||
================
|
||||
|
||||
You need python and PyUSB (python-usb package in Debian).
|
||||
You need python and pyscard (python-pyscard package in Debian) or
|
||||
PyUSB (python-usb package in Debian).
|
||||
|
||||
(1) In the 'src' directory, type
|
||||
(1) [pyscard] Stop scdaemon
|
||||
[PyUSB] Stop the pcsc daemon.
|
||||
|
||||
$ make random_bits
|
||||
If scdaemon is running, please kill it, or you will get "Smartcard
|
||||
Exception" by "Sharing violation".
|
||||
|
||||
In this process, it takes time for the command of
|
||||
$ killall -9 scdaemon
|
||||
|
||||
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) Stop the pcsc daemon.
|
||||
In case of PyUSB tool, you need to stop pcscd.
|
||||
|
||||
# /etc/init.d/pcscd stop
|
||||
|
||||
(3) Write the random bits to the device
|
||||
|
||||
Connect your board to USB port of your PC. And invoke gnuk_put_binary.py:
|
||||
|
||||
# ../tool/gnuk_put_binary.py -r random_bits
|
||||
random_bits: 1024
|
||||
Updating random bits
|
||||
...
|
||||
|
||||
(4) [Optional] Write fixed serial number
|
||||
(2) [Optional] Write fixed serial number
|
||||
|
||||
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
|
||||
|
||||
# EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary.py -s ../GNUK_SERIAL_NUMBER
|
||||
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary.py -s ../GNUK_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:
|
||||
|
||||
# ../tool/gnuk_put_binary.py ../../<YOUR-CERTIFICATE>.bin
|
||||
$ ../tool/gnuk_put_binary.py ../../<YOUR-CERTIFICATE>.bin
|
||||
../../<YOUR-CERTIFICATE>.bin: <LENGTH-OF-YOUR-CERTIFICATE>
|
||||
Updating card holder certificate
|
||||
...
|
||||
@@ -383,7 +490,55 @@ Try following to see Gnuk runs:
|
||||
$ gpg --card-status
|
||||
|
||||
|
||||
For more, see doc/DEMO.
|
||||
Personalize the Token and import keys
|
||||
-------------------------------------
|
||||
|
||||
You can personalize the token, putting your information like: Name,
|
||||
Login name, Sex, Languages, URL, etc., and password. To do so, GnuPG
|
||||
command is:
|
||||
|
||||
$ gpg --card-edit
|
||||
|
||||
Note that the factory setting of user password is "123456" and admin
|
||||
password is "12345678" as the specification.
|
||||
|
||||
No, Gnuk doesn't support key generation. You need to create your
|
||||
keys on your computer, and import them to Gnuk Token. After you create
|
||||
your keys (they must be 2048-bit RSA), you can import them.
|
||||
|
||||
For detail, please see doc/DEMO and doc/DEMO-2.
|
||||
|
||||
Note that it make sense to preserve your keys on your computer so that
|
||||
you can import the keys (again) to (possibly another) Gnuk Token. In
|
||||
this case, you can use GnuPG's option to specify the home directory by
|
||||
--homedir.
|
||||
|
||||
After creating keys by:
|
||||
|
||||
$ gpg --gen-key
|
||||
...
|
||||
|
||||
Copy directory which contains your secret keys to new directory named
|
||||
<gpgdir-with-your-secret-keys>:
|
||||
|
||||
$ cp -pa $HOME/.gnupg <gpgdir-with-your-secret-keys>
|
||||
|
||||
Then, import keys by:
|
||||
|
||||
$ gpg --edit-key <YOUR-KEYID>
|
||||
|
||||
While your $HOME/.gnupg now doesn't have your secret keys after
|
||||
import, <gpgdir-with-your-secret-keys> still has them. You can again
|
||||
import them by:
|
||||
|
||||
$ gpg --homedir=<gpgdir-with-your-secret-keys> --edit-key <YOUR-KEYID>
|
||||
|
||||
Note that you *should not* save changes this time to preserve keys
|
||||
on your computer. The session goes like this:
|
||||
|
||||
gpg> quit
|
||||
Save changes? (y/N) n
|
||||
Quit without saving? (y/N) y
|
||||
|
||||
|
||||
|
||||
@@ -413,15 +568,22 @@ linux/Documentation/usb/usbmon.txt
|
||||
Read-only Git Repository
|
||||
========================
|
||||
|
||||
You can browse at http://www.gniibe.org/gitweb?p=gnuk.git;a=summary
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://www.gniibe.org/gnuk.git/
|
||||
|
||||
or
|
||||
|
||||
$ git clone http://www.gniibe.org/git/gnuk.git/
|
||||
|
||||
|
||||
|
||||
Information on the Web
|
||||
======================
|
||||
|
||||
Please see: http://www.fsij.org/gnuk/
|
||||
Please visit: http://www.fsij.org/gnuk/
|
||||
|
||||
|
||||
Your Contributions
|
||||
|
||||
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_SUPPORT)
|
||||
/* PA0/TIM2_CH1 = 1 (pull up) */
|
||||
/* PA1/TIM2_CH2 = 0 (pull down) */
|
||||
/* PA2/TIM2_CH3 <= Vout of CIR receiver module */
|
||||
|
||||
/* EXTI2 <= PA2 */
|
||||
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI2_PA;
|
||||
EXTI->IMR = 0;
|
||||
EXTI->FTSR = EXTI_FTSR_TR2;
|
||||
NVICEnableVector(EXTI2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||
/* TIM2 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM2RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
NVICEnableVector(TIM2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||
|
||||
TIM2->CR1 = TIM_CR1_URS | TIM_CR1_ARPE;
|
||||
TIM2->CR2 = TIM_CR2_TI1S;
|
||||
TIM2->SMCR = TIM_SMCR_TS_0 | TIM_SMCR_TS_2 | TIM_SMCR_SMS_2;
|
||||
TIM2->DIER = 0; /* Disable interrupt for now */
|
||||
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_3
|
||||
| TIM_CCMR1_CC2S_1 | TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_3;
|
||||
TIM2->CCMR2 = 0;
|
||||
TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
|
||||
TIM2->PSC = 72 - 1; /* 1 MHz */
|
||||
TIM2->ARR = 18000; /* 18 ms */
|
||||
/* Generate UEV to upload PSC and ARR */
|
||||
TIM2->EGR = TIM_EGR_UG;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
USB_Cable_Config (int NewState)
|
||||
{
|
||||
if (NewState != DISABLE)
|
||||
palSetPad (IOPORT1, GPIOA_USB_ENABLE);
|
||||
else
|
||||
palClearPad (IOPORT1, GPIOA_USB_ENABLE);
|
||||
}
|
||||
|
||||
void
|
||||
set_led (int value)
|
||||
{
|
||||
if (value)
|
||||
palSetPad (IOPORT2, GPIOB_LED);
|
||||
else
|
||||
palClearPad (IOPORT2, GPIOB_LED);
|
||||
}
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
void
|
||||
cir_ext_disable (void)
|
||||
{
|
||||
EXTI->PR = EXTI_PR_PR2;
|
||||
EXTI->IMR &= ~EXTI_IMR_MR2;
|
||||
}
|
||||
|
||||
void
|
||||
cir_ext_enable (void)
|
||||
{
|
||||
EXTI->IMR |= EXTI_IMR_MR2;
|
||||
}
|
||||
|
||||
extern void cir_ext_interrupt (void);
|
||||
extern void cir_timer_interrupt (void);
|
||||
|
||||
CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
||||
{
|
||||
CH_IRQ_PROLOGUE ();
|
||||
chSysLockFromIsr ();
|
||||
|
||||
cir_ext_interrupt ();
|
||||
|
||||
chSysUnlockFromIsr ();
|
||||
CH_IRQ_EPILOGUE ();
|
||||
}
|
||||
|
||||
CH_IRQ_HANDLER (TIM2_IRQHandler)
|
||||
{
|
||||
CH_IRQ_PROLOGUE();
|
||||
chSysLockFromIsr();
|
||||
|
||||
cir_timer_interrupt ();
|
||||
|
||||
chSysUnlockFromIsr();
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#endif
|
||||
138
boards/FST_01/board.h
Normal file
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_
|
||||
|
||||
/*
|
||||
* Setup for the Olimex STM32-P103 proto board.
|
||||
* Setup for the Olimex STM32-H103 proto board.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Board identifier.
|
||||
*/
|
||||
#define BOARD_OLIMEX_STM32_P103
|
||||
#define BOARD_NAME "Olimex STM32-P103"
|
||||
#define BOARD_OLIMEX_STM32_H103
|
||||
#define BOARD_NAME "Olimex STM32-H103"
|
||||
|
||||
/*
|
||||
* Board frequencies.
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
#define HAVE_7SEGLED 1
|
||||
/*
|
||||
* Timer assignment for CIR
|
||||
*/
|
||||
#define TIMx TIM3
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
#define HAVE_7SEGLED 1
|
||||
/*
|
||||
* Timer assignment for CIR
|
||||
*/
|
||||
#define TIMx TIM3
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -10,3 +10,5 @@
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV4
|
||||
#define STM32_MCO STM32_MCO_NOCLOCK
|
||||
|
||||
#include "mcuconf-common.h"
|
||||
|
||||
@@ -56,6 +56,11 @@
|
||||
*/
|
||||
#define GPIOA_LED 8
|
||||
|
||||
/*
|
||||
* Timer assignment for CIR
|
||||
*/
|
||||
#define TIMx TIM3
|
||||
|
||||
/*
|
||||
* I/O ports initial setup, this configuration is established soon after reset
|
||||
* in the initialization code.
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
/*
|
||||
* ADC driver system settings.
|
||||
*/
|
||||
#define USE_STM32_ADC1 FALSE
|
||||
#define USE_STM32_ADC1 TRUE
|
||||
#define STM32_ADC1_DMA_PRIORITY 3
|
||||
#define STM32_ADC1_IRQ_PRIORITY 5
|
||||
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
|
||||
|
||||
47
doc/HACKING
47
doc/HACKING
@@ -1,17 +1,3 @@
|
||||
* [DONE] configure support
|
||||
|
||||
configure script would be good to select a board and to generate
|
||||
random serial number.
|
||||
|
||||
|
||||
* Random number update
|
||||
|
||||
Currently, Gnuk doesn't have random number generator, but use random
|
||||
bytes calculated by hosts. After Gnuk uses random number, the entry in
|
||||
Flash ROM will be cleared. Some scheme to update random number bytes
|
||||
is needed. Possibly, private Data Objects, or by another SELECT FILE.
|
||||
|
||||
|
||||
* Random Number Generator
|
||||
|
||||
RNG is needed for Data Encryption Key to encrypt private key (P and Q).
|
||||
@@ -24,21 +10,44 @@ be possible to get entropy from USB traffic (of other devices).
|
||||
It would be good not to use malloc.
|
||||
|
||||
|
||||
* Flash ROM recover from unexpected shutdown during write
|
||||
|
||||
|
||||
* [DONE] configure support
|
||||
|
||||
configure script would be good to select a board and to generate
|
||||
random serial number.
|
||||
|
||||
|
||||
* [DONE] Random number update
|
||||
|
||||
Implemented using SECECT_FILE and UPDATE_BINARY command, which is not
|
||||
in the OpenPGP card specification.
|
||||
|
||||
Old description: Currently, Gnuk doesn't have random number generator,
|
||||
but use random bytes calculated by hosts. After Gnuk uses random
|
||||
number, the entry in Flash ROM will be cleared. Some scheme to update
|
||||
random number bytes is needed. Possibly, private Data Objects, or by
|
||||
another SELECT FILE.
|
||||
|
||||
|
||||
* [DONE] Manufacture ID
|
||||
|
||||
Get it from FSFE.
|
||||
|
||||
|
||||
* [Mostly DONE] Serial number
|
||||
* [DONE] Serial number
|
||||
|
||||
The AID of the card contains serial number. It should be unique. USB
|
||||
serial number should be unique to identify different tokens, too.
|
||||
|
||||
|
||||
* Flash ROM recover from shutdown
|
||||
|
||||
|
||||
* [DONE] Flash ROM garbage collection
|
||||
|
||||
|
||||
* Flash ROM protection
|
||||
* [DONE] Flash ROM protection
|
||||
|
||||
Flash ROM can be protected with OpenOCD. DfuSe users should know that
|
||||
the content can be accessible by DfuSe, even if we enable read
|
||||
protection of flash ROM. For proper protection, don't use DfuSe but
|
||||
use OpenOCD to write and protect.
|
||||
|
||||
332
gnuk-sticker.svg
Normal file
332
gnuk-sticker.svg
Normal file
@@ -0,0 +1,332 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="248.03149"
|
||||
height="105.23622"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
enable-background="new"
|
||||
sodipodi:docname="gnuk-sticker.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4290">
|
||||
<stop
|
||||
style="stop-color:#000734;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4292" />
|
||||
<stop
|
||||
style="stop-color:#000734;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4294" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<inkscape:perspective
|
||||
id="perspective2884"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<filter
|
||||
height="1.2680969"
|
||||
y="-0.13404847"
|
||||
width="1.2847058"
|
||||
x="-0.1423529"
|
||||
id="filter0"
|
||||
inkscape:collect="always">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur0"
|
||||
stdDeviation="2.0538481"
|
||||
inkscape:collect="always" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
r="80"
|
||||
fy="440"
|
||||
fx="0"
|
||||
cy="440"
|
||||
cx="0"
|
||||
id="radialGradient1"
|
||||
xlink:href="#linearGradient1"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient1">
|
||||
<stop
|
||||
id="stop0"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#f8fcff;stop-opacity:1;"
|
||||
offset="0.0625"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#f0f8ff;stop-opacity:1;"
|
||||
offset="0.17166339"
|
||||
id="stop2" />
|
||||
<stop
|
||||
style="stop-color:#ecf4ff;stop-opacity:1;"
|
||||
offset="0.30279359"
|
||||
id="stop3" />
|
||||
<stop
|
||||
id="stop4"
|
||||
offset="0.5"
|
||||
style="stop-color:#e8f0ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e0ecff;stop-opacity:1;"
|
||||
offset="0.65893352"
|
||||
id="stop5" />
|
||||
<stop
|
||||
style="stop-color:#d8e8ff;stop-opacity:1;"
|
||||
offset="0.83552629"
|
||||
id="stop6" />
|
||||
<stop
|
||||
id="stop7"
|
||||
offset="1"
|
||||
style="stop-color:#d0e0ff;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.75369458,-1.760006,108.15135)"
|
||||
r="201.5"
|
||||
fy="750"
|
||||
fx="450"
|
||||
cy="750"
|
||||
cx="450"
|
||||
id="radialGradient0"
|
||||
xlink:href="#linearGradient0"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient0">
|
||||
<stop
|
||||
id="stop3620"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#c8c8e0;stop-opacity:1;"
|
||||
offset="0.07"
|
||||
id="stop3632" />
|
||||
<stop
|
||||
style="stop-color:#9696c8;stop-opacity:1;"
|
||||
offset="0.17"
|
||||
id="stop3630" />
|
||||
<stop
|
||||
style="stop-color:#6464b4;stop-opacity:1;"
|
||||
offset="0.33"
|
||||
id="stop3628" />
|
||||
<stop
|
||||
id="stop3634"
|
||||
offset="0.5"
|
||||
style="stop-color:#3232a0;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#282898;stop-opacity:1;"
|
||||
offset="0.66"
|
||||
id="stop3636" />
|
||||
<stop
|
||||
style="stop-color:#1e1e90;stop-opacity:1;"
|
||||
offset="0.85"
|
||||
id="stop3626" />
|
||||
<stop
|
||||
id="stop3622"
|
||||
offset="1"
|
||||
style="stop-color:#000088;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
id="perspective10-5"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3830"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter3875">
|
||||
<feBlend
|
||||
inkscape:collect="always"
|
||||
mode="screen"
|
||||
in2="BackgroundImage"
|
||||
id="feBlend3877" />
|
||||
</filter>
|
||||
<inkscape:perspective
|
||||
id="perspective3903"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4290"
|
||||
id="linearGradient4296"
|
||||
x1="85.996228"
|
||||
y1="1031.615"
|
||||
x2="240.89818"
|
||||
y2="1031.615"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="157.8139"
|
||||
inkscape:cy="53.468164"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
objecttolerance="10000"
|
||||
guidetolerance="10000"
|
||||
inkscape:window-width="1271"
|
||||
inkscape:window-height="718"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-947.12595)"
|
||||
style="display:inline"
|
||||
sodipodi:insensitive="true">
|
||||
<rect
|
||||
style="fill:#d9fffe;fill-opacity:1;stroke:none"
|
||||
id="rect0"
|
||||
width="248.19862"
|
||||
height="105.23622"
|
||||
x="0"
|
||||
y="947.12598" />
|
||||
<line id="line0"
|
||||
x1="0" y1="947.12598" x2="20" y2="947.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line1"
|
||||
x1="248.19862" y1="947.12598" x2="248.19862" y2="957.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line2"
|
||||
x1="248.19862" y1="1052.3622" x2="228.19862" y2="1052.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line3"
|
||||
x1="0" y1="1052.3622" x2="0" y2="1042.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<image
|
||||
y="951.12598"
|
||||
x="202.27382"
|
||||
id="image2886"
|
||||
height="28.346457"
|
||||
width="41.757679"
|
||||
xlink:href="FSIJ-s.png" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:52.27830124px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#032b7f;fill-opacity:1;stroke:none;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch Bold"
|
||||
x="94.433884"
|
||||
y="1014.9048"
|
||||
id="text2890"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2892"
|
||||
x="94.433884"
|
||||
y="1014.9048">GNUK</tspan></text>
|
||||
<g
|
||||
transform="matrix(-0.1014557,0,0,0.1014557,90.73972,926.6016)"
|
||||
id="layer1-6"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
id="path0"
|
||||
transform="matrix(-1.76,0,0,1.76,410,560)"
|
||||
d="m 0,0 c 0,0 0,0 -76,0 0,0 -8,-9 -12,-12 -18,-15 -48,-48 -36,-84 4,-14 12,-36 12,-36 -10,6 -50,26 -66,54 -8,16 -18,30 -18,54 0,24 25,100 48,108 0,0 0,0 150,0 0,0 0,0 150,0 23,-8 48,-84 48,-108 0,-24 -10,-38 -18,-54 -16,-28 -46,-48 -66,-54 0,0 8,22 12,36 12,36 -18,69 -36,84 C 88,-9 80,0 80,0 z"
|
||||
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:2.29999995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccscccscccccc"
|
||||
id="path0-9"
|
||||
d="m 411.01194,560.94628 c 0,0 0,0 133.76,0 0,0 14.08,-15.84 21.12,-21.12 31.68,-26.4 84.48,-84.48 63.36,-147.84 -7.04,-24.64 -21.12,-63.36 -21.12,-63.36 17.6,10.56 38,45.76 66.16,95.04 14.08,28.16 19.18,52.8 19.18,95.04 0,42.24 -44,176 -84.48,190.08 0,0 62.5,0 -201.5,0 0,0 62.5,0 -201.5,0 -40.48,-14.08 -84.48,-147.84 -84.48,-190.08 0,-42.24 5.1,-66.88 19.18,-95.04 28.16,-49.28 30.96,-84.48 66.16,-95.04 0,0 -14.08,38.72 -21.12,63.36 -21.12,63.36 31.68,121.44 63.36,147.84 7.04,5.28 21.12,21.12 21.12,21.12 z"
|
||||
style="fill:#000040;fill-opacity:1;stroke:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path1"
|
||||
d="m 409.21999,592 c 0,0 90,0 90,-33 0,-20 -4,-28 -12,-40 -5,-8 -8,-18 -8,-28 -1,-13 -1,-20 8,-36 6,-9 8,-23 5,-33 -5,-14 -19,-23 -33,-25 -16,-5 -35,-4 -50,-5 -15,1 -34,0 -50,5 -14,2 -28,9 -33,25 -3,10 1,24 5,33 9,16 9,23 8,36 0,10 -3,20 -8,28 -8,12 -12,20 -12,40 0,33 90,33 90,33 z"
|
||||
style="fill:#c0c0fd;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
transform="matrix(-0.75,0,0,0.8,410,100)"
|
||||
id="path1-1"
|
||||
d="m 0,592 c 0,0 -90,0 -90,-33 0,-20 4,-28 12,-40 5,-8 8,-18 8,-28 1,-13 1,-20 -8,-36 -6,-9 -8,-23 -5,-33 5,-14 19,-23 33,-25 16,-5 35,-4 50,-5 15,1 34,0 50,5 14,2 28,9 33,25 3,10 -1,24 -5,33 -9,16 -9,23 -8,36 0,10 3,20 8,28 8,12 12,20 12,40 0,33 -90,33 -90,33 z"
|
||||
style="fill:url(#radialGradient1);fill-opacity:1;fill-rule:evenodd;stroke:#d0e0ff;stroke-width:10px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
id="path1-2"
|
||||
d="m 344.11439,411.54794 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,949.00681,5.38669)"
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
id="path1-3"
|
||||
d="m 474.68123,406.16125 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2"
|
||||
d="M 236.90125,452.90625 C 135.34805,496.35376 97.060607,634.496 151.37,761.4375 c 50.02335,116.92341 158.1859,159.40625 257.75,159.40625 99.5641,0 207.72665,-42.48284 257.75,-159.40625 C 721.17939,634.496 682.89195,496.35376 581.33875,452.90625 526.07714,429.26367 466.8919,524.375 409.12,524.375 c -57.7719,0 -116.77668,-94.67646 -172.21875,-71.46875 z"
|
||||
style="fill:#afcfff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 538.23999,720 a 130,150 0 0 1 -260,0 130,150 0 1 1 260,0 z"
|
||||
id="path3"
|
||||
style="fill:url(#radialGradient0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4"
|
||||
d="m 538.30032,722.21875 c 56.32313,26.16396 100.82185,68.68738 119.76563,119.4375 33.50451,82.59901 -5.55269,179.72665 -93.67188,230.71875 -89.66782,55.4574 -224.43374,55.4574 -314.10156,0 -88.11919,-50.9921 -127.13733,-148.11974 -93.63281,-230.71875 18.61816,-50.41349 63.06491,-92.92973 119.25781,-119.1875 11.1304,10.32118 18.58377,23.0939 22.34375,36.6875 -5.94376,3.59375 -11.63988,7.47175 -16.99219,11.625 -73.95399,55.19241 -81.85302,155.28934 -18.59375,218.125 47.75721,51.30795 139.68,72.55545 213.4375,46.68755 87.41094,-28.2229 135.47694,-110.93384 113.94531,-183.2813 -9.09953,-36.85675 -36.47131,-70.33241 -73.67187,-92.96875 2.51871,-9.1715 6.69761,-18.00492 12.57812,-26 2.55237,-3.99852 5.70954,-7.71801 9.33594,-11.125 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4.47213602px;stroke-opacity:1" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:18px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:85.00000238%;writing-mode:lr-tb;text-anchor:start;fill:#120054;fill-opacity:1;stroke:none;display:inline;font-family:Gentium Basic;-inkscape-font-specification:Gentium Basic Bold Italic"
|
||||
x="98.368591"
|
||||
y="1038.1145"
|
||||
id="text3817"
|
||||
sodipodi:linespacing="85.000002%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4288"
|
||||
style="fill:#120054;fill-opacity:1"
|
||||
x="98.368591"
|
||||
y="1038.1145">GnuPG USB Token</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
553
gnuk-stickers.svg
Normal file
553
gnuk-stickers.svg
Normal file
@@ -0,0 +1,553 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
id="svg3961"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="gnuk-sticers.svg">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3967" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="1031.615"
|
||||
x2="240.89818"
|
||||
y1="1031.615"
|
||||
x1="85.996228"
|
||||
id="linearGradient4296"
|
||||
xlink:href="#linearGradient4290"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective3903" />
|
||||
<filter
|
||||
id="filter3875"
|
||||
inkscape:collect="always">
|
||||
<feBlend
|
||||
id="feBlend3877"
|
||||
in2="BackgroundImage"
|
||||
mode="screen"
|
||||
inkscape:collect="always" />
|
||||
</filter>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective3830" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10-5" />
|
||||
<linearGradient
|
||||
id="linearGradient0">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3620" />
|
||||
<stop
|
||||
id="stop3632"
|
||||
offset="0.07"
|
||||
style="stop-color:#c8c8e0;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3630"
|
||||
offset="0.17"
|
||||
style="stop-color:#9696c8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3628"
|
||||
offset="0.33"
|
||||
style="stop-color:#6464b4;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3232a0;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop3634" />
|
||||
<stop
|
||||
id="stop3636"
|
||||
offset="0.66"
|
||||
style="stop-color:#282898;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3626"
|
||||
offset="0.85"
|
||||
style="stop-color:#1e1e90;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000088;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3622" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient0"
|
||||
id="radialGradient0"
|
||||
cx="450"
|
||||
cy="750"
|
||||
fx="450"
|
||||
fy="750"
|
||||
r="201.5"
|
||||
gradientTransform="matrix(1,0,0,0.75369458,-1.760006,108.15135)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient1">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop0" />
|
||||
<stop
|
||||
id="stop1"
|
||||
offset="0.0625"
|
||||
style="stop-color:#f8fcff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2"
|
||||
offset="0.17166339"
|
||||
style="stop-color:#f0f8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3"
|
||||
offset="0.30279359"
|
||||
style="stop-color:#ecf4ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e8f0ff;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop4" />
|
||||
<stop
|
||||
id="stop5"
|
||||
offset="0.65893352"
|
||||
style="stop-color:#e0ecff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6"
|
||||
offset="0.83552629"
|
||||
style="stop-color:#d8e8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#d0e0ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop7" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="radialGradient1"
|
||||
cx="0"
|
||||
cy="440"
|
||||
fx="0"
|
||||
fy="440"
|
||||
r="80"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter0"
|
||||
x="-0.1423529"
|
||||
width="1.2847058"
|
||||
y="-0.13404847"
|
||||
height="1.2680969">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="2.0538481"
|
||||
id="feGaussianBlur0" />
|
||||
</filter>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective2884" />
|
||||
<inkscape:perspective
|
||||
id="perspective10"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
id="linearGradient4290"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4292"
|
||||
offset="0"
|
||||
style="stop-color:#000734;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4294"
|
||||
offset="1"
|
||||
style="stop-color:#000734;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:document-units="mm"
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="-75.714286"
|
||||
inkscape:cy="520"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1122"
|
||||
inkscape:window-height="692"
|
||||
inkscape:window-x="150"
|
||||
inkscape:window-y="51"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(0.5,-946.62598)"
|
||||
id="layer1-63"
|
||||
inkscape:label="Layer1"
|
||||
inkscape:tile-cx="124.59931"
|
||||
inkscape:tile-cy="53.118107"
|
||||
inkscape:tile-w="248.19862"
|
||||
inkscape:tile-h="105.23622"
|
||||
inkscape:tile-x0="0.5"
|
||||
inkscape:tile-y0="0.49999656">
|
||||
<rect
|
||||
y="947.12598"
|
||||
x="0"
|
||||
height="105.23622"
|
||||
width="248.19862"
|
||||
id="rect0"
|
||||
style="fill:#d9fffe;fill-opacity:1;stroke:none" />
|
||||
<line id="line0"
|
||||
x1="0" y1="947.12598" x2="20" y2="947.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line1"
|
||||
x1="248.19862" y1="947.12598" x2="248.19862" y2="957.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line2"
|
||||
x1="248.19862" y1="1052.3622" x2="228.19862" y2="1052.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line3"
|
||||
x1="0" y1="1052.3622" x2="0" y2="1042.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<image
|
||||
xlink:href="FSIJ-s.png"
|
||||
width="41.757679"
|
||||
height="28.346457"
|
||||
id="image2886"
|
||||
x="202.27382"
|
||||
y="951.12598" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2890"
|
||||
y="1014.9048"
|
||||
x="94.433884"
|
||||
style="font-size:52.27830124px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#032b7f;fill-opacity:1;stroke:none;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="1014.9048"
|
||||
x="94.433884"
|
||||
id="tspan2892"
|
||||
sodipodi:role="line">GNUK</tspan></text>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-6"
|
||||
transform="matrix(-0.1014557,0,0,0.1014557,90.73972,926.6016)">
|
||||
<path
|
||||
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:2.29999995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,0 c 0,0 0,0 -76,0 0,0 -8,-9 -12,-12 -18,-15 -48,-48 -36,-84 4,-14 12,-36 12,-36 -10,6 -50,26 -66,54 -8,16 -18,30 -18,54 0,24 25,100 48,108 0,0 0,0 150,0 0,0 0,0 150,0 23,-8 48,-84 48,-108 0,-24 -10,-38 -18,-54 -16,-28 -46,-48 -66,-54 0,0 8,22 12,36 12,36 -18,69 -36,84 C 88,-9 80,0 80,0 z"
|
||||
transform="matrix(-1.76,0,0,1.76,410,560)"
|
||||
id="path0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000040;fill-opacity:1;stroke:none"
|
||||
d="m 411.01194,560.94628 c 0,0 0,0 133.76,0 0,0 14.08,-15.84 21.12,-21.12 31.68,-26.4 84.48,-84.48 63.36,-147.84 -7.04,-24.64 -21.12,-63.36 -21.12,-63.36 17.6,10.56 38,45.76 66.16,95.04 14.08,28.16 19.18,52.8 19.18,95.04 0,42.24 -44,176 -84.48,190.08 0,0 62.5,0 -201.5,0 0,0 62.5,0 -201.5,0 -40.48,-14.08 -84.48,-147.84 -84.48,-190.08 0,-42.24 5.1,-66.88 19.18,-95.04 28.16,-49.28 30.96,-84.48 66.16,-95.04 0,0 -14.08,38.72 -21.12,63.36 -21.12,63.36 31.68,121.44 63.36,147.84 7.04,5.28 21.12,21.12 21.12,21.12 z"
|
||||
id="path0-9"
|
||||
sodipodi:nodetypes="ccccccscccscccccc" />
|
||||
<path
|
||||
style="fill:#c0c0fd;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 409.21999,592 c 0,0 90,0 90,-33 0,-20 -4,-28 -12,-40 -5,-8 -8,-18 -8,-28 -1,-13 -1,-20 8,-36 6,-9 8,-23 5,-33 -5,-14 -19,-23 -33,-25 -16,-5 -35,-4 -50,-5 -15,1 -34,0 -50,5 -14,2 -28,9 -33,25 -3,10 1,24 5,33 9,16 9,23 8,36 0,10 -3,20 -8,28 -8,12 -12,20 -12,40 0,33 90,33 90,33 z"
|
||||
id="path1" />
|
||||
<path
|
||||
style="fill:url(#radialGradient1);fill-opacity:1;fill-rule:evenodd;stroke:#d0e0ff;stroke-width:10px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,592 c 0,0 -90,0 -90,-33 0,-20 4,-28 12,-40 5,-8 8,-18 8,-28 1,-13 1,-20 -8,-36 -6,-9 -8,-23 -5,-33 5,-14 19,-23 33,-25 16,-5 35,-4 50,-5 15,1 34,0 50,5 14,2 28,9 33,25 3,10 -1,24 -5,33 -9,16 -9,23 -8,36 0,10 3,20 8,28 8,12 12,20 12,40 0,33 -90,33 -90,33 z"
|
||||
id="path1-1"
|
||||
transform="matrix(-0.75,0,0,0.8,410,100)" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 344.11439,411.54794 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-2"
|
||||
sodipodi:nodetypes="ccccsc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 474.68123,406.16125 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-3"
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
transform="matrix(-1,0,0,1,949.00681,5.38669)" />
|
||||
<path
|
||||
style="fill:#afcfff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 236.90125,452.90625 C 135.34805,496.35376 97.060607,634.496 151.37,761.4375 c 50.02335,116.92341 158.1859,159.40625 257.75,159.40625 99.5641,0 207.72665,-42.48284 257.75,-159.40625 C 721.17939,634.496 682.89195,496.35376 581.33875,452.90625 526.07714,429.26367 466.8919,524.375 409.12,524.375 c -57.7719,0 -116.77668,-94.67646 -172.21875,-71.46875 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#radialGradient0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3"
|
||||
d="m 538.23999,720 a 130,150 0 0 1 -260,0 130,150 0 1 1 260,0 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4.47213602px;stroke-opacity:1"
|
||||
d="m 538.30032,722.21875 c 56.32313,26.16396 100.82185,68.68738 119.76563,119.4375 33.50451,82.59901 -5.55269,179.72665 -93.67188,230.71875 -89.66782,55.4574 -224.43374,55.4574 -314.10156,0 -88.11919,-50.9921 -127.13733,-148.11974 -93.63281,-230.71875 18.61816,-50.41349 63.06491,-92.92973 119.25781,-119.1875 11.1304,10.32118 18.58377,23.0939 22.34375,36.6875 -5.94376,3.59375 -11.63988,7.47175 -16.99219,11.625 -73.95399,55.19241 -81.85302,155.28934 -18.59375,218.125 47.75721,51.30795 139.68,72.55545 213.4375,46.68755 87.41094,-28.2229 135.47694,-110.93384 113.94531,-183.2813 -9.09953,-36.85675 -36.47131,-70.33241 -73.67187,-92.96875 2.51871,-9.1715 6.69761,-18.00492 12.57812,-26 2.55237,-3.99852 5.70954,-7.71801 9.33594,-11.125 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<text
|
||||
sodipodi:linespacing="85.000002%"
|
||||
id="text3817"
|
||||
y="1038.1145"
|
||||
x="98.368591"
|
||||
style="font-size:18px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:85.00000238%;writing-mode:lr-tb;text-anchor:start;fill:#120054;fill-opacity:1;stroke:none;display:inline;font-family:Gentium Basic;-inkscape-font-specification:Gentium Basic Bold Italic"
|
||||
xml:space="preserve"><tspan
|
||||
y="1038.1145"
|
||||
x="98.368591"
|
||||
style="fill:#120054;fill-opacity:1"
|
||||
id="tspan4288"
|
||||
sodipodi:role="line">GnuPG USB Token</tspan></text>
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
id="use4758" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,105.23622)"
|
||||
id="use4760" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,210.47244)"
|
||||
id="use4762" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,315.70866)"
|
||||
id="use4764" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,420.94489)"
|
||||
id="use4766" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,526.18111)"
|
||||
id="use4768" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,631.41733)"
|
||||
id="use4770" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,736.65355)"
|
||||
id="use4772" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,841.88977)"
|
||||
id="use4774" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,947.12599)"
|
||||
id="use4776" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,0)"
|
||||
id="use4778" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,105.23622)"
|
||||
id="use4780" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,210.47244)"
|
||||
id="use4782" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,315.70866)"
|
||||
id="use4784" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,420.94489)"
|
||||
id="use4786" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,526.18111)"
|
||||
id="use4788" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,631.41733)"
|
||||
id="use4790" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,736.65355)"
|
||||
id="use4792" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,841.88977)"
|
||||
id="use4794" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,947.12599)"
|
||||
id="use4796" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,0)"
|
||||
id="use4798" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,105.23622)"
|
||||
id="use4800" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,210.47244)"
|
||||
id="use4802" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,315.70866)"
|
||||
id="use4804" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,420.94489)"
|
||||
id="use4806" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,526.18111)"
|
||||
id="use4808" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,631.41733)"
|
||||
id="use4810" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,736.65355)"
|
||||
id="use4812" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,841.88977)"
|
||||
id="use4814" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,947.12599)"
|
||||
id="use4816" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 20 KiB |
224
gnuk.svg
224
gnuk.svg
@@ -1,25 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<!-- Manually edited using GNU Emacs -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1052.3622"
|
||||
height="744.09448"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
sodipodi:docname="gnuk.svg"
|
||||
inkscape:export-filename="gnuk.png"
|
||||
inkscape:export-xdpi="30"
|
||||
inkscape:export-ydpi="30">
|
||||
<defs
|
||||
id="defs4">
|
||||
id="defs0">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
@@ -27,27 +28,110 @@
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<inkscape:perspective
|
||||
id="perspective2830"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3627"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3682"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
id="linearGradient0">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3620" />
|
||||
<stop
|
||||
id="stop3632"
|
||||
offset="0.07"
|
||||
style="stop-color:#c8c8e0;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3630"
|
||||
offset="0.17"
|
||||
style="stop-color:#9696c8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3628"
|
||||
offset="0.33"
|
||||
style="stop-color:#6464b4;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3232a0;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop3634" />
|
||||
<stop
|
||||
id="stop3636"
|
||||
offset="0.66"
|
||||
style="stop-color:#282898;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3626"
|
||||
offset="0.85"
|
||||
style="stop-color:#1e1e90;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000088;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3622" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient0"
|
||||
id="radialGradient0"
|
||||
cx="450"
|
||||
cy="750"
|
||||
fx="450"
|
||||
fy="750"
|
||||
r="201.5"
|
||||
gradientTransform="matrix(1,0,0,0.75369458,-1.760006,108.15135)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient1">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop0" />
|
||||
<stop
|
||||
id="stop1"
|
||||
offset="0.0625"
|
||||
style="stop-color:#f8fcff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2"
|
||||
offset="0.17166339"
|
||||
style="stop-color:#f0f8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3"
|
||||
offset="0.30279359"
|
||||
style="stop-color:#ecf4ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e8f0ff;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop4" />
|
||||
<stop
|
||||
id="stop5"
|
||||
offset="0.65893352"
|
||||
style="stop-color:#e0ecff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6"
|
||||
offset="0.83552629"
|
||||
style="stop-color:#d8e8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#d0e0ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop7" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="radialGradient1"
|
||||
cx="0"
|
||||
cy="440"
|
||||
fx="0"
|
||||
fy="440"
|
||||
r="80"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,1,0,0)" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter0"
|
||||
x="-0.1423529"
|
||||
width="1.2847058"
|
||||
y="-0.13404847"
|
||||
height="1.2680969">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="2.0538481"
|
||||
id="feGaussianBlur0" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@@ -57,7 +141,7 @@
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.70032923"
|
||||
inkscape:cx="487.47769"
|
||||
inkscape:cx="47.684539"
|
||||
inkscape:cy="434.02158"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
@@ -68,10 +152,10 @@
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:window-width="876"
|
||||
inkscape:window-height="747"
|
||||
inkscape:window-x="29"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-width="1014"
|
||||
inkscape:window-height="703"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
@@ -82,14 +166,14 @@
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
id="metadata0">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@@ -97,50 +181,52 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-308.2677)">
|
||||
transform="matrix(-0.80,0,0,0.80,650,-250)">
|
||||
<path
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 726.1305,600.36218 c 22.86832,-8.30901 48,-83.66895 48,-108 0,-24.33105 -10.30662,-51.88803 -24,-72 -13.12651,-19.27938 -60,-36 -60,-36 0,0 7.82067,22.19662 12,36 0,36 -37.18539,69.08582 -36,84 -4.37468,3.58638 -12,12 -12,12 -26.07681,26.07681 37.33885,96.59384 72,84 z"
|
||||
id="path3672-0"
|
||||
sodipodi:nodetypes="cssccccc" />
|
||||
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:2.3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,0 c 0,0 0,0 -76,0 0,0 -8,-9 -12,-12 -18,-15 -48,-48 -36,-84 4,-14 12,-36 12,-36 -10,6 -50,26 -66,54 -8,16 -18,30 -18,54 0,24 25,100 48,108 0,0 0,0 150,0 0,0 0,0 150,0 23,-8 48,-84 48,-108 0,-24 -10,-38 -18,-54 -16,-28 -46,-48 -66,-54 0,0 8,22 12,36 12,36 -18,69 -36,84 -4,3 -12,12 -12,12 z"
|
||||
transform="matrix(-1.76,0,0,1.76,410,560)"
|
||||
id="path0" />
|
||||
<path
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 204,600.36218 c -22.86832,-8.30901 -48,-83.66895 -48,-108 0,-24.33105 10.30662,-51.88803 24,-72 13.12651,-19.27938 60,-36 60,-36 0,0 -7.82067,22.19662 -12,36 0,36 37.18539,69.08582 36,84 4.37468,3.58638 12,12 12,12 26.07681,26.07681 -37.33885,96.59384 -72,84 z"
|
||||
id="path3672"
|
||||
sodipodi:nodetypes="cssccccc" />
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000040;fill-opacity:1;stroke:none"
|
||||
d="m 411.01194,560.94628 c 0,0 0,0 133.76,0 0,0 14.08,-15.84 21.12,-21.12 31.68,-26.4 84.48,-84.48 63.36,-147.84 -7.04,-24.64 -21.12,-63.36 -21.12,-63.36 17.6,10.56 38,45.76 66.16,95.04 14.08,28.16 19.18,52.8 19.18,95.04 0,42.24 -44,176 -84.48,190.08 0,0 62.5,0 -201.5,0 0,0 62.5,0 -201.5,0 -40.48,-14.08 -84.48,-147.84 -84.48,-190.08 0,-42.24 5.1,-66.88 19.18,-95.04 28.16,-49.28 30.96,-84.48 66.16,-95.04 0,0 -14.08,38.72 -21.12,63.36 -21.12,63.36 31.68,121.44 63.36,147.84 7.04,5.28 21.12,21.12 21.12,21.12 z"
|
||||
id="path0-9"
|
||||
sodipodi:nodetypes="ccccccscccscccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 387.06525,552.36218 c -10.14964,-12.99942 9.9849,-31.63115 12,-48 1.4662,-11.91009 2.75704,-24.32101 0,-36 -2.05497,-8.705 -9.94503,-15.295 -12,-24 -1.83802,-7.78599 -3.06147,-16.60896 0,-24 4.32957,-10.4525 13.5475,-19.67043 24,-24 33.25966,-13.7766 74.74034,-13.7766 108,0 10.4525,4.32957 19.67043,13.5475 24,24 3.06147,7.39104 1.83802,16.21401 0,24 -2.05497,8.705 -9.94503,15.295 -12,24 -2.75704,11.67899 -1.4662,24.08991 0,36 2.0151,16.36885 22.14964,35.00058 12,48 -32.00143,40.98668 -123.99857,40.98668 -156,0 z"
|
||||
id="path3670"
|
||||
sodipodi:nodetypes="caaaaaaaaaaaa" />
|
||||
style="fill:#c0c0fd;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 409.21999,592 c 0,0 90,0 90,-33 0,-20 -4,-28 -12,-40 -5,-8 -8,-18 -8,-28 -1,-13 -1,-20 8,-36 6,-9 8,-23 5,-33 -5,-14 -19,-23 -33,-25 -16,-5 -35,-4 -50,-5 -15,1 -34,0 -50,5 -14,2 -28,9 -33,25 -3,10 1,24 5,33 9,16 9,23 8,36 0,10 -3,20 -8,28 -8,12 -12,20 -12,40 0,33 90,33 90,33 z"
|
||||
id="path1" />
|
||||
<path
|
||||
style="fill:#ffffaf;fill-opacity:1;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 245.06525,436.36218 c -56.01988,12.27447 -95.51412,82.82688 -100,140 -4.6642,59.44578 23.48729,132.68883 70,170 64.3239,51.59881 167.53789,100 250,100 82.46211,0 185.6761,-48.40119 250,-100 46.51271,-37.31117 74.6642,-110.55422 70,-170 -4.48588,-57.17312 -43.98012,-127.72553 -100,-140 -52.50286,-11.50385 -90.127,59.96073 -140,80 -25.50547,10.24825 -52.51263,20 -80,20 -27.48737,0 -54.49453,-9.75175 -80,-20 -49.873,-20.03927 -87.49714,-91.50385 -140,-80 z"
|
||||
id="path2818"
|
||||
sodipodi:nodetypes="cssssssssss" />
|
||||
style="fill:url(#radialGradient1);fill-opacity:1;fill-rule:evenodd;stroke:#d0e0ff;stroke-width:10px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,592 c 0,0 -90,0 -90,-33 0,-20 4,-28 12,-40 5,-8 8,-18 8,-28 1,-13 1,-20 -8,-36 -6,-9 -8,-23 -5,-33 5,-14 19,-23 33,-25 16,-5 35,-4 50,-5 15,1 34,0 50,5 14,2 28,9 33,25 3,10 -1,24 -5,33 -9,16 -9,23 -8,36 0,10, 3,20 8,28 8,12 12,20 12,40 0,33 -90,33 -90,33 z"
|
||||
id="path1-1"
|
||||
transform="matrix(-0.75,0,0,0.8,410,100)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path2820"
|
||||
sodipodi:cx="480"
|
||||
sodipodi:cy="439.09448"
|
||||
sodipodi:rx="100"
|
||||
sodipodi:ry="75"
|
||||
d="m 580,439.09448 a 100,75 0 1 1 -200,0 100,75 0 1 1 200,0 z"
|
||||
transform="matrix(1.2,0,0,1,-108.71875,242.2677)" />
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 344.11439,411.54794 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-2"
|
||||
sodipodi:nodetypes="ccccsc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 468,683.55419 c -53.26272,0 -106.28935,23.67472 -145.72074,52.16211 -28.99055,20.94434 -50.12608,50.68828 -58.27926,81.16082 -10.16321,37.98504 -13.76535,84.29391 14.55851,115.9237 40.35231,45.0621 119.89779,69.56138 189.44149,69.56138 69.5437,0 149.08918,-24.49928 189.44149,-69.56138 C 685.76535,901.17103 682.16321,854.86216 672,816.87712 663.84682,786.40458 642.71129,756.66064 613.72074,735.7163 574.28935,707.22891 521.26272,683.55419 468,683.55419 z m -1.4468,22.772 c 45.32995,0 90.45998,19.43946 124.01861,42.83981 24.67281,17.20427 42.65953,41.61266 49.59841,66.64368 8.64953,31.20197 11.71709,69.26937 -12.38832,95.251 -34.34241,37.01536 -102.04258,57.14346 -161.2287,57.14346 -59.18615,0 -126.88629,-20.1281 -161.22873,-57.14346 -24.1054,-25.98163 -21.03783,-64.04903 -12.3883,-95.251 6.93887,-25.03102 24.92559,-49.43941 49.5984,-66.64368 33.55865,-23.40035 78.68865,-42.83981 124.01863,-42.83981 z"
|
||||
id="path2844" />
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 474.68123,406.16125 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-3"
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
transform="matrix(-1,0,0,1,949.00681,5.38669)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:3px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path2820-4"
|
||||
sodipodi:cx="480"
|
||||
sodipodi:cy="439.09448"
|
||||
sodipodi:rx="100"
|
||||
sodipodi:ry="75"
|
||||
d="m 580,439.09448 a 100,75 0 1 1 -200,0 100,75 0 1 1 200,0 z"
|
||||
transform="matrix(1.2,0,0,1,-108.71875,256.2677)" />
|
||||
style="fill:#afcfff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 236.90125,452.90625 C 135.34805,496.35376 97.060607,634.496 151.37,761.4375 c 50.02335,116.92341 158.1859,159.40625 257.75,159.40625 99.5641,0 207.72665,-42.48284 257.75,-159.40625 C 721.17939,634.496 682.89195,496.35376 581.33875,452.90625 526.07714,429.26367 466.8919,524.375 409.12,524.375 c -57.7719,0 -116.77668,-94.67646 -172.21875,-71.46875 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#radialGradient0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3"
|
||||
d="m 538.23999,720 a 130,150 0 0 1 -260,0 130,150 0 1 1 260,0 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4.47213602px;stroke-opacity:1"
|
||||
d="m 538.30032,722.21875 c 56.32313,26.16396 100.82185,68.68738 119.76563,119.4375 33.50451,82.59901 -5.55269,179.72665 -93.67188,230.71875 -89.66782,55.4574 -224.43374,55.4574 -314.10156,0 -88.11919,-50.9921 -127.13733,-148.11974 -93.63281,-230.71875 18.61816,-50.41349 63.06491,-92.92973 119.25781,-119.1875 11.1304,10.32118 18.58377,23.0939 22.34375,36.6875 -5.94376,3.59375 -11.63988,7.47175 -16.99219,11.625 -73.95399,55.19241 -81.85302,155.28934 -18.59375,218.125 47.75721,51.30795 139.68,72.55545 213.4375,46.68755 87.41094,-28.2229 135.47694,-110.93384 113.94531,-183.2813 -9.09953,-36.85675 -36.47131,-70.33241 -73.67187,-92.96875 2.51871,-9.1715 6.69761,-18.00492 12.57812,-26 2.55237,-3.99852 5.70954,-7.71801 9.33594,-11.125 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 10 KiB |
@@ -495,27 +495,130 @@
|
||||
#endif /* TriCore */
|
||||
|
||||
#if defined(__arm__)
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %0!, { r5, r6, r7 } \n" \
|
||||
"ldmia %1, { r8, r9, r10 } \n" \
|
||||
"umull r11, r12, %2, r5 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r8, r8, r11 \n" \
|
||||
"umull r11, r12, %2, r6 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r9, r9, r11 \n" \
|
||||
"umull r11, r12, %2, r7 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r10, r10, r11 \n" \
|
||||
"stmia %1!, { r8, r9, r10 } \n"
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm( "ldr r0, %0 " :: "m" (s)); \
|
||||
asm( "ldr r1, %0 " :: "m" (d)); \
|
||||
asm( "ldr r2, %0 " :: "m" (c)); \
|
||||
asm( "ldr r3, %0 " :: "m" (b));
|
||||
#define MULADDC_1024_LOOP \
|
||||
asm( "tst %4, #0xfe0 \n" \
|
||||
"beq 0f \n" \
|
||||
"1: sub %4, %4, #32 \n" \
|
||||
"ldmia %0!, { r5, r6, r7 } \n" \
|
||||
"ldmia %1, { r8, r9, r10 } \n" \
|
||||
"umull r11, r12, %2, r5 \n" \
|
||||
"adds r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r8, r8, r11 \n" \
|
||||
"umull r11, r12, %2, r6 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r9, r9, r11 \n" \
|
||||
"umull r11, r12, %2, r7 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r10, r10, r11 \n" \
|
||||
"stmia %1!, { r8, r9, r10 } \n" \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE \
|
||||
"ldmia %0!, { r5, r6 } \n" \
|
||||
"ldmia %1, { r8, r9 } \n" \
|
||||
"umull r11, r12, %2, r5 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r8, r8, r11 \n" \
|
||||
"umull r11, r12, %2, r6 \n" \
|
||||
"adcs r11, r11, %3 \n" \
|
||||
"adc %3, r12, #0 \n" \
|
||||
"adds r9, r9, r11 \n" \
|
||||
"stmia %1!, { r8, r9 } \n" \
|
||||
"adc %3, %3, #0 \n" \
|
||||
"tst %4, #0xfe0 \n" \
|
||||
"bne 1b \n" \
|
||||
"0:" \
|
||||
: "=r" (s), "=r" (d), "=r" (b), "=r" (c), "=r" (i) \
|
||||
: "0" (s), "1" (d), "2" (b), "3" (c), "4" (i) \
|
||||
: "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory", "cc" );
|
||||
|
||||
#define MULADDC_CORE \
|
||||
asm( "ldr r4, [r0], #4 " ); \
|
||||
asm( "mov r5, #0 " ); \
|
||||
asm( "ldr r6, [r1] " ); \
|
||||
asm( "umlal r2, r5, r3, r4 " ); \
|
||||
asm( "adds r7, r6, r2 " ); \
|
||||
asm( "adc r2, r5, #0 " ); \
|
||||
asm( "str r7, [r1], #4 " );
|
||||
/* Just for reference (dead code) */
|
||||
#define MULADDC_HUIT \
|
||||
"ldmia %0!, { r4, r5 } \n" \
|
||||
"ldmia %1, { r8, r9 } \n" \
|
||||
"umull r6, r7, %2, r4 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r8, r8, r6 \n" \
|
||||
"umull r6, r7, %2, r5 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r9, r9, r6 \n" \
|
||||
"stmia %1!, { r8, r9 } \n" \
|
||||
"ldmia %0!, { r4, r5 } \n" \
|
||||
"ldmia %1, { r8, r9 } \n" \
|
||||
"umull r6, r7, %2, r4 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r8, r8, r6 \n" \
|
||||
"umull r6, r7, %2, r5 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r9, r9, r6 \n" \
|
||||
"stmia %1!, { r8, r9 } \n" \
|
||||
"ldmia %0!, { r4, r5 } \n" \
|
||||
"ldmia %1, { r8, r9 } \n" \
|
||||
"umull r6, r7, %2, r4 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r8, r8, r6 \n" \
|
||||
"umull r6, r7, %2, r5 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r9, r9, r6 \n" \
|
||||
"stmia %1!, { r8, r9 } \n" \
|
||||
"ldmia %0!, { r4, r5 } \n" \
|
||||
"ldmia %1, { r8, r9 } \n" \
|
||||
"umull r6, r7, %2, r4 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r8, r8, r6 \n" \
|
||||
"umull r6, r7, %2, r5 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r9, r9, r6 \n" \
|
||||
"stmia %1!, { r8, r9 } \n"
|
||||
|
||||
#define MULADDC_STOP \
|
||||
asm( "str r2, %0 " : "=m" (c)); \
|
||||
asm( "str r1, %0 " : "=m" (d)); \
|
||||
asm( "str r0, %0 " : "=m" (s) :: \
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
|
||||
#define MULADDC_INIT \
|
||||
asm( "adds %0, #0 \n"
|
||||
|
||||
#define MULADDC_CORE \
|
||||
"ldr r5, [%1] \n" \
|
||||
"ldr r4, [%0], #4 \n" \
|
||||
"umull r6, r7, %2, r4 \n" \
|
||||
"adcs r6, r6, %3 \n" \
|
||||
"adc %3, r7, #0 \n" \
|
||||
"adds r5, r5, r6 \n" \
|
||||
"str r5, [%1], #4 \n"
|
||||
|
||||
#define MULADDC_STOP \
|
||||
"adc %3, %3, #0 " \
|
||||
: "=r" (s), "=r" (d), "=r" (b), "=r" (c) \
|
||||
: "0" (s), "1" (d), "2" (b), "3" (c) \
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc" );
|
||||
|
||||
#endif /* ARMv3 */
|
||||
|
||||
|
||||
@@ -894,7 +894,16 @@ static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
|
||||
{
|
||||
t_int c = 0, t = 0;
|
||||
|
||||
#if defined(MULADDC_HUIT)
|
||||
#if defined(MULADDC_1024_LOOP)
|
||||
MULADDC_1024_LOOP
|
||||
|
||||
for( ; i > 0; i-- )
|
||||
{
|
||||
MULADDC_INIT
|
||||
MULADDC_CORE
|
||||
MULADDC_STOP
|
||||
}
|
||||
#elif defined(MULADDC_HUIT)
|
||||
for( ; i >= 8; i -= 8 )
|
||||
{
|
||||
MULADDC_INIT
|
||||
|
||||
@@ -91,7 +91,7 @@ CSRC = $(PORTSRC) \
|
||||
main.c usb_lld.c \
|
||||
usb_desc.c usb_prop.c \
|
||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \
|
||||
random.c
|
||||
random.c neug.c
|
||||
|
||||
ifneq ($(ENABLE_DEBUG),)
|
||||
CSRC += debug.c
|
||||
@@ -205,9 +205,7 @@ ifeq ($(USE_FWLIB),yes)
|
||||
endif
|
||||
|
||||
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
|
||||
|
||||
random_bits:
|
||||
dd if=/dev/random bs=1 of=random_bits count=1024
|
||||
MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
|
||||
|
||||
distclean: clean
|
||||
-rm -f Makefile gnuk.ld config.h random_bits
|
||||
-rm -f Makefile gnuk.ld config.h
|
||||
|
||||
175
src/ac.c
175
src/ac.c
@@ -28,7 +28,7 @@
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
uint8_t volatile auth_status = AC_NONE_AUTHORIZED;
|
||||
uint8_t volatile auth_status; /* Initialized to AC_NONE_AUTHORIZED */
|
||||
|
||||
int
|
||||
ac_check_status (uint8_t ac_flag)
|
||||
@@ -56,71 +56,95 @@ ac_reset_other (void)
|
||||
auth_status &= ~AC_OTHER_AUTHORIZED;
|
||||
}
|
||||
|
||||
int
|
||||
verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw1)
|
||||
{
|
||||
int pw_len;
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
|
||||
if (gpg_pw_locked (PW_ERR_PW1))
|
||||
return 0;
|
||||
|
||||
if (ks_pw1 == NULL)
|
||||
{
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|
||||
goto failure;
|
||||
else
|
||||
goto success_one_step;
|
||||
}
|
||||
else
|
||||
pw_len = ks_pw1[0];
|
||||
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len)
|
||||
{
|
||||
failure:
|
||||
gpg_pw_increment_err_counter (PW_ERR_PW1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
success_one_step:
|
||||
sha1 (pw, pw_len, keystring);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring))
|
||||
< 0)
|
||||
goto failure;
|
||||
else if (r == 0)
|
||||
if (ks_pw1 != NULL && memcmp (ks_pw1+1, keystring, KEYSTRING_MD_SIZE) != 0)
|
||||
goto failure;
|
||||
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||
return pw_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify for "Perform Security Operation : Compute Digital Signature"
|
||||
*/
|
||||
int
|
||||
verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW1))
|
||||
return 0;
|
||||
|
||||
DEBUG_INFO ("verify_pso_cds\r\n");
|
||||
DEBUG_BYTE (pw_len);
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
|
||||
{
|
||||
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 1;
|
||||
r = verify_user_0 (pw, pw_len, pw_len, ks_pw1);
|
||||
if (r > 0)
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
verify_other (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
const uint8_t *ks_pw1;
|
||||
uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
|
||||
int r1, r2;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
|
||||
DEBUG_INFO ("verify_other\r\n");
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW1))
|
||||
if (gpg_pw_locked (PW_ERR_PW1))
|
||||
return 0;
|
||||
|
||||
ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
if ((ks_pw1 == NULL && pw_len == strlen (OPENPGP_CARD_INITIAL_PW1))
|
||||
|| (ks_pw1 != NULL && pw_len == ks_pw1[0]))
|
||||
{ /* No problem */
|
||||
pw1_keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, pw1_keystring+1);
|
||||
if (gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER,
|
||||
pw1_keystring + 1) < 0)
|
||||
goto error;
|
||||
|
||||
if (gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
|
||||
pw1_keystring + 1) < 0)
|
||||
goto error;
|
||||
|
||||
/* Reset counter as it's success now */
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
auth_status |= AC_OTHER_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
sha1 (pw, pw_len, keystring);
|
||||
if ((r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring)) < 0
|
||||
|| (r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
|
||||
keystring)) < 0)
|
||||
{
|
||||
error:
|
||||
gpg_increment_pw_err_counter (PW_ERR_PW1);
|
||||
return 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -148,7 +172,7 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
||||
count -= pw_len + 8;
|
||||
}
|
||||
|
||||
if (count < 8)
|
||||
if (count <= 8)
|
||||
sha1_update (&sha1_ctx, salt, count);
|
||||
else
|
||||
{
|
||||
@@ -161,15 +185,15 @@ calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
||||
memset (&sha1_ctx, 0, sizeof (sha1_ctx));
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
uint8_t admin_authorized;
|
||||
|
||||
int
|
||||
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
{
|
||||
const uint8_t *pw3_keystring;
|
||||
int pw_len;
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW3))
|
||||
return 0;
|
||||
|
||||
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
if (pw3_keystring != NULL)
|
||||
{
|
||||
@@ -177,6 +201,9 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
uint8_t md[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
|
||||
if (gpg_pw_locked (PW_ERR_PW3))
|
||||
return 0;
|
||||
|
||||
pw_len = pw3_keystring[0];
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
|
||||
goto failure;
|
||||
@@ -188,28 +215,45 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
|
||||
{
|
||||
failure:
|
||||
gpg_increment_pw_err_counter (PW_ERR_PW3);
|
||||
gpg_pw_increment_err_counter (PW_ERR_PW3);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
/* OK, the user is now authenticated */
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW3);
|
||||
|
||||
admin_authorized = BY_ADMIN;
|
||||
success: /* OK, the user is now authenticated */
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW3);
|
||||
return pw_len;
|
||||
}
|
||||
else
|
||||
/* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
|
||||
{
|
||||
if ((pw_len_known >=0
|
||||
&& pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3))
|
||||
|| buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3)
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3,
|
||||
strlen (OPENPGP_CARD_INITIAL_PW3)) != 0)
|
||||
/* It is failure, but we don't try to lock for the case of empty PW3 */
|
||||
return -1;
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (ks_pw1 != NULL)
|
||||
{ /* empty PW3, but PW1 exists */
|
||||
int r = verify_user_0 (pw, buf_len, pw_len_known, ks_pw1);
|
||||
|
||||
if (r > 0)
|
||||
admin_authorized = BY_USER;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (gpg_pw_locked (PW_ERR_PW3))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For the case of empty PW3 (with empty PW1), pass phrase
|
||||
* should be OPENPGP_CARD_INITIAL_PW3
|
||||
*/
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
}
|
||||
if ((pw_len_known >=0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
|
||||
goto failure;
|
||||
|
||||
return pw_len;
|
||||
admin_authorized = BY_ADMIN;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -219,9 +263,9 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
|
||||
uint32_t random;
|
||||
|
||||
ks[0] = newpw_len;
|
||||
random = get_random ();
|
||||
random = get_salt ();
|
||||
memcpy (&ks[1], &random, sizeof (random));
|
||||
random = get_random ();
|
||||
random = get_salt ();
|
||||
memcpy (&ks[5], &random, sizeof (random));
|
||||
ks[9] = 0x60; /* 65536 iterations */
|
||||
|
||||
@@ -229,8 +273,6 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
int
|
||||
verify_admin (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
@@ -255,8 +297,9 @@ ac_reset_admin (void)
|
||||
void
|
||||
ac_fini (void)
|
||||
{
|
||||
auth_status = AC_NONE_AUTHORIZED;
|
||||
memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE);
|
||||
gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING);
|
||||
gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
|
||||
gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
|
||||
auth_status = AC_NONE_AUTHORIZED;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -28,7 +28,9 @@
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
||||
#define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
|
||||
/* 256 byte == 2048-bit */
|
||||
/* 128 byte == 1024-bit */
|
||||
|
||||
static rsa_context rsa_ctx;
|
||||
|
||||
@@ -43,10 +45,10 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
mpi_init (&P1, &Q1, &H, NULL);
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
rsa_ctx.len = 2048 / 8;
|
||||
rsa_ctx.len = KEY_CONTENT_LEN;
|
||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], rsa_ctx.len / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2);
|
||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||
@@ -90,23 +92,25 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LEN: length in byte
|
||||
*/
|
||||
const uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
|
||||
(void)len; /* 2048-bit assumed */
|
||||
modulus = malloc (2048 / 8);
|
||||
modulus = malloc (len);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P, &Q, &N, NULL);
|
||||
mpi_read_binary (&P, p, 2048 / 8 / 2);
|
||||
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
|
||||
mpi_read_binary (&P, p, len / 2);
|
||||
mpi_read_binary (&Q, p + len / 2, len / 2);
|
||||
mpi_mul_mpi (&N, &P, &Q);
|
||||
|
||||
mpi_write_binary (&N, modulus, 2048 / 8);
|
||||
mpi_write_binary (&N, modulus, len);
|
||||
mpi_free (&P, &Q, &N, NULL);
|
||||
return modulus;
|
||||
}
|
||||
@@ -135,8 +139,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
DEBUG_WORD (msg_len);
|
||||
|
||||
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
||||
mpi_read_binary (&rsa_ctx.P, &kd->data[0], 2048 / 8 / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[128], 2048 / 8 / 2);
|
||||
mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2);
|
||||
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
|
||||
KEY_CONTENT_LEN / 2);
|
||||
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
||||
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
||||
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define CH_OPTIMIZE_SPEED TRUE
|
||||
#define CH_USE_REGISTRY TRUE
|
||||
#define CH_USE_WAITEXIT TRUE
|
||||
#define CH_USE_SEMAPHORES FALSE
|
||||
#define CH_USE_SEMAPHORES TRUE
|
||||
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
||||
#define CH_USE_SEMSW FALSE
|
||||
#define CH_USE_MUTEXES TRUE
|
||||
|
||||
@@ -5,7 +5,3 @@
|
||||
@DFU_DEFINE@
|
||||
@PINPAD_DEFINE@
|
||||
@PINPAD_MORE_DEFINE@
|
||||
|
||||
#if !defined(__ASSEMBLER__)
|
||||
extern const unsigned char *unique_device_id (void);
|
||||
#endif
|
||||
|
||||
56
src/flash.c
56
src/flash.c
@@ -24,9 +24,9 @@
|
||||
/*
|
||||
* We assume single DO size is less than 256.
|
||||
*
|
||||
* NOTE: When we will support "Card holder certificate" (which size is
|
||||
* larger than 256), it is not put into data pool, but is
|
||||
* implemented by its own flash page(s).
|
||||
* NOTE: "Card holder certificate" (which size is larger than 256) is
|
||||
* not put into data pool, but is implemented by its own flash
|
||||
* page(s).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -46,7 +46,7 @@ enum flash_status
|
||||
FLASH_TIMEOUT
|
||||
};
|
||||
|
||||
static void
|
||||
void
|
||||
flash_unlock (void)
|
||||
{
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
@@ -143,14 +143,16 @@ flash_erase_page (uint32_t addr)
|
||||
* .dtors
|
||||
* _etext
|
||||
* .data
|
||||
* ...
|
||||
* _etext + (_edata - _data)
|
||||
*
|
||||
* flash-page-size align padding
|
||||
*
|
||||
* flash-page-size data pool * 2
|
||||
*
|
||||
* 1.5-KiB Key store (512-byte (p, q and N) key-store * 3)
|
||||
* _bss_start
|
||||
* .bss
|
||||
* _end
|
||||
* <alignment to page>
|
||||
* ch_certificate_startp
|
||||
* <2048 bytes>
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
* _keystore_pool
|
||||
* 1.5-KiB Key store (512-byte (p, q and N) key-store * 3)
|
||||
*/
|
||||
#define FLASH_DATA_POOL_HEADER_SIZE 2
|
||||
#if defined(STM32F10X_HD)
|
||||
@@ -162,7 +164,7 @@ flash_erase_page (uint32_t addr)
|
||||
#define FLASH_KEYSTORE_SIZE (512*3)
|
||||
|
||||
static const uint8_t *data_pool;
|
||||
static const uint8_t *keystore_pool;
|
||||
extern uint8_t _keystore_pool;
|
||||
|
||||
static uint8_t *last_p;
|
||||
static const uint8_t *keystore;
|
||||
@@ -179,7 +181,6 @@ const uint8_t *
|
||||
flash_init (void)
|
||||
{
|
||||
const uint8_t *p;
|
||||
extern uint8_t _keystore_pool;
|
||||
uint16_t gen0, gen1;
|
||||
uint16_t *gen0_p = (uint16_t *)&_data_pool;
|
||||
uint16_t *gen1_p = (uint16_t *)(&_data_pool + FLASH_PAGE_SIZE);
|
||||
@@ -196,16 +197,13 @@ flash_init (void)
|
||||
else
|
||||
data_pool = &_data_pool;
|
||||
|
||||
keystore_pool = &_keystore_pool;
|
||||
|
||||
/* Seek empty keystore */
|
||||
p = keystore_pool;
|
||||
p = &_keystore_pool;
|
||||
while (*p != 0xff || *(p+1) != 0xff)
|
||||
p += 512;
|
||||
|
||||
keystore = p;
|
||||
|
||||
flash_unlock ();
|
||||
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
}
|
||||
|
||||
@@ -384,7 +382,7 @@ flash_key_alloc (void)
|
||||
{
|
||||
uint8_t *k = (uint8_t *)keystore;
|
||||
|
||||
if ((k - keystore_pool) >= FLASH_KEYSTORE_SIZE)
|
||||
if ((k - &_keystore_pool) >= FLASH_KEYSTORE_SIZE)
|
||||
return NULL;
|
||||
|
||||
keystore += 512;
|
||||
@@ -422,11 +420,11 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
void
|
||||
flash_keystore_release (void)
|
||||
{
|
||||
flash_erase_page ((uint32_t)keystore_pool);
|
||||
flash_erase_page ((uint32_t)&_keystore_pool);
|
||||
#if FLASH_KEYSTORE_SIZE > FLASH_PAGE_SIZE
|
||||
flash_erase_page ((uint32_t)keystore_pool + FLASH_PAGE_SIZE);
|
||||
flash_erase_page ((uint32_t)&_keystore_pool + FLASH_PAGE_SIZE);
|
||||
#endif
|
||||
keystore = keystore_pool;
|
||||
keystore = &_keystore_pool;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -613,15 +611,6 @@ flash_erase_binary (uint8_t file_id)
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (file_id == FILEID_RANDOM)
|
||||
{
|
||||
p = &random_bits_start;
|
||||
|
||||
if (flash_check_blank (p, FLASH_PAGE_SIZE) == 0)
|
||||
flash_erase_page ((uint32_t)p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@@ -641,11 +630,6 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
maxsize = FLASH_CH_CERTIFICATE_SIZE;
|
||||
p = &ch_certificate_start;
|
||||
}
|
||||
else if (file_id == FILEID_RANDOM)
|
||||
{
|
||||
maxsize = FLASH_PAGE_SIZE;
|
||||
p = &random_bits_start;
|
||||
}
|
||||
else if (file_id == FILEID_SERIAL_NO)
|
||||
{
|
||||
maxsize = 6;
|
||||
|
||||
46
src/gnuk.h
46
src/gnuk.h
@@ -72,13 +72,15 @@ extern volatile uint8_t auth_status;
|
||||
#define PW_ERR_PW1 0
|
||||
#define PW_ERR_RC 1
|
||||
#define PW_ERR_PW3 2
|
||||
extern int gpg_passwd_locked (uint8_t which);
|
||||
extern void gpg_reset_pw_err_counter (uint8_t which);
|
||||
extern void gpg_increment_pw_err_counter (uint8_t which);
|
||||
extern int gpg_pw_locked (uint8_t which);
|
||||
extern void gpg_pw_reset_err_counter (uint8_t which);
|
||||
extern void gpg_pw_increment_err_counter (uint8_t which);
|
||||
|
||||
extern int ac_check_status (uint8_t ac_flag);
|
||||
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
||||
extern int verify_other (const uint8_t *pw, int pw_len);
|
||||
extern int verify_user_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw1);
|
||||
extern int verify_admin (const uint8_t *pw, int pw_len);
|
||||
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known);
|
||||
|
||||
@@ -88,9 +90,8 @@ extern void ac_reset_admin (void);
|
||||
extern void ac_fini (void);
|
||||
|
||||
|
||||
extern void write_res_apdu (const uint8_t *p, int len,
|
||||
uint8_t sw1, uint8_t sw2);
|
||||
uint16_t data_objects_number_of_bytes;
|
||||
extern void set_res_apdu (uint8_t sw1, uint8_t sw2);
|
||||
extern uint16_t data_objects_number_of_bytes;
|
||||
|
||||
extern void gpg_data_scan (const uint8_t *p);
|
||||
extern void gpg_data_copy (const uint8_t *p);
|
||||
@@ -106,6 +107,7 @@ enum kind_of_key {
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
};
|
||||
|
||||
extern void flash_unlock (void);
|
||||
extern const uint8_t *flash_init (void);
|
||||
extern void flash_do_release (const uint8_t *);
|
||||
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||
@@ -122,7 +124,7 @@ extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
extern int flash_erase_binary (uint8_t file_id);
|
||||
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
||||
|
||||
/* Linker set this symbol */
|
||||
/* Linker set these two symbols */
|
||||
extern uint8_t ch_certificate_start;
|
||||
extern uint8_t random_bits_start;
|
||||
|
||||
@@ -133,6 +135,10 @@ extern uint8_t random_bits_start;
|
||||
/* encrypted data content */
|
||||
struct key_data {
|
||||
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
|
||||
};
|
||||
|
||||
struct key_data_internal {
|
||||
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
|
||||
uint32_t check;
|
||||
uint32_t random;
|
||||
char magic[KEY_MAGIC_LEN];
|
||||
@@ -143,7 +149,7 @@ struct key_data {
|
||||
struct prvkey_data {
|
||||
const uint8_t *key_addr;
|
||||
/*
|
||||
* CRM: [C]heck, [R]andom, and [M]agic in struct key_data
|
||||
* CRM: [C]heck, [R]andom, and [M]agic in struct key_data_internal
|
||||
*
|
||||
*/
|
||||
uint8_t crm_encrypted[ADDITIONAL_DATA_SIZE];
|
||||
@@ -211,6 +217,7 @@ extern void fatal (uint8_t code) __attribute__ ((noreturn));
|
||||
#define FATAL_RANDOM 2
|
||||
|
||||
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
extern uint8_t admin_authorized;
|
||||
|
||||
/*** Flash memory tag values ***/
|
||||
#define NR_NONE 0x00
|
||||
@@ -285,10 +292,12 @@ extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
#define SIZE_PW_STATUS_BYTES 7
|
||||
|
||||
/* 32-byte random bytes */
|
||||
extern uint32_t get_random (void);
|
||||
extern void random_init (void);
|
||||
/* 16-byte random bytes */
|
||||
extern const uint8_t *random_bytes_get (void);
|
||||
extern void random_bytes_free (const uint8_t *);
|
||||
/* 4-byte salt */
|
||||
extern uint32_t get_salt (void);
|
||||
|
||||
extern uint32_t hardclock (void);
|
||||
|
||||
@@ -308,8 +317,6 @@ extern uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
|
||||
|
||||
extern const uint8_t openpgpcard_aid[14];
|
||||
|
||||
extern int gpg_get_pw1_lifetime (void);
|
||||
|
||||
extern void flash_bool_clear (const uint8_t **addr_p);
|
||||
extern const uint8_t *flash_bool_write (uint8_t nr);
|
||||
extern int flash_cnt123_get_value (const uint8_t *p);
|
||||
@@ -323,6 +330,18 @@ extern void flash_bool_write_internal (const uint8_t *p, int nr);
|
||||
extern void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
|
||||
extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
|
||||
|
||||
extern const unsigned char *unique_device_id (void);
|
||||
extern const uint8_t gnukStringSerial[];
|
||||
|
||||
#define LED_ONESHOT_SHORT ((eventmask_t)1)
|
||||
#define LED_ONESHOT_LONG ((eventmask_t)2)
|
||||
#define LED_TWOSHOT ((eventmask_t)4)
|
||||
#define LED_STATUS_MODE ((eventmask_t)8)
|
||||
#define LED_INPUT_MODE ((eventmask_t)16)
|
||||
#define LED_FATAL_MODE ((eventmask_t)32)
|
||||
extern Thread *main_thread;
|
||||
extern void led_blink (int spec);
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
#if defined(PINPAD_CIR_SUPPORT)
|
||||
extern void cir_ext_disable (void);
|
||||
@@ -338,5 +357,6 @@ extern void dial_sw_enable (void);
|
||||
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||
extern uint8_t pin_input_len;
|
||||
|
||||
extern msg_t pin_main (void *arg);
|
||||
extern int pinpad_getline (int msg_code, systime_t timeout);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0400;
|
||||
__stacks_total_size__ = __main_stack_size__;
|
||||
__process_stack_size__ = 0x0200;
|
||||
__stacks_total_size__ = __main_stack_size__ + __process_stack_size__;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
@@ -114,18 +115,11 @@ SECTIONS
|
||||
PROVIDE(end = .);
|
||||
_end = .;
|
||||
|
||||
.gnuk_random :
|
||||
{
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
random_bits_start = .;
|
||||
. += 1;
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
} > flash =0xffffffff
|
||||
|
||||
.gnuk_ch_certificate :
|
||||
{
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
ch_certificate_start = .;
|
||||
LONG(0xffffffff);
|
||||
. += 1920;
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
} > flash =0xffffffff
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "mcuconf.h"
|
||||
|
||||
#define CH_HAL_USE_PAL TRUE
|
||||
#define CH_HAL_USE_ADC FALSE
|
||||
#define CH_HAL_USE_ADC TRUE
|
||||
#define CH_HAL_USE_CAN FALSE
|
||||
#define CH_HAL_USE_MAC FALSE
|
||||
#define CH_HAL_USE_PWM FALSE
|
||||
|
||||
315
src/main.c
315
src/main.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* main.c - main routine of Gnuk
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -164,8 +164,193 @@ extern msg_t USBthread (void *arg);
|
||||
#define LED_TIMEOUT_STOP MS2ST(500)
|
||||
|
||||
|
||||
#define ID_OFFSET 12
|
||||
static void
|
||||
device_initialize_once (void)
|
||||
{
|
||||
const uint8_t *p = &gnukStringSerial[ID_OFFSET];
|
||||
|
||||
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
|
||||
{
|
||||
/*
|
||||
* This is the first time invocation.
|
||||
* Setup serial number by unique device ID.
|
||||
*/
|
||||
const uint8_t *u = unique_device_id ();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
uint8_t b = u[i];
|
||||
uint8_t nibble;
|
||||
|
||||
nibble = (b >> 4);
|
||||
nibble += (nibble >= 10 ? ('A' - 10) : '0');
|
||||
flash_put_data_internal (&p[i*4], nibble);
|
||||
nibble = (b & 0x0f);
|
||||
nibble += (nibble >= 10 ? ('A' - 10) : '0');
|
||||
flash_put_data_internal (&p[i*4+2], nibble);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static volatile uint8_t fatal_code;
|
||||
|
||||
Thread *main_thread;
|
||||
|
||||
#define GNUK_INIT 0
|
||||
#define GNUK_RUNNING 1
|
||||
#define GNUK_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.
|
||||
*
|
||||
@@ -180,8 +365,13 @@ main (int argc, char **argv)
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
main_thread = chThdSelf ();
|
||||
|
||||
flash_unlock ();
|
||||
device_initialize_once ();
|
||||
usb_lld_init ();
|
||||
USB_Init();
|
||||
USB_Init ();
|
||||
random_init ();
|
||||
|
||||
#ifdef DEBUG
|
||||
stdout_init ();
|
||||
@@ -198,105 +388,47 @@ main (int argc, char **argv)
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
count++;
|
||||
|
||||
if (fatal_code != 0)
|
||||
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL);
|
||||
switch (m)
|
||||
{
|
||||
case LED_STATUS_MODE:
|
||||
main_mode = GNUK_RUNNING;
|
||||
break;
|
||||
case LED_FATAL_MODE:
|
||||
main_mode = GNUK_FATAL;
|
||||
break;
|
||||
case LED_INPUT_MODE:
|
||||
main_mode = GNUK_INPUT_WAIT;
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
chThdSleep (MS2ST (400));
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_STOP);
|
||||
set_led (1);
|
||||
if (fatal_code & 1)
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
else
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
if (fatal_code & 2)
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
else
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_STOP);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bDeviceState != CONFIGURED)
|
||||
switch (main_mode)
|
||||
{
|
||||
case GNUK_FATAL:
|
||||
display_fatal_code ();
|
||||
break;
|
||||
case GNUK_INIT:
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||
}
|
||||
else
|
||||
/* Device configured */
|
||||
if (icc_state == ICC_STATE_START)
|
||||
{
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||
}
|
||||
else
|
||||
/* GPGthread running */
|
||||
{
|
||||
set_led (1);
|
||||
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
else
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
else
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
else
|
||||
chThdSleep (LED_TIMEOUT_ZERO);
|
||||
|
||||
if (icc_state == ICC_STATE_WAIT)
|
||||
{
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_STOP * 2);
|
||||
}
|
||||
else if (icc_state == ICC_STATE_RECEIVE)
|
||||
{
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_ONE);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_STOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
set_led (1);
|
||||
chThdSleep (LED_TIMEOUT_STOP);
|
||||
set_led (0);
|
||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GNUK_INPUT_WAIT:
|
||||
display_interaction ();
|
||||
break;
|
||||
case GNUK_RUNNING:
|
||||
default:
|
||||
display_status_code ();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
if (bDeviceState == CONFIGURED && (count % 10) == 0)
|
||||
@@ -316,6 +448,7 @@ void
|
||||
fatal (uint8_t code)
|
||||
{
|
||||
fatal_code = code;
|
||||
chEvtSignal (main_thread, LED_FATAL_MODE);
|
||||
_write ("fatal\r\n", 7);
|
||||
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);
|
||||
177
src/openpgp-do.c
177
src/openpgp-do.c
@@ -32,71 +32,26 @@
|
||||
#include "polarssl/aes.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
static uint32_t digital_signature_counter;
|
||||
|
||||
static const uint8_t *
|
||||
gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc)
|
||||
{
|
||||
uint16_t hw0, hw1;
|
||||
|
||||
if ((dsc >> 10) == 0)
|
||||
{ /* no upper bits */
|
||||
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
|
||||
flash_put_data_internal (p, hw1);
|
||||
return p+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
|
||||
hw1 = NR_COUNTER_DS_LSB;
|
||||
flash_put_data_internal (p, hw0);
|
||||
flash_put_data_internal (p+2, hw1);
|
||||
return p+4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gpg_increment_digital_signature_counter (void)
|
||||
{
|
||||
uint16_t hw0, hw1;
|
||||
uint32_t dsc = (digital_signature_counter + 1) & 0x00ffffff;
|
||||
|
||||
if ((dsc & 0x03ff) == 0)
|
||||
{ /* carry occurs from l10 to h14 */
|
||||
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
|
||||
hw1 = NR_COUNTER_DS_LSB; /* zero */
|
||||
flash_put_data (hw0);
|
||||
flash_put_data (hw1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
|
||||
flash_put_data (hw1);
|
||||
}
|
||||
|
||||
digital_signature_counter = dsc;
|
||||
}
|
||||
|
||||
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
|
||||
static const uint8_t *pw_err_counter_p[3];
|
||||
|
||||
static int
|
||||
gpg_get_pw_err_counter (uint8_t which)
|
||||
gpg_pw_get_err_counter (uint8_t which)
|
||||
{
|
||||
return flash_cnt123_get_value (pw_err_counter_p[which]);
|
||||
}
|
||||
|
||||
int
|
||||
gpg_passwd_locked (uint8_t which)
|
||||
gpg_pw_locked (uint8_t which)
|
||||
{
|
||||
if (gpg_get_pw_err_counter (which) >= PASSWORD_ERRORS_MAX)
|
||||
if (gpg_pw_get_err_counter (which) >= PASSWORD_ERRORS_MAX)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gpg_reset_pw_err_counter (uint8_t which)
|
||||
gpg_pw_reset_err_counter (uint8_t which)
|
||||
{
|
||||
flash_cnt123_clear (&pw_err_counter_p[which]);
|
||||
if (pw_err_counter_p[which] != NULL)
|
||||
@@ -104,7 +59,7 @@ gpg_reset_pw_err_counter (uint8_t which)
|
||||
}
|
||||
|
||||
void
|
||||
gpg_increment_pw_err_counter (uint8_t which)
|
||||
gpg_pw_increment_err_counter (uint8_t which)
|
||||
{
|
||||
flash_cnt123_increment (which, &pw_err_counter_p[which]);
|
||||
}
|
||||
@@ -173,7 +128,8 @@ static const uint8_t algorithm_attr[] __attribute__ ((aligned (1))) = {
|
||||
* in flash memory
|
||||
*/
|
||||
static const uint8_t *pw1_lifetime_p;
|
||||
int
|
||||
|
||||
static int
|
||||
gpg_get_pw1_lifetime (void)
|
||||
{
|
||||
if (pw1_lifetime_p == NULL)
|
||||
@@ -182,6 +138,56 @@ gpg_get_pw1_lifetime (void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t digital_signature_counter;
|
||||
|
||||
static const uint8_t *
|
||||
gpg_write_digital_signature_counter (const uint8_t *p, uint32_t dsc)
|
||||
{
|
||||
uint16_t hw0, hw1;
|
||||
|
||||
if ((dsc >> 10) == 0)
|
||||
{ /* no upper bits */
|
||||
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
|
||||
flash_put_data_internal (p, hw1);
|
||||
return p+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
|
||||
hw1 = NR_COUNTER_DS_LSB;
|
||||
flash_put_data_internal (p, hw0);
|
||||
flash_put_data_internal (p+2, hw1);
|
||||
return p+4;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gpg_increment_digital_signature_counter (void)
|
||||
{
|
||||
uint16_t hw0, hw1;
|
||||
uint32_t dsc = (digital_signature_counter + 1) & 0x00ffffff;
|
||||
|
||||
if ((dsc & 0x03ff) == 0)
|
||||
{ /* carry occurs from l10 to h14 */
|
||||
hw0 = NR_COUNTER_DS | ((dsc & 0xfc0000) >> 18) | ((dsc & 0x03fc00) >> 2);
|
||||
hw1 = NR_COUNTER_DS_LSB; /* zero */
|
||||
flash_put_data (hw0);
|
||||
flash_put_data (hw1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hw1 = NR_COUNTER_DS_LSB | ((dsc & 0x0300) >> 8) | ((dsc & 0x00ff) << 8);
|
||||
flash_put_data (hw1);
|
||||
}
|
||||
|
||||
digital_signature_counter = dsc;
|
||||
|
||||
if (gpg_get_pw1_lifetime () == 0)
|
||||
ac_reset_pso_cds ();
|
||||
}
|
||||
|
||||
|
||||
#define SIZE_FINGER_PRINT 20
|
||||
#define SIZE_KEYGEN_TIME 4 /* RFC4880 */
|
||||
|
||||
@@ -502,9 +508,9 @@ rw_pw_status (uint16_t tag, int with_tag,
|
||||
*res_p++ = PW_LEN_MAX;
|
||||
*res_p++ = PW_LEN_MAX;
|
||||
*res_p++ = PW_LEN_MAX;
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_PW1);
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_RC);
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_get_pw_err_counter (PW_ERR_PW3);
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW1);
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_RC);
|
||||
*res_p++ = PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW3);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -525,8 +531,8 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
newpw = data;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (BY_ADMIN, old_ks, BY_RESETCODE, new_ks);
|
||||
if (r < -2)
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
return 0;
|
||||
@@ -547,7 +553,7 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, 1);
|
||||
}
|
||||
|
||||
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||
gpg_pw_reset_err_counter (PW_ERR_RC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -619,23 +625,31 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||
uint8_t *key_addr;
|
||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||
struct key_data_internal kdi;
|
||||
|
||||
DEBUG_INFO ("Loading private key: ");
|
||||
DEBUG_BYTE (kk);
|
||||
|
||||
if (do_data == NULL)
|
||||
return 0;
|
||||
|
||||
key_addr = *(uint8_t **)&(do_data)[1];
|
||||
memcpy (kd[kk].data, key_addr, KEY_CONTENT_LEN);
|
||||
memcpy (((uint8_t *)&kd[kk].check), do_data+5, ADDITIONAL_DATA_SIZE);
|
||||
memcpy (dek, do_data+5+16*who, DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (kdi.data, key_addr, KEY_CONTENT_LEN);
|
||||
memcpy (((uint8_t *)&kdi.check), do_data+5, ADDITIONAL_DATA_SIZE);
|
||||
|
||||
memcpy (dek, do_data+5+16*who, DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt (keystring, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt (dek, (uint8_t *)&kd[kk], sizeof (struct key_data));
|
||||
if (memcmp (kd[kk].magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
|
||||
|
||||
decrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
||||
if (memcmp (kdi.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
|
||||
{
|
||||
DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
/* more sanity check??? */
|
||||
|
||||
memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -656,7 +670,7 @@ static int8_t num_prv_keys;
|
||||
|
||||
static int
|
||||
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *keystring)
|
||||
const uint8_t *keystring_admin)
|
||||
{
|
||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||
const uint8_t *p;
|
||||
@@ -668,6 +682,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *do_data = do_ptr[nr - NR_DO__FIRST__];
|
||||
const uint8_t *ks_pw1;
|
||||
const uint8_t *ks_rc;
|
||||
struct key_data_internal kdi;
|
||||
|
||||
#if 0
|
||||
assert (key_len == KEY_CONTENT_LEN);
|
||||
@@ -703,10 +718,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
DEBUG_INFO ("key_addr: ");
|
||||
DEBUG_WORD ((uint32_t)key_addr);
|
||||
|
||||
memcpy (kd[kk].data, key_data, KEY_CONTENT_LEN);
|
||||
kd[kk].check = calc_check32 (key_data, KEY_CONTENT_LEN);
|
||||
kd[kk].random = get_random ();
|
||||
memcpy (kd[kk].magic, GNUK_MAGIC, KEY_MAGIC_LEN);
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
kdi.check = calc_check32 (key_data, KEY_CONTENT_LEN);
|
||||
kdi.random = get_salt ();
|
||||
memcpy (kdi.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
|
||||
|
||||
dek = random_bytes_get (); /* 16-byte random bytes */
|
||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
@@ -715,9 +730,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
|
||||
encrypt (dek, (uint8_t *)&kd[kk], sizeof (struct key_data));
|
||||
encrypt (dek, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
||||
|
||||
r = flash_key_write (key_addr, kd[kk].data, modulus);
|
||||
r = flash_key_write (key_addr, kdi.data, modulus);
|
||||
modulus_free (modulus);
|
||||
|
||||
if (r < 0)
|
||||
@@ -728,7 +743,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
}
|
||||
|
||||
pd->key_addr = key_addr;
|
||||
memcpy (pd->crm_encrypted, (uint8_t *)&kd[kk].check, ADDITIONAL_DATA_SIZE);
|
||||
memcpy (pd->crm_encrypted, (uint8_t *)&kdi.check, ADDITIONAL_DATA_SIZE);
|
||||
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
ac_reset_pso_cds ();
|
||||
@@ -752,7 +767,10 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
else
|
||||
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
||||
if (keystring_admin)
|
||||
encrypt (keystring_admin, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
||||
else
|
||||
memset (pd->dek_encrypted_3, 0, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_ptr[nr - NR_DO__FIRST__] = p;
|
||||
@@ -834,6 +852,12 @@ proc_key_import (const uint8_t *data, int len)
|
||||
{
|
||||
int r;
|
||||
enum kind_of_key kk;
|
||||
const uint8_t *keystring_admin;
|
||||
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
else
|
||||
keystring_admin = NULL;
|
||||
|
||||
DEBUG_BINARY (data, len);
|
||||
|
||||
@@ -869,7 +893,7 @@ proc_key_import (const uint8_t *data, int len)
|
||||
|
||||
/* It should starts with 00 01 00 01 (E) */
|
||||
/* Skip E, 4-byte */
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_md_pw3);
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
else
|
||||
@@ -941,8 +965,8 @@ gpg_do_table[] = {
|
||||
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||
proc_key_import },
|
||||
#if 0
|
||||
/* Card holder certificate */
|
||||
{ GPG_DO_CH_CERTIFICATE, DO_PROC_READ, AC_ALWAYS, AC_NEVER, NULL },
|
||||
/* Card holder certificate is handled in special way, as its size is big */
|
||||
{ GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1050,6 +1074,11 @@ gpg_data_scan (const uint8_t *p_start)
|
||||
digital_signature_counter = (dsc_h14 << 10) | dsc_l10;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write all data to newly allocated Flash ROM page (from P_START),
|
||||
* updating PW1_LIFETIME_P, PW_ERR_COUNTER_P, and DO_PTR.
|
||||
* Called by flash_copying_gc.
|
||||
*/
|
||||
void
|
||||
gpg_data_copy (const uint8_t *p_start)
|
||||
{
|
||||
|
||||
118
src/openpgp.c
118
src/openpgp.c
@@ -62,13 +62,11 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
||||
};
|
||||
|
||||
void
|
||||
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
||||
set_res_apdu (uint8_t sw1, uint8_t sw2)
|
||||
{
|
||||
res_APDU_size = 2 + len;
|
||||
if (len)
|
||||
memcpy (res_APDU, p, len);
|
||||
res_APDU[len] = sw1;
|
||||
res_APDU[len+1] = sw2;
|
||||
res_APDU_size = 2;
|
||||
res_APDU[0] = sw1;
|
||||
res_APDU[1] = sw2;
|
||||
}
|
||||
|
||||
#define FILE_NONE 0
|
||||
@@ -99,24 +97,19 @@ gpg_fini (void)
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
/*
|
||||
* Invoke the thread PIN_MAIN, and let user input PIN string.
|
||||
* Let user input PIN string.
|
||||
* Return length of the string.
|
||||
* The string itself is in PIN_INPUT_BUFFER.
|
||||
*/
|
||||
static int
|
||||
get_pinpad_input (int msg_code)
|
||||
{
|
||||
Thread *t;
|
||||
int r;
|
||||
|
||||
t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
|
||||
NORMALPRIO, pin_main, (void *)msg_code);
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
chThdWait (t);
|
||||
return pin_input_len;
|
||||
}
|
||||
chEvtSignal (main_thread, LED_INPUT_MODE);
|
||||
r = pinpad_getline (msg_code, MS2ST (8000));
|
||||
chEvtSignal (main_thread, LED_STATUS_MODE);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -302,24 +295,24 @@ cmd_change_password (void)
|
||||
|
||||
if (who == BY_USER) /* PW1 */
|
||||
{
|
||||
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (pk == NULL)
|
||||
pw_len = verify_user_0 (pw, len, -1, ks_pw1);
|
||||
|
||||
if (pw_len < 0)
|
||||
{
|
||||
if (len < (int)strlen (OPENPGP_CARD_INITIAL_PW1))
|
||||
{
|
||||
DEBUG_INFO ("permission denied.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
DEBUG_INFO ("permission denied.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (pw_len == 0)
|
||||
{
|
||||
DEBUG_INFO ("blocked.\r\n");
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
pw_len = pk[0];
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
}
|
||||
@@ -353,7 +346,7 @@ cmd_change_password (void)
|
||||
new_ks0[0] = newpw_len;
|
||||
|
||||
r = gpg_change_keystring (who, old_ks, who, new_ks);
|
||||
if (r < -2)
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
@@ -368,7 +361,6 @@ cmd_change_password (void)
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -377,7 +369,6 @@ cmd_change_password (void)
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -385,7 +376,6 @@ cmd_change_password (void)
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_admin ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW3);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
@@ -466,7 +456,7 @@ cmd_reset_user_password (void)
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_RC))
|
||||
if (gpg_pw_locked (PW_ERR_RC))
|
||||
{
|
||||
DEBUG_INFO ("blocked.\r\n");
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
@@ -487,7 +477,7 @@ cmd_reset_user_password (void)
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
|
||||
if (r < -2)
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
@@ -496,7 +486,7 @@ cmd_reset_user_password (void)
|
||||
{
|
||||
sec_fail:
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
gpg_increment_pw_err_counter (PW_ERR_RC);
|
||||
gpg_pw_increment_err_counter (PW_ERR_RC);
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
@@ -508,8 +498,8 @@ cmd_reset_user_password (void)
|
||||
KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
gpg_pw_reset_err_counter (PW_ERR_RC);
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else
|
||||
@@ -517,8 +507,8 @@ cmd_reset_user_password (void)
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_RC);
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
gpg_pw_reset_err_counter (PW_ERR_RC);
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
@@ -537,8 +527,8 @@ cmd_reset_user_password (void)
|
||||
newpw = pw;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (BY_ADMIN, old_ks, BY_USER, new_ks);
|
||||
if (r < -2)
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
@@ -555,7 +545,7 @@ cmd_reset_user_password (void)
|
||||
KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else
|
||||
@@ -563,7 +553,7 @@ cmd_reset_user_password (void)
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_reset_pw_err_counter (PW_ERR_PW1);
|
||||
gpg_pw_reset_err_counter (PW_ERR_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
@@ -681,10 +671,14 @@ cmd_select_file (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
write_res_apdu (select_file_TOP_result,
|
||||
sizeof (select_file_TOP_result), 0x90, 0x00);
|
||||
int len = sizeof (select_file_TOP_result);
|
||||
|
||||
res_APDU_size = 2 + len;
|
||||
memcpy (res_APDU, select_file_TOP_result, len);
|
||||
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
||||
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
||||
res_APDU[len] = 0x90;
|
||||
res_APDU[len+1] = 0x00;
|
||||
}
|
||||
|
||||
file_selection = FILE_MF;
|
||||
@@ -727,6 +721,7 @@ cmd_pso (void)
|
||||
|
||||
DEBUG_INFO (" - PSO: ");
|
||||
DEBUG_WORD ((uint32_t)&r);
|
||||
DEBUG_BINARY (cmd_APDU, cmd_APDU_size);
|
||||
|
||||
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
|
||||
{
|
||||
@@ -752,6 +747,7 @@ cmd_pso (void)
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
||||
|
||||
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_SIGNING]);
|
||||
@@ -761,20 +757,16 @@ cmd_pso (void)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{ /* Success */
|
||||
if (gpg_get_pw1_lifetime () == 0)
|
||||
ac_reset_pso_cds ();
|
||||
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
}
|
||||
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW1)
|
||||
|| !ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
@@ -790,7 +782,7 @@ cmd_pso (void)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{ /* XXX: not yet supported */
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[2]);
|
||||
DEBUG_INFO (" - ??");
|
||||
@@ -820,8 +812,7 @@ cmd_internal_authenticate (void)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW1)
|
||||
|| !ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
@@ -862,7 +853,7 @@ cmd_update_binary (void)
|
||||
|
||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
@@ -933,7 +924,7 @@ cmd_write_binary (void)
|
||||
|
||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||
|
||||
if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
@@ -955,7 +946,7 @@ cmd_write_binary (void)
|
||||
{
|
||||
if (file_selection != FILE_EF_CH_CERTIFICATE
|
||||
&& file_selection != FILE_EF_RANDOM
|
||||
&& file_selection != FILEID_SERIAL_NO)
|
||||
&& file_selection != FILE_EF_SERIAL)
|
||||
{
|
||||
GPG_COMMAND_NOT_ALLOWED ();
|
||||
return;
|
||||
@@ -1035,12 +1026,9 @@ GPGthread (void *arg)
|
||||
|
||||
while (!chThdShouldTerminate ())
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
m = chEvtWaitOne (ALL_EVENTS);
|
||||
chEvtWaitOne (ALL_EVENTS);
|
||||
|
||||
DEBUG_INFO ("GPG!: ");
|
||||
DEBUG_WORD ((uint32_t)&m);
|
||||
|
||||
res_APDU_pointer = NULL; /* default */
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
|
||||
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
|
||||
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
|
||||
#define GPG_COMMAND_NOT_ALLOWED() write_res_apdu (NULL, 0, 0x69, 0x86)
|
||||
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
|
||||
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
|
||||
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
|
||||
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
|
||||
#define GPG_ERROR() write_res_apdu (NULL, 0, 0x6f, 0x00)
|
||||
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 0x00)
|
||||
#define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81)
|
||||
#define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82)
|
||||
#define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83)
|
||||
#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86)
|
||||
#define GPG_NO_FILE() set_res_apdu (0x6a, 0x82)
|
||||
#define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88)
|
||||
#define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00)
|
||||
#define GPG_NO_INS() set_res_apdu (0x6d, 0x00)
|
||||
#define GPG_ERROR() set_res_apdu (0x6f, 0x00)
|
||||
#define GPG_SUCCESS() set_res_apdu (0x90, 0x00)
|
||||
|
||||
683
src/pin-cir.c
683
src/pin-cir.c
@@ -27,13 +27,41 @@
|
||||
#include "board.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_CIR 1
|
||||
#endif
|
||||
|
||||
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||
uint8_t pin_input_len;
|
||||
|
||||
/*
|
||||
* Supported/tested TV controllers:
|
||||
*
|
||||
* Controller of Toshiba REGZA
|
||||
* Controller of Sony BRAVIA
|
||||
* Controller of Sharp AQUOS
|
||||
* Dell Wireless Travel Remote MR425
|
||||
*
|
||||
* The code supports RC-5 protocol in fact, but I don't have any
|
||||
* controller at hand which I can test with, so I don't have any data
|
||||
* for controller of RC-5.
|
||||
*
|
||||
* Current code assumes following mapping:
|
||||
*
|
||||
* --------------------------------------
|
||||
* Protocol Controller
|
||||
* --------------------------------------
|
||||
* RC-6 Dell MR425
|
||||
* NEC Toshiba REGZA
|
||||
* Sharp Sharp AQUOS
|
||||
* Sony Sony BRAVIA
|
||||
* --------------------------------------
|
||||
*
|
||||
* In future, when I will have other controllers, this mapping will be
|
||||
* (should be) configurable, at compile time at least, preferably at
|
||||
* runtime.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Philips RC-5 Protocol: 14-bit (MSB first)
|
||||
*
|
||||
@@ -69,18 +97,26 @@ uint8_t pin_input_len;
|
||||
*/
|
||||
|
||||
/*
|
||||
* PB0 / TIM3_CH3
|
||||
* The implementation note of CIR signal decoding (on STM32).
|
||||
*
|
||||
* (1) Use EXTI interrupt to detect the first edge of signal.
|
||||
* (2) Use Timer (with PWM input mode) to measure timings of square wave.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Timer settings.
|
||||
*
|
||||
* See THE reference manual (RM0008) section 15.3.6 PWM input mode.
|
||||
*
|
||||
* 72MHz
|
||||
*
|
||||
* Prescaler = 72
|
||||
*
|
||||
* 1us
|
||||
*
|
||||
*
|
||||
* TIM3_CR1
|
||||
* CKD = 10 (sampling x4)
|
||||
* ARPE = 0 (not buffered)
|
||||
* TIMx_CR1
|
||||
* CKD = 00 (tDTS = tCK_INT)
|
||||
* ARPE = 1 (buffered)
|
||||
* CMS = 00 (up counter)
|
||||
* DIR = 0 (up counter)
|
||||
* OPM = 0 (up counter)
|
||||
@@ -88,13 +124,13 @@ uint8_t pin_input_len;
|
||||
* UDIS = 0 (UEV (update event) enabled)
|
||||
* CEN = 1 (counter enable)
|
||||
*
|
||||
* TIM3_CR2
|
||||
* TIMx_CR2
|
||||
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
|
||||
* MMS = 000 (TRGO at Reset)
|
||||
* CCDS = 0 (DMA on capture)
|
||||
* RSVD = 000
|
||||
*
|
||||
* TIM3_SMCR
|
||||
* TIMx_SMCR
|
||||
* ETP = 0
|
||||
* ECE = 0
|
||||
* ETPS = 00
|
||||
@@ -104,61 +140,37 @@ uint8_t pin_input_len;
|
||||
* RSVD = 0
|
||||
* SMS = 100 (Reset-mode)
|
||||
*
|
||||
* TIM3_DIER
|
||||
* TIMx_DIER
|
||||
*
|
||||
* TIM3_SR
|
||||
* TIMx_SR
|
||||
*
|
||||
* TIM3_EGR
|
||||
* TIMx_EGR
|
||||
*
|
||||
* TIM3_CCMR1
|
||||
* TIMx_CCMR1
|
||||
* CC1S = 01 (TI1 selected)
|
||||
* CC2S = 10 (TI1 selected)
|
||||
* IC1F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||
* IC2F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||
*
|
||||
* TIM3_CCMR2
|
||||
* TIMx_CCMR2
|
||||
*
|
||||
* TIM3_CCER
|
||||
* TIMx_CCER
|
||||
* CC2P = 1 (polarity = falling edge: TI1FP1)
|
||||
* CC2E = 1
|
||||
* CC1P = 0 (polarity = rising edge: TI1FP1)
|
||||
* CC1E = 1
|
||||
*
|
||||
* TIM3_CNT
|
||||
* TIM3_PSC = 71
|
||||
* TIM3_ARR = 18000
|
||||
* TIMx_CNT
|
||||
* TIMx_PSC = 71
|
||||
* TIMx_ARR = 18000
|
||||
*
|
||||
* TIM3_CCR1 period
|
||||
* TIM3_CCR2 duty
|
||||
* TIMx_CCR1 period
|
||||
* TIMx_CCR2 duty
|
||||
*
|
||||
* TIM3_DCR
|
||||
* TIM3_DMAR
|
||||
* TIMx_DCR
|
||||
* TIMx_DMAR
|
||||
*/
|
||||
|
||||
#define PINDISP_TIMEOUT_INTERVAL0 MS2ST(25)
|
||||
#define PINDISP_TIMEOUT_INTERVAL1 MS2ST(300)
|
||||
|
||||
static void
|
||||
pindisp (uint8_t c)
|
||||
{
|
||||
#if defined(HAVE_7SEGLED)
|
||||
switch (c)
|
||||
{
|
||||
case 'G':
|
||||
palWritePort (IOPORT2, 0xa1ff);
|
||||
break;
|
||||
case 'P':
|
||||
palWritePort (IOPORT2, 0x98ff);
|
||||
break;
|
||||
case '.':
|
||||
palWritePort (IOPORT2, 0x7fff);
|
||||
break;
|
||||
default:
|
||||
palWritePort (IOPORT2, 0xffff);
|
||||
}
|
||||
#else
|
||||
(void)c;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DEBUG_CIR)
|
||||
static uint16_t intr_ext;
|
||||
static uint16_t intr_trg;
|
||||
@@ -179,14 +191,6 @@ static uint8_t cir_proto;
|
||||
#define CIR_PROTO_NEC 5
|
||||
#define CIR_PROTO_SHARP 6
|
||||
|
||||
#define CIR_KEY_RC6_ENTER 0x0d /* Mute */
|
||||
#define CIR_KEY_RC6_BACKSPACE 0xa4 /* <= */
|
||||
#define CIR_KEY_NEC_ENTER 0x3d /* 'kettei' */
|
||||
#define CIR_KEY_NEC_BACKSPACE 0x3b /* 'modoru' */
|
||||
#define CIR_KEY_SONY_ENTER 0x65 /* 'kettei' */
|
||||
#define CIR_KEY_SONY_BACKSPACE 0xa3 /* 'modoru' */
|
||||
#define CIR_KEY_SHARP_ENTER 0x0252 /* 'kettei' */
|
||||
#define CIR_KEY_SHARP_BACKSPACE 0xe4 /* 'modoru' */
|
||||
|
||||
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
|
||||
static uint8_t cir_data_zero;
|
||||
@@ -196,6 +200,388 @@ static uint8_t cir_seq;
|
||||
static systime_t cir_input_last;
|
||||
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
|
||||
|
||||
static void
|
||||
cir_init (void)
|
||||
{
|
||||
cir_data = 0;
|
||||
cir_seq = 0;
|
||||
/* Don't touch cir_proto here */
|
||||
cir_ext_enable ();
|
||||
}
|
||||
|
||||
|
||||
#define CH_RETURN 0x0d
|
||||
#define CH_BACKSPACE 0x08
|
||||
|
||||
struct codetable {
|
||||
uint16_t cir_code;
|
||||
uint8_t char_code;
|
||||
};
|
||||
|
||||
/* NOTE: no way to input '0' */
|
||||
static const struct codetable
|
||||
cir_codetable_dell_mr425[] = {
|
||||
{0x10, '7' }, /* Speaker Louder */
|
||||
{0x11, '8' }, /* Speaker Quieter */
|
||||
{0x0d, '9' }, /* Speaker Mute */
|
||||
{0xce, 'a' }, /* Black triangle UP */
|
||||
{0xcf, 'b' }, /* Black triangle DOWN */
|
||||
{0x58, 'c' }, /* White triangle UP */
|
||||
{0x5a, 'd' }, /* White triangle LEFT */
|
||||
{0x5c, CH_RETURN }, /* Check */
|
||||
{0x5b, 'e' }, /* White triangle RIGHT */
|
||||
{0xa4, CH_BACKSPACE }, /* Back */
|
||||
{0x59, 'f' }, /* White triangle DOWN */
|
||||
{0x2f, '1' }, /* Rewind */
|
||||
{0x2c, '2' }, /* Play / Pause */
|
||||
{0x2e, '3' }, /* Forward */
|
||||
{0x21, '4' }, /* Skip backward */
|
||||
{0x31, '5' }, /* Stop */
|
||||
{0x20, '6' }, /* Skip forward */
|
||||
|
||||
{0, 0} /* <<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
|
||||
* have the one.
|
||||
@@ -207,125 +593,56 @@ static systime_t cir_input_last;
|
||||
#define CIR_BIT_PERIOD 1500
|
||||
#define CIR_BIT_SIRC_PERIOD_ON 1000
|
||||
|
||||
static void
|
||||
cir_init (void)
|
||||
{
|
||||
cir_data = 0;
|
||||
cir_seq = 0;
|
||||
/* Don't touch cir_proto here */
|
||||
cir_ext_enable ();
|
||||
}
|
||||
|
||||
static Thread *pin_thread;
|
||||
|
||||
static int
|
||||
cir_key_is_backspace (void)
|
||||
/*
|
||||
* Let user input PIN string.
|
||||
* Return length of the string.
|
||||
* The string itself is in PIN_INPUT_BUFFER.
|
||||
*/
|
||||
int
|
||||
pinpad_getline (int msg_code, systime_t timeout)
|
||||
{
|
||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_BACKSPACE)
|
||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_BACKSPACE)
|
||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_BACKSPACE)
|
||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_BACKSPACE);
|
||||
}
|
||||
|
||||
static int
|
||||
cir_key_is_enter (void)
|
||||
{
|
||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_ENTER)
|
||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_ENTER)
|
||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_ENTER)
|
||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_ENTER);
|
||||
}
|
||||
|
||||
msg_t
|
||||
pin_main (void *arg)
|
||||
{
|
||||
uint8_t s = 0;
|
||||
int msg_code = (int)arg;
|
||||
|
||||
(void)msg_code;
|
||||
|
||||
pin_thread = chThdSelf ();
|
||||
|
||||
#if defined(DEBUG_CIR)
|
||||
cirinput_p = cirinput;
|
||||
#endif
|
||||
DEBUG_INFO (">>>\r\n");
|
||||
|
||||
pin_input_len = 0;
|
||||
chEvtClear (ALL_EVENTS);
|
||||
cir_init ();
|
||||
|
||||
while (!chThdShouldTerminate ())
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
int ch;
|
||||
|
||||
m = chEvtWaitOneTimeout (ALL_EVENTS, PINDISP_TIMEOUT_INTERVAL1);
|
||||
ch = cir_getchar (timeout);
|
||||
if (ch < 0)
|
||||
return 0; /* timeout */
|
||||
|
||||
if (m)
|
||||
if (ch_is_backspace (ch))
|
||||
{
|
||||
#if defined(DEBUG_CIR)
|
||||
uint16_t *p;
|
||||
|
||||
DEBUG_INFO ("****\r\n");
|
||||
DEBUG_SHORT (intr_ext);
|
||||
DEBUG_SHORT (intr_trg);
|
||||
DEBUG_SHORT (intr_ovf);
|
||||
DEBUG_INFO ("----\r\n");
|
||||
for (p = cirinput; p < cirinput_p; p++)
|
||||
DEBUG_SHORT (*p);
|
||||
DEBUG_INFO ("====\r\n");
|
||||
|
||||
cirinput_p = cirinput;
|
||||
#endif
|
||||
DEBUG_INFO ("**** CIR data:");
|
||||
DEBUG_WORD (cir_data);
|
||||
if (cir_seq > 48)
|
||||
{
|
||||
DEBUG_SHORT (cir_data_more);
|
||||
}
|
||||
DEBUG_BYTE (cir_seq);
|
||||
|
||||
if (cir_key_is_backspace ())
|
||||
{
|
||||
if (pin_input_len > 0)
|
||||
pin_input_len--;
|
||||
}
|
||||
else if (cir_key_is_enter ())
|
||||
{
|
||||
pindisp (' ');
|
||||
chThdExit (0);
|
||||
}
|
||||
else if (pin_input_len < MAX_PIN_CHARS)
|
||||
pin_input_buffer[pin_input_len++] = (uint8_t)cir_data;
|
||||
|
||||
cir_init ();
|
||||
led_blink (2);
|
||||
if (pin_input_len > 0)
|
||||
pin_input_len--;
|
||||
}
|
||||
|
||||
switch (s++)
|
||||
else if (ch_is_enter (ch))
|
||||
break;
|
||||
else if (pin_input_len < MAX_PIN_CHARS)
|
||||
{
|
||||
case 0:
|
||||
pindisp ('G');
|
||||
break;
|
||||
case 1:
|
||||
pindisp ('P');
|
||||
break;
|
||||
case 2:
|
||||
pindisp ('G');
|
||||
break;
|
||||
case 3:
|
||||
pindisp ('.');
|
||||
break;
|
||||
default:
|
||||
pindisp (' ');
|
||||
s = 0;
|
||||
break;
|
||||
led_blink (0);
|
||||
pin_input_buffer[pin_input_len++] = ch;
|
||||
}
|
||||
|
||||
chThdSleep (PINDISP_TIMEOUT_INTERVAL0);
|
||||
}
|
||||
|
||||
cir_ext_disable ();
|
||||
return 0;
|
||||
|
||||
return pin_input_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Interrupt handler of EXTI.
|
||||
* @note This handler will be invoked at the beginning of signal.
|
||||
* Setup timer to measure period and duty using PWM input mode.
|
||||
*/
|
||||
void
|
||||
cir_ext_interrupt (void)
|
||||
{
|
||||
@@ -340,29 +657,33 @@ cir_ext_interrupt (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
||||
TIMx->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
||||
/* Enable Timer */
|
||||
TIM3->SR &= ~(TIM_SR_UIF
|
||||
TIMx->SR &= ~(TIM_SR_UIF
|
||||
| TIM_SR_CC1IF | TIM_SR_CC2IF
|
||||
| TIM_SR_TIF
|
||||
| TIM_SR_CC1OF | TIM_SR_CC2OF);
|
||||
TIM3->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
||||
TIM3->CR1 |= TIM_CR1_CEN;
|
||||
TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
||||
TIMx->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
|
||||
* CIR_BIT_PERIOD_RC6 * 3 / 2)
|
||||
|
||||
/**
|
||||
* @brief Interrupt handler of timer.
|
||||
* @note Timer is PWM input mode, this handler will be invoked on each cycle
|
||||
*/
|
||||
void
|
||||
cir_timer_interrupt (void)
|
||||
{
|
||||
uint16_t period, on, off;
|
||||
|
||||
period = TIM3->CCR1;
|
||||
on = TIM3->CCR2;
|
||||
period = TIMx->CCR1;
|
||||
on = TIMx->CCR2;
|
||||
off = period - on;
|
||||
|
||||
if ((TIM3->SR & TIM_SR_TIF))
|
||||
if ((TIMx->SR & TIM_SR_TIF))
|
||||
{
|
||||
if (cir_seq == 0)
|
||||
{
|
||||
@@ -477,23 +798,23 @@ cir_timer_interrupt (void)
|
||||
intr_trg++;
|
||||
#endif
|
||||
|
||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV */
|
||||
TIM3->SR &= ~TIM_SR_TIF;
|
||||
TIMx->EGR = TIM_EGR_UG; /* Generate UEV */
|
||||
TIMx->SR &= ~TIM_SR_TIF;
|
||||
}
|
||||
else
|
||||
/* overflow occurred */
|
||||
{
|
||||
systime_t now = chTimeNow ();
|
||||
|
||||
TIM3->SR &= ~TIM_SR_UIF;
|
||||
TIMx->SR &= ~TIM_SR_UIF;
|
||||
|
||||
if (on > 0)
|
||||
{
|
||||
uint8_t ignore_input = 0;
|
||||
|
||||
/* Disable the timer */
|
||||
TIM3->CR1 &= ~TIM_CR1_CEN;
|
||||
TIM3->DIER = 0;
|
||||
TIMx->CR1 &= ~TIM_CR1_CEN;
|
||||
TIMx->DIER = 0;
|
||||
|
||||
if (cir_seq == 12 || cir_seq == 15)
|
||||
{
|
||||
@@ -536,14 +857,9 @@ cir_timer_interrupt (void)
|
||||
cir_input_last = now;
|
||||
ignore_input = 1;
|
||||
}
|
||||
/* Remove ADDRESS bits and filter COMMAND bits */
|
||||
else if (cir_proto == CIR_PROTO_SONY)
|
||||
{
|
||||
if (cir_seq == 1 + 12)
|
||||
cir_data = cir_data & 0x007f;
|
||||
else if (cir_seq == 1 + 15)
|
||||
cir_data = cir_data & 0x00ff;
|
||||
else
|
||||
if (cir_seq != 1 + 12 && cir_seq != 1 + 15)
|
||||
ignore_input = 1;
|
||||
}
|
||||
else if (cir_proto == CIR_PROTO_OTHER)
|
||||
@@ -551,10 +867,7 @@ cir_timer_interrupt (void)
|
||||
if (cir_seq == 1 + 32)
|
||||
{
|
||||
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
|
||||
{
|
||||
cir_proto = CIR_PROTO_NEC;
|
||||
cir_data = (cir_data >> 16) & 0x00ff;
|
||||
}
|
||||
cir_proto = CIR_PROTO_NEC;
|
||||
else
|
||||
ignore_input = 1;
|
||||
}
|
||||
@@ -569,10 +882,7 @@ cir_timer_interrupt (void)
|
||||
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
|
||||
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
|
||||
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
|
||||
{
|
||||
cir_proto = CIR_PROTO_SHARP;
|
||||
cir_data = (cir_data >> 16) & 0x0fff;
|
||||
}
|
||||
cir_proto = CIR_PROTO_SHARP;
|
||||
else
|
||||
ignore_input = 1;
|
||||
}
|
||||
@@ -581,16 +891,12 @@ cir_timer_interrupt (void)
|
||||
}
|
||||
else if (cir_proto == CIR_PROTO_RC6)
|
||||
{
|
||||
if (cir_seq == 16 || cir_seq == 32)
|
||||
cir_data &= 0x00ff;
|
||||
else
|
||||
if (cir_seq != 16 && cir_seq != 32)
|
||||
ignore_input = 1;
|
||||
}
|
||||
else if (cir_proto == CIR_PROTO_RC5)
|
||||
{
|
||||
if (cir_seq == 14)
|
||||
cir_data &= 0x003f;
|
||||
else
|
||||
if (cir_seq != 14)
|
||||
ignore_input = 1;
|
||||
}
|
||||
else
|
||||
@@ -603,7 +909,8 @@ cir_timer_interrupt (void)
|
||||
{
|
||||
cir_input_last = now;
|
||||
/* Notify thread */
|
||||
chEvtSignal (pin_thread, (eventmask_t)1);
|
||||
if (pin_thread)
|
||||
chEvtSignalI (pin_thread, (eventmask_t)1);
|
||||
}
|
||||
|
||||
#if defined(DEBUG_CIR)
|
||||
|
||||
@@ -128,10 +128,9 @@ dial_sw_interrupt (void)
|
||||
}
|
||||
|
||||
|
||||
msg_t
|
||||
pin_main (void *arg)
|
||||
int
|
||||
pinpad_getline (int msg_code, systime_t timeout)
|
||||
{
|
||||
int msg_code = (int)arg;
|
||||
uint16_t count, count_prev;
|
||||
uint8_t input_mode;
|
||||
uint8_t sw_push_count;
|
||||
@@ -150,7 +149,7 @@ pin_main (void *arg)
|
||||
sw_push_count = 0;
|
||||
sw_event = 0;
|
||||
|
||||
while (!chThdShouldTerminate ())
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
@@ -218,5 +217,5 @@ pin_main (void *arg)
|
||||
led_disp (OFF);
|
||||
TIM4->CR1 &= ~TIM_CR1_CEN;
|
||||
dial_sw_disable ();
|
||||
return 0;
|
||||
return pin_input_len;
|
||||
}
|
||||
|
||||
64
src/random.c
64
src/random.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* random.c -- get random bytes
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -24,47 +24,49 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "neug.h"
|
||||
|
||||
#define RANDOM_BYTES_LENGTH 16
|
||||
static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
|
||||
|
||||
void
|
||||
random_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
|
||||
|
||||
for (i = 0; i < NEUG_PRE_LOOP; i++)
|
||||
(void)neug_get (NEUG_KICK_FILLING);
|
||||
|
||||
neug_prng_reseed ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pointer to random 16-byte
|
||||
*/
|
||||
const uint8_t *
|
||||
random_bytes_get (void)
|
||||
{
|
||||
uint32_t addr, addr0;
|
||||
|
||||
addr = (uint32_t)&random_bits_start + ((hardclock () << 5) & 0x3e0);
|
||||
addr0 = addr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (*(uint32_t *)addr != 0 && *(uint32_t *)addr != 0xffffffff)
|
||||
break;
|
||||
|
||||
addr += 32;
|
||||
if (addr >= ((uint32_t)&random_bits_start) + 1024)
|
||||
addr = ((uint32_t)&random_bits_start);
|
||||
|
||||
if (addr == addr0)
|
||||
fatal (FATAL_RANDOM);
|
||||
}
|
||||
|
||||
return (const uint8_t *)addr;
|
||||
neug_wait_full ();
|
||||
return (const uint8_t *)random_word;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free pointer to random 16-byte
|
||||
*/
|
||||
void
|
||||
random_bytes_free (const uint8_t *p)
|
||||
{
|
||||
int i;
|
||||
uint32_t addr = (uint32_t)p;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
flash_clear_halfword (addr+i*2);
|
||||
(void)p;
|
||||
neug_flush ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 4-byte salt
|
||||
*/
|
||||
uint32_t
|
||||
get_random (void)
|
||||
get_salt (void)
|
||||
{
|
||||
const uint32_t *p = (const uint32_t *)random_bytes_get ();
|
||||
uint32_t r = *p;
|
||||
|
||||
random_bytes_free ((const uint8_t *)p);
|
||||
return r;
|
||||
return neug_get (NEUG_KICK_FILLING);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ EP2_OUT_Callback (void)
|
||||
icc_prepare_receive (0);
|
||||
}
|
||||
else
|
||||
/* Notify icc_thread */
|
||||
/* Notify myself */
|
||||
chEvtSignalI (icc_thread, EV_RX_DATA_READY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,16 @@ static const uint8_t gnukStringProduct[] = {
|
||||
' ', 0, 'T', 0, 'o', 0, 'k', 0, 'e', 0, 'n', 0
|
||||
};
|
||||
|
||||
const uint8_t gnukStringSerial[] = {
|
||||
13*2+2, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'0', 0, '.', 0, '1', 0, '5', 0, /* Version number of Gnuk */
|
||||
'-', 0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
|
||||
const ONE_DESCRIPTOR Device_Descriptor = {
|
||||
(uint8_t*)gnukDeviceDescriptor,
|
||||
sizeof (gnukDeviceDescriptor)
|
||||
@@ -234,8 +244,9 @@ const ONE_DESCRIPTOR Config_Descriptor = {
|
||||
sizeof (gnukConfigDescriptor)
|
||||
};
|
||||
|
||||
const ONE_DESCRIPTOR String_Descriptor[3] = {
|
||||
const ONE_DESCRIPTOR String_Descriptor[] = {
|
||||
{(uint8_t*)gnukStringLangID, sizeof (gnukStringLangID)},
|
||||
{(uint8_t*)gnukStringVendor, sizeof (gnukStringVendor)},
|
||||
{(uint8_t*)gnukStringProduct, sizeof (gnukStringProduct)},
|
||||
{(uint8_t*)gnukStringSerial, sizeof (gnukStringSerial)},
|
||||
};
|
||||
|
||||
@@ -36,30 +36,10 @@
|
||||
#include "usb-cdc-vport.c"
|
||||
#endif
|
||||
|
||||
static uint8_t gnukStringSerial[] = {
|
||||
13*2+2, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
'0', 0, '.', 0, '1', 0, '1', 0, /* Version number of Gnuk */
|
||||
'-', 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
#define ID_OFFSET 12
|
||||
|
||||
static void
|
||||
gnuk_device_init (void)
|
||||
{
|
||||
const uint8_t *u = unique_device_id ();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
gnukStringSerial[i*4+ID_OFFSET+0] = (u[i*2] >> 4) + 'A';
|
||||
gnukStringSerial[i*4+ID_OFFSET+1] = 0;
|
||||
gnukStringSerial[i*4+ID_OFFSET+2] = (u[i*2+1] & 0x0f) + 'A';
|
||||
gnukStringSerial[i*4+ID_OFFSET+3] = 0;
|
||||
}
|
||||
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* Connect the device */
|
||||
@@ -140,8 +120,14 @@ gnuk_device_SetConfiguration (void)
|
||||
DEVICE_INFO *pInfo = &Device_Info;
|
||||
|
||||
if (pInfo->Current_Configuration != 0)
|
||||
/* Device configured */
|
||||
bDeviceState = CONFIGURED;
|
||||
{ /* Device configured */
|
||||
extern void *main_thread;
|
||||
extern void chEvtSignalI (void *, unsigned long);
|
||||
#define LED_STATUS_MODE (8)
|
||||
|
||||
bDeviceState = CONFIGURED;
|
||||
chEvtSignalI (main_thread, LED_STATUS_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -205,22 +191,13 @@ static uint8_t *
|
||||
gnuk_device_GetStringDescriptor (uint16_t Length)
|
||||
{
|
||||
uint8_t wValue0 = pInformation->USBwValue0;
|
||||
uint32_t wOffset = pInformation->Ctrl_Info.Usb_wOffset;
|
||||
|
||||
if (wValue0 == 3)
|
||||
/* Serial number is requested */
|
||||
if (Length == 0)
|
||||
{
|
||||
pInformation->Ctrl_Info.Usb_wLength = sizeof gnukStringSerial - wOffset;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return gnukStringSerial + wOffset;
|
||||
else if (wValue0 > (sizeof (String_Descriptor) / sizeof (ONE_DESCRIPTOR)))
|
||||
if (wValue0 >= (sizeof (String_Descriptor) / sizeof (ONE_DESCRIPTOR)))
|
||||
return NULL;
|
||||
else
|
||||
return Standard_GetDescriptorData (Length,
|
||||
(PONE_DESCRIPTOR)&String_Descriptor[wValue0]);
|
||||
return
|
||||
Standard_GetDescriptorData (Length,
|
||||
(PONE_DESCRIPTOR)&String_Descriptor[wValue0]);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
dfuse.py - DFU (Device Firmware Upgrade) tool for STM32 Processor.
|
||||
"SE" in DfuSe stands for "STmicroelectronics Extention".
|
||||
|
||||
Copyright (C) 2010 Free Software Initiative of Japan
|
||||
Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -208,10 +208,23 @@ class DFU_STM32:
|
||||
# First, erase pages
|
||||
sys.stdout.write("Erasing: ")
|
||||
sys.stdout.flush()
|
||||
last_addr = 0
|
||||
for start_addr in sorted(ih.memory.keys()):
|
||||
data = ih.memory[start_addr]
|
||||
end_addr = start_addr + len(data)
|
||||
addr = start_addr & 0xfffffc00
|
||||
if not last_addr == 0:
|
||||
i = 0
|
||||
if last_addr > addr:
|
||||
addr = last_addr
|
||||
else:
|
||||
while last_addr < addr:
|
||||
self.dfuse_erase(last_addr)
|
||||
if i & 0x03 == 0x03:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
last_addr += 1024
|
||||
i += 1
|
||||
i = 0
|
||||
while addr < end_addr:
|
||||
self.dfuse_erase(addr)
|
||||
@@ -220,20 +233,32 @@ class DFU_STM32:
|
||||
sys.stdout.flush()
|
||||
addr += 1024
|
||||
i += 1
|
||||
last_addr = addr
|
||||
sys.stdout.write("\n")
|
||||
sys.stdout.flush()
|
||||
# Then, write pages
|
||||
sys.stdout.write("Writing: ")
|
||||
sys.stdout.flush()
|
||||
last_addr = 0
|
||||
for start_addr in sorted(ih.memory.keys()):
|
||||
data = ih.memory[start_addr]
|
||||
end_addr = start_addr + len(data)
|
||||
addr = start_addr & 0xfffffc00
|
||||
# XXX: data should be 1-KiB aligned
|
||||
if addr != start_addr:
|
||||
raise ValueError, "padding is not supported yet"
|
||||
self.dfuse_set_address_pointer(addr)
|
||||
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
|
||||
i = 0
|
||||
if addr != start_addr:
|
||||
self.dfuse_set_address_pointer(start_addr)
|
||||
self.dfuse_write_memory(data[0:(addr + 1024 - start_addr)])
|
||||
data = data[(addr + 1024 - start_addr):]
|
||||
addr += 1024
|
||||
self.dfuse_set_address_pointer(addr)
|
||||
while addr < end_addr:
|
||||
self.dfuse_write_memory(data[i*1024:(i+1)*1024])
|
||||
if i & 0x03 == 0x03:
|
||||
@@ -241,6 +266,7 @@ class DFU_STM32:
|
||||
sys.stdout.flush()
|
||||
addr += 1024
|
||||
i += 1
|
||||
last_addr = addr
|
||||
if self.__protocol == DFU_STM32PROTOCOL_0:
|
||||
# 0-length write at the end
|
||||
self.ll_download_block(self.__blocknum, None)
|
||||
@@ -268,13 +294,33 @@ class DFU_STM32:
|
||||
# Read pages
|
||||
sys.stdout.write("Reading: ")
|
||||
sys.stdout.flush()
|
||||
last_addr = 0
|
||||
for start_addr in sorted(ih.memory.keys()):
|
||||
data = ih.memory[start_addr]
|
||||
end_addr = start_addr + len(data)
|
||||
addr = start_addr & 0xfffffc00
|
||||
# XXX: data should be 1-KiB aligned
|
||||
if not last_addr == 0:
|
||||
i = 0
|
||||
while last_addr < addr:
|
||||
if i & 0x03 == 0x03:
|
||||
sys.stdout.write(".")
|
||||
sys.stdout.flush()
|
||||
last_addr += 1024
|
||||
i += 1
|
||||
if addr != start_addr:
|
||||
raise ValueError, "padding is not supported yet"
|
||||
self.dfuse_set_address_pointer(addr)
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
block = self.dfuse_read_memory()
|
||||
j = 0
|
||||
for c in data[0:(addr + 1024 - start_addr)]:
|
||||
if (ord(c)&0xff) != block[j + start_addr - addr]:
|
||||
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
|
||||
j += 1
|
||||
data = data[(addr + 1024 - start_addr):]
|
||||
addr += 1024
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
self.dfuse_set_address_pointer(addr)
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
@@ -282,7 +328,7 @@ class DFU_STM32:
|
||||
while addr < end_addr:
|
||||
block = self.dfuse_read_memory()
|
||||
j = 0
|
||||
for c in data[i*1024:i*1024+1024]
|
||||
for c in data[i*1024:(i+1)*1024]:
|
||||
if (ord(c)&0xff) != block[j]:
|
||||
raise ValueError, "verify failed at %08x" % (addr + i*1024+j)
|
||||
j += 1
|
||||
@@ -291,6 +337,7 @@ class DFU_STM32:
|
||||
sys.stdout.flush()
|
||||
addr += 1024
|
||||
i += 1
|
||||
last_addr = addr
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
self.ll_clear_status()
|
||||
@@ -299,10 +346,19 @@ class DFU_STM32:
|
||||
|
||||
busses = usb.busses()
|
||||
|
||||
# 0483: SGS Thomson Microelectronics
|
||||
# df11: DfuSe
|
||||
USB_VENDOR_STMICRO=0x0483
|
||||
USB_PRODUCT_DFUSE=0xdf11
|
||||
|
||||
def get_device():
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
if dev.idVendor != USB_VENDOR_STMICRO:
|
||||
continue
|
||||
if dev.idProduct != USB_PRODUCT_DFUSE:
|
||||
continue
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
|
||||
@@ -23,186 +23,66 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from intel_hex import *
|
||||
from struct import *
|
||||
import sys, time, os, binascii, string
|
||||
import sys, os, binascii, string
|
||||
|
||||
# INPUT: binary file
|
||||
|
||||
# Assume only single CCID device is attached to computer, and it's Gnuk Token
|
||||
# Assume only single CCID device is attached to computer and it's Gnuk Token
|
||||
|
||||
import usb
|
||||
from smartcard.CardType import AnyCardType
|
||||
from smartcard.CardRequest import CardRequest
|
||||
from smartcard.util import toHexString
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
def s2l(s):
|
||||
return [ ord(c) for c in s ]
|
||||
|
||||
def icc_compose(msg_type, data_len, slot, seq, param, data):
|
||||
return pack('<BiBBBH', msg_type, data_len, slot, seq, 0, param) + data
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data):
|
||||
cls = 0x00
|
||||
data_len = len(data)
|
||||
if data_len == 0:
|
||||
return pack('>BBBB', cls, ins, p1, p2)
|
||||
else:
|
||||
return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data
|
||||
|
||||
# This class only supports Gnuk (for now)
|
||||
class gnuk_token:
|
||||
def __init__(self, device, configuration, interface):
|
||||
"""
|
||||
__init__(device, configuration, interface) -> None
|
||||
Initialize the device.
|
||||
device: usb.Device object.
|
||||
configuration: configuration number.
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != CCID_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
if interface.interfaceSubClass != CCID_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
self.__devhandle = device.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
self.__conf = configuration
|
||||
|
||||
self.__bulkout = 2
|
||||
self.__bulkin = 0x81
|
||||
|
||||
self.__timeout = 10000
|
||||
self.__seq = 0
|
||||
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print msg
|
||||
raise ValueError, "icc_get_result"
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data)
|
||||
|
||||
def icc_get_status(self):
|
||||
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_power_on(self):
|
||||
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check status, chain
|
||||
return data # ATR
|
||||
|
||||
def icc_power_off(self):
|
||||
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_send_data_block(self, data):
|
||||
msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data)
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
return self.icc_get_result()
|
||||
|
||||
def icc_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.icc_send_data_block(data)
|
||||
if chain == 0:
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data_rcv = self.icc_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd chain"
|
||||
return d
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd"
|
||||
class GnukToken(object):
|
||||
def __init__(self):
|
||||
cardtype = AnyCardType()
|
||||
cardrequest = CardRequest(timeout=1, cardType=cardtype)
|
||||
cardservice = cardrequest.waitforcard()
|
||||
self.connection = cardservice.connection
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_verify"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, "cmd_verify"
|
||||
|
||||
def cmd_write_binary(self, fileid, data):
|
||||
def cmd_write_binary(self, fileid, data, is_update):
|
||||
count = 0
|
||||
data_len = len(data)
|
||||
if is_update:
|
||||
ins = 0xd6
|
||||
else:
|
||||
ins = 0xd0
|
||||
while count*256 < data_len:
|
||||
if count == 0:
|
||||
cmd_data = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:256])
|
||||
d = data[:256]
|
||||
apdu = [0x00, ins, 0x80+fileid, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d)
|
||||
else:
|
||||
cmd_data = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_write_binary"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_write_binary"
|
||||
count += 1
|
||||
|
||||
def cmd_update_binary(self, fileid, data):
|
||||
count = 0
|
||||
data_len = len(data)
|
||||
while count*256 < data_len:
|
||||
if count == 0:
|
||||
cmd_data = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:256])
|
||||
else:
|
||||
cmd_data = iso7816_compose(0xd6, count, 0x00, data[256*count:256*(count+1)])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_update_binary"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_update_binary"
|
||||
d = data[256*count:256*(count+1)]
|
||||
apdu = [0x00, ins, count, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d)
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
if is_update:
|
||||
raise ValueError, "cmd_update_binary"
|
||||
else:
|
||||
raise ValueError, "cmd_write_binary"
|
||||
count += 1
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
|
||||
def cmd_get_data(self, tagh, tagl):
|
||||
cmd_data = iso7816_compose(0xca, tagh, tagl, "")
|
||||
result = self.icc_send_cmd(cmd_data)
|
||||
sw = result[-2:]
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
apdu = [0x00, 0xca, tagh, tagl]
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, "cmd_get_data"
|
||||
return result[:-2]
|
||||
return response
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
i = 0
|
||||
@@ -211,44 +91,40 @@ def compare(data_original, data_in_device):
|
||||
raise ValueError, "verify failed at %08x" % i
|
||||
i += 1
|
||||
|
||||
def get_device():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
if alt.interfaceClass == CCID_CLASS and \
|
||||
alt.interfaceSubClass == CCID_SUBCLASS and \
|
||||
alt.interfaceProtocol == CCID_PROTOCOL_0:
|
||||
return dev, config, alt
|
||||
raise ValueError, "Device not found"
|
||||
DEFAULT_PW3 = "12345678"
|
||||
BY_ADMIN = 3
|
||||
|
||||
def main(fileid, is_update, data):
|
||||
dev, config, intf = get_device()
|
||||
print "Device: ", dev.filename
|
||||
print "Configuration: ", config.value
|
||||
print "Interface: ", intf.interfaceNumber
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
if icc.icc_get_status() == 2:
|
||||
raise ValueError, "No ICC present"
|
||||
elif icc.icc_get_status() == 1:
|
||||
icc.icc_power_on()
|
||||
icc.cmd_verify(3, "12345678")
|
||||
if is_update:
|
||||
icc.cmd_update_binary(fileid, data)
|
||||
else:
|
||||
icc.cmd_write_binary(fileid, data)
|
||||
icc.cmd_select_openpgp()
|
||||
def main(fileid, is_update, data, passwd):
|
||||
gnuk = GnukToken()
|
||||
|
||||
gnuk.connection.connect()
|
||||
print "Token:", gnuk.connection.getReader()
|
||||
print "ATR:", toHexString( gnuk.connection.getATR() )
|
||||
|
||||
gnuk.cmd_verify(BY_ADMIN, passwd)
|
||||
gnuk.cmd_write_binary(fileid, data, is_update)
|
||||
if fileid == 0:
|
||||
data = data[:-2]
|
||||
data_in_device = icc.cmd_get_data(0x7f, 0x21)
|
||||
compare(data, data_in_device)
|
||||
icc.icc_power_off()
|
||||
gnuk.cmd_select_openpgp()
|
||||
data_in_device = gnuk.cmd_get_data(0x7f, 0x21)
|
||||
compare(data[:-2], data_in_device)
|
||||
elif fileid == 2:
|
||||
gnuk.cmd_select_openpgp()
|
||||
data_in_device = gnuk.cmd_get_data(0x00, 0x4f)
|
||||
for d in data_in_device:
|
||||
print "%02x" % d,
|
||||
print
|
||||
compare(data, data_in_device[8:])
|
||||
|
||||
gnuk.connection.disconnect()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
passwd = DEFAULT_PW3
|
||||
if sys.argv[1] == '-p':
|
||||
from getpass import getpass
|
||||
passwd = getpass("Admin password:")
|
||||
sys.argv.pop(1)
|
||||
if sys.argv[1] == '-u':
|
||||
is_update = True
|
||||
sys.argv.pop(1)
|
||||
@@ -291,4 +167,4 @@ if __name__ == '__main__':
|
||||
print "%s: %d" % (filename, len(data))
|
||||
data += "\x90\x00"
|
||||
print "Updating card holder certificate"
|
||||
main(fileid, is_update, data)
|
||||
main(fileid, is_update, data, passwd)
|
||||
|
||||
294
tool/gnuk_put_binary_libusb.py
Executable file
294
tool/gnuk_put_binary_libusb.py
Executable file
@@ -0,0 +1,294 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
"""
|
||||
gnuk_put_binary.py - a tool to put binary to Gnuk Token
|
||||
This tool is for importing certificate, updating random number, etc.
|
||||
|
||||
Copyright (C) 2011 Free Software Initiative of Japan
|
||||
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/>.
|
||||
"""
|
||||
|
||||
from intel_hex import *
|
||||
from struct import *
|
||||
import sys, time, os, binascii, string
|
||||
|
||||
# INPUT: binary file
|
||||
|
||||
# Assume only single CCID device is attached to computer, and it's Gnuk Token
|
||||
|
||||
import usb
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
|
||||
def icc_compose(msg_type, data_len, slot, seq, param, data):
|
||||
return pack('<BiBBBH', msg_type, data_len, slot, seq, 0, param) + data
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data):
|
||||
cls = 0x00
|
||||
data_len = len(data)
|
||||
if data_len == 0:
|
||||
return pack('>BBBB', cls, ins, p1, p2)
|
||||
else:
|
||||
return pack('>BBBBBh', cls, ins, p1, p2, 0, data_len) + data
|
||||
|
||||
# This class only supports Gnuk (for now)
|
||||
class gnuk_token:
|
||||
def __init__(self, device, configuration, interface):
|
||||
"""
|
||||
__init__(device, configuration, interface) -> None
|
||||
Initialize the device.
|
||||
device: usb.Device object.
|
||||
configuration: configuration number.
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != CCID_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
if interface.interfaceSubClass != CCID_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
self.__devhandle = device.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
self.__conf = configuration
|
||||
|
||||
self.__bulkout = 2
|
||||
self.__bulkin = 0x81
|
||||
|
||||
self.__timeout = 10000
|
||||
self.__seq = 0
|
||||
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print msg
|
||||
raise ValueError, "icc_get_result"
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data)
|
||||
|
||||
def icc_get_status(self):
|
||||
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_power_on(self):
|
||||
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check status, chain
|
||||
return data # ATR
|
||||
|
||||
def icc_power_off(self):
|
||||
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_send_data_block(self, data):
|
||||
msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data)
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
return self.icc_get_result()
|
||||
|
||||
def icc_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.icc_send_data_block(data)
|
||||
if chain == 0:
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data_rcv = self.icc_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd chain"
|
||||
return d
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd"
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_verify"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_verify"
|
||||
|
||||
def cmd_write_binary(self, fileid, data):
|
||||
count = 0
|
||||
data_len = len(data)
|
||||
while count*256 < data_len:
|
||||
if count == 0:
|
||||
cmd_data = iso7816_compose(0xd0, 0x80+fileid, 0x00, data[:256])
|
||||
else:
|
||||
cmd_data = iso7816_compose(0xd0, count, 0x00, data[256*count:256*(count+1)])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_write_binary"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_write_binary"
|
||||
count += 1
|
||||
|
||||
def cmd_update_binary(self, fileid, data):
|
||||
count = 0
|
||||
data_len = len(data)
|
||||
while count*256 < data_len:
|
||||
if count == 0:
|
||||
cmd_data = iso7816_compose(0xd6, 0x80+fileid, 0x00, data[:256])
|
||||
else:
|
||||
cmd_data = iso7816_compose(0xd6, count, 0x00, data[256*count:256*(count+1)])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_update_binary"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_update_binary"
|
||||
count += 1
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
|
||||
def cmd_get_data(self, tagh, tagl):
|
||||
cmd_data = iso7816_compose(0xca, tagh, tagl, "")
|
||||
result = self.icc_send_cmd(cmd_data)
|
||||
sw = result[-2:]
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, "cmd_get_data"
|
||||
return result[:-2]
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
i = 0
|
||||
for d in data_original:
|
||||
if ord(d) != data_in_device[i]:
|
||||
raise ValueError, "verify failed at %08x" % i
|
||||
i += 1
|
||||
|
||||
def get_device():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
if alt.interfaceClass == CCID_CLASS and \
|
||||
alt.interfaceSubClass == CCID_SUBCLASS and \
|
||||
alt.interfaceProtocol == CCID_PROTOCOL_0:
|
||||
return dev, config, alt
|
||||
raise ValueError, "Device not found"
|
||||
|
||||
def main(fileid, is_update, data):
|
||||
dev, config, intf = get_device()
|
||||
print "Device: ", dev.filename
|
||||
print "Configuration: ", config.value
|
||||
print "Interface: ", intf.interfaceNumber
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
if icc.icc_get_status() == 2:
|
||||
raise ValueError, "No ICC present"
|
||||
elif icc.icc_get_status() == 1:
|
||||
icc.icc_power_on()
|
||||
icc.cmd_verify(3, "12345678")
|
||||
if is_update:
|
||||
icc.cmd_update_binary(fileid, data)
|
||||
else:
|
||||
icc.cmd_write_binary(fileid, data)
|
||||
icc.cmd_select_openpgp()
|
||||
if fileid == 0:
|
||||
data = data[:-2]
|
||||
data_in_device = icc.cmd_get_data(0x7f, 0x21)
|
||||
compare(data, data_in_device)
|
||||
icc.icc_power_off()
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[1] == '-u':
|
||||
is_update = True
|
||||
sys.argv.pop(1)
|
||||
else:
|
||||
is_update = False
|
||||
if sys.argv[1] == '-s':
|
||||
fileid = 2 # serial number
|
||||
filename = sys.argv[2]
|
||||
f = open(filename)
|
||||
email = os.environ['EMAIL']
|
||||
serial_data_hex = None
|
||||
for line in f.readlines():
|
||||
field = string.split(line)
|
||||
if field[0] == email:
|
||||
serial_data_hex = field[1].replace(':','')
|
||||
f.close()
|
||||
if not serial_data_hex:
|
||||
print "No serial number"
|
||||
exit(1)
|
||||
print "Writing serial number"
|
||||
data = binascii.unhexlify(serial_data_hex)
|
||||
elif sys.argv[1] == '-r':
|
||||
fileid = 1 # Random number bits
|
||||
if len(sys.argv) == 3:
|
||||
filename = sys.argv[2]
|
||||
f = open(filename)
|
||||
else:
|
||||
filename = stdin
|
||||
f = sys.stdin
|
||||
data = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename, len(data))
|
||||
print "Updating random bits"
|
||||
else:
|
||||
fileid = 0 # Card holder certificate
|
||||
filename = sys.argv[1]
|
||||
f = open(filename)
|
||||
data = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename, len(data))
|
||||
data += "\x90\x00"
|
||||
print "Updating card holder certificate"
|
||||
main(fileid, is_update, data)
|
||||
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
|
||||
6
tool/openocd-script/lock.tcl
Normal file
6
tool/openocd-script/lock.tcl
Normal file
@@ -0,0 +1,6 @@
|
||||
init
|
||||
reset
|
||||
halt
|
||||
stm32x lock 0
|
||||
reset
|
||||
exit
|
||||
5
tool/openocd-script/options_read.tcl
Normal file
5
tool/openocd-script/options_read.tcl
Normal file
@@ -0,0 +1,5 @@
|
||||
init
|
||||
reset
|
||||
halt
|
||||
stm32x options_read 0
|
||||
exit
|
||||
6
tool/openocd-script/unlock.tcl
Normal file
6
tool/openocd-script/unlock.tcl
Normal file
@@ -0,0 +1,6 @@
|
||||
init
|
||||
reset
|
||||
halt
|
||||
stm32x unlock 0
|
||||
reset
|
||||
exit
|
||||
5
tool/openocd-script/write.tcl
Normal file
5
tool/openocd-script/write.tcl
Normal file
@@ -0,0 +1,5 @@
|
||||
init
|
||||
reset
|
||||
halt
|
||||
flash write_image erase gnuk.elf
|
||||
exit
|
||||
Reference in New Issue
Block a user