Compare commits
117 Commits
release/0.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed61ed980d | ||
|
|
7ff0baf5df | ||
|
|
46259ce63d | ||
|
|
0aca10f307 | ||
|
|
5f2a8b835c | ||
|
|
5213d9ab82 | ||
|
|
c12f331217 | ||
|
|
62b4369d2c | ||
|
|
9dde59867d | ||
|
|
eae955b15e | ||
|
|
7e8dd12654 | ||
|
|
8c91d2ef2e | ||
|
|
6b6913c676 | ||
|
|
3ad9373163 | ||
|
|
220d5c0307 | ||
|
|
de7f9f6417 | ||
|
|
a302585602 | ||
|
|
ea2191105f | ||
|
|
32094099dd | ||
|
|
9b71d70b73 | ||
|
|
77d06fb301 | ||
|
|
78b642507b | ||
|
|
90a11859dc | ||
|
|
ad9a901e1b | ||
|
|
500b12b60d | ||
|
|
4bfe087583 | ||
|
|
22d0cb689a | ||
|
|
fe6337f988 | ||
|
|
1a2560531d | ||
|
|
40e234b799 | ||
|
|
deccb981ad | ||
|
|
12bd1161a4 | ||
|
|
d72a0b7893 | ||
|
|
ee5b6a2a82 | ||
|
|
f9b43a67ee | ||
|
|
70846e8b81 | ||
|
|
f6df7701f9 | ||
|
|
b9772265cf | ||
|
|
254c521c6f | ||
|
|
d7c6b95ba1 | ||
|
|
2e7d93a556 | ||
|
|
db2d897c3f | ||
|
|
23a9fe3bdc | ||
|
|
e8f773d2f6 | ||
|
|
6b5fc04c0d | ||
|
|
39bee2ee01 | ||
|
|
f39380d3aa | ||
|
|
0d36a58804 | ||
|
|
eb0e913eee | ||
|
|
7575dda42a | ||
|
|
61ec9b7ed7 | ||
|
|
b49390de7a | ||
|
|
71eaffc0ee | ||
|
|
5e9a35c881 | ||
|
|
df5b7f31a3 | ||
|
|
add6fa8b67 | ||
|
|
c488bed215 | ||
|
|
63979416f6 | ||
|
|
92be182e8a | ||
|
|
9ffa68355d | ||
|
|
814f6b6329 | ||
|
|
1927f8a1ec | ||
|
|
d3fb62b437 | ||
|
|
5d3e6c2b29 | ||
|
|
8be278be17 | ||
|
|
6de9c11329 | ||
|
|
63df97a2e0 | ||
|
|
144dd88a07 | ||
|
|
e80c8f1e8e | ||
|
|
99d7e8d396 | ||
|
|
f38f33dade | ||
|
|
cbed6b49c7 | ||
|
|
51435e7dba | ||
|
|
29b68186bf | ||
|
|
a5fddc691d | ||
|
|
965dace0a4 | ||
|
|
ee4f3806c2 | ||
|
|
9ad6c6461d | ||
|
|
a796e9f145 | ||
|
|
f88e7af3ce | ||
|
|
fe31219d94 | ||
|
|
6f97e8a7c4 | ||
|
|
e78206e1cd | ||
|
|
ffba0e0158 | ||
|
|
324b648de8 | ||
|
|
9ef97836c9 | ||
|
|
628c03634b | ||
|
|
315bef4639 | ||
|
|
610573256e | ||
|
|
976e123413 | ||
|
|
6f4c868336 | ||
|
|
33c3980e46 | ||
|
|
6d8580f67a | ||
|
|
506761d823 | ||
|
|
09f22b114c | ||
|
|
9f0b8ff4c3 | ||
|
|
2764bbb5a9 | ||
|
|
3202b7d45c | ||
|
|
19e677ae74 | ||
|
|
9cc6de9e65 | ||
|
|
0988474d87 | ||
|
|
d564e4a3c1 | ||
|
|
839b0156a9 | ||
|
|
92d500d4b5 | ||
|
|
1944a78443 | ||
|
|
e11d81376c | ||
|
|
3c7a5bff61 | ||
|
|
a41476ab32 | ||
|
|
1118cd030a | ||
|
|
e6e11ddcb0 | ||
|
|
5c5074c5c7 | ||
|
|
d3f092a736 | ||
|
|
70efd3a1cd | ||
|
|
fd9f46bcc7 | ||
|
|
6f203bc4ea | ||
|
|
c25d98bc58 | ||
|
|
4290a2cc10 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -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
|
||||
|
||||
365
ChangeLog
365
ChangeLog
@@ -1,3 +1,368 @@
|
||||
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.
|
||||
|
||||
@@ -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> #################
|
||||
|
||||
74
NEWS
74
NEWS
@@ -1,5 +1,77 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
* 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 +95,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
|
||||
|
||||
125
README
125
README
@@ -1,7 +1,7 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 0.20
|
||||
2012-06-19
|
||||
Version 1.0.2
|
||||
2013-02-15
|
||||
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,18 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
|
||||
"GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
Qc: Do you know a good SWD debugger to connect FST-01 or something?
|
||||
Ac: STLink v2 is cheap one. See http://code.google.com/p/arm-utilities/
|
||||
for a control program.
|
||||
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
|
||||
writer program.
|
||||
|
||||
|
||||
Release notes
|
||||
=============
|
||||
|
||||
This is "version 1.0 release 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 second 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 +136,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 +154,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
|
||||
@@ -255,9 +261,8 @@ please contact Niibe, so that it is listed to the file in the official
|
||||
release of the source code.
|
||||
|
||||
When you are modifing Gnuk and installing the binary to device, you
|
||||
should replace "FSIJ" in the string gnukStringSerial (usb_desc.c) to
|
||||
yours, so that the device will say it's modified version by device
|
||||
serial number.
|
||||
should replace the vendor string to yours, so that users can see it's
|
||||
not by original vendor, and it is modified version.
|
||||
|
||||
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices
|
||||
with Gnuk under one of following conditions:
|
||||
@@ -288,15 +293,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 +318,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 +334,13 @@ of binutils-2.21.1) for preparation of GNU Toolchain for
|
||||
# -mno-thumb-interwork option. This means that you should not
|
||||
# link C library which contains ARM (not Thumb) code.
|
||||
|
||||
Recently, there is "gcc-arm-embedded" project. See:
|
||||
|
||||
https://launchpad.net/gcc-arm-embedded/
|
||||
|
||||
It is based on GCC 4.6. For version 4.6-2012-q2-update, you'd
|
||||
need "-O3 -Os" instead of "-O2" and it will be slightly better.
|
||||
|
||||
|
||||
Change directory to `src':
|
||||
|
||||
@@ -475,7 +488,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 +567,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 +595,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 +657,13 @@ linux/Documentation/usb/usbmon.txt
|
||||
Firmware update
|
||||
===============
|
||||
|
||||
See doc/firmware-update.
|
||||
See doc/note/firmware-update.
|
||||
|
||||
|
||||
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 +674,8 @@ or
|
||||
$ git clone http://www.gniibe.org/git/gnuk.git/
|
||||
|
||||
|
||||
Copy is available at: http://gitorious.org/gnuk
|
||||
|
||||
|
||||
Information on the Web
|
||||
======================
|
||||
|
||||
1
THANKS
1
THANKS
@@ -11,6 +11,7 @@ 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
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
153
doc/Makefile
Normal 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
3
doc/__update_web
Normal 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
246
doc/conf.py
Normal 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
71
doc/development.rst
Normal 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".
|
||||
311
doc/generating-2048-RSA-key.rst
Normal file
311
doc/generating-2048-RSA-key.rst
Normal 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
|
||||
38
doc/gnome3-gpg-settings.rst
Normal file
38
doc/gnome3-gpg-settings.rst
Normal 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.
|
||||
183
doc/gnuk-keytocard-noremoval.rst
Normal file
183
doc/gnuk-keytocard-noremoval.rst
Normal 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
193
doc/gnuk-keytocard.rst
Normal 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.
|
||||
153
doc/gnuk-personalization.rst
Normal file
153
doc/gnuk-personalization.rst
Normal 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.
|
||||
43
doc/gnuk-token-initial-configuration.rst
Normal file
43
doc/gnuk-token-initial-configuration.rst
Normal 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
43
doc/gpg-settings.rst
Normal 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
BIN
doc/images/gnuk-sticker.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
37
doc/index.rst
Normal file
37
doc/index.rst
Normal 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
69
doc/intro.rst
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
37
doc/stop-scdaemon.rst
Normal 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
51
doc/udev-rules.rst
Normal 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.
|
||||
178
doc/using-gnuk-token-with-another-computer.rst
Normal file
178
doc/using-gnuk-token-with-another-computer.rst
Normal 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
|
||||
$
|
||||
@@ -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
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
PROJECT = regnual
|
||||
|
||||
SRCS = regnual.c usb_lld.c sys.c
|
||||
OBJS = regnual.o usb_lld.o sys.o
|
||||
LDSCRIPT= regnual.ld
|
||||
|
||||
@@ -23,7 +22,7 @@ MCFLAGS= -mcpu=$(MCU) -mfix-cortex-m3-ldrd
|
||||
DEFS = -DFREE_STANDING
|
||||
|
||||
CFLAGS = -O2 -g
|
||||
CFLAGS += $(CWARN) -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
|
||||
CFLAGS += $(CWARN) -I . -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
|
||||
|
||||
LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
|
||||
|
||||
@@ -38,8 +37,8 @@ regnual.hex: regnual.elf
|
||||
$(OBJCOPY) -Obinary regnual.elf regnual.bin
|
||||
$(OBJCOPY) -Oihex regnual.elf regnual.hex
|
||||
|
||||
usb_lld.c: ../src/usb_lld.c
|
||||
cp -p ../src/usb_lld.c .
|
||||
usb_lld.o: ../src/usb_lld.c
|
||||
$(CC) $(CFLAGS) -c -o usb_lld.o ../src/usb_lld.c
|
||||
|
||||
regnual.elf: $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
|
||||
@@ -48,4 +47,3 @@ clean:
|
||||
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin
|
||||
|
||||
distclean: clean
|
||||
-rm -f usb_lld.c
|
||||
|
||||
@@ -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).
|
||||
|
||||
10
src/ac.c
10
src/ac.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ac.c -- Check access condition
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2012 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 (;;);
|
||||
}
|
||||
155
src/openpgp-do.c
155
src/openpgp-do.c
@@ -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
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -1086,18 +1105,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 +1303,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 +1393,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 +1408,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 +1523,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 +1581,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);
|
||||
}
|
||||
|
||||
155
src/openpgp.c
155
src/openpgp.c
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total[2];
|
||||
|
||||
@@ -827,36 +827,7 @@ icc_power_off (struct ccid *c)
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_data_block_0x9000 (struct ccid *c)
|
||||
{
|
||||
uint8_t p[ICC_MSG_HEADER_SIZE+2];
|
||||
size_t len = 2;
|
||||
|
||||
p[0] = ICC_DATA_BLOCK_RET;
|
||||
p[1] = len & 0xFF;
|
||||
p[2] = (len >> 8)& 0xFF;
|
||||
p[3] = (len >> 16)& 0xFF;
|
||||
p[4] = (len >> 24)& 0xFF;
|
||||
p[5] = 0x00; /* Slot */
|
||||
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
|
||||
p[ICC_MSG_STATUS_OFFSET] = 0;
|
||||
p[ICC_MSG_ERROR_OFFSET] = 0;
|
||||
p[ICC_MSG_CHAIN_OFFSET] = 0;
|
||||
p[ICC_MSG_CHAIN_OFFSET+1] = 0x90;
|
||||
p[ICC_MSG_CHAIN_OFFSET+2] = 0x00;
|
||||
|
||||
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len);
|
||||
c->epi->buf = NULL;
|
||||
c->epi->tx_done = 1;
|
||||
|
||||
usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len);
|
||||
#ifdef DEBUG_MORE
|
||||
DEBUG_INFO ("DATA\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_data_block (struct ccid *c, uint8_t status)
|
||||
icc_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error)
|
||||
{
|
||||
int tx_size = USB_LL_BUF_SIZE;
|
||||
uint8_t p[ICC_MSG_HEADER_SIZE];
|
||||
@@ -875,7 +846,7 @@ icc_send_data_block (struct ccid *c, uint8_t status)
|
||||
p[5] = 0x00; /* Slot */
|
||||
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
|
||||
p[ICC_MSG_STATUS_OFFSET] = status;
|
||||
p[ICC_MSG_ERROR_OFFSET] = 0;
|
||||
p[ICC_MSG_ERROR_OFFSET] = error;
|
||||
p[ICC_MSG_CHAIN_OFFSET] = 0;
|
||||
|
||||
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE);
|
||||
@@ -933,6 +904,50 @@ icc_send_data_block (struct ccid *c, uint8_t status)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_data_block (struct ccid *c)
|
||||
{
|
||||
icc_send_data_block_internal (c, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_data_block_time_extension (struct ccid *c)
|
||||
{
|
||||
icc_send_data_block_internal (c, ICC_CMD_STATUS_TIMEEXT, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
icc_send_data_block_0x9000 (struct ccid *c)
|
||||
{
|
||||
uint8_t p[ICC_MSG_HEADER_SIZE+2];
|
||||
size_t len = 2;
|
||||
|
||||
p[0] = ICC_DATA_BLOCK_RET;
|
||||
p[1] = len & 0xFF;
|
||||
p[2] = (len >> 8)& 0xFF;
|
||||
p[3] = (len >> 16)& 0xFF;
|
||||
p[4] = (len >> 24)& 0xFF;
|
||||
p[5] = 0x00; /* Slot */
|
||||
p[ICC_MSG_SEQ_OFFSET] = c->a->seq;
|
||||
p[ICC_MSG_STATUS_OFFSET] = 0;
|
||||
p[ICC_MSG_ERROR_OFFSET] = 0;
|
||||
p[ICC_MSG_CHAIN_OFFSET] = 0;
|
||||
p[ICC_MSG_CHAIN_OFFSET+1] = 0x90;
|
||||
p[ICC_MSG_CHAIN_OFFSET+2] = 0x00;
|
||||
|
||||
usb_lld_txcpy (p, c->epi->ep_num, 0, ICC_MSG_HEADER_SIZE + len);
|
||||
c->epi->buf = NULL;
|
||||
c->epi->tx_done = 1;
|
||||
|
||||
usb_lld_tx_enable (c->epi->ep_num, ICC_MSG_HEADER_SIZE + len);
|
||||
#ifdef DEBUG_MORE
|
||||
DEBUG_INFO ("DATA\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Reply to the host for "GET RESPONSE".
|
||||
*/
|
||||
static void
|
||||
icc_send_data_block_gr (struct ccid *c, size_t chunk_len)
|
||||
{
|
||||
@@ -1260,7 +1275,7 @@ icc_handle_timeout (struct ccid *c)
|
||||
switch (c->icc_state)
|
||||
{
|
||||
case ICC_STATE_EXECUTE:
|
||||
icc_send_data_block (c, ICC_CMD_STATUS_TIMEEXT);
|
||||
icc_send_data_block_time_extension (c);
|
||||
led_blink (LED_ONESHOT);
|
||||
break;
|
||||
default:
|
||||
@@ -1311,7 +1326,7 @@ USBthread (void *arg)
|
||||
c->sw1sw2[0] = 0x90;
|
||||
c->sw1sw2[1] = 0x00;
|
||||
c->state = APDU_STATE_RESULT;
|
||||
icc_send_data_block (c, 0);
|
||||
icc_send_data_block (c);
|
||||
c->icc_state = ICC_STATE_EXITED;
|
||||
break;
|
||||
}
|
||||
@@ -1323,7 +1338,7 @@ USBthread (void *arg)
|
||||
if (c->a->res_apdu_data_len <= c->a->expected_res_size)
|
||||
{
|
||||
c->state = APDU_STATE_RESULT;
|
||||
icc_send_data_block (c, 0);
|
||||
icc_send_data_block (c);
|
||||
c->icc_state = ICC_STATE_WAIT;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -258,11 +258,11 @@ 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.1- */
|
||||
'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, '2', 0, /* Version number of Gnuk */
|
||||
'-', 0,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
|
||||
20
test/README
Normal file
20
test/README
Normal 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.
|
||||
79
test/features/000_empty_check.feature
Normal file
79
test/features/000_empty_check.feature
Normal 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
|
||||
15
test/features/001_empty_check_passphrase.feature
Normal file
15
test/features/001_empty_check_passphrase.feature
Normal 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
|
||||
27
test/features/002_get_data_static.feature
Normal file
27
test/features/002_get_data_static.feature
Normal 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
|
||||
63
test/features/010_setup_passphrase.feature
Normal file
63
test/features/010_setup_passphrase.feature
Normal 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
|
||||
27
test/features/020_personalization_write.feature
Normal file
27
test/features/020_personalization_write.feature
Normal 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
|
||||
27
test/features/021_personalization_read.feature
Normal file
27
test/features/021_personalization_read.feature
Normal 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
|
||||
56
test/features/030_key_registration.feature
Normal file
56
test/features/030_key_registration.feature
Normal 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
|
||||
71
test/features/040_passphrase_change.feature
Normal file
71
test/features/040_passphrase_change.feature
Normal 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
|
||||
31
test/features/100_compute_signature.feature
Normal file
31
test/features/100_compute_signature.feature
Normal 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
|
||||
16
test/features/101_decryption.feature
Normal file
16
test/features/101_decryption.feature
Normal 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
|
||||
|
||||
40
test/features/200_key_removal.feature
Normal file
40
test/features/200_key_removal.feature
Normal 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
|
||||
32
test/features/201_setup_passphrase.feature
Normal file
32
test/features/201_setup_passphrase.feature
Normal 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
|
||||
37
test/features/202_keygen.feature
Normal file
37
test/features/202_keygen.feature
Normal 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
|
||||
71
test/features/203_passphrase_change.feature
Normal file
71
test/features/203_passphrase_change.feature
Normal 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
|
||||
36
test/features/210_compute_signature.feature
Normal file
36
test/features/210_compute_signature.feature
Normal 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)
|
||||
19
test/features/211_decryption.feature
Normal file
19
test/features/211_decryption.feature
Normal 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
|
||||
|
||||
39
test/features/370_key_removal.feature
Normal file
39
test/features/370_key_removal.feature
Normal 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
|
||||
27
test/features/380_personalization_reset.feature
Normal file
27
test/features/380_personalization_reset.feature
Normal 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
|
||||
7
test/features/390_reset_passphrase.feature
Normal file
7
test/features/390_reset_passphrase.feature
Normal 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
|
||||
79
test/features/400_empty_check.feature
Normal file
79
test/features/400_empty_check.feature
Normal 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
|
||||
15
test/features/401_empty_check_passphrase.feature
Normal file
15
test/features/401_empty_check_passphrase.feature
Normal 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
|
||||
27
test/features/402_get_data_static.feature
Normal file
27
test/features/402_get_data_static.feature
Normal 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
|
||||
55
test/features/410_setup_passphrase.feature
Normal file
55
test/features/410_setup_passphrase.feature
Normal 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
|
||||
27
test/features/420_personalization_write.feature
Normal file
27
test/features/420_personalization_write.feature
Normal 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
|
||||
27
test/features/421_personalization_read.feature
Normal file
27
test/features/421_personalization_read.feature
Normal 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
|
||||
56
test/features/430_key_registration.feature
Normal file
56
test/features/430_key_registration.feature
Normal 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
|
||||
51
test/features/440_passphrase_change.feature
Normal file
51
test/features/440_passphrase_change.feature
Normal 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
|
||||
31
test/features/500_compute_signature.feature
Normal file
31
test/features/500_compute_signature.feature
Normal 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
|
||||
16
test/features/501_decryption.feature
Normal file
16
test/features/501_decryption.feature
Normal 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
|
||||
|
||||
44
test/features/600_key_removal.feature
Normal file
44
test/features/600_key_removal.feature
Normal 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
|
||||
40
test/features/601_setup_passphrase.feature
Normal file
40
test/features/601_setup_passphrase.feature
Normal 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
|
||||
37
test/features/602_keygen.feature
Normal file
37
test/features/602_keygen.feature
Normal 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
|
||||
67
test/features/603_passphrase_change.feature
Normal file
67
test/features/603_passphrase_change.feature
Normal 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
|
||||
36
test/features/610_compute_signature.feature
Normal file
36
test/features/610_compute_signature.feature
Normal 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)
|
||||
19
test/features/611_decryption.feature
Normal file
19
test/features/611_decryption.feature
Normal 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
|
||||
|
||||
43
test/features/770_key_removal.feature
Normal file
43
test/features/770_key_removal.feature
Normal 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
|
||||
27
test/features/780_personalization_reset.feature
Normal file
27
test/features/780_personalization_reset.feature
Normal 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
|
||||
7
test/features/790_reset_passphrase.feature
Normal file
7
test/features/790_reset_passphrase.feature
Normal 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
|
||||
79
test/features/800_empty_check.feature
Normal file
79
test/features/800_empty_check.feature
Normal 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
|
||||
15
test/features/801_empty_check_passphrase.feature
Normal file
15
test/features/801_empty_check_passphrase.feature
Normal 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
|
||||
27
test/features/802_get_data_static.feature
Normal file
27
test/features/802_get_data_static.feature
Normal 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
|
||||
15
test/features/810_setup_passphrase.feature
Normal file
15
test/features/810_setup_passphrase.feature
Normal 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
|
||||
27
test/features/820_personalization_write.feature
Normal file
27
test/features/820_personalization_write.feature
Normal 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
|
||||
27
test/features/821_personalization_read.feature
Normal file
27
test/features/821_personalization_read.feature
Normal 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
|
||||
56
test/features/830_key_registration.feature
Normal file
56
test/features/830_key_registration.feature
Normal 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
|
||||
31
test/features/850_compute_signature.feature
Normal file
31
test/features/850_compute_signature.feature
Normal 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
|
||||
16
test/features/851_decryption.feature
Normal file
16
test/features/851_decryption.feature
Normal 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
|
||||
|
||||
48
test/features/860_key_removal.feature
Normal file
48
test/features/860_key_removal.feature
Normal file
@@ -0,0 +1,48 @@
|
||||
@keygen
|
||||
Feature: key removal
|
||||
In order to use a token
|
||||
A token should have keys
|
||||
|
||||
Scenario: remove OPENPGP.1 key (sign)
|
||||
When removing a key OPENPGP.1
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove OPENPGP.2 key (decrypt)
|
||||
When removing a key OPENPGP.2
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove OPENPGP.3 key (authentication)
|
||||
When removing a key OPENPGP.3
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object Finger print sig
|
||||
Given cmd_put_data with c7 and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object Finger print dec
|
||||
Given cmd_put_data with c8 and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object Finger print aut
|
||||
Given cmd_put_data with c9 and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object keygeneration data/time sig
|
||||
Given cmd_put_data with ce and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object keygeneration data/time dec
|
||||
Given cmd_put_data with cf and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: remove data object keygeneration data/time aut
|
||||
Given cmd_put_data with d0 and ""
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW1
|
||||
Given cmd_verify with 1 and "123456"
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW2
|
||||
Given cmd_verify with 2 and "123456"
|
||||
Then it should get success
|
||||
37
test/features/862_keygen.feature
Normal file
37
test/features/862_keygen.feature
Normal 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
|
||||
Given a message "GnuPG assumes that PW1 keeps valid after keygen."
|
||||
And a public key from token for OPENPGP.1
|
||||
And let a token compute digital signature
|
||||
And verify signature
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW1 (1) after keygen
|
||||
Given cmd_verify with 1 and "123456"
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW1 (2) after keygen
|
||||
Given cmd_verify with 2 and "123456"
|
||||
Then it should get success
|
||||
36
test/features/870_compute_signature.feature
Normal file
36
test/features/870_compute_signature.feature
Normal 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)
|
||||
19
test/features/871_decryption.feature
Normal file
19
test/features/871_decryption.feature
Normal 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
|
||||
|
||||
43
test/features/970_key_removal.feature
Normal file
43
test/features/970_key_removal.feature
Normal 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
|
||||
27
test/features/980_personalization_reset.feature
Normal file
27
test/features/980_personalization_reset.feature
Normal 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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user