Compare commits
233 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57fdadf283 | ||
|
|
870de72ee2 | ||
|
|
fa667b04f7 | ||
|
|
2a72f3df08 | ||
|
|
db2527459f | ||
|
|
1ca3bbdaae | ||
|
|
98119dc991 | ||
|
|
03cca1e451 | ||
|
|
3f65bf73e8 | ||
|
|
07be37f45e | ||
|
|
dcef6e0ffa | ||
|
|
d31687ebd6 | ||
|
|
92443f8f07 | ||
|
|
4af98308e0 | ||
|
|
baec3a1c1e | ||
|
|
4f1325794d | ||
|
|
0acf6485ae | ||
|
|
4d15700580 | ||
|
|
8822fcae77 | ||
|
|
20a2f99691 | ||
|
|
acfccb729d | ||
|
|
5283506755 | ||
|
|
c688df7c2c | ||
|
|
594896ac57 | ||
|
|
dfe046e08d | ||
|
|
c66b01e74b | ||
|
|
21a46306ae | ||
|
|
e5158572ee | ||
|
|
2142d0aa35 | ||
|
|
dd47cf4312 | ||
|
|
ffbb754fc0 | ||
|
|
d85750d791 | ||
|
|
d20e9e9b1e | ||
|
|
bf30144144 | ||
|
|
934daf3585 | ||
|
|
22420ed1f4 | ||
|
|
e97e3b1810 | ||
|
|
49f2544918 | ||
|
|
d156fc6261 | ||
|
|
81d6945081 | ||
|
|
c3e9db14e8 | ||
|
|
9180c35420 | ||
|
|
cc0d59cfe6 | ||
|
|
9c1368fdd0 | ||
|
|
2dd5a76002 | ||
|
|
f68ff0bddc | ||
|
|
add3299306 | ||
|
|
e28ec2c4c4 | ||
|
|
1ba05a0f0f | ||
|
|
2d50795d0a | ||
|
|
fd493562c3 | ||
|
|
16c6af215a | ||
|
|
177ef67edf | ||
|
|
126283b1ac | ||
|
|
076d727061 | ||
|
|
41fa424450 | ||
|
|
940332c47f | ||
|
|
aedf8267ec | ||
|
|
e9d9de3ae2 | ||
|
|
fc109fd8af | ||
|
|
3d06051a32 | ||
|
|
b7368e41e9 | ||
|
|
e760d5b780 | ||
|
|
b57c33c204 | ||
|
|
ca3312eb25 | ||
|
|
6a1f50abda | ||
|
|
66f39c57cd | ||
|
|
4b5f93624e | ||
|
|
0ef687ea4c | ||
|
|
786b4adc42 | ||
|
|
385261c9a0 | ||
|
|
65689199e7 | ||
|
|
8d15086d06 | ||
|
|
c17fd5401b | ||
|
|
56cd4ae7b5 | ||
|
|
fc36773c6a | ||
|
|
7249775c17 | ||
|
|
980cff0a2f | ||
|
|
8f44f5d3c6 | ||
|
|
37a84ed218 | ||
|
|
6c72147248 | ||
|
|
3d37003d8c | ||
|
|
becf8fabc5 | ||
|
|
17492287f3 | ||
|
|
c800dee95e | ||
|
|
2c390dc763 | ||
|
|
5aee75fd4b | ||
|
|
69e8c0f334 | ||
|
|
317cc2036d | ||
|
|
312d15c3fa | ||
|
|
d356f1b1e0 | ||
|
|
9cb6591491 | ||
|
|
ebec8ee156 | ||
|
|
f810fb83d3 | ||
|
|
12079974fd | ||
|
|
ca79f5421f | ||
|
|
c438367d67 | ||
|
|
4c6511231c | ||
|
|
ba750d153d | ||
|
|
72647f01d0 | ||
|
|
c6e32a36fb | ||
|
|
c3a0eb1439 | ||
|
|
030a9c576d | ||
|
|
8a5e0eb783 | ||
|
|
bce53546e7 | ||
|
|
b2b19e1ad4 | ||
|
|
58fa773bb7 | ||
|
|
ea88c3da66 | ||
|
|
b905b4802f | ||
|
|
40f2c6c49e | ||
|
|
61a7f9602b | ||
|
|
5465fda927 | ||
|
|
f7c46a6c55 | ||
|
|
4550458806 | ||
|
|
93a2bac94b | ||
|
|
24adc09406 | ||
|
|
bf9fc628b3 | ||
|
|
d76534dd3a | ||
|
|
d9c5dcf206 | ||
|
|
26448d58ee | ||
|
|
9cfeb817bd | ||
|
|
b6534dceba | ||
|
|
b47bd693ba | ||
|
|
1a7d3a698f | ||
|
|
f7b03f7fb5 | ||
|
|
44971541fe | ||
|
|
53ed5e0a42 | ||
|
|
63eccda0a1 | ||
|
|
f430c90715 | ||
|
|
1f18ec1d63 | ||
|
|
ec7423f493 | ||
|
|
e50dda28d1 | ||
|
|
8ad176921f | ||
|
|
d71b116be8 | ||
|
|
d9d3f35ac3 | ||
|
|
7cc8d8930e | ||
|
|
6446a5bd89 | ||
|
|
8b0cb8be65 | ||
|
|
c73bb0548e | ||
|
|
40b1d453dc | ||
|
|
3b965fafc0 | ||
|
|
35edbdc731 | ||
|
|
d4c776e308 | ||
|
|
6c0c510347 | ||
|
|
704d8a5cf1 | ||
|
|
55781cb7bb | ||
|
|
de24655920 | ||
|
|
7bfe0f5427 | ||
|
|
ec058537ed | ||
|
|
abeb1015ec | ||
|
|
c5f20dc355 | ||
|
|
4ff0b3c5f8 | ||
|
|
4e517778d0 | ||
|
|
c81544fffd | ||
|
|
ad42010272 | ||
|
|
8ce91267be | ||
|
|
b5c2ace2ae | ||
|
|
4cbc661fb7 | ||
|
|
543f28574e | ||
|
|
fe94e1885b | ||
|
|
ce82b347f9 | ||
|
|
d54712c04c | ||
|
|
9c63c874d0 | ||
|
|
bb9b31166f | ||
|
|
e417846408 | ||
|
|
21a481060c | ||
|
|
d4c9d6653b | ||
|
|
f00306627b | ||
|
|
f4b36b7503 | ||
|
|
e85527d302 | ||
|
|
bd58997dc9 | ||
|
|
9d5834d47b | ||
|
|
36ecf67694 | ||
|
|
c9b1e511ba | ||
|
|
01b5aa5984 | ||
|
|
b735c02ec2 | ||
|
|
2ecb104ae4 | ||
|
|
6b4f3c9934 | ||
|
|
660aaeb04b | ||
|
|
1022534c02 | ||
|
|
46cc64cf03 | ||
|
|
effc65381a | ||
|
|
6cbf5a4822 | ||
|
|
8ff3865890 | ||
|
|
43009f39e8 | ||
|
|
56fb5002bf | ||
|
|
3bb5097031 | ||
|
|
8319f4a14b | ||
|
|
f7cf0a3461 | ||
|
|
5ac52d3f2f | ||
|
|
209d459d09 | ||
|
|
ad704edc4e | ||
|
|
97a1870e6e | ||
|
|
f72e132967 | ||
|
|
a22b695f96 | ||
|
|
0c901d8052 | ||
|
|
a1b8e7f40c | ||
|
|
dccda32b93 | ||
|
|
75049ce949 | ||
|
|
be80a3ef2f | ||
|
|
94424e85c3 | ||
|
|
43980d1c81 | ||
|
|
183cec8a04 | ||
|
|
7bae61f300 | ||
|
|
7e4ee2b361 | ||
|
|
30fde2a0f0 | ||
|
|
eee8d046a9 | ||
|
|
550010f25f | ||
|
|
3adbe30c4d | ||
|
|
d9ec8778fc | ||
|
|
eff0c7077d | ||
|
|
289d3db8c4 | ||
|
|
7c5eb7efd2 | ||
|
|
6f1fbdd82d | ||
|
|
cbedf98a52 | ||
|
|
15689b5b86 | ||
|
|
8170b60ee2 | ||
|
|
ca7f4c8758 | ||
|
|
0b4099d6d1 | ||
|
|
65fee7eb2a | ||
|
|
0c229f5712 | ||
|
|
5948f6ec50 | ||
|
|
7b1ea00307 | ||
|
|
277be86958 | ||
|
|
a6b90ad648 | ||
|
|
547e263d6b | ||
|
|
7004453669 | ||
|
|
81b18f2db4 | ||
|
|
86715dd4fe | ||
|
|
62f27f319c | ||
|
|
7345f3c241 | ||
|
|
f4b9073b11 | ||
|
|
6678ac28c2 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,17 +1,20 @@
|
||||
*.lst
|
||||
*.o
|
||||
*.pyc
|
||||
regnual/regnual-no-vidpid.elf
|
||||
src/.dep
|
||||
src/config.mk
|
||||
src/config.h
|
||||
src/gnuk.ld
|
||||
src/stdaln-sys.ld
|
||||
src/board.h
|
||||
src/build/*
|
||||
src/*.inc
|
||||
src/put-vid-pid-ver.sh
|
||||
regnual/regnual.bin
|
||||
regnual/regnual.hex
|
||||
regnual/regnual.elf
|
||||
doc/_build
|
||||
tests/.cache
|
||||
tests/__pycache__
|
||||
emulation/gnuk_emulation
|
||||
tests/.pytest_cache
|
||||
|
||||
46
AUTHORS
46
AUTHORS
@@ -1,9 +1,26 @@
|
||||
Aurelien Jarno:
|
||||
Modified:
|
||||
src/Makefile
|
||||
src/configure
|
||||
src/main.c
|
||||
src/stack-def.h
|
||||
|
||||
Anthony Romano:
|
||||
Modified:
|
||||
src/call-rsa.c
|
||||
src/main.c
|
||||
src/mod.c
|
||||
|
||||
Bertrand Jacquin
|
||||
Modified:
|
||||
tool/add_openpgp_authkey_from_gpgssh.py
|
||||
tool/calc_precompute_table_ecc.py
|
||||
tool/dfuse.py
|
||||
tool/dump_mem.py
|
||||
tool/get_raw_public_key.py
|
||||
tool/pageant_proxy_to_gpg.py
|
||||
tool/pinpadtest.py
|
||||
|
||||
Jeremy Drake:
|
||||
Modified:
|
||||
regnual/regnual.c
|
||||
@@ -58,3 +75,32 @@ NIIBE Yutaka:
|
||||
src/usb_lld.h
|
||||
*
|
||||
and others.
|
||||
|
||||
Peter Lebbing:
|
||||
Modified:
|
||||
src/config.h.in
|
||||
src/configure
|
||||
src/main.c
|
||||
src/Makefile
|
||||
Wrote:
|
||||
src/stdaln-sys.ld.in
|
||||
|
||||
Vincent Pelletier:
|
||||
Modified:
|
||||
test/features/202_setup_passphrase.feature
|
||||
test/rsa_keys.py
|
||||
tests/card_const.py
|
||||
tests/card_reader.py
|
||||
tests/rsa_keys.py
|
||||
tool/gnuk_token.py
|
||||
Wrote:
|
||||
tests/card_test_ansix9p256r1.py
|
||||
tests/card_test_ansix9p384r1.py
|
||||
tests/card_test_ansix9p512r1.py
|
||||
tests/card_test_brainpoolp256r1.py
|
||||
tests/card_test_brainpoolp384r1.py
|
||||
tests/card_test_brainpoolp512r1.py
|
||||
tests/card_test_ed25519.py
|
||||
tests/card_test_x25519.py
|
||||
tests/func_pso_auth.py
|
||||
tests/test_006_pso.py
|
||||
|
||||
886
ChangeLog
886
ChangeLog
@@ -1,3 +1,889 @@
|
||||
2021-10-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.19.
|
||||
* chopstx: Update to 1.20.
|
||||
|
||||
2021-10-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure (kdf_do): It can be overridden, now.
|
||||
|
||||
2021-07-01 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure (CONFIG): Add KDF configuration.
|
||||
|
||||
2021-06-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/stlinkv2.py: Switch to Python3.
|
||||
|
||||
* tool/upgrade_by_passwd.py: Fix option handling.
|
||||
|
||||
2021-04-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_algorithm_attr): Fix writing algorithm
|
||||
attribute, which may cause GC. Note that flash_enum_write needs
|
||||
to call flash_enum_clear beforehand.
|
||||
|
||||
2021-04-28 Bertrand Jacquin <bertrand@jacquin.bzh>
|
||||
|
||||
* regnual/regnual.c: Include <string.h>.
|
||||
|
||||
2021-04-02 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.18.
|
||||
|
||||
2021-04-01 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/upgrade_by_passwd.py: Check configure target and
|
||||
the config in the device are same target.
|
||||
|
||||
2021-03-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests/openpgp_card.py (is_emulated_gnuk): Add.
|
||||
* tests/skip_if_emulation.py: New.
|
||||
* tests/skip_if_gnuk.py: New.
|
||||
* tests/test_001_personalize_card.py: Skip if emulation.
|
||||
* tests/test_002_personalize_reset.py: Skip if emulation.
|
||||
* tests/test_003_remove_keys.py: Skip if emulation.
|
||||
* tests/test_004_reset_pw3.py: Skip if emulation.
|
||||
* tests/test_005_personalize_admin_less.py: Skip if emulation.
|
||||
* tests/test_006_pso.py: Skip if Gnuk.
|
||||
* tests/test_009_keygen.py: Skip if emulation.
|
||||
* tests/test_021_personalize_admin_less.py: Rewrite.
|
||||
|
||||
2021-03-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pgp_gakp): Fix patch mistake.
|
||||
|
||||
2021-03-01 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
* tests/card_const.py: Add attributes for more algos.
|
||||
* tests/card_test_ansix9p256r1.py: New.
|
||||
* tests/card_test_ansix9p384r1.py: New.
|
||||
* tests/card_test_ansix9p512r1.py: New.
|
||||
* tests/card_test_brainpoolp256r1.py: New.
|
||||
* tests/card_test_brainpoolp384r1.py: New.
|
||||
* tests/card_test_brainpoolp512r1.py: New.
|
||||
* tests/card_test_ed25519.py: New.
|
||||
* tests/card_test_x25519.py: New.
|
||||
* tests/func_pso_auth.py: New.
|
||||
* tests/test_006_pso.py: New.
|
||||
|
||||
2021-02-25 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.17.
|
||||
|
||||
2021-02-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/config.h.in (@KDF_DO_REQUIRED_DEFINE@): New.
|
||||
|
||||
* src/configure (KDF_DO_REQUIRED_DEFINE): New for GNU/Linux.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_kdf_check): When LEN==0, check if
|
||||
KDO data object is available.
|
||||
[KDF_DO_REQUIRED] (proc_key_import): Refuse the key import when
|
||||
KDF data object is not available.
|
||||
|
||||
* src/openpgp.c [KDF_DO_REQUIRED] (cmd_pgp_gakp): Refuse key
|
||||
generation when KDF data object is not available.
|
||||
|
||||
2021-02-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/gnuk-emulation-setup: Remove.
|
||||
|
||||
* tool/upgrade_by_passwd.py (main): Use tobytes.
|
||||
* tool/gnuk_get_random.py: Likewise.
|
||||
* tool/gnuk_remove_keys_libusb.py (main): Likewise.
|
||||
Switch to Python3.
|
||||
* tool/gnuk_put_binary_libusb.py (main): Use tobytes.
|
||||
Switch to Python3.
|
||||
* tool/gnuk_upgrade.py (main): Use tobytes.
|
||||
Switch to Python3.
|
||||
|
||||
* chopstx: Update to 1.19.
|
||||
|
||||
2021-02-18 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
* test/features/202_setup_passphrase.feature: Fix.
|
||||
* test/rsa_keys.py: Fix escape.
|
||||
* tests/card_reader.py: Extend the timeout.
|
||||
Handle no card.
|
||||
* tests/rsa_keys.py: Fix escape.
|
||||
* tool/gnuk_token.py: Avoid hard-coding the endpoints.
|
||||
Longer timeout.
|
||||
|
||||
2021-02-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure [GNU_LINUX_EMULATION] (def_mhz): Define.
|
||||
(output_vendor_product_serial_strings): Output ARCH.
|
||||
|
||||
* GNUK_USB_DEVICE_ID: Use "Gnuk Token" for emulation, too.
|
||||
|
||||
* src/main.c [GNU_LINUX_EMULATION] (main): Add initialization of
|
||||
the .gnuk-flash-image file.
|
||||
(gnuk_sbrk): Rename from sbrk.
|
||||
|
||||
2020-09-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.16.
|
||||
|
||||
2020-09-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/modp256k1.c (modp256k1_add, modp256k1_sub): Use memcpy with
|
||||
dummy memory area.
|
||||
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
|
||||
(modp256r1_reduce): Likewise.
|
||||
|
||||
2020-09-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/modp256k1.c (modp256k1_add, modp256k1_reduce): Avoid
|
||||
optimization to remove call of memmove.
|
||||
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
|
||||
(modp256r1_reduce): Likewise.
|
||||
|
||||
2020-09-07 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (gpg_get_firmware_update_key): Use an array.
|
||||
|
||||
* src/modp256k1.c (modp256k1_add, modp256k1_sub): Use memmove.
|
||||
* src/modp256r1.c (modp256r1_add, modp256r1_sub)
|
||||
(modp256r1_reduce): Likewise.
|
||||
|
||||
2020-09-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (GPG_DO_ALG_INFO): New.
|
||||
(do_fp_all, do_cafp_all, do_kgtime_all, do_openpgpcard_aid)
|
||||
(do_ds_count): Return nothing.
|
||||
(copy_do): Change the API for DO_PROC_READ.
|
||||
(do_alg_info): New for GPG_DO_ALG_INFO.
|
||||
(gpg_do_table): Add an entry for GPG_DO_ALG_INFO.
|
||||
|
||||
2020-09-03 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_internal_authenticate): Remove checking
|
||||
against EDDSA_HASH_LEN_MAX.
|
||||
(cmd_pso): Likewise.
|
||||
|
||||
2020-08-28 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_reset_user_password): Add passphrase length
|
||||
check.
|
||||
|
||||
2020-08-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ac.c (verify_user_0): Fix for a use case of having
|
||||
signing key only.
|
||||
(verify_admin_00): Clean up.
|
||||
|
||||
* tests/test_000_empty_card.py (test_name_lang_sex): Support
|
||||
OpenPGP card version 3.3.
|
||||
|
||||
2020-01-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.15.
|
||||
|
||||
2020-01-11 Bertrand Jacquin <bertrand@jacquin.bzh>
|
||||
|
||||
* tool/add_openpgp_authkey_from_gpgssh.py: Switch to Python3.
|
||||
* tool/calc_precompute_table_ecc.py: Likewise.
|
||||
* tool/dfuse.py: Likewise.
|
||||
* tool/dump_mem.py: Likewise.
|
||||
* tool/get_raw_public_key.py: Likewise.
|
||||
* tool/pageant_proxy_to_gpg.py: Likewise.
|
||||
|
||||
2019-12-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Update to 1.18.
|
||||
|
||||
2019-06-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/bn.c (bn256_random): More portable.
|
||||
|
||||
2019-04-03 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests: Factor out tests into classes.
|
||||
|
||||
2019-03-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.14.
|
||||
|
||||
* chopstx: Update to 1.14.
|
||||
|
||||
* tool/gnuk_token.py: Add 1209:2440.
|
||||
|
||||
2019-02-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_thread): Clean up the ack button state
|
||||
at reset (by SET_INTERFACE).
|
||||
|
||||
* tool/gnuk_token.py (gnuk_token.__init__): Add back
|
||||
setAltInterface to issue SET_INTERFACE control transfer.
|
||||
|
||||
2019-02-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/gnuk_get_random.py: New.
|
||||
|
||||
* src/openpgp.c (cmd_external_authenticate): move
|
||||
ACKBTN_SUPPORT to...
|
||||
(cmd_get_challenge): ... here.
|
||||
|
||||
* src/gnuk.h (EV_*): Change the values.
|
||||
|
||||
* src/usb-ccid.c (GPG_ACK_TIMEOUT): New.
|
||||
(ccid_thread): Implement timout for the user interaction.
|
||||
|
||||
2019-02-21 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* GNUK_USB_DEVICE_ID: Add 1209:2440.
|
||||
|
||||
2018-12-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.13.
|
||||
|
||||
2018-12-22 Peter Lebbing <peter@digitalbrains.com>
|
||||
|
||||
* src/main.c (device_initialize_once): Fill the stack address and
|
||||
reset vector of Gnuk application (was the one of old SYS).
|
||||
Reset the board after updating the first five pages of flash.
|
||||
|
||||
2018-12-21 Peter Lebbing <peter@digitalbrains.com>
|
||||
|
||||
* src/main.c [DFU_SUPPORT] (flash_write_any): New.
|
||||
(device_initialize_once): Overwrite DFU bootloader by SYS.
|
||||
(main): Use SYS at ORIGIN_REAL.
|
||||
|
||||
* src/stdaln-sys.ld.in: New.
|
||||
|
||||
* src/Makefile [USE_DFU] (OBJS_ADD): Add standalone SYS object.
|
||||
Add rules for stdaln-sys-bin.o and src/stdaln-sys.ld.
|
||||
|
||||
* src/configure: Generate stdaln-sys.ld.
|
||||
[MAPLE_MINI]: Tweak ORIGIN and FLASH_SIZE.
|
||||
(ORIGIN_DEFINE, ORIGIN_REAL_DEFINE): New macros.
|
||||
(USE_DFU): New make variable.
|
||||
|
||||
* src/config.h.in (ORIGIN_DEFINE, ORIGIN_REAL_DEFINE): New.
|
||||
|
||||
2018-12-20 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Update to 1.13.
|
||||
|
||||
2018-12-07 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (EV_EXEC_ACK_REQUIRED): Have precedence
|
||||
than EV_EXEC_FINISHED.
|
||||
|
||||
2018-12-06 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_thread): Priority of handling
|
||||
EV_TX_FINISHED is most important. Don't handle
|
||||
Ack button event when c->tx_busy = 1.
|
||||
|
||||
2018-12-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_external_authenticate): Support
|
||||
ACK button for firmware update.
|
||||
|
||||
2018-12-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_data_copy): Fix for NR_DO_UIF_SIG.
|
||||
|
||||
2018-11-25 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.12.
|
||||
|
||||
2018-11-21 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_thread): Fix a race condition sending
|
||||
result APDU by ack button, time out, sending time extension block
|
||||
again while tx_busy=1.
|
||||
|
||||
2018-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c (device_initialize_once): Depends on MHZ to
|
||||
distinguish GD32F103.
|
||||
* src/openpgp-do.c (do_openpgpcard_aid): Ditto.
|
||||
|
||||
2018-11-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.11.
|
||||
|
||||
* chopstx: Update to 1.12.
|
||||
* src/configure (ackbtn_support): Always yes.
|
||||
* src/usb-ccid.c: Fix comma separator.
|
||||
|
||||
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/kdf_calc.py (kdf_calc): Use libgcrypt.so.20.
|
||||
|
||||
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso, cmd_internal_authenticate): Use
|
||||
ccid_comm.
|
||||
|
||||
* src/usb-ccid.c (struct ccid): New field tx_busy.
|
||||
(ccid_error, ccid_power_on, ccid_send_status, ccid_power_off)
|
||||
(ccid_send_data_block_internal, ccid_send_data_block_0x9000)
|
||||
(ccid_send_data_block_gr, ccid_send_params): Set c->tx_busy.
|
||||
(ccid_state_p): Remove.
|
||||
(ccid_get_ccid_state): New.
|
||||
(ccid_thread): Only handle EV_TX_FINISHED event when c->tx_busy.
|
||||
|
||||
* src/usb_ctrl.c (usb_setup, usb_ctrl_write_finish): Use
|
||||
ccid_get_ccid_state.
|
||||
* src/main.c (display_status_code): Likewise.
|
||||
|
||||
2018-11-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_handle_data): Set c->state for pinpad input.
|
||||
(ccid_send_data_block_internal): Fix the case of len == 0.
|
||||
|
||||
* src/main.c (display_status_code): There is
|
||||
no case where ccid_state == CCID_STATE_RECEIVE.
|
||||
* src/gnuk.h (CCID_STATE_RECEIVE): Remove.
|
||||
(CCID_STATE_SEND): Remove.
|
||||
|
||||
2018-10-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_thread): Notify host about ack button.
|
||||
|
||||
2018-10-02 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/stack-def.h (SIZE_0): Increase.
|
||||
|
||||
* chopstx: Update to 1.11.
|
||||
|
||||
2018-10-01 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (EV_EXEC_ACK_REQUIRED): New.
|
||||
(EV_EXEC_FINISHED_ACK): Remove.
|
||||
(CCID_STATE_CONFIRM_ACK): Remove.
|
||||
(CCID_STATE_ACK_REQUIRED_0, CCID_STATE_ACK_REQUIRED_1): New.
|
||||
* src/openpgp.c (cmd_pso): Send EV_EXEC_ACK_REQUIRED, if needed.
|
||||
(cmd_internal_authenticate): Likewise.
|
||||
(process_command_apdu): No return value.
|
||||
(openpgp_card_thread): Always send EV_EXEC_FINISHED.
|
||||
* src/usb-ccid.c (ccid_send_data_block_time_extension): Follow the
|
||||
change of state.
|
||||
(ccid_handle_data, ccid_handle_timeout): Likewise.
|
||||
(ccid_thread): Handle EV_EXEC_ACK_REQUIRED.
|
||||
Change for LED blink.
|
||||
* src/main.c (main): LED blink during waiting ACK.
|
||||
|
||||
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (NR_DO_UIF_SIG, NR_DO_UIF_DEC, NR_DO_UIF_AUT): New.
|
||||
* src/openpgp-do.c (rw_uif) [ACKBTN_SUPPORT]: New.
|
||||
(GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
|
||||
(feature_mngmnt) [ACKBTN_SUPPORT]: New.
|
||||
(cmp_app_data, cmp_discretionary): Add ACKBTN_SUPPORT.
|
||||
(gpg_do_table): Add for GPG_DO_UIF_SIG, GPG_DO_UIF_DEC,
|
||||
GPG_DO_UIF_AUT, and GPG_DO_FEATURE_MNGMNT.
|
||||
(gpg_do_get_uif) [ACKBTN_SUPPORT]: New.
|
||||
(gpg_data_scan): Handle uif_flags.
|
||||
* src/openpgp.c (process_command_apdu) [ACKBTN_SUPPORT]: Add user
|
||||
interaction handling.
|
||||
|
||||
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (LED_WAIT_FOR_BUTTON): New.
|
||||
* src/main.c (main): Blink rapidly when asking ACK.
|
||||
* src/usb-ccid.c (ccid_thread): Use LED_WAIT_FOR_BUTTON.
|
||||
|
||||
2018-09-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/config.h.in: Add @ACKBTN_DEFINE@.
|
||||
* src/configure: Add ACKBTN_SUPPORT.
|
||||
* src/gnuk.h (EV_EXEC_FINISHED_ACK): New.
|
||||
(CCID_STATE_CONFIRM_ACK): New.
|
||||
* src/openpgp.c (process_command_apdu): Change for cmd_pso, and
|
||||
cmd_internal_authenticate.
|
||||
* src/usb-ccid.c (ccid_send_data_block_time_extension): Report
|
||||
time extension differently when waiting ack button.
|
||||
(ccid_handle_data): Support case of CCID_STATE_CONFIRM_ACK.
|
||||
(ccid_handle_timeout): Likewise.
|
||||
(ack_intr) [ACKBTN_SUPPORT]: New.
|
||||
(ccid_thread) [ACKBTN_SUPPORT]: Add ack button handling.
|
||||
|
||||
2018-09-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Update.
|
||||
* src/usb-ccid.c (usb_event_handle): Fix for chopstx_intr_done.
|
||||
* src/pin-cir.c (tim_main, ext_main): Likewise.
|
||||
|
||||
* src/configure (FST_01SZ): Set MHZ=96.
|
||||
|
||||
2018-07-04 Szczepan Zalega <szczepan@nitrokey.com>
|
||||
|
||||
* tool/upgrade_by_passwd.py: Catch exception, when no KDF data is
|
||||
found.
|
||||
Output 'second' for 1 second.
|
||||
|
||||
2018-05-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.10.
|
||||
|
||||
* src/Makefile (build/gnuk.elf): New target.
|
||||
(build/gnuk-vidpid.elf): Remove.
|
||||
|
||||
* chopstx: Update to 1.9.
|
||||
|
||||
2018-04-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_ctrl.c (usb_device_reset): Don't stop the endpoints.
|
||||
|
||||
* src/configure (MHZ, def_mhz): New.
|
||||
|
||||
2018-04-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.9.
|
||||
|
||||
* tests: Add test cases for admin-less mode.
|
||||
|
||||
* src/openpgp.c (cmd_change_password): Care admin-less mode.
|
||||
|
||||
2018-04-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests: Add more tests, key generation and KDF support.
|
||||
|
||||
* src/openpgp.c (cmd_reset_user_password): Check length of
|
||||
new passphrase.
|
||||
|
||||
* src/openpgp-do.c (proc_resetting_code): Support removal.
|
||||
(gpg_do_kdf_check): Fix for the case of resetting PW3.
|
||||
|
||||
* tests/test_004_reset_pw3.py: New.
|
||||
|
||||
2018-04-03 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_kdf): Clear all auth state.
|
||||
|
||||
* tool/upgrade_by_passwd.py (main): Fix for byte compare.
|
||||
* tool/gnuk_remove_keys_libusb.py (main): Likewise.
|
||||
|
||||
2018-04-02 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/gnuk_token.py (parse_kdf_data): New.
|
||||
* tool/kdf_calc.py: New.
|
||||
|
||||
* tool/gnuk_remove_keys_libusb.py (main): Support KDF auth.
|
||||
* tool/upgrade_by_passwd.py (main): Likewise.
|
||||
|
||||
2018-03-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_kdf): Support single-salt KDF.
|
||||
(gpg_do_get_initial_pw_setting): Likewise.
|
||||
(gpg_do_kdf_check): Likewise.
|
||||
|
||||
2018-03-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_kdf): Do format validation earlier.
|
||||
|
||||
2018-03-13 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/flash.c [FLASH_UPGRADE_SUPPORT] (flash_terminate): Erase
|
||||
the page for upgrade public keys.
|
||||
|
||||
2018-02-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_kdf): Return 0 when NULL.
|
||||
|
||||
2018-01-23 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.8.
|
||||
|
||||
* src/Makefile (build/gnuk-vidpid.elf): Supply FILE here.
|
||||
* src/configure (output_vendor_product_serial_strings): For
|
||||
generating put-vid-pid-ver.sh, don't set FILE.
|
||||
|
||||
* regnual/regnual.c (regnual_device_desc): Make this array as a
|
||||
template.
|
||||
* regnual/Makefile (regnual.elf): Substitute VID:PID.
|
||||
|
||||
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (USER_PASSWD_MINLEN): New.
|
||||
(cmd_change_password): Check passphrase length.
|
||||
|
||||
2018-01-22 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_change_password): Remove access to private
|
||||
key with BY_ADMIN when it's becoming admin-less mode.
|
||||
|
||||
2018-01-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/binary-edit.sh: Copied from NeuG 1.0.8. Exclude FILE.
|
||||
* src/configure (output_vid_pid_version): Generate a shell script.
|
||||
* src/Makefile (build/gnuk-vidpid.elf): New target.
|
||||
* src/usb_desc.c (device_desc): Make this array as a template.
|
||||
|
||||
* chopstx: Update to 1.8.
|
||||
|
||||
2018-01-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/neug.c: Update from NeuG.
|
||||
|
||||
2018-01-09 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests/card_reader.py (CardReader.ccid_power_on): Fix for
|
||||
other card readers for Gemalto's.
|
||||
|
||||
2017-12-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Update to 1.7.
|
||||
|
||||
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_change_password): Bug fix for admin-less
|
||||
mode.
|
||||
|
||||
2017-11-26 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.7.
|
||||
|
||||
2017-11-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* regnual/regnual.c (calc_crc32): Enable CRC module fix.
|
||||
|
||||
* chopstx: Update to 1.6.
|
||||
|
||||
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/stack-def.h (SIZE_0): Decrease.
|
||||
|
||||
* src/main.c (emit_led, display_status_code, main): Use
|
||||
chopstx_poll instead of eventflag_wait_timeout.
|
||||
|
||||
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/stack-def.h (SIZE_0): Increase.
|
||||
|
||||
* src/main.c (emit_led, display_status_code, main): Use
|
||||
eventflag_wait_timeout instead of chopstx_usec_wait.
|
||||
|
||||
2017-11-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* regnual/regnual.c (calc_crc32): Enable CRC module.
|
||||
|
||||
* src/neug.c (crc32_rv_stop): New.
|
||||
(neug_fini): Call crc32_rv_stop.
|
||||
|
||||
* src/main.c (main): Call chopstx_conf_idle.
|
||||
|
||||
* src/usb-ccid.c (usb_event_handle): Use 2 for call of
|
||||
chopstx_conf_idle on suspend. Call random_fini on suspend
|
||||
to stop ADC module. Call random_init on wakeup.
|
||||
Sleep a bit to switch main thread.
|
||||
|
||||
2017-11-16 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (LED_OFF): New.
|
||||
|
||||
* src/usb-ccid.c (usb_event_handle): LED off on sleep.
|
||||
(ccid_thread): Use constant pointer for chopstx_poll.
|
||||
(poll_event_intr): Remove.
|
||||
|
||||
2017-11-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (usb_event_handle): Allow sleep on suspend.
|
||||
|
||||
* src/usb_ctrl.c (usb_device_reset): Fix device state.
|
||||
|
||||
2017-11-14 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_usb_reset): Remove
|
||||
(usb_event_handle): Return value change to notify
|
||||
caller about needs for going out of the loop.
|
||||
Support USB suspend/resume.
|
||||
(ccid_thread): Supporting USB suspend, sleep forever with
|
||||
timeout_p = NULL.
|
||||
|
||||
* src/main.c (main): Add USB_DEVICE_STATE_ prefix.
|
||||
* src/usb_ctrl.c: Likewise.
|
||||
(usb_device_reset): Don't call ccid_usb_reset.
|
||||
(usb_set_configuration, usb_set_interface): Likewise.
|
||||
|
||||
* src/usb_desc.c (device_desc): bcdUSB = 2.0, supporting
|
||||
suspend/resume.
|
||||
|
||||
2017-11-13 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_ctrl.c: Use new const USB_DEVICE_STATE_*
|
||||
* src/main.c (main): Likewise.
|
||||
* src/usb-ccid.c: Likewise.
|
||||
(INTR_REQ_USB): Remove. Use the definition
|
||||
in usb-lld.h.
|
||||
|
||||
2017-11-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_do_kdf_check): New.
|
||||
(proc_resetting_code): Use gpg_do_kdf_check.
|
||||
* src/openpgp.c (cmd_verify, cmd_change_password)
|
||||
(cmd_reset_user_password): Likewise.
|
||||
|
||||
2017-11-07 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (proc_resetting_code): Error when
|
||||
it's not pass-hash.
|
||||
|
||||
* src/openpgp.c (cmd_verify, cmd_change_password)
|
||||
(cmd_reset_user_password): Avoid authentication error
|
||||
by old GnuPG which doesn't support KDF.
|
||||
|
||||
2017-11-06 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests/test_empty_card.py (test_extended_capabilities): Support
|
||||
KDF-DO.
|
||||
* test/features/802_get_data_static.feature: Likewise.
|
||||
* test/features/402_get_data_static.feature: Likewise.
|
||||
* test/features/002_get_data_static.feature: Likewise.
|
||||
|
||||
2017-11-02 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (rw_kdf): Only writable when no keys.
|
||||
(gpg_do_get_initial_pw_setting): New.
|
||||
(gpg_do_write_prvkey): Use gpg_do_get_initial_pw_setting.
|
||||
(gpg_do_keygen): Likewise.
|
||||
(extended_capabilities): Enable KDF-DO available bit.
|
||||
|
||||
* src/openpgp.c (cmd_change_password): Use
|
||||
gpg_do_get_initial_pw_setting.
|
||||
* src/ac.c (verify_user_0, verify_admin_0): Likewise.
|
||||
|
||||
2017-11-01 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (GPG_DO_KDF): New.
|
||||
(GPG_DO_FEATURE_MNGMNT): New.
|
||||
(do_tag_to_nr): Support GPG_DO_KDF.
|
||||
(GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT): New.
|
||||
(rw_kdf): New.
|
||||
(gpg_do_table): Add an entry for GPG_DO_KDF.
|
||||
|
||||
* src/gnuk.h (NR_DO_KDF): New.
|
||||
|
||||
2017-10-31 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_do_keygen): Bug fix for memory alignment.
|
||||
|
||||
2017-10-24 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tests/card_reader.py (CardReader.ccid_power_on): Setting
|
||||
PPS only for Gemalto GemPC reader.
|
||||
|
||||
2017-10-18 Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
* src/gnuk.ld.in: Fix keystore_pool size.
|
||||
|
||||
2017-10-12 Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
* polarssl/include/polarssl/bn_mul.h (MULADDC_HUIT_DEAD): Rename
|
||||
from MULADDC_HUIT.
|
||||
[__ARM_FEATURE_DSP] (MULADDC_1024_CORE, MULADDC_1024_LOOP)
|
||||
(MULADDC_INIT, MULADDC_CORE, MULADDC_HUIT, MULADDC_STOP): New.
|
||||
|
||||
* polarssl/library/bignum.c (mpi_montsqr): Check on
|
||||
POLARSSL_HAVE_ASM and __arm__.
|
||||
[__ARM_FEATURE_DSP] (mpi_montsqr): New.
|
||||
(MAX_WSIZE): New.
|
||||
(mpi_exp_mod): Use MAX_WSIZE.
|
||||
|
||||
* src/Makefile (DEFS): Remove BIGNUM_C_IMPLEMENTATION.
|
||||
|
||||
* src/main.c (HEAP_SIZE): Rename from MEMORY_SIZE.
|
||||
(HEAP_END, HEAP_ALIGNMENT, HEAP_ALIGN): Likewise.
|
||||
|
||||
* src/stack-def.h (SIZE_3): Depend on MEMORY_SIZE.
|
||||
* src/configure: Emit DEFS with MEMORY_SIZE.
|
||||
|
||||
2017-10-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.6.
|
||||
|
||||
* regnual/Makefile (LDSCRIPT): Move after include.
|
||||
* regnual/types.h: Add uintptr_t.
|
||||
|
||||
* test/features/002_get_data_static.feature (data object AID): Fix
|
||||
for any binary value.
|
||||
* 402_get_data_static.feature: Likewise.
|
||||
* 802_get_data_static.feature: Likewise.
|
||||
|
||||
2017-10-10 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c (main): Support --debug option.
|
||||
* chopstx: Update to 1.5.
|
||||
|
||||
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure (flash_override): Fix suggested by Jeremy Drake.
|
||||
(help): STM8S_DISCOVERY is supported again.
|
||||
|
||||
2017-10-06 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.ld.in (.stacks): Specify NOLOAD type.
|
||||
|
||||
* src/configure: Allow not specifying VIDPID.
|
||||
|
||||
* src/main.c [GNU_LINUX_EMULATION] (main): Handle "--vidpid"
|
||||
option to assign vendor ID and product ID of USB.
|
||||
|
||||
* src/usb_desc.c [GNU_LINUX_EMULATION] (device_desc): Export.
|
||||
|
||||
* GNUK_USB_DEVICE_ID (0000:0000): New.
|
||||
|
||||
2017-10-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/stack-def.h (SIZE_1, SIZE_3): Tweak the size.
|
||||
|
||||
* src/call-rsa.c (rsa_genkey): Single step.
|
||||
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in single
|
||||
step, using APDU buffer.
|
||||
* src/openpgp.c (cmd_pgp_gakp): Supply the APDU as a buffer.
|
||||
|
||||
* src/Makefile (install): New target.
|
||||
|
||||
* src/configure (prefix. exec_prefix, libexecdir): Add.
|
||||
|
||||
* src/main.c [GNU_LINUX_EMULATION] (main): Option handling.
|
||||
|
||||
* tool/gnuk-emulation-setup: New.
|
||||
|
||||
* polarssl/library/bignum.c (M_LIMBS, limbs_M, MAX_A_LIMBS)
|
||||
(limbs_MAX_A, mpi_gen_prime): Fix for 64-bit machine.
|
||||
|
||||
2017-10-04 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure (output_vendor_product_serial_strings): Support
|
||||
GNU/Linux emulation.
|
||||
|
||||
* polarssl/library/bignum.c (mpi_div_mpi): Fix for 64-bit machine.
|
||||
|
||||
* src/main.c (gnuk_malloc, gnuk_free): Fix for 64-bit machine.
|
||||
|
||||
* src/stack-def.h (SIZE_3): Tweak the size.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in two
|
||||
steps.
|
||||
|
||||
* src/call-rsa.c (rsa_genkey_start, rsa_genkey_finish): New.
|
||||
(rsa_genkey): Remove.
|
||||
|
||||
2017-10-03 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/call-ec.c (ecc_compute_public): No use of malloc.
|
||||
* src/call-rsa.c (modulus_calc, rsa_genkey): Likewise.
|
||||
* src/ecc-edwards.c (eddsa_compute_public_25519): Likewise.
|
||||
* src/ecc-mont.c (ecdh_compute_public_25519): Likewise.
|
||||
* src/openpgp-do.c (gpg_do_write_prvkey, gpg_do_chks_prvkey)
|
||||
(proc_key_import, gpg_do_keygen): Likewise.
|
||||
|
||||
* polarssl/library/rsa.c: Don't include stdlib.h.
|
||||
* src/gnuk-malloc.h: Rename from stdlib.h.
|
||||
* polarssl/library/bignum.c: Include gnuk-malloc.h.
|
||||
|
||||
* src/Makefile (build/flash.data): Generate.
|
||||
|
||||
* src/main.c (flash_addr_key_storage_start)
|
||||
(flash_addr_data_storage_start): New.
|
||||
(main): Determine flash address.
|
||||
|
||||
* src/flash.c (FLASH_ADDR_KEY_STORAGE_START)
|
||||
(FLASH_ADDR_DATA_STORAGE_START): New.
|
||||
(flash_do_storage_init, flash_terminate, flash_activate)
|
||||
(flash_key_storage_init, flash_copying_gc, flash_do_release)
|
||||
(flash_key_getpage): Use new macros.
|
||||
|
||||
2017-10-02 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c (device_initialize_once): Not for GNU/Linux.
|
||||
|
||||
* src/openpgp.c, src/flash.c: Distinguish FLASH_UPGRADE_SUPPORT.
|
||||
|
||||
* src/main.c [GNU_LINUX_EMULATION]: Use emulated_main.
|
||||
(MEMORY_SIZE, MEMORY_END): Fix for GNU/Linux.
|
||||
|
||||
* src/usb-ccid.c (INTR_REQ_USB): Fix for GNU/Linux.
|
||||
|
||||
* polarssl/library/bignum.c (mpi_montsqr): Easy C implementation.
|
||||
|
||||
2017-09-30 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/flash.c (flash_terminate, flash_activate)
|
||||
(flash_copying_gc, flash_do_write_internal, flash_do_release)
|
||||
(flash_key_write, flash_check_all_other_keys_released)
|
||||
(flash_key_fill_zero_as_released, flash_key_release)
|
||||
(flash_key_release_page, flash_clear_halfword)
|
||||
(flash_put_data_internal, flash_put_data, flash_bool_clear)
|
||||
(flash_bool_write_internal, flash_bool_write)
|
||||
(flash_enum_write_internal, flash_enum_write)
|
||||
(flash_cnt123_write_internal, flash_cnt123_increment)
|
||||
(flash_cnt123_clear, flash_erase_binary, flash_write_binary): Fix
|
||||
for GNU/Linux.
|
||||
|
||||
* src/usb-ccid.c (ccid_tx_done): Rename from EP1_IN_Callback.
|
||||
(ccid_rx_ready): Rename from EP1_OUT_Callback.
|
||||
|
||||
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (epo_init, epi_init, ccid_thread): Simplify.
|
||||
(EP1_IN_Callback, ccid_prepare_receive, EP1_OUT_Callback)
|
||||
(usb_rx_ready, ccid_error, ccid_power_on, ccid_send_status)
|
||||
(ccid_send_data_block_internal, ccid_send_data_block_0x9000)
|
||||
(ccid_send_data_block_gr, ccid_send_params)
|
||||
(ccid_notify_slot_change, _write) [GNU_LINUX_EMULATION]: Use
|
||||
different usb driver API.
|
||||
|
||||
* src/usb_ctrl.c (usb_device_reset): Fix control endpoint init.
|
||||
(gnuk_setup_endpoints_for_interface): Add DEV
|
||||
argument.
|
||||
(usb_device_reset) [GNU_LINUX_EMULATION]: Use usb_lld_setup_endp.
|
||||
|
||||
2017-09-29 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c [FLASH_UPGRADE_SUPPORT] (main): Factor out flash ROM
|
||||
upgrade support.
|
||||
(calculate_regnual_entry_address): Likewise.
|
||||
* src/usb_ctrl.c (usb_setup, download_check_crc32): Likewise.
|
||||
|
||||
* src/openpgp.c (modify_binary): Fix for 64-bit machine.
|
||||
* src/openpgp-do.c (encrypt, decrypt): Likewise.
|
||||
(gpg_data_scan): Likewise.
|
||||
(gpg_do_chks_prvkey): Fix error return path.
|
||||
|
||||
* src/stack-def.h: New.
|
||||
|
||||
* src/gnuk.ld.in: Remove stack definitions.
|
||||
* src/configure: Remove stack size modifications.
|
||||
|
||||
* src/main.c (STACK_MAIN, STACK_PROCESS_1): Use stack-def.h.
|
||||
* src/usb-ccid.c (STACK_PROCESS_3): Likewise.
|
||||
* src/usb-msc.c (STACK_PROCESS_5): Likewise.
|
||||
* src/pin-cir.c (STACK_PROCESS_6, STACK_PROCESS_7): Likewise.
|
||||
|
||||
* src/usb_ctrl.c (download_check_crc32): Use chrc32_rv_ functions.
|
||||
|
||||
* src/mcu-stm32f103.c (rbit, check_crc32): Remove.
|
||||
|
||||
* src/neug.c: Update from NeuG.
|
||||
* src/neug.h: Ditto.
|
||||
|
||||
2017-09-28 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ec_p256k1.c (coefficient_a): Remove.
|
||||
|
||||
* polarssl/library/bignum.c (mpi_fill_pseudo_random): Fix for
|
||||
64-bit machine.
|
||||
|
||||
* src/call-rsa.c (rsa_decrypt): Fix for 64-bit machine.
|
||||
|
||||
* src/flash.c (flash_do_storage_init): Rename from flash_init.
|
||||
(flash_key_storage_init): Rename from flash_init_keys.
|
||||
* src/openpgp.c (gpg_init): Use new function names.
|
||||
|
||||
* src/stdlib.h: Update for GNU/Linux emulation.
|
||||
|
||||
* src/Makefile: Support GNU/Linux emulation.
|
||||
* src/configure: Support GNU/Linux emulation.
|
||||
* emulation: Remove.
|
||||
|
||||
2017-08-11 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.2.5.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# VID:PID bcdDev Product_STRING Vendor_STRING
|
||||
0000:0000 0200 Gnuk Token Free Software Initiative of Japan
|
||||
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
|
||||
20a0:4211 0200 Nitrokey Start Nitrokey
|
||||
1209:2440 0200 Gnuk Token GnuPG e.V.
|
||||
##########<TAB> ##<TAB> ##########<TAB> #################
|
||||
|
||||
254
NEWS
254
NEWS
@@ -1,5 +1,252 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.19
|
||||
|
||||
Released 2021-10-12, by NIIBE Yutaka
|
||||
|
||||
** KDF Data Object configuration
|
||||
KDF Data Object should be highly recommended for all configurations.
|
||||
Nevertheless, for backward compatibillity, in Gnuk 1.2, it is optional
|
||||
by default; It is up to user to configure KDF Data Object before
|
||||
importing private keys. In this situation, it is not good to
|
||||
introduce new build-time option like --enable-always-require-kdf-do,
|
||||
because it might wrongly encourage use of Gnuk with no KDF Data Object
|
||||
setting, by confusion. If needed, please run configure:
|
||||
|
||||
kdf_do=required ./configure --enable-factory-reset --target...
|
||||
|
||||
or
|
||||
|
||||
kdf_do=optional ./configure --enable-factory-reset --target...
|
||||
|
||||
Please note that such a use of variable by shell command line is not
|
||||
well supported by the configure script (for other variables), but
|
||||
override of kdf_do is needed in some situations.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.20. This enables use with PC/SC for GNU/Linux
|
||||
emulation.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.18
|
||||
|
||||
Released 2021-04-02, by NIIBE Yutaka
|
||||
|
||||
** GNU/Linux emulation bug fix
|
||||
This time, for GNU/Linux emulation, KDF Data Object is required before
|
||||
keygen and key import, really.
|
||||
|
||||
** tool/upgrade_by_passwd.py
|
||||
Now, it checks if the target of binary being written and the
|
||||
configured target of running device are same. This check can be
|
||||
skipped by -s option. Please note that FST-01 and FST-01SZ are
|
||||
different target, as it's MHz is different.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.17
|
||||
|
||||
Released 2021-02-25, by NIIBE Yutaka
|
||||
|
||||
** GNU/Linux: KDF Data Object is required before keygen and key import
|
||||
For GNU/Linux emulation, KDF Data Object is required before keygen and
|
||||
key import.
|
||||
|
||||
** GNU/Linux emulation
|
||||
Since 1.2.10, it was not build-able because of MHZ definition. It is
|
||||
build-able again, and its USB product string is now "Gnuk Token". It
|
||||
has ACK button support using terminal. It now has start-up message,
|
||||
and its driver show useful information to setup USBIP. When no file
|
||||
for the .gnuk-flash-image file, it is automatically created.
|
||||
|
||||
** Removal of tool/gnuk-emulation-setup
|
||||
Because it is automatically created, the tool is not needed any more.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.19.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.16
|
||||
|
||||
Released 2020-09-10, by NIIBE Yutaka
|
||||
|
||||
** New Data Object (Algorithm Information) of OpenPGP card v3.4
|
||||
The tag is 0x00FA. This is useful for user interaction to show which
|
||||
algorithms are supported by the device.
|
||||
|
||||
** Ed25519 signing allowing longer message
|
||||
For OpenPGP, it does hashing on host side before requesting signing to
|
||||
the device. Thus, the length of message to be signed is limited and
|
||||
determined by the hash algorithm. That's good feature of OpenPGP. On
|
||||
the other hand, there is a use case, like OpenSSH certificate signing,
|
||||
where the length of message is a kind of arbitrary. Even though Gnuk
|
||||
(or OpenPGP card protocol itself) has limitation, we removed the
|
||||
length check against EDDSA_HASH_LEN_MAX at cmd_pso.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.15
|
||||
|
||||
Released 2020-01-24, by NIIBE Yutaka
|
||||
|
||||
** Switch to Python3
|
||||
Scripts under tool/ are switched to Python3.
|
||||
Thanks to Bertrand Jacquin.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.18.
|
||||
|
||||
** Tests also support OpenPGPcard
|
||||
Now, a test suite under "tests" may be used to OpenPGPcard.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.14
|
||||
|
||||
Released 2019-03-05, by NIIBE Yutaka
|
||||
|
||||
** Timeout for ACK button support
|
||||
When a user doesn't acknowledge (> 15 seconds), the operation
|
||||
timeouts, and authentication state is cleared.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.14.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.13
|
||||
|
||||
Released 2018-12-26, by NIIBE Yutaka
|
||||
|
||||
** DFU support and its firmware upgrade fix
|
||||
DFU support was not well maintained, and firmware upgrade was not
|
||||
possible for boards with DFU. Now, at least for Maple Mini, it is
|
||||
tested. Note that using Gnuk with DFU on a board is only for an
|
||||
experiment, because DFU can access the content of flash ROM. DFU
|
||||
should be killed by upgrading to normal Gnuk, so that you can have
|
||||
your private keys.
|
||||
|
||||
** Fix for UIF Data Object
|
||||
When flash ROM is full and coping to new page, UIF DO was not properly
|
||||
copied. This bug resulted losing the flag for user interaction. Now,
|
||||
it's properly copied, keeping the setting of the feature.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.13.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.12
|
||||
|
||||
Released 2018-11-25, by NIIBE Yutaka
|
||||
|
||||
** FST-01SZ fixes
|
||||
Fixes for Ack button support and serial number.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.11
|
||||
|
||||
Released 2018-11-12, by NIIBE Yutaka
|
||||
|
||||
** Experimental ACK button support with FST-01SZ
|
||||
While OpenPGP card specification verison 3 has description for the
|
||||
"user interaction" button and data objects, there were no
|
||||
implementation. To evaluate the feature, experimental support is
|
||||
added.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.12, which comes with ACK button driver and supports
|
||||
FST-01SZ.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.10
|
||||
|
||||
Released 2018-05-10, by NIIBE Yutaka
|
||||
|
||||
** No inclusion of VID:PID in gnuk-no-vidpid.elf
|
||||
Now, we have new file named gnuk-no-vidpid.elf with no VID:PID. The
|
||||
file gnuk.elf has the VID:PID, like version 1.2.7 or older.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.9, which supports GD32F103.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.9
|
||||
|
||||
Released 2018-04-05, by NIIBE Yutaka
|
||||
|
||||
** A test suite fix: Clear PW3
|
||||
Until 1.2.8, after running the test suite under "tests", PW3 keystring
|
||||
remained, which affects use of admin-less mode. New test case is
|
||||
added to clear PW3.
|
||||
|
||||
** tool/upgrade_by_passwd.py supports KDF-DO auth
|
||||
With KDF-DO, firmware upgrade didn't work. Now, it's supported.
|
||||
|
||||
** Add "single-salt" support for KDF-DO
|
||||
With KDF-DO, "admin-less" mode didn't work well. With new feature of
|
||||
"single-salt" support, we can use "admin-less" mode with KDF-DO.
|
||||
|
||||
** factory-reset deletes all upgrade public keys
|
||||
By card-edit/factory-reset by GnuPG, it deletes all upgrade public
|
||||
keys, now.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.8
|
||||
|
||||
Released 2018-01-23, by NIIBE Yutaka
|
||||
|
||||
** No inclusion of VID:PID in gnuk.elf
|
||||
|
||||
Distribution of binary image with VID:PID would violate vendor ID
|
||||
agreement to USB Forum. Now, we have new file named gnuk-vidpid.elf
|
||||
for flashing. The file gnuk.elf can be used to generate
|
||||
gnuk-vidpid.elf and we can check if it is reproducible or not.
|
||||
|
||||
** Passphrase length check
|
||||
|
||||
Now, Gnuk checks length of passphrase if it's too short when
|
||||
changing passphrase.
|
||||
|
||||
** Remove unused DEK with BY_ADMIN
|
||||
|
||||
For admin-less mode, DEK by OPENPGP_CARD_INITIAL_PW3 remained on flash
|
||||
ROM. This could be considered a backdoor, if some other person had or
|
||||
kept access to the flash ROM, cheating a user. Now, the DEK is
|
||||
cleared by zero when the token is set to admin-less mode.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.8.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.7
|
||||
|
||||
Released 2017-11-26, by NIIBE Yutaka
|
||||
|
||||
** reGNUal
|
||||
reGNUal enables CRC module by itself.
|
||||
|
||||
** Flash update change
|
||||
CRC module is disabled when Gnuk stops. It's reGNUal which needs to
|
||||
enable CRC module.
|
||||
|
||||
** Support of USB suspend
|
||||
USB suspend and wakeup event are now handled.
|
||||
|
||||
** KDF-DO support and KDF by host
|
||||
KDF-DO is now available. Host can use this feature.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.6.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.6
|
||||
|
||||
Released 2017-10-11, by NIIBE Yutaka
|
||||
|
||||
** Port to GNU/Linux emulation
|
||||
We can "run" Gnuk Token on GNU/Linux by emulation through USBIP.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.5.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.5
|
||||
|
||||
Released 2017-08-11, by NIIBE Yutaka
|
||||
@@ -771,6 +1018,7 @@ Gnuk Token could run with GPG4WIN on MS Windows. GPG4WIN runs with
|
||||
|
||||
** This is initial release. Only it supports digital signing.
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
End:
|
||||
|
||||
# Local Variables:
|
||||
# mode: outline
|
||||
# End:
|
||||
|
||||
144
README
144
README
@@ -1,35 +1,43 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.2.5
|
||||
2017-08-11
|
||||
Version 1.2.19
|
||||
2021-10-12
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
|
||||
This is the release of Gnuk, version 1.2.5, which has major
|
||||
This is the release of Gnuk, version 1.2.19, which has major
|
||||
incompatible changes to Gnuk 1.0.x. Specifically, it now supports
|
||||
overriding key import, but importing keys (or generating keys) results
|
||||
password reset. Please update your documentation for Gnuk Token, so
|
||||
password reset. Also, you need to import private keys before changing
|
||||
your password. Please update your documentation for Gnuk Token, so
|
||||
that the instruction of importing keys won't cause any confusion.
|
||||
|
||||
It has supports of EdDSA, ECDSA (with NIST P256 and secp256k1), and
|
||||
ECDH (with X25519, NIST P256 and secp256k1), but this ECC feature is
|
||||
somehow experimental, and it requires modern GnuPG 2.1 with libgcrypt
|
||||
1.7.0 or later.
|
||||
It has supports of Ed25519 and X25519 (ECDH on Curve25519). It also
|
||||
has experimental support of ECDSA (on NIST P256 and secp256k1) and
|
||||
ECDH (on NIST P256 and secp256k1).
|
||||
|
||||
It also supports RSA-4096, but users should know that it takes more
|
||||
than 8 seconds to sign/decrypt. Key generation of RSA-4096 just fails,
|
||||
because the device doesn't have enough memory.
|
||||
|
||||
It supports new KDF-DO feature. Please note that this is
|
||||
experimental. To use the feature, you need to use newer GnuPG (2.2.6
|
||||
or later). You need to prepare the KDF-DO on your token by the
|
||||
card-edit/kdf-setup command.
|
||||
|
||||
With FST-01SZ and GNU/Linux emulation, experimental ack button support
|
||||
is available for test.
|
||||
|
||||
|
||||
What's Gnuk?
|
||||
============
|
||||
|
||||
Gnuk is an implementation of USB cryptographic token for GNU Privacy
|
||||
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
|
||||
STM32F103 processor.
|
||||
STM32F103 processor (and its compatible).
|
||||
|
||||
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.
|
||||
@@ -46,7 +54,7 @@ FAQ
|
||||
===
|
||||
|
||||
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
|
||||
card 2.0, YubiKey, etc.) ?
|
||||
card 2.0/3.3/3.4, YubiKey, etc.) ?
|
||||
https://www.g10code.de/p-card.html
|
||||
https://www.yubico.com/
|
||||
A0: Good points of Gnuk are:
|
||||
@@ -67,18 +75,16 @@ A1: Gnuk version 1.0 only supports RSA-2048.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so for RSA-2048.
|
||||
It takes more than 8 secondd for RSA-4096.
|
||||
It takes more than 8 seconds for RSA-4096.
|
||||
|
||||
Q3: What's your recommendation for target board?
|
||||
A3: Orthodox choice is Olimex STM32-H103.
|
||||
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
|
||||
kind of the best choice, hopefully.
|
||||
If you have a skill of electronics, STM32 Nucleo F103 is the best
|
||||
choice for experiment.
|
||||
FST-01SZ (Flying Stone Tiny 01 SZ) is available for sale, and it
|
||||
is a kind of the best choice, hopefully. If you have a skill of
|
||||
electronics, STM32 Nucleo F103 is the best choice for experiment.
|
||||
|
||||
Q4: What's version of GnuPG are you using?
|
||||
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.18 in
|
||||
unstable.
|
||||
A4: In Debian GNU/Linux system, I use GnuPG modern 2.2.23.
|
||||
|
||||
Q5: What's version of pcscd and libccid are you using?
|
||||
A5: I don't use them, pcscd and libccid are optional, you can use Gnuk
|
||||
@@ -139,14 +145,20 @@ Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
|
||||
Qd: Do you know a good SWD debugger to connect FST-01 or something?
|
||||
Ad: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
|
||||
writer program. STM32 Nucleo F103 comes with the valiant of
|
||||
ST-Link/V2. However, the firmware of ST-Link/V2 is proprietary.
|
||||
Now, I develop BBG-SWD, SWD debugger by BeagleBone Green.
|
||||
ST-Link/V2. Note that the firmware of ST-Link/V2 is proprietary.
|
||||
So, in case of transparency matters, ST-Link/V2 would not be your
|
||||
choice.
|
||||
I care transparency for our process of manufacturing FST-01SZ (and
|
||||
better control by Free Software, in general), thus, I develop
|
||||
BBG-SWD, SWD debugger by BeagleBone Green.
|
||||
I use ST-Link/V2 for daily development. For serious task like
|
||||
flashing product, I use BBG-SWD.
|
||||
|
||||
|
||||
Tested features
|
||||
===============
|
||||
|
||||
Gnuk is tested by test suite. Please see the test directory.
|
||||
Gnuk is tested by test suite. Please see the "tests" directory.
|
||||
|
||||
* Personalization of the card
|
||||
* Changing Login name, URL, Name, Sex, Language, etc.
|
||||
@@ -172,15 +184,6 @@ Original features of Gnuk, tested manually lightly:
|
||||
* Card holder certificate (write by UPDATE BINARY)
|
||||
* Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal
|
||||
|
||||
It is known not-working well:
|
||||
|
||||
* It is known that the specific combination of libccid 1.4.1
|
||||
(or newer) with libusb 1.0.8 (or older) had 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
|
||||
=======
|
||||
@@ -192,16 +195,6 @@ DfuSe is for experiment only, because it is impossible for DfuSe to
|
||||
disable read from flash. For real use, please consider killing DfuSe
|
||||
and enabling read protection using JTAG debugger.
|
||||
|
||||
For experimental PIN-pad support, I connect a consumer IR receive
|
||||
module to FST-01, and use controller for TV. PIN verification is
|
||||
supported by this configuration. Yes, it is not secure at all, since
|
||||
it is very easy to monitor IR output of the controllers. It is just
|
||||
an experiment. Note that hardware needed for this experiment is only
|
||||
a consumer IR receive module which is as cheap as 50 JPY.
|
||||
|
||||
Note that you need pinpad support for GnuPG to use PIN-pad enabled
|
||||
Gnuk. The pinpad support for GnuPG is only available in version 2.
|
||||
|
||||
|
||||
Build system and Host system
|
||||
============================
|
||||
@@ -212,19 +205,21 @@ If your bash is not installed as /bin/bash, you need to run configure
|
||||
script prepending 'bash' before './configure'.
|
||||
|
||||
Some tools are written in Python. If your Python is not installed as
|
||||
/usr/bin/python, please prepend 'python' for your command invocation.
|
||||
Python 2.7 and PyUSB 0.4.3 is assumed.
|
||||
/usr/bin/python, please prepend 'python' or 'python3' for your command
|
||||
invocation. I use Python 3.8 and PyUSB 1.0.2.
|
||||
|
||||
|
||||
Souce code
|
||||
==========
|
||||
Source code
|
||||
===========
|
||||
|
||||
Gnuk source code is under src/ directory.
|
||||
|
||||
Note that SHA-2 hash function implementation, src/sha256.c, is based
|
||||
on the original implementation by Dr. Brian Gladman. See:
|
||||
|
||||
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
|
||||
http://brg.a2hosted.com//oldsite/cryptography_technology/sha/index.php
|
||||
(was at:
|
||||
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php)
|
||||
|
||||
|
||||
License
|
||||
@@ -248,7 +243,7 @@ External source code
|
||||
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* chopstx/ -- Chopstx 1.3
|
||||
* chopstx/ -- Chopstx 1.20
|
||||
|
||||
We use Chopstx as the kernel for Gnuk.
|
||||
|
||||
@@ -297,6 +292,15 @@ Gnuk is distributed with external source code.
|
||||
POLARSSL_SELF_TEST, and POLARSSL_PADLOCK_C, and only define
|
||||
POLARSSL_GENPRIME when defined KEYGEN_SUPPORT.
|
||||
|
||||
And polarssl/library/bignum.c is modified to work on 64-bit machine.
|
||||
|
||||
Aurelien Jarno also modified:
|
||||
|
||||
polarssl/include/polarssl/bn_mul.h
|
||||
polarssl/library/bignum.c
|
||||
|
||||
See ChangeLog (and/or history of git) for detail.
|
||||
|
||||
|
||||
USB vendor ID and product ID (USB device ID)
|
||||
============================================
|
||||
@@ -358,13 +362,13 @@ How to compile
|
||||
|
||||
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
|
||||
On Debian we can install the packages of gcc-arm-none-eabi,
|
||||
gdb-arm-none-eabi and its friends. I'm using:
|
||||
On Debian we can install the packages of gcc-arm-none-eabi
|
||||
and its friends. I'm using:
|
||||
|
||||
binutils-arm-none-eabi 2.28-4+9+b2
|
||||
gcc-arm-none-eabi 15:5.4.1+svn241155-1
|
||||
gdb-arm-none-eabi 7.12-6+9+b2
|
||||
libnewlib-arm-none-eabi 2.4.0.20160527-2
|
||||
binutils-arm-none-eabi 2.35.2-2+14+b2
|
||||
gcc-arm-none-eabi 15:8-2019-q3-1+b1
|
||||
libnewlib-arm-none-eabi 3.3.0-1
|
||||
gdb-multiarch 10.1-2
|
||||
|
||||
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
|
||||
GNU Toolchain for 'arm-none-eabi' target.
|
||||
@@ -388,6 +392,12 @@ Then, type:
|
||||
|
||||
Then, we will have "gnuk.elf" under src/build directory.
|
||||
|
||||
If you are not the authorized vendor, please never distribute this
|
||||
file of "gnuk.elf", which includes VID:PID in the image. If you would
|
||||
like to distribute the image (for example, to check if it's
|
||||
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
|
||||
VID:PID.
|
||||
|
||||
|
||||
How to install
|
||||
==============
|
||||
@@ -416,10 +426,12 @@ OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
|
||||
-c "program build/gnuk.elf verify reset exit"
|
||||
|
||||
|
||||
|
||||
STBee
|
||||
-----
|
||||
|
||||
Note that this is only for your experiment; Your private key materials
|
||||
on the board can be accessed by DfuSe.
|
||||
|
||||
Reset the board with "USER" switch pushed. Type following to write
|
||||
to flash:
|
||||
|
||||
@@ -458,7 +470,7 @@ protect, killing DfuSe and accessing by JTAG debugger is recommended.
|
||||
This is completely optional.
|
||||
|
||||
For this procedure, you need python and pyscard (python-pyscard
|
||||
package in Debian) or PyUSB 0.4.3 (python-usb package in Debian).
|
||||
package in Debian) or PyUSB (python-usb package in Debian).
|
||||
|
||||
(1) [pyscard] Stop scdaemon
|
||||
[PyUSB] Stop the pcsc daemon.
|
||||
@@ -470,7 +482,7 @@ Exception" by "Sharing violation".
|
||||
|
||||
In case of PyUSB tool, you need to stop pcscd.
|
||||
|
||||
# /etc/init.d/pcscd stop
|
||||
# systemctl stop pcscd
|
||||
|
||||
|
||||
(2) [Optional] Write fixed serial number
|
||||
@@ -514,8 +526,8 @@ Type following command to see Gnuk runs:
|
||||
$ gpg --card-status
|
||||
|
||||
|
||||
Besides, there is a functionality test under test/ directory. See
|
||||
test/README.
|
||||
Besides, there is a functionality test under tests/ directory. See
|
||||
tests/README.
|
||||
|
||||
|
||||
Personalize the Token, import keys, and change the password
|
||||
@@ -537,7 +549,7 @@ Gnuk supports key generation, but this feature is young and should be
|
||||
considered experimental.
|
||||
|
||||
For detail, please see documentation under doc/. You can see the HTML
|
||||
version at: http://www.fsij.org/doc-gnuk/
|
||||
version at: https://www.fsij.org/doc-gnuk/
|
||||
|
||||
|
||||
How to debug
|
||||
@@ -576,31 +588,24 @@ See doc/note/firmware-update.
|
||||
Git Repositories
|
||||
================
|
||||
|
||||
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
|
||||
Please use: https://salsa.debian.org/gnuk-team/gnuk/
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
|
||||
$ git clone https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
|
||||
|
||||
It's also available at: www.gniibe.org
|
||||
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
|
||||
You can browse at: https://git.gniibe.org/cgit/gnuk/gnuk.git/
|
||||
|
||||
I put Chopstx as a submodule of Git. Please do this:
|
||||
|
||||
$ git submodule update --init
|
||||
|
||||
Gnuk 1.0 uses ChibiOS/RT, and then, we have migrated from to Chopstx
|
||||
in the development phase of Gnuk 1.1. If you have old code of
|
||||
ChibiOS/RT, you need:
|
||||
|
||||
Edit .git/config to remove chibios reference and
|
||||
$ git rm --cached chibios
|
||||
|
||||
|
||||
Information on the Web
|
||||
======================
|
||||
|
||||
Please visit: http://www.fsij.org/gnuk/
|
||||
For more information, please visit: https://www.fsij.org/gnuk/
|
||||
|
||||
Please see the FST-01 support pages:
|
||||
|
||||
@@ -608,7 +613,8 @@ Please see the FST-01 support pages:
|
||||
|
||||
Please consider to join Gnuk-users mailing list:
|
||||
|
||||
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
|
||||
https://lists.gnupg.org/mailman/listinfo/gnuk-users
|
||||
|
||||
|
||||
|
||||
Your Contributions
|
||||
|
||||
5
THANKS
5
THANKS
@@ -7,6 +7,7 @@ Gnuk was originally written by NIIBE Yutaka. People contributed by
|
||||
encouraging the development, testing the implementation, suggesting
|
||||
improvements, or fixing bugs. Here is a list of those people.
|
||||
|
||||
Aurelien Jarno aurelien@aurel32.net
|
||||
Achim Pietig achim@pietig.com
|
||||
Aidan Thornton
|
||||
Anibal Monsalve Salazar anibal@debian.org
|
||||
@@ -16,6 +17,8 @@ Bertrand Jacquin bertrand@jacquin.bzh
|
||||
Clint Adams clint@softwarefreedom.org
|
||||
Daniel Kahn Gillmor dkg@fifthhorseman.net
|
||||
Elliott Mitchell
|
||||
Fabio Utzig utzig@apache.org
|
||||
Heiko Schaefer heiko.schaefer@posteo.de
|
||||
Hironobu SUZUKI hironobu@h2np.net
|
||||
Jan Suhr jan@suhr.info
|
||||
Jeremy Drake jeremydrake+gnuk@eacceleration.com
|
||||
@@ -33,10 +36,12 @@ Nico Rikken nico@nicorikken.eu
|
||||
NOKUBI Takatsugu knok@daionet.gr.jp
|
||||
Paul Fertser
|
||||
Paul Bakker polarssl_maintainer@polarssl.org
|
||||
Peter Lebbing peter@digitalbrains.com
|
||||
Santiago Ruano Rincón santiago@debian.org
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
Stanislas Bach sbach@0g.re
|
||||
Szczepan Zalega szczepan@nitrokey.com
|
||||
Vasily Evseenko
|
||||
Vincent Pelletier plr.vincent@gmail.com
|
||||
Werner Koch wk@gnupg.org
|
||||
Yuji Imai ug@xcast.jp
|
||||
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: d8df82badf...a6b96fe434
@@ -40,11 +40,11 @@ We are using "-O3 -Os" for compiler option.
|
||||
Building Gnuk
|
||||
-------------
|
||||
|
||||
Change directory to ``src``:
|
||||
Change directory to ``src``: ::
|
||||
|
||||
$ cd gnuk-VERSION/src
|
||||
|
||||
Then, run ``configure``:
|
||||
Then, run ``configure``: ::
|
||||
|
||||
$ ./configure --vidpid=<VID:PID>
|
||||
|
||||
@@ -52,8 +52,14 @@ 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:
|
||||
Type: ::
|
||||
|
||||
$ make
|
||||
|
||||
Then, we will have "gnuk.elf" under src/build directory.
|
||||
|
||||
If you are not the authorized vendor, please never distribute this
|
||||
file of "gnuk.elf", which includes VID:PID in the image. If you would
|
||||
like to distribute the image (for example, to check if it's
|
||||
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
|
||||
VID:PID.
|
||||
|
||||
@@ -16,7 +16,7 @@ In addition to settings of Gnuk, I create a file
|
||||
|
||||
# For updating firmware, permission settings are needed.
|
||||
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
|
||||
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd"
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ setting). It should have lines something like: ::
|
||||
# Gnuk Token by FSIJ
|
||||
|
||||
SUBSYSTEMS=="usb", ACTION=="add", \
|
||||
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
|
||||
ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
|
||||
|
||||
I have those lines in /etc/udev/rules.d/69-gnuk.rules.
|
||||
@@ -73,16 +73,21 @@ and make: ::
|
||||
$ make
|
||||
|
||||
Please take care of configure options. The default target in 1.0.x
|
||||
series is Olimex STM32 H103 (not FST-01). The default target in 1.1.8
|
||||
series is Olimex STM32 H103 (not FST-01). The default target in 1.2.x
|
||||
is FST-01.
|
||||
|
||||
Then you get build/gnuk.elf.
|
||||
|
||||
Then you get build/gnuk.elf and build/gnuk.bin.
|
||||
If you are not the authorized vendor, please never distribute this
|
||||
file of "gnuk.elf", which includes VID:PID in the image. If you would
|
||||
like to distribute the image (for example, to check if it's
|
||||
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
|
||||
VID:PID.
|
||||
|
||||
Invoking configure with FSIJ's USB ID (234b:0000) means that you are
|
||||
using FSIJ's USB ID (for reGNUal in this case). Please note that FSIJ
|
||||
only allows use of its USB ID for specific situations. Please read
|
||||
README of Gnuk about that.
|
||||
Invoking configure with FSIJ's USB ID (234b:0000) and generating
|
||||
gnuk.elf means that you are using FSIJ's USB ID (for reGNUal in this
|
||||
case). Please note that FSIJ only allows use of its USB ID for
|
||||
specific situations. Please read README of Gnuk about that.
|
||||
|
||||
|
||||
Bulding reGNUal
|
||||
@@ -122,8 +127,8 @@ How to run the script: ::
|
||||
Then, the script on your host PC invoke the steps described above, and
|
||||
you will get new version of Gnuk installed.
|
||||
|
||||
You can also specify -p option to enter your password (other than
|
||||
factory setting).
|
||||
You can also specify -f option to skip entering your password (it
|
||||
assumes the factory setting).
|
||||
|
||||
If you already have configured another upgrade key installed, you can
|
||||
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0
|
||||
|
||||
@@ -30,9 +30,9 @@ command.
|
||||
|
||||
Or, you can use ``gpgconf`` command. Type::
|
||||
|
||||
$ gpgconf --reload scdameon
|
||||
$ gpgconf --reload scdaemon
|
||||
|
||||
will do the samething.
|
||||
will do the same thing.
|
||||
|
||||
|
||||
Let GPG-AGENT/SCDAEMON learn
|
||||
|
||||
@@ -37,7 +37,7 @@ When we only install "gnupg2" package for 2.0 (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", \
|
||||
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
|
||||
|
||||
Usually, udev daemon automatically handles for the changes of configuration
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
SRCS = usbip-server.c usb-emu.c glue.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
TARGET=gnuk_emulation
|
||||
GNUKDIR=../src
|
||||
|
||||
GNUK_SRCS = main.c call-rsa.c \
|
||||
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
|
||||
bn.c mod.c \
|
||||
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
|
||||
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
|
||||
mod25638.c ecc-edwards.c ecc-mont.c sha512.c \
|
||||
random.c neug.c sha256.c
|
||||
USB_SRCS=usb_desc.c usb_ctrl.c
|
||||
|
||||
GNUK_CSRC = $(addprefix $(GNUKDIR)/, $(GNUK_SRCS))
|
||||
GNUK_OBJS = $(notdir $(GNUK_CSRC:.c=.o))
|
||||
|
||||
USB_CSRC = $(addprefix $(GNUKDIR)/, $(USB_SRCS))
|
||||
USB_OBJS = $(notdir $(USB_CSRC:.c=.o))
|
||||
|
||||
# all:
|
||||
# echo $(GNUK_OBJS)
|
||||
|
||||
$(TARGET): $(OBJS) $(USB_OBJS) Makefile
|
||||
$(CC) -o $(TARGET) $(OBJS) $(USB_OBJS)
|
||||
|
||||
$(GNUK_OBJS): %.o : $(GNUKDIR)/%.c Makefile
|
||||
$(CC) -c $(CFLAGS) -I. -I$(GNUKDIR) -I../chopstx $< -o $@
|
||||
|
||||
$(USB_OBJS): %.o : $(GNUKDIR)/%.c Makefile
|
||||
$(CC) -c $(CFLAGS) -I. -I$(GNUKDIR) -I../chopstx $< -o $@
|
||||
@@ -1,54 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t _regnual_start;
|
||||
uint8_t __heap_end__;
|
||||
|
||||
int
|
||||
check_crc32 (const uint32_t *start_p, const uint32_t *end_p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
sram_address (uint32_t offset)
|
||||
{
|
||||
return ((uint8_t *)0x20000000) + offset;
|
||||
}
|
||||
|
||||
const uint8_t sys_version[8] = {
|
||||
3*2+2, /* bLength */
|
||||
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
|
||||
/* sys version: "3.0" */
|
||||
'3', 0, '.', 0, '0', 0,
|
||||
};
|
||||
|
||||
void
|
||||
led_blink (int spec)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ccid_usb_reset (int full)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ccid_card_change_signal (int how)
|
||||
{
|
||||
}
|
||||
|
||||
enum ccid_state {
|
||||
CCID_STATE_NOCARD, /* No card available */
|
||||
CCID_STATE_START, /* Initial */
|
||||
CCID_STATE_WAIT, /* Waiting APDU */
|
||||
/* Busy1, Busy2, Busy3, Busy5 */
|
||||
CCID_STATE_EXECUTE, /* Busy4 */
|
||||
CCID_STATE_RECEIVE, /* APDU Received Partially */
|
||||
CCID_STATE_SEND, /* APDU Sent Partially */
|
||||
|
||||
CCID_STATE_EXITED, /* ICC Thread Terminated */
|
||||
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
static enum ccid_state ccid_state;
|
||||
enum ccid_state *const ccid_state_p = &ccid_state;
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* usb-emu.c - USB driver for USBIP emulation
|
||||
*
|
||||
* Copyright (C) 2017 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Chopstx, a thread library for embedded.
|
||||
*
|
||||
* Chopstx 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.
|
||||
*
|
||||
* Chopstx 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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../chopstx/usb_lld.h"
|
||||
|
||||
int
|
||||
usb_lld_ctrl_ack (struct usb_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
usb_lld_ctrl_recv (struct usb_dev *dev, void *p, size_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
usb_lld_ctrl_send (struct usb_dev *dev, const void *buf, size_t buflen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
usb_lld_current_configuration (struct usb_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_prepare_shutdown (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_ctrl_error (struct usb_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_reset (struct usb_dev *dev, uint8_t feature)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_set_configuration (struct usb_dev *dev, uint8_t config)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
usb_lld_shutdown (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
||||
int ep_rx_addr, int ep_tx_addr,
|
||||
int ep_rx_memory_size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_stall (int ep_num)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usb_lld_stall_tx (int ep_num)
|
||||
{
|
||||
usb_lld_stall (ep_num);
|
||||
}
|
||||
|
||||
void
|
||||
usb_lld_stall_rx (int ep_num)
|
||||
{
|
||||
usb_lld_stall (ep_num);
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* usbip-server.c - USB Device Emulation by USBIP Protocol
|
||||
*
|
||||
* Copyright (C) 2017 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Chopstx, a thread library for embedded.
|
||||
*
|
||||
* Chopstx 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.
|
||||
*
|
||||
* Chopstx 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 <unistd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define USBIP_PORT 3240
|
||||
|
||||
#define CMD_REQ_LIST 0x01118005
|
||||
#define CMD_REQ_ATTACH 0x01118003
|
||||
#define CMD_URB 0x00000001
|
||||
#define CMD_DETACH 0x00000002
|
||||
|
||||
struct usbip_msg_head {
|
||||
uint32_t cmd;
|
||||
uint32_t seq;
|
||||
};
|
||||
|
||||
#define USBIP_REPLY_HEADER_SIZE 12
|
||||
#define DEVICE_INFO_SIZE (256+32+12+6+6)
|
||||
#define INTERFACE_INFO_SIZE 4
|
||||
#define DEVICE_LIST_SIZE (USBIP_REPLY_HEADER_SIZE+DEVICE_INFO_SIZE*1+INTERFACE_INFO_SIZE*1)
|
||||
|
||||
#define USBIP_REPLY_DEVICE_LIST "\x01\x11\x00\x05"
|
||||
#define NETWORK_UINT32_ZERO "\x00\x00\x00\x00"
|
||||
#define NETWORK_UINT32_ONE "\x00\x00\x00\x01"
|
||||
#define NETWORK_UINT32_TWO "\x00\x00\x00\x02"
|
||||
#define NETWORK_UINT16_FSIJ "\x23\x4b"
|
||||
#define NETWORK_UINT16_ZERO "\x00\x00"
|
||||
#define NETWORK_UINT16_ONE_ONE "\x01\x01"
|
||||
|
||||
static char *
|
||||
list_devices (size_t *len_p)
|
||||
{
|
||||
char *p0, *p;
|
||||
|
||||
*len_p = 0;
|
||||
p0 = malloc (DEVICE_LIST_SIZE);
|
||||
if (p0 == NULL)
|
||||
return NULL;
|
||||
|
||||
*len_p = DEVICE_LIST_SIZE;
|
||||
|
||||
p = p0;
|
||||
memcpy (p, USBIP_REPLY_DEVICE_LIST, 4);
|
||||
p += 4;
|
||||
memcpy (p, NETWORK_UINT32_ZERO, 4);
|
||||
p += 4;
|
||||
memcpy (p, NETWORK_UINT32_ONE, 4);
|
||||
p += 4;
|
||||
memset (p, 0, 256);
|
||||
strcpy (p, "/sys/devices/pci0000:00/0000:00:01.1/usb1/1-1");
|
||||
p += 256;
|
||||
memset (p, 0, 32);
|
||||
strcpy (p, "1-1");
|
||||
p += 32;
|
||||
memcpy (p, NETWORK_UINT32_ONE, 4); /* Bus */
|
||||
p += 4;
|
||||
memcpy (p, NETWORK_UINT32_TWO, 4); /* Dev */
|
||||
p += 4;
|
||||
memcpy (p, NETWORK_UINT32_ONE, 4); /* Speed */
|
||||
p += 4;
|
||||
memcpy (p, NETWORK_UINT16_FSIJ, 2);
|
||||
p += 2;
|
||||
memcpy (p, NETWORK_UINT16_ZERO, 2); /* Gnuk */
|
||||
p += 2;
|
||||
memcpy (p, NETWORK_UINT16_ONE_ONE, 2); /* USB 1.1 */
|
||||
p += 2;
|
||||
|
||||
*p++ = 0; /* bDeviceClass */
|
||||
*p++ = 0; /* bDeviceSubClass */
|
||||
*p++ = 0; /* bDeviceProtocol */
|
||||
*p++ = 0; /* bConfigurationValue */
|
||||
*p++ = 1; /* bConfigurationValue */
|
||||
*p++ = 1; /* bNumInterfaces */
|
||||
|
||||
*p++ = 11; /* bInterfaceClass */
|
||||
*p++ = 0; /* bInterfaceSubClass */
|
||||
*p++ = 0; /* bInterfaceProtocol */
|
||||
*p++ = 0; /* ----pad----------- */
|
||||
|
||||
return p0;
|
||||
}
|
||||
|
||||
static char *
|
||||
attach_device (char busid[32], size_t *len_p)
|
||||
{
|
||||
*len_p = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_urb (int fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
run_server (void)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in v4addr;
|
||||
const int one = 1;
|
||||
|
||||
if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
perror ("socket");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char*)&one, sizeof (int)) < 0)
|
||||
perror ("WARN: setsockopt");
|
||||
|
||||
memset (&v4addr, 0, sizeof (v4addr));
|
||||
v4addr.sin_family = AF_INET;
|
||||
v4addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||
v4addr.sin_port = htons (USBIP_PORT);
|
||||
|
||||
if (bind (sock, (const struct sockaddr *)&v4addr, sizeof (v4addr)) < 0)
|
||||
{
|
||||
perror ("bind");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* We only accept a connection from a single client. */
|
||||
if (listen (sock, 1) < 0)
|
||||
{
|
||||
perror ("listen");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd;
|
||||
int attached = 0;
|
||||
|
||||
/* We don't care who is connecting. */
|
||||
if ((fd = accept (sock, NULL, NULL)) < 0)
|
||||
{
|
||||
perror ("accept");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct usbip_msg_head msg;
|
||||
|
||||
if (recv (fd, (char *)&msg, sizeof (msg), 0) != sizeof (msg))
|
||||
{
|
||||
perror ("msg recv");
|
||||
break;
|
||||
}
|
||||
|
||||
msg.cmd = ntohl (msg.cmd);
|
||||
msg.seq = ntohl (msg.seq);
|
||||
|
||||
if (msg.cmd == CMD_REQ_LIST)
|
||||
{
|
||||
char *device_list;
|
||||
size_t device_list_size;
|
||||
|
||||
if (attached)
|
||||
{
|
||||
fprintf (stderr, "REQ list while attached\n");
|
||||
break;
|
||||
}
|
||||
|
||||
device_list = list_devices (&device_list_size);
|
||||
|
||||
if (send (fd, device_list, device_list_size, 0) != device_list_size)
|
||||
{
|
||||
perror ("list send");
|
||||
break;
|
||||
}
|
||||
|
||||
free (device_list);
|
||||
}
|
||||
else if (msg.cmd == CMD_REQ_ATTACH)
|
||||
{
|
||||
char busid[32];
|
||||
char *attach;
|
||||
size_t attach_size;
|
||||
|
||||
if (attached)
|
||||
{
|
||||
fprintf (stderr, "REQ attach while attached\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (recv (fd, busid, 32, 0) != 32)
|
||||
{
|
||||
perror ("attach recv");
|
||||
break;
|
||||
}
|
||||
|
||||
attach = attach_device (busid, &attach_size);
|
||||
if (send (fd, attach, attach_size, 0) != attach_size)
|
||||
{
|
||||
perror ("list send");
|
||||
break;
|
||||
}
|
||||
|
||||
free (attach);
|
||||
attached = 1;
|
||||
}
|
||||
else if (msg.cmd == CMD_URB)
|
||||
{
|
||||
if (!attached)
|
||||
{
|
||||
fprintf (stderr, "URB while attached\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle_urb (fd) < 0)
|
||||
{
|
||||
fprintf (stderr, "URB handling failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(msg.cmd == CMD_DETACH)
|
||||
{
|
||||
if (!attached)
|
||||
{
|
||||
fprintf (stderr, "DETACH while attached\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* send reply??? */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Unknown command %08x, disconnecting.\n", msg.cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
run_server ();
|
||||
return 0;
|
||||
}
|
||||
@@ -495,6 +495,67 @@
|
||||
#endif /* TriCore */
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__ARM_FEATURE_DSP)
|
||||
/* The ARM DSP instructions are available on Cortex M4, M7 and
|
||||
Cortex A CPUs */
|
||||
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %[s]!, { r7, r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r3, r4, r5, r6 } \n\t" \
|
||||
"umaal r3, %2, %[b], r7 \n\t" \
|
||||
"umaal r4, %2, %[b], r8 \n\t" \
|
||||
"umaal r5, %2, %[b], r9 \n\t" \
|
||||
"umaal r6, %2, %[b], r10 \n\t" \
|
||||
"stmia %[d]!, {r3, r4, r5, r6} \n\t"
|
||||
|
||||
#define MULADDC_1024_LOOP \
|
||||
asm( "tst %[i], #0xfe0 \n\t" \
|
||||
"beq 0f \n" \
|
||||
"1: sub %[i], %[i], #32 \n\t" \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
"tst %[i], #0xfe0 \n\t" \
|
||||
"bne 1b \n" \
|
||||
"0:" \
|
||||
: [s] "=r" (s), [d] "=r" (d), [c] "=r" (c), [i] "=r" (i) \
|
||||
: [b] "r" (b), "[s]" (s), "[d]" (d), "[c]" (c), "[i]" (i) \
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm(
|
||||
|
||||
#define MULADDC_CORE \
|
||||
"ldr r0, [%0], #4 \n\t" \
|
||||
"ldr r1, [%1] \n\t" \
|
||||
"umaal r1, %2, %3, r0 \n\t" \
|
||||
"str r1, [%1], #4 \n\t"
|
||||
|
||||
#define MULADDC_HUIT \
|
||||
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
|
||||
"ldmia %1, {r4, r5, r6, r7} \n\t" \
|
||||
"umaal r4, %2, %3, r0 \n\t" \
|
||||
"umaal r5, %2, %3, r1 \n\t" \
|
||||
"umaal r6, %2, %3, r2 \n\t" \
|
||||
"umaal r7, %2, %3, r3 \n\t" \
|
||||
"stmia %1!, {r4, r5, r6, r7} \n\t" \
|
||||
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
|
||||
"ldmia %1, {r4, r5, r6, r7} \n\t" \
|
||||
"umaal r4, %2, %3, r0 \n\t" \
|
||||
"umaal r5, %2, %3, r1 \n\t" \
|
||||
"umaal r6, %2, %3, r2 \n\t" \
|
||||
"umaal r7, %2, %3, r3 \n\t" \
|
||||
"stmia %1!, {r4, r5, r6, r7} \n\t"
|
||||
|
||||
#define MULADDC_STOP \
|
||||
: "=r" (s), "=r" (d), "=r" (c) \
|
||||
: "r" (b), "0" (s), "1" (d), "2" (c) \
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", \
|
||||
"r6", "r7", "memory");
|
||||
|
||||
#else /* __ARM_FEATURE_DSP */
|
||||
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
@@ -556,7 +617,7 @@
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
|
||||
|
||||
/* Just for reference (dead code) */
|
||||
#define MULADDC_HUIT \
|
||||
#define MULADDC_HUIT_DEAD \
|
||||
"ldmia %0!, { r4, r5 } \n\t" \
|
||||
"ldmia %1, { r8, r9 } \n\t" \
|
||||
"umull r6, r7, %3, r4 \n\t" \
|
||||
@@ -620,6 +681,7 @@
|
||||
: "r" (b), "0" (s), "1" (d), "2" (c) \
|
||||
: "r4", "r5", "r6", "r7", "memory", "cc" );
|
||||
|
||||
#endif /* __ARM_FEATURE_DSP */
|
||||
#endif /* ARMv3 */
|
||||
|
||||
#if defined(__alpha__)
|
||||
@@ -811,8 +873,8 @@
|
||||
#else
|
||||
#define MULADDC_INIT \
|
||||
{ \
|
||||
t_int s0, s1, b0, b1; \
|
||||
t_int r0, r1, rx, ry; \
|
||||
t_uint s0, s1, b0, b1; \
|
||||
t_uint r0, r1, rx, ry; \
|
||||
b0 = ( b << biH ) >> biH; \
|
||||
b1 = ( b >> biH );
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "polarssl/bignum.h"
|
||||
#include "polarssl/bn_mul.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <gnuk-malloc.h>
|
||||
|
||||
#define ciL (sizeof(t_uint)) /* chars in limb */
|
||||
#define biL (ciL << 3) /* bits in limb */
|
||||
@@ -223,6 +223,7 @@ size_t mpi_lsb( const mpi *X )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if !defined(POLARSSL_HAVE_UDBL)
|
||||
/*
|
||||
* Count leading zero bits in a given integer
|
||||
*/
|
||||
@@ -240,6 +241,7 @@ static size_t int_clz( const t_uint x )
|
||||
|
||||
return j;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the number of most significant bits
|
||||
@@ -1140,9 +1142,9 @@ static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
|
||||
*/
|
||||
if(( 0 == d ) || ( u1 >= d ))
|
||||
{
|
||||
if (r != NULL) *r = (~0);
|
||||
if (r != NULL) *r = (~0UL);
|
||||
|
||||
return (~0);
|
||||
return (~0UL);
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_HAVE_UDBL)
|
||||
@@ -1268,7 +1270,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
|
||||
for( i = n; i > t ; i-- )
|
||||
{
|
||||
if( X.p[i] >= Y.p[t] )
|
||||
Z.p[i - t - 1] = ~0;
|
||||
Z.p[i - t - 1] = ~0UL;
|
||||
else
|
||||
{
|
||||
Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i-1], Y.p[t], NULL);
|
||||
@@ -1295,7 +1297,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
|
||||
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
|
||||
MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
|
||||
|
||||
if( mpi_cmp_int( &X, 0 ) < 0 )
|
||||
while( mpi_cmp_int( &X, 0 ) < 0 )
|
||||
{
|
||||
MPI_CHK( mpi_copy( &T1, &Y ) );
|
||||
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
|
||||
@@ -1512,9 +1514,17 @@ static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
/*
|
||||
* Montgomery square: A = A * A * R^-1 mod N
|
||||
* A is placed at the upper half of D.
|
||||
*
|
||||
* n : number of limbs of N
|
||||
* np: pointer to limbs of bignum N
|
||||
* mm: m' = -N^(-1) mod b where b = 2^number-of-bit-in-limb
|
||||
* d (destination): the result [<-- temp -->][<--- A ---->]
|
||||
* lower part upper part
|
||||
* n-limb n-limb
|
||||
*/
|
||||
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_ASM) && defined(__arm__)
|
||||
size_t i;
|
||||
register t_uint c = 0;
|
||||
|
||||
@@ -1526,6 +1536,52 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
|
||||
x_i = *xj;
|
||||
*xj++ = c;
|
||||
|
||||
#if defined(__ARM_FEATURE_DSP)
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
"mov r4, %[c]\n\t"
|
||||
"umlal r5, r4, %[x_i], %[x_i]\n\t"
|
||||
"str r5, [%[wij]], #4\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bhi 0f\n\t"
|
||||
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
|
||||
"beq 1f\n"
|
||||
"2:\n\t"
|
||||
"ldmia %[xj]!, { r7, r8 }\n\t"
|
||||
"ldmia %[wij], { r5, r6 }\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umaal r5, r4, %[x_i], r7\n\t"
|
||||
"umlal r5, %[c], %[x_i], r7\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umaal r6, r4, %[x_i], r8\n\t"
|
||||
"umlal r6, %[c], %[x_i], r8\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
/**/
|
||||
"stmia %[wij]!, { r5, r6 }\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bcc 2b\n\t"
|
||||
"bne 0f\n"
|
||||
"1:\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"ldr r6, [%[xj]], #4\n\t"
|
||||
"umaal r5, r4, %[x_i], r6\n\t"
|
||||
"umlal r5, %[c], %[x_i], r6\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
"str r5, [%[wij]], #4\n"
|
||||
"0:\n\t"
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"adds r4, r4, r5\n\t"
|
||||
"adc %[c], %[c], #0\n\t"
|
||||
"str r4, [%[wij]]"
|
||||
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc");
|
||||
#else
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
@@ -1587,6 +1643,7 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
|
||||
#endif
|
||||
|
||||
c += mpi_mul_hlp( n, np, &d[i], d[i] * mm );
|
||||
}
|
||||
@@ -1598,16 +1655,29 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
mpi_sub_hlp( n, np, d );
|
||||
else
|
||||
mpi_sub_hlp( n, d - n, d - n);
|
||||
#else
|
||||
t_uint a_input[n];
|
||||
|
||||
memcpy (a_input, &d[n], sizeof (a_input));
|
||||
mpi_montmul (n, np, mm, d, a_input);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
|
||||
*/
|
||||
#if MEMORY_SIZE >= 32
|
||||
#define MAX_WSIZE 6
|
||||
#elif MEMORY_SIZE >= 24
|
||||
#define MAX_WSIZE 5
|
||||
#else
|
||||
#define MAX_WSIZE 4
|
||||
#endif
|
||||
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
{
|
||||
int ret;
|
||||
size_t i = mpi_msb( E );
|
||||
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
|
||||
size_t wsize = ( i > 1024 ) ? MAX_WSIZE :
|
||||
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
|
||||
size_t wbits, one = 1;
|
||||
@@ -2052,17 +2122,19 @@ jkiss (struct jkiss_state *s)
|
||||
static int mpi_fill_pseudo_random ( mpi *X, size_t size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t *p;
|
||||
uint32_t *p, *p_end;
|
||||
|
||||
MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
|
||||
MPI_CHK( mpi_lset( X, 0 ) );
|
||||
|
||||
/* Assume little endian. */
|
||||
p = X->p;
|
||||
while (p < X->p + (size/ciL))
|
||||
p = (uint32_t *)X->p;
|
||||
p_end = (uint32_t *)(X->p + (size/sizeof (uint32_t)));
|
||||
while (p < p_end)
|
||||
*p++ = jkiss (&jkiss_state_v);
|
||||
if ((size % ciL))
|
||||
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % ciL))) - 1);
|
||||
|
||||
if ((size%sizeof (uint32_t)))
|
||||
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % sizeof (uint32_t)))) - 1);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
@@ -2203,10 +2275,24 @@ cleanup:
|
||||
* Value M: multiply all primes up to 701 (except 97) and 797
|
||||
* (so that MAX_A will be convenient value)
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
#define M_LIMBS 16
|
||||
#else
|
||||
#define M_LIMBS 31
|
||||
#endif
|
||||
#define M_SIZE 122
|
||||
|
||||
static const t_uint limbs_M[] = { /* Little endian */
|
||||
#ifdef __LP64__
|
||||
0x9344A6AB84EEB59EUL, 0xEC855CDAFF21529FUL,
|
||||
0x477E991E009BAB38UL, 0x2EEA23579F5B86F3UL,
|
||||
0xAC17D30441D6502FUL, 0x38FF52B90A468A6DUL,
|
||||
0x63630419FD42E5EFUL, 0x48CE17D091DB2572UL,
|
||||
0x708AB00AE3B57D0EUL, 0xF8A9DE08CD723598UL,
|
||||
0x731411374432C93BUL, 0x554DF2612779FAB3UL,
|
||||
0xDEEBDA58953D2BA5UL, 0xD1D66F2F5F57D007UL,
|
||||
0xB85C9607E84E9F2BUL, 0x000000000000401DUL
|
||||
#else
|
||||
0x84EEB59E, 0x9344A6AB, 0xFF21529F, 0xEC855CDA,
|
||||
0x009BAB38, 0x477E991E, 0x9F5B86F3, 0x2EEA2357,
|
||||
0x41D6502F, 0xAC17D304, 0x0A468A6D, 0x38FF52B9,
|
||||
@@ -2215,6 +2301,7 @@ static const t_uint limbs_M[] = { /* Little endian */
|
||||
0x4432C93B, 0x73141137, 0x2779FAB3, 0x554DF261,
|
||||
0x953D2BA5, 0xDEEBDA58, 0x5F57D007, 0xD1D66F2F,
|
||||
0xE84E9F2B, 0xB85C9607, 0x0000401D
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
|
||||
@@ -2222,10 +2309,18 @@ static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
|
||||
/*
|
||||
* MAX_A : 2^1024 / M - 1
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
#define MAX_A_LIMBS 1
|
||||
#else
|
||||
#define MAX_A_LIMBS 2
|
||||
#endif
|
||||
#define MAX_A_FILL_SIZE 6
|
||||
static const t_uint limbs_MAX_A[] = { /* Little endian */
|
||||
#ifdef __LP64__
|
||||
0x0003FE2556A2B35FUL
|
||||
#else
|
||||
0x56A2B35F, 0x0003FE25
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mpi MAX_A[1] = {{ 1, MAX_A_LIMBS, (t_uint *)limbs_MAX_A }};
|
||||
@@ -2275,9 +2370,8 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
|
||||
|
||||
MPI_CHK ( mpi_mul_mpi ( X, X, M ) );
|
||||
MPI_CHK ( mpi_add_abs ( X, X, B ) );
|
||||
if (X->n <= 31 || (X->p[31] & 0xc0000000) == 0)
|
||||
if (X->n <= M_LIMBS || (X->p[M_LIMBS-1] & 0xc0000000) == 0)
|
||||
continue;
|
||||
|
||||
ret = mpi_is_prime ( X );
|
||||
if (ret == 0 || ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE)
|
||||
break;
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "polarssl/md.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# Makefile for reGNUal
|
||||
|
||||
PROJECT = regnual
|
||||
PROJECT = regnual-no-vidpid
|
||||
|
||||
OBJS = regnual.o usb-stm32f103.o reset.o
|
||||
LDSCRIPT= regnual.ld
|
||||
|
||||
include ../src/config.mk
|
||||
|
||||
LDSCRIPT= regnual.ld
|
||||
|
||||
###################################
|
||||
MCU = cortex-m3
|
||||
|
||||
@@ -40,13 +41,18 @@ regnual.hex: regnual.elf
|
||||
$(OBJCOPY) -Obinary regnual.elf regnual.bin
|
||||
$(OBJCOPY) -Oihex regnual.elf regnual.hex
|
||||
|
||||
regnual.elf: regnual-no-vidpid.elf
|
||||
cp -p regnual-no-vidpid.elf regnual.elf
|
||||
env FILE="regnual.elf" PATH="../src:$$PATH" bash put-vid-pid-ver.sh
|
||||
|
||||
usb-stm32f103.o: ../chopstx/mcu/usb-stm32f103.c
|
||||
$(CC) $(CFLAGS) -c -o usb-stm32f103.o ../chopstx/mcu/usb-stm32f103.c
|
||||
|
||||
regnual.elf: $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
|
||||
regnual-no-vidpid.elf: $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(LDFLAGS) -o regnual-no-vidpid.elf $(OBJS)
|
||||
|
||||
clean:
|
||||
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin *.lst
|
||||
-rm -f $(OBJS) regnual-no-vidpid.elf regnual.elf regnual.hex regnual.bin \
|
||||
*.lst
|
||||
|
||||
distclean: clean
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* regnual.c -- Firmware installation for STM32F103 Flash ROM
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2015, 2016, 2017
|
||||
* Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -26,6 +26,8 @@
|
||||
* ReGNUal
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "usb_lld.h"
|
||||
#include "sys.h"
|
||||
@@ -57,7 +59,9 @@ static const uint8_t regnual_device_desc[] = {
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
#include "../src/usb-vid-pid-ver.c.inc"
|
||||
0x00, 0x00, /* idVendor (will be replaced) */
|
||||
0x00, 0x00, /* idProduct (will be replaced) */
|
||||
0x00, 0x00, /* bcdDevice (will be replaced) */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
@@ -147,19 +151,33 @@ static uint32_t fetch (int i)
|
||||
}
|
||||
|
||||
struct CRC {
|
||||
__IO uint32_t DR;
|
||||
__IO uint8_t IDR;
|
||||
volatile uint32_t DR;
|
||||
volatile uint8_t IDR;
|
||||
uint8_t RESERVED0;
|
||||
uint16_t RESERVED1;
|
||||
__IO uint32_t CR;
|
||||
volatile uint32_t CR;
|
||||
};
|
||||
static struct CRC *const CRC = (struct CRC *)0x40023000;
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
/* ... */
|
||||
};
|
||||
static struct RCC *const RCC = (struct RCC *)0x40021000;
|
||||
#define RCC_AHBENR_CRCEN 0x00000040
|
||||
|
||||
|
||||
#define CRC_CR_RESET 0x01
|
||||
static uint32_t calc_crc32 (void)
|
||||
{
|
||||
struct CRC *CRC = (struct CRC *)0x40023000;
|
||||
int i;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
|
||||
for (i = 0; i < 256/4; i++)
|
||||
|
||||
@@ -3,10 +3,9 @@ typedef unsigned long size_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define NULL 0
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
61
src/Makefile
61
src/Makefile
@@ -5,10 +5,7 @@ PROJECT = gnuk
|
||||
|
||||
CHOPSTX = ../chopstx
|
||||
|
||||
# Define linker script file here
|
||||
LDSCRIPT= gnuk.ld
|
||||
|
||||
CSRC = main.c call-rsa.c mcu-stm32f103.c \
|
||||
CSRC = main.c call-rsa.c \
|
||||
usb_desc.c usb_ctrl.c \
|
||||
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
|
||||
bn.c mod.c \
|
||||
@@ -29,8 +26,17 @@ INCDIR += $(CRYPTINCDIR)
|
||||
|
||||
include config.mk
|
||||
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
USE_ADC = yes
|
||||
USE_EVENTFLAG = yes
|
||||
|
||||
ifeq ($(EMULATION),)
|
||||
DEFS += -DFLASH_UPGRADE_SUPPORT
|
||||
else
|
||||
DEFS += -DBN256_C_IMPLEMENTATION
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_DEBUG),)
|
||||
CSRC += debug.c
|
||||
endif
|
||||
@@ -43,21 +49,21 @@ ifeq ($(ENABLE_PINPAD),dnd)
|
||||
CSRC += usb-msc.c
|
||||
endif
|
||||
|
||||
CHIP=stm32f103
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
USE_ADC = yes
|
||||
ifeq ($(CHIP),stm32f103)
|
||||
CSRC += mcu-stm32f103.c
|
||||
endif
|
||||
|
||||
ifneq ($(USE_DFU),)
|
||||
OBJS_ADD += build/stdaln-sys-bin.o
|
||||
endif
|
||||
|
||||
###################################
|
||||
CROSS = arm-none-eabi-
|
||||
CC = $(CROSS)gcc
|
||||
LD = $(CROSS)gcc
|
||||
OBJCOPY = $(CROSS)objcopy
|
||||
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
#######################
|
||||
include $(CHOPSTX)/rules.mk
|
||||
@@ -70,6 +76,35 @@ sys.c: board.h
|
||||
|
||||
build/bignum.o: OPT = -O3 -g
|
||||
|
||||
build/stdaln-sys.elf: build/sys-$(CHIP).o stdaln-sys.ld
|
||||
@echo
|
||||
$(LD) -v $< $(MCFLAGS) -nostartfiles -Tstdaln-sys.ld -Wl,--no-warn-mismatch,--gc-sections $(LLIBDIR) -o $@
|
||||
|
||||
build/stdaln-sys-bin.o: build/stdaln-sys.elf
|
||||
@echo
|
||||
$(OBJCOPY) -O binary -j .sys $< build/stdaln-sys.bin
|
||||
$(OBJCOPY) -I binary -O default --rename-section .data=.rodata \
|
||||
build/stdaln-sys.bin $@
|
||||
|
||||
distclean: clean
|
||||
-rm -f gnuk.ld config.h board.h config.mk \
|
||||
usb-strings.c.inc usb-vid-pid-ver.c.inc
|
||||
-rm -f gnuk.ld stdaln-sys.ld config.h board.h config.mk \
|
||||
usb-strings.c.inc put-vid-pid-ver.sh
|
||||
|
||||
ifeq ($(EMULATION),)
|
||||
build/gnuk.elf: build/gnuk-no-vidpid.elf binary-edit.sh put-vid-pid-ver.sh
|
||||
cp -p build/gnuk-no-vidpid.elf build/gnuk.elf
|
||||
env FILE="build/gnuk.elf" bash put-vid-pid-ver.sh
|
||||
$(OBJCOPY) -O ihex build/gnuk.elf build/gnuk.hex
|
||||
$(OBJCOPY) -O binary build/gnuk.elf build/gnuk.bin
|
||||
else
|
||||
# By specifying DESTDIR on invocation of "make", you can install
|
||||
# program to different ROOT.
|
||||
|
||||
# The variables prefix, exec_prefix, libexecdir are defined in
|
||||
# config.mk.
|
||||
|
||||
install: build/gnuk
|
||||
test -d "$(DESTDIR)$(libexecdir)" || mkdir -p "$(DESTDIR)$(libexecdir)"
|
||||
install -c build/gnuk "$(DESTDIR)$(libexecdir)"
|
||||
|
||||
endif
|
||||
|
||||
56
src/ac.c
56
src/ac.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ac.c -- Check access condition
|
||||
*
|
||||
* Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -63,7 +63,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw1, int save_ks)
|
||||
{
|
||||
int pw_len;
|
||||
int r1, r2;
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
@@ -73,12 +73,14 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
|
||||
if (ks_pw1 == NULL)
|
||||
{
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
const uint8_t *initial_pw;
|
||||
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|
||||
|| memcmp (pw, initial_pw, pw_len))
|
||||
goto failure;
|
||||
}
|
||||
else
|
||||
@@ -97,21 +99,31 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
|
||||
|
||||
if (access == AC_PSO_CDS_AUTHORIZED)
|
||||
{
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
r2 = 0;
|
||||
}
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
else
|
||||
{
|
||||
int r1, r2;
|
||||
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring);
|
||||
r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring);
|
||||
|
||||
if (r1 < 0 || r2 < 0)
|
||||
r = -1;
|
||||
else if (r1 == 0)
|
||||
{
|
||||
if (r2 == 0)
|
||||
/* No encryption/authentication keys, then, check signing key. */
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
else
|
||||
r = r2;
|
||||
}
|
||||
else if (r2 == 0)
|
||||
r = r1;
|
||||
else
|
||||
r = 1;
|
||||
}
|
||||
|
||||
if (r1 < 0 || r2 < 0
|
||||
|| (r1 == 0 && r2 == 0 && ks_pw1 != NULL
|
||||
&& ((ks_pw1[0] & PW_LEN_KEYSTRING_BIT) == 0
|
||||
|| memcmp (KS_GET_KEYSTRING (ks_pw1),
|
||||
keystring, KEYSTRING_MD_SIZE) != 0)))
|
||||
if (r < 0)
|
||||
{
|
||||
failure:
|
||||
gpg_pw_increment_err_counter (PW_ERR_PW1);
|
||||
@@ -161,7 +173,7 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks, int save_ks)
|
||||
{
|
||||
int pw_len;
|
||||
int r1, r2;
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
@@ -177,12 +189,11 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
if (save_ks)
|
||||
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
|
||||
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
|
||||
r2 = 0;
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
|
||||
|
||||
if (r1 < 0 || r2 < 0)
|
||||
if (r < 0)
|
||||
return -1;
|
||||
else if (r1 == 0 && r2 == 0)
|
||||
else if (r == 0)
|
||||
if ((ks[0] & PW_LEN_KEYSTRING_BIT) == 0
|
||||
|| memcmp (KS_GET_KEYSTRING (ks), keystring, KEYSTRING_MD_SIZE) != 0)
|
||||
return -1;
|
||||
@@ -220,6 +231,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *initial_pw;
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (ks_pw1 != NULL)
|
||||
@@ -237,13 +249,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For the case of empty PW3 (with empty PW1), pass phrase
|
||||
* should be OPENPGP_CARD_INITIAL_PW3
|
||||
* For the case of empty PW3 (with empty PW1), passphrase is
|
||||
* OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO.
|
||||
*/
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw);
|
||||
if ((pw_len_known >=0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
|
||||
|| memcmp (pw, initial_pw, pw_len))
|
||||
goto failure;
|
||||
|
||||
admin_authorized = BY_ADMIN;
|
||||
|
||||
76
src/binary-edit.sh
Normal file
76
src/binary-edit.sh
Normal file
@@ -0,0 +1,76 @@
|
||||
# This is a Bash script to be included.
|
||||
|
||||
# Idx Name Size VMA LMA File off Algn
|
||||
# =================
|
||||
# 2 .text 00004a40 080010f0 080010f0 000110f0 2**4
|
||||
# 08006550 l O .text 00000012 device_desc
|
||||
# =================
|
||||
# VMA =0x080010f0
|
||||
# FOFF=0x000110f0
|
||||
# ADDR=0x08005ad0
|
||||
# file_off_ADDR = ADDR - VMA + FOFF
|
||||
# = 0x08005ad0 - 0x080010f0 + 0x000110f0 = 0x00015ad0
|
||||
|
||||
function calc_addr () {
|
||||
local line_sym="" VMA FOFF ADDR
|
||||
|
||||
arm-none-eabi-objdump -h -t -j .text $FILE | \
|
||||
egrep -e '(^ +[0-9] +\.text +|device_desc)' | \
|
||||
while read -r F0 F1 F2 F3 F4 F5 F6; do
|
||||
if [ -z "$line_sym" ]; then
|
||||
VMA=$F3
|
||||
FOFF=$F5
|
||||
line_sym="next is a line for the symbol"
|
||||
else
|
||||
ADDR=$F0
|
||||
echo "$((0x$ADDR - 0x$VMA + 0x$FOFF))"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
declare -a OFFSETS
|
||||
OFFSETS=($(calc_addr))
|
||||
file_off_ADDR=${OFFSETS[0]}
|
||||
file_off_fraucheky_ADDR=${OFFSETS[1]}
|
||||
|
||||
echo "Offset is $file_off_ADDR"
|
||||
if [ -n "$file_off_fraucheky_ADDR" ]; then
|
||||
echo "Offset is $file_off_fraucheky_ADDR"
|
||||
fi
|
||||
|
||||
function replace_file_byte_at () {
|
||||
printf "\x$1" | dd of=$FILE bs=1 seek=$2 conv=notrunc >& /dev/null
|
||||
}
|
||||
|
||||
#
|
||||
# vid_lsb: 8
|
||||
# vid_msb: 9
|
||||
# pid_lsb: 10
|
||||
# pid_msb: 11
|
||||
# bcd_device_lsb: 12
|
||||
# bcd_device_msb: 13
|
||||
#
|
||||
|
||||
function replace_vid_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 8))
|
||||
}
|
||||
|
||||
function replace_vid_msb () {
|
||||
replace_file_byte_at $1 $((addr + 9))
|
||||
}
|
||||
|
||||
function replace_pid_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 10))
|
||||
}
|
||||
|
||||
function replace_pid_msb () {
|
||||
replace_file_byte_at $1 $((addr + 11))
|
||||
}
|
||||
|
||||
function replace_bcd_device_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 12))
|
||||
}
|
||||
|
||||
function replace_bcd_device_msb () {
|
||||
replace_file_byte_at $1 $((addr + 13))
|
||||
}
|
||||
23
src/bn.c
23
src/bn.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* bn.c -- 256-bit (and 512-bit) bignum calculation
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2013, 2014, 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -412,17 +413,15 @@ bn256_cmp (const bn256 *A, const bn256 *B)
|
||||
void
|
||||
bn256_random (bn256 *X)
|
||||
{
|
||||
const uint8_t *rand = random_bytes_get ();
|
||||
int i, j;
|
||||
const uint8_t *rand;
|
||||
|
||||
X->word[7] = ((uint32_t *)rand)[7];
|
||||
X->word[6] = ((uint32_t *)rand)[6];
|
||||
X->word[5] = ((uint32_t *)rand)[5];
|
||||
X->word[4] = ((uint32_t *)rand)[4];
|
||||
X->word[3] = ((uint32_t *)rand)[3];
|
||||
X->word[2] = ((uint32_t *)rand)[2];
|
||||
X->word[1] = ((uint32_t *)rand)[1];
|
||||
X->word[0] = ((uint32_t *)rand)[0];
|
||||
|
||||
random_bytes_free (rand);
|
||||
for (i = 0; i < 256/256; i++)
|
||||
{
|
||||
rand = random_bytes_get ();
|
||||
for (j = 0; j < BN256_WORDS; j++)
|
||||
X->word[i*BN256_WORDS+j] = ((uint32_t *)rand)[j];
|
||||
random_bytes_free (rand);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
|
||||
*
|
||||
* Copyright (C) 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2013, 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -54,28 +54,21 @@ FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
FUNC(ecc_compute_public) (const uint8_t *key_data)
|
||||
int
|
||||
FUNC(ecc_compute_public) (const uint8_t *key_data, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p0, *p, *p1;
|
||||
uint8_t *p, *p1;
|
||||
ac q[1];
|
||||
bn256 k[1];
|
||||
int i;
|
||||
|
||||
p0 = (uint8_t *)malloc (ECDSA_BYTE_SIZE * 2);
|
||||
if (p0 == NULL)
|
||||
return NULL;
|
||||
|
||||
p = (uint8_t *)k;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
|
||||
if (FUNC(compute_kG) (q, k) < 0)
|
||||
{
|
||||
free (p0);
|
||||
return NULL;
|
||||
}
|
||||
return -1;
|
||||
|
||||
p = p0;
|
||||
p = pubkey;
|
||||
p1 = (uint8_t *)q->x;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
|
||||
@@ -83,7 +76,7 @@ FUNC(ecc_compute_public) (const uint8_t *key_data)
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
|
||||
|
||||
return p0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* call-ec_p256k1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256k1)
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* call-ec_p256r1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256r1)
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2017
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <chopstx.h>
|
||||
|
||||
#include "config.h"
|
||||
@@ -41,7 +40,7 @@ static struct chx_cleanup clp;
|
||||
static void
|
||||
rsa_cleanup (void *arg)
|
||||
{
|
||||
free (arg);
|
||||
(void)arg;
|
||||
rsa_free (&rsa_ctx);
|
||||
}
|
||||
|
||||
@@ -111,30 +110,23 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
/*
|
||||
* LEN: length in byte
|
||||
*/
|
||||
uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
int
|
||||
modulus_calc (const uint8_t *p, int len, uint8_t *pubkey)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
int ret;
|
||||
|
||||
modulus = malloc (len);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P); mpi_init (&Q); mpi_init (&N);
|
||||
MPI_CHK( mpi_read_binary (&P, p, len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
|
||||
MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
|
||||
MPI_CHK( mpi_write_binary (&N, modulus, len) );
|
||||
MPI_CHK( mpi_write_binary (&N, pubkey, len) );
|
||||
cleanup:
|
||||
mpi_free (&P); mpi_free (&Q); mpi_free (&N);
|
||||
if (ret != 0)
|
||||
{
|
||||
free (modulus);
|
||||
return NULL;
|
||||
}
|
||||
return modulus;
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +136,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int ret;
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
size_t output_len;
|
||||
#endif
|
||||
|
||||
DEBUG_INFO ("RSA decrypt:");
|
||||
DEBUG_WORD ((uint32_t)&ret);
|
||||
@@ -179,9 +174,16 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
clp.arg = NULL;
|
||||
chopstx_cleanup_push (&clp);
|
||||
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, &output_len, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
*output_len_p = (unsigned int)output_len;
|
||||
#else
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, output_len_p, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
#endif
|
||||
chopstx_setcancelstate (cs);
|
||||
chopstx_cleanup_pop (0);
|
||||
}
|
||||
@@ -234,45 +236,39 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
|
||||
|
||||
#define RSA_EXPONENT 0x10001
|
||||
|
||||
uint8_t *
|
||||
rsa_genkey (int pubkey_len)
|
||||
int
|
||||
rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q)
|
||||
{
|
||||
int ret;
|
||||
uint8_t index = 0;
|
||||
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
|
||||
uint8_t *p = p_q_modulus;
|
||||
uint8_t *q = p_q_modulus + pubkey_len / 2;
|
||||
uint8_t *modulus = p_q_modulus + pubkey_len;
|
||||
uint8_t *p = p_q;
|
||||
uint8_t *q = p_q + pubkey_len / 2;
|
||||
int cs;
|
||||
|
||||
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng);
|
||||
extern void neug_flush (void);
|
||||
|
||||
if (p_q_modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
neug_flush ();
|
||||
prng_seed (random_gen, &index);
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
clp.next = NULL;
|
||||
clp.routine = rsa_cleanup;
|
||||
clp.arg = (void *)p_q_modulus;
|
||||
clp.arg = NULL;
|
||||
chopstx_cleanup_push (&clp);
|
||||
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
|
||||
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
|
||||
RSA_EXPONENT) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
|
||||
clp.arg = NULL;
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
|
||||
|
||||
cleanup:
|
||||
chopstx_setcancelstate (cs);
|
||||
chopstx_cleanup_pop (1);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
return -1;
|
||||
else
|
||||
return p_q_modulus;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
#define ENABLE_VIRTUAL_COM_PORT 1
|
||||
#endif
|
||||
@DFU_DEFINE@
|
||||
@ORIGIN_DEFINE@
|
||||
@ORIGIN_REAL_DEFINE@
|
||||
@PINPAD_DEFINE@
|
||||
@PINPAD_MORE_DEFINE@
|
||||
@CERTDO_DEFINE@
|
||||
@HID_CARD_CHANGE_DEFINE@
|
||||
@SERIALNO_STR_LEN_DEFINE@
|
||||
@LIFE_CYCLE_MANAGEMENT_DEFINE@
|
||||
@ACKBTN_DEFINE@
|
||||
@SERIALNO_STR_LEN_DEFINE@
|
||||
@KDF_DO_REQUIRED_DEFINE@
|
||||
|
||||
257
src/configure
vendored
257
src/configure
vendored
@@ -6,10 +6,11 @@ nl=$'\n'
|
||||
#
|
||||
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
|
||||
#
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2021
|
||||
# Free Software Initiative of Japan
|
||||
#
|
||||
# This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
#
|
||||
# Gnuk is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -43,7 +44,13 @@ pinpad=no
|
||||
certdo=no
|
||||
hid_card_change=no
|
||||
factory_reset=no
|
||||
ackbtn_support=yes
|
||||
flash_override=""
|
||||
kdf_do=${kdf_do:-optional}
|
||||
# For emulation
|
||||
prefix=/usr/local
|
||||
exec_prefix='${prefix}'
|
||||
libexecdir='${exec_prefix}/libexec'
|
||||
|
||||
# Revision number
|
||||
if test -e ../.git; then
|
||||
@@ -100,6 +107,15 @@ for option; do
|
||||
with_dfu=yes ;;
|
||||
--without-dfu)
|
||||
with_dfu=no ;;
|
||||
#
|
||||
# For emulation
|
||||
#
|
||||
--prefix=*)
|
||||
prefix=optarg ;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=optarg ;;
|
||||
--libexecdir=*)
|
||||
libexecdir=optarg ;;
|
||||
*)
|
||||
echo "Unrecognized option \`$option'" >&2
|
||||
echo "Try \`$0 --help' for more information." >&2
|
||||
@@ -121,17 +137,21 @@ Configuration:
|
||||
supported targets are:
|
||||
FST_01
|
||||
FST_01G
|
||||
FST_01SZ
|
||||
OLIMEX_STM32_H103
|
||||
MAPLE_MINI
|
||||
ST_DONGLE
|
||||
ST_NUCLEO_F103
|
||||
NITROKEY_START
|
||||
BLUE_PILL
|
||||
STM8S_DISCOVERY
|
||||
CQ_STARM
|
||||
STM32_PRIMER2
|
||||
STBEE
|
||||
STBEE_MINI
|
||||
FST_01_00 (unreleased version with 8MHz XTAL)
|
||||
--enable-factory-reset
|
||||
support life cycle management [no]
|
||||
--enable-debug debug with virtual COM port [no]
|
||||
--enable-pinpad=cir
|
||||
PIN entry support [no]
|
||||
@@ -141,22 +161,17 @@ Configuration:
|
||||
--disable-sys1-compat disable SYS 1.0 compatibility [no]
|
||||
executable is target independent
|
||||
but requires SYS 2.0 or newer
|
||||
--enable-factory-reset
|
||||
support life cycle management [no]
|
||||
--with-dfu build image for DFU [<target specific>]
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test "$vidpid" = "none"; then
|
||||
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BOARD_HEADER_FILE=board-$(echo $target | tr '_[:upper:]' '-[:lower:]').h
|
||||
echo "Header file is: $BOARD_HEADER_FILE"
|
||||
ln -sf "../chopstx/board/$BOARD_HEADER_FILE" board.h
|
||||
|
||||
# Frequency
|
||||
MHZ=72
|
||||
# Flash page size in byte
|
||||
FLASH_PAGE_SIZE=1024
|
||||
# Flash memory size in KiB
|
||||
@@ -166,8 +181,10 @@ MEMORY_SIZE=20
|
||||
|
||||
# Settings for TARGET
|
||||
case $target in
|
||||
BLUE_PILL)
|
||||
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB" ;;
|
||||
BLUE_PILL|STM8S_DISCOVERY)
|
||||
# It's 64KB version of STM32F103, but actually has 128KB
|
||||
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB=128"
|
||||
;;
|
||||
CQ_STARM|STBEE_MINI)
|
||||
if test "$with_dfu" = "default"; then
|
||||
with_dfu=yes;
|
||||
@@ -184,13 +201,57 @@ STBEE)
|
||||
if test "$with_dfu" = "default"; then
|
||||
with_dfu=yes;
|
||||
fi ;;
|
||||
STM8S_DISCOVERY)
|
||||
FLASH_SIZE=64
|
||||
BLUE_PILL_G)
|
||||
MHZ=96
|
||||
;;
|
||||
FST_01SZ)
|
||||
MHZ=96
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
def_mhz="-DMHZ=$MHZ"
|
||||
if test "$target" = "GNU_LINUX"; then
|
||||
ldscript=""
|
||||
chip="gnu-linux"
|
||||
arch="gnu-linux"
|
||||
emulation="yes"
|
||||
cross=""
|
||||
mcu="none"
|
||||
kdf_do=${kdf_do:-required}
|
||||
def_emulation="-DGNU_LINUX_EMULATION"
|
||||
def_memory_size="-DMEMORY_SIZE=1024"
|
||||
enable_hexoutput=""
|
||||
libs="-lpthread"
|
||||
else
|
||||
ldscript="gnuk.ld"
|
||||
chip="stm32f103"
|
||||
arch="cortex-m"
|
||||
emulation=""
|
||||
cross="arm-none-eabi-"
|
||||
mcu="cortex-m3"
|
||||
def_emulation=""
|
||||
def_memory_size="-DMEMORY_SIZE=$MEMORY_SIZE"
|
||||
enable_hexoutput=yes
|
||||
libs=""
|
||||
fi
|
||||
|
||||
if test "$emulation" = "yes"; then
|
||||
if test "$vidpid" = "none"; then
|
||||
vidpid=0000:0000
|
||||
else
|
||||
echo "Please don't specify VID:PID for emulation at compile time;"
|
||||
echo "It is a user who should specify VID:PID at run time."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if test "$vidpid" = "none"; then
|
||||
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# --enable-debug option
|
||||
if test "$debug" = "yes"; then
|
||||
DEBUG_MAKE_OPTION="ENABLE_DEBUG=1"
|
||||
@@ -202,6 +263,8 @@ else
|
||||
echo "Debug option disabled"
|
||||
fi
|
||||
|
||||
ORIGIN_REAL=0x08000000
|
||||
ORIGIN_REAL_DEFINE="#define ORIGIN_REAL $ORIGIN_REAL"
|
||||
# --with-dfu option
|
||||
if test "$with_dfu" = "yes"; then
|
||||
if test "$target" = "FST_01" -o "$target" = "FST_01G" \
|
||||
@@ -210,22 +273,25 @@ if test "$with_dfu" = "yes"; then
|
||||
exit 1
|
||||
fi
|
||||
echo "Configured for DFU"
|
||||
ORIGIN=0x08003000
|
||||
FLASH_SIZE=$((FLASH_SIZE - 12))
|
||||
if test "$target" = "MAPLE_MINI"; then
|
||||
# Note that the default bootloader is too large, need for instance
|
||||
# STM32duino for DFU on Maple Mini
|
||||
ORIGIN=0x08002000
|
||||
FLASH_SIZE=$((FLASH_SIZE - 8))
|
||||
else
|
||||
ORIGIN=0x08003000
|
||||
FLASH_SIZE=$((FLASH_SIZE - 12))
|
||||
fi
|
||||
DFU_DEFINE="#define DFU_SUPPORT 1"
|
||||
HEXOUTPUT_MAKE_OPTION="ENABLE_OUTPUT_HEX=yes"
|
||||
else
|
||||
with_dfu=no
|
||||
echo "Configured for bare system (no-DFU)"
|
||||
ORIGIN=0x08000000
|
||||
ORIGIN=${ORIGIN_REAL}
|
||||
DFU_DEFINE="#undef DFU_SUPPORT"
|
||||
HEXOUTPUT_MAKE_OPTION=""
|
||||
fi
|
||||
ORIGIN_DEFINE="#define ORIGIN $ORIGIN"
|
||||
|
||||
# --enable-pinpad option
|
||||
MSC_SIZE="0"
|
||||
TIM_SIZE="0"
|
||||
EXT_SIZE="0"
|
||||
if test "$pinpad" = "no"; then
|
||||
PINPAD_MAKE_OPTION="# ENABLE_PINPAD="
|
||||
PINPAD_DEFINE="#undef PINPAD_SUPPORT"
|
||||
@@ -236,12 +302,6 @@ else
|
||||
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
||||
PINPAD_MORE_DEFINE="#define PINPAD_${pinpad^^[a-z]}_SUPPORT 1"
|
||||
echo "PIN pad option enabled ($pinpad)"
|
||||
if test "$pinpad" = "dnd"; then
|
||||
MSC_SIZE="0x0200"
|
||||
elif test "$pinpad" = "cir"; then
|
||||
TIM_SIZE="0x00c0"
|
||||
EXT_SIZE="0x00c0"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --enable-certdo option
|
||||
@@ -271,6 +331,23 @@ else
|
||||
echo "Life cycle management is NOT supported"
|
||||
fi
|
||||
|
||||
# Acknowledge button support
|
||||
if test "$ackbtn_support" = "yes"; then
|
||||
ACKBTN_DEFINE="#define ACKBTN_SUPPORT 1"
|
||||
echo "Acknowledge button is supported"
|
||||
else
|
||||
ACKBTN_DEFINE="#undef ACKBTN_SUPPORT"
|
||||
echo "Acknowledge button is not supported"
|
||||
fi
|
||||
|
||||
# KDF Data Object is always required for GNU/Linux emulation
|
||||
if test "$kdf_do" = "required"; then
|
||||
KDF_DO_REQUIRED_DEFINE="#define KDF_DO_REQUIRED 1"
|
||||
echo "KDF DO is required before key import/generation"
|
||||
else
|
||||
KDF_DO_REQUIRED_DEFINE="#undef KDF_DO_REQUIRED"
|
||||
fi
|
||||
|
||||
### !!! Replace following string of "FSIJ" to yours !!! ####
|
||||
SERIALNO="FSIJ-$(sed -e 's%^[^/]*/%%' <../VERSION)-"
|
||||
|
||||
@@ -278,7 +355,7 @@ SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
|
||||
|
||||
|
||||
if test "$sys1_compat" = "yes"; then
|
||||
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo"
|
||||
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
|
||||
else
|
||||
if test "$with_dfu" = "yes"; then
|
||||
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
|
||||
@@ -288,53 +365,82 @@ else
|
||||
FLASH_PAGE_SIZE=2048
|
||||
FLASH_SIZE=128
|
||||
MEMORY_SIZE=20
|
||||
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo"
|
||||
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
|
||||
fi
|
||||
|
||||
output_vid_pid_version () {
|
||||
echo "$VIDPID" | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\\${nl} 0x\4, 0x\3, /* idProduct */%p"
|
||||
echo "$VERSION" | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
|
||||
echo "$VIDPID" | \
|
||||
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2\t\3\t\4%p" | \
|
||||
while read -r FIRST SECOND THIRD FOURTH; do
|
||||
if test $FIRST != 00; then
|
||||
echo replace_vid_msb $FIRST
|
||||
fi
|
||||
if test $SECOND != 00; then
|
||||
echo replace_vid_lsb $SECOND
|
||||
fi
|
||||
if test $THIRD != 00; then
|
||||
echo replace_pid_msb $THIRD
|
||||
fi
|
||||
if test $FOURTH != 00; then
|
||||
echo replace_pid_lsb $FOURTH
|
||||
fi
|
||||
done
|
||||
echo "$VERSION" | \
|
||||
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2%p" | \
|
||||
while read -r FIRST SECOND; do
|
||||
if test $FIRST != 00; then
|
||||
echo replace_bcd_device_msb $FIRST
|
||||
fi
|
||||
if test $SECOND != 00; then
|
||||
echo replace_bcd_device_lsb $SECOND
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
output_vendor_product_serial_strings () {
|
||||
prefix=$1
|
||||
name=$1
|
||||
|
||||
echo "static const uint8_t ${prefix}string_vendor[] = {"
|
||||
echo " ${#VENDOR}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}string_vendor[] = {"
|
||||
echo " ${#VENDOR}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Manufacturer: \"$VENDOR\" */"
|
||||
echo "$VENDOR" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
echo
|
||||
echo "static const uint8_t ${prefix}string_product[] = {"
|
||||
echo " ${#PRODUCT}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}string_product[] = {"
|
||||
echo " ${#PRODUCT}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Product name: \"$PRODUCT\" */"
|
||||
echo "$PRODUCT" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
|
||||
if test -n "$prefix"; then
|
||||
if test -n "$name"; then
|
||||
echo
|
||||
echo "const uint8_t ${prefix}string_serial[] = {"
|
||||
echo " ${#SERIALNO}*2+2+16, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo "const uint8_t ${name}string_serial[] = {"
|
||||
echo " ${#SERIALNO}*2+2+16, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Serial number: \"$SERIALNO\" */"
|
||||
echo "$SERIALNO" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
if test "$emulation" = "yes"; then
|
||||
echo " 'E', 0, 'M', 0, 'U', 0, 'L', 0,"
|
||||
echo " 'A', 0, 'T', 0, 'E', 0, 'D', 0,"
|
||||
else
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
fi
|
||||
echo '};'
|
||||
echo
|
||||
echo '#ifdef USB_STRINGS_FOR_GNUK'
|
||||
echo "static const uint8_t ${prefix}revision_detail[] = {"
|
||||
echo " ${#REVISION}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}revision_detail[] = {"
|
||||
echo " ${#REVISION}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* revision detail: \"$REVISION\" */"
|
||||
echo "$REVISION" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
echo
|
||||
echo "static const uint8_t ${prefix}config_options[] = {"
|
||||
echo " ${#CONFIG}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}config_options[] = {"
|
||||
echo " ${#CONFIG}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* configure options: \"$CONFIG\" */"
|
||||
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
@@ -342,16 +448,22 @@ output_vendor_product_serial_strings () {
|
||||
fi
|
||||
}
|
||||
|
||||
if ! (IFS=" "
|
||||
(echo "#! /bin/bash"
|
||||
echo
|
||||
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
|
||||
|
||||
if !(IFS=" "
|
||||
while read -r VIDPID VERSION PRODUCT VENDOR; do
|
||||
if test "$vidpid" = "$VIDPID"; then
|
||||
output_vid_pid_version > usb-vid-pid-ver.c.inc
|
||||
echo >> put-vid-pid-ver.sh
|
||||
echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
|
||||
output_vid_pid_version >> put-vid-pid-ver.sh
|
||||
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
|
||||
exit 0
|
||||
fi
|
||||
done; exit 1) < ../GNUK_USB_DEVICE_ID
|
||||
then
|
||||
echo "Please specify valid Vendor ID and Product ID." >&2
|
||||
echo "Please specify valid Vendor ID and Product ID." >&2
|
||||
echo "Check ../GNUK_USB_DEVICE_ID." >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -368,38 +480,57 @@ else
|
||||
fi
|
||||
|
||||
|
||||
echo -e "DEFS=$use_sys3 $flash_override" '\n' \
|
||||
"$DEBUG_MAKE_OPTION" '\n' \
|
||||
"$PINPAD_MAKE_OPTION" '\n' \
|
||||
"$HEXOUTPUT_MAKE_OPTION" \
|
||||
> config.mk
|
||||
(echo "CHIP=$chip";
|
||||
echo "ARCH=$arch";
|
||||
echo "EMULATION=$emulation";
|
||||
echo "CROSS=$cross";
|
||||
echo "MCU=$mcu";
|
||||
echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size $def_mhz";
|
||||
echo "LDSCRIPT=$ldscript";
|
||||
echo "LIBS=$libs";
|
||||
echo "$DEBUG_MAKE_OPTION";
|
||||
echo "$PINPAD_MAKE_OPTION";
|
||||
echo "ENABLE_FRAUCHEKY=$enable_fraucheky";
|
||||
echo "ENABLE_OUTPUT_HEX=$enable_hexoutput"
|
||||
if test "$ackbtn_support" = "yes"; then
|
||||
echo "USE_ACKBTN=yes"
|
||||
fi
|
||||
if test "$with_dfu" = "yes"; then
|
||||
echo "USE_DFU=yes"
|
||||
fi
|
||||
if test "$emulation" = "yes"; then
|
||||
echo "prefix=$prefix"
|
||||
echo "exec_prefix=$exec_prefix"
|
||||
echo "libexecdir=$libexecdir"
|
||||
fi
|
||||
) > config.mk
|
||||
|
||||
if test "$certdo" = "yes"; then
|
||||
sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \
|
||||
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
|
||||
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
||||
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
|
||||
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
|
||||
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
|
||||
< gnuk.ld.in > gnuk.ld
|
||||
else
|
||||
sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \
|
||||
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
|
||||
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
||||
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
|
||||
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
|
||||
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
|
||||
< gnuk.ld.in > gnuk.ld
|
||||
fi
|
||||
sed -e "s/@ORIGIN_REAL@/$ORIGIN_REAL/" -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
< stdaln-sys.ld.in > stdaln-sys.ld
|
||||
sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
|
||||
-e "s/@DFU_DEFINE@/$DFU_DEFINE/" \
|
||||
-e "s/@ORIGIN_DEFINE@/$ORIGIN_DEFINE/" \
|
||||
-e "s/@ORIGIN_REAL_DEFINE@/$ORIGIN_REAL_DEFINE/" \
|
||||
-e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \
|
||||
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \
|
||||
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
|
||||
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_DEFINE/" \
|
||||
-e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
|
||||
-e "s/@ACKBTN_DEFINE@/$ACKBTN_DEFINE/" \
|
||||
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
|
||||
-e "s/@KDF_DO_REQUIRED_DEFINE@/$KDF_DO_REQUIRED_DEFINE/" \
|
||||
< config.h.in > config.h
|
||||
exit 0
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
/*
|
||||
* a = 0, b = 7
|
||||
*/
|
||||
#if 0
|
||||
static const bn256 coefficient_a[1] = {
|
||||
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
};
|
||||
#endif
|
||||
|
||||
static const bn256 coefficient_b[1] = {
|
||||
{{ 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* ecc-edwards.c - Elliptic curve computation for
|
||||
* the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
@@ -708,7 +707,7 @@ eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
|
||||
{
|
||||
ac R[1];
|
||||
@@ -730,18 +729,10 @@ eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
eddsa_compute_public_25519 (const uint8_t *kd)
|
||||
void
|
||||
eddsa_compute_public_25519 (const uint8_t *kd, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p0;
|
||||
const bn256 *a = (const bn256 *)kd;
|
||||
|
||||
p0 = (uint8_t *)malloc (sizeof (bn256));
|
||||
if (p0 == NULL)
|
||||
return NULL;
|
||||
|
||||
eddsa_public_key_25519 ((bn256 *)p0, a);
|
||||
return p0;
|
||||
eddsa_public_key_25519 ((bn256 *)pubkey, (const bn256 *)kd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* ecc-mont.c - Elliptic curve computation for
|
||||
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
|
||||
*
|
||||
* Copyright (C) 2014, 2015 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2015, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "bn.h"
|
||||
#include "mod25638.h"
|
||||
#include "mod.h"
|
||||
@@ -198,22 +197,17 @@ compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
ecdh_compute_public_25519 (const uint8_t *key_data)
|
||||
void
|
||||
ecdh_compute_public_25519 (const uint8_t *key_data, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p;
|
||||
bn256 gx[1];
|
||||
bn256 k[1];
|
||||
|
||||
memset (gx, 0, sizeof (bn256));
|
||||
gx[0].word[0] = 9; /* Gx = 9 */
|
||||
memcpy (k, key_data, sizeof (bn256));
|
||||
p = (uint8_t *)malloc (sizeof (bn256));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
compute_nQ ((bn256 *)p, k, gx);
|
||||
return p;
|
||||
compute_nQ ((bn256 *)pubkey, k, gx);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
146
src/flash.c
146
src/flash.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -53,33 +53,40 @@
|
||||
* <alignment to page>
|
||||
* ch_certificate_startp
|
||||
* <2048 bytes>
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
* _keystore_pool
|
||||
* Three flash pages for keystore
|
||||
* a page contains a key data of:
|
||||
* For RSA-2048: 512-byte (p, q and N)
|
||||
* For RSA-4096: 1024-byte (p, q and N)
|
||||
* For ECDSA/ECDH and EdDSA, there are padding after public key
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
*/
|
||||
|
||||
#define FLASH_DATA_POOL_HEADER_SIZE 2
|
||||
#define FLASH_DATA_POOL_SIZE (flash_page_size*2)
|
||||
|
||||
static uint16_t flash_page_size;
|
||||
|
||||
static const uint8_t *data_pool;
|
||||
extern uint8_t _keystore_pool;
|
||||
|
||||
static uint8_t *last_p;
|
||||
|
||||
/* The first halfword is generation for the data page (little endian) */
|
||||
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
const uint8_t flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
0x00, 0x00, 0xff, 0xff
|
||||
};
|
||||
|
||||
/* Linker set this symbol */
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
extern uint8_t *flash_addr_key_storage_start;
|
||||
extern uint8_t *flash_addr_data_storage_start;
|
||||
#define FLASH_ADDR_KEY_STORAGE_START flash_addr_key_storage_start
|
||||
#define FLASH_ADDR_DATA_STORAGE_START flash_addr_data_storage_start
|
||||
#else
|
||||
/* Linker sets these symbols */
|
||||
extern uint8_t _keystore_pool;
|
||||
extern uint8_t _data_pool;
|
||||
#define FLASH_ADDR_KEY_STORAGE_START ((&_keystore_pool))
|
||||
#define FLASH_ADDR_DATA_STORAGE_START ((&_data_pool))
|
||||
#endif
|
||||
|
||||
static int key_available_at (const uint8_t *k, int key_size)
|
||||
{
|
||||
@@ -103,18 +110,20 @@ static int key_available_at (const uint8_t *k, int key_size)
|
||||
|
||||
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
||||
void
|
||||
flash_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
|
||||
flash_do_storage_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
|
||||
{
|
||||
uint16_t gen0, gen1;
|
||||
uint16_t *gen0_p = (uint16_t *)&_data_pool;
|
||||
uint16_t *gen0_p = (uint16_t *)FLASH_ADDR_DATA_STORAGE_START;
|
||||
uint16_t *gen1_p;
|
||||
|
||||
flash_page_size = 1024;
|
||||
#if !defined (GNU_LINUX_EMULATION)
|
||||
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
|
||||
flash_page_size = 2048;
|
||||
#endif
|
||||
|
||||
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
|
||||
data_pool = &_data_pool;
|
||||
gen1_p = (uint16_t *)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size);
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
|
||||
/* Check data pool generation and choose the page */
|
||||
gen0 = *gen0_p;
|
||||
@@ -129,13 +138,13 @@ flash_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
|
||||
|
||||
if (gen0 == 0xffff)
|
||||
/* Use another page if a page is erased. */
|
||||
data_pool = &_data_pool + flash_page_size;
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
else if (gen1 == 0xffff)
|
||||
/* Or use different page if another page is erased. */
|
||||
data_pool = &_data_pool;
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0)
|
||||
/* When both pages have valid header, use newer page. */
|
||||
data_pool = &_data_pool + flash_page_size;
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
|
||||
*p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
*p_do_end = data_pool + flash_page_size;
|
||||
@@ -148,34 +157,40 @@ flash_terminate (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
const uint8_t *p;
|
||||
|
||||
p = gpg_get_firmware_update_key (0);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
#endif
|
||||
for (i = 0; i < 3; i++)
|
||||
flash_erase_page ((uint32_t)flash_key_getpage (i));
|
||||
flash_erase_page ((uint32_t)&_data_pool);
|
||||
flash_erase_page ((uint32_t)(&_data_pool + flash_page_size));
|
||||
data_pool = &_data_pool;
|
||||
last_p = &_data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
flash_erase_page ((uintptr_t)flash_key_getpage (i));
|
||||
flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START);
|
||||
flash_erase_page ((uintptr_t)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size));
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
last_p = FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
flash_erase_page ((uint32_t)&ch_certificate_start);
|
||||
flash_erase_page ((uintptr_t)&ch_certificate_start);
|
||||
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
|
||||
flash_erase_page ((uint32_t)(&ch_certificate_start + flash_page_size));
|
||||
flash_erase_page ((uintptr_t)(&ch_certificate_start + flash_page_size));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
flash_activate (void)
|
||||
{
|
||||
flash_program_halfword ((uint32_t)&_data_pool, 0);
|
||||
flash_program_halfword ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flash_init_keys (void)
|
||||
flash_key_storage_init (void)
|
||||
{
|
||||
const uint8_t *p;
|
||||
int i;
|
||||
|
||||
/* For each key, find its address. */
|
||||
p = &_keystore_pool;
|
||||
p = FLASH_ADDR_KEY_STORAGE_START;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
const uint8_t *k;
|
||||
@@ -233,15 +248,15 @@ flash_copying_gc (void)
|
||||
uint8_t *src, *dst;
|
||||
uint16_t generation;
|
||||
|
||||
if (data_pool == &_data_pool)
|
||||
if (data_pool == FLASH_ADDR_DATA_STORAGE_START)
|
||||
{
|
||||
src = &_data_pool;
|
||||
dst = &_data_pool + flash_page_size;
|
||||
src = FLASH_ADDR_DATA_STORAGE_START;
|
||||
dst = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = &_data_pool + flash_page_size;
|
||||
dst = &_data_pool;
|
||||
src = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
dst = FLASH_ADDR_DATA_STORAGE_START;
|
||||
}
|
||||
|
||||
generation = *(uint16_t *)src;
|
||||
@@ -251,8 +266,8 @@ flash_copying_gc (void)
|
||||
generation = 0;
|
||||
else
|
||||
generation++;
|
||||
flash_program_halfword ((uint32_t)dst, generation);
|
||||
flash_erase_page ((uint32_t)src);
|
||||
flash_program_halfword ((uintptr_t)dst, generation);
|
||||
flash_erase_page ((uintptr_t)src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -282,10 +297,10 @@ void
|
||||
flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len)
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)p;
|
||||
addr = (uintptr_t)p;
|
||||
hw = nr | (len << 8);
|
||||
if (flash_program_halfword (addr, hw) != 0)
|
||||
flash_warning ("DO WRITE ERROR");
|
||||
@@ -338,13 +353,14 @@ flash_warning (const char *msg)
|
||||
void
|
||||
flash_do_release (const uint8_t *do_data)
|
||||
{
|
||||
uint32_t addr = (uint32_t)do_data - 1;
|
||||
uint32_t addr_tag = addr;
|
||||
uintptr_t addr = (uintptr_t)do_data - 1;
|
||||
uintptr_t addr_tag = addr;
|
||||
int i;
|
||||
int len = do_data[0];
|
||||
|
||||
/* Don't filling zero for data in code (such as ds_count_initial_value) */
|
||||
if (do_data < &_data_pool || do_data > &_data_pool + FLASH_DATA_POOL_SIZE)
|
||||
if (do_data < FLASH_ADDR_DATA_STORAGE_START
|
||||
|| do_data > FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_SIZE)
|
||||
return;
|
||||
|
||||
addr += 2;
|
||||
@@ -373,7 +389,7 @@ static uint8_t *
|
||||
flash_key_getpage (enum kind_of_key kk)
|
||||
{
|
||||
/* There is a page for each KK. */
|
||||
return &_keystore_pool + (flash_page_size * kk);
|
||||
return FLASH_ADDR_KEY_STORAGE_START + (flash_page_size * kk);
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
@@ -407,10 +423,10 @@ flash_key_write (uint8_t *key_addr,
|
||||
const uint8_t *pubkey, int pubkey_len)
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)key_addr;
|
||||
addr = (uintptr_t)key_addr;
|
||||
for (i = 0; i < key_data_len/2; i ++)
|
||||
{
|
||||
hw = key_data[i*2] | (key_data[i*2+1]<<8);
|
||||
@@ -433,7 +449,7 @@ flash_key_write (uint8_t *key_addr,
|
||||
static int
|
||||
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
|
||||
{
|
||||
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
|
||||
uintptr_t start = (uintptr_t)key_addr & ~(flash_page_size - 1);
|
||||
const uint32_t *p = (const uint32_t *)start;
|
||||
|
||||
while (p < (const uint32_t *)(start + flash_page_size))
|
||||
@@ -452,7 +468,7 @@ static void
|
||||
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
int i;
|
||||
uint32_t addr = (uint32_t)key_addr;
|
||||
uintptr_t addr = (uintptr_t)key_addr;
|
||||
|
||||
for (i = 0; i < key_size/2; i++)
|
||||
flash_program_halfword (addr + i*2, 0);
|
||||
@@ -462,7 +478,7 @@ void
|
||||
flash_key_release (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
if (flash_check_all_other_keys_released (key_addr, key_size))
|
||||
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
|
||||
flash_erase_page (((uintptr_t)key_addr & ~(flash_page_size - 1)));
|
||||
else
|
||||
flash_key_fill_zero_as_released (key_addr, key_size);
|
||||
}
|
||||
@@ -470,12 +486,12 @@ flash_key_release (uint8_t *key_addr, int key_size)
|
||||
void
|
||||
flash_key_release_page (enum kind_of_key kk)
|
||||
{
|
||||
flash_erase_page ((uint32_t)flash_key_getpage (kk));
|
||||
flash_erase_page ((uintptr_t)flash_key_getpage (kk));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flash_clear_halfword (uint32_t addr)
|
||||
flash_clear_halfword (uintptr_t addr)
|
||||
{
|
||||
flash_program_halfword (addr, 0);
|
||||
}
|
||||
@@ -484,7 +500,7 @@ flash_clear_halfword (uint32_t addr)
|
||||
void
|
||||
flash_put_data_internal (const uint8_t *p, uint16_t hw)
|
||||
{
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -498,7 +514,7 @@ flash_put_data (uint16_t hw)
|
||||
DEBUG_INFO ("data allocation failure.\r\n");
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
|
||||
@@ -510,14 +526,14 @@ flash_bool_clear (const uint8_t **addr_p)
|
||||
if ((p = *addr_p) == NULL)
|
||||
return;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
*addr_p = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
flash_bool_write_internal (const uint8_t *p, int nr)
|
||||
{
|
||||
flash_program_halfword ((uint32_t)p, nr);
|
||||
flash_program_halfword ((uintptr_t)p, nr);
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
@@ -533,7 +549,7 @@ flash_bool_write (uint8_t nr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -549,7 +565,7 @@ flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v)
|
||||
{
|
||||
uint16_t hw = nr | (v << 8);
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
@@ -565,7 +581,7 @@ flash_enum_write (uint8_t nr, uint8_t v)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -601,14 +617,14 @@ flash_cnt123_write_internal (const uint8_t *p, int which, int v)
|
||||
uint16_t hw;
|
||||
|
||||
hw = NR_COUNTER_123 | (which << 8);
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
|
||||
if (v == 1)
|
||||
return;
|
||||
else if (v == 2)
|
||||
flash_program_halfword ((uint32_t)p+2, 0xc3c3);
|
||||
flash_program_halfword ((uintptr_t)p+2, 0xc3c3);
|
||||
else /* v == 3 */
|
||||
flash_program_halfword ((uint32_t)p+2, 0);
|
||||
flash_program_halfword ((uintptr_t)p+2, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -626,7 +642,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
|
||||
return;
|
||||
}
|
||||
hw = NR_COUNTER_123 | (which << 8);
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
*addr_p = p + 2;
|
||||
}
|
||||
else
|
||||
@@ -641,7 +657,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
|
||||
else
|
||||
hw = 0;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,9 +669,9 @@ flash_cnt123_clear (const uint8_t **addr_p)
|
||||
if ((p = *addr_p) == NULL)
|
||||
return;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
p -= 2;
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
*addr_p = NULL;
|
||||
}
|
||||
|
||||
@@ -669,9 +685,9 @@ flash_erase_binary (uint8_t file_id)
|
||||
const uint8_t *p = &ch_certificate_start;
|
||||
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
|
||||
{
|
||||
flash_erase_page ((uint32_t)p);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
|
||||
flash_erase_page ((uint32_t)p + flash_page_size);
|
||||
flash_erase_page ((uintptr_t)p + flash_page_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -694,17 +710,19 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
maxsize = 6;
|
||||
p = &openpgpcard_aid[8];
|
||||
}
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
{
|
||||
maxsize = FIRMWARE_UPDATE_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)
|
||||
if (flash_program_halfword ((uintptr_t)p, 0) != 0)
|
||||
flash_warning ("DO WRITE ERROR");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
else if (file_id == FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
@@ -720,13 +738,13 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
else
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
if (flash_check_blank (p + offset, len) == 0)
|
||||
return -1;
|
||||
|
||||
addr = (uint32_t)p + offset;
|
||||
addr = (uintptr_t)p + offset;
|
||||
for (i = 0; i < len/2; i++)
|
||||
{
|
||||
hw = data[i*2] | (data[i*2+1]<<8);
|
||||
|
||||
16
src/gnuk-malloc.h
Normal file
16
src/gnuk-malloc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Gnuk uses its own malloc functions.
|
||||
*
|
||||
* The intention is no-dependency to C library. But, we provide
|
||||
* malloc and free here, since RSA routines uses malloc/free
|
||||
* internally.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> /* NULL and size_t */
|
||||
|
||||
#define malloc(size) gnuk_malloc (size)
|
||||
#define free(p) gnuk_free (p)
|
||||
|
||||
void *gnuk_malloc (size_t);
|
||||
void gnuk_free (void *);
|
||||
79
src/gnuk.h
79
src/gnuk.h
@@ -22,22 +22,20 @@ extern struct apdu apdu;
|
||||
#define CARD_CHANGE_REMOVE 1
|
||||
#define CARD_CHANGE_TOGGLE 2
|
||||
void ccid_card_change_signal (int how);
|
||||
void ccid_usb_reset (int);
|
||||
|
||||
/* CCID thread */
|
||||
#define EV_RX_DATA_READY 1 /* USB Rx data available */
|
||||
#define EV_EXEC_FINISHED 2 /* OpenPGP Execution finished */
|
||||
#define EV_TX_FINISHED 4 /* CCID Tx finished */
|
||||
#define EV_CARD_CHANGE 8
|
||||
#define EV_USB_SET_INTERFACE 16
|
||||
#define EV_USB_DEVICE_RESET 32
|
||||
#define EV_CARD_CHANGE 1
|
||||
#define EV_TX_FINISHED 2 /* CCID Tx finished */
|
||||
#define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */
|
||||
#define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */
|
||||
#define EV_RX_DATA_READY 16 /* USB Rx data available */
|
||||
|
||||
/* OpenPGPcard thread */
|
||||
#define EV_PINPAD_INPUT_DONE 1
|
||||
#define EV_EXIT 2
|
||||
#define EV_MODIFY_CMD_AVAILABLE 1
|
||||
#define EV_VERIFY_CMD_AVAILABLE 2
|
||||
#define EV_CMD_AVAILABLE 4
|
||||
#define EV_VERIFY_CMD_AVAILABLE 8
|
||||
#define EV_MODIFY_CMD_AVAILABLE 16
|
||||
#define EV_EXIT 8
|
||||
#define EV_PINPAD_INPUT_DONE 16
|
||||
|
||||
/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */
|
||||
#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */
|
||||
@@ -56,17 +54,17 @@ enum ccid_state {
|
||||
CCID_STATE_NOCARD, /* No card available */
|
||||
CCID_STATE_START, /* Initial */
|
||||
CCID_STATE_WAIT, /* Waiting APDU */
|
||||
/* Busy1, Busy2, Busy3, Busy5 */
|
||||
CCID_STATE_EXECUTE, /* Busy4 */
|
||||
CCID_STATE_RECEIVE, /* APDU Received Partially */
|
||||
CCID_STATE_SEND, /* APDU Sent Partially */
|
||||
|
||||
CCID_STATE_EXITED, /* ICC Thread Terminated */
|
||||
CCID_STATE_EXECUTE, /* Executing command */
|
||||
CCID_STATE_ACK_REQUIRED_0, /* Ack required (executing)*/
|
||||
CCID_STATE_ACK_REQUIRED_1, /* Waiting user's ACK (execution finished) */
|
||||
|
||||
CCID_STATE_EXITED, /* CCID Thread Terminated */
|
||||
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
|
||||
extern enum ccid_state *const ccid_state_p;
|
||||
enum ccid_state ccid_get_ccid_state (void);
|
||||
|
||||
extern volatile uint8_t auth_status;
|
||||
#define AC_NONE_AUTHORIZED 0x00
|
||||
@@ -112,7 +110,7 @@ void gpg_do_terminate (void);
|
||||
void gpg_do_get_data (uint16_t tag, int with_tag);
|
||||
void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
|
||||
void gpg_do_public_key (uint8_t kk_byte);
|
||||
void gpg_do_keygen (uint8_t kk_byte);
|
||||
void gpg_do_keygen (uint8_t *buf);
|
||||
|
||||
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
|
||||
@@ -126,8 +124,8 @@ const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNING = 0,
|
||||
GPG_KEY_FOR_DECRYPTION,
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
GPG_KEY_FOR_DECRYPTION = 1,
|
||||
GPG_KEY_FOR_AUTHENTICATION = 2,
|
||||
};
|
||||
|
||||
enum size_of_key {
|
||||
@@ -139,10 +137,10 @@ enum size_of_key {
|
||||
int gpg_get_algo_attr (enum kind_of_key kk);
|
||||
int gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s);
|
||||
|
||||
void flash_init (const uint8_t **, const uint8_t **);
|
||||
void flash_do_storage_init (const uint8_t **, const uint8_t **);
|
||||
void flash_terminate (void);
|
||||
void flash_activate (void);
|
||||
void flash_init_keys (void);
|
||||
void flash_key_storage_init (void);
|
||||
void flash_do_release (const uint8_t *);
|
||||
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||
uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
@@ -152,7 +150,7 @@ int flash_key_write (uint8_t *key_addr,
|
||||
const uint8_t *key_data, int key_data_len,
|
||||
const uint8_t *pubkey, int pubkey_len);
|
||||
void flash_set_data_pool_last (const uint8_t *p);
|
||||
void flash_clear_halfword (uint32_t addr);
|
||||
void flash_clear_halfword (uintptr_t addr);
|
||||
void flash_increment_counter (uint8_t counter_tag_nr);
|
||||
void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
|
||||
@@ -265,22 +263,22 @@ void put_binary (const char *s, int len);
|
||||
#endif
|
||||
|
||||
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
|
||||
uint8_t *modulus_calc (const uint8_t *, int);
|
||||
int modulus_calc (const uint8_t *, int, uint8_t *);
|
||||
int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *,
|
||||
unsigned int *);
|
||||
int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *);
|
||||
uint8_t *rsa_genkey (int);
|
||||
int rsa_genkey (int, uint8_t *, uint8_t *);
|
||||
|
||||
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
|
||||
int ecc_compute_public_p256r1 (const uint8_t *key_data, uint8_t *);
|
||||
int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
|
||||
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
|
||||
int ecc_compute_public_p256k1 (const uint8_t *key_data, uint8_t *);
|
||||
int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1);
|
||||
int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
@@ -288,14 +286,18 @@ int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
|
||||
int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
|
||||
const uint8_t *sk_a, const uint8_t *seed,
|
||||
const uint8_t *pk);
|
||||
uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
|
||||
uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
|
||||
void eddsa_compute_public_25519 (const uint8_t *a, uint8_t *);
|
||||
void ecdh_compute_public_25519 (const uint8_t *a, uint8_t *);
|
||||
int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
const uint8_t *gpg_do_read_simple (uint8_t);
|
||||
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||
void gpg_increment_digital_signature_counter (void);
|
||||
void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len,
|
||||
const uint8_t **r_p);
|
||||
int gpg_do_kdf_check (int len, int how_many);
|
||||
int gpg_do_get_uif (enum kind_of_key kk);
|
||||
|
||||
|
||||
void fatal (uint8_t code) __attribute__ ((noreturn));
|
||||
@@ -334,7 +336,8 @@ extern uint8_t admin_authorized;
|
||||
#define NR_DO_KEYSTRING_PW1 0x11
|
||||
#define NR_DO_KEYSTRING_RC 0x12
|
||||
#define NR_DO_KEYSTRING_PW3 0x13
|
||||
#define NR_DO__LAST__ 20 /* == 0x14 */
|
||||
#define NR_DO_KDF 0x14
|
||||
#define NR_DO__LAST__ 21 /* == 0x15 */
|
||||
/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */
|
||||
/*
|
||||
* Representation of 14-bit counter:
|
||||
@@ -377,7 +380,17 @@ extern uint8_t admin_authorized;
|
||||
#define NR_KEY_ALGO_ATTR_DEC 0xf2
|
||||
#define NR_KEY_ALGO_ATTR_AUT 0xf3
|
||||
/*
|
||||
* NR_UINT_SOMETHING could be here... Use 0xf[456789abcd]
|
||||
* Representation of User Interaction Flag:
|
||||
* 0 (UIF disabled): 0xf?00 or No record in flash memory
|
||||
* 1 (UIF enabled): 0xf?01
|
||||
* 2 (UIF permanently enabled): 0xf?02
|
||||
*
|
||||
*/
|
||||
#define NR_DO_UIF_SIG 0xf6
|
||||
#define NR_DO_UIF_DEC 0xf7
|
||||
#define NR_DO_UIF_AUT 0xf8
|
||||
/*
|
||||
* NR_UINT_SOMETHING could be here... Use 0xf[459abcd]
|
||||
*/
|
||||
/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */
|
||||
/*
|
||||
@@ -433,6 +446,8 @@ extern const uint8_t gnuk_string_serial[];
|
||||
#define LED_GNUK_EXEC 32
|
||||
#define LED_START_COMMAND 64
|
||||
#define LED_FINISH_COMMAND 128
|
||||
#define LED_WAIT_FOR_BUTTON 256
|
||||
#define LED_OFF LED_FINISH_COMMAND
|
||||
void led_blink (int spec);
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
@@ -459,7 +474,7 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern uint8_t _regnual_start, __heap_end__[];
|
||||
|
||||
int check_crc32 (const uint32_t *start_p, const uint32_t *end_p);
|
||||
uint8_t * sram_address (uint32_t offset);
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0080; /* Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* main */
|
||||
__process1_stack_size__ = 0x01a0; /* ccid */
|
||||
__process2_stack_size__ = 0x0180; /* rng */
|
||||
__process3_stack_size__ = 0x1660; /* gpg */
|
||||
__process4_stack_size__ = 0; /* --- */
|
||||
__process5_stack_size__ = @MSC_SIZE@; /* msc */
|
||||
__process6_stack_size__ = @TIM_SIZE@; /* intr: timer */
|
||||
__process7_stack_size__ = @EXT_SIZE@; /* intr: ext */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = @ORIGIN@, len = 4k
|
||||
@@ -82,45 +72,18 @@ SECTIONS
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.stacks :
|
||||
.stacks (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process4_stack_base__ = .;
|
||||
. += __process4_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process4_stack_end__ = .;
|
||||
__process5_stack_base__ = .;
|
||||
. += __process5_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process5_stack_end__ = .;
|
||||
__process6_stack_base__ = .;
|
||||
. += __process6_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process6_stack_end__ = .;
|
||||
__process7_stack_base__ = .;
|
||||
. += __process7_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process7_stack_end__ = .;
|
||||
*(.main_stack)
|
||||
*(.process_stack.0)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.3)
|
||||
*(.process_stack.4)
|
||||
*(.process_stack.5)
|
||||
*(.process_stack.6)
|
||||
*(.process_stack.7)
|
||||
. = ALIGN(8);
|
||||
} > ram
|
||||
|
||||
@@ -172,11 +135,11 @@ SECTIONS
|
||||
{
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
_keystore_pool = .;
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
_updatekey_store = .;
|
||||
. += 1024;
|
||||
|
||||
335
src/main.c
335
src/main.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* main.c - main routine of Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018, 2021
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -35,8 +35,18 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb-cdc.h"
|
||||
#include "random.h"
|
||||
#include "mcu/stm32f103.h"
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define main emulated_main
|
||||
#else
|
||||
#include "mcu/stm32f103.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* main thread does 1-bit LED display output
|
||||
@@ -46,7 +56,33 @@
|
||||
#define LED_TIMEOUT_ONE (100*1000)
|
||||
#define LED_TIMEOUT_STOP (200*1000)
|
||||
|
||||
#ifdef DFU_SUPPORT
|
||||
static int
|
||||
flash_write_any (uintptr_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
while (len)
|
||||
{
|
||||
uint16_t hw = *src++;
|
||||
|
||||
hw |= (*src++ << 8);
|
||||
status = flash_program_halfword (dst_addr, hw);
|
||||
if (status != 0)
|
||||
return 0; /* error return */
|
||||
|
||||
dst_addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
uint8_t *flash_addr_key_storage_start;
|
||||
uint8_t *flash_addr_data_storage_start;
|
||||
#else
|
||||
#define ID_OFFSET (2+SERIALNO_STR_LEN*2)
|
||||
static void
|
||||
device_initialize_once (void)
|
||||
@@ -59,7 +95,7 @@ device_initialize_once (void)
|
||||
* This is the first time invocation.
|
||||
* Setup serial number by unique device ID.
|
||||
*/
|
||||
const uint8_t *u = unique_device_id () + 8;
|
||||
const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
@@ -74,12 +110,66 @@ device_initialize_once (void)
|
||||
nibble += (nibble >= 10 ? ('A' - 10) : '0');
|
||||
flash_put_data_internal (&p[i*4+2], nibble);
|
||||
}
|
||||
|
||||
#ifdef DFU_SUPPORT
|
||||
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
|
||||
/*
|
||||
* Overwrite DFU bootloader with a copy of SYS linked to ORIGIN_REAL.
|
||||
* Then protect flash from readout.
|
||||
*/
|
||||
{
|
||||
extern uint8_t _binary_build_stdaln_sys_bin_start;
|
||||
extern uint8_t _binary_build_stdaln_sys_bin_size;
|
||||
size_t stdaln_sys_size = (size_t) &_binary_build_stdaln_sys_bin_size;
|
||||
extern const uint32_t FT0[256], FT1[256], FT2[256];
|
||||
extern handler vector_table[];
|
||||
uintptr_t addr;
|
||||
uint32_t flash_page_size = 1024; /* 1KiB default */
|
||||
|
||||
if (((*CHIP_ID_REG)&0x07) == 0x04) /* High density device. */
|
||||
flash_page_size = 2048; /* It's 2KiB. */
|
||||
|
||||
/* Kill DFU */
|
||||
for (addr = ORIGIN_REAL; addr < ORIGIN;
|
||||
addr += flash_page_size)
|
||||
flash_erase_page (addr);
|
||||
|
||||
/* Copy SYS */
|
||||
addr = ORIGIN_REAL;
|
||||
flash_write_any(addr, &_binary_build_stdaln_sys_bin_start,
|
||||
stdaln_sys_size);
|
||||
addr += stdaln_sys_size;
|
||||
flash_write_any(addr, (const uint8_t *) &FT0, sizeof(FT0));
|
||||
addr += sizeof(FT0);
|
||||
flash_write_any(addr, (const uint8_t *) &FT1, sizeof(FT1));
|
||||
addr += sizeof(FT1);
|
||||
flash_write_any(addr, (const uint8_t *) &FT2, sizeof(FT2));
|
||||
|
||||
addr = ORIGIN_REAL + 0x1000;
|
||||
if (addr < ORIGIN) {
|
||||
/* Need to patch top of stack and reset vector there */
|
||||
handler *new_vector = (handler *) addr;
|
||||
flash_write((uintptr_t) &new_vector[0], (const uint8_t *)
|
||||
&vector_table[0], sizeof(handler));
|
||||
flash_write((uintptr_t) &new_vector[1], (const uint8_t *)
|
||||
&vector[1], sizeof(handler));
|
||||
}
|
||||
|
||||
flash_protect();
|
||||
nvic_system_reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static volatile uint8_t fatal_code;
|
||||
static struct eventflag led_event;
|
||||
static chopstx_poll_cond_t led_event_poll_desc;
|
||||
static struct chx_poll_head *const led_event_poll[] = {
|
||||
(struct chx_poll_head *)&led_event_poll_desc
|
||||
};
|
||||
|
||||
static void display_fatal_code (void)
|
||||
{
|
||||
@@ -120,17 +210,20 @@ static void display_fatal_code (void)
|
||||
|
||||
static uint8_t led_inverted;
|
||||
|
||||
static void emit_led (int on_time, int off_time)
|
||||
static void
|
||||
emit_led (uint32_t on_time, uint32_t off_time)
|
||||
{
|
||||
set_led (!led_inverted);
|
||||
chopstx_usec_wait (on_time);
|
||||
chopstx_poll (&on_time, 1, led_event_poll);
|
||||
set_led (led_inverted);
|
||||
chopstx_usec_wait (off_time);
|
||||
chopstx_poll (&off_time, 1, led_event_poll);
|
||||
}
|
||||
|
||||
static void display_status_code (void)
|
||||
static void
|
||||
display_status_code (void)
|
||||
{
|
||||
enum ccid_state ccid_state = *ccid_state_p;
|
||||
enum ccid_state ccid_state = ccid_get_ccid_state ();
|
||||
uint32_t usec;
|
||||
|
||||
if (ccid_state == CCID_STATE_START)
|
||||
emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
|
||||
@@ -145,12 +238,15 @@ static void display_status_code (void)
|
||||
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
|
||||
|
||||
if (ccid_state == CCID_STATE_WAIT)
|
||||
chopstx_usec_wait (LED_TIMEOUT_STOP * 2);
|
||||
{
|
||||
usec = LED_TIMEOUT_STOP * 2;
|
||||
chopstx_poll (&usec, 1, led_event_poll);
|
||||
}
|
||||
else
|
||||
{
|
||||
chopstx_usec_wait (LED_TIMEOUT_INTERVAL);
|
||||
emit_led (ccid_state == CCID_STATE_RECEIVE?
|
||||
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
|
||||
usec = LED_TIMEOUT_INTERVAL;
|
||||
chopstx_poll (&usec, 1, led_event_poll);
|
||||
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,26 +263,30 @@ led_blink (int spec)
|
||||
eventflag_signal (&led_event, spec);
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/*
|
||||
* In Gnuk 1.0.[12], reGNUal was not relocatable.
|
||||
* Now, it's relocatable, but we need to calculate its entry address
|
||||
* based on it's pre-defined address.
|
||||
*/
|
||||
#define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
|
||||
static uint32_t
|
||||
static uintptr_t
|
||||
calculate_regnual_entry_address (const uint8_t *addr)
|
||||
{
|
||||
const uint8_t *p = addr + 4;
|
||||
uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||
uintptr_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||
|
||||
v -= REGNUAL_START_ADDRESS_COMPATIBLE;
|
||||
v += (uint32_t)addr;
|
||||
v += (uintptr_t)addr;
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
|
||||
#define STACK_ADDR_CCID ((uint32_t)__process1_stack_base__)
|
||||
#define STACK_SIZE_CCID ((uint32_t)__process1_stack_size__)
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_CCID ((uintptr_t)process1_base)
|
||||
#define STACK_SIZE_CCID (sizeof process1_base)
|
||||
|
||||
#define PRIO_CCID 3
|
||||
#define PRIO_MAIN 5
|
||||
@@ -202,18 +302,125 @@ extern uint32_t bDeviceState;
|
||||
* Entry point.
|
||||
*/
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
uint32_t entry;
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
uintptr_t flash_addr;
|
||||
const char *flash_image_path;
|
||||
char *path_string = NULL;
|
||||
#endif
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
uintptr_t entry;
|
||||
#endif
|
||||
chopstx_t ccid_thd;
|
||||
int wait_for_ack = 0;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
chopstx_conf_idle (1);
|
||||
|
||||
gnuk_malloc_init ();
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define FLASH_IMAGE_NAME ".gnuk-flash-image"
|
||||
|
||||
if (argc >= 4 || (argc == 2 && !strcmp (argv[1], "--help")))
|
||||
{
|
||||
fprintf (stdout, "Usage: %s [--vidpid=Vxxx:Pxxx] [flash-image-file]",
|
||||
argv[0]);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strncmp (argv[1], "--debug=", 8))
|
||||
{
|
||||
debug = strtol (&argv[1][8], NULL, 10);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strncmp (argv[1], "--vidpid=", 9))
|
||||
{
|
||||
extern uint8_t device_desc[];
|
||||
uint32_t id;
|
||||
char *p;
|
||||
|
||||
id = (uint32_t)strtol (&argv[1][9], &p, 16);
|
||||
device_desc[8] = (id & 0xff);
|
||||
device_desc[9] = (id >> 8);
|
||||
|
||||
if (p && p[0] == ':')
|
||||
{
|
||||
id = (uint32_t)strtol (&p[1], NULL, 16);
|
||||
device_desc[10] = (id & 0xff);
|
||||
device_desc[11] = (id >> 8);
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
char *p = getenv ("HOME");
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr, "Can't find $HOME\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
path_string = malloc (strlen (p) + strlen (FLASH_IMAGE_NAME) + 2);
|
||||
|
||||
p = stpcpy (path_string, p);
|
||||
*p++ = '/';
|
||||
strcpy (p, FLASH_IMAGE_NAME);
|
||||
flash_image_path = path_string;
|
||||
}
|
||||
else
|
||||
flash_image_path = argv[1];
|
||||
|
||||
if (access (flash_image_path, F_OK) < 0)
|
||||
{
|
||||
int fd;
|
||||
char buf[8192];
|
||||
|
||||
memset (buf, 0xff, sizeof buf);
|
||||
memset (buf+4*1024, 0, 2);
|
||||
fd = open (flash_image_path, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("creating flash file");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (write (fd, buf, sizeof buf) != sizeof buf)
|
||||
{
|
||||
perror ("initializing flash file");
|
||||
close (fd);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
puts ("Gnuk (emulation with USBIP), a GnuPG USB Token implementation");
|
||||
puts ("Copyright (C) 2021 Free Software Initiative of Japan");
|
||||
puts ("This is free software under GPLv3+.");
|
||||
|
||||
flash_addr = flash_init (flash_image_path);
|
||||
flash_addr_key_storage_start = (uint8_t *)flash_addr;
|
||||
flash_addr_data_storage_start = (uint8_t *)flash_addr + 4096;
|
||||
#else
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#endif
|
||||
|
||||
flash_unlock ();
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
if (path_string)
|
||||
free (path_string);
|
||||
#else
|
||||
device_initialize_once ();
|
||||
#endif
|
||||
|
||||
adc_init ();
|
||||
|
||||
@@ -239,17 +446,23 @@ main (int argc, char *argv[])
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bDeviceState != UNCONNECTED)
|
||||
if (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
|
||||
break;
|
||||
|
||||
chopstx_usec_wait (250*1000);
|
||||
}
|
||||
|
||||
eventflag_prepare_poll (&led_event, &led_event_poll_desc);
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
m = eventflag_wait (&led_event);
|
||||
if (wait_for_ack)
|
||||
m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL);
|
||||
else
|
||||
m = eventflag_wait (&led_event);
|
||||
|
||||
switch (m)
|
||||
{
|
||||
case LED_ONESHOT:
|
||||
@@ -270,8 +483,11 @@ main (int argc, char *argv[])
|
||||
break;
|
||||
case LED_GNUK_EXEC:
|
||||
goto exec;
|
||||
case LED_WAIT_FOR_BUTTON:
|
||||
wait_for_ack ^= 1;
|
||||
/* fall through */
|
||||
default:
|
||||
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
|
||||
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_ZERO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -285,30 +501,15 @@ main (int argc, char *argv[])
|
||||
/* Finish application. */
|
||||
chopstx_join (ccid_thd, NULL);
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/* Set vector */
|
||||
SCB->VTOR = (uint32_t)&_regnual_start;
|
||||
SCB->VTOR = (uintptr_t)&_regnual_start;
|
||||
entry = calculate_regnual_entry_address (&_regnual_start);
|
||||
#ifdef DFU_SUPPORT
|
||||
#define FLASH_SYS_START_ADDR 0x08000000
|
||||
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
|
||||
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
|
||||
{
|
||||
extern uint8_t _sys;
|
||||
uint32_t addr;
|
||||
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
|
||||
uint32_t flash_page_size = 1024; /* 1KiB default */
|
||||
|
||||
if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
|
||||
flash_page_size = 2048; /* It's 2KiB. */
|
||||
|
||||
/* 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);
|
||||
/* Use SYS at ORIGIN_REAL instead of the one at ORIGIN */
|
||||
handler *new_vector = (handler *)ORIGIN_REAL;
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void))) new_vector[9];
|
||||
|
||||
/* Leave Gnuk to exec reGNUal */
|
||||
(*func) ((void (*)(void))entry);
|
||||
@@ -318,6 +519,9 @@ main (int argc, char *argv[])
|
||||
/* Leave Gnuk to exec reGNUal */
|
||||
flash_erase_all_and_exec ((void (*)(void))entry);
|
||||
#endif
|
||||
#else
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
/* Never reached */
|
||||
return 0;
|
||||
@@ -348,26 +552,37 @@ fatal (uint8_t code)
|
||||
* reclaimed to system.
|
||||
*/
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define HEAP_SIZE (32*1024)
|
||||
uint8_t __heap_base__[HEAP_SIZE];
|
||||
|
||||
#define HEAP_START __heap_base__
|
||||
#define HEAP_END (__heap_base__ + HEAP_SIZE)
|
||||
#define HEAP_ALIGNMENT 32
|
||||
#else
|
||||
extern uint8_t __heap_base__[];
|
||||
extern uint8_t __heap_end__[];
|
||||
|
||||
#define MEMORY_END (__heap_end__)
|
||||
#define MEMORY_ALIGNMENT 16
|
||||
#define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
|
||||
#define MEMORY_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
|
||||
#define HEAP_START __heap_base__
|
||||
#define HEAP_END (__heap_end__)
|
||||
#define HEAP_ALIGNMENT 16
|
||||
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
|
||||
#endif
|
||||
|
||||
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
|
||||
|
||||
static uint8_t *heap_p;
|
||||
static chopstx_mutex_t malloc_mtx;
|
||||
|
||||
struct mem_head {
|
||||
uint32_t size;
|
||||
uintptr_t size;
|
||||
/**/
|
||||
struct mem_head *next, *prev; /* free list chain */
|
||||
struct mem_head *neighbor; /* backlink to neighbor */
|
||||
};
|
||||
|
||||
#define MEM_HEAD_IS_CORRUPT(x) \
|
||||
((x)->size != MEMORY_ALIGN((x)->size) || (x)->size > MEMORY_SIZE)
|
||||
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
|
||||
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
|
||||
|
||||
static struct mem_head *free_list;
|
||||
@@ -376,16 +591,16 @@ static void
|
||||
gnuk_malloc_init (void)
|
||||
{
|
||||
chopstx_mutex_init (&malloc_mtx);
|
||||
heap_p = __heap_base__;
|
||||
heap_p = HEAP_START;
|
||||
free_list = NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
sbrk (size_t size)
|
||||
gnuk_sbrk (intptr_t size)
|
||||
{
|
||||
void *p = (void *)heap_p;
|
||||
|
||||
if ((size_t)(MEMORY_END - heap_p) < size)
|
||||
if ((HEAP_END - heap_p) < size)
|
||||
return NULL;
|
||||
|
||||
heap_p += size;
|
||||
@@ -410,7 +625,7 @@ gnuk_malloc (size_t size)
|
||||
struct mem_head *m;
|
||||
struct mem_head *m0;
|
||||
|
||||
size = MEMORY_ALIGN (size + sizeof (uint32_t));
|
||||
size = HEAP_ALIGN (size + sizeof (uintptr_t));
|
||||
|
||||
chopstx_mutex_lock (&malloc_mtx);
|
||||
DEBUG_INFO ("malloc: ");
|
||||
@@ -421,7 +636,7 @@ gnuk_malloc (size_t size)
|
||||
{
|
||||
if (m == NULL)
|
||||
{
|
||||
m = (struct mem_head *)sbrk (size);
|
||||
m = (struct mem_head *)gnuk_sbrk (size);
|
||||
if (m)
|
||||
m->size = size;
|
||||
break;
|
||||
@@ -450,8 +665,8 @@ gnuk_malloc (size_t size)
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WORD ((uint32_t)m + sizeof (uint32_t));
|
||||
return (void *)m + sizeof (uint32_t);
|
||||
DEBUG_WORD ((uintptr_t)m + sizeof (uintptr_t));
|
||||
return (void *)m + sizeof (uintptr_t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,7 +674,7 @@ gnuk_malloc (size_t size)
|
||||
void
|
||||
gnuk_free (void *p)
|
||||
{
|
||||
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uint32_t));
|
||||
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uintptr_t));
|
||||
struct mem_head *m0;
|
||||
|
||||
if (p == NULL)
|
||||
@@ -469,7 +684,7 @@ gnuk_free (void *p)
|
||||
m0 = free_list;
|
||||
DEBUG_INFO ("free: ");
|
||||
DEBUG_SHORT (m->size);
|
||||
DEBUG_WORD ((uint32_t)p);
|
||||
DEBUG_WORD ((uintptr_t)p);
|
||||
|
||||
MEM_HEAD_CHECK (m);
|
||||
m->neighbor = NULL;
|
||||
|
||||
@@ -25,30 +25,6 @@
|
||||
#include <stdint.h>
|
||||
#include "mcu/stm32f103.h"
|
||||
|
||||
static uint32_t
|
||||
rbit (uint32_t v)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
check_crc32 (const uint32_t *start_p, const uint32_t *end_p)
|
||||
{
|
||||
uint32_t crc32 = *end_p;
|
||||
const uint32_t *p;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
|
||||
for (p = start_p; p < end_p; p++)
|
||||
CRC->DR = rbit (*p);
|
||||
|
||||
return (rbit (CRC->DR) ^ crc32) == 0xffffffff;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
sram_address (uint32_t offset)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* modp256k1.c -- modulo arithmetic for p256k1
|
||||
*
|
||||
* Copyright (C) 2014, 2016 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2016, 2020 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -71,14 +71,12 @@ modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t cond;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
cond = (bn256_add (X, A, B) == 0);
|
||||
cond &= bn256_sub (tmp, X, P256K1);
|
||||
if (cond)
|
||||
/* No-carry AND borrow */
|
||||
memcpy (tmp, tmp, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
memcpy (cond?dummy:X, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,13 +87,12 @@ modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
bn256_add (tmp, X, P256K1);
|
||||
if (borrow)
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
else
|
||||
memcpy (tmp, tmp, sizeof (bn256));
|
||||
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* modp256r1.c -- modulo arithmetic for p256r1
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014, 2016
|
||||
* Copyright (C) 2011, 2013, 2014, 2016, 2020
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -66,14 +66,12 @@ modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t cond;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
cond = (bn256_add (X, A, B) == 0);
|
||||
cond &= bn256_sub (tmp, X, P256R1);
|
||||
if (cond)
|
||||
/* No-carry AND borrow */
|
||||
memcpy (tmp, tmp, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
memcpy (cond?dummy:X, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,13 +82,12 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
bn256_add (tmp, X, P256R1);
|
||||
if (borrow)
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
else
|
||||
memcpy (tmp, tmp, sizeof (bn256));
|
||||
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,6 +97,7 @@ void
|
||||
modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
{
|
||||
bn256 tmp[1], tmp0[1];
|
||||
bn256 dummy[1];
|
||||
uint32_t borrow;
|
||||
|
||||
#define S1 X
|
||||
@@ -121,10 +119,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S1->word[1] = A->word[1];
|
||||
S1->word[0] = A->word[0];
|
||||
borrow = bn256_sub (tmp0, S1, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp0, tmp0, sizeof (bn256));
|
||||
else
|
||||
memcpy (S1, tmp0, sizeof (bn256));
|
||||
memcpy (borrow?dummy:S1, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X = S1 */
|
||||
|
||||
S2->word[7] = A->word[15];
|
||||
@@ -165,10 +161,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S5->word[1] = A->word[10];
|
||||
S5->word[0] = A->word[9];
|
||||
borrow = bn256_sub (tmp0, S5, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp0, tmp0, sizeof (bn256));
|
||||
else
|
||||
memcpy (S5, tmp0, sizeof (bn256));
|
||||
memcpy (borrow?dummy:S5, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X += S5 */
|
||||
modp256r1_add (X, X, S5);
|
||||
|
||||
@@ -179,10 +173,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S6->word[1] = A->word[12];
|
||||
S6->word[0] = A->word[11];
|
||||
borrow = bn256_sub (tmp0, S6, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp0, tmp0, sizeof (bn256));
|
||||
else
|
||||
memcpy (S6, tmp0, sizeof (bn256));
|
||||
memcpy (borrow?dummy:S6, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X -= S6 */
|
||||
modp256r1_sub (X, X, S6);
|
||||
|
||||
@@ -194,10 +186,8 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S7->word[1] = A->word[13];
|
||||
S7->word[0] = A->word[12];
|
||||
borrow = bn256_sub (tmp0, S7, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp0, tmp0, sizeof (bn256));
|
||||
else
|
||||
memcpy (S7, tmp0, sizeof (bn256));
|
||||
memcpy (borrow?dummy:S7, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X -= S7 */
|
||||
modp256r1_sub (X, X, S7);
|
||||
|
||||
|
||||
195
src/neug.c
195
src/neug.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* neug.c - true random number generation
|
||||
*
|
||||
* Copyright (C) 2011, 2012, 2013, 2016
|
||||
* Copyright (C) 2011, 2012, 2013, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -29,10 +29,133 @@
|
||||
|
||||
#include "sys.h"
|
||||
#include "neug.h"
|
||||
#ifndef GNU_LINUX_EMULATION
|
||||
#include "mcu/stm32f103.h"
|
||||
#endif
|
||||
#include "adc.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
static const uint32_t crc32_rv_table[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
|
||||
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
|
||||
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
|
||||
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
|
||||
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
|
||||
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
|
||||
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
|
||||
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
|
||||
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
|
||||
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
|
||||
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
|
||||
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
|
||||
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
|
||||
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
|
||||
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
|
||||
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
|
||||
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
|
||||
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
|
||||
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
|
||||
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
|
||||
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
static uint32_t crc;
|
||||
|
||||
void
|
||||
crc32_rv_reset (void)
|
||||
{
|
||||
crc = 0xffffffff;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_step (uint32_t v)
|
||||
{
|
||||
crc = crc32_rv_table[(crc ^ (v << 0)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 8)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 16)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 24)) >> 24] ^ (crc << 8);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc32_rv_get (void)
|
||||
{
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rbit (uint32_t v)
|
||||
{
|
||||
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
|
||||
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
|
||||
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
|
||||
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
|
||||
v = ( v >> 16 ) | ( v << 16);
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_stop (void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
void
|
||||
crc32_rv_reset (void)
|
||||
{
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_step (uint32_t v)
|
||||
{
|
||||
CRC->DR = v;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc32_rv_get (void)
|
||||
{
|
||||
return CRC->DR;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rbit (uint32_t v)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_stop (void)
|
||||
{
|
||||
RCC->AHBENR &= ~RCC_AHBENR_CRCEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
static chopstx_mutex_t mode_mtx;
|
||||
static chopstx_cond_t mode_cond;
|
||||
|
||||
@@ -94,11 +217,11 @@ static void noise_source_continuous_test_word (uint8_t b0, uint8_t b1,
|
||||
* Then, three-byte from noise source follows.
|
||||
*
|
||||
* One-byte was used in the previous turn, and we have three bytes in
|
||||
* CRC->DR.
|
||||
* CRC32.
|
||||
*/
|
||||
static void ep_fill_initial_string (void)
|
||||
{
|
||||
uint32_t v = CRC->DR;
|
||||
uint32_t v = crc32_rv_get ();
|
||||
uint8_t b1, b2, b3;
|
||||
|
||||
b3 = v >> 24;
|
||||
@@ -164,11 +287,11 @@ static int ep_process (int mode)
|
||||
sha256_ctx_data.wbuf[1] = adc_buf[1];
|
||||
for (i = 0; i < EP_ROUND_0_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
CRC->DR = adc_buf[i*4 + 4];
|
||||
CRC->DR = adc_buf[i*4 + 5];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
crc32_rv_step (adc_buf[i*4 + 4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 5]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i+2, 1, v);
|
||||
}
|
||||
|
||||
@@ -181,11 +304,11 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_1_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
@@ -198,23 +321,23 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_2_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR & 0xff; /* First byte of CRC->DR is used here. */
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get () & 0xff; /* First byte of CRC32 is used here. */
|
||||
noise_source_continuous_test (v);
|
||||
sha256_ctx_data.wbuf[i] = v;
|
||||
ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
|
||||
CRC->DR is used here. */
|
||||
CRC32 is used here. */
|
||||
n = SHA256_DIGEST_SIZE / 2;
|
||||
memcpy (((uint8_t *)sha256_ctx_data.wbuf) + EP_ROUND_2_INPUTS,
|
||||
sha256_output, n);
|
||||
@@ -226,11 +349,11 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_RAW_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
@@ -640,9 +763,11 @@ rng (void *arg)
|
||||
|
||||
static struct rng_rb the_ring_buffer;
|
||||
|
||||
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
|
||||
#define STACK_ADDR_RNG ((uint32_t)__process2_stack_base__)
|
||||
#define STACK_SIZE_RNG ((uint32_t)__process2_stack_size__)
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_RNG ((uintptr_t)process2_base)
|
||||
#define STACK_SIZE_RNG (sizeof process2_base)
|
||||
|
||||
#define PRIO_RNG 2
|
||||
|
||||
/**
|
||||
@@ -655,15 +780,14 @@ neug_init (uint32_t *buf, uint8_t size)
|
||||
struct rng_rb *rb = &the_ring_buffer;
|
||||
int i;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
crc32_rv_reset ();
|
||||
|
||||
/*
|
||||
* This initialization ensures that it generates different sequence
|
||||
* even if all physical conditions are same.
|
||||
*/
|
||||
for (i = 0; i < 3; i++)
|
||||
CRC->DR = *u++;
|
||||
crc32_rv_step (*u++);
|
||||
|
||||
neug_mode = NEUG_MODE_CONDITIONED;
|
||||
rb_init (rb, buf, size);
|
||||
@@ -781,6 +905,7 @@ neug_fini (void)
|
||||
rng_should_terminate = 1;
|
||||
neug_get (1);
|
||||
chopstx_join (rng_thread, NULL);
|
||||
crc32_rv_stop ();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -26,3 +26,8 @@ void neug_fini (void);
|
||||
void neug_mode_select (uint8_t mode);
|
||||
|
||||
int neug_consume_random (void (*proc) (uint32_t, int));
|
||||
|
||||
void crc32_rv_reset (void);
|
||||
void crc32_rv_step (uint32_t v);
|
||||
uint32_t crc32_rv_get (void);
|
||||
uint32_t rbit (uint32_t v);
|
||||
|
||||
600
src/openpgp-do.c
600
src/openpgp-do.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
|
||||
* 2020
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -24,7 +25,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -113,13 +113,15 @@ const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
|
||||
/* Extended Capabilities */
|
||||
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
|
||||
10,
|
||||
0x74, /*
|
||||
0x75, /*
|
||||
* No Secure Messaging supported
|
||||
* GET CHALLENGE supported
|
||||
* Key import supported
|
||||
* PW status byte can be put
|
||||
* No private_use_DO
|
||||
* Algorithm attrs are changable
|
||||
* No DEC with AES
|
||||
* KDF-DO available
|
||||
*/
|
||||
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
|
||||
0x00, CHALLENGE_LEN, /* Max size of GET CHALLENGE */
|
||||
@@ -134,6 +136,14 @@ static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
|
||||
0x01, 0x00,
|
||||
};
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
/* General Feature Management */
|
||||
static const uint8_t feature_mngmnt[] __attribute__ ((aligned (1))) = {
|
||||
3,
|
||||
0x81, 0x01, 0x20,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Algorithm Attributes */
|
||||
#define OPENPGP_ALGO_RSA 0x01
|
||||
#define OPENPGP_ALGO_ECDH 0x12
|
||||
@@ -453,12 +463,18 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
|
||||
#define GPG_DO_KGTIME_DEC 0x00cf
|
||||
#define GPG_DO_KGTIME_AUT 0x00d0
|
||||
#define GPG_DO_RESETTING_CODE 0x00d3
|
||||
#define GPG_DO_UIF_SIG 0x00d6
|
||||
#define GPG_DO_UIF_DEC 0x00d7
|
||||
#define GPG_DO_UIF_AUT 0x00d8
|
||||
#define GPG_DO_KDF 0x00f9
|
||||
#define GPG_DO_ALG_INFO 0x00fa
|
||||
#define GPG_DO_KEY_IMPORT 0x3fff
|
||||
#define GPG_DO_LANGUAGE 0x5f2d
|
||||
#define GPG_DO_SEX 0x5f35
|
||||
#define GPG_DO_URL 0x5f50
|
||||
#define GPG_DO_HIST_BYTES 0x5f52
|
||||
#define GPG_DO_CH_CERTIFICATE 0x7f21
|
||||
#define GPG_DO_FEATURE_MNGMNT 0x7f74
|
||||
|
||||
static const uint8_t *do_ptr[NR_DO__LAST__];
|
||||
|
||||
@@ -495,6 +511,8 @@ do_tag_to_nr (uint16_t tag)
|
||||
return NR_DO_NAME;
|
||||
case GPG_DO_LANGUAGE:
|
||||
return NR_DO_LANGUAGE;
|
||||
case GPG_DO_KDF:
|
||||
return NR_DO_KDF;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -516,7 +534,7 @@ copy_tag (uint16_t tag)
|
||||
#define SIZE_FP 20
|
||||
#define SIZE_KGTIME 4
|
||||
|
||||
static int
|
||||
static void
|
||||
do_fp_all (uint16_t tag, int with_tag)
|
||||
{
|
||||
const uint8_t *data;
|
||||
@@ -547,10 +565,9 @@ do_fp_all (uint16_t tag, int with_tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_FP);
|
||||
res_p += SIZE_FP;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
do_cafp_all (uint16_t tag, int with_tag)
|
||||
{
|
||||
const uint8_t *data;
|
||||
@@ -581,10 +598,9 @@ do_cafp_all (uint16_t tag, int with_tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_FP);
|
||||
res_p += SIZE_FP;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
do_kgtime_all (uint16_t tag, int with_tag)
|
||||
{
|
||||
const uint8_t *data;
|
||||
@@ -615,7 +631,6 @@ do_kgtime_all (uint16_t tag, int with_tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_KGTIME);
|
||||
res_p += SIZE_KGTIME;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t openpgpcard_aid[] = {
|
||||
@@ -627,7 +642,7 @@ const uint8_t openpgpcard_aid[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
|
||||
};
|
||||
|
||||
static int
|
||||
static void
|
||||
do_openpgpcard_aid (uint16_t tag, int with_tag)
|
||||
{
|
||||
const volatile uint8_t *p = openpgpcard_aid;
|
||||
@@ -641,7 +656,7 @@ do_openpgpcard_aid (uint16_t tag, int with_tag)
|
||||
|
||||
if (vid == 0xffff || vid == 0x0000)
|
||||
{
|
||||
const uint8_t *u = unique_device_id () + 8;
|
||||
const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0);
|
||||
|
||||
memcpy (res_p, openpgpcard_aid, 8);
|
||||
res_p += 8;
|
||||
@@ -663,11 +678,9 @@ do_openpgpcard_aid (uint16_t tag, int with_tag)
|
||||
|
||||
*res_p++ = 0;
|
||||
*res_p++ = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
do_ds_count (uint16_t tag, int with_tag)
|
||||
{
|
||||
if (with_tag)
|
||||
@@ -679,7 +692,37 @@ do_ds_count (uint16_t tag, int with_tag)
|
||||
*res_p++ = (digital_signature_counter >> 16) & 0xff;
|
||||
*res_p++ = (digital_signature_counter >> 8) & 0xff;
|
||||
*res_p++ = digital_signature_counter & 0xff;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
do_alg_info (uint16_t tag, int with_tag)
|
||||
{
|
||||
uint8_t *len_p = NULL;
|
||||
int i;
|
||||
|
||||
if (with_tag)
|
||||
{
|
||||
copy_tag (tag);
|
||||
len_p = res_p;
|
||||
*res_p++ = 0; /* Filled later, assuming length is <= 127 */
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
uint16_t tag_algo = GPG_DO_ALG_SIG + i;
|
||||
|
||||
copy_do_1 (tag_algo, algorithm_attr_rsa2k, 1);
|
||||
copy_do_1 (tag_algo, algorithm_attr_rsa4k, 1);
|
||||
copy_do_1 (tag_algo, algorithm_attr_p256r1, 1);
|
||||
copy_do_1 (tag_algo, algorithm_attr_p256k1, 1);
|
||||
if (i == 0 || i == 2)
|
||||
copy_do_1 (tag_algo, algorithm_attr_ed25519, 1);
|
||||
if (i == 1)
|
||||
copy_do_1 (tag_algo, algorithm_attr_cv25519, 1);
|
||||
};
|
||||
|
||||
if (len_p)
|
||||
*len_p = res_p - len_p - 1; /* Actually, it's 127-byte long. */
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -772,6 +815,8 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
|
||||
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
|
||||
{
|
||||
gpg_reset_algo_attr (kk);
|
||||
/* Read it again, since GC may occur. */
|
||||
algo_attr_pp = get_algo_attr_pointer (kk);
|
||||
flash_enum_clear (algo_attr_pp);
|
||||
if (*algo_attr_pp != NULL)
|
||||
return 0;
|
||||
@@ -780,6 +825,10 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
|
||||
(*algo_attr_pp != NULL && (*algo_attr_pp)[1] != algo))
|
||||
{
|
||||
gpg_reset_algo_attr (kk);
|
||||
/* Read it again, since GC may occur. */
|
||||
algo_attr_pp = get_algo_attr_pointer (kk);
|
||||
if (*algo_attr_pp)
|
||||
flash_enum_clear (algo_attr_pp);
|
||||
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
|
||||
if (*algo_attr_pp == NULL)
|
||||
return 0;
|
||||
@@ -799,6 +848,229 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t uif_flags; /* Six bits of flags */
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
int
|
||||
gpg_do_get_uif (enum kind_of_key kk)
|
||||
{
|
||||
return ((uif_flags >> (kk * 2)) & 3) != 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rw_uif (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
|
||||
{
|
||||
uint8_t nr;
|
||||
int v;
|
||||
|
||||
if (tag != GPG_DO_UIF_SIG && tag != GPG_DO_UIF_DEC && tag != GPG_DO_UIF_AUT)
|
||||
return 0; /* Failure */
|
||||
|
||||
nr = (tag - GPG_DO_UIF_SIG) + NR_DO_UIF_SIG;
|
||||
v = (uif_flags >> ((tag - GPG_DO_UIF_SIG) * 2)) & 3;
|
||||
if (is_write)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
if (len != 2 || data[1] != 0x20)
|
||||
return 0;
|
||||
|
||||
if (v == 2)
|
||||
return 0;
|
||||
|
||||
if (data[0] != 0x00 && data[0] != 0x01 && data[0] != 0x02)
|
||||
return 0;
|
||||
|
||||
p = flash_enum_write (nr, data[0]);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
|
||||
uif_flags |= (data[0] & 3) << ((nr - NR_DO_UIF_SIG) * 2);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (with_tag)
|
||||
{
|
||||
copy_tag (tag);
|
||||
*res_p++ = 2;
|
||||
}
|
||||
|
||||
*res_p++ = v;
|
||||
*res_p++ = 0x20;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define SIZE_OF_KDF_DO_MIN 90
|
||||
#define SIZE_OF_KDF_DO_MAX 110
|
||||
#define OPENPGP_KDF_ITERSALTED_S2K 3
|
||||
#define OPENPGP_SHA256 8
|
||||
|
||||
static int
|
||||
rw_kdf (uint16_t tag, int with_tag, const uint8_t *data, int len, int is_write)
|
||||
{
|
||||
if (tag != GPG_DO_KDF)
|
||||
return 0; /* Failure */
|
||||
|
||||
if (is_write)
|
||||
{
|
||||
const uint8_t **do_data_p = (const uint8_t **)&do_ptr[NR_DO_KDF];
|
||||
|
||||
/* KDF DO can be changed only when no keys are registered. */
|
||||
if (do_ptr[NR_DO_PRVKEY_SIG] || do_ptr[NR_DO_PRVKEY_DEC]
|
||||
|| do_ptr[NR_DO_PRVKEY_AUT])
|
||||
return 0;
|
||||
|
||||
/* The valid data format is:
|
||||
Deleting:
|
||||
nothing
|
||||
Minimum (for admin-less):
|
||||
81 01 03 = KDF_ITERSALTED_S2K
|
||||
82 01 08 = SHA256
|
||||
83 04 4-byte... = count
|
||||
84 08 8-byte... = salt
|
||||
87 20 32-byte user hash
|
||||
88 20 32-byte admin hash
|
||||
Full:
|
||||
81 01 03 = KDF_ITERSALTED_S2K
|
||||
82 01 08 = SHA256
|
||||
83 04 4-byte... = count
|
||||
84 08 8-byte... = salt user
|
||||
85 08 8-byte... = salt reset-code
|
||||
86 08 8-byte... = salt admin
|
||||
87 20 32-byte user hash
|
||||
88 20 32-byte admin hash
|
||||
*/
|
||||
if (!(len == 0
|
||||
|| (len == SIZE_OF_KDF_DO_MIN &&
|
||||
(data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83
|
||||
&& data[12] == 0x84 && data[22] == 0x87 && data[56] == 0x88))
|
||||
|| (len == SIZE_OF_KDF_DO_MAX &&
|
||||
(data[0] == 0x81 && data[3] == 0x82 && data[6] == 0x83
|
||||
&& data[12] == 0x84 && data[22] == 0x85 && data[32] == 0x86
|
||||
&& data[42] == 0x87 && data[76] == 0x88))))
|
||||
return 0;
|
||||
|
||||
if (*do_data_p)
|
||||
flash_do_release (*do_data_p);
|
||||
|
||||
/* Clear all keystrings and auth states */
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, NULL, 0);
|
||||
ac_reset_admin ();
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
*do_data_p = NULL;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*do_data_p = flash_do_write (NR_DO_KDF, data, len);
|
||||
if (*do_data_p)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_ptr[NR_DO_KDF])
|
||||
copy_do_1 (tag, do_ptr[NR_DO_KDF], with_tag);
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check LEN is valid for HOW_MANY of passphrase string.
|
||||
*
|
||||
* HOW_MANY = 1: LEN is valid for a single passphrase string.
|
||||
* HOW_MANY = 2: LEN is valid for two single passphrase strings.
|
||||
* This is used to change passphrase.
|
||||
* The second passphrase may be nothing.
|
||||
*
|
||||
* LEN = 0: Check if KDF-DO is available.
|
||||
*/
|
||||
int
|
||||
gpg_do_kdf_check (int len, int how_many)
|
||||
{
|
||||
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
|
||||
|
||||
if (len == 0)
|
||||
return kdf_do != NULL;
|
||||
|
||||
if (kdf_do)
|
||||
{
|
||||
const uint8_t *kdf_spec = kdf_do+1;
|
||||
int kdf_do_len = kdf_do[0];
|
||||
int hash_len;
|
||||
|
||||
if (kdf_do_len == SIZE_OF_KDF_DO_MIN)
|
||||
hash_len = kdf_spec[23];
|
||||
else
|
||||
hash_len = kdf_spec[43];
|
||||
|
||||
if ((hash_len * how_many) != len && hash_len != len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_get_initial_pw_setting (int is_pw3, int *r_len, const uint8_t **r_p)
|
||||
{
|
||||
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
|
||||
|
||||
if (kdf_do)
|
||||
{
|
||||
int len = kdf_do[0];
|
||||
const uint8_t *kdf_spec = kdf_do+1;
|
||||
|
||||
*r_len = 32;
|
||||
|
||||
if (len == SIZE_OF_KDF_DO_MIN)
|
||||
{
|
||||
if (is_pw3)
|
||||
*r_p = kdf_spec + 58;
|
||||
else
|
||||
*r_p = kdf_spec + 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_pw3)
|
||||
*r_p = kdf_spec + 78;
|
||||
else
|
||||
*r_p = kdf_spec + 44;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_pw3)
|
||||
{
|
||||
*r_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r_len = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
*r_p = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
proc_resetting_code (const uint8_t *data, int len)
|
||||
{
|
||||
@@ -812,31 +1084,45 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
|
||||
DEBUG_INFO ("Resetting Code!\r\n");
|
||||
|
||||
newpw_len = len;
|
||||
newpw = data;
|
||||
new_ks0[0] = newpw_len;
|
||||
random_get_salt (salt);
|
||||
s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
return 0;
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
return 0;
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
DEBUG_INFO ("error (no prvkey).\r\n");
|
||||
return 0;
|
||||
if (len == 0)
|
||||
{ /* Removal of resetting code. */
|
||||
enum kind_of_key kk0;
|
||||
|
||||
for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++)
|
||||
gpg_do_chks_prvkey (kk0, BY_RESETCODE, NULL, 0, NULL);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE);
|
||||
if (gpg_do_kdf_check (len, 1) == 0)
|
||||
return 0;
|
||||
|
||||
newpw_len = len;
|
||||
newpw = data;
|
||||
new_ks0[0] = newpw_len;
|
||||
random_get_salt (salt);
|
||||
s2k (salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
return 0;
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
return 0;
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
DEBUG_INFO ("error (no prvkey).\r\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KS_META_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
gpg_pw_reset_err_counter (PW_ERR_RC);
|
||||
@@ -848,7 +1134,7 @@ encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
|
||||
{
|
||||
aes_context aes;
|
||||
uint8_t iv0[INITIAL_VECTOR_SIZE];
|
||||
unsigned int iv_offset;
|
||||
size_t iv_offset;
|
||||
|
||||
DEBUG_INFO ("ENC\r\n");
|
||||
DEBUG_BINARY (data, len);
|
||||
@@ -867,7 +1153,7 @@ decrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
|
||||
{
|
||||
aes_context aes;
|
||||
uint8_t iv0[INITIAL_VECTOR_SIZE];
|
||||
unsigned int iv_offset;
|
||||
size_t iv_offset;
|
||||
|
||||
aes_setkey_enc (&aes, key, 128); /* This is setkey_enc, because of CFB. */
|
||||
memcpy (iv0, iv, INITIAL_VECTOR_SIZE);
|
||||
@@ -1083,14 +1369,16 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
int attr = gpg_get_algo_attr (kk);;
|
||||
const uint8_t *p;
|
||||
int r;
|
||||
struct prvkey_data *pd;
|
||||
struct prvkey_data prv;
|
||||
struct prvkey_data *pd = &prv;
|
||||
uint8_t *key_addr;
|
||||
const uint8_t *dek, *iv;
|
||||
struct key_data_internal kdi;
|
||||
uint8_t *pubkey_allocated_here = NULL;
|
||||
int pubkey_len;
|
||||
uint8_t ks[KEYSTRING_MD_SIZE];
|
||||
enum kind_of_key kk0;
|
||||
int pw_len;
|
||||
const uint8_t *initial_pw;
|
||||
|
||||
DEBUG_INFO ("Key import\r\n");
|
||||
DEBUG_SHORT (prvkey_len);
|
||||
@@ -1098,10 +1386,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
/* Delete it first, if any. */
|
||||
gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
if (pd == NULL)
|
||||
return -1;
|
||||
|
||||
if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
pubkey_len = prvkey_len * 2;
|
||||
@@ -1129,38 +1413,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pubkey == NULL)
|
||||
{
|
||||
if (attr == ALGO_SECP256K1)
|
||||
pubkey_allocated_here = ecc_compute_public_p256k1 (key_data);
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
|
||||
else if (attr == ALGO_ED25519)
|
||||
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
|
||||
else if (attr == ALGO_CURVE25519)
|
||||
pubkey_allocated_here = ecdh_compute_public_25519 (key_data);
|
||||
else /* RSA */
|
||||
pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
|
||||
|
||||
if (pubkey_allocated_here == NULL)
|
||||
{
|
||||
free (pd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO ("Getting keystore address...\r\n");
|
||||
key_addr = flash_key_alloc (kk);
|
||||
if (key_addr == NULL)
|
||||
{
|
||||
if (pubkey_allocated_here)
|
||||
{
|
||||
memset (pubkey_allocated_here, 0, pubkey_len);
|
||||
free (pubkey_allocated_here);
|
||||
}
|
||||
free (pd);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
|
||||
kd[kk].pubkey = key_addr + prvkey_len;
|
||||
|
||||
num_prv_keys++;
|
||||
@@ -1179,8 +1436,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
s2k (NULL, 0, (const uint8_t *)OPENPGP_CARD_INITIAL_PW1,
|
||||
strlen (OPENPGP_CARD_INITIAL_PW1), ks);
|
||||
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
|
||||
s2k (NULL, 0, initial_pw, pw_len, ks);
|
||||
|
||||
/* Handle existing keys and keystring DOs. */
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
|
||||
@@ -1196,19 +1453,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
|
||||
|
||||
r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len,
|
||||
pubkey_allocated_here? pubkey_allocated_here: pubkey,
|
||||
pubkey_len);
|
||||
if (pubkey_allocated_here)
|
||||
{
|
||||
memset (pubkey_allocated_here, 0, pubkey_len);
|
||||
free (pubkey_allocated_here);
|
||||
}
|
||||
|
||||
pubkey, pubkey_len);
|
||||
if (r < 0)
|
||||
{
|
||||
random_bytes_free (dek);
|
||||
memset (pd, 0, sizeof (struct prvkey_data));
|
||||
free (pd);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1230,7 +1479,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
|
||||
|
||||
random_bytes_free (dek);
|
||||
memset (pd, 0, sizeof (struct prvkey_data));
|
||||
free (pd);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -1262,18 +1510,15 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
uint8_t nr = get_do_ptr_nr_for_kk (kk);
|
||||
const uint8_t *do_data = do_ptr[nr];
|
||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||
struct prvkey_data *pd;
|
||||
const uint8_t *p;
|
||||
struct prvkey_data prv;
|
||||
struct prvkey_data *pd = &prv;
|
||||
uint8_t *dek_p;
|
||||
int update_needed = 0;
|
||||
int r = 1; /* Success */
|
||||
|
||||
if (do_data == NULL)
|
||||
return 0; /* No private key */
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
if (pd == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
|
||||
|
||||
dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE
|
||||
@@ -1304,18 +1549,19 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
|
||||
if (update_needed)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
flash_do_release (do_data);
|
||||
do_ptr[nr] = NULL;
|
||||
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_ptr[nr] = p;
|
||||
if (p == NULL)
|
||||
r = -1;
|
||||
}
|
||||
|
||||
memset (pd, 0, sizeof (struct prvkey_data));
|
||||
free (pd);
|
||||
if (update_needed && p == NULL)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -1370,6 +1616,14 @@ proc_key_import (const uint8_t *data, int len)
|
||||
const uint8_t *keystring_admin;
|
||||
int attr;
|
||||
const uint8_t *p = data;
|
||||
uint8_t pubkey[512];
|
||||
|
||||
#ifdef KDF_DO_REQUIRED
|
||||
const uint8_t *kdf_do = do_ptr[NR_DO_KDF];
|
||||
|
||||
if (kdf_do == NULL)
|
||||
return 0; /* Error. */
|
||||
#endif
|
||||
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
@@ -1409,13 +1663,35 @@ proc_key_import (const uint8_t *data, int len)
|
||||
}
|
||||
|
||||
if (attr == ALGO_RSA2K)
|
||||
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
|
||||
{
|
||||
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
|
||||
r = modulus_calc (&data[26], len - 26, pubkey);
|
||||
if (r >= 0)
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin,
|
||||
pubkey);
|
||||
}
|
||||
else if (attr == ALGO_RSA4K)
|
||||
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
|
||||
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, NULL);
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
|
||||
{
|
||||
/* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
|
||||
r = modulus_calc (&data[28], len - 28, pubkey);
|
||||
if (r >= 0)
|
||||
r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin,
|
||||
pubkey);
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
{
|
||||
r = ecc_compute_public_p256r1 (&data[12], pubkey);
|
||||
if (r >= 0)
|
||||
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
|
||||
pubkey);
|
||||
}
|
||||
else if (attr == ALGO_SECP256K1)
|
||||
{
|
||||
r = ecc_compute_public_p256k1 (&data[12], pubkey);
|
||||
if (r >= 0)
|
||||
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
|
||||
pubkey);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
uint8_t hash[64];
|
||||
@@ -1427,7 +1703,8 @@ proc_key_import (const uint8_t *data, int len)
|
||||
hash[0] &= 248;
|
||||
hash[31] &= 127;
|
||||
hash[31] |= 64;
|
||||
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
|
||||
eddsa_compute_public_25519 (hash, pubkey);
|
||||
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, pubkey);
|
||||
}
|
||||
else if (attr == ALGO_CURVE25519)
|
||||
{
|
||||
@@ -1439,7 +1716,8 @@ proc_key_import (const uint8_t *data, int len)
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
priv[31-i] = data[12+i];
|
||||
r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, NULL);
|
||||
ecdh_compute_public_25519 (priv, pubkey);
|
||||
r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, pubkey);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
@@ -1456,18 +1734,32 @@ static const uint16_t cmp_ch_data[] = {
|
||||
};
|
||||
|
||||
static const uint16_t cmp_app_data[] = {
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
4,
|
||||
#else
|
||||
3,
|
||||
#endif
|
||||
GPG_DO_AID,
|
||||
GPG_DO_HIST_BYTES,
|
||||
GPG_DO_DISCRETIONARY,
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
GPG_DO_FEATURE_MNGMNT,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const uint16_t cmp_discretionary[] = {
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
11,
|
||||
#else
|
||||
8,
|
||||
#endif
|
||||
GPG_DO_EXTCAP,
|
||||
GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
|
||||
GPG_DO_PW_STATUS,
|
||||
GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL
|
||||
GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL,
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
GPG_DO_UIF_SIG, GPG_DO_UIF_DEC, GPG_DO_UIF_AUT
|
||||
#endif
|
||||
};
|
||||
|
||||
static const uint16_t cmp_ss_temp[] = { 1, GPG_DO_DS_COUNT };
|
||||
@@ -1497,6 +1789,7 @@ gpg_do_table[] = {
|
||||
/* Pseudo DO READ: calculated, not changeable by user */
|
||||
{ GPG_DO_DS_COUNT, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_ds_count },
|
||||
{ GPG_DO_AID, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_openpgpcard_aid },
|
||||
{ GPG_DO_ALG_INFO, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_alg_info },
|
||||
/* Pseudo DO READ/WRITE: calculated */
|
||||
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
||||
rw_pw_status },
|
||||
@@ -1506,9 +1799,19 @@ gpg_do_table[] = {
|
||||
rw_algorithm_attr },
|
||||
{ GPG_DO_ALG_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
||||
rw_algorithm_attr },
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
{ GPG_DO_UIF_SIG, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
|
||||
{ GPG_DO_UIF_DEC, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
|
||||
{ GPG_DO_UIF_AUT, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, rw_uif },
|
||||
#endif
|
||||
{ GPG_DO_KDF, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
|
||||
rw_kdf },
|
||||
/* Fixed data */
|
||||
{ GPG_DO_HIST_BYTES, DO_FIXED, AC_ALWAYS, AC_NEVER, historical_bytes },
|
||||
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
{ GPG_DO_FEATURE_MNGMNT, DO_FIXED, AC_ALWAYS, AC_NEVER, feature_mngmnt },
|
||||
#endif
|
||||
/* Compound data: Read access only */
|
||||
{ GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
|
||||
{ GPG_DO_APP_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_app_data },
|
||||
@@ -1547,6 +1850,11 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
|
||||
pw_err_counter_p[PW_ERR_PW3] = NULL;
|
||||
algo_attr_sig_p = algo_attr_dec_p = algo_attr_aut_p = NULL;
|
||||
digital_signature_counter = 0;
|
||||
uif_flags = 0;
|
||||
|
||||
/* Clear all data objects. */
|
||||
for (i = 0; i < NR_DO__LAST__; i++)
|
||||
do_ptr[i] = NULL;
|
||||
|
||||
/* When the card is terminated no data objects are valid. */
|
||||
if (do_start == NULL)
|
||||
@@ -1571,7 +1879,7 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
|
||||
|
||||
p += second_byte + 1; /* second_byte has length */
|
||||
|
||||
if (((uint32_t)p & 1))
|
||||
if (((uintptr_t)p & 1))
|
||||
p++;
|
||||
}
|
||||
else if (nr >= 0x80 && nr <= 0xbf)
|
||||
@@ -1605,6 +1913,13 @@ gpg_data_scan (const uint8_t *do_start, const uint8_t *do_end)
|
||||
algo_attr_aut_p = p - 1;
|
||||
p++;
|
||||
break;
|
||||
case NR_DO_UIF_SIG:
|
||||
case NR_DO_UIF_DEC:
|
||||
case NR_DO_UIF_AUT:
|
||||
uif_flags &= ~(3 << ((nr - NR_DO_UIF_SIG) * 2));
|
||||
uif_flags |= (second_byte & 3) << ((nr - NR_DO_UIF_SIG) * 2);
|
||||
p++;
|
||||
break;
|
||||
case NR_COUNTER_123:
|
||||
p++;
|
||||
if (second_byte <= PW_ERR_PW3)
|
||||
@@ -1704,6 +2019,13 @@ gpg_data_copy (const uint8_t *p_start)
|
||||
p += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
if ((v = (uif_flags >> (i * 2)) & 3))
|
||||
{
|
||||
flash_enum_write_internal (p, NR_DO_UIF_SIG + i, v);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
data_objects_number_of_bytes = 0;
|
||||
for (i = 0; i < NR_DO__LAST__; i++)
|
||||
if (do_ptr[i] != NULL)
|
||||
@@ -1817,9 +2139,10 @@ copy_do (const struct do_table_entry *do_p, int with_tag)
|
||||
}
|
||||
case DO_PROC_READ:
|
||||
{
|
||||
int (*do_func)(uint16_t, int) = (int (*)(uint16_t, int))do_p->obj;
|
||||
void (*do_func)(uint16_t, int) = (void (*)(uint16_t, int))do_p->obj;
|
||||
|
||||
return do_func (do_p->tag, with_tag);
|
||||
do_func (do_p->tag, with_tag);
|
||||
return 1;
|
||||
}
|
||||
case DO_PROC_READWRITE:
|
||||
{
|
||||
@@ -2076,44 +2399,37 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_keygen (uint8_t kk_byte)
|
||||
gpg_do_keygen (uint8_t *buf)
|
||||
{
|
||||
uint8_t kk_byte = buf[0];
|
||||
enum kind_of_key kk = kkb_to_kk (kk_byte);
|
||||
int attr = gpg_get_algo_attr (kk);;
|
||||
int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE);
|
||||
const uint8_t *keystring_admin;
|
||||
uint8_t *p_q_modulus = NULL;
|
||||
uint8_t d[64];
|
||||
const uint8_t *rnd;
|
||||
const uint8_t *prv;
|
||||
const uint8_t *pubkey;
|
||||
int r;
|
||||
const uint8_t *rnd;
|
||||
int r = 0;
|
||||
#define p_q (&buf[3])
|
||||
#define d (&buf[3])
|
||||
#define d1 (&buf[3+64])
|
||||
#define pubkey (&buf[3+256])
|
||||
|
||||
DEBUG_INFO ("Keygen\r\n");
|
||||
DEBUG_BYTE (kk_byte);
|
||||
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
else
|
||||
keystring_admin = NULL;
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
p_q_modulus = rsa_genkey (prvkey_len);
|
||||
if (p_q_modulus == NULL)
|
||||
if (rsa_genkey (prvkey_len, pubkey, p_q) < 0)
|
||||
{
|
||||
GPG_MEMORY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
prv = p_q_modulus;
|
||||
pubkey = p_q_modulus + prvkey_len;
|
||||
prv = p_q;
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
uint8_t d1[32];
|
||||
const uint8_t *p;
|
||||
int i, r;
|
||||
int i;
|
||||
|
||||
rnd = NULL;
|
||||
do
|
||||
@@ -2140,7 +2456,10 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
random_bytes_free (rnd);
|
||||
|
||||
prv = d;
|
||||
pubkey = NULL;
|
||||
if (attr == ALGO_SECP256K1)
|
||||
r = ecc_compute_public_p256k1 (prv, pubkey);
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
r = ecc_compute_public_p256r1 (prv, pubkey);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
@@ -2151,7 +2470,7 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
prv = d;
|
||||
pubkey = NULL;
|
||||
eddsa_compute_public_25519 (d, pubkey);
|
||||
}
|
||||
else if (attr == ALGO_CURVE25519)
|
||||
{
|
||||
@@ -2162,7 +2481,7 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
prv = d;
|
||||
pubkey = NULL;
|
||||
ecdh_compute_public_25519 (prv, pubkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2170,12 +2489,21 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
return;
|
||||
}
|
||||
|
||||
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
|
||||
if (p_q_modulus)
|
||||
if (r >= 0)
|
||||
{
|
||||
memset (p_q_modulus, 0, prvkey_len * 2);
|
||||
free (p_q_modulus);
|
||||
const uint8_t *keystring_admin;
|
||||
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
else
|
||||
keystring_admin = NULL;
|
||||
|
||||
r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
|
||||
}
|
||||
|
||||
/* Clear private key data in the buffer. */
|
||||
memset (buf, 0, 256);
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
GPG_ERROR ();
|
||||
@@ -2186,14 +2514,16 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
const uint8_t *pw = (const uint8_t *)OPENPGP_CARD_INITIAL_PW1;
|
||||
int pw_len;
|
||||
const uint8_t *initial_pw;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
|
||||
/* GnuPG expects it's ready for signing. */
|
||||
/* Don't call ac_reset_pso_cds here, but load the private key */
|
||||
|
||||
gpg_reset_digital_signature_counter ();
|
||||
s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
|
||||
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
|
||||
s2k (NULL, 0, initial_pw, pw_len, keystring);
|
||||
gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
}
|
||||
else
|
||||
|
||||
252
src/openpgp.c
252
src/openpgp.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -37,6 +38,7 @@
|
||||
|
||||
static struct eventflag *openpgp_comm;
|
||||
|
||||
#define USER_PASSWD_MINLEN 6
|
||||
#define ADMIN_PASSWD_MINLEN 8
|
||||
|
||||
#define CLS(a) a.cmd_apdu_head[0]
|
||||
@@ -108,7 +110,7 @@ gpg_init (void)
|
||||
const uint8_t *flash_do_start;
|
||||
const uint8_t *flash_do_end;
|
||||
|
||||
flash_init (&flash_do_start, &flash_do_end);
|
||||
flash_do_storage_init (&flash_do_start, &flash_do_end);
|
||||
|
||||
if (flash_do_start == NULL)
|
||||
file_selection = FILE_CARD_TERMINATED;
|
||||
@@ -116,7 +118,7 @@ gpg_init (void)
|
||||
file_selection = FILE_NONE;
|
||||
|
||||
gpg_data_scan (flash_do_start, flash_do_end);
|
||||
flash_init_keys ();
|
||||
flash_key_storage_init ();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -144,7 +146,7 @@ get_pinpad_input (int msg_code)
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_verify (void)
|
||||
cmd_verify (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len;
|
||||
uint8_t p1 = P1 (apdu);
|
||||
@@ -152,6 +154,7 @@ cmd_verify (void)
|
||||
int r;
|
||||
const uint8_t *pw;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
DEBUG_BYTE (p2);
|
||||
|
||||
@@ -170,7 +173,8 @@ cmd_verify (void)
|
||||
r = ac_check_status (AC_ADMIN_AUTHORIZED);
|
||||
|
||||
if (r)
|
||||
GPG_SUCCESS (); /* If authentication done already, return success. */
|
||||
/* If authentication done already, return success. */
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
{ /* If not, return retry counter, encoded. */
|
||||
r = gpg_pw_get_retry_counter (p2);
|
||||
@@ -192,6 +196,12 @@ cmd_verify (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 1) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is real authentication. */
|
||||
if (p2 == 0x81)
|
||||
r = verify_pso_cds (pw, len);
|
||||
@@ -267,7 +277,7 @@ gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_change_password (void)
|
||||
cmd_change_password (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
uint8_t new_ks0[KEYSTRING_SIZE];
|
||||
@@ -287,6 +297,7 @@ cmd_change_password (void)
|
||||
int salt_len;
|
||||
const uint8_t *ks_pw3;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
DEBUG_BYTE (who);
|
||||
|
||||
@@ -299,6 +310,12 @@ cmd_change_password (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 2) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (who == BY_USER) /* PW1 */
|
||||
{
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
@@ -335,8 +352,9 @@ cmd_change_password (void)
|
||||
newpw_len = len - pw_len;
|
||||
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
|
||||
/* Check length of password for admin-less mode. */
|
||||
if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
/* Check length of password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
@@ -351,8 +369,24 @@ cmd_change_password (void)
|
||||
|
||||
if (ks_pw3 == NULL)
|
||||
{
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
if (admin_authorized == BY_USER)
|
||||
{
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (ks_pw1 == NULL)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
salt = KS_GET_SALT (ks_pw1);
|
||||
salt_len = SALT_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -376,13 +410,22 @@ cmd_change_password (void)
|
||||
{
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
|
||||
if (newpw_len == 0 && admin_authorized == BY_ADMIN)
|
||||
{
|
||||
newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
|
||||
const uint8_t *initial_pw;
|
||||
|
||||
gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw);
|
||||
memcpy (newpw, initial_pw, newpw_len);
|
||||
newsalt_len = 0;
|
||||
pw3_null = 1;
|
||||
}
|
||||
else if (newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
who_old = admin_authorized;
|
||||
}
|
||||
@@ -412,11 +455,26 @@ cmd_change_password (void)
|
||||
}
|
||||
else if (r > 0 && who == BY_USER)
|
||||
{
|
||||
/* When it was already admin-less mode, admin_authorized is
|
||||
* BY_USER. If no PW3 keystring, it's becoming admin-less mode,
|
||||
* now. For these two cases, we need to reset admin
|
||||
* authorization status. */
|
||||
if (admin_authorized == BY_USER)
|
||||
ac_reset_admin ();
|
||||
else if (ks_pw3 == NULL)
|
||||
{
|
||||
enum kind_of_key kk0;
|
||||
|
||||
/* Remove keystrings for BY_ADMIN. */
|
||||
for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++)
|
||||
gpg_do_chks_prvkey (kk0, BY_ADMIN, NULL, 0, NULL);
|
||||
|
||||
ac_reset_admin ();
|
||||
}
|
||||
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
|
||||
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 ();
|
||||
}
|
||||
@@ -492,7 +550,7 @@ s2k (const unsigned char *salt, size_t slen,
|
||||
|
||||
|
||||
static void
|
||||
cmd_reset_user_password (void)
|
||||
cmd_reset_user_password (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t p1 = P1 (apdu);
|
||||
int len;
|
||||
@@ -503,9 +561,11 @@ cmd_reset_user_password (void)
|
||||
uint8_t new_ks0[KEYSTRING_SIZE];
|
||||
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
|
||||
uint8_t *new_salt = KS_GET_SALT (new_ks0);
|
||||
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO ("Reset PW1\r\n");
|
||||
DEBUG_BYTE (p1);
|
||||
|
||||
@@ -517,6 +577,12 @@ cmd_reset_user_password (void)
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
|
||||
if (gpg_do_kdf_check (len, 2) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_pw_locked (PW_ERR_RC))
|
||||
{
|
||||
DEBUG_INFO ("blocked.\r\n");
|
||||
@@ -536,6 +602,16 @@ cmd_reset_user_password (void)
|
||||
salt_len = SALT_SIZE;
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
|
||||
/* Check length of new password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
random_get_salt (new_salt);
|
||||
s2k (salt, salt_len, pw, pw_len, old_ks);
|
||||
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
@@ -581,8 +657,24 @@ cmd_reset_user_password (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 1) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
newpw_len = len;
|
||||
newpw = pw;
|
||||
|
||||
/* Check length of new password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
random_get_salt (new_salt);
|
||||
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
@@ -617,12 +709,13 @@ cmd_reset_user_password (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_put_data (void)
|
||||
cmd_put_data (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint16_t tag;
|
||||
int len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - PUT DATA\r\n");
|
||||
|
||||
tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||
@@ -632,8 +725,9 @@ cmd_put_data (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_pgp_gakp (void)
|
||||
cmd_pgp_gakp (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
|
||||
@@ -644,19 +738,26 @@ cmd_pgp_gakp (void)
|
||||
{
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
GPG_SECURITY_FAILURE ();
|
||||
gpg_do_keygen (apdu.cmd_apdu_data[0]);
|
||||
#ifdef KDF_DO_REQUIRED
|
||||
else if (!gpg_do_kdf_check (0, 0))
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
#endif
|
||||
else
|
||||
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
const uint8_t *
|
||||
gpg_get_firmware_update_key (uint8_t keyno)
|
||||
{
|
||||
extern uint8_t _updatekey_store;
|
||||
extern uint8_t _updatekey_store[1024];
|
||||
const uint8_t *p;
|
||||
|
||||
p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
p = _updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CERTDO_SUPPORT
|
||||
#define FILEID_CH_CERTIFICATE_IS_VALID 1
|
||||
@@ -665,13 +766,13 @@ gpg_get_firmware_update_key (uint8_t keyno)
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_read_binary (void)
|
||||
cmd_read_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int is_short_EF = (P1 (apdu) & 0x80) != 0;
|
||||
uint8_t file_id;
|
||||
const uint8_t *p;
|
||||
uint16_t offset;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Read binary\r\n");
|
||||
|
||||
if (is_short_EF)
|
||||
@@ -679,13 +780,6 @@ cmd_read_binary (void)
|
||||
else
|
||||
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
|
||||
|
||||
if ((!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE)
|
||||
|| file_id > FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_short_EF)
|
||||
{
|
||||
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
|
||||
@@ -705,22 +799,26 @@ cmd_read_binary (void)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
{
|
||||
if (offset != 0)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
else
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
|
||||
res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
else /* file_id == FILEID_CH_CERTIFICATE */
|
||||
else if (file_id == FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
const uint8_t *p;
|
||||
uint16_t len = 256;
|
||||
|
||||
p = &ch_certificate_start;
|
||||
@@ -737,11 +835,17 @@ cmd_read_binary (void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_select_file (void)
|
||||
cmd_select_file (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
if (P1 (apdu) == 4) /* Selection by DF name */
|
||||
{
|
||||
DEBUG_INFO (" - select DF by name\r\n");
|
||||
@@ -810,10 +914,11 @@ cmd_select_file (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_get_data (void)
|
||||
cmd_get_data (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Get Data\r\n");
|
||||
|
||||
gpg_do_get_data (tag, 0);
|
||||
@@ -828,7 +933,7 @@ cmd_get_data (void)
|
||||
#define ECC_CIPHER_DO_HEADER_SIZE 7
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
cmd_pso (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r = -1;
|
||||
@@ -855,6 +960,11 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
/* Check size of digestInfo */
|
||||
@@ -900,13 +1010,6 @@ cmd_pso (void)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
@@ -946,6 +1049,13 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#else
|
||||
(void)ccid_comm;
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
/* Skip padding 0x00 */
|
||||
@@ -1022,7 +1132,7 @@ cmd_pso (void)
|
||||
|
||||
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
cmd_internal_authenticate (struct eventflag *ccid_comm)
|
||||
{
|
||||
int attr = gpg_get_algo_attr (GPG_KEY_FOR_AUTHENTICATION);
|
||||
int pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_AUTHENTICATION,
|
||||
@@ -1052,6 +1162,13 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#else
|
||||
(void)ccid_comm;
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
if (len > MAX_RSA_DIGEST_INFO_LEN)
|
||||
@@ -1099,13 +1216,6 @@ cmd_internal_authenticate (void)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
@@ -1200,6 +1310,7 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3
|
||||
&& len == 0 && offset == 0)
|
||||
{
|
||||
@@ -1216,9 +1327,10 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
if (i == 4) /* all update keys are removed */
|
||||
{
|
||||
p = gpg_get_firmware_update_key (0);
|
||||
flash_erase_page ((uint32_t)p);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -1226,10 +1338,11 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
static void
|
||||
cmd_update_binary (void)
|
||||
cmd_update_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||
modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len);
|
||||
DEBUG_INFO ("UPDATE BINARY done.\r\n");
|
||||
@@ -1238,18 +1351,20 @@ cmd_update_binary (void)
|
||||
|
||||
|
||||
static void
|
||||
cmd_write_binary (void)
|
||||
cmd_write_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
|
||||
DEBUG_INFO ("WRITE BINARY done.\r\n");
|
||||
}
|
||||
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
static void
|
||||
cmd_external_authenticate (void)
|
||||
cmd_external_authenticate (struct eventflag *ccid_comm)
|
||||
{
|
||||
const uint8_t *pubkey;
|
||||
const uint8_t *signature = apdu.cmd_apdu_data;
|
||||
@@ -1257,6 +1372,7 @@ cmd_external_authenticate (void)
|
||||
uint8_t keyno = P2 (apdu);
|
||||
int r;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (keyno >= 4)
|
||||
@@ -1289,12 +1405,14 @@ cmd_external_authenticate (void)
|
||||
set_res_sw (0xff, 0xff);
|
||||
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_get_challenge (void)
|
||||
cmd_get_challenge (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.expected_res_size;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - GET CHALLENGE\r\n");
|
||||
|
||||
if (len > CHALLENGE_LEN)
|
||||
@@ -1309,6 +1427,13 @@ cmd_get_challenge (void)
|
||||
if (challenge)
|
||||
random_bytes_free (challenge);
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
challenge = random_bytes_get ();
|
||||
memcpy (res_APDU, challenge, len);
|
||||
res_APDU_size = len;
|
||||
@@ -1319,8 +1444,9 @@ cmd_get_challenge (void)
|
||||
|
||||
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
|
||||
static void
|
||||
cmd_activate_file (void)
|
||||
cmd_activate_file (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
if (file_selection != FILE_CARD_TERMINATED)
|
||||
{
|
||||
GPG_NO_RECORD ();
|
||||
@@ -1333,13 +1459,13 @@ cmd_activate_file (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_terminate_df (void)
|
||||
cmd_terminate_df (struct eventflag *ccid_comm)
|
||||
{
|
||||
const uint8_t *ks_pw3;
|
||||
|
||||
uint8_t p1 = P1 (apdu);
|
||||
uint8_t p2 = P2 (apdu);
|
||||
|
||||
(void)ccid_comm;
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
{
|
||||
GPG_NO_RECORD ();
|
||||
@@ -1383,7 +1509,7 @@ cmd_terminate_df (void)
|
||||
struct command
|
||||
{
|
||||
uint8_t command;
|
||||
void (*cmd_handler) (void);
|
||||
void (*cmd_handler) (struct eventflag *ccid_comm);
|
||||
};
|
||||
|
||||
const struct command cmds[] = {
|
||||
@@ -1395,8 +1521,10 @@ const struct command cmds[] = {
|
||||
{ INS_ACTIVATE_FILE, cmd_activate_file },
|
||||
#endif
|
||||
{ INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
{ INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */
|
||||
cmd_external_authenticate },
|
||||
#endif
|
||||
{ INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */
|
||||
{ INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
|
||||
{ INS_SELECT_FILE, cmd_select_file },
|
||||
@@ -1415,7 +1543,7 @@ const struct command cmds[] = {
|
||||
#define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
|
||||
|
||||
static void
|
||||
process_command_apdu (void)
|
||||
process_command_apdu (struct eventflag *ccid_comm)
|
||||
{
|
||||
int i;
|
||||
uint8_t cmd = INS (apdu);
|
||||
@@ -1439,7 +1567,7 @@ process_command_apdu (void)
|
||||
else
|
||||
{
|
||||
chopstx_setcancelstate (1);
|
||||
cmds[i].cmd_handler ();
|
||||
cmds[i].cmd_handler (ccid_comm);
|
||||
chopstx_setcancelstate (0);
|
||||
}
|
||||
}
|
||||
@@ -1553,7 +1681,7 @@ openpgp_card_thread (void *arg)
|
||||
break;
|
||||
|
||||
led_blink (LED_START_COMMAND);
|
||||
process_command_apdu ();
|
||||
process_command_apdu (ccid_comm);
|
||||
led_blink (LED_FINISH_COMMAND);
|
||||
done:
|
||||
eventflag_signal (ccid_comm, EV_EXEC_FINISHED);
|
||||
|
||||
@@ -40,14 +40,14 @@ cir_ext_disable (void)
|
||||
int rcvd = (EXTI->PR & EXTI_PR) != 0;
|
||||
|
||||
EXTI->IMR &= ~EXTI_IMR;
|
||||
EXTI->PR = EXTI_PR;
|
||||
EXTI->PR |= EXTI_PR;
|
||||
return rcvd;
|
||||
}
|
||||
|
||||
static void
|
||||
cir_ext_enable (void)
|
||||
{
|
||||
EXTI->PR = EXTI_PR;
|
||||
EXTI->PR |= EXTI_PR;
|
||||
EXTI->IMR |= EXTI_IMR;
|
||||
}
|
||||
|
||||
@@ -964,9 +964,14 @@ cir_timer_interrupt (void)
|
||||
}
|
||||
|
||||
|
||||
extern uint8_t __process6_stack_base__[], __process6_stack_size__[];
|
||||
#define STACK_ADDR_TIM ((uint32_t)__process6_stack_base__)
|
||||
#define STACK_SIZE_TIM ((uint32_t)__process6_stack_size__)
|
||||
#define STACK_PROCESS_6
|
||||
#define STACK_PROCESS_7
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_TIM ((uintptr_t)process6_base)
|
||||
#define STACK_SIZE_TIM (sizeof process6_base)
|
||||
#define STACK_ADDR_EXT ((uintptr_t)process7_base)
|
||||
#define STACK_SIZE_EXT (sizeof process7_base)
|
||||
|
||||
#define PRIO_TIM 4
|
||||
|
||||
static void *
|
||||
@@ -981,14 +986,13 @@ tim_main (void *arg)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
cir_timer_interrupt ();
|
||||
chopstx_intr_done (&interrupt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern uint8_t __process7_stack_base__, __process7_stack_size__;
|
||||
const uint32_t __stackaddr_ext = (uint32_t)&__process7_stack_base__;
|
||||
const size_t __stacksize_ext = (size_t)&__process7_stack_size__;
|
||||
|
||||
#define PRIO_EXT 4
|
||||
|
||||
static void *
|
||||
@@ -1003,6 +1007,7 @@ ext_main (void *arg)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
cir_ext_interrupt ();
|
||||
chopstx_intr_done (&interrupt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1030,8 +1035,8 @@ cir_init (void)
|
||||
|
||||
/* EXTIx <= Py */
|
||||
AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py;
|
||||
EXTI->IMR = 0;
|
||||
EXTI->FTSR = EXTI_FTSR_TR;
|
||||
EXTI->IMR &= ~EXTI_IMR;
|
||||
EXTI->FTSR |= EXTI_FTSR_TR;
|
||||
|
||||
/* TIM */
|
||||
#ifdef ENABLE_RCC_APB1
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha256.h"
|
||||
|
||||
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha512.h"
|
||||
|
||||
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
|
||||
|
||||
65
src/stack-def.h
Normal file
65
src/stack-def.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define SIZE_1 4096
|
||||
#define SIZE_2 4096
|
||||
#define SIZE_3 (5 * 4096)
|
||||
#else
|
||||
#define SIZE_0 0x0160 /* Main */
|
||||
#define SIZE_1 0x01a0 /* CCID */
|
||||
#define SIZE_2 0x0180 /* RNG */
|
||||
#if MEMORY_SIZE >= 32
|
||||
#define SIZE_3 0x4640 /* openpgp-card */
|
||||
#elif MEMORY_SIZE >= 24
|
||||
#define SIZE_3 0x2640 /* openpgp-card */
|
||||
#else
|
||||
#define SIZE_3 0x1640 /* openpgp-card */
|
||||
#endif
|
||||
#define SIZE_4 0x0000 /* --- */
|
||||
#define SIZE_5 0x0200 /* msc */
|
||||
#define SIZE_6 0x00c0 /* timer (cir) */
|
||||
#define SIZE_7 0x00c0 /* ext (cir) */
|
||||
#endif
|
||||
|
||||
#if defined(STACK_MAIN) && !defined(GNU_LINUX_EMULATION)
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[0x0080] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
|
||||
/* Fourth thread program */
|
||||
#if defined(STACK_PROCESS_4)
|
||||
char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4")));
|
||||
#endif
|
||||
|
||||
/* Fifth thread program */
|
||||
#if defined(STACK_PROCESS_5)
|
||||
char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5")));
|
||||
#endif
|
||||
|
||||
/* Sixth thread program */
|
||||
#if defined(STACK_PROCESS_6)
|
||||
char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6")));
|
||||
#endif
|
||||
|
||||
/* Seventh thread program */
|
||||
#if defined(STACK_PROCESS_7)
|
||||
char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7")));
|
||||
#endif
|
||||
39
src/stdaln-sys.ld.in
Normal file
39
src/stdaln-sys.ld.in
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = @ORIGIN_REAL@, len = 4k
|
||||
ram : org = 0x20000000, len = @MEMORY_SIZE@k
|
||||
}
|
||||
|
||||
__ram_start__ = ORIGIN(ram);
|
||||
__ram_size__ = LENGTH(ram);
|
||||
__ram_end__ = __ram_start__ + __ram_size__;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.sys : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
_sys = .;
|
||||
KEEP(*(.vectors))
|
||||
. = ALIGN(16);
|
||||
KEEP(*(.sys.version))
|
||||
KEEP(*(.sys.board_id))
|
||||
KEEP(*(.sys.board_name))
|
||||
build/sys-*.o(.text)
|
||||
build/sys-*.o(.text.*)
|
||||
build/sys-*.o(.rodata)
|
||||
build/sys-*.o(.rodata.*)
|
||||
. = ALIGN(1024);
|
||||
} > flash0
|
||||
|
||||
.aesft : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
*(.sys.0)
|
||||
*(.sys.1)
|
||||
*(.sys.2)
|
||||
} > flash0
|
||||
}
|
||||
13
src/stdlib.h
13
src/stdlib.h
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* stdlib.h replacement to replace malloc functions
|
||||
*/
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
|
||||
#define malloc(size) gnuk_malloc (size)
|
||||
#define free(p) gnuk_free (p)
|
||||
|
||||
void *gnuk_malloc (size_t);
|
||||
void gnuk_free (void *);
|
||||
587
src/usb-ccid.c
587
src/usb-ccid.c
File diff suppressed because it is too large
Load Diff
@@ -31,9 +31,11 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb-msc.h"
|
||||
|
||||
extern uint8_t __process5_stack_base__[], __process5_stack_size__[];
|
||||
#define STACK_ADDR_MSC ((uint32_t)__process5_stack_base__)
|
||||
#define STACK_SIZE_MSC ((uint32_t)__process5_stack_size__)
|
||||
#define STACK_PROCESS_5
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_MSC ((uintptr_t)process5_base)
|
||||
#define STACK_SIZE_MSC (sizeof process5_base)
|
||||
|
||||
#define PRIO_MSC 3
|
||||
|
||||
static chopstx_mutex_t a_pinpad_mutex;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* usb_ctrl.c - USB control pipe device specific code for Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb_conf.h"
|
||||
#include "gnuk.h"
|
||||
#include "neug.h"
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#include "usb-cdc.h"
|
||||
@@ -86,7 +87,7 @@ vcom_port_data_setup (struct usb_dev *dev)
|
||||
#include "usb-msc.h"
|
||||
#endif
|
||||
|
||||
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
|
||||
#define USB_HID_REQ_GET_REPORT 1
|
||||
#define USB_HID_REQ_GET_IDLE 2
|
||||
@@ -107,15 +108,25 @@ static uint16_t hid_report;
|
||||
#endif
|
||||
|
||||
static void
|
||||
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
gnuk_setup_endpoints_for_interface (struct usb_dev *dev,
|
||||
uint16_t interface, int stop)
|
||||
{
|
||||
#if !defined(GNU_LINUX_EMULATION)
|
||||
(void)dev;
|
||||
#endif
|
||||
|
||||
if (interface == CCID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP1, 1, 1);
|
||||
usb_lld_setup_endp (dev, ENDP2, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR,
|
||||
ENDP1_TXADDR, GNUK_MAX_PACKET_SIZE);
|
||||
usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -128,7 +139,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == HID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP7, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
|
||||
#endif
|
||||
else
|
||||
usb_lld_stall_tx (ENDP7);
|
||||
}
|
||||
@@ -137,7 +152,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == VCOM_INTERFACE_0)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP4, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
|
||||
#endif
|
||||
else
|
||||
usb_lld_stall_tx (ENDP4);
|
||||
}
|
||||
@@ -145,9 +164,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP3, 0, 1);
|
||||
usb_lld_setup_endp (dev, ENDP5, 1, 0);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0);
|
||||
usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0,
|
||||
VIRTUAL_COM_PORT_DATA_SIZE);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -160,8 +184,12 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == MSC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP6, 1, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
|
||||
ENDP6_RXADDR, ENDP6_TXADDR, 64);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
usb_lld_stall_tx (ENDP6);
|
||||
@@ -174,20 +202,17 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
void
|
||||
usb_device_reset (struct usb_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_lld_reset (dev, USB_INITIAL_FEATURE);
|
||||
|
||||
/* Initialize Endpoint 0 */
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP0, 1, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
|
||||
GNUK_MAX_PACKET_SIZE);
|
||||
64);
|
||||
#endif
|
||||
|
||||
/* Stop the interface */
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 1);
|
||||
|
||||
bDeviceState = ATTACHED;
|
||||
ccid_usb_reset (1);
|
||||
bDeviceState = USB_DEVICE_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
#define USB_CCID_REQ_ABORT 0x01
|
||||
@@ -201,22 +226,34 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
|
||||
static const uint8_t lun_table[] = { 0, 0, 0, 0, };
|
||||
#endif
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
static const uint8_t *const mem_info[] = { &_regnual_start, __heap_end__, };
|
||||
#endif
|
||||
|
||||
#define USB_FSIJ_GNUK_MEMINFO 0
|
||||
#define USB_FSIJ_GNUK_DOWNLOAD 1
|
||||
#define USB_FSIJ_GNUK_EXEC 2
|
||||
#define USB_FSIJ_GNUK_CARD_CHANGE 3
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/* After calling this function, CRC module remain enabled. */
|
||||
static int
|
||||
download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
|
||||
{
|
||||
if (check_crc32 ((const uint32_t *)&_regnual_start, end_p))
|
||||
uint32_t crc32 = *end_p;
|
||||
const uint32_t *p;
|
||||
|
||||
crc32_rv_reset ();
|
||||
|
||||
for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
|
||||
crc32_rv_step (rbit (*p));
|
||||
|
||||
if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
usb_setup (struct usb_dev *dev)
|
||||
@@ -228,16 +265,23 @@ usb_setup (struct usb_dev *dev)
|
||||
{
|
||||
if (USB_SETUP_GET (arg->type))
|
||||
{
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (arg->request == USB_FSIJ_GNUK_MEMINFO)
|
||||
return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else /* SETUP_SET */
|
||||
{
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
uint8_t *addr = sram_address ((arg->value * 0x100) + arg->index);
|
||||
#endif
|
||||
|
||||
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
|
||||
{
|
||||
if (*ccid_state_p != CCID_STATE_EXITED)
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return -1;
|
||||
|
||||
if (addr < &_regnual_start || addr + arg->len > __heap_end__)
|
||||
@@ -248,16 +292,23 @@ usb_setup (struct usb_dev *dev)
|
||||
256 - (arg->index + arg->len));
|
||||
|
||||
return usb_lld_ctrl_recv (dev, addr, arg->len);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0)
|
||||
{
|
||||
if (*ccid_state_p != CCID_STATE_EXITED)
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return -1;
|
||||
|
||||
if (((uintptr_t)addr & 0x03))
|
||||
return -1;
|
||||
|
||||
return download_check_crc32 (dev, (uint32_t *)addr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else if (arg->request == USB_FSIJ_GNUK_CARD_CHANGE && arg->len == 0)
|
||||
{
|
||||
@@ -353,10 +404,10 @@ usb_ctrl_write_finish (struct usb_dev *dev)
|
||||
{
|
||||
if (USB_SETUP_SET (arg->type) && arg->request == USB_FSIJ_GNUK_EXEC)
|
||||
{
|
||||
if (*ccid_state_p != CCID_STATE_EXITED)
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return;
|
||||
|
||||
bDeviceState = UNCONNECTED;
|
||||
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
usb_lld_prepare_shutdown (); /* No further USB communication */
|
||||
led_blink (LED_GNUK_EXEC); /* Notify the main. */
|
||||
}
|
||||
@@ -417,8 +468,8 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
|
||||
usb_lld_set_configuration (dev, 1);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 0);
|
||||
bDeviceState = CONFIGURED;
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 0);
|
||||
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
|
||||
}
|
||||
else if (current_conf != dev->dev_req.value)
|
||||
{
|
||||
@@ -427,9 +478,8 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
|
||||
usb_lld_set_configuration (dev, 0);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 1);
|
||||
bDeviceState = ADDRESSED;
|
||||
ccid_usb_reset (1);
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 1);
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
}
|
||||
|
||||
/* Do nothing when current_conf == value */
|
||||
@@ -450,8 +500,7 @@ usb_set_interface (struct usb_dev *dev)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
gnuk_setup_endpoints_for_interface (interface, 0);
|
||||
ccid_usb_reset (0);
|
||||
gnuk_setup_endpoints_for_interface (dev, interface, 0);
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,15 +59,20 @@ static const uint8_t hid_report_desc[] = {
|
||||
#define USB_CCID_DATA_SIZE 64
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
static const uint8_t device_desc[] = {
|
||||
#if !defined(GNU_LINUX_EMULATION)
|
||||
static const
|
||||
#endif
|
||||
uint8_t device_desc[] = {
|
||||
18, /* bLength */
|
||||
DEVICE_DESCRIPTOR, /* bDescriptorType */
|
||||
0x10, 0x01, /* bcdUSB = 1.1 */
|
||||
0x00, 0x02, /* bcdUSB = 2.0 */
|
||||
0x00, /* bDeviceClass: 0 means deferred to interface */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
#include "usb-vid-pid-ver.c.inc"
|
||||
0x00, 0x00, /* idVendor (will be replaced) */
|
||||
0x00, 0x00, /* idProduct (will be replaced) */
|
||||
0x00, 0x00, /* bcdDevice (will be replaced) */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -4,7 +4,7 @@ Feature: setup pass phrase
|
||||
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"
|
||||
Given cmd_change_reference_data with 1 and "another user pass phraseuser pass phrase"
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW1 (1)
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -70,11 +70,11 @@ def build_privkey_template_for_remove(openpgp_keyno):
|
||||
keyspec = b'\xb8'
|
||||
else:
|
||||
keyspec = b'\xa4'
|
||||
return b'\x4d\02' + keyspec + b'\0x00'
|
||||
return b'\x4d\x02' + keyspec + b'\x00'
|
||||
|
||||
def compute_digestinfo(msg):
|
||||
digest = sha256(msg).digest()
|
||||
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
prefix = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
return prefix + digest
|
||||
|
||||
# egcd and modinv are from wikibooks
|
||||
|
||||
@@ -6,7 +6,7 @@ Gnuk Token is supported as well.
|
||||
|
||||
You need to install:
|
||||
|
||||
$ sudo apt-get install python3-pytest python3-usb
|
||||
$ sudo apt install python3-pytest python3-usb python3-cffi
|
||||
|
||||
Please run test by typing:
|
||||
|
||||
|
||||
12
tests/card_const.py
Normal file
12
tests/card_const.py
Normal file
@@ -0,0 +1,12 @@
|
||||
FACTORY_PASSPHRASE_PW1=b"123456"
|
||||
FACTORY_PASSPHRASE_PW3=b"12345678"
|
||||
KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00"
|
||||
KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P256R1=b"\x12\x2a\x86\x48\xce\x3d\x03\x01\x07"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P384R1=b"\x12\x2b\x81\x04\x00\x22"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P521R1=b"\x12\x2b\x81\x04\x00\x23"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP256R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x07"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP384R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0b"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP512R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0d"
|
||||
KEY_ATTRIBUTES_X25519=b"\x12\x2b\x06\x01\x04\x01\x97\x55\x01\x05\x01"
|
||||
KEY_ATTRIBUTES_ED25519=b"\x16\x2b\x06\x01\x04\x01\xda\x47\x0f\x01"
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
card_reader.py - a library for smartcard reader
|
||||
|
||||
Copyright (C) 2016 Free Software Initiative of Japan
|
||||
Copyright (C) 2016, 2017, 2019 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -25,6 +25,7 @@ from struct import pack
|
||||
from usb.util import find_descriptor, claim_interface, get_string, \
|
||||
endpoint_type, endpoint_direction, \
|
||||
ENDPOINT_TYPE_BULK, ENDPOINT_OUT, ENDPOINT_IN
|
||||
from binascii import hexlify
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
@@ -125,9 +126,12 @@ class CardReader(object):
|
||||
# intf.extra_descriptors[41]
|
||||
|
||||
self.__dev = dev
|
||||
self.__timeout = 10000
|
||||
self.__timeout = 100000
|
||||
self.__seq = 0
|
||||
|
||||
if self.ccid_get_status() & 0x03 not in (0, 1):
|
||||
raise ValueError("Card absent")
|
||||
|
||||
def get_string(self, num):
|
||||
return get_string(self.__dev, num)
|
||||
|
||||
@@ -168,7 +172,7 @@ class CardReader(object):
|
||||
return status
|
||||
|
||||
def ccid_power_on(self):
|
||||
msg = ccid_compose(0x62, self.__seq, rsv=1) # Vcc=5V
|
||||
msg = ccid_compose(0x62, self.__seq, rsv=2) # Vcc=3.3V
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data = self.ccid_get_result()
|
||||
@@ -179,9 +183,11 @@ class CardReader(object):
|
||||
# TPDU reader configuration
|
||||
self.ns = 0
|
||||
self.nr = 0
|
||||
# Set PPS
|
||||
pps = b"\xFF\x11\x18\xF6"
|
||||
status, chain, ret_pps = self.ccid_send_data_block(pps)
|
||||
# For Gemalto's SmartCard Reader(s)
|
||||
if self.__dev.idVendor == 0x08E6:
|
||||
# Set PPS
|
||||
pps = b"\xFF\x11\x18\xF6"
|
||||
status, chain, ret_pps = self.ccid_send_data_block(pps)
|
||||
# Set parameters
|
||||
param = b"\x18\x10\xFF\x75\x00\xFE\x00"
|
||||
# ^--- This shoud be adapted by ATR string, see update_param_by_atr
|
||||
@@ -235,16 +241,21 @@ class CardReader(object):
|
||||
|
||||
def send_tpdu(self, info=None, more=0, response_time_ext=0,
|
||||
edc_error=0, no_error=0):
|
||||
rsv = 0
|
||||
if info:
|
||||
data = compose_i_block(self.ns, info, more)
|
||||
elif response_time_ext:
|
||||
# compose S-block
|
||||
data = b"\x00\xE3\x00\xE3"
|
||||
# compose S-block response
|
||||
pcb = 0xe3
|
||||
bwi_byte = bytes([response_time_ext])
|
||||
edc = compute_edc(pcb, bwi_byte)
|
||||
data = bytes([0, pcb, 1]) + bwi_byte + bytes([edc])
|
||||
rsv = response_time_ext
|
||||
elif edc_error:
|
||||
data = compose_r_block(self.nr, edc_error=1)
|
||||
elif no_error:
|
||||
data = compose_r_block(self.nr)
|
||||
msg = ccid_compose(0x6f, self.__seq, data=data)
|
||||
msg = ccid_compose(0x6f, self.__seq, rsv=rsv, data=data)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
|
||||
@@ -275,7 +286,7 @@ class CardReader(object):
|
||||
res = b""
|
||||
while True:
|
||||
if is_s_block_time_ext(blk):
|
||||
self.send_tpdu(response_time_ext=1)
|
||||
self.send_tpdu(response_time_ext=blk[3])
|
||||
elif is_i_block_last(blk):
|
||||
self.nr = self.nr ^ 1
|
||||
if is_edc_error(blk):
|
||||
|
||||
58
tests/card_test_ansix9p256r1.py
Normal file
58
tests/card_test_ansix9p256r1.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
card_test_ansix9p256r1.py - test ansix9p256r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_AnsiX9P256R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc5903#section-8.1
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P256R1,
|
||||
key_attribute_caption='ECDH ansix9p256r1',
|
||||
private_key=(
|
||||
b'\xC8\x8F\x01\xF5\x10\xD9\xAC\x3F\x70\xA2\x92\xDA\xA2\x31\x6D\xE5'
|
||||
b'\x44\xE9\xAA\xB8\xAF\xE8\x40\x49\xC6\x2A\x9C\x57\x86\x2D\x14\x33'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\xDA\xD0\xB6\x53\x94\x22\x1C\xF9\xB0\x51\xE1\xFE\xCA\x57\x87\xD0'
|
||||
b'\x98\xDF\xE6\x37\xFC\x90\xB9\xEF\x94\x5D\x0C\x37\x72\x58\x11\x80'
|
||||
b'\x52\x71\xA0\x46\x1C\xDB\x82\x52\xD6\x1F\x1C\x45\x6F\xA3\xE5\x9A'
|
||||
b'\xB1\xF4\x5B\x33\xAC\xCF\x5F\x58\x38\x9E\x05\x77\xB8\x99\x0B\xB3'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x46\x7f\x49\x43\x86\x41'
|
||||
b'\x04'
|
||||
b'\xD1\x2D\xFB\x52\x89\xC8\xD4\xF8\x12\x08\xB7\x02\x70\x39\x8C\x34'
|
||||
b'\x22\x96\x97\x0A\x0B\xCC\xB7\x4C\x73\x6F\xC7\x55\x44\x94\xBF\x63'
|
||||
b'\x56\xFB\xF3\xCA\x36\x6C\xC2\x3E\x81\x57\x85\x4C\x13\xC5\x8D\x6A'
|
||||
b'\xAC\x23\xF0\x46\xAD\xA3\x0F\x83\x53\xE7\x4F\x33\x03\x98\x72\xAB'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\xD6\x84\x0F\x6B\x42\xF6\xED\xAF\xD1\x31\x16\xE0\xE1\x25\x65\x20'
|
||||
b'\x2F\xEF\x8E\x9E\xCE\x7D\xCE\x03\x81\x24\x64\xD0\x4B\x94\x42\xDE'
|
||||
),
|
||||
)
|
||||
64
tests/card_test_ansix9p384r1.py
Normal file
64
tests/card_test_ansix9p384r1.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
card_test_ansix9p384r1.py - test ansix9p384r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_AnsiX9P384R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc5903#section-8.2
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P384R1,
|
||||
key_attribute_caption='ECDH ansix9p384r1',
|
||||
private_key=(
|
||||
b'\x09\x9F\x3C\x70\x34\xD4\xA2\xC6\x99\x88\x4D\x73\xA3\x75\xA6\x7F'
|
||||
b'\x76\x24\xEF\x7C\x6B\x3C\x0F\x16\x06\x47\xB6\x74\x14\xDC\xE6\x55'
|
||||
b'\xE3\x5B\x53\x80\x41\xE6\x49\xEE\x3F\xAE\xF8\x96\x78\x3A\xB1\x94'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\x66\x78\x42\xD7\xD1\x80\xAC\x2C\xDE\x6F\x74\xF3\x75\x51\xF5\x57'
|
||||
b'\x55\xC7\x64\x5C\x20\xEF\x73\xE3\x16\x34\xFE\x72\xB4\xC5\x5E\xE6'
|
||||
b'\xDE\x3A\xC8\x08\xAC\xB4\xBD\xB4\xC8\x87\x32\xAE\xE9\x5F\x41\xAA'
|
||||
b'\x94\x82\xED\x1F\xC0\xEE\xB9\xCA\xFC\x49\x84\x62\x5C\xCF\xC2\x3F'
|
||||
b'\x65\x03\x21\x49\xE0\xE1\x44\xAD\xA0\x24\x18\x15\x35\xA0\xF3\x8E'
|
||||
b'\xEB\x9F\xCF\xF3\xC2\xC9\x47\xDA\xE6\x9B\x4C\x63\x45\x73\xA8\x1C'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x66\x7f\x49\x63\x86\x61'
|
||||
b'\x04'
|
||||
b'\xE5\x58\xDB\xEF\x53\xEE\xCD\xE3\xD3\xFC\xCF\xC1\xAE\xA0\x8A\x89'
|
||||
b'\xA9\x87\x47\x5D\x12\xFD\x95\x0D\x83\xCF\xA4\x17\x32\xBC\x50\x9D'
|
||||
b'\x0D\x1A\xC4\x3A\x03\x36\xDE\xF9\x6F\xDA\x41\xD0\x77\x4A\x35\x71'
|
||||
b'\xDC\xFB\xEC\x7A\xAC\xF3\x19\x64\x72\x16\x9E\x83\x84\x30\x36\x7F'
|
||||
b'\x66\xEE\xBE\x3C\x6E\x70\xC4\x16\xDD\x5F\x0C\x68\x75\x9D\xD1\xFF'
|
||||
b'\xF8\x3F\xA4\x01\x42\x20\x9D\xFF\x5E\xAA\xD9\x6D\xB9\xE6\x38\x6C'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\x11\x18\x73\x31\xC2\x79\x96\x2D\x93\xD6\x04\x24\x3F\xD5\x92\xCB'
|
||||
b'\x9D\x0A\x92\x6F\x42\x2E\x47\x18\x75\x21\x28\x7E\x71\x56\xC5\xC4'
|
||||
b'\xD6\x03\x13\x55\x69\xB9\xE9\xD0\x9C\xF5\xD4\xA2\x70\xF5\x97\x46'
|
||||
),
|
||||
)
|
||||
76
tests/card_test_ansix9p512r1.py
Normal file
76
tests/card_test_ansix9p512r1.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
card_test_ansix9p512r1.py - test ansix9p512r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_AnsiX9P512R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc5903#section-8.3
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P521R1,
|
||||
key_attribute_caption='ECDH ansix9p521r1',
|
||||
private_key=(
|
||||
b'\x00\x37\xAD\xE9\x31\x9A\x89\xF4\xDA\xBD\xB3\xEF\x41\x1A\xAC\xCC'
|
||||
b'\xA5\x12\x3C\x61\xAC\xAB\x57\xB5\x39\x3D\xCE\x47\x60\x81\x72\xA0'
|
||||
b'\x95\xAA\x85\xA3\x0F\xE1\xC2\x95\x2C\x67\x71\xD9\x37\xBA\x97\x77'
|
||||
b'\xF5\x95\x7B\x26\x39\xBA\xB0\x72\x46\x2F\x68\xC2\x7A\x57\x38\x2D'
|
||||
b'\x4A\x52'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\x00\x15\x41\x7E\x84\xDB\xF2\x8C\x0A\xD3\xC2\x78\x71\x33\x49\xDC'
|
||||
b'\x7D\xF1\x53\xC8\x97\xA1\x89\x1B\xD9\x8B\xAB\x43\x57\xC9\xEC\xBE'
|
||||
b'\xE1\xE3\xBF\x42\xE0\x0B\x8E\x38\x0A\xEA\xE5\x7C\x2D\x10\x75\x64'
|
||||
b'\x94\x18\x85\x94\x2A\xF5\xA7\xF4\x60\x17\x23\xC4\x19\x5D\x17\x6C'
|
||||
b'\xED\x3E'
|
||||
b'\x01\x7C\xAE\x20\xB6\x64\x1D\x2E\xEB\x69\x57\x86\xD8\xC9\x46\x14'
|
||||
b'\x62\x39\xD0\x99\xE1\x8E\x1D\x5A\x51\x4C\x73\x9D\x7C\xB4\xA1\x0A'
|
||||
b'\xD8\xA7\x88\x01\x5A\xC4\x05\xD7\x79\x9D\xC7\x5E\x7B\x7D\x5B\x6C'
|
||||
b'\xF2\x26\x1A\x6A\x7F\x15\x07\x43\x8B\xF0\x1B\xEB\x6C\xA3\x92\x6F'
|
||||
b'\x95\x82'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x81\x8c\x7f\x49\x81\x88\x86\x81\x85'
|
||||
b'\x04'
|
||||
b'\x00\xD0\xB3\x97\x5A\xC4\xB7\x99\xF5\xBE\xA1\x6D\x5E\x13\xE9\xAF'
|
||||
b'\x97\x1D\x5E\x9B\x98\x4C\x9F\x39\x72\x8B\x5E\x57\x39\x73\x5A\x21'
|
||||
b'\x9B\x97\xC3\x56\x43\x6A\xDC\x6E\x95\xBB\x03\x52\xF6\xBE\x64\xA6'
|
||||
b'\xC2\x91\x2D\x4E\xF2\xD0\x43\x3C\xED\x2B\x61\x71\x64\x00\x12\xD9'
|
||||
b'\x46\x0F'
|
||||
b'\x01\x5C\x68\x22\x63\x83\x95\x6E\x3B\xD0\x66\xE7\x97\xB6\x23\xC2'
|
||||
b'\x7C\xE0\xEA\xC2\xF5\x51\xA1\x0C\x2C\x72\x4D\x98\x52\x07\x7B\x87'
|
||||
b'\x22\x0B\x65\x36\xC5\xC4\x08\xA1\xD2\xAE\xBB\x8E\x86\xD6\x78\xAE'
|
||||
b'\x49\xCB\x57\x09\x1F\x47\x32\x29\x65\x79\xAB\x44\xFC\xD1\x7F\x0F'
|
||||
b'\xC5\x6A'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\x01\x14\x4C\x7D\x79\xAE\x69\x56\xBC\x8E\xDB\x8E\x7C\x78\x7C\x45'
|
||||
b'\x21\xCB\x08\x6F\xA6\x44\x07\xF9\x78\x94\xE5\xE6\xB2\xD7\x9B\x04'
|
||||
b'\xD1\x42\x7E\x73\xCA\x4B\xAA\x24\x0A\x34\x78\x68\x59\x81\x0C\x06'
|
||||
b'\xB3\xC7\x15\xA3\xA8\xCC\x31\x51\xF2\xBE\xE4\x17\x99\x6D\x19\xF3'
|
||||
b'\xDD\xEA'
|
||||
),
|
||||
)
|
||||
58
tests/card_test_brainpoolp256r1.py
Normal file
58
tests/card_test_brainpoolp256r1.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
card_test_brainpoolp256r1.py - test brainpoolp256r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_BrainpoolP256R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc7027#appendix-A.1
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP256R1,
|
||||
key_attribute_caption='ECDH brainpoolp256r1',
|
||||
private_key=(
|
||||
b'\x81\xDB\x1E\xE1\x00\x15\x0F\xF2\xEA\x33\x8D\x70\x82\x71\xBE\x38'
|
||||
b'\x30\x0C\xB5\x42\x41\xD7\x99\x50\xF7\x7B\x06\x30\x39\x80\x4F\x1D'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\x44\x10\x6E\x91\x3F\x92\xBC\x02\xA1\x70\x5D\x99\x53\xA8\x41\x4D'
|
||||
b'\xB9\x5E\x1A\xAA\x49\xE8\x1D\x9E\x85\xF9\x29\xA8\xE3\x10\x0B\xE5'
|
||||
b'\x8A\xB4\x84\x6F\x11\xCA\xCC\xB7\x3C\xE4\x9C\xBD\xD1\x20\xF5\xA9'
|
||||
b'\x00\xA6\x9F\xD3\x2C\x27\x22\x23\xF7\x89\xEF\x10\xEB\x08\x9B\xDC'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x46\x7f\x49\x43\x86\x41'
|
||||
b'\x04'
|
||||
b'\x8D\x2D\x68\x8C\x6C\xF9\x3E\x11\x60\xAD\x04\xCC\x44\x29\x11\x7D'
|
||||
b'\xC2\xC4\x18\x25\xE1\xE9\xFC\xA0\xAD\xDD\x34\xE6\xF1\xB3\x9F\x7B'
|
||||
b'\x99\x0C\x57\x52\x08\x12\xBE\x51\x26\x41\xE4\x70\x34\x83\x21\x06'
|
||||
b'\xBC\x7D\x3E\x8D\xD0\xE4\xC7\xF1\x13\x6D\x70\x06\x54\x7C\xEC\x6A'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\x89\xAF\xC3\x9D\x41\xD3\xB3\x27\x81\x4B\x80\x94\x0B\x04\x25\x90'
|
||||
b'\xF9\x65\x56\xEC\x91\xE6\xAE\x79\x39\xBC\xE3\x1F\x3A\x18\xBF\x2B'
|
||||
),
|
||||
)
|
||||
64
tests/card_test_brainpoolp384r1.py
Normal file
64
tests/card_test_brainpoolp384r1.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
card_test_brainpoolp384r1.py - test brainpoolp384r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_BrainpoolP384R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc7027#appendix-A.2
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP384R1,
|
||||
key_attribute_caption='ECDH brainpoolp384r1',
|
||||
private_key=(
|
||||
b'\x1E\x20\xF5\xE0\x48\xA5\x88\x6F\x1F\x15\x7C\x74\xE9\x1B\xDE\x2B'
|
||||
b'\x98\xC8\xB5\x2D\x58\xE5\x00\x3D\x57\x05\x3F\xC4\xB0\xBD\x65\xD6'
|
||||
b'\xF1\x5E\xB5\xD1\xEE\x16\x10\xDF\x87\x07\x95\x14\x36\x27\xD0\x42'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\x68\xB6\x65\xDD\x91\xC1\x95\x80\x06\x50\xCD\xD3\x63\xC6\x25\xF4'
|
||||
b'\xE7\x42\xE8\x13\x46\x67\xB7\x67\xB1\xB4\x76\x79\x35\x88\xF8\x85'
|
||||
b'\xAB\x69\x8C\x85\x2D\x4A\x6E\x77\xA2\x52\xD6\x38\x0F\xCA\xF0\x68'
|
||||
b'\x55\xBC\x91\xA3\x9C\x9E\xC0\x1D\xEE\x36\x01\x7B\x7D\x67\x3A\x93'
|
||||
b'\x12\x36\xD2\xF1\xF5\xC8\x39\x42\xD0\x49\xE3\xFA\x20\x60\x74\x93'
|
||||
b'\xE0\xD0\x38\xFF\x2F\xD3\x0C\x2A\xB6\x7D\x15\xC8\x5F\x7F\xAA\x59'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x66\x7f\x49\x63\x86\x61'
|
||||
b'\x04'
|
||||
b'\x4D\x44\x32\x6F\x26\x9A\x59\x7A\x5B\x58\xBB\xA5\x65\xDA\x55\x56'
|
||||
b'\xED\x7F\xD9\xA8\xA9\xEB\x76\xC2\x5F\x46\xDB\x69\xD1\x9D\xC8\xCE'
|
||||
b'\x6A\xD1\x8E\x40\x4B\x15\x73\x8B\x20\x86\xDF\x37\xE7\x1D\x1E\xB4'
|
||||
b'\x62\xD6\x92\x13\x6D\xE5\x6C\xBE\x93\xBF\x5F\xA3\x18\x8E\xF5\x8B'
|
||||
b'\xC8\xA3\xA0\xEC\x6C\x1E\x15\x1A\x21\x03\x8A\x42\xE9\x18\x53\x29'
|
||||
b'\xB5\xB2\x75\x90\x3D\x19\x2F\x8D\x4E\x1F\x32\xFE\x9C\xC7\x8C\x48'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\x0B\xD9\xD3\xA7\xEA\x0B\x3D\x51\x9D\x09\xD8\xE4\x8D\x07\x85\xFB'
|
||||
b'\x74\x4A\x6B\x35\x5E\x63\x04\xBC\x51\xC2\x29\xFB\xBC\xE2\x39\xBB'
|
||||
b'\xAD\xF6\x40\x37\x15\xC3\x5D\x4F\xB2\xA5\x44\x4F\x57\x5D\x4F\x42'
|
||||
),
|
||||
)
|
||||
70
tests/card_test_brainpoolp512r1.py
Normal file
70
tests/card_test_brainpoolp512r1.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
card_test_brainpoolp512r1.py - test brainpoolp512r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_BrainpoolP512R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc7027#appendix-A.3
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_BRAINPOOLP512R1,
|
||||
key_attribute_caption='ECDH brainpoolp512r1',
|
||||
private_key=(
|
||||
b'\x16\x30\x2F\xF0\xDB\xBB\x5A\x8D\x73\x3D\xAB\x71\x41\xC1\xB4\x5A'
|
||||
b'\xCB\xC8\x71\x59\x39\x67\x7F\x6A\x56\x85\x0A\x38\xBD\x87\xBD\x59'
|
||||
b'\xB0\x9E\x80\x27\x96\x09\xFF\x33\x3E\xB9\xD4\xC0\x61\x23\x1F\xB2'
|
||||
b'\x6F\x92\xEE\xB0\x49\x82\xA5\xF1\xD1\x76\x4C\xAD\x57\x66\x54\x22'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\x0A\x42\x05\x17\xE4\x06\xAA\xC0\xAC\xDC\xE9\x0F\xCD\x71\x48\x77'
|
||||
b'\x18\xD3\xB9\x53\xEF\xD7\xFB\xEC\x5F\x7F\x27\xE2\x8C\x61\x49\x99'
|
||||
b'\x93\x97\xE9\x1E\x02\x9E\x06\x45\x7D\xB2\xD3\xE6\x40\x66\x8B\x39'
|
||||
b'\x2C\x2A\x7E\x73\x7A\x7F\x0B\xF0\x44\x36\xD1\x16\x40\xFD\x09\xFD'
|
||||
b'\x72\xE6\x88\x2E\x8D\xB2\x8A\xAD\x36\x23\x7C\xD2\x5D\x58\x0D\xB2'
|
||||
b'\x37\x83\x96\x1C\x8D\xC5\x2D\xFA\x2E\xC1\x38\xAD\x47\x2A\x0F\xCE'
|
||||
b'\xF3\x88\x7C\xF6\x2B\x62\x3B\x2A\x87\xDE\x5C\x58\x83\x01\xEA\x3E'
|
||||
b'\x5F\xC2\x69\xB3\x73\xB6\x07\x24\xF5\xE8\x2A\x6A\xD1\x47\xFD\xE7'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x81\x88\x7f\x49\x81\x84\x86\x81\x81'
|
||||
b'\x04'
|
||||
b'\x9D\x45\xF6\x6D\xE5\xD6\x7E\x2E\x6D\xB6\xE9\x3A\x59\xCE\x0B\xB4'
|
||||
b'\x81\x06\x09\x7F\xF7\x8A\x08\x1D\xE7\x81\xCD\xB3\x1F\xCE\x8C\xCB'
|
||||
b'\xAA\xEA\x8D\xD4\x32\x0C\x41\x19\xF1\xE9\xCD\x43\x7A\x2E\xAB\x37'
|
||||
b'\x31\xFA\x96\x68\xAB\x26\x8D\x87\x1D\xED\xA5\x5A\x54\x73\x19\x9F'
|
||||
b'\x2F\xDC\x31\x30\x95\xBC\xDD\x5F\xB3\xA9\x16\x36\xF0\x7A\x95\x9C'
|
||||
b'\x8E\x86\xB5\x63\x6A\x1E\x93\x0E\x83\x96\x04\x9C\xB4\x81\x96\x1D'
|
||||
b'\x36\x5C\xC1\x14\x53\xA0\x6C\x71\x98\x35\x47\x5B\x12\xCB\x52\xFC'
|
||||
b'\x3C\x38\x3B\xCE\x35\xE2\x7E\xF1\x94\x51\x2B\x71\x87\x62\x85\xFA'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\xA7\x92\x70\x98\x65\x5F\x1F\x99\x76\xFA\x50\xA9\xD5\x66\x86\x5D'
|
||||
b'\xC5\x30\x33\x18\x46\x38\x1C\x87\x25\x6B\xAF\x32\x26\x24\x4B\x76'
|
||||
b'\xD3\x64\x03\xC0\x24\xD7\xBB\xF0\xAA\x08\x03\xEA\xFF\x40\x5D\x3D'
|
||||
b'\x24\xF1\x1A\x9B\x5C\x0B\xEF\x67\x9F\xE1\x45\x4B\x21\xC4\xCD\x1F'
|
||||
),
|
||||
)
|
||||
51
tests/card_test_ed25519.py
Normal file
51
tests/card_test_ed25519.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
card_test_ed25519.py - test ed25519 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_ED25519(object):
|
||||
def test_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc8032#section-7.3
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=0,
|
||||
key_attributes=KEY_ATTRIBUTES_ED25519,
|
||||
key_attribute_caption='ed25519',
|
||||
private_key=(
|
||||
b'\x83\x3f\xe6\x24\x09\x23\x7b\x9d\x62\xec\x77\x58\x75\x20\x91\x1e'
|
||||
b'\x9a\x75\x9c\xec\x1d\x19\x75\x5b\x7d\xa9\x01\xb9\x6d\xca\x3d\x42'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\xec\x17\x2b\x93\xad\x5e\x56\x3b\xf4\x93\x2c\x70\xe1\x24\x50\x34'
|
||||
b'\xc3\x54\x67\xef\x2e\xfd\x4d\x64\xeb\xf8\x19\x68\x34\x67\xe2\xbf'
|
||||
),
|
||||
pso_input=hashlib.sha512(b'\x61\x62\x63').digest(),
|
||||
expected_pso_output=(
|
||||
b'\x98\xa7\x02\x22\xf0\xb8\x12\x1a\xa9\xd3\x0f\x81\x3d\x68\x3f\x80'
|
||||
b'\x9e\x46\x2b\x46\x9c\x7f\xf8\x76\x39\x49\x9b\xb9\x4e\x6d\xae\x41'
|
||||
b'\x31\xf8\x50\x42\x46\x3c\x2a\x35\x5a\x20\x03\xd0\x62\xad\xf5\xaa'
|
||||
b'\xa1\x0b\x8c\x61\xe6\x36\x06\x2a\xaa\xd1\x1c\x2a\x26\x08\x34\x06'
|
||||
),
|
||||
)
|
||||
36
tests/card_test_kdf_full.py
Normal file
36
tests/card_test_kdf_full.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
card_test_kdf_full.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_KDF_full(object):
|
||||
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_full(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_FULL)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
35
tests/card_test_kdf_single.py
Normal file
35
tests/card_test_kdf_single.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
card_test_kdf_single.py - test KDF data object
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_KDF_Single(object):
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_kdf_put_single(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xf9, KDF_SINGLE)
|
||||
if r:
|
||||
card.configure_with_kdf()
|
||||
assert r
|
||||
84
tests/card_test_keygen.py
Normal file
84
tests/card_test_keygen.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
card_test_keygen.py - test key generation
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from binascii import hexlify
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_Keygen(object):
|
||||
def test_keygen_1(self, card):
|
||||
pk = card.cmd_genkey(1)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xce, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_2(self, card):
|
||||
pk = card.cmd_genkey(2)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xcf, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_keygen_3(self, card):
|
||||
pk = card.cmd_genkey(3)
|
||||
fpr_date = rsa_keys.calc_fpr(pk[0], pk[1])
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr_date[0])
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xd0, fpr_date[1])
|
||||
assert r
|
||||
|
||||
def test_verify_pw1(self, card):
|
||||
v = card.cmd_verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_signature_sigkey(self, card):
|
||||
msg = b"Sign me please"
|
||||
pk = card.cmd_get_public_key(1)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_pso(0x9e, 0x9a, digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.cmd_verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_decryption(self, card):
|
||||
msg = b"encrypt me please"
|
||||
pk = card.cmd_get_public_key(2)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
ciphertext = rsa_keys.encrypt_with_pubkey(pk_info, msg)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == msg
|
||||
|
||||
def test_signature_authkey(self, card):
|
||||
msg = b"Sign me please to authenticate"
|
||||
pk = card.cmd_get_public_key(3)
|
||||
pk_info = (pk[9:9+256], pk[9+256+2:])
|
||||
digest = rsa_keys.compute_digestinfo(msg)
|
||||
sig = int(hexlify(card.cmd_internal_authenticate(digest)),16)
|
||||
r = rsa_keys.verify_signature(pk_info, digest, sig)
|
||||
assert r
|
||||
312
tests/card_test_personalize_admin_less.py
Normal file
312
tests/card_test_personalize_admin_less.py
Normal file
@@ -0,0 +1,312 @@
|
||||
"""
|
||||
card_test_personalize_admin_less.py - test admin-less mode
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_Personalize_Adminless(object):
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_rsa_import_key_1(self, card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(self, card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(self, card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(self, card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(self, card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(self, card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(self, card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(self, card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(self, card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(self, card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(self, card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(self, card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(self, card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
# Changing PW1 to admin-less mode
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
# Now, it's admin-less mode, auth-status admin cleared
|
||||
|
||||
def test_verify_pw3_fail_1(self, card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = False
|
||||
assert not v
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(self, card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(self, card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_admin_less_1(self, card):
|
||||
v = card.verify(3, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(self, card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(self, card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
# Changing PW1, auth status for admin cleared
|
||||
def test_login_put_fail(self, card):
|
||||
try:
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(self, card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw3_fail_2(self, card):
|
||||
try:
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
except ValueError as e:
|
||||
v = e.args[0]
|
||||
assert v == "6982"
|
||||
|
||||
def test_sign_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
# Since forcesig setting, failed
|
||||
def test_sign_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
try:
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
except ValueError as e:
|
||||
r = e.args[0]
|
||||
assert r == "6982"
|
||||
|
||||
def test_ds_counter_1(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x01'
|
||||
|
||||
def test_sign_auth_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
|
||||
def test_verify_pw3_admin_less_2(self, card):
|
||||
v = card.verify(3, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(self, card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(self, card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(self, card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
# Setting PW3, changed to admin-full mode
|
||||
|
||||
def test_setup_pw3_1(self, card):
|
||||
r = card.change_passwd(3, PW1_TEST2, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(self, card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(self, card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(self, card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(self, card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(self, card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(self, card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
277
tests/card_test_personalize_card.py
Normal file
277
tests/card_test_personalize_card.py
Normal file
@@ -0,0 +1,277 @@
|
||||
"""
|
||||
card_test_personalize_card.py - test personalizing card
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Card_Personalize_Card(object):
|
||||
def test_setup_pw3_0(self, card):
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"gpg_user")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"GnuPG User")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"ja")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"1")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"https://www.fsij.org/gnuk/")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x01")
|
||||
assert r
|
||||
|
||||
def test_login(self, card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert login == b"gpg_user"
|
||||
|
||||
def test_name_lang_sex(self, card):
|
||||
name = b"GnuPG User"
|
||||
lang = b"ja"
|
||||
sex = b"1"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == expected
|
||||
|
||||
def test_url(self, card):
|
||||
url = get_data_object(card, 0x5f50)
|
||||
assert url == b"https://www.fsij.org/gnuk/"
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_rsa_import_key_1(self, card):
|
||||
t = rsa_keys.build_privkey_template(1, 0)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_2(self, card):
|
||||
t = rsa_keys.build_privkey_template(2, 1)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(self, card):
|
||||
t = rsa_keys.build_privkey_template(3, 2)
|
||||
r = card.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_1_put(self, card):
|
||||
fpr1 = rsa_keys.fpr[0]
|
||||
r = card.cmd_put_data(0x00, 0xc7, fpr1)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_2_put(self, card):
|
||||
fpr2 = rsa_keys.fpr[1]
|
||||
r = card.cmd_put_data(0x00, 0xc8, fpr2)
|
||||
assert r
|
||||
|
||||
def test_fingerprint_3_put(self, card):
|
||||
fpr3 = rsa_keys.fpr[2]
|
||||
r = card.cmd_put_data(0x00, 0xc9, fpr3)
|
||||
assert r
|
||||
|
||||
def test_timestamp_1_put(self, card):
|
||||
timestamp1 = rsa_keys.timestamp[0]
|
||||
r = card.cmd_put_data(0x00, 0xce, timestamp1)
|
||||
assert r
|
||||
|
||||
def test_timestamp_2_put(self, card):
|
||||
timestamp2 = rsa_keys.timestamp[1]
|
||||
r = card.cmd_put_data(0x00, 0xcf, timestamp2)
|
||||
assert r
|
||||
|
||||
def test_timestamp_3_put(self, card):
|
||||
timestamp3 = rsa_keys.timestamp[2]
|
||||
r = card.cmd_put_data(0x00, 0xd0, timestamp3)
|
||||
assert r
|
||||
|
||||
def test_ds_counter_0(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x00'
|
||||
|
||||
def test_pw1_status(self, card):
|
||||
s = get_data_object(card, 0xc4)
|
||||
assert match(b'\x01...\x03[\x00\x03]\x03', s, DOTALL)
|
||||
|
||||
def test_app_data(self, card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
hist_len = app_data[20]
|
||||
# FIXME: parse and check DO of C0, C1, C2, C3, C4, and C6
|
||||
assert app_data[0:8] == b"\x4f\x10\xd2\x76\x00\x01\x24\x01" and \
|
||||
app_data[18:18+2] == b"\x5f\x52"
|
||||
|
||||
def test_public_key_1(self, card):
|
||||
pk = card.cmd_get_public_key(1)
|
||||
assert rsa_keys.key[0][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_2(self, card):
|
||||
pk = card.cmd_get_public_key(2)
|
||||
assert rsa_keys.key[1][0] == pk[9:9+256]
|
||||
|
||||
def test_public_key_3(self, card):
|
||||
pk = card.cmd_get_public_key(3)
|
||||
assert rsa_keys.key[2][0] == pk[9:9+256]
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, PW1_TEST0)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_1(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST0, PW1_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_1(self, card):
|
||||
v = card.verify(1, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_1_2(self, card):
|
||||
v = card.verify(2, PW1_TEST1)
|
||||
assert v
|
||||
|
||||
def test_setup_reset_code(self, card):
|
||||
r = card.setup_reset_code(RESETCODE_TEST)
|
||||
assert r
|
||||
|
||||
def test_reset_code(self, card):
|
||||
r = card.reset_passwd_by_resetcode(RESETCODE_TEST, PW1_TEST2)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(1, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2_2(self, card):
|
||||
v = card.verify(2, PW1_TEST2)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_1(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST0, PW3_TEST1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_1(self, card):
|
||||
v = card.verify(3, PW3_TEST1)
|
||||
assert v
|
||||
|
||||
def test_reset_userpass_admin(self, card):
|
||||
r = card.reset_passwd_by_admin(PW1_TEST3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_3(self, card):
|
||||
v = card.verify(1, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_3_2(self, card):
|
||||
v = card.verify(2, PW1_TEST3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_4(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST3, PW1_TEST4)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_4(self, card):
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_4_2(self, card):
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
|
||||
def test_setup_pw3_2(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST1, PW3_TEST0)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_sign_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x9e, 0x9a, digestinfo)
|
||||
sig = rsa_keys.compute_signature(0, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_ds_counter_1(self, card):
|
||||
c = get_data_object(card, 0x7a)
|
||||
assert c == b'\x93\x03\x00\x00\x02'
|
||||
|
||||
def test_sign_auth_0(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT0)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_sign_auth_1(self, card):
|
||||
digestinfo = rsa_keys.compute_digestinfo(PLAIN_TEXT1)
|
||||
r = card.cmd_internal_authenticate(digestinfo)
|
||||
sig = rsa_keys.compute_signature(2, digestinfo)
|
||||
sig_bytes = sig.to_bytes(int((sig.bit_length()+7)/8), byteorder='big')
|
||||
assert r == sig_bytes
|
||||
|
||||
def test_decrypt_0(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT0)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT0
|
||||
|
||||
def test_decrypt_1(self, card):
|
||||
ciphertext = rsa_keys.encrypt(1, PLAIN_TEXT1)
|
||||
r = card.cmd_pso(0x80, 0x86, ciphertext)
|
||||
assert r == PLAIN_TEXT1
|
||||
82
tests/card_test_personalize_reset.py
Normal file
82
tests/card_test_personalize_reset.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
card_test_personalize_reset.py - test resetting personalization of card
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from struct import pack
|
||||
from re import match, DOTALL
|
||||
from util import *
|
||||
import rsa_keys
|
||||
from card_const import *
|
||||
from constants_for_test import *
|
||||
|
||||
class Test_Personalize_Reset(object):
|
||||
def test_login_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5e, b"")
|
||||
assert r
|
||||
|
||||
def test_name_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0x5b, b"")
|
||||
assert r
|
||||
|
||||
def test_lang_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x2d, b"")
|
||||
assert r
|
||||
|
||||
def test_sex_put(self, card):
|
||||
try:
|
||||
# Gnuk
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"")
|
||||
except ValueError:
|
||||
# OpenPGP card which doesn't allow b""
|
||||
r = card.cmd_put_data(0x5f, 0x35, b"9")
|
||||
assert r
|
||||
|
||||
def test_url_put(self, card):
|
||||
r = card.cmd_put_data(0x5f, 0x50, b"")
|
||||
assert r
|
||||
|
||||
def test_pw1_status_put(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc4, b"\x00")
|
||||
assert r
|
||||
|
||||
def test_setup_pw3_0(self, card):
|
||||
r = card.change_passwd(3, PW3_TEST0, FACTORY_PASSPHRASE_PW3)
|
||||
assert r
|
||||
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
def test_setup_pw1_0(self, card):
|
||||
r = card.change_passwd(1, PW1_TEST4, FACTORY_PASSPHRASE_PW1)
|
||||
assert r
|
||||
|
||||
def test_verify_pw1_0(self, card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_0_2(self, card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_delete_reset_code(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xd3, b"")
|
||||
assert r
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_remove_keys_card.py - test removing keys on card
|
||||
card_test_remove_keys.py - test removing keys on card
|
||||
|
||||
Copyright (C) 2016 g10 Code GmbH
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -22,23 +22,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Remove a key material on card by changing algorithm attributes of the key
|
||||
|
||||
KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00"
|
||||
KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00"
|
||||
from card_const import *
|
||||
|
||||
def test_rsa_import_key_1(card):
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
class Test_Remove_Keys(object):
|
||||
|
||||
def test_rsa_import_key_2(card):
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
def test_rsa_keyattr_change_1(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc1, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_import_key_3(card):
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
def test_rsa_keyattr_change_2(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc2, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
|
||||
def test_rsa_keyattr_change_3(self, card):
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA4K)
|
||||
if r:
|
||||
r = card.cmd_put_data(0x00, 0xc3, KEY_ATTRIBUTES_RSA2K)
|
||||
assert r
|
||||
46
tests/card_test_reset_pw3.py
Normal file
46
tests/card_test_reset_pw3.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
card_test_reset_pw3.py - test resetting pw3
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from card_const import *
|
||||
import pytest
|
||||
|
||||
class Test_Reset_PW3(object):
|
||||
# Gnuk specific feature of clear PW3
|
||||
def test_setup_pw3_null(self, card):
|
||||
if card.is_gnuk:
|
||||
r = card.change_passwd(3, FACTORY_PASSPHRASE_PW3, None)
|
||||
assert r
|
||||
else:
|
||||
pytest.skip("Gnuk only feature of clearing PW3")
|
||||
|
||||
def test_verify_pw3(self, card):
|
||||
v = card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert v
|
||||
|
||||
# Check PW1 again to see the possiblity of admin-less mode
|
||||
def test_verify_pw1(self, card):
|
||||
v = card.verify(1, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
|
||||
def test_verify_pw1_2(self, card):
|
||||
v = card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
assert v
|
||||
52
tests/card_test_x25519.py
Normal file
52
tests/card_test_x25519.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
card_test_x25519.py - test x25519 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_X25519(object):
|
||||
def test_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc7748#section-6.1
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_X25519,
|
||||
key_attribute_caption='x25519',
|
||||
private_key=(
|
||||
b'\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45'
|
||||
b'\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x85\x20\xf0\x09\x89\x30\xa7\x54\x74\x8b\x7d\xdc\xb4\x3e\xf7\x5a'
|
||||
b'\x0d\xbf\x3a\x0d\x26\x38\x1a\xf4\xeb\xa4\xa9\x8e\xaa\x9b\x4e\x6a'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x25\x7f\x49\x22\x86\x20'
|
||||
b'\xde\x9e\xdb\x7d\x7b\x7d\xc1\xb4\xd3\x5b\x61\xc2\xec\xe4\x35\x37'
|
||||
b'\x3f\x83\x43\xc8\x5b\x78\x67\x4d\xad\xfc\x7e\x14\x6f\x88\x2b\x4f'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\x4a\x5d\x9d\x5b\xa4\xce\x2d\xe1\x72\x8e\x3b\xf4\x80\x35\x0f\x25'
|
||||
b'\xe0\x7e\x21\xc9\x47\xd1\x9e\x33\x76\xf0\x9b\x3c\x1e\x16\x17\x42'
|
||||
),
|
||||
)
|
||||
@@ -16,3 +16,4 @@ def card():
|
||||
card.cmd_select_openpgp()
|
||||
yield card
|
||||
del card
|
||||
reader.ccid_power_off()
|
||||
|
||||
21
tests/constants_for_test.py
Normal file
21
tests/constants_for_test.py
Normal file
@@ -0,0 +1,21 @@
|
||||
PW1_TEST0=b"another user pass phrase"
|
||||
PW1_TEST1=b"PASSPHRASE SHOULD BE LONG"
|
||||
PW1_TEST2=b"new user pass phrase"
|
||||
PW1_TEST3=b"next user pass phrase"
|
||||
PW1_TEST4=b"another user pass phrase"
|
||||
PW3_TEST0=b"admin pass phrase"
|
||||
PW3_TEST1=b"another admin pass phrase"
|
||||
|
||||
RESETCODE_TEST=b"example reset code 000"
|
||||
|
||||
PLAIN_TEXT0=b"This is a test message."
|
||||
PLAIN_TEXT1=b"RSA decryption is as easy as pie."
|
||||
PLAIN_TEXT2=b"This is another test message.\nMultiple lines.\n"
|
||||
|
||||
KDF_FULL=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\xC5\x1F\xB7\xF9\xEE\xF3\xD3\xE8\x85\x08\x75\x1A\x2A\x70\xC0\x7C\xB1\x81\x86\x08\xE6\xB2\x4E\x0C\xEE\x92\xAB\x93\x87\x20\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D\x88\x20\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03"
|
||||
KDF_FULL_HASH_PW1=b"\xA2\x08\x89\x16\x09\xD3\xE4\x3D\x48\xAC\x5B\xAA\xBD\xE9\xF1\xB8\xD2\xFC\xD8\x3C\x5F\x35\xCB\xEB\xDA\xFB\x75\x92\x88\xC6\x8B\x2D"
|
||||
KDF_FULL_HASH_PW3=b"\xF1\x34\x00\xD2\x5F\x28\x57\xE6\x66\xAA\x9E\xBB\xE0\x7C\x57\x4B\x84\x8B\xD6\x52\x14\xE7\x31\x99\x1A\x3D\x2D\xAA\x3F\x8A\x7F\x03"
|
||||
|
||||
KDF_SINGLE=b"\x81\x01\x03\x82\x01\x08\x83\x04\x00\xC8\x00\x00\x84\x08\x69\x9E\xDA\xAD\x5A\x72\x5F\x4C\x87\x20\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07\x88\x20\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB"
|
||||
KDF_SINGLE_HASH_PW1=b"\x12\xDB\x16\x9A\x9D\x1A\x56\xCA\x2B\x9E\x96\x7F\xC4\xDA\xB8\xAE\x70\x41\x51\x8E\x3C\xEF\x49\x7E\xC2\x56\x60\x32\x2F\x4C\x03\x07"
|
||||
KDF_SINGLE_HASH_PW3=b"\x1C\x93\x99\xC3\x6D\x49\x92\x27\x54\x39\x76\x7E\xA7\xB4\xEE\xE5\x16\xDA\x92\xC0\x0E\xF4\x74\xBD\x01\x28\x0F\x0C\x30\x45\x4B\xBB"
|
||||
108
tests/func_pso_auth.py
Normal file
108
tests/func_pso_auth.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
func_pso_auth.py - functions for testing PSO commands
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from card_const import KEY_ATTRIBUTES_RSA2K
|
||||
|
||||
def _encodeDERLength(length):
|
||||
if length < 0x80:
|
||||
return length.to_bytes(1, 'big')
|
||||
if length < 0x100:
|
||||
return b'\x81' + length.to_bytes(1, 'big')
|
||||
return b'\x82' + length.to_bytes(2, 'big')
|
||||
|
||||
def get_ec_pso(
|
||||
card,
|
||||
key_index,
|
||||
key_attributes,
|
||||
key_attribute_caption,
|
||||
private_key, expected_public_key,
|
||||
pso_input,
|
||||
):
|
||||
"""
|
||||
If card supports, change key attributes for given key slot, store
|
||||
given private key, check that the card could derive the expected
|
||||
public key from it, then call the appropriate PSO for this key slot
|
||||
and return its result.
|
||||
Sets key attributes to RSA2K before returning to caller.
|
||||
Skips the test if initial key attribute change is rejected by the card.
|
||||
"""
|
||||
key_attribute_index, control_reference_template, pso_p1, pso_p2 = (
|
||||
(0xc1, b'\xb6\x00', 0x9e, 0x9a), # Sign
|
||||
(0xc2, b'\xb8\x00', 0x80, 0x86), # Decrypt
|
||||
(0xc3, b'\xa4\x00', 0x9e, 0x9a), # Authenticate
|
||||
)[key_index]
|
||||
try:
|
||||
card.cmd_put_data(0x00, key_attribute_index, key_attributes)
|
||||
except ValueError:
|
||||
pytest.skip('No %s support' % (key_attribute_caption, ))
|
||||
try:
|
||||
private_key_len = len(private_key)
|
||||
r = card.cmd_put_data_odd(
|
||||
0x3f,
|
||||
0xff,
|
||||
b'\x4d' + _encodeDERLength(private_key_len + 10) +
|
||||
control_reference_template +
|
||||
b'\x7f\x48\x02'
|
||||
b'\x92' + _encodeDERLength(private_key_len) +
|
||||
b'\x5f\x48' + _encodeDERLength(private_key_len) +
|
||||
private_key,
|
||||
)
|
||||
assert r
|
||||
r = card.cmd_get_public_key(key_index + 1)
|
||||
expected_public_key_len = len(expected_public_key)
|
||||
encoded_expected_public_key_len = _encodeDERLength(
|
||||
expected_public_key_len,
|
||||
)
|
||||
expected_public_key_response = (
|
||||
b'\x7f\x49' + _encodeDERLength(
|
||||
expected_public_key_len +
|
||||
len(encoded_expected_public_key_len) + 1,
|
||||
) +
|
||||
b'\x86' + encoded_expected_public_key_len +
|
||||
expected_public_key
|
||||
)
|
||||
assert r == expected_public_key_response
|
||||
return card.cmd_pso(pso_p1, pso_p2, pso_input)
|
||||
finally:
|
||||
card.cmd_put_data(0x00, key_attribute_index, KEY_ATTRIBUTES_RSA2K)
|
||||
|
||||
def assert_ec_pso(
|
||||
card,
|
||||
key_index,
|
||||
key_attributes,
|
||||
key_attribute_caption,
|
||||
private_key, expected_public_key,
|
||||
pso_input, expected_pso_output,
|
||||
):
|
||||
"""
|
||||
Calls get_ec_pso and checks if produced output matches the expected value.
|
||||
"""
|
||||
r = get_ec_pso(
|
||||
card=card,
|
||||
key_index=key_index,
|
||||
key_attributes=key_attributes,
|
||||
key_attribute_caption=key_attribute_caption,
|
||||
private_key=private_key,
|
||||
expected_public_key=expected_public_key,
|
||||
pso_input=pso_input,
|
||||
)
|
||||
assert r == expected_pso_output
|
||||
1
tests/kdf_calc.py
Symbolic link
1
tests/kdf_calc.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../tool/kdf_calc.py
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
openpgp_card.py - a library for OpenPGP card
|
||||
|
||||
Copyright (C) 2011, 2012, 2013, 2015, 2016
|
||||
Copyright (C) 2011, 2012, 2013, 2015, 2016, 2018, 2019
|
||||
Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
@@ -21,7 +21,8 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from struct import pack
|
||||
from struct import pack, unpack
|
||||
from kdf_calc import kdf_calc
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data, cls=0x00, le=None):
|
||||
data_len = len(data)
|
||||
@@ -54,6 +55,85 @@ class OpenPGP_Card(object):
|
||||
"""
|
||||
|
||||
self.__reader = reader
|
||||
self.__kdf_iters = None
|
||||
self.__kdf_salt_user = None
|
||||
self.__kdf_salt_reset = None
|
||||
self.__kdf_salt_admin = None
|
||||
self.is_gnuk = (reader.get_string(2) == "Gnuk Token")
|
||||
self.is_emulated_gnuk = (reader.get_string(3)[-8:] == "EMULATED")
|
||||
|
||||
def configure_with_kdf(self):
|
||||
kdf_data = self.cmd_get_data(0x00, 0xf9)
|
||||
if kdf_data != b"":
|
||||
algo, subalgo, iters, salt_user, salt_reset, salt_admin, hash_user, hash_admin = parse_kdf_data(kdf_data)
|
||||
self.__kdf_iters = iters
|
||||
self.__kdf_salt_user = salt_user
|
||||
self.__kdf_salt_reset = salt_reset
|
||||
self.__kdf_salt_admin = salt_admin
|
||||
else:
|
||||
self.__kdf_iters = None
|
||||
self.__kdf_salt_user = None
|
||||
self.__kdf_salt_reset = None
|
||||
self.__kdf_salt_admin = None
|
||||
|
||||
# Higher layer VERIFY possibly using KDF Data Object
|
||||
def verify(self, who, passwd):
|
||||
if self.__kdf_iters:
|
||||
salt = self.__kdf_salt_user
|
||||
if who == 3 and self.__kdf_salt_admin:
|
||||
salt = self.__kdf_salt_admin
|
||||
pw_hash = kdf_calc(passwd, salt, self.__kdf_iters)
|
||||
return self.cmd_verify(who, pw_hash)
|
||||
else:
|
||||
return self.cmd_verify(who, passwd)
|
||||
|
||||
# Higher layer CHANGE_PASSWD possibly using KDF Data Object
|
||||
def change_passwd(self, who, passwd_old, passwd_new):
|
||||
if self.__kdf_iters:
|
||||
salt = self.__kdf_salt_user
|
||||
if who == 3 and self.__kdf_salt_admin:
|
||||
salt = self.__kdf_salt_admin
|
||||
hash_old = kdf_calc(passwd_old, salt, self.__kdf_iters)
|
||||
if passwd_new:
|
||||
hash_new = kdf_calc(passwd_new, salt, self.__kdf_iters)
|
||||
else:
|
||||
hash_new = b""
|
||||
return self.cmd_change_reference_data(who, hash_old + hash_new)
|
||||
else:
|
||||
if not passwd_new:
|
||||
passwd_new = b""
|
||||
return self.cmd_change_reference_data(who, passwd_old + passwd_new)
|
||||
|
||||
# Higher layer SETUP_RESET_CODE possibly using KDF Data Object
|
||||
def setup_reset_code(self, resetcode):
|
||||
if self.__kdf_iters:
|
||||
salt = self.__kdf_salt_user
|
||||
if self.__kdf_salt_reset:
|
||||
salt = self.__kdf_salt_user
|
||||
reset_hash = kdf_calc(resetcode, salt, self.__kdf_iters)
|
||||
return self.cmd_put_data(0x00, 0xd3, reset_hash)
|
||||
else:
|
||||
return self.cmd_put_data(0x00, 0xd3, resetcode)
|
||||
|
||||
# Higher layer reset passwd possibly using KDF Data Object
|
||||
def reset_passwd_by_resetcode(self, resetcode, pw1):
|
||||
if self.__kdf_iters:
|
||||
salt = self.__kdf_salt_user
|
||||
if self.__kdf_salt_reset:
|
||||
salt = self.__kdf_salt_user
|
||||
reset_hash = kdf_calc(resetcode, salt, self.__kdf_iters)
|
||||
pw1_hash = kdf_calc(pw1, self.__kdf_salt_user, self.__kdf_iters)
|
||||
return self.cmd_reset_retry_counter(0, 0x81, reset_hash + pw1_hash)
|
||||
else:
|
||||
return self.cmd_reset_retry_counter(0, 0x81, resetcode + pw1)
|
||||
|
||||
# Higher layer reset passwd possibly using KDF Data Object
|
||||
def reset_passwd_by_admin(self, pw1):
|
||||
if self.__kdf_iters:
|
||||
pw1_hash = kdf_calc(pw1, self.__kdf_salt_user, self.__kdf_iters)
|
||||
return self.cmd_reset_retry_counter(2, 0x81, pw1_hash)
|
||||
else:
|
||||
return self.cmd_reset_retry_counter(2, 0x81, pw1)
|
||||
|
||||
def cmd_get_response(self, expected_len):
|
||||
result = b""
|
||||
@@ -260,16 +340,20 @@ class OpenPGP_Card(object):
|
||||
data = b'\xb8\x00'
|
||||
else:
|
||||
data = b'\xa4\x00'
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data)
|
||||
if self.__reader.is_tpdu_reader():
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data, le=512)
|
||||
else:
|
||||
cmd_data = iso7816_compose(0x47, 0x80, 0, data)
|
||||
sw = self.__reader.send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
if len(sw) < 2:
|
||||
raise ValueError(sw)
|
||||
if sw[0] == 0x90 and sw[1] == 0x00:
|
||||
return b""
|
||||
elif sw[0] != 0x61:
|
||||
if sw[-2] == 0x61:
|
||||
pk = self.cmd_get_response(sw[1])
|
||||
elif sw[-2] == 0x90 and sw[-1] == 0x00:
|
||||
pk = sw
|
||||
else:
|
||||
raise ValueError("%02x%02x" % (sw[0], sw[1]))
|
||||
pk = self.cmd_get_response(sw[1])
|
||||
return (pk[9:9+256], pk[9+256+2:9+256+2+3])
|
||||
return (pk[9:9+256], pk[9+256+2:-2])
|
||||
|
||||
def cmd_get_public_key(self, keyno):
|
||||
if keyno == 1:
|
||||
@@ -280,10 +364,9 @@ class OpenPGP_Card(object):
|
||||
data = b'\xa4\x00'
|
||||
if self.__reader.is_tpdu_reader():
|
||||
cmd_data = iso7816_compose(0x47, 0x81, 0, data, le=512)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
else:
|
||||
cmd_data = iso7816_compose(0x47, 0x81, 0, data)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
r = self.__reader.send_cmd(cmd_data)
|
||||
if len(r) < 2:
|
||||
raise ValueError(r)
|
||||
sw = r[-2:]
|
||||
@@ -336,3 +419,48 @@ class OpenPGP_Card(object):
|
||||
raise ValueError(sw)
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def parse_kdf_data(kdf_data):
|
||||
if len(kdf_data) == 90:
|
||||
single_salt = True
|
||||
elif len(kdf_data) == 110:
|
||||
single_salt = False
|
||||
else:
|
||||
raise ValueError("length does not much", kdf_data)
|
||||
|
||||
if kdf_data[0:2] != b'\x81\x01':
|
||||
raise ValueError("data does not much")
|
||||
algo = kdf_data[2]
|
||||
if kdf_data[3:5] != b'\x82\x01':
|
||||
raise ValueError("data does not much")
|
||||
subalgo = kdf_data[5]
|
||||
if kdf_data[6:8] != b'\x83\x04':
|
||||
raise ValueError("data does not much")
|
||||
iters = unpack(">I", kdf_data[8:12])[0]
|
||||
if kdf_data[12:14] != b'\x84\x08':
|
||||
raise ValueError("data does not much")
|
||||
salt = kdf_data[14:22]
|
||||
if single_salt:
|
||||
salt_reset = None
|
||||
salt_admin = None
|
||||
if kdf_data[22:24] != b'\x87\x20':
|
||||
raise ValueError("data does not much")
|
||||
hash_user = kdf_data[24:56]
|
||||
if kdf_data[56:58] != b'\x88\x20':
|
||||
raise ValueError("data does not much")
|
||||
hash_admin = kdf_data[58:90]
|
||||
else:
|
||||
if kdf_data[22:24] != b'\x85\x08':
|
||||
raise ValueError("data does not much")
|
||||
salt_reset = kdf_data[24:32]
|
||||
if kdf_data[32:34] != b'\x86\x08':
|
||||
raise ValueError("data does not much")
|
||||
salt_admin = kdf_data[34:42]
|
||||
if kdf_data[42:44] != b'\x87\x20':
|
||||
raise ValueError("data does not much")
|
||||
hash_user = kdf_data[44:76]
|
||||
if kdf_data[76:78] != b'\x88\x20':
|
||||
raise ValueError("data does not much")
|
||||
hash_admin = kdf_data[78:110]
|
||||
return ( algo, subalgo, iters, salt, salt_reset, salt_admin,
|
||||
hash_user, hash_admin )
|
||||
|
||||
@@ -70,11 +70,11 @@ def build_privkey_template_for_remove(openpgp_keyno):
|
||||
keyspec = b'\xb8'
|
||||
else:
|
||||
keyspec = b'\xa4'
|
||||
return b'\x4d\02' + keyspec + b'\0x00'
|
||||
return b'\x4d\x02' + keyspec + b'\x00'
|
||||
|
||||
def compute_digestinfo(msg):
|
||||
digest = sha256(msg).digest()
|
||||
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
prefix = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
return prefix + digest
|
||||
|
||||
# egcd and modinv are from wikibooks
|
||||
|
||||
6
tests/skip_gnuk_only_tests.py
Normal file
6
tests/skip_gnuk_only_tests.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="module",autouse=True)
|
||||
def check_gnuk(card):
|
||||
if not card.is_gnuk:
|
||||
pytest.skip("Gnuk only feature", allow_module_level=True)
|
||||
6
tests/skip_if_emulation.py
Normal file
6
tests/skip_if_emulation.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="module",autouse=True)
|
||||
def check_emulation(card):
|
||||
if card.is_emulated_gnuk:
|
||||
pytest.skip("Emulation requires KDF setup", allow_module_level=True)
|
||||
6
tests/skip_if_gnuk.py
Normal file
6
tests/skip_if_gnuk.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="module",autouse=True)
|
||||
def check_gnuk(card):
|
||||
if card.is_gnuk:
|
||||
pytest.skip("Gnuk has no support for those features", allow_module_level=True)
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
test_empty_card.py - test empty card
|
||||
|
||||
Copyright (C) 2016 g10 Code GmbH
|
||||
Copyright (C) 2016, 2018 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -24,13 +24,11 @@ from binascii import hexlify
|
||||
from re import match, DOTALL
|
||||
from struct import pack
|
||||
from util import *
|
||||
from card_const import *
|
||||
import pytest
|
||||
|
||||
EMPTY_60=bytes(60)
|
||||
|
||||
FACTORY_PASSPHRASE_PW1=b"123456"
|
||||
FACTORY_PASSPHRASE_PW3=b"12345678"
|
||||
|
||||
def test_login(card):
|
||||
login = get_data_object(card, 0x5e)
|
||||
assert check_null(login)
|
||||
@@ -52,12 +50,21 @@ def test_sex(card):
|
||||
def test_name_lang_sex(card):
|
||||
name = b""
|
||||
lang = b""
|
||||
lang_de = b"de"
|
||||
sex = b"9"
|
||||
sex_alt = b"0"
|
||||
expected = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang)) + lang \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
expected_de = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang_de)) + lang_de \
|
||||
+ b'\x5f\x35' + pack('B', len(sex)) + sex
|
||||
expected_de_alt = b'\x5b' + pack('B', len(name)) + name \
|
||||
+ b'\x5f\x2d' + pack('B', len(lang_de)) + lang_de \
|
||||
+ b'\x5f\x35' + pack('B', len(sex_alt)) + sex_alt
|
||||
name_lang_sex = get_data_object(card, 0x65)
|
||||
assert name_lang_sex == b'' or name_lang_sex == expected
|
||||
assert name_lang_sex == b'' or name_lang_sex == expected \
|
||||
or name_lang_sex == expected_de or name_lang_sex == expected_de_alt
|
||||
|
||||
def test_app_data(card):
|
||||
app_data = get_data_object(card, 0x6e)
|
||||
@@ -142,11 +149,12 @@ def test_historical_bytes(card):
|
||||
h = get_data_object(card, 0x5f52)
|
||||
assert h == b'\x001\xc5s\xc0\x01@\x05\x90\x00' or \
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x00\x90\x00' or \
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x05\x90\x00'
|
||||
h == b'\x00\x31\x84\x73\x80\x01\x80\x05\x90\x00' or \
|
||||
h == b'\x00\x31\xf5\x73\xc0\x01\x60\x05\x90\x00'
|
||||
|
||||
def test_extended_capabilities(card):
|
||||
a = get_data_object(card, 0xc0)
|
||||
assert a == None or match(b'[\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00', a)
|
||||
assert a == None or match(b'[\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00', a)
|
||||
|
||||
def test_algorithm_attributes_1(card):
|
||||
a = get_data_object(card, 0xc1)
|
||||
2
tests/test_001_personalize_card.py
Normal file
2
tests/test_001_personalize_card.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from skip_if_emulation import *
|
||||
from card_test_personalize_card import *
|
||||
2
tests/test_002_personalize_reset.py
Normal file
2
tests/test_002_personalize_reset.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from skip_if_emulation import *
|
||||
from card_test_personalize_reset import *
|
||||
2
tests/test_003_remove_keys.py
Normal file
2
tests/test_003_remove_keys.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from skip_if_emulation import *
|
||||
from card_test_remove_keys import *
|
||||
2
tests/test_004_reset_pw3.py
Normal file
2
tests/test_004_reset_pw3.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from skip_if_emulation import *
|
||||
from card_test_reset_pw3 import *
|
||||
29
tests/test_005_personalize_admin_less.py
Normal file
29
tests/test_005_personalize_admin_less.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
test_005_personalize_admin_less.py - test admin-less mode
|
||||
|
||||
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from skip_if_emulation import *
|
||||
from skip_gnuk_only_tests import *
|
||||
|
||||
from card_test_personalize_admin_less import *
|
||||
from card_test_personalize_reset import *
|
||||
from card_test_remove_keys import *
|
||||
from card_test_reset_pw3 import *
|
||||
9
tests/test_006_pso.py
Normal file
9
tests/test_006_pso.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from skip_if_gnuk import *
|
||||
from card_test_ed25519 import *
|
||||
from card_test_x25519 import *
|
||||
from card_test_ansix9p256r1 import *
|
||||
from card_test_ansix9p384r1 import *
|
||||
from card_test_ansix9p512r1 import *
|
||||
from card_test_brainpoolp256r1 import *
|
||||
from card_test_brainpoolp384r1 import *
|
||||
from card_test_brainpoolp512r1 import *
|
||||
25
tests/test_009_keygen.py
Normal file
25
tests/test_009_keygen.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
test_005_keygen.py - test key generation
|
||||
|
||||
Copyright (C) 2018, 2019 g10 Code GmbH
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from skip_if_emulation import *
|
||||
from card_test_keygen import *
|
||||
from card_test_remove_keys import *
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user