Compare commits

...

138 Commits

Author SHA1 Message Date
NIIBE Yutaka
b619db59d2 version 1.0.3 2013-03-14 14:46:53 +09:00
NIIBE Yutaka
8870d58b69 stabilize stlinkv2.py 2013-03-14 14:02:23 +09:00
NIIBE Yutaka
4abcddef93 fix for newer GNU Toolchain 2013-03-14 13:24:35 +09:00
NIIBE Yutaka
ca46cc465c more 2013-03-12 14:49:52 +09:00
NIIBE Yutaka
3cf5ed482f more 2013-03-12 14:24:47 +09:00
NIIBE Yutaka
87d95d0864 more change for stlinkv2.py 2013-03-12 14:10:50 +09:00
NIIBE Yutaka
428adc7ac6 add changelog 2013-03-12 11:43:44 +09:00
NIIBE Yutaka
cc185eabb5 Improve initialization 2013-03-12 11:42:07 +09:00
NIIBE Yutaka
80e3cda267 change main.c for relocatable reGNUal 2013-03-09 10:18:24 +09:00
NIIBE Yutaka
ee867794e7 update regnual 2013-03-09 10:17:16 +09:00
NIIBE Yutaka
a4f7386b8a relocatable reGNUal 2013-03-09 10:16:51 +09:00
NIIBE Yutaka
7d4d6cff5e fix usb. 2013-03-07 13:07:31 +09:00
NIIBE Yutaka
b09460f0ae follow change of USB stack 2013-03-07 09:42:49 +09:00
NIIBE Yutaka
4298809ffb USB stack implementation improvement 2013-03-07 09:37:49 +09:00
NIIBE Yutaka
b297cf22b6 add changelog entry for the bug fix of usb-icc 2013-02-27 20:23:01 +09:00
NIIBE Yutaka
f84f52156c bug fix 2013-02-27 20:20:59 +09:00
NIIBE Yutaka
1564a4fbe6 Fix configure typo, type punning pointers 2013-02-25 15:46:02 +09:00
NIIBE Yutaka
16610ca5c7 Merge branch 'STABLE-BRANCH-1-0' of www.gniibe.org:git/gnuk into STABLE-BRANCH-1-0 2013-02-22 21:34:16 +09:00
NIIBE Yutaka
352f81a61f Add Quan to THANKS 2013-02-22 21:32:58 +09:00
NIIBE Yutaka
7c82839fba apply GPG_DO_DISCRETIONARY from master 2013-02-22 21:29:27 +09:00
NIIBE Yutaka
10c685be16 add Paul to THANKS (should be done at the beginning) 2013-02-20 16:56:10 +09:00
NIIBE Yutaka
ed61ed980d version 1.0.2 2013-02-15 11:45:52 +09:00
NIIBE Yutaka
7ff0baf5df test script changes 2013-02-14 16:59:41 +09:00
NIIBE Yutaka
46259ce63d fix Le field handling 2013-02-14 16:38:38 +09:00
NIIBE Yutaka
0aca10f307 fixes for removing update keys 2013-02-14 11:09:06 +09:00
NIIBE Yutaka
5f2a8b835c update documentation 2013-02-13 14:23:24 +09:00
NIIBE Yutaka
5213d9ab82 fix GET CHALLENGE 2013-02-13 13:32:38 +09:00
NIIBE Yutaka
c12f331217 fix typo in openpgp.c 2013-02-04 16:40:26 +09:00
NIIBE Yutaka
62b4369d2c minor change to external_authenticate 2013-01-30 16:50:19 +09:00
NIIBE Yutaka
9dde59867d Implement VERIFY with empty data 2013-01-28 12:10:14 +09:00
NIIBE Yutaka
eae955b15e try VEGA ALPHA specific change 2013-01-22 21:08:55 +09:00
NIIBE Yutaka
7e8dd12654 New tool/pageant_proxy_to_gpg.py 2013-01-21 12:10:25 +09:00
NIIBE Yutaka
8c91d2ef2e Use APPDATA for HOME equivalent 2013-01-21 12:09:33 +09:00
NIIBE Yutaka
6b6913c676 add tool/sexp.py 2013-01-21 12:05:06 +09:00
NIIBE Yutaka
3ad9373163 fix gpg_agent.py 2013-01-21 09:22:47 +09:00
NIIBE Yutaka
220d5c0307 Add tool/pageant_proxy_to_gpg.py 2013-01-20 21:18:21 +09:00
NIIBE Yutaka
de7f9f6417 improve 2013-01-20 21:17:43 +09:00
NIIBE Yutaka
a302585602 move 2013-01-20 20:40:34 +09:00
NIIBE Yutaka
ea2191105f improve gpg-agent.py 2013-01-20 20:40:19 +09:00
NIIBE Yutaka
32094099dd add tool/gpg-agent.py 2013-01-20 18:01:24 +09:00
NIIBE Yutaka
9b71d70b73 fix pinpadtest.py 2013-01-11 13:21:38 +09:00
NIIBE Yutaka
77d06fb301 tool/pinpadtest: add fixed length input 2013-01-11 12:16:50 +09:00
NIIBE Yutaka
78b642507b change the order of sections 2012-12-26 14:08:49 +09:00
NIIBE Yutaka
90a11859dc update doc (partially) 2012-12-26 11:11:18 +09:00
NIIBE Yutaka
ad9a901e1b upgrade_by_passwd.py 2012-12-25 14:47:49 +09:00
NIIBE Yutaka
500b12b60d update NEWS 2012-12-19 16:07:33 +09:00
NIIBE Yutaka
4bfe087583 add test/factory_upgrade.py 2012-12-19 15:53:07 +09:00
NIIBE Yutaka
22d0cb689a add regnual class 2012-12-19 13:13:52 +09:00
NIIBE Yutaka
fe6337f988 new methods for gnuk_token.py 2012-12-19 12:57:36 +09:00
NIIBE Yutaka
1a2560531d fix 2012-12-19 11:19:17 +09:00
NIIBE Yutaka
40e234b799 Use tool/gnuk_token.py 2012-12-19 10:44:50 +09:00
NIIBE Yutaka
deccb981ad minor: fix style 2012-12-19 10:04:45 +09:00
NIIBE Yutaka
12bd1161a4 password length check for adminlessmode 2012-12-14 10:31:46 +09:00
NIIBE Yutaka
d72a0b7893 fix src/openpgp-do.c 2012-12-14 09:53:16 +09:00
NIIBE Yutaka
ee5b6a2a82 fix tool/gnuk_remove_keys* 2012-12-12 15:30:40 +09:00
NIIBE Yutaka
f9b43a67ee Add tool/gnuk_remove_keys_libusb.py 2012-12-05 14:27:15 +09:00
NIIBE Yutaka
70846e8b81 add explanation for gnuk-personalization.rst 2012-11-12 10:49:27 +09:00
NIIBE Yutaka
f6df7701f9 add explanation for gnuk-personalization.rst 2012-11-12 10:44:44 +09:00
NIIBE Yutaka
b9772265cf proper bError value for time extension 2012-11-07 11:30:00 +09:00
NIIBE Yutaka
254c521c6f tool/gnuk_upgrade.py: Support non-smartcard auth 2012-11-01 09:18:55 +09:00
NIIBE Yutaka
d7c6b95ba1 add tool/get_raw_public_key.py 2012-10-31 16:23:19 +09:00
NIIBE Yutaka
2e7d93a556 change the product string 2012-10-26 11:05:33 +09:00
NIIBE Yutaka
db2d897c3f Update README and fix for STBEE_MINI 2012-10-13 08:40:37 +09:00
NIIBE Yutaka
23a9fe3bdc stlinkv2 fixes 2012-09-25 09:00:10 +09:00
NIIBE Yutaka
e8f773d2f6 fix stlinkv2.py 2012-09-18 15:32:12 +09:00
NIIBE Yutaka
6b5fc04c0d fix sha256 2012-09-12 14:16:40 +09:00
NIIBE Yutaka
39bee2ee01 Fix by Henry Hu 2012-08-29 13:16:27 +09:00
NIIBE Yutaka
f39380d3aa version 1.0.1 2012-08-03 11:20:13 +09:00
NIIBE Yutaka
0d36a58804 Add more doc 2012-08-03 11:15:26 +09:00
NIIBE Yutaka
eb0e913eee Add doc 2012-08-03 10:53:04 +09:00
NIIBE Yutaka
7575dda42a Add test for USB version string 2012-08-02 17:44:08 +09:00
NIIBE Yutaka
61ec9b7ed7 add doc 2012-08-02 17:11:42 +09:00
NIIBE Yutaka
b49390de7a add an entry in NEWS 2012-07-26 18:53:59 +09:00
NIIBE Yutaka
71eaffc0ee version 1.0 2012-07-21 09:36:25 +09:00
NIIBE Yutaka
5e9a35c881 doc 2012-07-21 09:27:08 +09:00
NIIBE Yutaka
df5b7f31a3 doc 2012-07-21 09:26:51 +09:00
NIIBE Yutaka
add6fa8b67 add document in Sphinx 2012-07-21 08:33:31 +09:00
NIIBE Yutaka
c488bed215 move old documents to doc/note 2012-07-21 08:32:53 +09:00
NIIBE Yutaka
63979416f6 fix tests for CERTDO 2012-07-20 16:00:41 +09:00
NIIBE Yutaka
92be182e8a update README for gcc-arm-embedded toolchain 2012-07-20 13:24:15 +09:00
NIIBE Yutaka
9ffa68355d update README for gcc-arm-embedded toolchain 2012-07-20 13:12:51 +09:00
NIIBE Yutaka
814f6b6329 update README 2012-07-20 13:04:39 +09:00
NIIBE Yutaka
1927f8a1ec update doc/ 2012-07-10 17:04:14 +09:00
NIIBE Yutaka
d3fb62b437 no keygen test cases 2012-07-10 17:03:50 +09:00
NIIBE Yutaka
5d3e6c2b29 initial PW1 123456 test cases 2012-07-10 14:16:53 +09:00
NIIBE Yutaka
8be278be17 not PW3 but PW1 2012-07-10 13:21:27 +09:00
NIIBE Yutaka
6de9c11329 test: fix signature counter 2012-07-10 10:36:15 +09:00
NIIBE Yutaka
63df97a2e0 Add tests 2012-07-10 08:55:48 +09:00
NIIBE Yutaka
144dd88a07 Bug fix for keygen 2012-07-10 08:51:38 +09:00
NIIBE Yutaka
e80c8f1e8e USB disconnect tool/stlinkv2.py 2012-07-10 08:50:32 +09:00
NIIBE Yutaka
99d7e8d396 reset is not needed as writ_prvkey does so 2012-07-09 15:16:56 +09:00
NIIBE Yutaka
f38f33dade bug fix for finish_gpio 2012-07-09 12:58:03 +09:00
NIIBE Yutaka
cbed6b49c7 LED off for -u 2012-07-09 10:19:01 +09:00
NIIBE Yutaka
51435e7dba return error sooner for decryption 2012-07-09 09:29:00 +09:00
NIIBE Yutaka
29b68186bf fix stlinkv2 for FST-01's LED 2012-07-09 09:27:38 +09:00
NIIBE Yutaka
a5fddc691d fix decryption test case 2012-07-09 09:26:10 +09:00
NIIBE Yutaka
965dace0a4 version 0.21 2012-07-06 10:21:58 +09:00
NIIBE Yutaka
ee4f3806c2 Add SPI flash ROM support for tool/stlinkv2.py 2012-07-06 10:03:10 +09:00
NIIBE Yutaka
9ad6c6461d SPI flash support starts for FST-01 2012-07-06 08:26:20 +09:00
NIIBE Yutaka
a796e9f145 RSA change 2012-07-05 09:32:46 +09:00
NIIBE Yutaka
f88e7af3ce add more tests 2012-07-05 09:26:58 +09:00
NIIBE Yutaka
fe31219d94 fix title 2012-07-05 09:13:32 +09:00
NIIBE Yutaka
6f97e8a7c4 Bug fix for s2k call 2012-07-05 09:12:04 +09:00
NIIBE Yutaka
e78206e1cd fix resetting ADMIN pass phrase in admi-less mode 2012-07-05 08:56:42 +09:00
NIIBE Yutaka
ffba0e0158 changelog 2012-07-04 06:00:14 +09:00
NIIBE Yutaka
324b648de8 test update 2012-07-03 19:32:15 +09:00
NIIBE Yutaka
9ef97836c9 Bug fix for changing PW3 2012-07-03 19:01:50 +09:00
NIIBE Yutaka
628c03634b Bug fix against flash GC 2012-07-03 18:36:24 +09:00
NIIBE Yutaka
315bef4639 Bug fix for PW1 2012-07-03 18:33:39 +09:00
NIIBE Yutaka
610573256e add new tests 2012-07-03 09:38:18 +09:00
NIIBE Yutaka
976e123413 more change for stlinkv2 2012-07-02 17:26:49 +09:00
NIIBE Yutaka
6f4c868336 file open with rb 2012-07-02 14:22:33 +09:00
NIIBE Yutaka
33c3980e46 fix stlinkv2.py (for Windows) 2012-07-02 13:55:21 +09:00
NIIBE Yutaka
6d8580f67a s2k 2012-06-30 07:49:40 +09:00
NIIBE Yutaka
506761d823 regnual cleanup 2012-06-29 13:45:37 +09:00
NIIBE Yutaka
09f22b114c update NEWS 2012-06-28 14:19:05 +09:00
NIIBE Yutaka
9f0b8ff4c3 removal of ~ 2012-06-28 12:58:58 +09:00
NIIBE Yutaka
2764bbb5a9 decryption test after keygen 2012-06-28 12:01:37 +09:00
NIIBE Yutaka
3202b7d45c add test for digital signature after keygen 2012-06-28 11:07:11 +09:00
NIIBE Yutaka
19e677ae74 add keygen test 2012-06-28 09:30:16 +09:00
NIIBE Yutaka
9cc6de9e65 naming: make it clear for crypt 2012-06-28 09:04:06 +09:00
NIIBE Yutaka
0988474d87 adding to gnuk.py 2012-06-28 09:03:15 +09:00
NIIBE Yutaka
d564e4a3c1 cleanup 2012-06-27 14:30:39 +09:00
NIIBE Yutaka
839b0156a9 more tests 2012-06-27 14:15:51 +09:00
NIIBE Yutaka
92d500d4b5 bug fix flash write and flash access before that while flash GC 2012-06-27 14:14:15 +09:00
NIIBE Yutaka
1944a78443 PW3 handling and signature counter 2012-06-27 13:10:12 +09:00
NIIBE Yutaka
e11d81376c key fingerprint and timestamp 2012-06-27 08:48:41 +09:00
NIIBE Yutaka
3c7a5bff61 fix string handling 2012-06-27 08:06:39 +09:00
NIIBE Yutaka
a41476ab32 add test 2012-06-26 17:59:24 +09:00
NIIBE Yutaka
1118cd030a usb_strings.py 2012-06-25 10:53:06 +09:00
NIIBE Yutaka
e6e11ddcb0 It's not like UNIX tools. 2012-06-22 17:00:35 +09:00
NIIBE Yutaka
5c5074c5c7 support FST-01 too 2012-06-22 15:33:03 +09:00
NIIBE Yutaka
d3f092a736 failure handling 2012-06-22 14:38:43 +09:00
NIIBE Yutaka
70efd3a1cd stlinkv2.py: Add blank check 2012-06-22 13:18:30 +09:00
NIIBE Yutaka
fd9f46bcc7 fix blank_check.S 2012-06-22 13:16:30 +09:00
NIIBE Yutaka
6f203bc4ea Add blank_check.S 2012-06-21 19:40:41 +09:00
NIIBE Yutaka
c25d98bc58 modify stlinkv2.py. 2012-06-20 17:31:27 +09:00
NIIBE Yutaka
4290a2cc10 ST-Link/V2 flash ROM writer 2012-06-20 14:44:20 +09:00
137 changed files with 7666 additions and 1257 deletions

4
.gitignore vendored
View File

@@ -11,9 +11,7 @@ src/gnuk.elf
src/gnuk.hex
src/gnuk.map
src/*.inc
regnual/sys.h
regnual/regnual.bin
regnual/regnual.hex
regnual/regnual.elf
regnual/usb_lld.c
regnual/usb_lld.h
doc/_build

489
ChangeLog
View File

@@ -1,3 +1,492 @@
2013-03-14 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.3.
* src/usb_desc.c (gnukStringSerial): Updated.
* tool/stlinkv2.py (stlinkv2.start): Call write_debug_reg to run
the core again.
2013-03-13 Niibe Yutaka <gniibe@fsij.org>
* ChibiOS_2.0.8/os/ports/GCC/ARMCMx/cmsis/core_cm3.c (__STREXB)
(__STREXH, __STREXW): Specify R2 to avoid %0 and %2 will be same
register. This is for newer GNU binutils (>= 2.22).
2013-03-12 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (stlinkv2.exit_from_debug_swd)
(stlinkv2.exit_from_debug_swim): New.
(stlinkv2.start): Call exit_from_debug_swd or
exit_from_debug_swim.
2013-03-09 Niibe Yutaka <gniibe@fsij.org>
* src/main.c (calculate_regnual_entry_address): New.
(main): Use calculate_regnual_entry_address for entry point.
2013-03-08 Niibe Yutaka <gniibe@fsij.org>
Relocatable reGNUal.
* regnual/regnual.ld (MEMORY): 0x1400 was the value of Gnuk 1.0.1.
Keep this value.
(.text): Include .text.entry next to the .vectors.
(.got): New.
* regnual/sys.c (entry): Now, it's at .text.entry section.
Do relocations.
Don't use absolute values which causes relocations, but
access at GOT.
* regnual/Makefile (CFLAGS): Add -fpie.
2013-03-07 Niibe Yutaka <gniibe@fsij.org>
* src/usb_stm32f103.c (handle_setup0): Fix selecting handler.
Follow the USB stack change.
* regnual/regnual.c (usb_cb_device_reset): Rename from
regnual_device_reset.
(mem): Change type to uint32_t.
(mem_info): Removed.
(fetch): Avoid pointer punning.
(usb_cb_ctrl_write_finish): Rename from regnual_ctrl_write_finish.
(usb_cb_setup): Rename from regnual_setup.
(usb_cb_get_descriptor): Rename from regnual_get_descriptor.
(usb_cb_handle_event): Rename regnual_usb_event.
(usb_cb_interface): Rename regnual_interface.
(Device_Method): Remove.
(usb_cb_get_descriptor): Not use struct Descriptor.
2013-03-06 Niibe Yutaka <gniibe@fsij.org>
USB stack implementation improvement.
* src/usb_lld.c (Device_Method, method_p): Remove.
(usb_interrupt_handler): Call usb_cb_device_reset.
(std_get_descriptor): Call usb_cb_get_descriptor.
(std_set_configuration): Call usb_cb_handle_event.
(std_get_status, std_get_interface, std_set_interface): Call
usb_cb_interface.
(handle_setup0): Call usb_cb_setup.
(handle_in0): Call usb_cb_handle_event and
usb_cb_ctrl_write_finish.
(request_handler): Remove.
(handle_setup0): Call std_* directly, not indirectly by
request_handler.
(ep_intr_handler_IN, ep_intr_handler_OUT): Remove.
(usb_handle_transfer): Call EP*_Callback directly, not indirectly
by ep_intr_handler_IN, ep_intr_handler_OUT.
* src/usb_lld.h (struct usb_device_method, Device_Method): Remove.
(usb_cb_device_reset, usb_cb_ctrl_write_finish)
(usb_cb_setup, usb_cb_get_descriptor, usb_cb_handle_event)
(usb_cb_interface): Define callbacks.
(usb_initial_feature): New.
(struct Descriptor): Move to ...
* src/usb_desc.c: ... here.
(usb_initial_feature): New.
(usb_cb_get_descriptor): Rename from gnuk_get_descriptor and move
from usb_ctrl.c.
* src/usb_ctrl.c (usb_cb_device_reset): Rename from
gnuk_device_reset.
(usb_cb_setup): Rename from gnuk_setup.
(usb_cb_ctrl_write_finish): Rename from gnuk_ctrl_write_finish.
(usb_cb_event): Rename from gnuk_usb_event.
(usb_cb_interface): Rename from gnuk_interface.
(Device_Method): Remove.
* src/main.c (main): Use usb_initial_feature.
2013-02-27 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (set_sw1sw2): Arguments are C and CHUNK_LEN.
Fix reporting remaining bytes.
(icc_send_data_block_gr): Follow the arguments change of
set_sw1sw2.
2013-02-25 Niibe Yutaka <gniibe@fsij.org>
* src/configure: Correct typo in help text.
* src/gnuk.h (struct key_data_internal): Use uint32_t.
* src/openpgp-do.c (do_openpgpcard_aid): Fix calculation of VID.
(compute_key_data_checksum): Don't use type-punning pointer.
(gpg_do_write_prvkey): Use coercing to char *.
2013-02-22 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (GPG_DO_DISCRETIONARY, cmp_discretionary): New.
(cmp_app_data): Change to factor out GPG_DO_DISCRETIONARY.
(gpg_do_table): Add GPG_DO_DISCRETIONARY.
2013-02-15 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.2.
* src/usb_desc.c (gnukStringSerial): Updated.
2013-02-14 Niibe Yutaka <gniibe@fsij.org>
* test/features/002_get_data_static.feature: Value of extended
capabilities changed.
* test/features/402_get_data_static.feature: Ditto.
* test/features/802_get_data_static.feature: Ditto.
* src/openpgp.c (cmd_write_binary): Move erasing page of update
keys to...
(modify_binary): ...here.
* src/flash.c (flash_write_binary): Handle removal of update keys.
2013-02-13 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_get_challenge): Handle Le field.
* src/openpgp-do.c (extended_capabilities): Fix for GET CHALLENGE.
* src/gnuk.h (CHALLENGE_LEN): Moved here (was: openpgp.c).
* tool/gnuk_token.py (iso7816_compose): Add Le field.
2013-01-30 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_external_authenticate): Fix off-by-one error.
* tool/gnuk_token.py (gnuk_token.cmd_external_authenticate): Add
KEYNO to the arguments.
* tool/upgrade_by_passwd.py (main): Explicitly say it's KEYNO.
2013-01-28 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_pw_get_retry_counter): New.
* src/openpgp.c (cmd_verify): Implement VERIFY with empty data.
2013-01-22 Niibe Yutaka <gniibe@fsij.org>
* tool/pinpadtest.py (Card.cmd_vega_alpha_disable_empty_verify):
New.
(main): call cmd_vega_alpha_disable_empty_verify if it's
COVADIS_VEGA_ALPHA.
2013-01-21 Niibe Yutaka <gniibe@fsij.org>
* tool/pageant_proxy_to_gpg.py: New.
* tool/sexp.py: New.
2013-01-20 Niibe Yutaka <gniibe@fsij.org>
* tool/gpg_agent.py: New.
2013-01-11 Niibe Yutaka <gniibe@fsij.org>
* tool/pinpadtest.py: Add fixed length input.
2012-12-25 Niibe Yutaka <gniibe@fsij.org>
* tool/rsa.py: New.
* tool/rsa_example.key: New. Example RSA key information.
* tool/upgrade_by_passwd.py: New.
2012-12-19 Niibe Yutaka <gniibe@fsij.org>
* src/Makefile.in (USE_OPT): -O3 and -Os (was: -O2).
* tool/gnuk_token.py (gnuk_token.stop_gnuk, gnuk_token.mem_info)
(gnuk_token.download, gnuk_token.execute)
(gnuk_token.cmd_get_challenge)
(gnuk_token.cmd_external_authenticate): New.
(gnuk_devices_by_vidpid): New.
(regnual): New.
2012-12-18 Niibe Yutaka <gniibe@fsij.org>
* test/gnuk.py: Remove.
* test/features/steps.py: Use tool/gnuk_token.py.
* tool/gnuk_put_binary_libusb.py: Use gnuk_token.py.
(main): Follow the API change.
* tool/gnuk_token.py (list_to_string): New.
(gnuk_token.get_string, gnuk_token.increment_seq)
(gnuk_token.reset_device, gnuk_token.release_gnuk): New.
(gnuk_token.icc_power_on): Set self.atr and it's now string.
(gnuk_token.icc_send_cmd): Handle time extension.
(gnuk_token.cmd_get_response): Return string (was: list).
(gnuk_token.cmd_get_data): Return "" when success.
(gnuk_token.cmd_change_reference_data, gnuk_token.cmd_put_data)
(gnuk_token.cmd_put_data_odd)
(gnuk_token.cmd_reset_retry_counter, gnuk_token.cmd_pso)
(gnuk_token.cmd_pso_longdata)
(gnuk_token.cmd_internal_authenticate, gnuk_token.cmd_genkey)
(gnuk_token.cmd_get_public_key): New.
(compare): New.
(get_gnuk_device): New.
2012-12-14 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_change_password): Check password length
for admin less mode.
2012-12-13 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp-do.c (gpg_do_put_data): Add GPG_SUCCESS for
completeness (it worked because of lower layer goodness).
2012-12-12 Niibe Yutaka <gniibe@fsij.org>
* tool/gnuk_token.py: Add module imports.
* tool/gnuk_remove_keys.py (main): Fix data object number
for KGTIME_SIG, KGTIME_DEC and KGTIME_AUT.
* tool/gnuk_remove_keys_libusb.py (main): Likewise.
2012-12-05 Niibe Yutaka <gniibe@fsij.org>
* tool/gnuk_remove_keys_libusb.py: New.
* tool/gnuk_token.py: New.
2012-11-07 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (icc_send_data_block_internal): New.
(icc_send_data_block_time_extension): New.
(icc_handle_timeout): Use icc_send_data_block_time_extension.
(icc_send_data_block): Only one argument.
(USBthread): Follow the change.
2012-11-01 Niibe Yutaka <gniibe@fsij.org>
* tool/gnuk_upgrade.py (main): New option '-k' to specify keygrip
for non-smartcard key.
(gpg_sign): Support non-smartcard key.
2012-10-31 Niibe Yutaka <gniibe@fsij.org>
* tool/get_raw_public_key.py: New.
2012-10-26 Niibe Yutaka <gniibe@fsij.org>
* GNUK_USB_DEVICE_ID (Product_STRING): It's considered better not
to include vendor name. Change the name to "Gnuk Token" (was:
FSIJ USB Token).
2012-10-13 Niibe Yutaka <gniibe@fsij.org>
* boards/STBEE_MINI/board.c [!DFU_SUPPORT] (hwinit1): Don't run
when "user switch" is pushed. This is for JTAG/SWD debugger.
2012-09-25 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (main): Print out option bytes value.
Call reset_sys before blank_check.
2012-09-18 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (stlinkv2.option_bytes_erase)
(stlinkv2.flash_erase_all, stlinkv2.flash_erase_page): : Fix
OperationFailure (was OperationError).
(main): Call option_bytes_erase if it's not 0xff.
2012-09-12 Niibe Yutaka <gniibe@fsij.org>
* src/sha256.c: Include <stdint.h>.
* src/sha256.h (SHA256_DIGEST_SIZE, SHA256_BLOCK_SIZE): Move
from sha256.c.
2012-08-29 Niibe Yutaka <gniibe@fsij.org>
* tool/hub_ctrl.py (__main__): Fix to busnum (was: bunum).
Thanks to Henry Hu.
2012-08-03 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.1.
* src/usb_desc.c (gnukStringSerial): Updated.
* src/main.c (ID_OFFSET): Fix.
2012-08-02 Niibe Yutaka <gniibe@fsij.org>
* test/gnuk.py (gnuk_token.get_string): New.
* test/features/991_version_string.feature: New.
2012-07-21 Niibe Yutaka <gniibe@fsij.org>
* Version 1.0.
* src/usb_desc.c (gnukStringSerial): Updated.
Documentation by Sphinx.
* doc/Makefile: New.
* doc/note: Old notes are moved here.
2012-07-20 Niibe Yutaka <gniibe@fsij.org>
* test/features/002_get_data_static.feature: Support CERTDO enabled
Gnuk for the test of extended capabilities.
* test/features/802_get_data_static.feature: Ditto.
* test/features/402_get_data_static.feature: Ditto.
2012-07-10 Niibe Yutaka <gniibe@fsij.org>
* test/features/*: Add test cases for PW1/PW3 of factory settings.
* test/features/202_keygen.feature: Add PSO signature test after
keygen.
* test/features/602_keygen.feature: Ditto.
Bug fix.
* src/openpgp-do.c (gpg_do_write_prvkey): Don't call ac_reset_*
here.
(proc_key_import): But call ac_reset_* here.
(gpg_do_keygen): Load private key for signing.
* tool/stlinkv2.py (stlinkv2.usb_disconnect): New.
2012-07-09 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (cmd_pso): For decryption, return error sooner for
invalid data.
* tool/stlinkv2.py (stlinkv2.setup_gpio): Fix GPIOB_CRL.
* test/rsa_keys.py (integer_to_bytes_256): Rename from
integer_to_bytes and it should be exactly 256-byte long.
2012-07-06 Niibe Yutaka <gniibe@fsij.org>
* Version 0.21.
* src/usb_desc.c (gnukStringSerial): Updated.
* boards/FST_01/board.h (VAL_GPIOACRL): Change for SPI flash.
* tool/stlinkv2.py (stlinkv2.setup_gpio): Likewise.
(stlinkv2.spi_flash_init, stlinkv2.spi_flash_select)
(stlinkv2.spi_flash_sendbyte, stlinkv2.spi_flash_read_id): New.
(main): Add SPI flash ROM id check.
2012-07-05 Niibe Yutaka <gniibe@fsij.org>
* src/call-rsa.c (rsa_sign, rsa_decrypt): Don't need to setup N.
* polarssl-0.14.0/library/rsa.c (rsa_check_pubkey)
(rsa_check_privkey): Ifdef-out.
More tests.
* test/*: Add tests for admin-less mode.
* test/features/990_reset_passphrase.feature: This is now for
admin-less mode.
* test/features/970_key_removal.feature: Ditto.
* src/openpgp.c (cmd_change_password): Call ac_reset_admin when
admin-less mode.
(cmd_reset_user_password): Likewise.
* src/ac.c (ac_reset_admin, ac_fini): Clear ADMIN_AUTHORIZED.
Bug fix.
* src/ac.c (verify_admin): Call s2k with ADMIN_AUTHORIZED.
2012-07-04 Niibe Yutaka <gniibe@fsij.org>
Bug fixes.
* src/ac.c (verify_admin_0): Compare PW_LEN and BUF_LEN.
* src/openpgp-do.c (gpg_do_chks_prvkey): Set do_ptr to NULL before
calling flash_do_write (which might cause GC).
(gpg_do_put_data, gpg_do_write_simple): Likewise.
* src/openpgp.c (cmd_reset_user_password): Write to
DO_KEYSTRING_PW1.
2012-07-03 Niibe Yutaka <gniibe@fsij.org>
* test/features/040_passphrase_change.feature: New.
* test/features/203_passphrase_change.feature: New.
* test/features/210_compute_signature.feature: Rename (was:
203_compute_signature.feature)
* test/features/211_decryption.feature: Rename (was:
204_decryption.feature)
2012-07-02 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (stlinkv2.__init__): Don't call setAltInterface.
2012-06-30 Niibe Yutaka <gniibe@fsij.org>
* src/openpgp.c (s2k): New.
(resetcode_s2k): Remove.
(cmd_reset_user_password, cmd_change_password): Use s2k (was:
sha256 directly or resetcode_s2k).
* src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey):
Likewise.
* src/ac.c (verify_user_0, verify_admin): Likewise.
2012-06-29 Niibe Yutaka <gniibe@fsij.org>
* regnual/Makefile: Don't copy usb_lld.c.
2012-06-28 Niibe Yutaka <gniibe@fsij.org>
* test/features/204_decryption.feature: New.
* test/features/203_compute_signature.feature: New.
* test/features/202_keygen.feature: New.
* test/features/201_setup_passphrase.feature: New.
* test/features/200_key_removal.feature: New.
* test/rsa_keys.py (verify_signature): New.
(encrypt_with_pubkey): New.
* test/gnuk.py (gnuk_token): New method: increment_seq.
(gnuk_token.icc_send_cmd): Handle timeout.
(gnuk_token.cmd_genkey): New.
(gnuk_token.cmd_get_public_key): New.
2012-06-27 Niibe Yutaka <gniibe@fsij.org>
* test/features/101_decryption.feature: New.
* test/features/100_compute_signature.feature: New.
* src/openpgp-do.c (gpg_do_chks_prvkey): Call flash_do_release before
flash_do_write.
(gpg_do_write_prvkey): Bug fix when GC occurs.
* src/openpgp.c (cmd_change_password): Support resetting to
factory setting of PW3.
* src/openpgp-do.c (gpg_do_write_prvkey): Don't reset signagure
counter here.
(proc_key_import): But reset here.
Call ac_reset_* when key is imported.
2012-06-26 Niibe Yutaka <gniibe@fsij.org>
* test: New.
2012-06-25 Niibe Yutaka <gniibe@fsij.org>
* tool/usb_strings.py: New.
2012-06-22 Niibe Yutaka <gniibe@fsij.org>
* tool/stlinkv2.py (stlinkv2.blank_check): Add blank check of
Flash ROM.
2012-06-21 Niibe Yutaka <gniibe@fsij.org>
* tool/asm-thumb/blank_check.S: New.
2012-06-20 Niibe Yutaka <gniibe@fsij.org>
ST-Link/V2 flash ROM writer.
* tool/stlinkv2.py: New.
* tool/asm-thumb/opt_bytes_write.S: New.
* tool/asm-thumb/flash_write.S: New.
2012-06-19 Niibe Yutaka <gniibe@fsij.org>
* Version 0.20.

View File

@@ -731,7 +731,7 @@ uint32_t __LDREXW(uint32_t *addr)
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
@@ -748,7 +748,7 @@ uint32_t __STREXB(uint8_t value, uint8_t *addr)
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
@@ -765,7 +765,7 @@ uint32_t __STREXH(uint16_t value, uint16_t *addr)
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
register uint32_t result asm ("r2");
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);

View File

@@ -1,3 +1,3 @@
# VID:PID bcdDev Product_STRING Vender_STRING
234b:0000 0200 FSIJ USB Token Free Software Initiative of Japan
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
##########<TAB> ##<TAB> ##########<TAB> #################

96
NEWS
View File

@@ -1,5 +1,99 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.0.3
Released 2013-03-14, by NIIBE Yutaka
** Relocatable reGNUal
The upgrade helper, reGNUal, is now relocatable (other than the first
vector table). It runs well when loaded at different address. This
makes the upgrade procedure more stable.
** Compilation by newer GNU Toolchain
Now, Gnuk can be compiled with newer GNU Toolchain, specifically GCC
4.7.x and GNU Binutils 2.22. Old versions of Gnuk had problem for
ChibiOS_2.0.8/os/ports/GCC/ARMCMx/cmsis/core_cm3.c, which was fixed.
** Data object 0x0073
Data object 0x0073 is now available.
* Major changes in Gnuk 1.0.2
Released 2013-02-15, by NIIBE Yutaka
** Product string is now "Gnuk Token" (was: "FSIJ USB Token")
Since the USB ID Repository suggests not including vendor name
in product string, we changed the product string.
** New tool (experimental): test/upgrade_by_passwd.py
This is the tool to install new firmware to Gnuk Token, provided
that it's just shipped from factory (and nothing changed). It
authenticate as admin by factory setting, register a public key
for firmware upgrade, and then, does firmware upgrade.
** tool/gnuk_upgrade.py supports '-k' option
It now supports RSA key on the host PC (not the one on the Token).
** New tool: tool/get_raw_public_key.py
This is a script to dump raw data of RSA public key, which is useful
to register to Gnuk Token as a firmware upgrade key.
** New tool: tool/gnuk_remove_keys_libusb.py
This tool is libusb version of gnuk_remove_keys.py. Besides, a bug in
gnuk_remove_keys.py was fixed.
** CCID protocol fix
When time extension is requested by Gnuk Token to host PC, argument
field was 0, which was wrong (but it works for most PC/SC
implementations and GnuPG internal driver). Now it's 1, which means
1*BWT.
** OpenPGP card protocol enhancement
Now, VERIFY command accepts empty data and returns remaining trial
counts, or 0x9000 (OK) when it's already authenticated. This is
useful for application to synchronize card's authentication status.
** Extended Capabilities
Since Gnuk supports GET CHALLENGE command, the flag for GET CHALLENGE
in extended capabilities are now on.
* Major changes in Gnuk 1.0.1
Released 2012-08-03, by NIIBE Yutaka
** USB SerialNumber String
In 1.0, it has a bug for USB SerialNumber String. It has been fixed
in 1.0.1.
* Major changes in Gnuk 1.0
Released 2012-07-21, by NIIBE Yutaka
This is bug fixes only release.
* Major changes in Gnuk 0.21
Released 2012-07-06, by NIIBE Yutaka
** Test suite
A functinality test suite is added under test/ directory.
** New tool: stlinkv2.py
This tool is SWD flash ROM writer with ST-Link/V2.
** New tool: usb_strings.py
This tool is to dump USB strings, which include revision detail and config
options.
** Protection improvement (even when internal data is disclosed)
Even if PW1 and PW3 is same, content of encrypted DEK is different
now.
* Major changes in Gnuk 0.20
Released 2012-06-19, by NIIBE Yutaka
@@ -23,7 +117,7 @@ Keystring is now computed by SHA-256 (it was SHA1 before).
** Protection improvements (even when internal data is disclosed)
Three improvements. (1) Even if PW1 and Reset-code is same, content
of encripted DEK is different now. (2) DEK is now encrypted and
of encrypted DEK is different now. (2) DEK is now encrypted and
decrypted by keystring in ECB mode (it was just a kind of xor by
single block CFB mode). (3) Key data plus checksum are encrypted in
CFB mode with initial vector (it will be able to switch OCB mode

132
README
View File

@@ -1,7 +1,7 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 0.20
2012-06-19
Version 1.0.3
2013-03-14
Niibe Yutaka
Free Software Initiative of Japan
@@ -14,9 +14,9 @@ STM32F103 processor.
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
been nervous of storing secret key(s) on usual secondary storage.
There is a solution with OpenPGP card, but it is not the choice for me
to bring a card reader all the time. With Gnuk, this issue will be
solved by a USB token which is small enough.
There is a solution with OpenPGP card, but it is not the choice for
me, as card reader is not common device. With Gnuk, this issue will
be solved by a USB token.
Please look at the graphics of "gnuk.svg" for the software name. My
son used to be with his NUK(R), always, everywhere. Now, I am with a
@@ -30,23 +30,19 @@ Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, GPF Crypto Stick, etc.) ?
http://www.g10code.de/p-card.html
http://www.privacyfoundation.de/crypto_stick/
A0: IMRHO, not quite, since there is no ready-to-use out-of-box Gnuk
product yet. (It is welcome for me that some vendor will
manufacture Gnuk USB Token. Even I can help design of hardware,
if needed.)
Good points for Gnuk are:
A0: Good points of Gnuk are:
* If you have skill of electronics and like DIY, you can build
Gnuk Token cheaper (see Q8-A8).
* You can study Gnuk to modify and to enhance. For example, you
can implement your own authentication method with some sensor
such as acceleration sensor.
such as an acceleration sensor.
* It is "of Free Software"; Gnuk is distributed under GPLv3+,
"by Free Software"; Gnuk development requires only Free Software
(GNU Toolchain, Python, etc.),
"for Free Software"; Gnuk supports GnuPG.
Q1: What kind of key algorithm is supported?
A1: Gnuk only supports 2048-bit RSA.
A1: Gnuk version 1 only supports 2048-bit RSA.
Q2: How long does it take for digital signing?
A2: It takes a second and a half or so.
@@ -55,24 +51,25 @@ Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103.
If you have skill of electronics and like DIY, STM32 part of STM8S
Discovery Kit might be the best choice.
Currently FST-01 (Flying Stone Tiny 01) is under development,
it will be the best choice, hopefully.
FST-01 (Flying Stone Tiny 01) will be soon available for sale,
and it will be the best choice, hopefully.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use gnupg 1.4.11-3 and gnupg-agent
2.0.14-2 (in sid). With older versions, you can only sign with SHA1.
2.0.18-2. With older versions, you can only sign with SHA1.
See: http://www.fsij.org/gnuk/gnupg2-fixes-needed
Q5: What's version of pcscd and libccid are you using?
A5: In Debian GNU/Linux system, I use pcscd 1.5.5-4 and libccid 1.3.11-2,
which is in squeeze. Note that you need to edit /etc/libccid_Info.plist
when using libccid (< 1.4.1).
Note that pcscd and libccid are optional, you can use Gnuk without them.
Q6: What kinds of hardware is required for development?
A6: You need a target board plus a JTAG debugger. If you just want to
test Gnuk for target boards with DfuSe, JTAG debugger is not
the requirement. Note that for real use, you need JTAG debugger
to enable flash ROM protection.
A6: You need a target board plus a JTAG/SWD debugger. If you just
want to test Gnuk for target boards with DfuSe, JTAG debugger is
not the requirement. Note that for real use, you need JTAG/SWD
debugger to enable flash ROM protection.
Q7: How much does it cost?
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
@@ -83,13 +80,18 @@ A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build
http://www.fsij.org/gnuk/jtag_dongle_ftdi2232
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
card/reader (problems are fixed in trunk). When your newly
inserted token is not found by GnuPG, try killing scdaemon and let
it to be invoked again. I do:
$ killall -9 scdaemon
card/reader (problems are fixed in trunk, and backported to 2.0
branch, it will be 2.0.20). When your newly inserted token is not
found by GnuPG, try killing scdaemon and let it to be invoked
again. I do:
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
and confirm scdaemon doesn't exist, then,
$ gpg-connect-agent learn /bye
$ gpg-connect-agent learn /bye
Qa: With GNOME 2, I can't use Gnuk Token for SSH. How can we use it for SSH?
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
@@ -106,17 +108,23 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
"GPG Password Agent" and "SSH Key Agent".
Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: STLink v2 is cheap one. See http://code.google.com/p/arm-utilities/
for a control program.
Ac: ST-Link/V2 is cheap one and works, although it's not very good
(for example, we have not yet been able to use OpenOCD to write
option bytes of STM32F103). We have a tool/stlinkv2.py as a flash
ROM writer program. Note that some "Discovery Kit" from ST has
the feature of ST-Link/V2, but it is not as stable as the real
one.
Release notes
=============
This is "version 1.0 release candidate" of Gnuk. In this release, key
generation feature is added. While it is daily use, some features
(including key generation and firmware upgrade) are still considered
experimental.
This is a third minor release in version 1.0 series of Gnuk.
While it is daily use for a year and a half, some newly introduced
features (including key generation and firmware upgrade) should be
considered experimental.
Tested features are:
@@ -133,13 +141,16 @@ Tested features are:
* Changing value of password status bytes (0x00C4): forcesig
* Verify with pin pad
* Modify with pin pad
* Card holder certificate
* Removal of keys (Overriding key import is not supported,
* Card holder certificate (read)
* Removal of keys
(Overriding key import is not supported,
but you can remove all keys to import again).
* Key generation on device side
Original feature of Gnuk, tested (lightly):
Original features of Gnuk, tested lightly:
* OpenPGP card serial number setup
* Card holder certificate (write by UPDATE BINARY)
* Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal
It is known not-working well:
@@ -148,11 +159,11 @@ It is known not-working well:
work well. Please make sure to disable DEBUG option if it
doesn't work well.
It is known that the combination libccid 1.4.1 (or newer) with libusb
1.0.8 (or older) has a problem. It is possible for USB communication
to be failed, because of a bug in libusb implementation. Use libusbx
1.0.9 or newer, or don't use PC/SC, but use internal CCID driver of
GnuPG.
It is known that the combination of libccid 1.4.1 (or newer) with
libusb 1.0.8 (or older) has a minor problem. It is rare but it is
possible for USB communication to be failed, because of a bug in
libusb implementation. Use libusbx 1.0.9 or newer, or don't use
PC/SC, but use internal CCID driver of GnuPG.
Targets
@@ -168,7 +179,7 @@ disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger.
I think that it could run on Olimex STM32-P103, or other boards with
STM32F103. Besides, we are porting it to STM32 Primer 2.
STM32F103. Besides, we did an experiment with STM32 Primer 2.
For PIN-pad support, I connect a consumer IR receive module to STBee
Mini and STM8S Discovery Kit, and use controller for TV. PIN
@@ -255,9 +266,8 @@ please contact Niibe, so that it is listed to the file in the official
release of the source code.
When you are modifing Gnuk and installing the binary to device, you
should replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to
yours, so that the device will say it's modified version by device
serial number.
should replace the vendor string to yours, so that users can see it's
not by original vendor, and it is modified version.
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices
with Gnuk under one of following conditions:
@@ -288,15 +298,16 @@ respect users' freedom for computing. Please ask FSIJ for the
license.
Otherwise, companies which want to distribute Gnuk devices, please use
your own USB vendor ID and product ID. Note that please replace
"FSIJ" in the string gnukStringSerial (usb_desc.c) to yours, when you
modify Gnuk.
your own USB vendor ID and product ID. Please replace vendor string
and possibly product string to yours, when you modify Gnuk.
Host Requirements
=================
For GNU/Linux, libccid version >= 1.3.11 is recommended.
For GNU/Linux, PC/SC service is an option, you can use GnuPG's
internal CCID driver instead. If you chose using PC/SC service,
libccid version >= 1.3.11 is recommended for GNU/Linux.
I think that it should not be requirment but the kernel version of my use is:
Linux version 2.6.32-5-686 (Debian 2.6.32-18) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-2) ) #1 SMP Sat Jul 24 02:27:10 UTC 2010
@@ -312,7 +323,7 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
See http://github.com/esden/summon-arm-toolchain/ (which includes fix
of binutils-2.21.1) for preparation of GNU Toolchain for
'arm-none-eabi' target.
'arm-none-eabi' target. This is for GCC 4.5.
# Note that we need to link correct C library (for string functions).
# For this purpose, Makefile.in contains following line:
@@ -328,6 +339,12 @@ of binutils-2.21.1) for preparation of GNU Toolchain for
# -mno-thumb-interwork option. This means that you should not
# link C library which contains ARM (not Thumb) code.
Recently, there is "gcc-arm-embedded" project. See:
https://launchpad.net/gcc-arm-embedded/
It is based on GCC 4.6 or 4.7.
Change directory to `src':
@@ -475,7 +492,7 @@ PyUSB (python-usb package in Debian).
If scdaemon is running, please kill it, or you will get "Smartcard
Exception" by "Sharing violation".
$ killall -9 scdaemon
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
In case of PyUSB tool, you need to stop pcscd.
@@ -554,11 +571,15 @@ This entry has been added into libccid 1.4.1 already ([r5425]).
Testing Gnuk
------------
Try following to see Gnuk runs:
Type following command to see Gnuk runs:
$ gpg --card-status
Besides, there is a functinality test under test/ directory. See
test/README.
Personalize the Token and import keys
-------------------------------------
@@ -578,7 +599,7 @@ RSA), you can import them.
Gnuk supports key generation, but this feature is young and should be
considered experimental.
For detail, please see doc/DEMO and doc/DEMO-2.
For detail, please see doc/note/DEMO and doc/note/DEMO-2.
Note that it make sense to preserve your keys on your computer so that
you can import the keys (again) to (possibly another) Gnuk Token. In
@@ -640,13 +661,14 @@ linux/Documentation/usb/usbmon.txt
Firmware update
===============
See doc/firmware-update.
See doc/note/firmware-update. Note that this is an experimental
feature.
Read-only Git Repository
========================
Git Repositories
================
You can browse at http://www.gniibe.org/gitweb?p=gnuk.git;a=summary
You can browse at: http://www.gniibe.org/gitweb?p=gnuk.git;a=summary
You can get it by:
@@ -657,6 +679,8 @@ or
$ git clone http://www.gniibe.org/git/gnuk.git/
Copy is available at: http://gitorious.org/gnuk
Information on the Web
======================

5
THANKS
View File

@@ -1,3 +1,5 @@
-*- coding: utf-8 -*-
We would like to express our gratitudes to Werner Koch for GnuPG, and
Giovanni Di Sirio for ChibiOS/RT.
@@ -11,7 +13,10 @@ Hironobu SUZUKI hironobu@h2np.net
Jan Suhr jan@suhr.info
Kaz Kojima kkojima@rr.iij4u.or.jp
Ludovic Rousseau ludovic.rousseau@free.fr
Luis Felipe R. Murillo luisfelipe@ucla.edu
MATSUU Takuto matsuu@gentoo.org
NAGAMI Takeshi nagami-takeshi@aist.go.jp
Nguyễn Hồng Quân quannguyen@mbm.vn
Paul Bakker polarssl_maintainer@polarssl.org
Shane Coughlan scoughlan@openinventionnetwork.com
Werner Koch wk@gnupg.org

View File

@@ -97,12 +97,15 @@
* PA0 - input with pull-up (TIM2_CH1)
* PA1 - input with pull-down (TIM2_CH2)
* PA2 - input with pull-up (TIM2_CH3)
* PA4 - Push pull output (SPI1_NSS)
* PA5 - Alternate Push pull output (SPI1_SCK)
* PA6 - Alternate Push pull output (SPI1_MISO)
* PA7 - Alternate Push pull output (SPI1_MOSI)
* PA10 - Push pull output (USB 1:ON 0:OFF)
* PA11 - input with pull-up (USBDM)
* PA12 - input with pull-up (USBDP)
* Everything input with pull-up except:
* PA10 - Push pull output (USB 1:ON 0:OFF)
*/
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIOACRL 0xBBB38888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888388 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFD

View File

@@ -9,6 +9,15 @@ hwinit1 (void)
{
hwinit1_common ();
#if !defined(DFU_SUPPORT)
if (palReadPad (IOPORT3, GPIOC_BUTTON) == 0)
/*
* Since LEDs are connected to JTMS/SWDIO and JTDI pin,
* we can't use LED to let know users in this state.
*/
for (;;); /* Wait for JTAG debugger connection */
#endif
#if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT)
palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */
while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0)

153
doc/Makefile Normal file
View File

@@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER = a4
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GnukDocumentation.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GnukDocumentation.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/GnukDocumentation"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GnukDocumentation"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

3
doc/__update_web Normal file
View File

@@ -0,0 +1,3 @@
cd _build
rsync -rntpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/
rsync -rtpv html/ atom.fsij.org:/home/fsij/gnuk-doc-html/

246
doc/conf.py Normal file
View File

@@ -0,0 +1,246 @@
# -*- coding: utf-8 -*-
#
# Gnuk Documentation documentation build configuration file, created by
# sphinx-quickstart on Wed Jul 4 15:29:05 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Gnuk Documentation'
copyright = u'2012, NIIBE Yutaka'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'GnukDocumentationdoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'GnukDocumentation.tex', u'Gnuk Documentation Documentation',
u'NIIBE Yutaka', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'gnukdocumentation', u'Gnuk Documentation Documentation',
[u'NIIBE Yutaka'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'GnukDocumentation', u'Gnuk Documentation Documentation',
u'NIIBE Yutaka', 'GnukDocumentation', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}

71
doc/development.rst Normal file
View File

@@ -0,0 +1,71 @@
Development Environment
=======================
Hardware
--------
For development, it is highly recommended to have JTAG/SWD debugger.
For boards with DFU (Device Firmware Upgrade) feature (such as DfuSe),
it is possible to develop with that. But it should be considered
*experimental* environment, and it should not be used for usual
purpose. That's because it is basically impossible for DfuSe
implementations to disable reading-out from flash ROM. It means
that your secret will be readily extracted by DfuSe.
For JTAG debugger, Olimex JTAG-Tiny is good and supported well. For
SWD debugger, ST-Link/V2 would be good, and it is supported by
tool/stlinkv2.py.
OpenOCD
-------
For JTAG/SWD debugger, we can use OpenOCD.
Note that ST-Link/V2 is *not* supported by OpenOCD 0.5.0. It is
supported by version 0.6 or later.
GNU Toolchain
-------------
You need GNU toolchain and newlib for 'arm-none-eabi' target.
There is "gcc-arm-embedded" project. See:
https://launchpad.net/gcc-arm-embedded/
It is based on GCC 4.6. You'd need "-O3 -Os" instead of "-O2" and it
will be slightly better.
Note that we need to link correct C library (for string functions).
For this purpose, our src/Makefile.in contains following line:
MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
This should not be needed (as -mcpu=cortex-m3 means
-mfix-cortex-m3-ldrd), but it was needed for the configuration of
patch-gcc-config-arm-t-arm-elf.diff in summon-arm-toolchain in practice.
Building Gnuk
-------------
Change directory to ``src``:
$ cd gnuk-VERSION/src
Then, run ``configure``:
$ ./configure --vidpid=<VID:PID>
Here, you need to specify USB vendor ID and product ID. For FSIJ's,
it's: --vidpid=234b:0000 . Please read the section 'USB vendor ID and
product ID' in README.
Type:
$ make
Then, we will have "gnuk.elf".

View File

@@ -0,0 +1,311 @@
============================
Generating 2048-bit RSA keys
============================
In this section, we describe how to generate 2048-bit RSA keys.
Key length of RSA
=================
In 2005, NIST (National Institute of Standards and Technology, USA)
has issued the first revision of NIST Special Publication 800-57,
"Recommendation for Key Management".
In 800-57, NIST advises that 1024-bit RSA keys will no longer be
viable after 2010 and advises moving to 2048-bit RSA keys. NIST
advises that 2048-bit keys should be viable until 2030.
As of 2010, GnuPG's default for generating RSA key is 2048-bit.
Some people have preference on RSA 4096-bit keys, considering
"longer is better".
However, "longer is better" is not always true. When it's long, it
requires more computational resource, memory and storage, and it
consumes more power for nomal usages. These days, many people has
enough computational resource, that would be true, but less is better
for power consumption.
For security, the key length is a single factor. We had and will have
algorithm issues, too. It is true that it's difficult to update
our public keys, but this problem wouldn't be solved by just have
longer keys.
We deliberately support only RSA 2048-bit keys for Gnuk, considering
device computation power and host software constraints.
Thus, the key size is 2048-bit in the examples below.
Generating keys on host PC
==========================
Here is the example session to generate main key and a subkey for encryption.
I invoke GnuPG with ``--gen-key`` option. ::
$ gpg --gen-key
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
and GnuPG asks kind of key. Select ``RSA and RSA``. ::
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
and select 2048-bit (as Gnuk Token only supports this). ::
What keysize do you want? (2048)
Requested keysize is 2048 bits
and select expiration of the key. ::
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Confirm key types, bitsize and expiration. ::
Is this correct? (y/N) y
Then enter user ID. ::
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
Real name: Niibe Yutaka
Email address: gniibe@fsij.org
Comment:
You selected this USER-ID:
"Niibe Yutaka <gniibe@fsij.org>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
and enter passphrase for this **key on host PC**.
Note that this is a passphrase for the key on host PC.
It is different thing to the password of Gnuk Token.
We enter two same inputs two times
(once for passphrase input, and another for confirmation). ::
You need a Passphrase to protect your secret key.
<PASSWORD-KEY-ON-PC>
Then, GnuPG generate keys. It takes some time. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
...+++++
+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
..+++++
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 15 more bytes)
...+++++
gpg: key 28C0CD7C marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
pub 2048R/4CA7BABE 2010-10-15
Key fingerprint = 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
uid Niibe Yutaka <gniibe@fsij.org>
sub 2048R/084239CF 2010-10-15
$
Done.
Then, we create authentication subkey.
Authentication subkey is not that common,
but very useful (for SSH authentication).
As it is not that common, we need ``--expert`` option for GnuPG. ::
$ gpg --expert --edit-key 4CA7BABE
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
[ultimate] (1). Niibe Yutaka <gniibe@fsij.org>
gpg>
Here, it displays that there are main key and a subkey.
It prompts sub-command with ``gpg>`` .
Here, we enter ``addkey`` sub-command.
Then, we enter the passphrase of **key on host PC**.
It's the one we entered above as <PASSWORD-KEY-ON-PC>. ::
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Niibe Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
<PASSWORD-KEY-ON-PC>
gpg: gpg-agent is not available in this session
GnuPG asks kind of key. We select ``RSA (set your own capabilities)``. ::
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
Your selection? 8
And select ``Authenticate`` for the capabilities for this key.
Initially, it's ``Sign`` and ``Encrypt``.
I need to deselect ``Sign`` and ``Encrypt``, and select ``Authenticate``.
To do that, I enter ``s``, ``e``, and ``a``. ::
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? e
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? a
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
OK, we set the capability of ``Authenticate``.
We enter ``q`` to finish setting capabilities. ::
Your selection? q
GnuPG asks bitsize and expiration, we enter 2048 for bitsize and no expiration.
Then, we confirm that we really create the key. ::
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
Then, GnuPG generate the key. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.......+++++
+++++
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ultimate] (1). Niibe Yutaka <gniibe@fsij.org>
gpg>
We save the key (to the storage of the host PC. ::
gpg> save
$
Now, we have three keys (one primary key for signature and certification,
subkey for encryption, and another subkey for authentication).
Publishing public key
=====================
We make a file for the public key by ``--export`` option of GnuPG. ::
$ gpg --armor --output <YOUR-KEY>.asc --export <YOUR-KEY-ID>
We can publish the file by web server. Or we can publish the key
to a keyserver, by invoking GnuPG with ``--send-keys`` option. ::
$ gpg --keyserver pool.sks-keyservers.net --send-keys <YOUR-KEY-ID>
Here, pool.sks-keyservers.net is a keyserver, which is widely used.
Backup the private key
======================
There are some ways to back up private key, such that backup .gnupg
directory entirely, use of paperkey. Here we describe backup by ASCII
file. ASCII file is good, because it has less risk on transfer.
Binary file has a risk to be modified on transfer.
Note that the key on host PC is protected by passphrase (which
is <PASSWORD-KEY-ON-PC> in the example above). Using the key
from the backup needs this passphrase. It is common that
people will forget passphrase for backup. Never forget it.
You have been warned.
To make ASCII backup for private key,
invokde GnuPG with ``--armor`` option and ``--export-secret-keys``
specifying the key identifier. ::
$ gpg --armor --output <YOUR-SECRET>.asc --export-secret-keys <YOUR-KEY-ID>
From the backup,
we can recover privet key by invoking GnuPG with ``--import`` option. ::
$ gpg --import <YOUR-SECRET>.asc

View File

@@ -0,0 +1,38 @@
==========================
GnuPG settings for GNOME 3
==========================
In the article `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
It was for GNOME 2. The old days was good, we just disabled GNOME-keyrings
interference to SSH and customizing our desktop was easy for GNU and UNIX users.
.. _GnuPG settings: gpg-settings
GNOME keyrings in GNOME 3
=========================
It seems that it is more integrated into the desktop.
It is difficult to kill it. It would be possible to kill it simply,
but then, I can't use, say, wi-fi access (which needs to access "secrets")
any more.
We can't use GNOME configuration tool to disable interference by
GNOME keyrings any more. It seems that desktop should not have
customization these days.
GNOME-SESSION-PROPERTIES
========================
After struggling some hours, I figured out it is GNOME-SESSION-PROPERTIES
to disable the interference. Invoking::
$ gnome-session-properties
and at the tab of "Startup Programs", I removed radio check buttons
for "GPG Password Agent" and "SSH Key Agent".
Now, I use gpg-agent for GnuPG Agent and SSH agent with Gnuk Token.

View File

@@ -0,0 +1,183 @@
=============================================
Key import from PC to Gnuk Token (no removal)
=============================================
This document describes how I put my **keys on PC** to the Token
without removing keys from PC.
The difference is just not-to-save changes after key imports.
After personalization, I put my keys into the Token.
Here is the log.
I invoke GnuPG with my key (4ca7babe) and with ``--homedir`` option
to specify the directory which contains my secret keys. ::
$ gpg --homedir=/home/gniibe/tmp/gnuk-testing-dir --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``.
To enable ``keytocard`` command, I type ``toggle`` command. ::
gpg> toggle
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
Firstly, I import my primary key into Gnuk Token.
I type ``keytocard`` command, answer ``y`` to confirm keyimport,
and type ``1`` to say it's signature key. ::
gpg> keytocard
Really move the primary key? (y/N) y
gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00'
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
Then, GnuPG asks two passwords. One is the passphrase of **keys on PC**
and another is the password of **Gnuk Token**. Note that the password of
the token and the password of the keys on PC are different things,
although they can be same.
I enter these passwords. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
gpg: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN
Enter Admin PIN: <PASSWORD-GNUK>
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
The primary key is now on the Token and GnuPG says its card-no (F517 00000001),
where F517 is the vendor ID of FSIJ.
Secondly, I import my subkey of encryption. I select key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
You can see that the subkey is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``2`` as it's encryption key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(2) Encryption key
Your selection? 2
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 084239CF, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
The sub key is now on the Token and GnuPG says its card-no for it.
I type ``key 1`` to deselect key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
Thirdly, I select sub key of authentication which has key number '2'. ::
gpg> key 2
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
You can see that the subkey number '2' is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``3`` as it's authentication key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(3) Authentication key
Your selection? 3
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 5BB065DC, created 2010-10-22
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
card-no: F517 00000001
(1) NIIBE Yutaka <gniibe@fsij.org>
The sub key is now on the Token and GnuPG says its card-no for it.
Lastly, I quit GnuPG. Note that I **don't** save changes. ::
gpg> quit
Save changes? (y/N) n
Quit without saving? (y/N) y
$
All keys are imported to Gnuk Token now.

193
doc/gnuk-keytocard.rst Normal file
View File

@@ -0,0 +1,193 @@
================================
Key import from PC to Gnuk Token
================================
This document describes how I put my **keys on PC** to the Token,
and remove keys from PC.
Note that there is **no ways** to export keys from the Token,
so please be careful.
If you want to import same keys to multiple Tokens,
please copy ``.gnupg`` directory beforehand.
In my case, I do something like following: ::
$ cp -a .gnupg tmp/gnuk-testing-dir
See `another document`_ to import keys to the Token from copied directory.
.. _another document: gnuk-keytocard-noremoval
After personalization, I put my keys into the Token.
Here is the log.
I invoke GnuPG with my key (4ca7babe). ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``.
To enable ``keytocard`` command, I type ``toggle`` command. ::
gpg> toggle
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
Firstly, I import my primary key into Gnuk Token.
I type ``keytocard`` command, answer ``y`` to confirm keyimport,
and type ``1`` to say it's signature key. ::
gpg> keytocard
Really move the primary key? (y/N) y
gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00'
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
Then, GnuPG asks two passwords. One is the passphrase of **keys on PC**
and another is the password of **Gnuk Token**. Note that the password of
the token and the password of the keys on PC are different things,
although they can be same.
I enter these passwords. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
gpg: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN
Enter Admin PIN: <PASSWORD-GNUK>
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
The primary key is now on the Token and GnuPG says its card-no (F517 00000001) , where F517 is the vendor ID of FSIJ.
Secondly, I import my subkey of encryption. I select key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
You can see that the subkey is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``2`` as it's encryption key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(2) Encryption key
Your selection? 2
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 084239CF, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
The sub key is now on the Token and GnuPG says its card-no for it.
I type ``key 1`` to deselect key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
Thirdly, I select sub key of authentication which has key number '2'. ::
gpg> key 2
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
You can see that the subkey number '2' is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``3`` as it's authentication key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(3) Authentication key
Your selection? 3
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 5BB065DC, created 2010-10-22
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
card-no: F517 00000001
(1) NIIBE Yutaka <gniibe@fsij.org>
The sub key is now on the Token and GnuPG says its card-no for it.
Lastly, I save changes of **keys on PC** and quit GnuPG. ::
gpg> save
$
All secret keys are imported to Gnuk Token now.
On PC, only references (card-no) to the Token remain.

View File

@@ -0,0 +1,153 @@
=============================
Personalization of Gnuk Token
=============================
Personalize your Gnuk Token
===========================
Invoke GnuPG with the option ``--card-edit``. ::
$ gpg --card-edit
gpg: detected reader `FSIJ Gnuk (0.12-34006E06) 00 00'
Application ID ...: D276000124010200F517000000010000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
It shows the status of the card (as same as the output of ``gpg --card-status``). It shows token's name and its USB serial string (0.12-34006E06) from PC/SC-lite.
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``.
In the OpenPGPcard specification, there are two passwords: one is
user-password and another is admin-password. In the specification,
user-password is refered as PW1, and admin-password is refered as PW3.
Note that people sometimes use different words than "password" to
refer same thing, in GnuPG and its applications. For example, the
output explained above includes the word "PIN" (Personal
Identification Number), and the helper program for input is named
"pinentry". Note that it is OK (and recommended) to include
characters other than digits for the case of OpenPGPcard.
Besides, some people sometimes prefer the word "passphrase" to
"password", as it can encourage to have longer string, but it means
same thing and it just refer user-password or admin-password.
Firstly, I change PIN of card user from factory setting (of "123456").
Note that, by only changing user's PIN, it enables "admin less mode" of Gnuk.
"Admin less mode" means that admin password will become same one of user's.
That is, PW1 = PW3.
Note that *the length of PIN should be more than (or equals to) 8* for
"admin less mode". ::
gpg/card> passwd
gpg: OpenPGP card no. D276000124010200F517000000010000 detected
Please enter the PIN
Enter PIN: 123456
New PIN
Enter New PIN: <PASSWORD-OF-GNUK>
New PIN
Repeat this PIN: <PASSWORD-OF-GNUK>
PIN changed.
The "admin less mode" is Gnuk only feature, not defined in the
OpenPGPcard specification. By using "admin less mode", it will be
only a sigle password for user to memorize, and it will be easier if a token
is used by an individual.
(If you want normal way ("admin full mode" in Gnuk's term),
that is, user-password *and* admin-password independently,
please change admin-password at first.
Then, the token works as same as OpenPGPcard specification
with regards to PW1 and PW3.)
Secondly, enabling admin command, I put name of mine.
Note that I input user's PIN (which I set above) here,
because it is "admin less mode". ::
gpg/card> admin
Admin commands are allowed
gpg/card> name
Cardholder's surname: Niibe
Cardholder's given name: Yutaka
gpg: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN
Enter Admin PIN: <PASSWORD-OF-GNUK>
Thirdly, I put some other informations, such as language, sex,
login, and URL. URL specifies the place where I put my public keys. ::
gpg/card> lang
Language preferences: ja
gpg/card> sex
Sex ((M)ale, (F)emale or space): m
gpg/card> url
URL to retrieve public key: http://www.gniibe.org/gniibe.asc
gpg/card> login
Login data (account name): gniibe
Since I don't force PIN input everytime,
toggle it to non-force-pin-for-signature. ::
gpg/card> forcesig
Lastly, I setup reset code. This is optional. ::
gpg/card> passwd
gpg: OpenPGP card no. D276000124010200F517000000010000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? 4
gpg: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN
Enter Admin PIN: <PASSWORD-OF-GNUK>
New Reset Code
Enter New PIN: <RESETCODE-OF-GNUK>
New Reset Code
Repeat this PIN: <RESETCODE-OF-GNUK>
Reset Code set.
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? q
Then, I quit. ::
gpg/card> quit
That's all.

View File

@@ -0,0 +1,43 @@
===================================
Initial Configuration of Gnuk Token
===================================
This is optional. You don't need to setup the serial number of Gnuk Token,
as it comes with its default serial number based on MCU's chip ID.
You can setup the serial number of Gnuk Token only once.
Conditions
==========
I assume you are using GNU/Linux.
Preparation
===========
Make sure there is no ``scdaemon`` for configuring Gnuk Token. You can kill ``scdaemon`` by: ::
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
Serial Number (optional)
========================
In the file ``GNUK_SERIAL_NUMBER``, each line has email and 6-byte serial number. The first two bytes are organization number (F5:17 is for FSIJ). Last four bytes are number for tokens.
The tool ``../tool/gnuk_put_binary_libusb.py`` examines environment variable of ``EMAIL``, and writes corresponding serial number to Gnuk Token. ::
$ ../tool/gnuk_put_binary_libusb.py -s ../GNUK_SERIAL_NUMBER
Writing serial number
Device: 006
Configuration: 1
Interface: 0
d2 76 00 01 24 01 02 00 f5 17 00 00 00 01 00 00
The example above is the case of libusb version.
Use the tool ``../tool/gnuk_put_binary.py`` instead , for PC/SC Lite.
You need PyScard for this.

43
doc/gpg-settings.rst Normal file
View File

@@ -0,0 +1,43 @@
.. -*- coding: utf-8 -*-
==============
GnuPG settings
==============
Here is my GnuPG settings.
.gnupg/gpg.conf
===============
I create ``.gnupg/gpg.conf`` file with the following content. ::
use-agent
personal-digest-preferences SHA256
cert-digest-algo SHA256
default-preference-list SHA512 SHA384 SHA256 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
default-key 0x4ca7babe
Let gpg-agent manage SSH key
============================
I deactivate seahose-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
I edit the file /etc/X11/Xsession.options and comment out use-ssh-agent line.
Then, I create ``.gnupg/gpg-agent.conf`` file with the following content. ::
enable-ssh-support
References
==========
* `Creating a new GPG key`_
* `Use OpenPGP Keys for OpenSSH, how to use gpg with ssh`_
.. _Creating a new GPG key: http://keyring.debian.org/creating-key.html
.. _Use OpenPGP Keys for OpenSSH, how to use gpg with ssh: http://www.programmierecke.net/howto/gpg-ssh.html

BIN
doc/images/gnuk-sticker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

37
doc/index.rst Normal file
View File

@@ -0,0 +1,37 @@
.. Gnuk Documentation documentation master file, created by
sphinx-quickstart on Wed Jul 4 15:29:05 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Copyright (C) 2012 NIIBE Yutaka
Copyright (C) 2012 Free Software Initiative of Japan
This document is licensed under a CC-BY-SA 3.0 Unported License
Gnuk Documentation
==================
Contents:
.. toctree::
:maxdepth: 2
intro.rst
development.rst
stop-scdaemon.rst
udev-rules.rst
gnuk-token-initial-configuration.rst
gnuk-personalization.rst
generating-2048-RSA-key.rst
gnuk-keytocard.rst
gnuk-keytocard-noremoval.rst
using-gnuk-token-with-another-computer.rst
gpg-settings.rst
gnome3-gpg-settings.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

69
doc/intro.rst Normal file
View File

@@ -0,0 +1,69 @@
Introduction
============
What's Gnuk?
------------
Gnuk is an implementation of USB cryptographic token for GNU Privacy
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
STM32F103 processor.
Cryptographic token and feature of Gnuk
---------------------------------------
Cryptographic token is a store of private keys and it computes cryptographic
functions on the device.
The idea is to separate important secrets to independent device,
from where nobody can extract them.
Development Environment
-----------------------
See :doc:`development` for development environment for Gnuk.
Gnuk is developed on the environment where there are only Free Software.
Target boards for running Gnuk
------------------------------
Hardware requirement for Gnuk is the micro controller STM32F103.
In version 1.0, Gnuk supports following boards.
* FST-01 (Flying Stone Tiny ZERO-ONE)
* Olimex STM32-H103
* CQ STARM
* STBee
* STBee Mini
* STM32 part of STM8S Discovery Kit
Host prerequisites for using Gnuk Token
---------------------------------------
* GNU Privacy Guard (GnuPG)
* libusb
* [Optional] PC/SC lite (pcscd, libccid)
* SSH: openssh
* Web: scute, firefox
Usages
------
* Sign with GnuPG
* Decrypt with GnuPG
* Use with OpenSSH
* Use with Firefox for X.509 client certificate authentication

View File

@@ -1,4 +1,4 @@
* Random Number Generator
* [DONE] Random Number Generator
RNG is needed for Data Encryption Key to encrypt private key (P and Q).
It is important to collect enough entropy. Perhaps, it would

View File

@@ -77,7 +77,8 @@ KEYPTR
<---encrypted----><--- plain ---->
key_addr 4-byte
additional_data_encrypted 16-byte
initial_vector (random) 16-byte
checksum_encrypted 16-byte
dek_encrypted_by_keystring_pw1 16-byte
dek_encrypted_by_keystring_rc 16-byte
dek_encrypted_by_keystring_pw3 16-byte
@@ -85,6 +86,4 @@ dek_encrypted_by_keystring_pw3 16-byte
... decrypted to
[ P ][ Q ]
check 4-byte
random 4-byte
magic[] 8-byte
checksum 16-byte

View File

@@ -38,14 +38,12 @@ We can examine key information of gpg-agent by "KEYINFO" command.
Here is my example::
$ gpg-connect-agent "KEYINFO --list" /bye
S KEYINFO 4970A0D537CA2EF7CE6A106E47AD89B0EFB684C8 D - - - - -
S KEYINFO 65F67E742101C7FE6D5B33FCEFCF4F65EAF0688C T D276000124010200F517000000010000 OPENPGP.2 - - -
S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - -
S KEYINFO 7D180C0C2A991B25204110A92F5F92A5A509845B D - - - - -
S KEYINFO 101DE7B639FE29F4636BDEECF442A9273AFA6565 T D276000124010200F517000000010000 OPENPGP.1 - - -
S KEYINFO 5D6C89682D07CCFC034AF508420BF2276D8018ED T D276000124010200F517000000010000 OPENPGP.3 - - -
OK
I have two local keys (in my PC) and three keys in my token.
I have three keys in my token.
With the script below, I extract public key of the keygrip
5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin::
@@ -63,7 +61,7 @@ Here is the script, get_public_key.py::
result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"])
key = ""
while True:
i = result.find('%')
i = result.find('%')
if i < 0:
key += result
break

37
doc/stop-scdaemon.rst Normal file
View File

@@ -0,0 +1,37 @@
===========================
Stopping/Resetting SCDAEMON
===========================
There is a daemon named ``scdaemon`` behind gpg-agent, which handles
communication to smartcard/token.
Ideally, we don't need to care about ``scdaemon``, and it should
handle everything automatically. But, there are some cases (because
of bugs), where we need to talk to the daemon directly, in practice.
How to communicate SCDAEMON
===========================
We have a utility to communicate with a running gpg-agent, that's
gpg-connect-agent. We can use it to communicate with scdaemon,
as it supports sub-command "SCD", exactly for this purpose.
Stopping SCDAEMON
=================
To stop SCDAEMON and let it exit, type::
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
Then, you can confirm that there is no SCDAEMON any more by ``ps``
command.
Let GPG-AGENT/SCDAEMON learn
============================
To let gpg-agent/scdaemon learn, type::
$ gpg-connect-agent learn /bye

51
doc/udev-rules.rst Normal file
View File

@@ -0,0 +1,51 @@
===============================================
Device Configuration for Gnuk Token with libusb
===============================================
In order to use Gnuk Token with libusb, configuration of device is
needed for permissions. Note that this is not needed for the case of
PC/SC Lite, as it has its own device configuration.
udev rules for Gnuk Token
=========================
In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules,
when you install "gnupg" package. This is the place we need to change.
We add lines for Gnuk Token to give a desktop user the permission to
use the device. We specify USB ID of Gnuk Token (by FSIJ)::
--- /lib/udev/rules.d/60-gnupg.rules.orig 2012-06-24 21:51:26.000000000 +0900
+++ /lib/udev/rules.d/60-gnupg.rules 2012-07-13 17:18:55.149587687 +0900
@@ -10,4 +10,7 @@
ATTR{idVendor}=="04e6", ATTR{idProduct}=="5115", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
ATTR{idVendor}=="20a0", ATTR{idProduct}=="4107", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
+# Gnuk
+ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
+
LABEL="gnupg_rules_end"
When we install "gnupg2" package only (with no "gnupg" package),
there will be no udev rules (there is a bug report #543217 for this issue).
In this case, we need something like this in /etc/udev/rules.d/60-gnuk.rules::
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
Usually, udev daemon automatically handles for the changes of configuration
files. If not, please let the daemon reload rules::
# udevadm control --reload-rules
udev rules for ST-Link/V2
=========================
We need to have a udev rule for ST-Link/V2. It's like::
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", GROUP="tape", MODE="664", SYMLINK+="stlink"
I have this in the file /etc/udev/rules.d/10-stlink.rules.

View File

@@ -0,0 +1,178 @@
======================================
Using Gnuk Token with another computer
======================================
This document describes how you can use Gnuk Token
on another PC (which is not the one you generate your keys).
Note that the Token only brings your secret keys,
while ``.gnupg`` directory contains keyrings and trustdb, too.
Fetch the public key and connect it to the Token
================================================
Using the Token, we need to put the public key and the secret
key reference (to the token) in ``.gnupg``.
To do that, invoke GnuPG with ``--card-edit`` option. ::
$ gpg --card-edit
gpg: detected reader `FSIJ Gnuk (0.12-37006A06) 00 00'
Application ID ...: D276000124010200F517000000010000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Name of cardholder: Yutaka Niibe
Language prefs ...: ja
Sex ..............: male
URL of public key : http://www.gniibe.org/gniibe.asc
Login data .......: gniibe
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 6
Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
created ....: 2010-10-15 06:46:33
Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF
created ....: 2010-10-15 06:46:33
Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC
created ....: 2010-10-22 06:06:36
General key info..: [none]
gpg/card>
It says, there is no key info related to this token on your PC (``[none]``).
Fetch the public key from URL specified in the Token. ::
gpg/card> fetch
gpg: requesting key 4CA7BABE from http server www.gniibe.org
gpg: key 4CA7BABE: public key "NIIBE Yutaka <gniibe@fsij.org>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg/card>
Good. The public key is now in ``.gnupg``. We can examine by ``gpg --list-keys``.
However, the secret key reference (to the token) is not in ``.gnupg`` yet.
It will be generated when I do ``--card-status`` by GnuPG with
correspoinding public key in ``.gnupg``, or just type return
at the ``gpg/card>`` prompt. ::
gpg/card>
Application ID ...: D276000124010200F517000000010000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Name of cardholder: Yutaka Niibe
Language prefs ...: ja
Sex ..............: male
URL of public key : http://www.gniibe.org/gniibe.asc
Login data .......: gniibe
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 6
Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
created ....: 2010-10-15 06:46:33
Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF
created ....: 2010-10-15 06:46:33
Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC
created ....: 2010-10-22 06:06:36
General key info..:
pub 2048R/4CA7BABE 2010-10-15 NIIBE Yutaka <gniibe@fsij.org>
sec> 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb> 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb> 2048R/5BB065DC created: 2010-10-22 expires: never
card-no: F517 00000001
gpg/card>
OK, now I can use the Token on this computer.
Update trustdb for the key on Gnuk Token
========================================
Yes, I can use the Token by the public key and the secret
key reference to the card. More, I need to update the trustdb.
To do that I do: ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: unknown validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
gpg>
See, the key is ``unknown`` state. Add trust for that. ::
gpg> trust
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: unknown validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
Please note that the shown key validity is not necessarily correct
unless you restart the program.
$
Next time I invoke GnuPG, it will be ``ultimate`` key. Let's see: ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
gpg> quit
$

View File

@@ -131,6 +131,7 @@ cleanup:
#endif
#if 0
/*
* Check a public RSA key
*/
@@ -199,6 +200,7 @@ cleanup:
mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
}
#endif
/*
* Do an RSA public key operation

View File

@@ -2,7 +2,6 @@
PROJECT = regnual
SRCS = regnual.c usb_lld.c sys.c
OBJS = regnual.o usb_lld.o sys.o
LDSCRIPT= regnual.ld
@@ -23,7 +22,8 @@ MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
DEFS = -DFREE_STANDING
CFLAGS = -O2 -g
CFLAGS += $(CWARN) -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie
CFLAGS += $(CWARN) -I . -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
@@ -38,8 +38,8 @@ regnual.hex: regnual.elf
$(OBJCOPY) -Obinary regnual.elf regnual.bin
$(OBJCOPY) -Oihex regnual.elf regnual.hex
usb_lld.c: ../src/usb_lld.c
cp -p ../src/usb_lld.c .
usb_lld.o: ../src/usb_lld.c
$(CC) $(CFLAGS) -c -o usb_lld.o ../src/usb_lld.c
regnual.elf: $(OBJS) $(LDSCRIPT)
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
@@ -48,4 +48,3 @@ clean:
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin
distclean: clean
-rm -f usb_lld.c

View File

@@ -1,7 +1,7 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012 Free Software Initiative of Japan
* Copyright (C) 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -99,33 +99,15 @@ static const uint8_t regnual_string_serial[] = {
'0', 0, '.', 0, '0', 0,
};
const struct Descriptor device_desc = {
regnual_device_desc,
sizeof (regnual_device_desc)
};
const struct Descriptor config_desc = {
regnual_config_desc,
sizeof (regnual_config_desc)
};
const struct Descriptor string_descs[] = {
{regnual_string_lang_id, sizeof (regnual_string_lang_id)},
{gnukStringVendor, sizeof (gnukStringVendor)},
{gnukStringProduct, sizeof (gnukStringProduct)},
{regnual_string_serial, sizeof (regnual_string_serial)},
};
#define NUM_STRING_DESC (sizeof (string_descs)/sizeof (struct Descriptor))
static void
regnual_device_reset (void)
void
usb_cb_device_reset (void)
{
/* Set DEVICE as not configured */
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (config_desc.Descriptor[7]);
usb_lld_set_feature (regnual_config_desc[7]);
usb_lld_reset ();
@@ -141,11 +123,9 @@ regnual_device_reset (void)
#define USB_REGNUAL_PROTECT 4
#define USB_REGNUAL_FINISH 5
static uint8_t mem[256];
static uint32_t mem[256/4];
static uint32_t result;
static const uint8_t *const mem_info[] = { &_flash_start, &_flash_end, };
static uint32_t rbit (uint32_t v)
{
@@ -159,7 +139,7 @@ static uint32_t fetch (int i)
{
uint32_t v;
v = *(uint32_t *)(&mem[i*4]);
v = mem[i];
return rbit (v);
}
@@ -186,9 +166,8 @@ static uint32_t calc_crc32 (void)
}
static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index,
uint16_t len)
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -200,7 +179,7 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
result = flash_write (dst_addr, mem, 256);
result = flash_write (dst_addr, (const uint8_t *)mem, 256);
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
@@ -211,9 +190,9 @@ static void regnual_ctrl_write_finish (uint8_t req, uint8_t req_no,
}
}
static int
regnual_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -223,6 +202,10 @@ regnual_setup (uint8_t req, uint8_t req_no,
{
if (req_no == USB_REGNUAL_MEMINFO)
{
static const uint8_t *mem_info[2];
mem_info[0] = &_flash_start;
mem_info[1] = &_flash_end;
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
return USB_SUCCESS;
}
@@ -240,7 +223,8 @@ regnual_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
if (index + len < 256)
memset (mem + index + len, 0xff, 256 - (index + len));
memset ((uint8_t *)mem + index + len, 0xff,
256 - (index + len));
usb_lld_set_data_to_recv (mem + index, len);
return USB_SUCCESS;
@@ -264,38 +248,55 @@ regnual_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
}
static int
regnual_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
int
usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (device_desc.Descriptor,
device_desc.Descriptor_Size);
usb_lld_set_data_to_send (regnual_device_desc,
sizeof (regnual_device_desc));
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (config_desc.Descriptor,
config_desc.Descriptor_Size);
usb_lld_set_data_to_send (regnual_config_desc,
sizeof (regnual_config_desc));
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
const uint8_t *str;
int size;
if (desc_index < NUM_STRING_DESC)
switch (desc_index)
{
usb_lld_set_data_to_send (string_descs[desc_index].Descriptor,
string_descs[desc_index].Descriptor_Size);
return USB_SUCCESS;
case 0:
str = regnual_string_lang_id;
size = sizeof (regnual_string_lang_id);
case 1:
str = gnukStringVendor;
size = sizeof (gnukStringVendor);
case 2:
str = gnukStringProduct;
size = sizeof (gnukStringProduct);
case 3:
str = regnual_string_serial;
size = sizeof (regnual_string_serial);
break;
default:
return USB_UNSUPPORT;
}
usb_lld_set_data_to_send (str, size);
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
static int regnual_usb_event (uint8_t event_type, uint16_t value)
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
{
(void)value;
@@ -311,20 +312,12 @@ static int regnual_usb_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
static int regnual_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
{
(void)cmd; (void)interface; (void)alt;
return USB_UNSUPPORT;
}
const struct usb_device_method Device_Method = {
regnual_device_reset,
regnual_ctrl_write_finish,
regnual_setup,
regnual_get_descriptor,
regnual_usb_event,
regnual_interface,
};
static void wait (int count)
{

View File

@@ -39,6 +39,7 @@ SECTIONS
{
_text = .;
KEEP(*(.vectors))
*(.text.entry)
*(.text)
*(.text.*)
*(.rodata)
@@ -48,6 +49,12 @@ SECTIONS
*(.gcc*)
} > ram1
.got :
{
*(.got)
*(.got.*)
} > ram1
.ctors :
{
PROVIDE(_ctors_start_ = .);

View File

@@ -9,17 +9,41 @@ static void none (void)
{
}
/* Note: it is not reset */
static __attribute__ ((naked))
/*
* Note: the address of this routine 'entry' will be in the vectors as
* RESET, but this will be called from application. It's not RESET
* state, then.
*/
static __attribute__ ((naked,section(".text.entry")))
void entry (void)
{
asm volatile ("ldr r0, =__ram_end__\n\t"
"ldr r1, =__main_stack_size__\n\t"
asm volatile ("mov r0, pc\n\t"
"bic r0, r0, #255\n\t" /* R0 := vector_table address */
"mov r1, #0x90\n" /* R1 := numbers of entries * 4 */
"0:\n\t"
"ldr r2, [r0, r1]\n\t"
"add r2, r2, #-0x20000000\n\t"
"sub r2, r2, #0x1400\n\t"
"add r2, r2, r0\n\t" /* Relocate: -0x20001400 + R0 */
"str r2, [r0, r1]\n\t"
"subs r1, r1, #4\n\t"
"bne 0b\n\t"
/* Relocation done. We don't care the first entry. */
"ldr r3, .L00\n"
".LPIC00:\n\t"
"add r3, pc\n\t" /* R3 := @_GLOBAL_OFFSET_TABLE_ */
"ldr r4, .L00+4\n\t"
"ldr r0, [r3, r4]\n\t"
"ldr r4, .L00+8\n\t"
"ldr r1, [r3, r4]\n\t"
"sub r0, r0, r1\n\t"
"mov sp, r0\n\t"
/* Clear BSS. */
"mov r0, #0\n\t"
"ldr r1, =_bss_start\n\t"
"ldr r2, =_bss_end\n"
"ldr r4, .L00+12\n\t"
"ldr r1, [r3, r4]\n\t"
"ldr r4, .L00+16\n\t"
"ldr r2, [r3, r4]\n"
"0:\n\t"
"str r0, [r1], #4\n\t"
"cmp r2, r1\n\t"
@@ -30,6 +54,12 @@ void entry (void)
"bl main\n"
"1:\n\t"
"b 1b\n"
".L00:\n\t"
".word _GLOBAL_OFFSET_TABLE_-(.LPIC00+4)\n\t"
".word __ram_end__(GOT)\n\t"
".word __main_stack_size__(GOT)\n\t"
".word _bss_start(GOT)\n\t"
".word _bss_end(GOT)"
: /* no output */ : /* no input */ : "memory");
}

View File

@@ -11,7 +11,7 @@ BOARD_DIR=@BOARD_DIR@
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
USE_OPT = -O3 -Os -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C++ specific options here (added to USE_OPT).

View File

@@ -1,7 +1,7 @@
/*
* ac.c -- Check access condition
*
* Copyright (C) 2010 Free Software Initiative of Japan
* Copyright (C) 2010, 2012 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -87,7 +87,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
}
success_one_step:
sha256 (pw, pw_len, keystring);
s2k (BY_USER, pw, pw_len, keystring);
if (access == AC_PSO_CDS_AUTHORIZED)
{
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
@@ -202,7 +202,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
return 0;
pw_len = pw3_keystring[0];
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len > buf_len)
goto failure;
salt = &pw3_keystring[1];
@@ -280,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len)
if (r <= 0)
return r;
sha256 (pw, pw_len, keystring_md_pw3);
s2k (admin_authorized, pw, pw_len, keystring_md_pw3);
auth_status |= AC_ADMIN_AUTHORIZED;
return 1;
}
@@ -290,6 +290,7 @@ ac_reset_admin (void)
{
memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE);
auth_status &= ~AC_ADMIN_AUTHORIZED;
admin_authorized = 0;
}
void
@@ -300,4 +301,5 @@ ac_fini (void)
gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
auth_status = AC_NONE_AUTHORIZED;
admin_authorized = 0;
}

View File

@@ -50,7 +50,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
mpi_lset (&rsa_ctx.E, 0x10001);
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2);
#if 0 /* Using CRT, we don't use N */
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
#endif
mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
mpi_mul_mpi (&H, &P1, &Q1);
@@ -61,17 +63,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
mpi_free (&P1, &Q1, &H, NULL);
DEBUG_INFO ("RSA sign...");
#if 0
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
DEBUG_INFO ("ok...");
else
{
DEBUG_INFO ("failed.\r\n");
DEBUG_SHORT (r);
rsa_free (&rsa_ctx);
return r;
}
#endif
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, temp);
@@ -142,7 +133,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2);
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
KEY_CONTENT_LEN / 2);
#if 0 /* Using CRT, we don't use N */
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
#endif
mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
mpi_mul_mpi (&H, &P1, &Q1);
@@ -153,18 +146,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
mpi_free (&P1, &Q1, &H, NULL);
DEBUG_INFO ("RSA decrypt ...");
#if 0
/* This consume some memory */
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
DEBUG_INFO ("ok...");
else
{
DEBUG_INFO ("failed.\r\n");
DEBUG_SHORT (r);
rsa_free (&rsa_ctx);
return r;
}
#endif
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
input, output, MAX_RES_APDU_DATA_SIZE);

2
src/configure vendored
View File

@@ -84,7 +84,7 @@ Configuration:
-h, --help display this help and exit [no]
--vidpid=VID:PID specify vendor/product ID [<NONE>]
--target=TARGET specify target [OLIMEX_STM32_H103]
supported targes are:
supported targets are:
OLIMEX_STM32_H103
STM32_PRIMER2
CQ_STARM

View File

@@ -1,7 +1,8 @@
/*
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -516,6 +517,12 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
{
maxsize = KEY_CONTENT_LEN;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
if (len == 0 && offset == 0)
{ /* This means removal of update key. */
if (flash_program_halfword ((uint32_t)p, 0) != 0)
flash_warning ("DO WRITE ERROR");
return 0;
}
}
#if defined(CERTDO_SUPPORT)
else if (file_id == FILEID_CH_CERTIFICATE)

View File

@@ -94,6 +94,7 @@ extern volatile uint8_t auth_status;
#define PW_ERR_PW1 0
#define PW_ERR_RC 1
#define PW_ERR_PW3 2
extern int gpg_pw_get_retry_counter (int who);
extern int gpg_pw_locked (uint8_t which);
extern void gpg_pw_reset_err_counter (uint8_t which);
extern void gpg_pw_increment_err_counter (uint8_t which);
@@ -115,6 +116,8 @@ extern void ac_fini (void);
extern void set_res_sw (uint8_t sw1, uint8_t sw2);
extern uint16_t data_objects_number_of_bytes;
#define CHALLENGE_LEN 32
extern void gpg_data_scan (const uint8_t *p);
extern void gpg_data_copy (const uint8_t *p);
extern void gpg_do_get_data (uint16_t tag, int with_tag);
@@ -168,8 +171,8 @@ struct key_data {
};
struct key_data_internal {
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
uint8_t checksum[DATA_ENCRYPTION_KEY_SIZE];
uint32_t data[KEY_CONTENT_LEN/4]; /* p and q */
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
};
struct prvkey_data {
@@ -194,8 +197,8 @@ struct prvkey_data {
#define BY_RESETCODE 2
#define BY_ADMIN 3
extern void resetcode_s2k (const unsigned char *input, unsigned int ilen,
unsigned char output[32]);
extern void s2k (int who, const unsigned char *input, unsigned int ilen,
unsigned char output[32]);
#define KEYSTRING_PASSLEN_SIZE 1
@@ -306,7 +309,7 @@ extern uint8_t admin_authorized;
/*
* Representation of Boolean object:
* 0: No record in flash memory
* 1: 0xc?00
* 1: 0xf000
*/
#define NR_BOOL_PW1_LIFETIME 0xf0
/*

View File

@@ -1,7 +1,7 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -178,7 +178,8 @@ extern msg_t USBthread (void *arg);
#define LED_TIMEOUT_STOP MS2ST(200)
#define ID_OFFSET 22
/* It has two-byte prefix and content is "FSIJ-1.0.1-" (2 + 11*2). */
#define ID_OFFSET 24
static void
device_initialize_once (void)
{
@@ -318,6 +319,23 @@ led_blink (int spec)
chEvtSignal (main_thread, spec);
}
/*
* In Gnuk 1.0.[12], reGNUal was not relocatable.
* Now, it's relocatable, but we need to calculate its entry address
* based on it's pre-defined address.
*/
#define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
static uint32_t
calculate_regnual_entry_address (const uint8_t *addr)
{
const uint8_t *p = addr + 4;
uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
v -= REGNUAL_START_ADDRESS_COMPATIBLE;
v += (uint32_t)addr;
return v;
}
/*
* Entry point.
@@ -329,6 +347,7 @@ int
main (int argc, char *argv[])
{
unsigned int count = 0;
uint32_t entry;
(void)argc;
(void)argv;
@@ -337,7 +356,7 @@ main (int argc, char *argv[])
flash_unlock ();
device_initialize_once ();
usb_lld_init (Config_Descriptor.Descriptor[7]);
usb_lld_init (usb_initial_feature);
random_init ();
while (1)
@@ -428,6 +447,7 @@ main (int argc, char *argv[])
port_disable ();
/* Set vector */
SCB->VTOR = (uint32_t)&_regnual_start;
entry = calculate_regnual_entry_address (&_regnual_start);
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
@@ -446,12 +466,12 @@ main (int argc, char *argv[])
flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
/* Leave Gnuk to exec reGNUal */
(*func) (*((void (**)(void))(&_regnual_start+4)));
(*func) ((void (*)(void))entry);
for (;;);
}
#else
/* Leave Gnuk to exec reGNUal */
flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4)));
flash_erase_all_and_exec ((void (*)(void))entry);
#endif
/* Never reached */

View File

@@ -1,519 +0,0 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "ch.h"
#include "hal.h"
#include "sys.h"
#include "gnuk.h"
#include "usb_lld.h"
#include "usb-cdc.h"
#ifdef DEBUG
struct stdout {
Mutex m;
CondVar start_cnd;
CondVar finish_cnd;
const char *str;
int size;
};
static struct stdout stdout;
static void
stdout_init (void)
{
chMtxInit (&stdout.m);
chCondInit (&stdout.start_cnd);
chCondInit (&stdout.finish_cnd);
stdout.size = 0;
stdout.str = NULL;
}
void
_write (const char *s, int size)
{
if (size == 0)
return;
chMtxLock (&stdout.m);
while (stdout.str)
chCondWait (&stdout.finish_cnd);
stdout.str = s;
stdout.size = size;
chCondSignal (&stdout.start_cnd);
chCondWait (&stdout.finish_cnd);
chMtxUnlock ();
}
Thread *stdout_thread;
uint32_t count_in;
uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE];
static WORKING_AREA(waSTDOUTthread, 128);
static msg_t
STDOUTthread (void *arg)
{
(void)arg;
stdout_thread = chThdSelf ();
again:
while (1)
{
if (bDeviceState == CONFIGURED)
break;
chThdSleepMilliseconds (100);
}
while (1)
{
const char *p;
int len;
if (bDeviceState != CONFIGURED)
break;
chMtxLock (&stdout.m);
if (stdout.str == NULL)
chCondWait (&stdout.start_cnd);
p = stdout.str;
len = stdout.size;
while (1)
{
int i;
if (len == 0)
if (count_in != VIRTUAL_COM_PORT_DATA_SIZE)
break;
if (len < VIRTUAL_COM_PORT_DATA_SIZE)
{
for (i = 0; i < len; i++)
buffer_in[i] = p[i];
count_in = len;
len = 0;
}
else
{
for (i = 0; i < VIRTUAL_COM_PORT_DATA_SIZE; i++)
buffer_in[i] = p[i];
len -= VIRTUAL_COM_PORT_DATA_SIZE;
count_in = VIRTUAL_COM_PORT_DATA_SIZE;
p += count_in;
}
chEvtClear (EV_TX_READY);
usb_lld_write (ENDP3, buffer_in, count_in);
chEvtWaitOne (EV_TX_READY);
}
stdout.str = NULL;
stdout.size = 0;
chCondBroadcast (&stdout.finish_cnd);
chMtxUnlock ();
}
goto again;
return 0;
}
void
EP3_IN_Callback (void)
{
if (stdout_thread)
chEvtSignalI (stdout_thread, EV_TX_READY);
}
void
EP5_OUT_Callback (void)
{
usb_lld_rx_enable (ENDP5);
}
#else
void
_write (const char *s, int size)
{
(void)s;
(void)size;
}
#endif
static WORKING_AREA(waUSBthread, 128);
extern msg_t USBthread (void *arg);
/*
* main thread does 1-bit LED display output
*/
#define LED_TIMEOUT_INTERVAL MS2ST(100)
#define LED_TIMEOUT_ZERO MS2ST(50)
#define LED_TIMEOUT_ONE MS2ST(200)
#define LED_TIMEOUT_STOP MS2ST(500)
#define ID_OFFSET 22
static void
device_initialize_once (void)
{
const uint8_t *p = &gnukStringSerial[ID_OFFSET];
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
{
/*
* This is the first time invocation.
* Setup serial number by unique device ID.
*/
const uint8_t *u = unique_device_id ();
int i;
for (i = 0; i < 4; i++)
{
uint8_t b = u[i];
uint8_t nibble;
nibble = (b >> 4);
nibble += (nibble >= 10 ? ('A' - 10) : '0');
flash_put_data_internal (&p[i*4], nibble);
nibble = (b & 0x0f);
nibble += (nibble >= 10 ? ('A' - 10) : '0');
flash_put_data_internal (&p[i*4+2], nibble);
}
}
}
static volatile uint8_t fatal_code;
Thread *main_thread;
#define GNUK_INIT 0
#define GNUK_RUNNING 1
#define GNUK_WAIT 2
#define GNUK_FATAL 255
/*
* 0 for initializing
* 1 for normal mode
* 2 for input waiting / under calculation
* 255 for fatal
*/
static uint8_t main_mode;
static void display_interaction (void)
{
eventmask_t m;
set_led (1);
while (1)
{
m = chEvtWaitOne (ALL_EVENTS);
set_led (0);
switch (m)
{
case LED_ONESHOT_SHORT:
chThdSleep (MS2ST (100));
break;
case LED_ONESHOT_LONG:
chThdSleep (MS2ST (400));
break;
case LED_TWOSHOT:
chThdSleep (MS2ST (50));
set_led (1);
chThdSleep (MS2ST (50));
set_led (0);
chThdSleep (MS2ST (50));
break;
case LED_STATUS_MODE:
main_mode = GNUK_RUNNING;
return;
case LED_FATAL_MODE:
main_mode = GNUK_FATAL;
return;
default:
break;
}
set_led (1);
}
}
static void display_fatal_code (void)
{
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
set_led (1);
if (fatal_code & 1)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if (fatal_code & 2)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
}
static void display_status_code (void)
{
enum icc_state icc_state;
if (icc_state_p == NULL)
icc_state = ICC_STATE_START;
else
icc_state = *icc_state_p;
if (icc_state == ICC_STATE_START)
{
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 3);
}
else
/* GPGthread running */
{
set_led (1);
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
chThdSleep (LED_TIMEOUT_ONE);
else
chThdSleep (LED_TIMEOUT_ZERO);
if (icc_state == ICC_STATE_WAIT)
{
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 2);
}
else if (icc_state == ICC_STATE_RECEIVE)
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_ONE);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP);
}
else
{
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
set_led (1);
chThdSleep (LED_TIMEOUT_STOP);
set_led (0);
chThdSleep (LED_TIMEOUT_INTERVAL);
}
}
}
void
led_blink (int spec)
{
if (spec == 0)
chEvtSignal (main_thread, LED_ONESHOT_SHORT);
else if (spec == 1)
chEvtSignal (main_thread, LED_ONESHOT_LONG);
else
chEvtSignal (main_thread, LED_TWOSHOT);
}
/*
* Entry point.
*
* NOTE: the main function is already a thread in the system on entry.
* See the hwinit1_common function.
*/
int
main (int argc, char *argv[])
{
int count = 0;
(void)argc;
(void)argv;
main_thread = chThdSelf ();
flash_unlock ();
device_initialize_once ();
usb_lld_init (Config_Descriptor.Descriptor[7]);
random_init ();
while (1)
{
if (bDeviceState != UNCONNECTED)
break;
chThdSleepMilliseconds (250);
}
#ifdef DEBUG
stdout_init ();
/*
* Creates 'stdout' thread.
*/
chThdCreateStatic (waSTDOUTthread, sizeof(waSTDOUTthread),
NORMALPRIO, STDOUTthread, NULL);
#endif
chThdCreateStatic (waUSBthread, sizeof(waUSBthread),
NORMALPRIO, USBthread, NULL);
#ifdef PINPAD_DND_SUPPORT
msc_init ();
#endif
while (1)
{
eventmask_t m;
if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED)
break;
count++;
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL);
switch (m)
{
case LED_STATUS_MODE:
main_mode = GNUK_RUNNING;
break;
case LED_FATAL_MODE:
main_mode = GNUK_FATAL;
break;
case LED_WAIT_MODE:
main_mode = GNUK_WAIT;
break;
default:
break;
}
switch (main_mode)
{
case GNUK_FATAL:
display_fatal_code ();
break;
case GNUK_INIT:
set_led (1);
chThdSleep (LED_TIMEOUT_ZERO);
set_led (0);
chThdSleep (LED_TIMEOUT_STOP * 3);
break;
case GNUK_WAIT:
display_interaction ();
break;
case GNUK_RUNNING:
default:
display_status_code ();
break;
}
#ifdef DEBUG_MORE
if (bDeviceState == CONFIGURED && (count % 10) == 0)
{
DEBUG_SHORT (count / 10);
_write ("\r\nThis is ChibiOS 2.0.8 on STM32.\r\n"
"Testing USB driver.\n\n"
"Hello world\r\n\r\n", 35+21+15);
}
#endif
}
set_led (1);
usb_lld_shutdown ();
/* Disable SysTick */
SysTick->CTRL = 0;
/* Disable all interrupts */
port_disable ();
/* Set vector */
SCB->VTOR = (uint32_t)&_regnual_start;
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
{
extern uint8_t _sys;
uint32_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10];
/* Kill DFU */
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
addr += FLASH_PAGE_SIZE)
flash_erase_page (addr);
/* copy system service routines */
flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
/* Leave Gnuk to exec reGNUal */
(*func) (*((void (**)(void))(&_regnual_start+4)));
for (;;);
}
#else
/* Leave Gnuk to exec reGNUal */
flash_erase_all_and_exec (*((void (**)(void))(&_regnual_start+4)));
#endif
/* Never reached */
return 0;
}
void
fatal (uint8_t code)
{
fatal_code = code;
chEvtSignal (main_thread, LED_FATAL_MODE);
_write ("fatal\r\n", 7);
for (;;);
}

View File

@@ -1,7 +1,8 @@
/*
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013
* 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 +29,6 @@
#include "sys.h"
#include "gnuk.h"
#include "openpgp.h"
#include "sha256.h"
#include "polarssl/config.h"
#include "polarssl/aes.h"
@@ -42,6 +42,17 @@ gpg_pw_get_err_counter (uint8_t which)
return flash_cnt123_get_value (pw_err_counter_p[which]);
}
int
gpg_pw_get_retry_counter (int who)
{
if (who == 0x81 || who == 0x82)
return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW1);
else if (who == 0x83)
return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_PW3);
else
return PASSWORD_ERRORS_MAX - gpg_pw_get_err_counter (PW_ERR_RC);
}
int
gpg_pw_locked (uint8_t which)
{
@@ -89,16 +100,16 @@ static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
/* Extended Capabilities */
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
10,
0x30, /*
0x70, /*
* No SM,
* No get challenge,
* GET CHALLENGE supported,
* Key import supported,
* PW status byte can be put,
* No private_use_DO,
* No algo change allowed
*/
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 0x00, /* Max get challenge (0: Get challenge not supported) */
0x00, CHALLENGE_LEN, /* Max size of GET CHALLENGE */
#ifdef CERTDO_SUPPORT
0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
#else
@@ -230,7 +241,7 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
#define GPG_DO_LOGIN_DATA 0x005e
#define GPG_DO_CH_DATA 0x0065
#define GPG_DO_APP_DATA 0x006e
/* XXX: 0x0073 ??? */
#define GPG_DO_DISCRETIONARY 0x0073
#define GPG_DO_SS_TEMP 0x007a
#define GPG_DO_DS_COUNT 0x0093
#define GPG_DO_EXTCAP 0x00c0
@@ -436,7 +447,7 @@ const uint8_t openpgpcard_aid[] = {
static int
do_openpgpcard_aid (uint16_t tag, int with_tag)
{
uint16_t vid = *((const volatile uint16_t *)&openpgpcard_aid[8]);
uint16_t vid = (openpgpcard_aid[8] << 8) | openpgpcard_aid[9];
if (with_tag)
{
@@ -543,7 +554,7 @@ proc_resetting_code (const uint8_t *data, int len)
newpw_len = len;
newpw = data;
resetcode_s2k (newpw, newpw_len, new_ks);
s2k (BY_RESETCODE, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
if (r <= -2)
@@ -653,7 +664,7 @@ compute_key_data_checksum (struct key_data_internal *kdi, int check_or_calc)
uint32_t d[4] = { 0, 0, 0, 0 };
for (i = 0; i < KEY_CONTENT_LEN / sizeof (uint32_t); i++)
d[i&3] ^= *(uint32_t *)(&kdi->data[i*4]);
d[i&3] ^= kdi->data[i];
if (check_or_calc == 0) /* store */
{
@@ -724,6 +735,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
const uint8_t *ks_rc;
struct key_data_internal kdi;
int modulus_allocated_here = 0;
uint8_t ks_pw1_len = 0;
uint8_t ks_rc_len = 0;
DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (key_len);
@@ -777,7 +790,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
encrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal));
r = flash_key_write (key_addr, kdi.data, modulus);
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, modulus);
if (modulus_allocated_here)
modulus_free (modulus);
@@ -792,28 +805,25 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE);
memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE);
if (kk == GPG_KEY_FOR_SIGNING)
if (ks_pw1)
{
ac_reset_pso_cds ();
gpg_reset_digital_signature_counter ();
ks_pw1_len = ks_pw1[0];
encrypt_dek (ks_pw1+1, pd->dek_encrypted_1);
}
else
ac_reset_other ();
if (ks_pw1)
encrypt_dek (ks_pw1+1, pd->dek_encrypted_1);
else
{
uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
uint8_t ks[KEYSTRING_MD_SIZE];
ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1);
sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1);
encrypt_dek (ks123_pw1+1, pd->dek_encrypted_1);
s2k (BY_USER, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
encrypt_dek (ks, pd->dek_encrypted_1);
}
if (ks_rc)
encrypt_dek (ks_rc+1, pd->dek_encrypted_2);
{
ks_rc_len = ks_rc[0];
encrypt_dek (ks_rc+1, pd->dek_encrypted_2);
}
else
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
@@ -833,17 +843,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
if (++num_prv_keys == NUM_ALL_PRV_KEYS) /* All keys are registered. */
{
/* Remove contents of keystrings from DO, but length */
if (ks_pw1)
{
uint8_t ks_pw1_len = ks_pw1[0];
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
}
if (ks_pw1_len)
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
if (ks_rc)
{
uint8_t ks_rc_len = ks_rc[0];
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
}
if (ks_rc_len)
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
}
return 0;
@@ -868,7 +872,9 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
if (pd == NULL)
return -1;
memcpy (pd, &(do_data)[1], sizeof (struct prvkey_data));
memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
flash_do_release (do_data);
dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE
+ DATA_ENCRYPTION_KEY_SIZE * who_old;
memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE);
@@ -877,10 +883,10 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old);
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
do_ptr[nr - NR_DO__FIRST__] = NULL;
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr - NR_DO__FIRST__] = p;
flash_do_release (do_data);
free (pd);
if (p == NULL)
return -1;
@@ -924,11 +930,19 @@ proc_key_import (const uint8_t *data, int len)
p += 1;
if (*p == 0xb6)
kk = GPG_KEY_FOR_SIGNING;
else if (*p == 0xb8)
kk = GPG_KEY_FOR_DECRYPTION;
else /* 0xa4 */
kk = GPG_KEY_FOR_AUTHENTICATION;
{
kk = GPG_KEY_FOR_SIGNING;
ac_reset_pso_cds ();
gpg_reset_digital_signature_counter ();
}
else
{
if (*p == 0xb8)
kk = GPG_KEY_FOR_DECRYPTION;
else /* 0xa4 */
kk = GPG_KEY_FOR_AUTHENTICATION;
ac_reset_other ();
}
if (len <= 22)
{ /* Deletion of the key */
@@ -948,6 +962,11 @@ proc_key_import (const uint8_t *data, int len)
/* Delete PW1 and RC if any */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
}
return 1;
@@ -970,10 +989,14 @@ static const uint16_t cmp_ch_data[] = {
};
static const uint16_t cmp_app_data[] = {
10,
3,
GPG_DO_AID,
GPG_DO_HIST_BYTES,
/* XXX Discretionary data objects 0x0073 ??? */
GPG_DO_DISCRETIONARY,
};
static const uint16_t cmp_discretionary[] = {
8,
GPG_DO_EXTCAP,
GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
GPG_DO_PW_STATUS,
@@ -1019,6 +1042,7 @@ gpg_do_table[] = {
/* Compound data: Read access only */
{ GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
{ GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
{ GPG_DO_DISCRETIONARY, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_discretionary },
{ GPG_DO_SS_TEMP, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ss_temp },
/* Simple data: write access only */
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
@@ -1086,18 +1110,18 @@ gpg_data_scan (const uint8_t *p_start)
}
else
switch (nr)
{
case NR_BOOL_PW1_LIFETIME:
pw1_lifetime_p = p - 1;
p++;
continue;
case NR_COUNTER_123:
p++;
if (second_byte <= PW_ERR_PW3)
pw_err_counter_p[second_byte] = p;
p += 2;
break;
}
{
case NR_BOOL_PW1_LIFETIME:
pw1_lifetime_p = p - 1;
p++;
continue;
case NR_COUNTER_123:
p++;
if (second_byte <= PW_ERR_PW3)
pw_err_counter_p[second_byte] = p;
p += 2;
break;
}
}
}
@@ -1284,8 +1308,8 @@ copy_do (const struct do_table_entry *do_p, int with_tag)
}
case DO_PROC_READWRITE:
{
int (*rw_func)(uint16_t, int, uint8_t *, int, int)
= (int (*)(uint16_t, int, uint8_t *, int, int))do_p->obj;
int (*rw_func)(uint16_t, int, const uint8_t *, int, int)
= (int (*)(uint16_t, int, const uint8_t *, int, int))do_p->obj;
return rw_func (do_p->tag, with_tag, NULL, 0, 0);
}
@@ -1374,8 +1398,11 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
flash_do_release (*do_data_p);
if (len == 0)
/* make DO empty */
*do_data_p = NULL;
{
/* make DO empty */
*do_data_p = NULL;
GPG_SUCCESS ();
}
else if (len > 255)
GPG_MEMORY_FAILURE ();
else
@@ -1386,6 +1413,7 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
GPG_MEMORY_FAILURE ();
else
{
*do_data_p = NULL;
*do_data_p = flash_do_write (nr, data, len);
if (*do_data_p)
GPG_SUCCESS ();
@@ -1500,6 +1528,7 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
if (data != NULL)
{
*do_data_p = NULL;
*do_data_p = flash_do_write (nr, data, size);
if (*do_data_p == NULL)
flash_warning ("DO WRITE ERROR");
@@ -1557,26 +1586,27 @@ gpg_do_keygen (uint8_t kk_byte)
if (kk == GPG_KEY_FOR_SIGNING)
{
/* Authintication has been reset within gpg_do_write_prvkey. */
/* But GnuPG expects it's ready for signing. */
/* Thus, we call verify_pso_cds here. */
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
const uint8_t *pw;
int pw_len;
uint8_t keystring[KEYSTRING_MD_SIZE];
const uint8_t *ks;
/* GnuPG expects it's ready for signing. */
/* Don't call ac_reset_pso_cds here, but load the private key */
if (ks_pw1)
{
pw = ks_pw1+1;
pw_len = ks_pw1[0];
}
ks = ks_pw1+1;
else
{
pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
const uint8_t * pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
s2k (BY_USER, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
ks = keystring;
}
verify_pso_cds (pw, pw_len);
gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, ks);
}
else
ac_reset_other ();
gpg_do_public_key (kk_byte);
}

View File

@@ -1,7 +1,8 @@
/*
* openpgp.c -- OpenPGP card protocol support
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -29,6 +30,8 @@
#include "openpgp.h"
#include "sha256.h"
#define ADMIN_PASSWD_MINLEN 8
#define CLS(a) a.cmd_apdu_head[0]
#define INS(a) a.cmd_apdu_head[1]
#define P1(a) a.cmd_apdu_head[2]
@@ -50,7 +53,6 @@
#define INS_PUT_DATA 0xda
#define INS_PUT_DATA_ODD 0xdb /* For key import */
#define CHALLENGE_LEN 32
static const uint8_t *challenge; /* Random bytes */
static const uint8_t
@@ -138,6 +140,27 @@ cmd_verify (void)
len = apdu.cmd_apdu_data_len;
pw = apdu.cmd_apdu_data;
if (len == 0)
{ /* This is to examine status. */
if (p2 == 0x81)
r = ac_check_status (AC_PSO_CDS_AUTHORIZED);
else if (p2 == 0x82)
r = ac_check_status (AC_OTHER_AUTHORIZED);
else
r = ac_check_status (AC_ADMIN_AUTHORIZED);
if (r)
GPG_SUCCESS (); /* If authentication done already, return success. */
else
{ /* If not, return retry counter, encoded. */
r = gpg_pw_get_retry_counter (p2);
set_res_sw (0x63, 0xc0 | (r&0x0f));
}
return;
}
/* This is real authentication. */
if (p2 == 0x81)
r = verify_pso_cds (pw, len);
else if (p2 == 0x82)
@@ -220,8 +243,7 @@ cmd_change_password (void)
uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */
uint8_t p2 = P2 (apdu);
int len;
const uint8_t *pw;
const uint8_t *newpw;
uint8_t *pw, *newpw;
int pw_len, newpw_len;
int who = p2 - 0x80;
int who_old;
@@ -235,7 +257,7 @@ cmd_change_password (void)
if (p1 != 0)
{
GPG_FUNCTION_NOT_SUPPORTED();
GPG_FUNCTION_NOT_SUPPORTED ();
return;
}
@@ -260,8 +282,18 @@ cmd_change_password (void)
}
else
{
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
newpw = pw + pw_len;
newpw_len = len - pw_len;
/* Check length of password for admin-less mode. */
if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
{
DEBUG_INFO ("new password length is too short.");
GPG_CONDITION_NOT_SATISFIED ();
return;
}
}
}
else /* PW3 (0x83) */
@@ -284,13 +316,20 @@ cmd_change_password (void)
{
newpw = pw + pw_len;
newpw_len = len - pw_len;
gpg_set_pw3 (newpw, newpw_len);
if (newpw_len == 0 && admin_authorized == BY_ADMIN)
{
newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0);
}
else
gpg_set_pw3 (newpw, newpw_len);
who_old = admin_authorized;
}
}
sha256 (pw, pw_len, old_ks);
sha256 (newpw, newpw_len, new_ks);
s2k (who_old, pw, pw_len, old_ks);
s2k (who, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
r = gpg_change_keystring (who_old, old_ks, who, new_ks);
@@ -309,6 +348,8 @@ cmd_change_password (void)
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
GPG_SUCCESS ();
}
@@ -317,6 +358,8 @@ cmd_change_password (void)
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
GPG_SUCCESS ();
}
@@ -329,18 +372,24 @@ cmd_change_password (void)
}
#define USER_S2K_MAGIC "\xffUSER\r\n"
#define RESETCODE_S2K_MAGIC "\xffRESET\r\n"
void
resetcode_s2k (const unsigned char *input, unsigned int ilen,
unsigned char output[32])
s2k (int who, const unsigned char *input, unsigned int ilen,
unsigned char output[32])
{
sha256_context ctx;
sha256_start (&ctx);
sha256_update (&ctx, input, ilen);
sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC,
sizeof (RESETCODE_S2K_MAGIC));
if (who == BY_USER)
sha256_update (&ctx, (unsigned char *)USER_S2K_MAGIC,
sizeof (USER_S2K_MAGIC));
else if (who == BY_RESETCODE)
sha256_update (&ctx, (unsigned char *)RESETCODE_S2K_MAGIC,
sizeof (RESETCODE_S2K_MAGIC));
/* Not add any for BY_ADMIN */
sha256_finish (&ctx, output);
}
@@ -385,8 +434,8 @@ cmd_reset_user_password (void)
pw_len = ks_rc[0];
newpw = pw + pw_len;
newpw_len = len - pw_len;
resetcode_s2k (pw, pw_len, old_ks);
sha256 (newpw, newpw_len, new_ks);
s2k (BY_RESETCODE, pw, pw_len, old_ks);
s2k (BY_USER, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
if (r <= -2)
@@ -410,6 +459,8 @@ cmd_reset_user_password (void)
KEYSTRING_SIZE_PW1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
gpg_pw_reset_err_counter (PW_ERR_RC);
gpg_pw_reset_err_counter (PW_ERR_PW1);
GPG_SUCCESS ();
@@ -417,8 +468,11 @@ cmd_reset_user_password (void)
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
gpg_pw_reset_err_counter (PW_ERR_RC);
gpg_pw_reset_err_counter (PW_ERR_PW1);
GPG_SUCCESS ();
@@ -437,7 +491,7 @@ cmd_reset_user_password (void)
newpw_len = len;
newpw = pw;
sha256 (newpw, newpw_len, new_ks);
s2k (BY_USER, newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
if (r <= -2)
@@ -457,14 +511,19 @@ cmd_reset_user_password (void)
KEYSTRING_SIZE_PW1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
gpg_pw_reset_err_counter (PW_ERR_PW1);
GPG_SUCCESS ();
}
else
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
ac_reset_pso_cds ();
ac_reset_other ();
if (admin_authorized == BY_USER)
ac_reset_admin ();
gpg_pw_reset_err_counter (PW_ERR_PW1);
GPG_SUCCESS ();
}
@@ -750,10 +809,15 @@ cmd_pso (void)
/* Skip padding 0x00 */
len--;
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
&kd[GPG_KEY_FOR_DECRYPTION]);
if (r < 0)
GPG_ERROR ();
if (len != KEY_CONTENT_LEN)
GPG_CONDITION_NOT_SATISFIED ();
else
{
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
&kd[GPG_KEY_FOR_DECRYPTION]);
if (r < 0)
GPG_ERROR ();
}
}
else
{
@@ -883,6 +947,26 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
return;
}
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3
&& len == 0 && offset == 0)
{
int i;
const uint8_t *p;
for (i = 0; i < 4; i++)
{
p = gpg_get_firmware_update_key (i);
if (p[0] != 0x00 || p[1] != 0x00) /* still valid */
break;
}
if (i == 4) /* all update keys are removed */
{
p = gpg_get_firmware_update_key (0);
flash_erase_page ((uint32_t)p);
}
}
GPG_SUCCESS ();
}
@@ -904,25 +988,9 @@ static void
cmd_write_binary (void)
{
int len = apdu.cmd_apdu_data_len;
int i;
const uint8_t *p;
DEBUG_INFO (" - WRITE BINARY\r\n");
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
for (i = 0; i < 4; i++)
{
p = gpg_get_firmware_update_key (i);
if (p[0] != 0x00 || p[1] != 0x00) /* still valid */
break;
}
if (i == 4) /* all update keys are removed */
{
p = gpg_get_firmware_update_key (0);
flash_erase_page ((uint32_t)p);
}
DEBUG_INFO ("WRITE BINARY done.\r\n");
}
@@ -938,7 +1006,7 @@ cmd_external_authenticate (void)
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
if (keyno > 4)
if (keyno >= 4)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
@@ -971,14 +1039,25 @@ cmd_external_authenticate (void)
static void
cmd_get_challenge (void)
{
int len = apdu.expected_res_size;
DEBUG_INFO (" - GET CHALLENGE\r\n");
if (len > CHALLENGE_LEN)
{
GPG_CONDITION_NOT_SATISFIED ();
return;
}
else if (len == 0)
/* Le is not specified. Return full-sized challenge by GET_RESPONSE. */
len = CHALLENGE_LEN;
if (challenge)
random_bytes_free (challenge);
challenge = random_bytes_get ();
memcpy (res_APDU, challenge, CHALLENGE_LEN);
res_APDU_size = CHALLENGE_LEN;
memcpy (res_APDU, challenge, len);
res_APDU_size = len;
GPG_SUCCESS ();
DEBUG_INFO ("GET CHALLENGE done.\r\n");
}

View File

@@ -46,11 +46,10 @@
*/
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "sha256.h"
#define SHA256_DIGEST_SIZE 32
#define SHA256_BLOCK_SIZE 64
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
static void bswap32_buf (uint32_t *p, int n)

View File

@@ -1,3 +1,6 @@
#define SHA256_DIGEST_SIZE 32
#define SHA256_BLOCK_SIZE 64
typedef struct
{
uint32_t total[2];

View File

@@ -321,10 +321,8 @@ static void no_buf (struct ep_in *epi, size_t len)
epi->buf_len = 0;
}
static void set_sw1sw2 (struct ep_in *epi)
static void set_sw1sw2 (struct ccid *c, size_t chunk_len)
{
struct ccid *c = (struct ccid *)epi->priv;
if (c->a->expected_res_size >= c->len)
{
c->sw1sw2[0] = 0x90;
@@ -333,10 +331,10 @@ static void set_sw1sw2 (struct ep_in *epi)
else
{
c->sw1sw2[0] = 0x61;
if (c->len >= 256)
if (c->len - chunk_len >= 256)
c->sw1sw2[1] = 0;
else
c->sw1sw2[1] = (uint8_t)c->len;
c->sw1sw2[1] = (uint8_t)(c->len - chunk_len);
}
}
@@ -827,36 +825,7 @@ icc_power_off (struct ccid *c)
}
static void
icc_send_data_block_0x9000 (struct ccid *c)
{
uint8_t p[ICC_MSG_HEADER_SIZE+2];
size_t len = 2;
p[0] = ICC_DATA_BLOCK_RET;
p[1] = len & 0xFF;
p[2] = (len >> 8)& 0xFF;
p[3] = (len >> 16)& 0xFF;
p[4] = (len >> 24)& 0xFF;
p[5] = 0x00; /* Slot */
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
p[ICC_MSG_STATUS_OFFSET] = 0;
p[ICC_MSG_ERROR_OFFSET] = 0;
p[ICC_MSG_CHAIN_OFFSET] = 0;
p[ICC_MSG_CHAIN_OFFSET+1] = 0x90;
p[ICC_MSG_CHAIN_OFFSET+2] = 0x00;
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len);
c->epi->buf = NULL;
c->epi->tx_done = 1;
usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len);
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
}
static void
icc_send_data_block (struct ccid *c, uint8_t status)
icc_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
{
int tx_size = USB_LL_BUF_SIZE;
uint8_t p[ICC_MSG_HEADER_SIZE];
@@ -875,7 +844,7 @@ icc_send_data_block (struct ccid *c, uint8_t status)
p[5] = 0x00; /* Slot */
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
p[ICC_MSG_STATUS_OFFSET] = status;
p[ICC_MSG_ERROR_OFFSET] = 0;
p[ICC_MSG_ERROR_OFFSET] = error;
p[ICC_MSG_CHAIN_OFFSET] = 0;
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE);
@@ -933,6 +902,50 @@ icc_send_data_block (struct ccid *c, uint8_t status)
#endif
}
static void
icc_send_data_block (struct ccid *c)
{
icc_send_data_block_internal (c, 0, 0);
}
static void
icc_send_data_block_time_extension (struct ccid *c)
{
icc_send_data_block_internal (c, ICC_CMD_STATUS_TIMEEXT, 1);
}
static void
icc_send_data_block_0x9000 (struct ccid *c)
{
uint8_t p[ICC_MSG_HEADER_SIZE+2];
size_t len = 2;
p[0] = ICC_DATA_BLOCK_RET;
p[1] = len & 0xFF;
p[2] = (len >> 8)& 0xFF;
p[3] = (len >> 16)& 0xFF;
p[4] = (len >> 24)& 0xFF;
p[5] = 0x00; /* Slot */
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
p[ICC_MSG_STATUS_OFFSET] = 0;
p[ICC_MSG_ERROR_OFFSET] = 0;
p[ICC_MSG_CHAIN_OFFSET] = 0;
p[ICC_MSG_CHAIN_OFFSET+1] = 0x90;
p[ICC_MSG_CHAIN_OFFSET+2] = 0x00;
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len);
c->epi->buf = NULL;
c->epi->tx_done = 1;
usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len);
#ifdef DEBUG_MORE
DEBUG_INFO ("DATA\r\n");
#endif
}
/*
* Reply to the host for "GET RESPONSE".
*/
static void
icc_send_data_block_gr (struct ccid *c, size_t chunk_len)
{
@@ -953,7 +966,7 @@ icc_send_data_block_gr (struct ccid *c, size_t chunk_len)
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE);
set_sw1sw2 (c->epi);
set_sw1sw2 (c, chunk_len);
if (chunk_len <= USB_LL_BUF_SIZE - ICC_MSG_HEADER_SIZE)
{
@@ -1260,7 +1273,7 @@ icc_handle_timeout (struct ccid *c)
switch (c->icc_state)
{
case ICC_STATE_EXECUTE:
icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT);
icc_send_data_block_time_extension (c);
led_blink (LED_ONESHOT);
break;
default:
@@ -1311,7 +1324,7 @@ USBthread (void *arg)
c->sw1sw2[0] = 0x90;
c->sw1sw2[1] = 0x00;
c->state = APDU_STATE_RESULT;
icc_send_data_block (c, 0);
icc_send_data_block (c);
c->icc_state = ICC_STATE_EXITED;
break;
}
@@ -1323,7 +1336,7 @@ USBthread (void *arg)
if (c->a->res_apdu_data_len <= c->a->expected_res_size)
{
c->state = APDU_STATE_RESULT;
icc_send_data_block (c, 0);
icc_send_data_block (c);
c->icc_state = ICC_STATE_WAIT;
}
else

View File

@@ -1,7 +1,7 @@
/*
* usb_ctrl.c - USB control pipe device specific code for Gnuk
*
* Copyright (C) 2010, 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -147,8 +147,8 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
#endif
}
static void
gnuk_device_reset (void)
void
usb_cb_device_reset (void)
{
int i;
@@ -156,7 +156,7 @@ gnuk_device_reset (void)
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (Config_Descriptor.Descriptor[7]);
usb_lld_set_feature (usb_initial_feature);
usb_lld_reset ();
@@ -214,9 +214,9 @@ static int download_check_crc32 (const uint32_t *end_p)
return USB_UNSUPPORT;
}
static int
gnuk_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -310,9 +310,8 @@ gnuk_setup (uint8_t req, uint8_t req_no,
return USB_UNSUPPORT;
}
static void gnuk_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index,
uint16_t len)
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
@@ -329,38 +328,7 @@ static void gnuk_ctrl_write_finish (uint8_t req, uint8_t req_no,
}
static int
gnuk_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (Device_Descriptor.Descriptor,
Device_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (Config_Descriptor.Descriptor,
Config_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
if (desc_index < NUM_STRING_DESC)
{
usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor,
String_Descriptors[desc_index].Descriptor_Size);
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
static int gnuk_usb_event (uint8_t event_type, uint16_t value)
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
{
int i;
uint8_t current_conf;
@@ -401,7 +369,7 @@ static int gnuk_usb_event (uint8_t event_type, uint16_t value)
return USB_UNSUPPORT;
}
static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
{
static uint8_t zero = 0;
@@ -429,18 +397,6 @@ static int gnuk_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
}
}
/*
* Interface to USB core
*/
const struct usb_device_method Device_Method = {
gnuk_device_reset,
gnuk_ctrl_write_finish,
gnuk_setup,
gnuk_get_descriptor,
gnuk_usb_event,
gnuk_interface,
};
CH_IRQ_HANDLER (Vector90)
{

View File

@@ -9,6 +9,13 @@
#include "usb_conf.h"
#include "usb-cdc.h"
struct Descriptor
{
const uint8_t *Descriptor;
uint16_t Descriptor_Size;
};
#define USB_ICC_INTERFACE_CLASS 0x0B
#define USB_ICC_INTERFACE_SUBCLASS 0x00
#define USB_ICC_INTERFACE_BULK_PROTOCOL 0x00
@@ -53,6 +60,15 @@ static const uint8_t gnukDeviceDescriptor[] = {
#define NUM_INTERFACES (ICC_NUM_INTERFACES+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES)
#if defined(USB_SELF_POWERED)
#define USB_INITIAL_FEATURE 0xC0 /* bmAttributes: self powered */
#else
#define USB_INITIAL_FEATURE 0x80 /* bmAttributes: bus powered */
#endif
const uint8_t usb_initial_feature = USB_INITIAL_FEATURE;
/* Configuation Descriptor */
static const uint8_t gnukConfigDescriptor[] = {
9, /* bLength: Configuation Descriptor size */
@@ -61,11 +77,7 @@ static const uint8_t gnukConfigDescriptor[] = {
NUM_INTERFACES, /* bNumInterfaces: */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
#if defined(USB_SELF_POWERED)
0xC0, /* bmAttributes: self powered */
#else
0x80, /* bmAttributes: bus powered */
#endif
USB_INITIAL_FEATURE, /* bmAttributes*/
50, /* MaxPower 100 mA */
/* Interface Descriptor */
@@ -258,27 +270,27 @@ static const uint8_t gnukStringLangID[] = {
#include "usb-strings.c.inc"
const uint8_t gnukStringSerial[] = {
18*2+2, /* bLength */
19*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
/* FSIJ-0.19 */
/* FSIJ-1.0.3- */
'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0,
'0', 0, '.', 0, '2', 0, '0', 0, /* Version number of Gnuk */
'1', 0, '.', 0, '0', 0, '.', 0, '3', 0, /* Version number of Gnuk */
'-', 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
const struct Descriptor Device_Descriptor = {
static const struct Descriptor Device_Descriptor = {
gnukDeviceDescriptor,
sizeof (gnukDeviceDescriptor)
};
const struct Descriptor Config_Descriptor = {
static const struct Descriptor Config_Descriptor = {
gnukConfigDescriptor,
sizeof (gnukConfigDescriptor)
};
const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
static const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
{gnukStringLangID, sizeof (gnukStringLangID)},
{gnukStringVendor, sizeof (gnukStringVendor)},
{gnukStringProduct, sizeof (gnukStringProduct)},
@@ -287,3 +299,34 @@ const struct Descriptor String_Descriptors[NUM_STRING_DESC] = {
{gnuk_config_options, sizeof (gnuk_config_options)},
{sys_version, sizeof (sys_version)},
};
int
usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
{
(void)index;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (Device_Descriptor.Descriptor,
Device_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (Config_Descriptor.Descriptor,
Config_Descriptor.Descriptor_Size);
return USB_SUCCESS;
}
else if (desc_type == STRING_DESCRIPTOR)
{
uint8_t desc_index = value & 0xff;
if (desc_index < NUM_STRING_DESC)
{
usb_lld_set_data_to_send (String_Descriptors[desc_index].Descriptor,
String_Descriptors[desc_index].Descriptor_Size);
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}

View File

@@ -74,12 +74,10 @@ struct DEVICE_INFO
static struct CONTROL_INFO control_info;
static struct DEVICE_INFO device_info;
static struct DATA_INFO data_info;
extern const struct usb_device_method Device_Method;
static struct CONTROL_INFO *const ctrl_p = &control_info;
static struct DEVICE_INFO *const dev_p = &device_info;
static struct DATA_INFO *const data_p = &data_info;
static const struct usb_device_method *const method_p = &Device_Method;
#define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */
#define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */
@@ -399,7 +397,7 @@ usb_interrupt_handler (void)
if (istr_value & ISTR_RESET)
{
st103_set_istr (CLR_RESET);
method_p->reset ();
usb_cb_device_reset ();
}
if (istr_value & ISTR_DOVR)
@@ -529,7 +527,7 @@ static int std_get_status (uint8_t req,
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
r = (*method_p->interface) (USB_QUERY_INTERFACE, index, 0);
r = usb_cb_interface (USB_QUERY_INTERFACE, index, 0);
if (r != USB_SUCCESS)
return USB_UNSUPPORT;
@@ -700,7 +698,7 @@ static int std_get_descriptor (uint8_t req, uint16_t value,
(void)length;
if (rcp == DEVICE_RECIPIENT)
return (*method_p->get_descriptor) ((value >> 8), index, value);
return usb_cb_get_descriptor ((value >> 8), index, value);
return USB_UNSUPPORT;
}
@@ -736,7 +734,7 @@ static int std_set_configuration (uint8_t req, uint16_t value,
{
int r;
r = (*method_p->event) (USB_EVENT_CONFIG, value);
r = usb_cb_handle_event (USB_EVENT_CONFIG, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
@@ -760,7 +758,7 @@ static int std_get_interface (uint8_t req, uint16_t value,
if (dev_p->current_configuration == 0)
return USB_UNSUPPORT;
return (*method_p->interface) (USB_GET_INTERFACE, index, 0);
return usb_cb_interface (USB_GET_INTERFACE, index, 0);
}
return USB_UNSUPPORT;
@@ -784,7 +782,7 @@ static int std_set_interface (uint8_t req, uint16_t value,
if (dev_p->current_configuration != 0)
return USB_UNSUPPORT;
r = (*method_p->interface) (USB_SET_INTERFACE, index, value);
r = usb_cb_interface (USB_SET_INTERFACE, index, value);
if (r == USB_SUCCESS)
return USB_SUCCESS;
}
@@ -792,21 +790,6 @@ static int std_set_interface (uint8_t req, uint16_t value,
return USB_UNSUPPORT;
}
static const HANDLER std_request_handler[TOTAL_REQUEST] = {
std_get_status,
std_clear_feature,
std_none,
std_set_feature,
std_none,
std_set_address,
std_get_descriptor,
std_none, /* set_descriptor is not supported */
std_get_configuration,
std_set_configuration,
std_get_interface,
std_set_interface,
std_none, /* sync_frame is not supported (for now) */
};
static void handle_setup0 (void)
{
@@ -836,14 +819,27 @@ static void handle_setup0 (void)
{
if (req < TOTAL_REQUEST)
{
handler = std_request_handler[req];
switch (req)
{
case 0: handler = std_get_status; break;
case 1: handler = std_clear_feature; break;
case 3: handler = std_set_feature; break;
case 5: handler = std_set_address; break;
case 6: handler = std_get_descriptor; break;
case 8: handler = std_get_configuration; break;
case 9: handler = std_set_configuration; break;
case 10: handler = std_get_interface; break;
case 11: handler = std_set_interface; break;
default: handler = std_none; break;
}
r = (*handler) (ctrl_p->bmRequestType,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
}
}
else
r = (*method_p->setup) (ctrl_p->bmRequestType, req,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
r = usb_cb_setup (ctrl_p->bmRequestType, req,
ctrl_p->wValue, ctrl_p->wIndex, ctrl_p->wLength);
if (r != USB_SUCCESS)
dev_p->state = STALLED;
@@ -890,12 +886,12 @@ static void handle_in0 (void)
== (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
st103_set_daddr (ctrl_p->wValue);
(*method_p->event) (USB_EVENT_ADDRESS, ctrl_p->wValue);
usb_cb_handle_event (USB_EVENT_ADDRESS, ctrl_p->wValue);
}
else
(*method_p->ctrl_write_finish) (ctrl_p->bmRequestType,
ctrl_p->bRequest, ctrl_p->wValue,
ctrl_p->wIndex, ctrl_p->wLength);
usb_cb_ctrl_write_finish (ctrl_p->bmRequestType,
ctrl_p->bRequest, ctrl_p->wValue,
ctrl_p->wIndex, ctrl_p->wLength);
dev_p->state = STALLED;
}
@@ -938,26 +934,6 @@ void WEAK EP5_OUT_Callback (void);
void WEAK EP6_OUT_Callback (void);
void WEAK EP7_OUT_Callback (void);
void (*const ep_intr_handler_IN[7]) (void) = {
EP1_IN_Callback,
EP2_IN_Callback,
EP3_IN_Callback,
EP4_IN_Callback,
EP5_IN_Callback,
EP6_IN_Callback,
EP7_IN_Callback,
};
void (*const ep_intr_handler_OUT[7]) (void) = {
EP1_OUT_Callback,
EP2_OUT_Callback,
EP3_OUT_Callback,
EP4_OUT_Callback,
EP5_OUT_Callback,
EP6_OUT_Callback,
EP7_OUT_Callback,
};
static void
usb_handle_transfer (void)
{
@@ -1008,13 +984,31 @@ usb_handle_transfer (void)
if ((ep_value & EP_CTR_RX) != 0)
{
st103_ep_clear_ctr_rx (ep_index);
(*ep_intr_handler_OUT[ep_index-1]) ();
switch ((ep_index - 1))
{
case 0: EP1_OUT_Callback (); break;
case 1: EP2_OUT_Callback (); break;
case 2: EP3_OUT_Callback (); break;
case 3: EP4_OUT_Callback (); break;
case 4: EP5_OUT_Callback (); break;
case 5: EP6_OUT_Callback (); break;
case 6: EP7_OUT_Callback (); break;
}
}
if ((ep_value & EP_CTR_TX) != 0)
{
st103_ep_clear_ctr_tx (ep_index);
(*ep_intr_handler_IN[ep_index-1]) ();
switch ((ep_index - 1))
{
case 0: EP1_IN_Callback (); break;
case 1: EP2_IN_Callback (); break;
case 2: EP3_IN_Callback (); break;
case 3: EP4_IN_Callback (); break;
case 4: EP5_IN_Callback (); break;
case 5: EP6_IN_Callback (); break;
case 6: EP7_IN_Callback (); break;
}
}
}
}

View File

@@ -49,29 +49,20 @@ enum DESCRIPTOR_TYPE
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
struct Descriptor
{
const uint8_t *Descriptor;
uint16_t Descriptor_Size;
};
enum
{
USB_UNSUPPORT = 0,
USB_SUCCESS = 1,
};
struct usb_device_method
{
void (*reset) (void);
void (*ctrl_write_finish) (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int (*setup) (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int (*get_descriptor) (uint8_t desc_type, uint16_t index, uint16_t value);
int (*event) (uint8_t event_type, uint16_t value);
int (*interface) (uint8_t cmd, uint16_t interface, uint16_t value);
};
void usb_cb_device_reset (void);
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len);
int usb_cb_setup (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len);
int usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value);
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t value);
enum {
USB_EVENT_ADDRESS,
@@ -87,14 +78,6 @@ enum {
USB_QUERY_INTERFACE,
};
extern void USB_Cable_Config (int NewState);
extern const struct usb_device_method Device_Method;
extern const struct Descriptor Device_Descriptor;
extern const struct Descriptor Config_Descriptor;
extern const struct Descriptor String_Descriptors[];
enum DEVICE_STATE
{
UNCONNECTED,
@@ -106,6 +89,7 @@ enum DEVICE_STATE
};
extern uint32_t bDeviceState;
extern const uint8_t usb_initial_feature;
#define STM32_USB_IRQ_PRIORITY 11

20
test/README Normal file
View File

@@ -0,0 +1,20 @@
This is a functionality test suite for Gnuk.
You need python-nose, python-freshen as well as python-usb.
Besides, python-crypto is needed when you use generate_keys.py to
update contents of *.key.
Type:
$ nosetests --with-freshen
or
$ nosetests -v --with-freshen
to run the test suite.
To skip tests for key generation, add an option "--tag ~keygen". To
stop running tests after the first error or failure, add "--stop" option.

View File

@@ -0,0 +1,79 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no data, no keys)
Scenario: data object Login
When requesting login data: 5e
Then you should get NULL
Scenario: data object Name
When requesting name: 5b
Then you should get NULL
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get NULL
Scenario: data object Sex
When requesting sex: 5f35
Then you should get NULL
Scenario: data object URL
When requesting URL: 5f50
Then you should get NULL
Scenario: data object ds counter
When requesting ds counter: 93
Then you should get: \x00\x00\x00
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03
Scenario: data object finger print 0
When requesting finger print: c5
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object finger print 1
When requesting finger print: c7
Then you should get NULL
Scenario: data object finger print 2
When requesting finger print: c8
Then you should get NULL
Scenario: data object finger print 3
When requesting finger print: c9
Then you should get NULL
Scenario: data object CA finger print 0
When requesting finger print: c6
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object CA finger print 1
When requesting finger print: ca
Then you should get NULL
Scenario: data object CA finger print 2
When requesting finger print: cb
Then you should get NULL
Scenario: data object CA finger print 3
When requesting finger print: cc
Then you should get NULL
Scenario: data object date/time of key pair 0
When requesting date/time of key pair: cd
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object date/time of key pair 1
When requesting date/time of key pair: ce
Then you should get NULL
Scenario: data object date/time of key pair 2
When requesting date/time of key pair: cf
Then you should get NULL
Scenario: data object date/time of key pair 3
When requesting date/time of key pair: d0
Then you should get NULL

View File

@@ -0,0 +1,15 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no pass phrase)
Scenario: verify PW1 factory setting (1)
Given cmd_verify with 1 and "123456"
Then it should get success
Scenario: verify PW1 factory setting (2)
Given cmd_verify with 2 and "123456"
Then it should get success
Scenario: verify PW3 factory setting
Given cmd_verify with 3 and "12345678"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: command GET DATA
In order to conform OpenPGP card 2.0 specification
A token should support all mandatory features of the specification
Scenario: data object historical bytes
When requesting historical bytes: 5f52
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 2
When requesting algorithm attributes 2: c2
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 3
When requesting algorighm attributes 3: c3
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00

View File

@@ -0,0 +1,63 @@
Feature: setup pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW1 (admin-less mode)
Given cmd_change_reference_data with 1 and "123456user pass phrase"
Then it should get success
Scenario: verify PW1 (1)
Given cmd_verify with 1 and "user pass phrase"
Then it should get success
Scenario: verify PW1 (2)
Given cmd_verify with 2 and "user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "user pass phrase"
Then it should get success
Scenario: setup reset code (in admin-less mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-less mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode) again
Given cmd_verify with 3 and "new user pass phrase"
Then it should get success
Scenario: setup PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "new user pass phraseadmin pass phrase"
Then it should get success
Scenario: verify PW3 (admin-full mode)
Given cmd_verify with 3 and "admin pass phrase"
Then it should get success
Scenario: setup reset code (in admin-full mode)
Given cmd_put_data with d3 and "another reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-full mode)
Given cmd_reset_retry_counter with 0 and "another reset code 000another user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token write
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
Given cmd_put_data with 5e and "gpg_user"
Then it should get success
Scenario: data object Name
Given cmd_put_data with 5b and "GnuPG User"
Then it should get success
Scenario: data object Language preference
Given cmd_put_data with 5f2d and "ja"
Then it should get success
Scenario: data object Sex
Given cmd_put_data with 5f35 and "1"
Then it should get success
Scenario: data object URL
Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/"
Then it should get success
Scenario: data object pw1 status bytes
Given cmd_put_data with c4 and "\x01"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token read
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
When requesting login data: 5e
Then you should get: gpg_user
Scenario: data object Name
When requesting name: 5b
Then you should get: GnuPG User
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get: ja
Scenario: data object Sex
When requesting sex: 5f35
Then you should get: 1
Scenario: data object URL
When requesting URL: 5f50
Then you should get: http://www.fsij.org/gnuk/
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03

View File

@@ -0,0 +1,56 @@
Feature: import keys to token
In order to use a token
A token should have keys
Scenario: importing OPENPGP.1 key (sign)
Given a RSA key pair 0
And importing it to the token as OPENPGP.1
Then it should get success
Scenario: importing OPENPGP.2 key (decrypt)
Given a RSA key pair 1
And importing it to the token as OPENPGP.2
Then it should get success
Scenario: importing OPENPGP.3 key (authentication)
Given a RSA key pair 2
And importing it to the token as OPENPGP.3
Then it should get success
Scenario: setup data object Finger print sig
Given a fingerprint of OPENPGP.1 key
And put the data to c7
Then it should get success
Scenario: setup data object Finger print dec
Given a fingerprint of OPENPGP.2 key
And put the data to c8
Then it should get success
Scenario: setup data object Finger print aut
Given a fingerprint of OPENPGP.3 key
And put the data to c9
Then it should get success
Scenario: setup data object keygeneration data/time sig
Given a timestamp of OPENPGP.1 key
And put the data to ce
Then it should get success
Scenario: setup data object keygeneration data/time dec
Given a timestamp of OPENPGP.2 key
And put the data to cf
Then it should get success
Scenario: setup data object keygeneration data/time aut
Given a timestamp of OPENPGP.3 key
And put the data to d0
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,71 @@
Feature: change pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: change PW1
Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: setup reset code again (in admin-full mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-full mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase"
Then it should get success
Scenario: verify PW3 (admin-full mode)
Given cmd_verify with 3 and "another admin pass phrase"
Then it should get success
Scenario: reset pass phrase by admin (in admin-full mode)
Given cmd_reset_retry_counter with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW1
Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: change PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase"
Then it should get success
Scenario: verify PW3 (admin-full mode)
Given cmd_verify with 3 and "admin pass phrase"
Then it should get success

View File

@@ -0,0 +1,31 @@
Feature: compute digital signature
In order to use a token
A token should compute digital signature properly
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "This is a test message."
And let a token compute digital signature
And compute digital signature on host with RSA key pair 0
Then results should be same
Scenario: compute digital signature by OPENPGP.1 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And let a token compute digital signature
And compute digital signature on host with RSA key pair 0
Then results should be same
Scenario: compute digital signature by OPENPGP.3 key (1)
Given a message "This is a test message."
And let a token authenticate
And compute digital signature on host with RSA key pair 2
Then results should be same
Scenario: compute digital signature by OPENPGP.3 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And let a token authenticate
And compute digital signature on host with RSA key pair 2
Then results should be same
Scenario: data object ds counter
When requesting ds counter: 93
Then you should get: \x00\x00\x02

View File

@@ -0,0 +1,16 @@
Feature: decryption
In order to use a token
A token should decrypt encrypted data
Scenario: decrypt by OPENPGP.2 key (1)
Given a plain text "This is a test message."
And encrypt it on host with RSA key pair 1
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text
Scenario: decrypt by OPENPGP.2 key (2)
Given a plain text "RSA decryption is as easy as pie."
And encrypt it on host with RSA key pair 1
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text

View File

@@ -0,0 +1,40 @@
@keygen
Feature: key removal
In order to use a token
A token should have keys
Scenario: remove OPENPGP.1 key (sign)
When removing a key OPENPGP.1
Then it should get success
Scenario: remove OPENPGP.2 key (decrypt)
When removing a key OPENPGP.2
Then it should get success
Scenario: remove OPENPGP.3 key (authentication)
When removing a key OPENPGP.3
Then it should get success
Scenario: remove data object Finger print sig
Given cmd_put_data with c7 and ""
Then it should get success
Scenario: remove data object Finger print dec
Given cmd_put_data with c8 and ""
Then it should get success
Scenario: remove data object Finger print aut
Given cmd_put_data with c9 and ""
Then it should get success
Scenario: remove data object keygeneration data/time sig
Given cmd_put_data with ce and ""
Then it should get success
Scenario: remove data object keygeneration data/time dec
Given cmd_put_data with cf and ""
Then it should get success
Scenario: remove data object keygeneration data/time aut
Given cmd_put_data with d0 and ""
Then it should get success

View File

@@ -0,0 +1,32 @@
@keygen
Feature: setup pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW1 (admin-full mode)
Given cmd_change_reference_data with 1 and "123456user pass phrase"
Then it should get success
Scenario: verify PW1 (1)
Given cmd_verify with 1 and "user pass phrase"
Then it should get success
Scenario: verify PW1 (2)
Given cmd_verify with 2 and "user pass phrase"
Then it should get success
Scenario: setup reset code (in admin-full mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-full mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,37 @@
@keygen
Feature: key generation
In order to use a token
A token should have keys
Scenario: generate OPENPGP.1 key (sign)
When generating a key of OPENPGP.1
And put the first data to c7
And put the second data to ce
Then it should get success
Scenario: generate OPENPGP.2 key (decrypt)
When generating a key of OPENPGP.2
And put the first data to c8
And put the second data to cf
Then it should get success
Scenario: generate OPENPGP.3 key (authentication)
When generating a key of OPENPGP.3
And put the first data to c9
And put the second data to d0
Then it should get success
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "GnuPG assumes that PW1 keeps valid after keygen."
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: verify PW1 (1) after keygen
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) after keygen
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,71 @@
Feature: change pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: change PW1
Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: setup reset code again (in admin-full mode)
Given cmd_put_data with d3 and "example reset code 111"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-full mode)
Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "admin pass phraseanother admin pass phrase"
Then it should get success
Scenario: verify PW3 (admin-full mode)
Given cmd_verify with 3 and "another admin pass phrase"
Then it should get success
Scenario: reset pass phrase by admin (in admin-full mode)
Given cmd_reset_retry_counter with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW1
Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: change PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "another admin pass phraseadmin pass phrase"
Then it should get success
Scenario: verify PW3 (admin-full mode)
Given cmd_verify with 3 and "admin pass phrase"
Then it should get success

View File

@@ -0,0 +1,36 @@
@keygen
Feature: compute digital signature
In order to use a token
A token should compute digital signature properly
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "This is a test message."
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.1 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.3 key (1)
Given a message "This is a test message."
And a public key from token for OPENPGP.3
And let a token authenticate
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.3 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And a public key from token for OPENPGP.3
And let a token authenticate
And verify signature
Then it should get success
Scenario: data object ds counter
When requesting ds counter: 93
Then data should match: \x00\x00(\x02|\x03)

View File

@@ -0,0 +1,19 @@
@keygen
Feature: decryption
In order to use a token
A token should decrypt encrypted data
Scenario: decrypt by OPENPGP.2 key (1)
Given a plain text "This is a test message."
And a public key from token for OPENPGP.2
And encrypt it on host
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text
Scenario: decrypt by OPENPGP.2 key (2)
Given a plain text "RSA decryption is as easy as pie."
And a public key from token for OPENPGP.2
And encrypt it on host
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text

View File

@@ -0,0 +1,39 @@
Feature: key removal
In order to use a token
A token should have keys
Scenario: remove OPENPGP.1 key (sign)
When removing a key OPENPGP.1
Then it should get success
Scenario: remove OPENPGP.2 key (decrypt)
When removing a key OPENPGP.2
Then it should get success
Scenario: remove OPENPGP.3 key (authentication)
When removing a key OPENPGP.3
Then it should get success
Scenario: remove data object Finger print sig
Given cmd_put_data with c7 and ""
Then it should get success
Scenario: remove data object Finger print dec
Given cmd_put_data with c8 and ""
Then it should get success
Scenario: remove data object Finger print aut
Given cmd_put_data with c9 and ""
Then it should get success
Scenario: remove data object keygeneration data/time sig
Given cmd_put_data with ce and ""
Then it should get success
Scenario: remove data object keygeneration data/time dec
Given cmd_put_data with cf and ""
Then it should get success
Scenario: remove data object keygeneration data/time aut
Given cmd_put_data with d0 and ""
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: removal of data objects
In order to use a token
A token should have personalized data
Scenario: remove data object Login
Given cmd_put_data with 5e and ""
Then it should get success
Scenario: remove data object Name
Given cmd_put_data with 5b and ""
Then it should get success
Scenario: remove data object Language preference
Given cmd_put_data with 5f2d and ""
Then it should get success
Scenario: remove data object Sex
Given cmd_put_data with 5f35 and ""
Then it should get success
Scenario: remove data object URL
Given cmd_put_data with 5f50 and ""
Then it should get success
Scenario: remove data object pw1 status bytes
Given cmd_put_data with c4 and "\x00"
Then it should get success

View File

@@ -0,0 +1,7 @@
Feature: reset pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW3 (admin-full mode)
Given cmd_change_reference_data with 3 and "admin pass phrase"
Then it should get success

View File

@@ -0,0 +1,79 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no data, no keys)
Scenario: data object Login
When requesting login data: 5e
Then you should get NULL
Scenario: data object Name
When requesting name: 5b
Then you should get NULL
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get NULL
Scenario: data object Sex
When requesting sex: 5f35
Then you should get NULL
Scenario: data object URL
When requesting URL: 5f50
Then you should get NULL
Scenario: data object ds counter
When requesting ds counter: 93
Then you should get: \x00\x00\x00
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03
Scenario: data object finger print 0
When requesting finger print: c5
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object finger print 1
When requesting finger print: c7
Then you should get NULL
Scenario: data object finger print 2
When requesting finger print: c8
Then you should get NULL
Scenario: data object finger print 3
When requesting finger print: c9
Then you should get NULL
Scenario: data object CA finger print 0
When requesting finger print: c6
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object CA finger print 1
When requesting finger print: ca
Then you should get NULL
Scenario: data object CA finger print 2
When requesting finger print: cb
Then you should get NULL
Scenario: data object CA finger print 3
When requesting finger print: cc
Then you should get NULL
Scenario: data object date/time of key pair 0
When requesting date/time of key pair: cd
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object date/time of key pair 1
When requesting date/time of key pair: ce
Then you should get NULL
Scenario: data object date/time of key pair 2
When requesting date/time of key pair: cf
Then you should get NULL
Scenario: data object date/time of key pair 3
When requesting date/time of key pair: d0
Then you should get NULL

View File

@@ -0,0 +1,15 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no pass phrase)
Scenario: verify PW1 factory setting (1)
Given cmd_verify with 1 and "123456"
Then it should get success
Scenario: verify PW1 factory setting (2)
Given cmd_verify with 2 and "123456"
Then it should get success
Scenario: verify PW3 factory setting
Given cmd_verify with 3 and "12345678"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: command GET DATA
In order to conform OpenPGP card 2.0 specification
A token should support all mandatory features of the specification
Scenario: data object historical bytes
When requesting historical bytes: 5f52
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 2
When requesting algorithm attributes 2: c2
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 3
When requesting algorighm attributes 3: c3
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00

View File

@@ -0,0 +1,55 @@
Feature: setup pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW1 (admin-less mode)
Given cmd_change_reference_data with 1 and "123456user pass phrase"
Then it should get success
Scenario: verify PW1 (1)
Given cmd_verify with 1 and "user pass phrase"
Then it should get success
Scenario: verify PW1 (2)
Given cmd_verify with 2 and "user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "user pass phrase"
Then it should get success
Scenario: setup reset code (in admin-less mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-less mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode) again
Given cmd_verify with 3 and "new user pass phrase"
Then it should get success
Scenario: change PW1
Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode) again
Given cmd_verify with 3 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token write
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
Given cmd_put_data with 5e and "gpg_user"
Then it should get success
Scenario: data object Name
Given cmd_put_data with 5b and "GnuPG User"
Then it should get success
Scenario: data object Language preference
Given cmd_put_data with 5f2d and "ja"
Then it should get success
Scenario: data object Sex
Given cmd_put_data with 5f35 and "1"
Then it should get success
Scenario: data object URL
Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/"
Then it should get success
Scenario: data object pw1 status bytes
Given cmd_put_data with c4 and "\x01"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token read
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
When requesting login data: 5e
Then you should get: gpg_user
Scenario: data object Name
When requesting name: 5b
Then you should get: GnuPG User
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get: ja
Scenario: data object Sex
When requesting sex: 5f35
Then you should get: 1
Scenario: data object URL
When requesting URL: 5f50
Then you should get: http://www.fsij.org/gnuk/
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03

View File

@@ -0,0 +1,56 @@
Feature: import keys to token
In order to use a token
A token should have keys
Scenario: importing OPENPGP.1 key (sign)
Given a RSA key pair 0
And importing it to the token as OPENPGP.1
Then it should get success
Scenario: importing OPENPGP.2 key (decrypt)
Given a RSA key pair 1
And importing it to the token as OPENPGP.2
Then it should get success
Scenario: importing OPENPGP.3 key (authentication)
Given a RSA key pair 2
And importing it to the token as OPENPGP.3
Then it should get success
Scenario: setup data object Finger print sig
Given a fingerprint of OPENPGP.1 key
And put the data to c7
Then it should get success
Scenario: setup data object Finger print dec
Given a fingerprint of OPENPGP.2 key
And put the data to c8
Then it should get success
Scenario: setup data object Finger print aut
Given a fingerprint of OPENPGP.3 key
And put the data to c9
Then it should get success
Scenario: setup data object keygeneration data/time sig
Given a timestamp of OPENPGP.1 key
And put the data to ce
Then it should get success
Scenario: setup data object keygeneration data/time dec
Given a timestamp of OPENPGP.2 key
And put the data to cf
Then it should get success
Scenario: setup data object keygeneration data/time aut
Given a timestamp of OPENPGP.3 key
And put the data to d0
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,51 @@
Feature: change pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: change PW1 (in admin-less mode)
Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: setup reset code again (in admin-less mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-less mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW1
Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,31 @@
Feature: compute digital signature
In order to use a token
A token should compute digital signature properly
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "This is a test message."
And let a token compute digital signature
And compute digital signature on host with RSA key pair 0
Then results should be same
Scenario: compute digital signature by OPENPGP.1 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And let a token compute digital signature
And compute digital signature on host with RSA key pair 0
Then results should be same
Scenario: compute digital signature by OPENPGP.3 key (1)
Given a message "This is a test message."
And let a token authenticate
And compute digital signature on host with RSA key pair 2
Then results should be same
Scenario: compute digital signature by OPENPGP.3 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And let a token authenticate
And compute digital signature on host with RSA key pair 2
Then results should be same
Scenario: data object ds counter
When requesting ds counter: 93
Then you should get: \x00\x00\x02

View File

@@ -0,0 +1,16 @@
Feature: decryption
In order to use a token
A token should decrypt encrypted data
Scenario: decrypt by OPENPGP.2 key (1)
Given a plain text "This is a test message."
And encrypt it on host with RSA key pair 1
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text
Scenario: decrypt by OPENPGP.2 key (2)
Given a plain text "RSA decryption is as easy as pie."
And encrypt it on host with RSA key pair 1
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text

View File

@@ -0,0 +1,44 @@
@keygen
Feature: key removal
In order to use a token
A token should have keys
Scenario: remove OPENPGP.1 key (sign)
When removing a key OPENPGP.1
Then it should get success
Scenario: remove OPENPGP.2 key (decrypt)
When removing a key OPENPGP.2
Then it should get success
Scenario: remove OPENPGP.3 key (authentication)
When removing a key OPENPGP.3
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "12345678"
Then it should get success
Scenario: remove data object Finger print sig
Given cmd_put_data with c7 and ""
Then it should get success
Scenario: remove data object Finger print dec
Given cmd_put_data with c8 and ""
Then it should get success
Scenario: remove data object Finger print aut
Given cmd_put_data with c9 and ""
Then it should get success
Scenario: remove data object keygeneration data/time sig
Given cmd_put_data with ce and ""
Then it should get success
Scenario: remove data object keygeneration data/time dec
Given cmd_put_data with cf and ""
Then it should get success
Scenario: remove data object keygeneration data/time aut
Given cmd_put_data with d0 and ""
Then it should get success

View File

@@ -0,0 +1,40 @@
@keygen
Feature: setup pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: setup PW1 (admin-less mode)
Given cmd_change_reference_data with 1 and "123456user pass phrase"
Then it should get success
Scenario: verify PW1 (1)
Given cmd_verify with 1 and "user pass phrase"
Then it should get success
Scenario: verify PW1 (2)
Given cmd_verify with 2 and "user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "user pass phrase"
Then it should get success
Scenario: setup reset code (in admin-less mode)
Given cmd_put_data with d3 and "example reset code 000"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-less mode)
Given cmd_reset_retry_counter with 0 and "example reset code 000another user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode) again
Given cmd_verify with 3 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,37 @@
@keygen
Feature: key generation
In order to use a token
A token should have keys
Scenario: generate OPENPGP.1 key (sign)
When generating a key of OPENPGP.1
And put the first data to c7
And put the second data to ce
Then it should get success
Scenario: generate OPENPGP.2 key (decrypt)
When generating a key of OPENPGP.2
And put the first data to c8
And put the second data to cf
Then it should get success
Scenario: generate OPENPGP.3 key (authentication)
When generating a key of OPENPGP.3
And put the first data to c9
And put the second data to d0
Then it should get success
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "GnuPG assumes that PW1 keeps valid after keygen."
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: verify PW1 (1) after keygen
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) after keygen
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,67 @@
Feature: change pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: change PW1
Given cmd_change_reference_data with 1 and "another user pass phrasePASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "PASSPHRASE SHOULD BE LONG"
Then it should get success
Scenario: setup reset code again (in admin-less mode)
Given cmd_put_data with d3 and "example reset code 111"
Then it should get success
Scenario: reset pass phrase by reset code (in admin-less mode)
Given cmd_reset_retry_counter with 0 and "example reset code 111new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "new user pass phrase"
Then it should get success
Scenario: reset pass phrase by admin (in admin-less mode)
Given cmd_reset_retry_counter with 2 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "new user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "new user pass phrase"
Then it should get success
Scenario: change PW1
Given cmd_change_reference_data with 1 and "new user pass phraseanother user pass phrase"
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "another user pass phrase"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "another user pass phrase"
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "another user pass phrase"
Then it should get success

View File

@@ -0,0 +1,36 @@
@keygen
Feature: compute digital signature
In order to use a token
A token should compute digital signature properly
Scenario: compute digital signature by OPENPGP.1 key (1)
Given a message "This is a test message."
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.1 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And a public key from token for OPENPGP.1
And let a token compute digital signature
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.3 key (1)
Given a message "This is a test message."
And a public key from token for OPENPGP.3
And let a token authenticate
And verify signature
Then it should get success
Scenario: compute digital signature by OPENPGP.3 key (2)
Given a message "This is another test message.\nMultiple lines.\n"
And a public key from token for OPENPGP.3
And let a token authenticate
And verify signature
Then it should get success
Scenario: data object ds counter
When requesting ds counter: 93
Then data should match: \x00\x00(\x02|\x03)

View File

@@ -0,0 +1,19 @@
@keygen
Feature: decryption
In order to use a token
A token should decrypt encrypted data
Scenario: decrypt by OPENPGP.2 key (1)
Given a plain text "This is a test message."
And a public key from token for OPENPGP.2
And encrypt it on host
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text
Scenario: decrypt by OPENPGP.2 key (2)
Given a plain text "RSA decryption is as easy as pie."
And a public key from token for OPENPGP.2
And encrypt it on host
And let a token decrypt encrypted data
Then decrypted data should be same as a plain text

View File

@@ -0,0 +1,43 @@
Feature: key removal
In order to use a token
A token should have keys
Scenario: remove OPENPGP.1 key (sign)
When removing a key OPENPGP.1
Then it should get success
Scenario: remove OPENPGP.2 key (decrypt)
When removing a key OPENPGP.2
Then it should get success
Scenario: remove OPENPGP.3 key (authentication)
When removing a key OPENPGP.3
Then it should get success
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "12345678"
Then it should get success
Scenario: remove data object Finger print sig
Given cmd_put_data with c7 and ""
Then it should get success
Scenario: remove data object Finger print dec
Given cmd_put_data with c8 and ""
Then it should get success
Scenario: remove data object Finger print aut
Given cmd_put_data with c9 and ""
Then it should get success
Scenario: remove data object keygeneration data/time sig
Given cmd_put_data with ce and ""
Then it should get success
Scenario: remove data object keygeneration data/time dec
Given cmd_put_data with cf and ""
Then it should get success
Scenario: remove data object keygeneration data/time aut
Given cmd_put_data with d0 and ""
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: removal of data objects
In order to use a token
A token should have personalized data
Scenario: remove data object Login
Given cmd_put_data with 5e and ""
Then it should get success
Scenario: remove data object Name
Given cmd_put_data with 5b and ""
Then it should get success
Scenario: remove data object Language preference
Given cmd_put_data with 5f2d and ""
Then it should get success
Scenario: remove data object Sex
Given cmd_put_data with 5f35 and ""
Then it should get success
Scenario: remove data object URL
Given cmd_put_data with 5f50 and ""
Then it should get success
Scenario: remove data object pw1 status bytes
Given cmd_put_data with c4 and "\x00"
Then it should get success

View File

@@ -0,0 +1,7 @@
Feature: confirm factory setting pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: verify PW3 (admin-less mode)
Given cmd_verify with 3 and "12345678"
Then it should get success

View File

@@ -0,0 +1,79 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no data, no keys)
Scenario: data object Login
When requesting login data: 5e
Then you should get NULL
Scenario: data object Name
When requesting name: 5b
Then you should get NULL
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get NULL
Scenario: data object Sex
When requesting sex: 5f35
Then you should get NULL
Scenario: data object URL
When requesting URL: 5f50
Then you should get NULL
Scenario: data object ds counter
When requesting ds counter: 93
Then you should get: \x00\x00\x00
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x00\x7f\x7f\x7f\x03\x03\x03
Scenario: data object finger print 0
When requesting finger print: c5
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object finger print 1
When requesting finger print: c7
Then you should get NULL
Scenario: data object finger print 2
When requesting finger print: c8
Then you should get NULL
Scenario: data object finger print 3
When requesting finger print: c9
Then you should get NULL
Scenario: data object CA finger print 0
When requesting finger print: c6
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object CA finger print 1
When requesting finger print: ca
Then you should get NULL
Scenario: data object CA finger print 2
When requesting finger print: cb
Then you should get NULL
Scenario: data object CA finger print 3
When requesting finger print: cc
Then you should get NULL
Scenario: data object date/time of key pair 0
When requesting date/time of key pair: cd
Then you should get: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Scenario: data object date/time of key pair 1
When requesting date/time of key pair: ce
Then you should get NULL
Scenario: data object date/time of key pair 2
When requesting date/time of key pair: cf
Then you should get NULL
Scenario: data object date/time of key pair 3
When requesting date/time of key pair: d0
Then you should get NULL

View File

@@ -0,0 +1,15 @@
Feature: confirm empty token
In order to start tests
A token should be empty (no pass phrase)
Scenario: verify PW1 factory setting (1)
Given cmd_verify with 1 and "123456"
Then it should get success
Scenario: verify PW1 factory setting (2)
Given cmd_verify with 2 and "123456"
Then it should get success
Scenario: verify PW3 factory setting
Given cmd_verify with 3 and "12345678"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: command GET DATA
In order to conform OpenPGP card 2.0 specification
A token should support all mandatory features of the specification
Scenario: data object historical bytes
When requesting historical bytes: 5f52
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
Scenario: data object extended capabilities
When requesting extended capabilities: c0
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
Scenario: data object algorithm attributes 1
When requesting algorithm attributes 1: c1
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 2
When requesting algorithm attributes 2: c2
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object algorithm attributes 3
When requesting algorighm attributes 3: c3
Then you should get: \x01\x08\x00\x00\x20\x00
Scenario: data object AID
When requesting AID: 4f
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00

View File

@@ -0,0 +1,15 @@
Feature: check pass phrase
In order to conform OpenPGP card 2.0 specification
A token should support pass phrase: PW1, PW3 and reset code
Scenario: verify PW1 (1)
Given cmd_verify with 1 and "123456"
Then it should get success
Scenario: verify PW1 (2)
Given cmd_verify with 2 and "123456"
Then it should get success
Scenario: verify PW3
Given cmd_verify with 3 and "12345678"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token write
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
Given cmd_put_data with 5e and "gpg_user"
Then it should get success
Scenario: data object Name
Given cmd_put_data with 5b and "GnuPG User"
Then it should get success
Scenario: data object Language preference
Given cmd_put_data with 5f2d and "ja"
Then it should get success
Scenario: data object Sex
Given cmd_put_data with 5f35 and "1"
Then it should get success
Scenario: data object URL
Given cmd_put_data with 5f50 and "http://www.fsij.org/gnuk/"
Then it should get success
Scenario: data object pw1 status bytes
Given cmd_put_data with c4 and "\x01"
Then it should get success

View File

@@ -0,0 +1,27 @@
Feature: personalize token read
In order to use a token
A token should be personalized with name, sex, url, etc.
Scenario: data object Login
When requesting login data: 5e
Then you should get: gpg_user
Scenario: data object Name
When requesting name: 5b
Then you should get: GnuPG User
Scenario: data object Language preference
When requesting anguage preference: 5f2d
Then you should get: ja
Scenario: data object Sex
When requesting sex: 5f35
Then you should get: 1
Scenario: data object URL
When requesting URL: 5f50
Then you should get: http://www.fsij.org/gnuk/
Scenario: data object pw1 status bytes
When requesting pw1 status bytes: c4
Then you should get: \x01\x7f\x7f\x7f\x03\x03\x03

View File

@@ -0,0 +1,56 @@
Feature: import keys to token
In order to use a token
A token should have keys
Scenario: importing OPENPGP.1 key (sign)
Given a RSA key pair 0
And importing it to the token as OPENPGP.1
Then it should get success
Scenario: importing OPENPGP.2 key (decrypt)
Given a RSA key pair 1
And importing it to the token as OPENPGP.2
Then it should get success
Scenario: importing OPENPGP.3 key (authentication)
Given a RSA key pair 2
And importing it to the token as OPENPGP.3
Then it should get success
Scenario: setup data object Finger print sig
Given a fingerprint of OPENPGP.1 key
And put the data to c7
Then it should get success
Scenario: setup data object Finger print dec
Given a fingerprint of OPENPGP.2 key
And put the data to c8
Then it should get success
Scenario: setup data object Finger print aut
Given a fingerprint of OPENPGP.3 key
And put the data to c9
Then it should get success
Scenario: setup data object keygeneration data/time sig
Given a timestamp of OPENPGP.1 key
And put the data to ce
Then it should get success
Scenario: setup data object keygeneration data/time dec
Given a timestamp of OPENPGP.2 key
And put the data to cf
Then it should get success
Scenario: setup data object keygeneration data/time aut
Given a timestamp of OPENPGP.3 key
And put the data to d0
Then it should get success
Scenario: verify PW1 (1) again
Given cmd_verify with 1 and "123456"
Then it should get success
Scenario: verify PW1 (2) again
Given cmd_verify with 2 and "123456"
Then it should get success

Some files were not shown because too many files have changed in this diff Show More