Compare commits
83 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2471616f74 | ||
|
|
3926f42647 | ||
|
|
ce070f85ff | ||
|
|
bd02cbfdb0 | ||
|
|
16149ff960 | ||
|
|
c4a5681f35 | ||
|
|
3d5a776ab1 | ||
|
|
9f4671eaf6 | ||
|
|
5af5d18310 | ||
|
|
3765c9233b | ||
|
|
0bd0af1fe1 | ||
|
|
92189e2d12 | ||
|
|
6dcd5aa00c | ||
|
|
09d3068222 | ||
|
|
0f11d320e6 | ||
|
|
365308f374 | ||
|
|
0e510b32c1 | ||
|
|
a9244d9b13 | ||
|
|
c268e59813 | ||
|
|
e7e8b9f5ca | ||
|
|
d6e70ab0f4 | ||
|
|
3cca2798b0 | ||
|
|
a695ad03ab | ||
|
|
41f5145fe1 | ||
|
|
b6db3b449e | ||
|
|
c54bb0c559 | ||
|
|
91222b5e22 | ||
|
|
f89b9ef8b7 | ||
|
|
4e984276e3 | ||
|
|
abde30b943 | ||
|
|
8d56a4bff5 | ||
|
|
fd8543f092 | ||
|
|
9cba1e2a8e | ||
|
|
8f33df9819 | ||
|
|
ff3df302e4 | ||
|
|
75e8de2df1 | ||
|
|
8e6fa1a627 | ||
|
|
14e2633c52 | ||
|
|
0d59d31230 | ||
|
|
f82206e7d5 | ||
|
|
9ea262ffde | ||
|
|
1309527c3c | ||
|
|
df08bb473c | ||
|
|
d7c3441dd4 | ||
|
|
cd06bada05 | ||
|
|
e25f50eabc | ||
|
|
62a59b56fe | ||
|
|
4f1343e154 | ||
|
|
272875ee76 | ||
|
|
85b2698bb3 | ||
|
|
4d6f59079a | ||
|
|
53aa3de9b4 | ||
|
|
afa0683495 | ||
|
|
a7f3a3e260 | ||
|
|
9cd4a1a47f | ||
|
|
f9ed79f644 | ||
|
|
c7a6370b74 | ||
|
|
dc4584a8a5 | ||
|
|
89f0af1496 | ||
|
|
28a5799cf7 | ||
|
|
07b960009a | ||
|
|
b37a1e728e | ||
|
|
c5bdc370dd | ||
|
|
9c5eb9ea4b | ||
|
|
356a9cc615 | ||
|
|
5882b37b58 | ||
|
|
1920c5fc69 | ||
|
|
fc53d507ce | ||
|
|
da027eb67f | ||
|
|
fcf6c60336 | ||
|
|
cbf896a61b | ||
|
|
adbb67deb8 | ||
|
|
129d1b0d30 | ||
|
|
25e71cb29b | ||
|
|
7d8696946a | ||
|
|
2bb12e55c2 | ||
|
|
fa10e78344 | ||
|
|
116486affa | ||
|
|
53bf87acf5 | ||
|
|
22bc67959e | ||
|
|
971ee94d8f | ||
|
|
a3504e8510 | ||
|
|
bfe0466bd2 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "chopstx"]
|
||||
path = chopstx
|
||||
url = git@gitorious.org:chopstx/chopstx.git
|
||||
url = ../../chopstx/chopstx.git
|
||||
|
||||
380
ChangeLog
380
ChangeLog
@@ -1,3 +1,383 @@
|
||||
2015-06-03 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.5.
|
||||
|
||||
* test/ecc_nistp256_keys.py: New.
|
||||
|
||||
* tool/upgrade_by_passwd.py: Remove -p option and add -f option.
|
||||
|
||||
* tool/gnuk_token.py (gnuk_token.download): Add verbose flag.
|
||||
(regnual.download): Ditto.
|
||||
|
||||
* tool/gnuk_upgrade.py: Use gnuk_token module.
|
||||
|
||||
2015-06-02 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Support OpenPGPcard spec v3.0.
|
||||
|
||||
2015-04-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Upgrade to 0.05.
|
||||
|
||||
2015-04-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (CCID_CARD_INIT): New.
|
||||
* src/usb_desc.c (gnukConfigDescriptor): Update dwDefaultClock,
|
||||
dwMaximumClock, dwFeatures, and bClassEnvelope.
|
||||
* src/usb_ctrl.c (freq_table): Change the value to 4000MHz.
|
||||
(usb_cb_handle_event): Call ccid_card_change_signal after configure.
|
||||
* src/usb-icc.c (ccid_thread): Change EV_CARD_CHANGE handling.
|
||||
|
||||
2015-04-18 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c (main): Call chopstx_main_init.
|
||||
* src/Makefile.in (DEFS): Remove CHX_PRIO_MAIN.
|
||||
|
||||
2015-04-17 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure: Fix shell syntax.
|
||||
|
||||
2015-03-31 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_conf.h (ICC_NUM_INTERFACES, HID_NUM_INTERFACES)
|
||||
(HID_NUM_INTERFACES, VCOM_NUM_INTERFACES, MSC_NUM_INTERFACES)
|
||||
(NUM_INTERFACES): Define here (moved from usb_desc.c).
|
||||
(ICC_INTERFACE, HID_INTERFACE, VCOM_INTERFACE_0, VCOM_INTERFACE_1)
|
||||
(MSC_INTERFACE): New.
|
||||
* src/usb_ctrl.c (gnuk_setup_endpoints_for_interface)
|
||||
(usb_cb_setup, usb_cb_ctrl_write_finish): Use *_INTERFACE.
|
||||
* src/usb_desc.c (gnukConfigDescriptor): Likewise.
|
||||
|
||||
2015-03-06 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (eddsa_sign_25519): Return 0.
|
||||
|
||||
2015-02-25 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_internal_authenticate): Fix storing to
|
||||
res_APDU_size.
|
||||
|
||||
2015-02-10 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Fix counter update for EdDSA. Thanks
|
||||
to Jonathan Schleifer.
|
||||
|
||||
* src/call-rsa.c (rsa_sign): Don't set res_APDU_len.
|
||||
(rsa_decrypt): Likewise, but get OUTPUT_LEN_P as an argument.
|
||||
|
||||
2015-02-09 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Fix EdDSA. Use GPG_KEY_FOR_SIGNING.
|
||||
|
||||
2014-12-15 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.4.
|
||||
|
||||
2014-12-13 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/flash.c (flash_key_getpage, flash_key_release_page): New.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_delete_prvkey): New arg.
|
||||
(rw_algorithm_attr): Call gpg_do_delete_prvkey with CLEAN_PAGE_FULL.
|
||||
|
||||
2014-12-12 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/Makefile.in (build/bignum.o): Specific OPT for this target.
|
||||
|
||||
* src/configure (target): Default is FST-01.
|
||||
(--with-dfu): FST-01 doesn't have DFU. If set, it must be
|
||||
mistake.
|
||||
|
||||
* boards/STBEE_MINI: Remove, since it is now supported by Chopstx.
|
||||
|
||||
* test/features/802_get_data_static.feature: Reflect the change
|
||||
of extended capabilities.
|
||||
* test/features/402_get_data_static.feature: Ditto.
|
||||
* test/features/002_get_data_static.feature: Ditto.
|
||||
|
||||
* test/features/003_keyattr_change.feature: New test.
|
||||
|
||||
* src/usb_lld.h: Don't use 'extern' for function declarations.
|
||||
* src/usb-icc.c (end_cmd_apdu_data): Fix Le handling.
|
||||
|
||||
2014-12-11 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Upgrade to 0.04.
|
||||
* src/syc.c: Update from 0.04.
|
||||
|
||||
2014-12-10 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-cdh.c: Remove as smartcard only does
|
||||
a part of ECDH computation as gpg-agent does.
|
||||
|
||||
* src/chconf.h, src/halconf.h: Remove files needed for ChibiOS/RT.
|
||||
|
||||
2014-12-09 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/call-ec.c (ecc_compute_public): Rename, as we share
|
||||
same routine among ECDSA and ECDH.
|
||||
(ecdh_decrypt): New.
|
||||
|
||||
2014-12-09 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc.c (compute_kP): Bug fix. It's P, not G.
|
||||
(point_is_on_the_curve): Bug fix.
|
||||
|
||||
2014-12-03 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
Changes for RSA-4096.
|
||||
|
||||
* src/gnuk.h (MAX_CMD_APDU_DATA_SIZE, MAX_RES_APDU_DATA_SIZE):
|
||||
Send/Recv buffer should be bigger.
|
||||
* polarssl/library/bignum.c (mpi_exp_mod): Don't consume much.
|
||||
* polarssl/library/rsa.c (rsa_rsaes_pkcs1_v15_decrypt): buffer
|
||||
allocation size should be variable.
|
||||
|
||||
2014-12-01 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/Makefile.in (DEFS): Don't define compile time preference of
|
||||
key algo attributes.
|
||||
|
||||
* src/openpgp-do.c (proc_key_import): Support modifiable key algo
|
||||
attributes.
|
||||
|
||||
2014-11-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (ALGO_RSA4K, ALGO_NISTP256R1, ALGO_SECP256K1)
|
||||
(ALGO_ED25519, ALGO_RSA2K): New.
|
||||
(struct key_data_internal): Move to ...
|
||||
* src/openpgp-do.c (struct key_data_internal): ... here.
|
||||
(CHECKSUM_ADDR, kdi_len): New.
|
||||
(CKDC_CALC, CKDC_CHECK): New.
|
||||
(compute_key_data_checksum): Add arg PRVKEY_LEN.
|
||||
(gpg_do_load_prvkey, gpg_do_delete_prvkey): Support modifiable key
|
||||
algo attributes.
|
||||
(gpg_do_write_prvkey, gpg_do_public_key, gpg_do_keygen): Likewise.
|
||||
(gpg_do_clear_prvkey): Use MAX_PRVKEY_LEN.
|
||||
|
||||
* src/openpgp.c (gpg_init): Call flash_init_keys after
|
||||
gpg_data_scan.
|
||||
(cmd_pso): Support modifiable key algo attributes.
|
||||
(cmd_internal_authenticate): Likewise.
|
||||
|
||||
2014-11-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (algorithm_attr_rsa2k): Rename from *_rsa.
|
||||
(algorithm_attr_rsa4k): New.
|
||||
(get_algo_attr_pointer, kk_to_nr, gpg_get_algo_attr)
|
||||
(get_algo_attr_data_object, gpg_get_algo_attr_key_size): New.
|
||||
(rw_algorithm_attr): New.
|
||||
(gpg_do_table): Register rw_algorithm_attr for GPG_DO_ALG_*.
|
||||
(gpg_data_scan, gpg_data_copy): Handle algo attributes.
|
||||
|
||||
(rw_pw_status): Fix checking against redundant write.
|
||||
|
||||
2014-11-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (extended_capabilities): Key attributes can be
|
||||
modifid now.
|
||||
|
||||
2014-11-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (NR_NONE, NR_DO__FIRST__): Remove.
|
||||
(NR_DO_*): Redefine.
|
||||
(NR_KEY_ALGO_ATTR_SIG, NR_KEY_ALGO_ATTR_DEC)
|
||||
(NR_KEY_ALGO_ATTR_AUT): New.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_load_prvkey, gpg_do_delete_prvkey)
|
||||
(gpg_do_write_prvkey, gpg_do_chks_prvkey, gpg_data_scan)
|
||||
(gpg_data_copy, gpg_do_read_simple)
|
||||
(gpg_do_write_simple): Don't use NR_DO__FIRST__.
|
||||
(gpg_do_put_data): Don't use NR_NONE any more.
|
||||
(do_tag_to_nr): Use -1 to specify NONE.
|
||||
|
||||
* src/flash.c (flash_enum_clear, flash_enum_write_internal)
|
||||
(flash_enum_write): New.
|
||||
|
||||
2014-11-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (FIRMWARE_UPDATE_KEY_CONTENT_LEN): New.
|
||||
(size_of_key): New enum.
|
||||
|
||||
* src/openpgp.c (gpg_get_firmware_update_key)
|
||||
(cmd_read_binary, cmd_external_authenticate): Use
|
||||
FIRMWARE_UPDATE_KEY_CONTENT_LEN.
|
||||
|
||||
* src/flash.c (KEY_SIZE): Remove.
|
||||
(key_available_at): Add new arg as KEY_SIZE.
|
||||
(flash_check_all_other_keys_released): Likewise.
|
||||
(flash_key_fill_zero_as_released, flash_key_release): Likewise.
|
||||
|
||||
(flash_init): Move initializing keys into another function.
|
||||
(flash_init_keys): New function.
|
||||
|
||||
(flash_key_alloc): Use gpg_get_algo_attr_key_size.
|
||||
(flash_key_write): Add new arg as KEY_DATA_LEN.
|
||||
|
||||
(flash_write_binary): Use FIRMWARE_UPDATE_KEY_CONTENT_LEN.
|
||||
|
||||
2014-09-16 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (MAX_PRVKEY_LEN): New.
|
||||
(KEY_CONTENT_LEN): Remove.
|
||||
|
||||
* src/call-rsa.c (RSA_SIGNATURE_LENGTH): Remove.
|
||||
(rsa_sign, rsa_verify, rsa_genkey): Add new arg: PUBKEY_LEN.
|
||||
(rsa_decrypt): Don't use KEY_CONTENT_LEN.
|
||||
|
||||
2014-06-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-mont.c (compute_nQ): Add comment.
|
||||
|
||||
* src/mod.c (mod_inv): Fix comment. X^-1 = 0 when X=0
|
||||
is important for Montgomery curve computation.
|
||||
|
||||
2014-06-05 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/add_openpgp_authkey_from_gpgssh.py: New.
|
||||
|
||||
2014-04-17 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/muladd_256.h (MULADD_256_ASM): New.
|
||||
(MULADD_256): Use MULADD_256_ASM.
|
||||
* src/ecc-mont.c (mod25638_mul_121665): Add asm implementation.
|
||||
|
||||
* src/bn.c (bn256_add_uint, bn256_sub_uint): Simplify.
|
||||
* src/mod25638.c (mod25638_add, mod25638_sub): Simplify.
|
||||
(n25638, add19): Remove.
|
||||
(ADDWORD_256): Add s_ as source pointer.
|
||||
(mod25519_reduce): Remove a call to memcpy. Use bn256_add_uint.
|
||||
* src/ecc-edwards.c (point_double): Simplify.
|
||||
|
||||
2014-04-16 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.3.
|
||||
|
||||
2014-04-15 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-mont.c: New.
|
||||
|
||||
* src/mod25638.c (p25519): Move from ecc-edwards.c.
|
||||
(mod25519_reduce, add19): Likewise.
|
||||
(mod25638_reduce) [!ASM_IMPLEMENTATION]: Use bn256_add_uint.
|
||||
|
||||
2014-04-14 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/jpc.c (jpc_to_ac): Error check before mod_inv.
|
||||
|
||||
* src/mod.c (mod_inv): No return value (if N==0 returns ZERO).
|
||||
|
||||
* src/bn.c [BN256_NO_RANDOM]: Only include "random.h" if needed.
|
||||
|
||||
2014-04-08 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/mod.c (mod_inv): Use MAX_GCD_STEPS_BN256.
|
||||
Return failure or success.
|
||||
* src/jpc.c (jpc_to_ac): Use mod_inv.
|
||||
* src/modp256k1.c (modp256k1_inv): Remove.
|
||||
* src/modp256r1.c (modp256r1_inv): Remove.
|
||||
|
||||
2014-04-07 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (algorithm_attr_ed25519): It's OID only.
|
||||
|
||||
2014-04-03 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (eddsa_sign_25519): Change type of OUT.
|
||||
* src/openpgp.c (cmd_internal_authenticate): Have a buffer.
|
||||
|
||||
* src/flash.c (flash_init): Fix key address finder.
|
||||
|
||||
2014-04-02 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (proc_key_import): Handle EdDSA.
|
||||
(algorithm_attr_ed25519): Fix OID and add ID for SHA512.
|
||||
|
||||
2014-04-01 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (eddsa_compute_public_25519): New.
|
||||
|
||||
* src/openpgp-do.c (algorithm_attr_ed25519): New.
|
||||
(gpg_do_write_prvkey, proc_key_import, gpg_do_public_key): Add
|
||||
EdDSA handling.
|
||||
|
||||
2014-03-31 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (eddsa_sign_25519): Rename and API change.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_load_prvkey, gpg_do_delete_prvkey)
|
||||
(gpg_do_write_prvkey, gpg_do_public_key, gpg_do_keygen): Follow
|
||||
the change of PRVKEY_DATA and KEY_DATA.
|
||||
|
||||
* src/flash.c (key_available_at): New.
|
||||
(flash_init): Initilize KD.
|
||||
|
||||
* src/gnuk.h (struct prvkey_data): Remove member KEY_ADDR.
|
||||
(struct key_data): Addd member KEY_ADDR.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_keygen): Bug fix. Reset the signature
|
||||
counter when new key is generated.
|
||||
|
||||
* src/flash.c (flash_key_alloc): Change API, supply KK.
|
||||
|
||||
2014-03-29 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (point_double, point_add): Rename.
|
||||
(mod25519_reduce): New.
|
||||
|
||||
2014-03-28 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* misc/t-eddsa.c (main): Update for new API of eddsa_25519.
|
||||
|
||||
* src/ecc-edwards.c (compute_kG_25519): Tune for 252-bit.
|
||||
(eddsa_25519): Public key should be provided by caller.
|
||||
(eddsa_public_key_25519): New.
|
||||
|
||||
2014-03-27 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (ed_add_25638): Remove the third argument.
|
||||
(compute_kG_25519): The curve is complete, we don't need to avoid
|
||||
identity element as NIST curve or secp256k1 curve.
|
||||
(eddsa_25519): Change the API, with A and the seed.
|
||||
|
||||
2014-03-26 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/mod25638.c (mod25638_reduce): New.
|
||||
(mod25638_mul, mod25638_sqr): Use mod25638_reduce.
|
||||
|
||||
* src/ecc-edwards.c (ptc_to_ac_25519): No need to subtract p25519.
|
||||
|
||||
2014-03-25 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* misc/t-eddsa.c: New.
|
||||
|
||||
* src/ecc-edwards.c (bnX_mul_C, mod_reduce_M): New.
|
||||
(eddsa_25519): New.
|
||||
|
||||
2014-03-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (ed_add_25638): Fix for X == A.
|
||||
(main): Compute pre-computed tables.
|
||||
(precomputed_KG, precomputed_2E_KG): Add.
|
||||
(compute_kG_25519): New.
|
||||
|
||||
2014-03-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/bn.c (bn256_add): Fix for X == B.
|
||||
(bn256_sub): Likewise.
|
||||
|
||||
* src/ecc-edwards.c: New.
|
||||
|
||||
2014-03-18 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/mod25638.c (mod25638_add, mod25638_sub, mod25638_sqr)
|
||||
(mod25638_shift): New.
|
||||
|
||||
2014-03-13 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/mod25638.c: Rename from fe25519.c.
|
||||
* src/mod25638.h: Likewise.
|
||||
|
||||
2014-03-07 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.2.
|
||||
|
||||
58
NEWS
58
NEWS
@@ -1,5 +1,63 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
* Major changes in Gnuk 1.1.5
|
||||
|
||||
Released 2015-06-03, by NIIBE Yutaka
|
||||
|
||||
** upgrade_by_passwd.py is not so noisy any more.
|
||||
Since it's getting stable, no debug output any more.
|
||||
|
||||
** Maple mini support.
|
||||
Although it's random number generation is not tested, Maple mini
|
||||
support is added.
|
||||
|
||||
** Windows interoperability fix.
|
||||
1.1.x (0 to 4) didn't work with Windows because of INTERRUPT transfer.
|
||||
It's fixed and it works now.
|
||||
|
||||
** OpenPGPcard specification v3.0 compatibility.
|
||||
OpenPGPcard specification v3.0 now include NIST curves (and other
|
||||
curves) and ECDSA and ECDH operations are defined. Gnuk follows
|
||||
this specification.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.4
|
||||
|
||||
Released 2014-12-15, by NIIBE Yutaka
|
||||
|
||||
** Experimental RSA-4096 support.
|
||||
Although it takes too long (more than 8.7 second), RSA-4096
|
||||
is now implemented.
|
||||
|
||||
** ECDH support.
|
||||
ECDH is now supported. You need development branch (master)
|
||||
of GnuPG to use this feature.
|
||||
|
||||
** ECDSA and EdDSA is not that experimental.
|
||||
You don't need to edit DEFS variable in src/Makefile.
|
||||
|
||||
** STM8S_DISCOVERY is not supported any more.
|
||||
It's flash ROM size (64KiB) is a bit small to have all features of
|
||||
Gnuk now. If you manually edit code to limit the size of executable,
|
||||
it still could run Gnuk, though.
|
||||
|
||||
** configure's default target is now FST-01.
|
||||
Receiving reports from those who complain default target, I
|
||||
reconsidered. Those who has Olimex STM32 H103 usually has JTAG
|
||||
debugger, while FST-01 users don't. So, to be safe, the default
|
||||
target is now FST-01, instead of Olimex STM32 H103.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.3
|
||||
|
||||
Released 2014-04-16, by NIIBE Yutaka
|
||||
|
||||
** Experimental EdDSA support.
|
||||
After configure, you can edit the DEFS variable in src/Makefile, so
|
||||
that Gnuk can support EdDSA with Ed25519 (for authentication). Note
|
||||
that this is pretty much experimental, and subjects to change.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.2
|
||||
|
||||
Released 2014-03-07, by NIIBE Yutaka
|
||||
|
||||
131
README
131
README
@@ -1,28 +1,31 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.1.2
|
||||
2014-03-07
|
||||
Version 1.1.5
|
||||
2015-06-03
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Warning
|
||||
=======
|
||||
|
||||
This is another experimental release of Gnuk, version 1.1.2, which has
|
||||
This is another experimental release of Gnuk, version 1.1.5, which has
|
||||
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
|
||||
that the instruction of importing keys won't cause any confusion. It
|
||||
has support of ECDSA (with NIST P256 and secp256k1), but this feature
|
||||
is pretty much experimental, and it requires development version of
|
||||
GnuPG with newest version of libgcrypt.
|
||||
has supports of ECDSA (with NIST P256 and secp256k1) and EdDSA with
|
||||
EdDSA, but this feature is pretty much experimental, and it requires
|
||||
development version of GnuPG with newest version of libgcrypt. You
|
||||
will not able to keep using EdDSA keys, as the key format is subject
|
||||
to change. It also support RSA-4096 experimentally, but users should
|
||||
know that it takes more than 8 second to sign/decrypt.
|
||||
|
||||
|
||||
What's Gnuk?
|
||||
============
|
||||
|
||||
Gnuk is an implementation of USB cryptographic token for GNU Privacy
|
||||
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
|
||||
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
|
||||
STM32F103 processor.
|
||||
|
||||
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
|
||||
@@ -55,16 +58,15 @@ A0: Good points of Gnuk are:
|
||||
"for Free Software"; Gnuk supports GnuPG.
|
||||
|
||||
Q1: What kind of key algorithm is supported?
|
||||
A1: Gnuk version 1.0 only supports 2048-bit RSA.
|
||||
Development version of Gnuk (1.1.x) supports 256-bit ECDSA.
|
||||
A1: Gnuk version 1.0 only supports RSA 2048.
|
||||
Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA,
|
||||
as well as RSA 4096-bit. But it takes long time to sign with RSA 4096.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so.
|
||||
|
||||
Q3: What's your recommendation for target board?
|
||||
A3: Orthodox choice is Olimex STM32-H103.
|
||||
If you have skill of electronics and like DIY, STM32 part of STM8S
|
||||
Discovery Kit might be the best choice.
|
||||
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
|
||||
kind of the best choice, hopefully.
|
||||
|
||||
@@ -87,13 +89,7 @@ A6: You need a target board plus a JTAG/SWD debugger. If you just
|
||||
Q7: How much does it cost?
|
||||
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
|
||||
|
||||
Q8: How much does it cost for DIY version?
|
||||
A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build
|
||||
your own JTAG debugger using FTDI2232 module (1450 JPY), see:
|
||||
http://www.fsij.org/gnuk/jtag_dongle_ftdi2232
|
||||
|
||||
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
|
||||
|
||||
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
|
||||
card/reader. When your newly inserted token is not found by
|
||||
GnuPG, try killing scdaemon and let it to be invoked again. I do:
|
||||
@@ -110,7 +106,7 @@ Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
Qb: With GNOME 3, I can't use Gnuk Token at all. Why?
|
||||
Qb: With GNOME 3.0, I can't use Gnuk Token at all. Why?
|
||||
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
|
||||
|
||||
$ gnome-session-properties
|
||||
@@ -122,6 +118,16 @@ Qc: Do you know a good SWD debugger to connect FST-01 or something?
|
||||
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
|
||||
writer program.
|
||||
|
||||
Qd: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
|
||||
Ad: Please set the configration variable OnlyShowIn as none. Like:
|
||||
|
||||
OnlyShowIn=
|
||||
|
||||
In the files of /etc/xdg/autostart/gnome-keyring-gpg.desktop and
|
||||
/etc/xdg/autostart/gnome-keyring-ssh.desktop
|
||||
|
||||
|
||||
|
||||
|
||||
Release notes
|
||||
=============
|
||||
@@ -129,9 +135,10 @@ Release notes
|
||||
This is third experimental release in version 1.1 series of Gnuk.
|
||||
|
||||
While it is daily use by its developer, some newly introduced features
|
||||
(including ECDSA, key generation and firmware upgrade) should be
|
||||
considered experimental. ECDSA is really experimental. The feature
|
||||
even requires manual edit of Makefile after 'configure'.
|
||||
(including ECDSA/EdDSA, key generation and firmware upgrade) should be
|
||||
considered experimental. ECDSA/EdDSA is really experimental.
|
||||
Further, EdDSA is much experimental. You won't be able to keep using
|
||||
the EdDSA key, as the key format of GnuPG is subject to change.
|
||||
|
||||
Tested features are:
|
||||
|
||||
@@ -172,20 +179,19 @@ It is known not-working well:
|
||||
Targets
|
||||
=======
|
||||
|
||||
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We
|
||||
also use STM32 part of STM8S Discovery Kit.
|
||||
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01).
|
||||
|
||||
With DfuSe support, STBee is also our targets. But this target with
|
||||
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 PIN-pad support, I connect a consumer IR receive module to FST-01
|
||||
and STM8S Discovery Kit, 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.
|
||||
For 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.
|
||||
@@ -223,7 +229,7 @@ External source code
|
||||
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* chopstx/ -- Chopstx 0.03 (+ STBee support)
|
||||
* chopstx/ -- Chopstx 0.04
|
||||
|
||||
We use Chopstx as the kernel for Gnuk.
|
||||
|
||||
@@ -365,7 +371,7 @@ Olimex STM32-H103 board
|
||||
|
||||
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
|
||||
|
||||
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
|
||||
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
|
||||
|
||||
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
|
||||
@@ -380,30 +386,7 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
Flying Stone Tiny 01
|
||||
--------------------
|
||||
|
||||
If you are using Flying Stone Tiny 01, you need a SWD writer. I am
|
||||
using revision 946 of Simon Qian's Versaloon.
|
||||
|
||||
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
|
||||
|
||||
For OpenOCD, we need unofficial patch.
|
||||
|
||||
See the article of Versaloon Forum:
|
||||
|
||||
http://www.versaloon.com/bbs/viewtopic.php?p=16179
|
||||
|
||||
|
||||
Type following to invoke OpenOCD:
|
||||
|
||||
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
|
||||
|
||||
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> flash write_image erase gnuk.elf
|
||||
> reset
|
||||
> exit
|
||||
$
|
||||
If you are using Flying Stone Tiny 01, you need a SWD writer.
|
||||
|
||||
OpenOCD 0.6.1 now supports ST-Link/V2. We can use it:
|
||||
|
||||
@@ -412,29 +395,6 @@ OpenOCD 0.6.1 now supports ST-Link/V2. We can use it:
|
||||
But it doesn't support option bytes handling (protection) yet.
|
||||
|
||||
|
||||
STM8S Discovery Kit
|
||||
-------------------
|
||||
|
||||
If you are using FTDI-2232D module and the connection is standard, type:
|
||||
|
||||
$ openocd -f interface/openocd-usb.cfg -f target/stm32f1x.cfg
|
||||
|
||||
Initially, the flash ROM of the chip is protected. you need to do:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> stm32f1x unlock 0
|
||||
> reset
|
||||
> shutdown
|
||||
$
|
||||
|
||||
and re-connect the board. Note that power-off / power-on sequence is
|
||||
required to reset flash ROM.
|
||||
|
||||
Then, invoke OpenOCD again and telnet to connect OpenCD and write
|
||||
image as above example of Olimex STM32-H103.
|
||||
|
||||
|
||||
STBee
|
||||
-----
|
||||
|
||||
@@ -584,14 +544,14 @@ See doc/note/firmware-update.
|
||||
Git Repositories
|
||||
================
|
||||
|
||||
Please use: http://gitorious.org/gnuk
|
||||
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://gitorious.org/gnuk/gnuk.git
|
||||
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
|
||||
|
||||
It's also available at: www.gniibe.org
|
||||
You can browse at: http://www.gniibe.org/gitweb?p=gnuk.git;a=summary
|
||||
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
|
||||
|
||||
I put Chopstx as a submodule of Git. Please do this:
|
||||
|
||||
@@ -610,6 +570,14 @@ Information on the Web
|
||||
|
||||
Please visit: http://www.fsij.org/gnuk/
|
||||
|
||||
Please see the FST-01 support pages:
|
||||
|
||||
http://www.gniibe.org/category/fst-01.html
|
||||
|
||||
Please consider to join Gnuk-users mailing list:
|
||||
|
||||
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
|
||||
|
||||
|
||||
Your Contributions
|
||||
==================
|
||||
@@ -620,5 +588,6 @@ to FSIJ (if possible).
|
||||
|
||||
Foot note
|
||||
==========
|
||||
|
||||
* NUK(R) is a registered trademark owend by MAPA GmbH, Germany.
|
||||
--
|
||||
|
||||
3
THANKS
3
THANKS
@@ -8,6 +8,7 @@ encouraging the development, testing the implementation, suggesting
|
||||
improvements, or fixing bugs. Here is a list of those people.
|
||||
|
||||
Achim Pietig achim@pietig.com
|
||||
Aidan Thornton
|
||||
Andre Zepezauer andre.zepezauer@student.uni-halle.de
|
||||
Hironobu SUZUKI hironobu@h2np.net
|
||||
Jan Suhr jan@suhr.info
|
||||
@@ -17,7 +18,9 @@ Luis Felipe R. Murillo luisfelipe@ucla.edu
|
||||
MATSUU Takuto matsuu@gentoo.org
|
||||
NAGAMI Takeshi nagami-takeshi@aist.go.jp
|
||||
Nguyễn Hồng Quân quannguyen@mbm.vn
|
||||
NOKUBI Takatsugu knok@daionet.gr.jp
|
||||
Paul Bakker polarssl_maintainer@polarssl.org
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
Vasily Evseenko
|
||||
Werner Koch wk@gnupg.org
|
||||
Yuji Imai ug@xcast.jp
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
/*
|
||||
* Board-specific initialization code.
|
||||
*/
|
||||
void boardInit(void)
|
||||
{
|
||||
#if !defined(DFU_SUPPORT)
|
||||
if (palReadPad (IOPORT3, GPIOC_BUTTON) == 0)
|
||||
/*
|
||||
* Since LEDs are connected to JTMS/SWDIO and JTDI pin,
|
||||
* we can't use LED to let know users in this state.
|
||||
*/
|
||||
for (;;); /* Wait for JTAG debugger connection */
|
||||
#endif
|
||||
|
||||
#if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT)
|
||||
palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */
|
||||
while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0)
|
||||
; /* Wait for JTAG debugger connection */
|
||||
palWritePort(IOPORT2, 0xffff); /* All set */
|
||||
#endif
|
||||
|
||||
#if defined(PINPAD_CIR_SUPPORT)
|
||||
/* EXTI0 <= PB0 */
|
||||
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
|
||||
EXTI->IMR = 0;
|
||||
EXTI->FTSR = EXTI_FTSR_TR0;
|
||||
NVICEnableVector(EXTI0_IRQn,
|
||||
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||
|
||||
/* TIM3 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM3RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
NVICEnableVector(TIM3_IRQn,
|
||||
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||
TIM3->CR1 = TIM_CR1_URS | TIM_CR1_ARPE; /* Don't enable TIM3 for now */
|
||||
TIM3->CR2 = TIM_CR2_TI1S;
|
||||
TIM3->SMCR = TIM_SMCR_TS_0 | TIM_SMCR_TS_2 | TIM_SMCR_SMS_2;
|
||||
TIM3->DIER = 0; /* Disable interrupt for now */
|
||||
TIM3->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_3
|
||||
| TIM_CCMR1_CC2S_1 | TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_3;
|
||||
TIM3->CCMR2 = 0;
|
||||
TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
|
||||
TIM3->PSC = 72 - 1; /* 1 MHz */
|
||||
TIM3->ARR = 18000; /* 18 ms */
|
||||
/* Generate UEV to upload PSC and ARR */
|
||||
TIM3->EGR = TIM_EGR_UG;
|
||||
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||
/* EXTI2 <= PB2 */
|
||||
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI2_PB;
|
||||
EXTI->IMR = 0;
|
||||
EXTI->FTSR = EXTI_FTSR_TR2;
|
||||
NVICEnableVector(EXTI2_IRQn,
|
||||
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||
|
||||
/* TIM4 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_TIM4RST;
|
||||
RCC->APB1RSTR = 0;
|
||||
|
||||
TIM4->CR1 = TIM_CR1_URS | TIM_CR1_ARPE | TIM_CR1_CKD_1;
|
||||
TIM4->CR2 = 0;
|
||||
TIM4->SMCR = TIM_SMCR_SMS_0;
|
||||
TIM4->DIER = 0; /* no interrupt */
|
||||
TIM4->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0
|
||||
| TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 | TIM_CCMR1_IC1F_3
|
||||
| TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_IC2F_2 | TIM_CCMR1_IC2F_3;
|
||||
TIM4->CCMR2 = 0;
|
||||
TIM4->CCER = 0;
|
||||
TIM4->PSC = 0;
|
||||
TIM4->ARR = 31;
|
||||
/* Generate UEV to upload PSC and ARR */
|
||||
TIM4->EGR = TIM_EGR_UG;
|
||||
#endif
|
||||
/*
|
||||
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
|
||||
*/
|
||||
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE;
|
||||
/* We use LED2 as optional "error" indicator */
|
||||
palSetPad (IOPORT1, GPIOA_LED2);
|
||||
}
|
||||
|
||||
#if defined(PINPAD_CIR_SUPPORT)
|
||||
void
|
||||
cir_ext_disable (void)
|
||||
{
|
||||
EXTI->PR = EXTI_PR_PR0;
|
||||
EXTI->IMR &= ~EXTI_IMR_MR0;
|
||||
}
|
||||
|
||||
void
|
||||
cir_ext_enable (void)
|
||||
{
|
||||
EXTI->IMR |= EXTI_IMR_MR0;
|
||||
}
|
||||
|
||||
extern void cir_ext_interrupt (void);
|
||||
extern void cir_timer_interrupt (void);
|
||||
|
||||
CH_IRQ_HANDLER (EXTI0_IRQHandler)
|
||||
{
|
||||
CH_IRQ_PROLOGUE ();
|
||||
chSysLockFromIsr ();
|
||||
|
||||
cir_ext_interrupt ();
|
||||
|
||||
chSysUnlockFromIsr ();
|
||||
CH_IRQ_EPILOGUE ();
|
||||
}
|
||||
|
||||
CH_IRQ_HANDLER (TIM3_IRQHandler)
|
||||
{
|
||||
CH_IRQ_PROLOGUE();
|
||||
chSysLockFromIsr();
|
||||
|
||||
cir_timer_interrupt ();
|
||||
|
||||
chSysUnlockFromIsr();
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||
void
|
||||
dial_sw_disable (void)
|
||||
{
|
||||
EXTI->PR = EXTI_PR_PR2;
|
||||
EXTI->IMR &= ~EXTI_IMR_MR2;
|
||||
}
|
||||
|
||||
void
|
||||
dial_sw_enable (void)
|
||||
{
|
||||
EXTI->IMR |= EXTI_IMR_MR2;
|
||||
}
|
||||
|
||||
extern void dial_sw_interrupt (void);
|
||||
|
||||
CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
||||
{
|
||||
CH_IRQ_PROLOGUE ();
|
||||
chSysLockFromIsr ();
|
||||
|
||||
dial_sw_interrupt ();
|
||||
|
||||
chSysUnlockFromIsr ();
|
||||
CH_IRQ_EPILOGUE ();
|
||||
}
|
||||
#endif
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS/RT.
|
||||
|
||||
ChibiOS/RT is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS/RT is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
---
|
||||
|
||||
A special exception to the GPL can be applied should you wish to distribute
|
||||
a combined work that includes ChibiOS/RT, without being obliged to provide
|
||||
the source code for any proprietary components. See the file exception.txt
|
||||
for full details of how and when the exception can be applied.
|
||||
*/
|
||||
|
||||
#ifndef _BOARD_H_
|
||||
#define _BOARD_H_
|
||||
|
||||
#include "config.h"
|
||||
/*
|
||||
* Setup for the STBee Mini board.
|
||||
*/
|
||||
#define SET_USB_CONDITION(en) (en) /* To connect USB, call palSetPad */
|
||||
#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */
|
||||
#define GPIO_USB GPIOA_USB_ENABLE
|
||||
#define IOPORT_USB GPIOA
|
||||
#define GPIO_LED GPIOA_LED1
|
||||
#define IOPORT_LED GPIOA
|
||||
|
||||
#define NEUG_ADC_SETTING2_SMPR1 0
|
||||
#define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5) \
|
||||
| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5)
|
||||
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1) \
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2)
|
||||
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
|
||||
|
||||
/*
|
||||
* Board identifier.
|
||||
*/
|
||||
#define BOARD_STBEE_MINI
|
||||
#define BOARD_NAME "STBee Mini"
|
||||
|
||||
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
|
||||
#define HAVE_7SEGLED 1
|
||||
/*
|
||||
* Timer assignment for CIR
|
||||
*/
|
||||
#define TIMx TIM3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Board frequencies.
|
||||
*/
|
||||
#define STM32_LSECLK 32768
|
||||
#define STM32_HSECLK 12000000
|
||||
|
||||
/*
|
||||
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
|
||||
* native STM32 HAL.
|
||||
*/
|
||||
#define STM32F10X_MD
|
||||
|
||||
/*
|
||||
* IO pins assignments.
|
||||
*/
|
||||
#define GPIOA_LED1 13
|
||||
#define GPIOA_USB_ENABLE 14
|
||||
#define GPIOA_LED2 15
|
||||
|
||||
#define GPIOC_BUTTON 13
|
||||
|
||||
/*
|
||||
* I/O ports initial setup, this configuration is established soon after reset
|
||||
* in the initialization code.
|
||||
*
|
||||
* The digits have the following meaning:
|
||||
* 0 - Analog input.
|
||||
* 1 - Push Pull output 10MHz.
|
||||
* 2 - Push Pull output 2MHz.
|
||||
* 3 - Push Pull output 50MHz.
|
||||
* 4 - Digital input.
|
||||
* 5 - Open Drain output 10MHz.
|
||||
* 6 - Open Drain output 2MHz.
|
||||
* 7 - Open Drain output 50MHz.
|
||||
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
|
||||
* 9 - Alternate Push Pull output 10MHz.
|
||||
* A - Alternate Push Pull output 2MHz.
|
||||
* B - Alternate Push Pull output 50MHz.
|
||||
* C - Reserved.
|
||||
* D - Alternate Open Drain output 10MHz.
|
||||
* E - Alternate Open Drain output 2MHz.
|
||||
* F - Alternate Open Drain output 50MHz.
|
||||
* Please refer to the STM32 Reference Manual for details.
|
||||
*/
|
||||
|
||||
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
|
||||
/*
|
||||
* Port A setup.
|
||||
* PA1 - Digital input with PullUp. AN1 for NeuG
|
||||
* PA2 - Digital input with PullUp. AN2 for NeuG
|
||||
* PA6 - (TIM3_CH1) input with pull-up
|
||||
* PA7 - (TIM3_CH2) input with pull-down
|
||||
* PA11 - input with pull-up (USBDM)
|
||||
* PA12 - input with pull-up (USBDP)
|
||||
* Everything input with pull-up except:
|
||||
* PA13 - Open Drain output (LED1 0:ON 1:OFF)
|
||||
* PA14 - Push pull output (USB ENABLE 0:DISABLE 1:ENABLE)
|
||||
* PA15 - Open Drain output (LED2 0:ON 1:OFF)
|
||||
*/
|
||||
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
|
||||
#define VAL_GPIOACRH 0x63688888 /* PA15...PA8 */
|
||||
#define VAL_GPIOAODR 0xFFFFFF7F
|
||||
|
||||
/* Port B setup. */
|
||||
#define GPIOB_CIR 0
|
||||
#define GPIOB_BUTTON 2
|
||||
#define GPIOB_ROT_A 6
|
||||
#define GPIOB_ROT_B 7
|
||||
|
||||
#define GPIOB_7SEG_DP 15
|
||||
#define GPIOB_7SEG_A 14
|
||||
#define GPIOB_7SEG_B 13
|
||||
#define GPIOB_7SEG_C 12
|
||||
#define GPIOB_7SEG_D 11
|
||||
#define GPIOB_7SEG_E 10
|
||||
#define GPIOB_7SEG_F 9
|
||||
#define GPIOB_7SEG_G 8
|
||||
|
||||
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
|
||||
#define VAL_GPIOBCRH 0x66666666 /* PB15...PB8 */
|
||||
#define VAL_GPIOBODR 0xFFFFFFFF
|
||||
#else
|
||||
/*
|
||||
* Port A setup.
|
||||
* PA1 - Digital input with PullUp. AN1 for NeuG
|
||||
* PA2 - Digital input with PullUp. AN2 for NeuG
|
||||
* PA11 - input with pull-up (USBDM)
|
||||
* PA12 - input with pull-up (USBDP)
|
||||
* Everything input with pull-up except:
|
||||
* PA13 - Open Drain output (LED1 0:ON 1:OFF)
|
||||
* PA14 - Push pull output (USB ENABLE 0:DISABLE 1:ENABLE)
|
||||
* PA15 - Open Drain output (LED2 0:ON 1:OFF)
|
||||
*/
|
||||
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
|
||||
#define VAL_GPIOACRH 0x63688888 /* PA15...PA8 */
|
||||
#define VAL_GPIOAODR 0xFFFFFFFF
|
||||
|
||||
/* Port B setup. */
|
||||
/* Everything input with pull-up */
|
||||
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
|
||||
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
|
||||
#define VAL_GPIOBODR 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Port C setup.
|
||||
* Everything input with pull-up except:
|
||||
* PC13 - Normal input.
|
||||
* PC14 - Normal input.
|
||||
* PC15 - Normal input.
|
||||
*/
|
||||
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
|
||||
#define VAL_GPIOCCRH 0x44488888 /* PC15...PC8 */
|
||||
#define VAL_GPIOCODR 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* Port D setup.
|
||||
* Everything input with pull-up except:
|
||||
* PD0 - Normal input (XTAL).
|
||||
* PD1 - Normal input (XTAL).
|
||||
*/
|
||||
#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
|
||||
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
|
||||
#define VAL_GPIODODR 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* Port E setup.
|
||||
* Everything input with pull-up except:
|
||||
*/
|
||||
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
|
||||
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
|
||||
#define VAL_GPIOEODR 0xFFFFFFFF
|
||||
|
||||
#if !defined(_FROM_ASM_)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void boardInit(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FROM_ASM_ */
|
||||
|
||||
#endif /* _BOARD_H_ */
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
|
||||
#define STM32_PLLMUL_VALUE 6
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV2
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV1
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV6
|
||||
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
|
||||
|
||||
#include "mcuconf-common.h"
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: f344d926c1...fc26cf0889
@@ -1,8 +1,8 @@
|
||||
==========================
|
||||
GnuPG settings for GNOME 3
|
||||
==========================
|
||||
===========================================
|
||||
GnuPG settings for GNOME 3.1x and GNOME 3.0
|
||||
===========================================
|
||||
|
||||
In the article `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
|
||||
In the section `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
|
||||
|
||||
It was for GNOME 2. The old days was good, we just disabled GNOME-keyrings
|
||||
interference to SSH and customizing our desktop was easy for GNU and UNIX users.
|
||||
@@ -10,29 +10,33 @@ interference to SSH and customizing our desktop was easy for GNU and UNIX users.
|
||||
.. _GnuPG settings: gpg-settings
|
||||
|
||||
|
||||
GNOME keyrings in GNOME 3
|
||||
=========================
|
||||
GNOME keyrings in GNOME 3.1x
|
||||
============================
|
||||
|
||||
It seems that it is more integrated into the desktop.
|
||||
It is difficult to kill it. It would be possible to kill it simply,
|
||||
but then, I can't use, say, wi-fi access (which needs to access "secrets")
|
||||
any more.
|
||||
In the files /etc/xdg/autostart/gnome-keyring-ssh.desktop
|
||||
and /etc/xdg/autostart/gnome-keyring-gpg.desktop,
|
||||
we have a line something like: ::
|
||||
|
||||
We can't use GNOME configuration tool to disable interference by
|
||||
GNOME keyrings any more. It seems that desktop should not have
|
||||
customization these days.
|
||||
OnlyShowIn=GNOME;Unity;MATE;
|
||||
|
||||
Please edit this line to: ::
|
||||
|
||||
OnlyShowIn=
|
||||
|
||||
Then, no desktop environment invokes gnome-keyring for ssh and gpg. I think that it is The Right Thing.
|
||||
|
||||
|
||||
GNOME-SESSION-PROPERTIES
|
||||
========================
|
||||
GNOME keyrings in GNOME 3.0 by GNOME-SESSION-PROPERTIES
|
||||
=======================================================
|
||||
|
||||
After struggling some hours, I figured out it is GNOME-SESSION-PROPERTIES
|
||||
to disable the interference. Invoking::
|
||||
We can't use GNOME configuration tool (like GNOME 2) to disable interference by
|
||||
GNOME keyrings in GNOME 3.0.
|
||||
|
||||
It is GNOME-SESSION-PROPERTIES to disable the interference. Invoking::
|
||||
|
||||
$ gnome-session-properties
|
||||
|
||||
and at the tab of "Startup Programs", I removed radio check buttons
|
||||
for "GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
|
||||
Now, I use gpg-agent for GnuPG Agent and SSH agent with Gnuk Token.
|
||||
Then, I can use proper gpg-agent for GnuPG Agent Service and SSH Agent Service with Gnuk Token in GNOME 3.0.
|
||||
|
||||
@@ -5,174 +5,14 @@ Key import from PC to Gnuk Token (no removal)
|
||||
This document describes how I put my **keys on PC** to the Token
|
||||
without removing keys from PC.
|
||||
|
||||
The difference is just not-to-save changes after key imports.
|
||||
The difference is only the last step.
|
||||
I don't save changes on PC after keytocard.
|
||||
|
||||
After personalization, I put my keys into the Token.
|
||||
For the steps before the last step, please see `keytocard with removing keys on PC`_.
|
||||
|
||||
Here is the log.
|
||||
.. _keytocard removing keys: gnuk-keytocard
|
||||
|
||||
I invoke GnuPG with my key (4ca7babe) and with ``--homedir`` option
|
||||
to specify the directory which contains my secret keys. ::
|
||||
|
||||
$ gpg --homedir=/home/gniibe/tmp/gnuk-testing-dir --edit-key 4ca7babe
|
||||
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
|
||||
Secret key is available.
|
||||
|
||||
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
|
||||
trust: ultimate validity: ultimate
|
||||
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
|
||||
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
|
||||
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
|
||||
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``.
|
||||
To enable ``keytocard`` command, I type ``toggle`` command. ::
|
||||
|
||||
gpg> toggle
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
Firstly, I import my primary key into Gnuk Token.
|
||||
I type ``keytocard`` command, answer ``y`` to confirm keyimport,
|
||||
and type ``1`` to say it's signature key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Really move the primary key? (y/N) y
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(1) Signature key
|
||||
(3) Authentication key
|
||||
Your selection? 1
|
||||
|
||||
Then, GnuPG asks two passwords. One is the passphrase of **keys on PC**
|
||||
and another is the password of **Gnuk Token**. Note that the password of
|
||||
the token and the password of the keys on PC are different things,
|
||||
although they can be same.
|
||||
|
||||
Here, I assume that Gnuk Token's admin password of factory setting (12345678).
|
||||
|
||||
I enter these passwords. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
gpg: 3 Admin PIN attempts remaining before card is permanently locked
|
||||
|
||||
Please enter the Admin PIN
|
||||
Enter Admin PIN: 12345678
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The primary key is now on the Token and GnuPG says its card-no (F517 00000001),
|
||||
where F517 is the vendor ID of FSIJ.
|
||||
|
||||
Secondly, I import my subkey of encryption. I select key number '1'. ::
|
||||
|
||||
gpg> key 1
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
You can see that the subkey is marked by '*'.
|
||||
I type ``keytocard`` command to import this subkey to Gnuk Token.
|
||||
I select ``2`` as it's encryption key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(2) Encryption key
|
||||
Your selection? 2
|
||||
|
||||
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 084239CF, created 2010-10-15
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The sub key is now on the Token and GnuPG says its card-no for it.
|
||||
|
||||
I type ``key 1`` to deselect key number '1'. ::
|
||||
|
||||
gpg> key 1
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
Thirdly, I select sub key of authentication which has key number '2'. ::
|
||||
|
||||
gpg> key 2
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
You can see that the subkey number '2' is marked by '*'.
|
||||
I type ``keytocard`` command to import this subkey to Gnuk Token.
|
||||
I select ``3`` as it's authentication key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(3) Authentication key
|
||||
Your selection? 3
|
||||
|
||||
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 5BB065DC, created 2010-10-22
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
card-no: F517 00000001
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The sub key is now on the Token and GnuPG says its card-no for it.
|
||||
Here is the session log of the last step.
|
||||
|
||||
Lastly, I quit GnuPG. Note that I **don't** save changes. ::
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ See `another document`_ to import keys to the Token from copied directory.
|
||||
|
||||
After personalization, I put my keys into the Token.
|
||||
|
||||
Here is the log.
|
||||
Here is the session log.
|
||||
|
||||
I invoke GnuPG with my key (4ca7babe). ::
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ For GnuPG 2.0.x, gpg-agent is always used, so there is no need to specify the ``
|
||||
Let gpg-agent manage SSH key
|
||||
============================
|
||||
|
||||
I deactivate seahose-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
|
||||
I deactivate seahorse-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ KEYPTR
|
||||
----> [ P ][ Q ][ N ]
|
||||
<---encrypted----><--- plain ---->
|
||||
|
||||
key_addr 4-byte
|
||||
initial_vector (random) 16-byte
|
||||
checksum_encrypted 16-byte
|
||||
dek_encrypted_by_keystring_pw1 16-byte
|
||||
|
||||
@@ -48,9 +48,9 @@ I have three keys in my token.
|
||||
With the script below, I extract public key of the keygrip
|
||||
5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin::
|
||||
|
||||
$ ./get_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
||||
$ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
||||
|
||||
Here is the script, get_public_key.py::
|
||||
Here is the script, get_raw_public_key.py::
|
||||
|
||||
#! /usr/bin/python
|
||||
|
||||
|
||||
398
misc/t-eddsa.c
Normal file
398
misc/t-eddsa.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* t-eddsa.c - testing EdDSA
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* Run following commands. The file t-ed25519.inp is available in GNU
|
||||
* libgcrypt source code under 'tests' directory.
|
||||
|
||||
gcc -Wall -c ecc-edwards.c
|
||||
gcc -Wall -c -DBN256_NO_RANDOM -DBN256_C_IMPLEMENTATION bn.c
|
||||
gcc -Wall -c mod.c
|
||||
gcc -Wall -c -DBN256_C_IMPLEMENTATION mod25638.c
|
||||
gcc -Wall -c sha512.c
|
||||
gcc -Wall -c t-eddsa.c
|
||||
gcc -o t-eddsa t-eddsa.o ecc-edwards.o bn.o mod.o mod25638.o sha512.o
|
||||
./t-eddsa < ./t-ed25519.inp
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
#include "sha512.h"
|
||||
|
||||
static void
|
||||
print_le_bn256 (const bn256 *X)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *p = (const uint8_t *)X;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
printf ("%02x", p[i]);
|
||||
puts ("");
|
||||
}
|
||||
|
||||
static void
|
||||
print_be_bn256 (const bn256 *X)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->word[i]);
|
||||
puts ("");
|
||||
}
|
||||
|
||||
#define MAXLINE 4096
|
||||
|
||||
static int lineno;
|
||||
static int test_no;
|
||||
static bn256 sk[1];
|
||||
static bn256 pk[1];
|
||||
static unsigned char msg[MAXLINE];
|
||||
static size_t msglen;
|
||||
static bn512 sig[1];
|
||||
|
||||
static const char *
|
||||
skip_white_space (const char *l)
|
||||
{
|
||||
while (*l != '\n' && isspace (*l))
|
||||
l++;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_hex_4bit (char c)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
r = c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
r = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
r = c - 'A' + 10;
|
||||
else
|
||||
r = -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
read_hex_8bit (const char **l_p)
|
||||
{
|
||||
const char *l = *l_p;
|
||||
int r, v;
|
||||
|
||||
r = read_hex_4bit (*l++);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
v = r*16;
|
||||
r = read_hex_4bit (*l++);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
v += r;
|
||||
|
||||
*l_p = l;
|
||||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
read_msg (unsigned char *msg, const char *l, int len)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
r = read_hex_8bit (&l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
msg[i] = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_le_bn256 (bn256 *sk, const char *l)
|
||||
{
|
||||
int i;
|
||||
uint8_t *p = (uint8_t *)sk;
|
||||
|
||||
for (i = 0; i < sizeof (bn256); i++)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (*l == '\n')
|
||||
{
|
||||
/* should support small input??? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = read_hex_8bit (&l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
p[i] = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
read_be_bn256 (bn256 *sk, const char *l)
|
||||
{
|
||||
int i;
|
||||
uint8_t *p = (uint8_t *)sk;
|
||||
|
||||
for (i = 0; i < sizeof (bn256); i++)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (*l == '\n')
|
||||
{
|
||||
/* should support small input??? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = read_hex_8bit (&l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
p[31 - i] = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_pk (bn256 *pk, const char *l, int len)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (len == 64) /* 64 chars == 32-byte */
|
||||
{ /* compressed form */
|
||||
r = read_le_bn256 (pk, l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256 x[1];
|
||||
|
||||
r = read_hex_8bit (&l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
if (r != 4)
|
||||
return -1;
|
||||
|
||||
r = read_be_bn256 (x, l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
r = read_be_bn256 (pk, l+64);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
pk->word[7] ^= (x->word[0] & 1) * 0x80000000;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_le_bn512 (bn512 *sig, const char *l)
|
||||
{
|
||||
int i;
|
||||
uint8_t *p = (uint8_t *)sig;
|
||||
|
||||
for (i = 0; i < sizeof (bn512); i++)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (*l == '\n')
|
||||
{
|
||||
/* should support small input??? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = read_hex_8bit (&l);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
p[i] = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
read_testcase (void)
|
||||
{
|
||||
ssize_t r;
|
||||
size_t len = 0;
|
||||
char *line = NULL;
|
||||
int start = 0;
|
||||
int err = 0;
|
||||
|
||||
test_no = 0;
|
||||
memset (sk, 0, sizeof (bn256));
|
||||
memset (pk, 0, sizeof (ac));
|
||||
msglen = 0;
|
||||
memset (sig, 0, sizeof (bn512));
|
||||
|
||||
while (1)
|
||||
{
|
||||
lineno++;
|
||||
r = getline (&line, &len, stdin);
|
||||
if (r < 0)
|
||||
{
|
||||
/* EOF */
|
||||
if (!start)
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
len = r; /* We don't need allocated size, but length. */
|
||||
if (len >= MAXLINE)
|
||||
{
|
||||
fprintf (stderr, "Line too long: %d: >= %d\n", lineno, MAXLINE);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r == 1 && *line == '\n')
|
||||
{
|
||||
if (start)
|
||||
break; /* Done. */
|
||||
else
|
||||
continue; /* Ignore blank line before start. */
|
||||
}
|
||||
|
||||
if (r > 0 && *line == '#') /* Ignore comment line. */
|
||||
continue;
|
||||
|
||||
start = 1;
|
||||
if (r > 4 && strncmp (line, "TST:", 4) == 0)
|
||||
test_no = strtol (line+4, NULL, 10);
|
||||
else if (r > 3 && strncmp (line, "SK:", 3) == 0)
|
||||
{
|
||||
const char *l = skip_white_space (line+3);
|
||||
if (read_le_bn256 (sk, l) < 0)
|
||||
{
|
||||
fprintf (stderr, "read_le_bn256: %d\n", lineno);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (r > 3 && strncmp (line, "PK:", 3) == 0)
|
||||
{
|
||||
const char *l = skip_white_space (line+3);
|
||||
if (read_pk (pk, l, line+len-1-l) < 0)
|
||||
{
|
||||
fprintf (stderr, "read_pk: %d\n", lineno);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (r > 4 && strncmp (line, "MSG:", 4) == 0)
|
||||
{
|
||||
const char *l = skip_white_space (line+4);
|
||||
msglen = (line+len-1-l)/2;
|
||||
if (read_msg (msg, l, msglen) < 0)
|
||||
{
|
||||
fprintf (stderr, "read_msg: %d\n", lineno);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (r > 4 && strncmp (line, "SIG:", 4) == 0)
|
||||
{
|
||||
const char *l = skip_white_space (line+4);
|
||||
if (read_le_bn512 (sig, l) < 0)
|
||||
{
|
||||
fprintf (stderr, "read_le_bn512: %d\n", lineno);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Garbage line: %d", lineno);
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (line);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int all_good = 1;
|
||||
int r;
|
||||
bn256 pk_calculated[1];
|
||||
uint8_t hash[64];
|
||||
bn256 a[1];
|
||||
bn256 *R, *S;
|
||||
uint8_t out[64];
|
||||
|
||||
extern void eddsa_sign_25519 (const uint8_t *input, size_t ilen,
|
||||
uint8_t *output,
|
||||
const bn256 *a, const uint8_t *seed,
|
||||
const bn256 *pk);
|
||||
extern void eddsa_public_key_25519 (bn256 *pk, const bn256 *a);
|
||||
|
||||
R = (bn256 *)out;
|
||||
S = (bn256 *)(out+32);
|
||||
|
||||
while (1)
|
||||
{
|
||||
r = read_testcase ();
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
sha512 ((uint8_t *)sk, sizeof (bn256), hash);
|
||||
hash[0] &= 248;
|
||||
hash[31] &= 127;
|
||||
hash[31] |= 64;
|
||||
memcpy (a, hash, sizeof (bn256)); /* Lower half of hash */
|
||||
|
||||
eddsa_public_key_25519 (pk_calculated, a);
|
||||
if (memcmp (pk, pk_calculated, sizeof (bn256)) != 0)
|
||||
{
|
||||
printf ("ERR PK: %d\n", test_no);
|
||||
print_be_bn256 (sk);
|
||||
print_be_bn256 (pk);
|
||||
print_be_bn256 (pk_calculated);
|
||||
all_good = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
eddsa_sign_25519 (msg, msglen, out, a, hash+32, pk);
|
||||
if (memcmp (sig, R, sizeof (bn256)) != 0
|
||||
|| memcmp (((const uint8_t *)sig)+32, S, sizeof (bn256)) != 0)
|
||||
{
|
||||
printf ("ERR SIG: %d\n", test_no);
|
||||
print_le_bn256 (R);
|
||||
print_le_bn256 (S);
|
||||
print_le_bn256 ((const bn256 *)sig);
|
||||
print_le_bn256 ((const bn256 *)(((const uint8_t *)sig)+32));
|
||||
all_good = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf ("%d\n", test_no);
|
||||
}
|
||||
return all_good == 1?0:1;
|
||||
}
|
||||
@@ -1545,7 +1545,8 @@ 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 > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
|
||||
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
|
||||
size_t wbits, one = 1;
|
||||
size_t nblimbs;
|
||||
|
||||
@@ -671,14 +671,14 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
|
||||
size_t ilen, pad_count = 0;
|
||||
unsigned char *p, *q;
|
||||
unsigned char bt;
|
||||
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
|
||||
unsigned char buf[ctx->len];
|
||||
|
||||
if( ctx->padding != RSA_PKCS_V15 )
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
ilen = ctx->len;
|
||||
|
||||
if( ilen < 16 || ilen > sizeof( buf ) )
|
||||
if( ilen < 16)
|
||||
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
ret = ( mode == RSA_PUBLIC )
|
||||
|
||||
@@ -15,6 +15,7 @@ CSRC = main.c usb_stm32f103.c adc_stm32f103.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 sha512.c \
|
||||
random.c neug.c sha256.c sys.c
|
||||
|
||||
INCDIR =
|
||||
@@ -54,7 +55,7 @@ OBJCOPY = $(CROSS)objcopy
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
# DEFS: Add
|
||||
DEFS = -DCHX_PRIO_MAIN=5 -DRSA_AUTH -DRSA_SIG @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
DEFS = @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
@@ -67,6 +68,8 @@ board.h:
|
||||
|
||||
sys.c: board.h
|
||||
|
||||
build/bignum.o: OPT = -O3 -g
|
||||
|
||||
distclean: clean
|
||||
-rm -f gnuk.ld config.h board.h Makefile \
|
||||
usb-strings.c.inc usb-vid-pid-ver.c.inc
|
||||
|
||||
8
src/affine.h
Normal file
8
src/affine.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @brief Affine coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
} ac;
|
||||
33
src/bn.c
33
src/bn.c
@@ -23,13 +23,16 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#ifndef BN256_NO_RANDOM
|
||||
#include "random.h"
|
||||
#endif
|
||||
#include "bn.h"
|
||||
|
||||
uint32_t
|
||||
bn256_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int i;
|
||||
uint32_t v;
|
||||
uint32_t carry = 0;
|
||||
uint32_t *px;
|
||||
const uint32_t *pa, *pb;
|
||||
@@ -40,10 +43,11 @@ bn256_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
v = *pb;
|
||||
*px = *pa + carry;
|
||||
carry = (*px < carry);
|
||||
*px += *pb;
|
||||
carry += (*px < *pb);
|
||||
*px += v;
|
||||
carry += (*px < v);
|
||||
px++;
|
||||
pa++;
|
||||
pb++;
|
||||
@@ -56,6 +60,7 @@ uint32_t
|
||||
bn256_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int i;
|
||||
uint32_t v;
|
||||
uint32_t borrow = 0;
|
||||
uint32_t *px;
|
||||
const uint32_t *pa, *pb;
|
||||
@@ -68,9 +73,10 @@ bn256_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow0 = (*pa < borrow);
|
||||
|
||||
v = *pb;
|
||||
*px = *pa - borrow;
|
||||
borrow = (*px < *pb) + borrow0;
|
||||
*px -= *pb;
|
||||
borrow = (*px < v) + borrow0;
|
||||
*px -= v;
|
||||
px++;
|
||||
pa++;
|
||||
pb++;
|
||||
@@ -83,7 +89,7 @@ uint32_t
|
||||
bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
{
|
||||
int i;
|
||||
uint32_t carry = 0;
|
||||
uint32_t carry = w;
|
||||
uint32_t *px;
|
||||
const uint32_t *pa;
|
||||
|
||||
@@ -94,12 +100,6 @@ bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
{
|
||||
*px = *pa + carry;
|
||||
carry = (*px < carry);
|
||||
if (i == 0)
|
||||
{
|
||||
*px += w;
|
||||
carry += (*px < w);
|
||||
}
|
||||
|
||||
px++;
|
||||
pa++;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ uint32_t
|
||||
bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
{
|
||||
int i;
|
||||
uint32_t borrow = 0;
|
||||
uint32_t borrow = w;
|
||||
uint32_t *px;
|
||||
const uint32_t *pa;
|
||||
|
||||
@@ -123,14 +123,7 @@ bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
uint32_t borrow0 = (*pa < borrow);
|
||||
|
||||
*px = *pa - borrow;
|
||||
if (i == 0)
|
||||
{
|
||||
borrow = (*px < w) + borrow0;
|
||||
*px -= w;
|
||||
}
|
||||
else
|
||||
borrow = borrow0;
|
||||
|
||||
borrow = borrow0;
|
||||
px++;
|
||||
pa++;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
|
||||
*
|
||||
* Copyright (C) 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2013, 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,9 +23,10 @@
|
||||
|
||||
#include "field-group-select.h"
|
||||
|
||||
/* We are little endian. */
|
||||
/* We are little-endian in the computation, but the protocol is big-endian. */
|
||||
|
||||
#define ECDSA_BYTE_SIZE 32
|
||||
#define ECDH_BYTE_SIZE 32
|
||||
|
||||
int
|
||||
FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
|
||||
@@ -54,7 +55,7 @@ FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
FUNC(ecdsa_compute_public) (const uint8_t *key_data)
|
||||
FUNC(ecc_compute_public) (const uint8_t *key_data)
|
||||
{
|
||||
uint8_t *p0, *p, *p1;
|
||||
ac q[1];
|
||||
@@ -84,3 +85,42 @@ FUNC(ecdsa_compute_public) (const uint8_t *key_data)
|
||||
|
||||
return p0;
|
||||
}
|
||||
|
||||
int
|
||||
FUNC(ecdh_decrypt) (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data)
|
||||
{
|
||||
bn256 k[1];
|
||||
ac X[1], P[1];
|
||||
int i;
|
||||
uint8_t *p0;
|
||||
const uint8_t *p1;
|
||||
int r;
|
||||
|
||||
p0 = (uint8_t *)k;
|
||||
for (i = 0; i < ECDH_BYTE_SIZE; i++)
|
||||
p0[ECDH_BYTE_SIZE - i - 1] = key_data[i];
|
||||
|
||||
p1 = input+1; /* skip '04' */
|
||||
p0 = (uint8_t *)P->x;
|
||||
for (i = 0; i < ECDH_BYTE_SIZE; i++)
|
||||
p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
|
||||
p0 = (uint8_t *)P->y;
|
||||
for (i = 0; i < ECDH_BYTE_SIZE; i++)
|
||||
p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
|
||||
|
||||
r = FUNC(compute_kP) (X, k, P);
|
||||
if (r == 0)
|
||||
{
|
||||
p0 = output;
|
||||
p1 = (const uint8_t *)X->x;
|
||||
*p0++ = 4;
|
||||
for (i = 0; i < ECDH_BYTE_SIZE; i++)
|
||||
*p0++ = p1[ECDH_BYTE_SIZE - i - 1];
|
||||
p1 = (const uint8_t *)X->y;
|
||||
for (i = 0; i < ECDH_BYTE_SIZE; i++)
|
||||
*p0++ = p1[ECDH_BYTE_SIZE - i - 1];
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
#include "ec_p256k1.h"
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
#include "ec_p256r1.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -32,29 +33,25 @@
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
|
||||
/* 256 byte == 2048-bit */
|
||||
/* 128 byte == 1024-bit */
|
||||
|
||||
static rsa_context rsa_ctx;
|
||||
|
||||
int
|
||||
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
struct key_data *kd)
|
||||
struct key_data *kd, int pubkey_len)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int ret = 0;
|
||||
unsigned char temp[RSA_SIGNATURE_LENGTH];
|
||||
unsigned char temp[pubkey_len];
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
|
||||
|
||||
rsa_ctx.len = KEY_CONTENT_LEN;
|
||||
rsa_ctx.len = pubkey_len;
|
||||
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
|
||||
rsa_ctx.len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], pubkey_len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[pubkey_len / 2],
|
||||
pubkey_len / 2) );
|
||||
#if 0
|
||||
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
|
||||
#endif
|
||||
@@ -74,7 +71,7 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
ret = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, SIG_RSA_RAW,
|
||||
msg_len, raw_message, temp);
|
||||
memcpy (output, temp, RSA_SIGNATURE_LENGTH);
|
||||
memcpy (output, temp, pubkey_len);
|
||||
}
|
||||
|
||||
rsa_free (&rsa_ctx);
|
||||
@@ -86,7 +83,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU_size = RSA_SIGNATURE_LENGTH;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
@@ -123,14 +119,13 @@ modulus_calc (const uint8_t *p, int len)
|
||||
|
||||
int
|
||||
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
struct key_data *kd)
|
||||
struct key_data *kd, unsigned int *output_len_p)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int ret;
|
||||
unsigned int output_len;
|
||||
|
||||
DEBUG_INFO ("RSA decrypt:");
|
||||
DEBUG_WORD ((uint32_t)&output_len);
|
||||
DEBUG_WORD ((uint32_t)&ret);
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
|
||||
@@ -139,9 +134,8 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
DEBUG_WORD (msg_len);
|
||||
|
||||
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
|
||||
KEY_CONTENT_LEN / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], msg_len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[msg_len / 2], msg_len / 2) );
|
||||
#if 0
|
||||
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
|
||||
#endif
|
||||
@@ -158,7 +152,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
{
|
||||
DEBUG_INFO ("RSA decrypt ...");
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, &output_len, input,
|
||||
RSA_PRIVATE, output_len_p, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
}
|
||||
|
||||
@@ -171,7 +165,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU_size = output_len;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
@@ -179,14 +172,15 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
}
|
||||
|
||||
int
|
||||
rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
|
||||
rsa_verify (const uint8_t *pubkey, int pubkey_len,
|
||||
const uint8_t *hash, const uint8_t *sig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
rsa_ctx.len = KEY_CONTENT_LEN;
|
||||
rsa_ctx.len = pubkey_len;
|
||||
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN) );
|
||||
MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, pubkey_len) );
|
||||
|
||||
DEBUG_INFO ("RSA verify...");
|
||||
|
||||
@@ -212,14 +206,14 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
|
||||
|
||||
#ifdef KEYGEN_SUPPORT
|
||||
uint8_t *
|
||||
rsa_genkey (void)
|
||||
rsa_genkey (int pubkey_len)
|
||||
{
|
||||
int ret;
|
||||
uint8_t index = 0;
|
||||
uint8_t *p_q_modulus = (uint8_t *)malloc (KEY_CONTENT_LEN*2);
|
||||
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
|
||||
uint8_t *p = p_q_modulus;
|
||||
uint8_t *q = p_q_modulus + KEY_CONTENT_LEN/2;
|
||||
uint8_t *modulus = p_q_modulus + KEY_CONTENT_LEN;
|
||||
uint8_t *q = p_q_modulus + pubkey_len / 2;
|
||||
uint8_t *modulus = p_q_modulus + pubkey_len;
|
||||
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng);
|
||||
extern void neug_flush (void);
|
||||
@@ -231,8 +225,8 @@ rsa_genkey (void)
|
||||
prng_seed (random_gen, &index);
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index,
|
||||
KEY_CONTENT_LEN * 8, RSA_EXPONENT) );
|
||||
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
|
||||
RSA_EXPONENT) );
|
||||
if (ret != 0)
|
||||
{
|
||||
free (p_q_modulus);
|
||||
@@ -240,9 +234,9 @@ rsa_genkey (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, KEY_CONTENT_LEN/2) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, KEY_CONTENT_LEN/2) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, KEY_CONTENT_LEN) );
|
||||
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) );
|
||||
|
||||
cleanup:
|
||||
rsa_free (&rsa_ctx);
|
||||
|
||||
74
src/chconf.h
74
src/chconf.h
@@ -1,74 +0,0 @@
|
||||
/* ChibiOS/RT configuration file */
|
||||
|
||||
#ifndef _CHCONF_H_
|
||||
#define _CHCONF_H_
|
||||
|
||||
#include <config.h>
|
||||
#ifdef DFU_SUPPORT
|
||||
#define CORTEX_VTOR_INIT (0x00003000+0x00001000)
|
||||
#else
|
||||
#define CORTEX_VTOR_INIT 0x00001000
|
||||
#endif
|
||||
|
||||
#define CH_FREQUENCY 1000
|
||||
#define CH_TIME_QUANTUM 20
|
||||
#define CH_USE_NESTED_LOCKS FALSE
|
||||
#define CH_MEMCORE_SIZE 0 /* Whole RAM */
|
||||
#define CH_NO_IDLE_THREAD FALSE
|
||||
#define CH_OPTIMIZE_SPEED TRUE
|
||||
#define CH_USE_REGISTRY TRUE
|
||||
#define CH_USE_WAITEXIT TRUE
|
||||
#define CH_USE_SEMAPHORES TRUE
|
||||
#define CH_USE_SEMAPHORES_PRIORITY FALSE
|
||||
#define CH_USE_SEMSW FALSE
|
||||
#define CH_USE_MUTEXES TRUE
|
||||
#define CH_USE_CONDVARS TRUE
|
||||
#define CH_USE_CONDVARS_TIMEOUT TRUE
|
||||
#define CH_USE_EVENTS TRUE /* We use this! */
|
||||
#define CH_USE_EVENTS_TIMEOUT TRUE /* We use this! */
|
||||
#define CH_USE_MESSAGES FALSE
|
||||
#define CH_USE_MESSAGES_PRIORITY FALSE
|
||||
#define CH_USE_MAILBOXES FALSE
|
||||
#define CH_USE_QUEUES FALSE
|
||||
#define CH_USE_MEMCORE TRUE
|
||||
#define CH_USE_HEAP TRUE
|
||||
#define CH_USE_MALLOC_HEAP FALSE
|
||||
#define CH_USE_MEMPOOLS FALSE
|
||||
#define CH_USE_DYNAMIC TRUE
|
||||
|
||||
/* Debug options */
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
#define CH_DBG_ENABLE_TRACE FALSE
|
||||
#define CH_DBG_ENABLE_STACK_CHECK TRUE
|
||||
#define CH_DBG_FILL_THREADS FALSE
|
||||
#define CH_DBG_THREADS_PROFILING FALSE
|
||||
|
||||
#define THREAD_EXT_FIELDS \
|
||||
/* Add threads custom fields here.*/ \
|
||||
|
||||
#define THREAD_EXT_INIT(tp) { \
|
||||
/* Add threads initialization code here.*/ \
|
||||
}
|
||||
|
||||
#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \
|
||||
/* System halt code here.*/ \
|
||||
}
|
||||
|
||||
#define THREAD_EXT_EXIT(tp) { \
|
||||
/* Add threads finalization code here.*/ \
|
||||
}
|
||||
|
||||
#define IDLE_LOOP_HOOK() { \
|
||||
/* Idle loop code here.*/ \
|
||||
}
|
||||
|
||||
#define SYSTEM_TICK_EVENT_HOOK() { \
|
||||
/* System tick event code here.*/ \
|
||||
}
|
||||
|
||||
#define SYSTEM_HALT_HOOK() { \
|
||||
/* System halt code here.*/ \
|
||||
}
|
||||
|
||||
#endif /* _CHCONF_H_ */
|
||||
27
src/configure
vendored
27
src/configure
vendored
@@ -3,7 +3,8 @@
|
||||
#
|
||||
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
|
||||
#
|
||||
# Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
# 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
|
||||
@@ -22,7 +23,7 @@
|
||||
# Default settings
|
||||
help=no
|
||||
vidpid=none
|
||||
target=OLIMEX_STM32_H103
|
||||
target=FST_01
|
||||
verbose=no
|
||||
with_dfu=default
|
||||
debug=no
|
||||
@@ -65,13 +66,13 @@ for option; do
|
||||
--disable-keygen)
|
||||
keygen=no ;;
|
||||
--enable-sys1-compat)
|
||||
sys1_compat = yes ;;
|
||||
sys1_compat=yes ;;
|
||||
--disable-sys1-compat)
|
||||
sys1_compat = no ;;
|
||||
sys1_compat=no ;;
|
||||
--enable-hid-card-change)
|
||||
hid_card_change = yes ;;
|
||||
hid_card_change=yes ;;
|
||||
--disable-hid-card-change)
|
||||
hid_card_change = no ;;
|
||||
hid_card_change=no ;;
|
||||
--with-dfu)
|
||||
with_dfu=yes ;;
|
||||
--without-dfu)
|
||||
@@ -93,12 +94,14 @@ Defaults for the options are specified in brackets.
|
||||
Configuration:
|
||||
-h, --help display this help and exit [no]
|
||||
--vidpid=VID:PID specify vendor/product ID [<NONE>]
|
||||
--target=TARGET specify target [OLIMEX_STM32_H103]
|
||||
--target=TARGET specify target [FST_01]
|
||||
supported targets are:
|
||||
OLIMEX_STM32_H103
|
||||
STM8S_DISCOVERY
|
||||
FST_01
|
||||
FST_01_00
|
||||
OLIMEX_STM32_H103
|
||||
STBEE
|
||||
STBEE_MINI
|
||||
MAPLE_MINI
|
||||
FST_01_00 (unreleased version with 8MHz XTAL)
|
||||
--enable-debug debug with virtual COM port [no]
|
||||
--enable-pinpad=cir
|
||||
PIN entry support [no]
|
||||
@@ -169,6 +172,10 @@ fi
|
||||
|
||||
# --with-dfu option
|
||||
if test "$with_dfu" = "yes"; then
|
||||
if test "$target" = "FST_01" -o "$target" = "FST_01_00"; then
|
||||
echo "FST-01 doesn't have DFU loader, you should not enable this."
|
||||
exit 1
|
||||
fi
|
||||
echo "Configured for DFU"
|
||||
ORIGIN=0x08003000
|
||||
FLASH_SIZE=`expr $FLASH_SIZE - 12`
|
||||
|
||||
@@ -21,10 +21,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: we don't take advantage of the specific feature of this curve,
|
||||
* but use same method of computation as NIST P-256 curve. That's due
|
||||
* to some software patent(s).
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "modp256k1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
#include "mod.h"
|
||||
#include "ec_p256k1.h"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "modp256r1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
#include "mod.h"
|
||||
#include "ec_p256r1.h"
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* ecc-cdh.c - One-Pass Diffie-Hellman method implementation
|
||||
* C(1, 1, ECC CDH) for EC DH of OpenPGP ECC
|
||||
*
|
||||
* Copyright (C) 2013 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* References:
|
||||
*
|
||||
* [1] A. Jivsov, Elliptic Curve Cryptography (ECC) in OpenPGP, RFC 6637,
|
||||
* June 2012.
|
||||
*
|
||||
* [2] Suite B Implementer's Guide to NIST SP 800-56A, July 28, 2009.
|
||||
*
|
||||
*/
|
||||
|
||||
static const char param[] = {
|
||||
/**/
|
||||
curve_OID_len,
|
||||
curve_OID,
|
||||
public-key_alg_ID, /*ecdh*/
|
||||
0x03,
|
||||
0x01,
|
||||
KDF_hash_ID, /*sha256*/
|
||||
KEK_alg_ID, /*aes128*/
|
||||
"Anonymous Sender ",
|
||||
my_finger_print /*20-byte*/
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int
|
||||
ecdh (unsigned char *key,
|
||||
const unsigned char *key_encrypted, const ac *P,
|
||||
const naf4_257 *naf_d, const unsigned char *fp)
|
||||
{
|
||||
ac S[1];
|
||||
sha256_context ctx;
|
||||
unsigned char kek[32];
|
||||
unsigned char x[32];
|
||||
int i;
|
||||
const unsigned char *p;
|
||||
|
||||
compute_kP (S, naf_d, P); /* Get shared secret. */
|
||||
|
||||
/* Endian change from big to little. */
|
||||
p = (const unsigned char *)S->x;
|
||||
for (i = 0; i < 32; i++)
|
||||
x[31-i] = p[i];
|
||||
|
||||
/* kdf (kek, S, parameter) */
|
||||
sha256_start (&ctx);
|
||||
sha256_update (&ctx, "\x00\x00\x00\x01", 4);
|
||||
sha256_update (&ctx, x, size of x);
|
||||
sha256_update (&ctx, (const char *)param, size of param);
|
||||
sha256_finish (&ctx, kek);
|
||||
}
|
||||
960
src/ecc-edwards.c
Normal file
960
src/ecc-edwards.c
Normal file
@@ -0,0 +1,960 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* 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
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "mod.h"
|
||||
#include "mod25638.h"
|
||||
#include "sha512.h"
|
||||
|
||||
/*
|
||||
* References:
|
||||
*
|
||||
* [1] Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin Yang.
|
||||
* High-speed high-security signatures.
|
||||
* Journal of Cryptographic Engineering 2 (2012), 77--89.
|
||||
* http://cr.yp.to/papers.html#ed25519
|
||||
*
|
||||
* [2] Daniel J. Bernstein, Peter Birkner, Marc Joye, Tanja Lange,
|
||||
* Christiane Peters.
|
||||
* Twisted Edwards curves.
|
||||
* Pages 389--405 in Progress in cryptology---AFRICACRYPT 2008.
|
||||
* http://cr.yp.to/papers.html#twisted
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPLEMENTATION NOTE
|
||||
*
|
||||
* (0) We assume that the processor has no cache, nor branch target
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* We don't avoid conditional jump if both cases have same timing,
|
||||
* either.
|
||||
*
|
||||
* (1) We use Radix-32 field arithmetic. It's a representation like
|
||||
* 2^256-38, but it's more redundant. For example, "1" can be
|
||||
* represented in three ways in 256-bit: 1, 2^255-18, and
|
||||
* 2^256-37.
|
||||
*
|
||||
* (2) We use fixed base comb multiplication. Scalar is 252-bit.
|
||||
* There are various possible choices for 252 = 2 * 2 * 3 * 3 * 7.
|
||||
* Current choice of total size is 3KB. We use three tables, and
|
||||
* a table has 16 points (3 * 1KB).
|
||||
*
|
||||
* Window size W = 4-bit, E = 21.
|
||||
* <--21-bit-
|
||||
* <---42-bit----------
|
||||
* [ ][########][////////][ ][########][////////]
|
||||
* <-------63-bit----------------
|
||||
* <-----------84-bit----------------------
|
||||
* <--------------105-bit----------------------------
|
||||
*
|
||||
* [ ][########][////////][ ][########][////////]
|
||||
* <-126-bit-
|
||||
* <-147-bit-
|
||||
* <----168-bit--------
|
||||
*
|
||||
* <-------189-bit---------------
|
||||
* <----------210-bit----------------------
|
||||
* <-------------231-bit-----------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Identity element: (0,1)
|
||||
* Negation: -(x,y) = (-x,y)
|
||||
*
|
||||
* d: -0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A
|
||||
* order:
|
||||
* 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED
|
||||
* Gx: 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A
|
||||
* Gy: 0x6666666666666666666666666666666666666666666666666666666666666658
|
||||
*/
|
||||
|
||||
/* d + 2^255 - 19 */
|
||||
static const bn256 coefficient_d[1] = {
|
||||
{{ 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d,
|
||||
0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee }} };
|
||||
|
||||
|
||||
/**
|
||||
* @brief Projective Twisted Coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
bn256 z[1];
|
||||
} ptc;
|
||||
|
||||
#include "affine.h"
|
||||
|
||||
|
||||
static int
|
||||
mod25519_is_neg (const bn256 *a)
|
||||
{
|
||||
return (a->word[0] & 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = 2 * A
|
||||
*
|
||||
* Compute (X3 : Y3 : Z3) = 2 * (X1 : Y1 : Z1)
|
||||
*/
|
||||
static void
|
||||
point_double (ptc *X, const ptc *A)
|
||||
{
|
||||
bn256 b[1], d[1], e[1];
|
||||
|
||||
/* Compute: B = (X1 + Y1)^2 */
|
||||
mod25638_add (b, A->x, A->y);
|
||||
mod25638_sqr (b, b);
|
||||
|
||||
/* Compute: C = X1^2 : E */
|
||||
mod25638_sqr (e, A->x);
|
||||
|
||||
/* Compute: D = Y1^2 */
|
||||
mod25638_sqr (d, A->y);
|
||||
|
||||
/* E = aC; where a = -1 */
|
||||
/* Compute: D - E = D + C : Y3_tmp */
|
||||
mod25638_add (X->y, e, d);
|
||||
|
||||
/* Compute: -F = -(E + D) = C - D; where a = -1 : E */
|
||||
mod25638_sub (e, e, d);
|
||||
|
||||
/* Compute: H = Z1^2 : D */
|
||||
mod25638_sqr (d, A->z);
|
||||
|
||||
/* Compute: -J = 2*H - F : D */
|
||||
mod25638_add (d, d, d);
|
||||
mod25638_add (d, d, e);
|
||||
|
||||
/* Compute: X3 = (B-C-D)*J = -J*(C+D-B) = -J*(Y3_tmp-B) */
|
||||
mod25638_sub (X->x, X->y, b);
|
||||
mod25638_mul (X->x, X->x, d);
|
||||
|
||||
/* Compute: Y3 = -F*(D-E) = -F*Y3_tmp */
|
||||
mod25638_mul (X->y, X->y, e);
|
||||
|
||||
/* Z3 = -F*-J */
|
||||
mod25638_mul (X->z, e, d);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = A + B
|
||||
*
|
||||
* @param X Destination PTC
|
||||
* @param A PTC
|
||||
* @param B AC
|
||||
*
|
||||
* Compute: (X3 : Y3 : Z3) = (X1 : Y1 : Z1) + (X2 : Y2 : 1)
|
||||
*/
|
||||
static void
|
||||
point_add (ptc *X, const ptc *A, const ac *B)
|
||||
{
|
||||
bn256 c[1], d[1], e[1], tmp[1];
|
||||
|
||||
/* Compute: C = X1 * X2 */
|
||||
mod25638_mul (c, A->x, B->x);
|
||||
|
||||
/* Compute: D = Y1 * Y2 */
|
||||
mod25638_mul (d, A->y, B->y);
|
||||
|
||||
/* Compute: E = d * C * D */
|
||||
mod25638_mul (e, c, d);
|
||||
mod25638_mul (e, coefficient_d, e);
|
||||
|
||||
/* Compute: C_1 = C + D */
|
||||
mod25638_add (c, c, d);
|
||||
|
||||
/* Compute: D_1 = Z1^2 : B */
|
||||
mod25638_sqr (d, A->z);
|
||||
|
||||
/* tmp = D_1 - E : F */
|
||||
mod25638_sub (tmp, d, e);
|
||||
|
||||
/* D_2 = D_1 + E : G */
|
||||
mod25638_add (d, d, e);
|
||||
|
||||
/* X3_final = Z1 * tmp * ((X1 + Y1) * (X2 + Y2) - C_1) */
|
||||
mod25638_add (X->x, A->x, A->y);
|
||||
mod25638_add (e, B->x, B->y);
|
||||
mod25638_mul (e, X->x, e);
|
||||
mod25638_sub (e, e, c);
|
||||
mod25638_mul (e, tmp, e);
|
||||
mod25638_mul (X->x, A->z, e);
|
||||
|
||||
/* Y3_final = Z1 * D_2 * C_1 */
|
||||
mod25638_mul (c, d, c);
|
||||
mod25638_mul (X->y, A->z, c);
|
||||
|
||||
/* Z3_final = tmp * D_2 */
|
||||
mod25638_mul (X->z, tmp, d);
|
||||
|
||||
/* A = Z1 */
|
||||
/* B = A^2 */
|
||||
/* C = X1 * X2 */
|
||||
/* D = Y1 * Y2 */
|
||||
/* E = d * C * D */
|
||||
/* F = B - E */
|
||||
/* G = B + E */
|
||||
/* X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) */
|
||||
/* Y3 = A * G * (D - aC); where a = -1 */
|
||||
/* Z3 = F * G */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = convert A
|
||||
*
|
||||
* @param X Destination AC
|
||||
* @param A PTC
|
||||
*
|
||||
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
|
||||
*/
|
||||
static void
|
||||
point_ptc_to_ac (ac *X, const ptc *A)
|
||||
{
|
||||
bn256 z_inv[1];
|
||||
|
||||
/*
|
||||
* A->z may be bigger than p25519, or two times bigger than p25519.
|
||||
* But this is no problem for computation of mod_inv.
|
||||
*/
|
||||
mod_inv (z_inv, A->z, p25519);
|
||||
|
||||
mod25638_mul (X->x, A->x, z_inv);
|
||||
mod25519_reduce (X->x);
|
||||
mod25638_mul (X->y, A->y, z_inv);
|
||||
mod25519_reduce (X->y);
|
||||
}
|
||||
|
||||
|
||||
static const ac precomputed_KG[16] = {
|
||||
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
|
||||
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
|
||||
{ {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
|
||||
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
|
||||
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
|
||||
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}} },
|
||||
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
|
||||
0xa815e038, 0xce0d0064, 0xbca90151, 0x041c030f }}},
|
||||
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
|
||||
0x655e5c16, 0xc67dc71c, 0xee43fb7a, 0x72467625 }}} },
|
||||
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
|
||||
0x6aeae260, 0x31f39299, 0x5f4a9bb2, 0x6d9e4545 }}},
|
||||
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
|
||||
0xa259dc8a, 0xaab95e0b, 0x99013cd0, 0x28bd5fc3 }}} },
|
||||
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
|
||||
0xda13ef4b, 0x4583ff4c, 0x95083f85, 0x1f13202c }}},
|
||||
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
|
||||
0xfdfd7ffa, 0xf21109e7, 0x6c381b7e, 0x66336d35 }}} },
|
||||
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
|
||||
0x1a52df87, 0x0de65625, 0xbd675870, 0x5f0dd494 }}},
|
||||
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
|
||||
0xa80e1eb6, 0x497e74bd, 0xe9365b15, 0x1648eaac }}} },
|
||||
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
|
||||
0xb34cf697, 0xb75832f4, 0x3a2bce94, 0x7aaf57c5 }}},
|
||||
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
|
||||
0x48742dd1, 0xaebd15dd, 0x55d38439, 0x6311bb16 }}} },
|
||||
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
|
||||
0x70611a3f, 0x91c1cd94, 0x8075dbcb, 0x1d0c34f6 }}},
|
||||
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
|
||||
0x46f167bb, 0x54b1992f, 0xb74a9944, 0x01a11f3c }}} },
|
||||
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
|
||||
0x2f6cc814, 0x359c5b5f, 0x7786383d, 0x7b6a5565 }}},
|
||||
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
|
||||
0xeddb8571, 0x61d526f6, 0x0eac739a, 0x0cb7acea }}} },
|
||||
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
|
||||
0x8397f958, 0x4870f214, 0x8a175fbb, 0x5aa0c67c }}},
|
||||
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
|
||||
0x7cbe4e3b, 0x87e293fa, 0xbda72395, 0x17040799 }}} },
|
||||
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
|
||||
0x2216fa67, 0x383a533a, 0x684d3925, 0x338bbe0a }}},
|
||||
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
|
||||
0x2e30380e, 0xa7c2e708, 0x9e4b3d62, 0x69f13e09 }}} },
|
||||
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
|
||||
0x9ebc7613, 0xb642f86a, 0xcb77c3b9, 0x5ce45e73 }}},
|
||||
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
|
||||
0xd8782345, 0x55c53916, 0xdb7b202a, 0x6b1dfa87 }}} },
|
||||
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
|
||||
0x3a6e8673, 0x0fcafd1d, 0x45d10f48, 0x0d264435 }}},
|
||||
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
|
||||
0xd2119aa4, 0x41d5b8eb, 0x8b09b6a5, 0x36bd9ab4 }}} },
|
||||
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
|
||||
0xa4730880, 0xefc0dd80, 0x4079fe2f, 0x40617e56 }}},
|
||||
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
|
||||
0xda13cdcb, 0xe315c425, 0x67ff5370, 0x37bc6e84 }}} },
|
||||
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
|
||||
0xf4085f62, 0x0f540498, 0x0db7bd1b, 0x6f0bb035 }}},
|
||||
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
|
||||
0x355facf6, 0x07f45010, 0x3a989a9c, 0x5cd416a9 }}} },
|
||||
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
|
||||
0x57aa0119, 0x44afdd5f, 0x430dc946, 0x05d68802 }}},
|
||||
{{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33,
|
||||
0x48c51347, 0x37520265, 0x00a21bfb, 0x6f4be0af }}} }
|
||||
};
|
||||
|
||||
static const ac precomputed_2E_KG[16] = {
|
||||
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
|
||||
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
|
||||
{ {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16,
|
||||
0xedd4d15f, 0xab1c92b8, 0x57d9eada, 0x482a4cdf }}},
|
||||
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
|
||||
0x14519298, 0x0b3c5fc6, 0x81c2f7a8, 0x7391de43 }}} },
|
||||
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
|
||||
0x63e7328e, 0x44c6e34f, 0xca63ab3e, 0x3f748617 }}},
|
||||
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
|
||||
0x1ba9acee, 0x3938a289, 0x420fc47b, 0x0fed89e6 }}} },
|
||||
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
|
||||
0x9d128c33, 0xda44186c, 0xbf98c24f, 0x54183ede }}},
|
||||
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
|
||||
0xb4ab035d, 0xb3fe651b, 0xa0b0d4e5, 0x426c99c3 }}} },
|
||||
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
|
||||
0x24240b15, 0x18795ff8, 0x9989ffcc, 0x13aea184 }}},
|
||||
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
|
||||
0x1b25e570, 0xfbddbff2, 0x8ca12b70, 0x0884949c }}} },
|
||||
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
|
||||
0xeb17ad71, 0xb6719dfb, 0xc0bc3517, 0x46871ad0 }}},
|
||||
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
|
||||
0x884785dc, 0xad295dd0, 0x74a1276a, 0x359debad }}} },
|
||||
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
|
||||
0x9c969001, 0xef4c051e, 0x02cb45f4, 0x0d4ea946 }}},
|
||||
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
|
||||
0x2b372386, 0x5c12fd04, 0xdbfee11f, 0x1aedbd3e }}} },
|
||||
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
|
||||
0xa17dc97e, 0xeea9bddf, 0x3350a2bd, 0x0d12fe3d }}},
|
||||
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
|
||||
0x3dbbf921, 0x75c63df4, 0x2958a5a6, 0x545b109c }}} },
|
||||
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
|
||||
0x5985dcbe, 0x57a69c0f, 0xeb87a534, 0x3c0c1e7b }}},
|
||||
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
|
||||
0x6e2f1973, 0x922c4554, 0xf1347631, 0x74e826b2 }}} },
|
||||
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
|
||||
0x2c874953, 0xe298a02e, 0x8932b73f, 0x225093ed }}},
|
||||
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
|
||||
0x85dba986, 0xdf41da94, 0xccee8edc, 0x36fe85e7 }}} },
|
||||
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
|
||||
0x6a966d2d, 0x8242aa25, 0x4cd36d32, 0x03500a94 }}},
|
||||
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
|
||||
0x06eab6b4, 0xd0030f92, 0x62c91d46, 0x2dc80d5f }}} },
|
||||
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
|
||||
0x8159db27, 0x4591b980, 0xd3d84740, 0x36c6533c }}},
|
||||
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
|
||||
0x71b9dc16, 0xbd306903, 0xf88f8d32, 0x7edd5a95 }}} },
|
||||
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
|
||||
0x02b56105, 0x67c9d9d0, 0x5971b456, 0x4d318012 }}},
|
||||
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
|
||||
0x00607ea0, 0x4dbeaa6f, 0x6959e688, 0x115c221d }}} },
|
||||
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
|
||||
0xc2e9d5f4, 0xefa699bb, 0x021da209, 0x2469e813 }}},
|
||||
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
|
||||
0x2fb3ec8f, 0xd21b75e4, 0xd72a7545, 0x10dd726a }}} },
|
||||
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
|
||||
0x44f1161f, 0xbda6f3ee, 0xf339efe5, 0x7680aebf }}},
|
||||
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
|
||||
0xa320c916, 0xd81ef6f2, 0x62a3b54d, 0x3e22a1fb }}} },
|
||||
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
|
||||
0xea49af98, 0xc0a880b9, 0xf2dfddd0, 0x53bf600b }}},
|
||||
{{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee,
|
||||
0x2b9f233c, 0xb17712ae, 0xd0eb909e, 0x71f0b344 }}} }
|
||||
};
|
||||
|
||||
static const ac precomputed_4E_KG[16] = {
|
||||
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
|
||||
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
|
||||
{ {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283,
|
||||
0xa9a6eb83, 0x2259174d, 0x45500054, 0x184b48cb }}},
|
||||
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
|
||||
0x2380ef73, 0xdd60c268, 0x03dc33a9, 0x3ee0e07a }}} },
|
||||
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
|
||||
0xecd898fb, 0xec57038c, 0xb663ed49, 0x2898ffaa }}},
|
||||
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
|
||||
0xb9934557, 0xe759d6bc, 0xab6c9477, 0x094f3b96 }}} },
|
||||
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
|
||||
0xda17203d, 0xa4850a2b, 0x77289e0f, 0x0062f7a7 }}},
|
||||
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
|
||||
0x475795f6, 0x9f38bda4, 0xdece4a4c, 0x560ed4b3 }}} },
|
||||
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
|
||||
0xdb08fe30, 0xd7a8d50d, 0xa2851109, 0x7efb45d3 }}},
|
||||
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
|
||||
0x9d71f8b7, 0x867091c6, 0x11a1bf56, 0x0fe1198b }}} },
|
||||
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
|
||||
0x0140502b, 0xad882043, 0x6ea1e46a, 0x34b5c0cb }}},
|
||||
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
|
||||
0xbd4801fb, 0x78b4d622, 0xcf18ae9a, 0x6cf4e146 }}} },
|
||||
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
|
||||
0x0205cf0e, 0x71908cc2, 0x32bcd754, 0x0cc15edd }}},
|
||||
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
|
||||
0x5e5a9312, 0xf22f64ef, 0x3c5e6155, 0x649b8859 }}} },
|
||||
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
|
||||
0x0df500ff, 0xe81faaa4, 0x6f50e615, 0x0792c79b }}},
|
||||
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
|
||||
0xc1d02d32, 0xdc57c526, 0x3c8aaa55, 0x5fb9a9a6 }}} },
|
||||
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
|
||||
0x446ac562, 0x1f8c510f, 0x2cc6b66e, 0x4676d381 }}},
|
||||
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
|
||||
0x457fa0eb, 0x051450a0, 0x744c57b1, 0x7d89e2b7 }}} },
|
||||
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
|
||||
0xf4d22d72, 0xd4c2f1a9, 0x4dc516b5, 0x73ecfdf1 }}},
|
||||
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
|
||||
0xa098cbb3, 0x9ba84f2e, 0xf9bdd37a, 0x1425aa8b }}} },
|
||||
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
|
||||
0xee26f5ff, 0x835dff85, 0xe509e1ea, 0x4927e622 }}},
|
||||
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
|
||||
0x682fd457, 0x9b87a676, 0x1a53145f, 0x75f382ff }}} },
|
||||
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
|
||||
0x9ccf2dc8, 0xf1c2b116, 0x808283d8, 0x7417e00f }}},
|
||||
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
|
||||
0x8f3d5d57, 0x231fc664, 0xe5853194, 0x38141a19 }}} },
|
||||
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
|
||||
0xe1dbdd65, 0x65d7f9b9, 0xf7c6698a, 0x7133424c }}},
|
||||
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
|
||||
0xb518e3eb, 0xa53e50e0, 0x98a40196, 0x2b4b9267 }}} },
|
||||
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
|
||||
0xcd2517af, 0x420cdef8, 0x0b695a8a, 0x513a307e }}},
|
||||
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
|
||||
0x973afe12, 0x8f3cbbea, 0x872f2538, 0x005c2350 }}} },
|
||||
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
|
||||
0x6e79d539, 0xc1f6d766, 0x795b5248, 0x34ec043f }}},
|
||||
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
|
||||
0x1666c1f1, 0xaeac7792, 0x66084bc0, 0x72426e97 }}} },
|
||||
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
|
||||
0x69e9b92b, 0xaf0984b4, 0x3ffe9093, 0x5fe6736f }}},
|
||||
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
|
||||
0x3c65a606, 0x94f893b1, 0x2d65496f, 0x2fee5e8c }}} }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief X = k * G
|
||||
*
|
||||
* @param K scalar k
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
static void
|
||||
compute_kG_25519 (ac *X, const bn256 *K)
|
||||
{
|
||||
ptc Q[1];
|
||||
int i;
|
||||
|
||||
/* identity element */
|
||||
memset (Q, 0, sizeof (ptc));
|
||||
Q->y->word[0] = 1;
|
||||
Q->z->word[0] = 1;
|
||||
|
||||
for (i = 20; i >= 0; i--)
|
||||
{
|
||||
int k0, k1, k2;
|
||||
|
||||
k0 = ((K->word[0] >> i) & 1)
|
||||
| (i < 1 ? ((K->word[1] >> 30) & 2)
|
||||
: (((K->word[2] >> (i-1)) & 1) << 1))
|
||||
| (i < 2 ? ((K->word[3] >> (i+28)) & 4)
|
||||
: (((K->word[4] >> (i-2)) & 1) << 2))
|
||||
| (i < 3 ? ((K->word[5] >> (i+26)) & 8)
|
||||
: (((K->word[6] >> (i-3)) & 1) << 3));
|
||||
|
||||
k1 = (i < 11 ? ((K->word[0] >> (i+21)) & 1)
|
||||
: ((K->word[1] >> (i-11)) & 1))
|
||||
| (i < 12 ? ((K->word[2] >> (i+19)) & 2)
|
||||
: (((K->word[3] >> (i-12)) & 1) << 1))
|
||||
| (i < 13 ? ((K->word[4] >> (i+17)) & 4)
|
||||
: (((K->word[5] >> (i-13)) & 1) << 2))
|
||||
| (i < 14 ? ((K->word[6] >> (i+15)) & 8)
|
||||
: (((K->word[7] >> (i-14)) & 1) << 3));
|
||||
|
||||
k2 = ((K->word[1] >> (i+10)) & 1)
|
||||
| ((K->word[3] >> (i+8)) & 2)
|
||||
| ((K->word[5] >> (i+6)) & 4)
|
||||
| ((K->word[7] >> (i+4)) & 8);
|
||||
|
||||
point_double (Q, Q);
|
||||
point_add (Q, Q, &precomputed_KG[k0]);
|
||||
point_add (Q, Q, &precomputed_2E_KG[k1]);
|
||||
point_add (Q, Q, &precomputed_4E_KG[k2]);
|
||||
}
|
||||
|
||||
point_ptc_to_ac (X, Q);
|
||||
}
|
||||
|
||||
|
||||
#define BN416_WORDS 13
|
||||
#define BN128_WORDS 4
|
||||
|
||||
/* M: The order of the generator G. */
|
||||
static const bn256 M[1] = {
|
||||
{{ 0x5CF5D3ED, 0x5812631A, 0xA2F79CD6, 0x14DEF9DE,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x10000000 }}
|
||||
};
|
||||
|
||||
#define C ((const uint32_t *)M)
|
||||
|
||||
static void
|
||||
bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size)
|
||||
{
|
||||
int i, j, k;
|
||||
int i_beg, i_end;
|
||||
uint32_t r0, r1, r2;
|
||||
|
||||
r0 = r1 = r2 = 0;
|
||||
for (k = 0; k <= q_size + BN128_WORDS - 2; k++)
|
||||
{
|
||||
if (q_size < BN128_WORDS)
|
||||
if (k < q_size)
|
||||
{
|
||||
i_beg = 0;
|
||||
i_end = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
i_beg = k - q_size + 1;
|
||||
i_end = k;
|
||||
if (i_end > BN128_WORDS - 1)
|
||||
i_end = BN128_WORDS - 1;
|
||||
}
|
||||
else
|
||||
if (k < BN128_WORDS)
|
||||
{
|
||||
i_beg = 0;
|
||||
i_end = k;
|
||||
}
|
||||
else
|
||||
{
|
||||
i_beg = k - BN128_WORDS + 1;
|
||||
i_end = k;
|
||||
if (i_end > q_size - 1)
|
||||
i_end = q_size - 1;
|
||||
}
|
||||
|
||||
for (i = i_beg; i <= i_end; i++)
|
||||
{
|
||||
uint64_t uv;
|
||||
uint32_t u, v;
|
||||
uint32_t carry;
|
||||
|
||||
j = k - i;
|
||||
if (q_size < BN128_WORDS)
|
||||
uv = ((uint64_t )q[j])*((uint64_t )C[i]);
|
||||
else
|
||||
uv = ((uint64_t )q[i])*((uint64_t )C[j]);
|
||||
v = uv;
|
||||
u = (uv >> 32);
|
||||
r0 += v;
|
||||
carry = (r0 < v);
|
||||
r1 += carry;
|
||||
carry = (r1 < carry);
|
||||
r1 += u;
|
||||
carry += (r1 < u);
|
||||
r2 += carry;
|
||||
}
|
||||
|
||||
r[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
r[k] = r0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief R = A mod M (using M=2^252+C) (Barret reduction)
|
||||
*
|
||||
* See HAC 14.47.
|
||||
*/
|
||||
static void
|
||||
mod_reduce_M (bn256 *R, const bn512 *A)
|
||||
{
|
||||
uint32_t q[BN256_WORDS+1];
|
||||
uint32_t tmp[BN416_WORDS];
|
||||
bn256 r[1];
|
||||
uint32_t carry, next_carry;
|
||||
int i;
|
||||
#define borrow carry
|
||||
|
||||
q[8] = A->word[15]>>28;
|
||||
carry = A->word[15] & 0x0fffffff;
|
||||
for (i = BN256_WORDS - 1; i >= 0; i--)
|
||||
{
|
||||
next_carry = A->word[i+7] & 0x0fffffff;
|
||||
q[i] = (A->word[i+7] >> 28) | (carry << 4);
|
||||
carry = next_carry;
|
||||
}
|
||||
memcpy (R, A, sizeof (bn256));
|
||||
R->word[7] &= 0x0fffffff;
|
||||
|
||||
/* Q_size: 9 */
|
||||
bnX_mul_C (tmp, q, 9); /* TMP = Q*C */
|
||||
/* Q = tmp / 2^252 */
|
||||
carry = tmp[12] & 0x0fffffff;
|
||||
for (i = 4; i >= 0; i--)
|
||||
{
|
||||
next_carry = tmp[i+7] & 0x0fffffff;
|
||||
q[i] = (tmp[i+7] >> 28) | (carry << 4);
|
||||
carry = next_carry;
|
||||
}
|
||||
/* R' = tmp % 2^252 */
|
||||
memcpy (r, tmp, sizeof (bn256));
|
||||
r->word[7] &= 0x0fffffff;
|
||||
/* R -= R' */
|
||||
borrow = bn256_sub (R, R, r);
|
||||
if (borrow)
|
||||
bn256_add (R, R, M);
|
||||
else
|
||||
bn256_add ((bn256 *)tmp, R, M);
|
||||
|
||||
/* Q_size: 5 */
|
||||
bnX_mul_C (tmp, q, 5); /* TMP = Q*C */
|
||||
carry = tmp[8] & 0x0fffffff;
|
||||
q[0] = (tmp[7] >> 28) | (carry << 4);
|
||||
/* R' = tmp % 2^252 */
|
||||
memcpy (r, tmp, sizeof (bn256));
|
||||
r->word[7] &= 0x0fffffff;
|
||||
/* R += R' */
|
||||
bn256_add (R, R, r);
|
||||
borrow = bn256_sub (R, R, M);
|
||||
if (borrow)
|
||||
bn256_add (R, R, M);
|
||||
else
|
||||
bn256_add ((bn256 *)tmp, R, M);
|
||||
|
||||
/* Q_size: 1 */
|
||||
bnX_mul_C (tmp, q, 1); /* TMP = Q*C */
|
||||
/* R' = tmp % 2^252 */
|
||||
memset (((uint8_t *)r)+(sizeof (uint32_t)*5), 0, sizeof (uint32_t)*3);
|
||||
memcpy (r, tmp, sizeof (uint32_t)*5);
|
||||
/* R -= R' */
|
||||
borrow = bn256_sub (R, R, r);
|
||||
if (borrow)
|
||||
bn256_add (R, R, M);
|
||||
else
|
||||
bn256_add ((bn256 *)tmp, R, M);
|
||||
#undef borrow
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
|
||||
const bn256 *a, const uint8_t *seed, const bn256 *pk)
|
||||
{
|
||||
bn256 *r, *s;
|
||||
sha512_context ctx;
|
||||
uint8_t hash[64];
|
||||
bn256 tmp[1];
|
||||
ac R[1];
|
||||
uint32_t carry, borrow;
|
||||
|
||||
r = (bn256 *)out;
|
||||
s = (bn256 *)(out+(32/4));
|
||||
|
||||
sha512_start (&ctx);
|
||||
sha512_update (&ctx, seed, sizeof (bn256)); /* It's upper half of the hash */
|
||||
sha512_update (&ctx, input, ilen);
|
||||
sha512_finish (&ctx, hash);
|
||||
|
||||
mod_reduce_M (r, (bn512 *)hash);
|
||||
compute_kG_25519 (R, r);
|
||||
|
||||
/* EdDSA encoding. */
|
||||
memcpy (tmp, R->y, sizeof (bn256));
|
||||
tmp->word[7] ^= mod25519_is_neg (R->x) * 0x80000000;
|
||||
|
||||
sha512_start (&ctx);
|
||||
sha512_update (&ctx, (uint8_t *)tmp, sizeof (bn256));
|
||||
sha512_update (&ctx, (uint8_t *)pk, sizeof (bn256));
|
||||
sha512_update (&ctx, input, ilen);
|
||||
sha512_finish (&ctx, (uint8_t *)hash);
|
||||
|
||||
mod_reduce_M (s, (bn512 *)hash);
|
||||
bn256_mul ((bn512 *)hash, s, a);
|
||||
mod_reduce_M (s, (bn512 *)hash);
|
||||
carry = bn256_add (s, s, r);
|
||||
borrow = bn256_sub (s, s, M);
|
||||
|
||||
memcpy (r, tmp, sizeof (bn256));
|
||||
|
||||
if ((borrow && !carry))
|
||||
bn256_add (s, s, M);
|
||||
else
|
||||
bn256_add (tmp, s, M);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
|
||||
{
|
||||
ac R[1];
|
||||
ptc X[1];
|
||||
bn256 a0[1];
|
||||
|
||||
bn256_shift (a0, a, -3);
|
||||
compute_kG_25519 (R, a0);
|
||||
memcpy (X, R, sizeof (ac));
|
||||
memset (X->z, 0, sizeof (bn256));
|
||||
X->z->word[0] = 1;
|
||||
point_double (X, X);
|
||||
point_double (X, X);
|
||||
point_double (X, X);
|
||||
point_ptc_to_ac (R, X);
|
||||
/* EdDSA encoding. */
|
||||
memcpy (pk, R->y, sizeof (bn256));
|
||||
pk->word[7] ^= mod25519_is_neg (R->x) * 0x80000000;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
eddsa_compute_public_25519 (const uint8_t *kd)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* check if P is on the curve.
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
static int
|
||||
point_is_on_the_curve (const ac *P)
|
||||
{
|
||||
bn256 s[1], t[1];
|
||||
|
||||
/* Twisted Edwards curve: a*x^2 + y^2 = 1 + d*x^2*y^2 */
|
||||
}
|
||||
|
||||
int
|
||||
compute_kP_25519 (ac *X, const bn256 *K, const ac *P);
|
||||
#endif
|
||||
|
||||
#ifdef PRINT_OUT_TABLE
|
||||
static const ptc G[1] = {{
|
||||
{{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
|
||||
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
|
||||
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
|
||||
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}},
|
||||
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}},
|
||||
}};
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef TESTING_EDDSA
|
||||
static void
|
||||
print_bn256 (const bn256 *X)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->word[i]);
|
||||
puts ("");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_point (const ac *X)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef PRINT_OUT_TABLE_AS_C
|
||||
fputs (" { {{{ ", stdout);
|
||||
for (i = 0; i < 4; i++)
|
||||
printf ("0x%08x, ", X->x->word[i]);
|
||||
fputs ("\n ", stdout);
|
||||
for (; i < 7; i++)
|
||||
printf ("0x%08x, ", X->x->word[i]);
|
||||
printf ("0x%08x }}},\n", X->x->word[i]);
|
||||
fputs (" {{{ ", stdout);
|
||||
for (i = 0; i < 4; i++)
|
||||
printf ("0x%08x, ", X->y->word[i]);
|
||||
fputs ("\n ", stdout);
|
||||
for (; i < 7; i++)
|
||||
printf ("0x%08x, ", X->y->word[i]);
|
||||
printf ("0x%08x }}} },\n", X->y->word[i]);
|
||||
#else
|
||||
puts ("--");
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->x->word[i]);
|
||||
puts ("");
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->y->word[i]);
|
||||
puts ("");
|
||||
puts ("--");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
print_point_ptc (const ptc *X)
|
||||
{
|
||||
int i;
|
||||
|
||||
puts ("---");
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->x->word[i]);
|
||||
puts ("");
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->y->word[i]);
|
||||
puts ("");
|
||||
for (i = 7; i >= 0; i--)
|
||||
printf ("%08x", X->z->word[i]);
|
||||
puts ("");
|
||||
puts ("---");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TESTING_EDDSA
|
||||
static void power_2 (ac *A, ptc *a, int N)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
ed_double_25638 (a, a);
|
||||
ptc_to_ac_25519 (A, a);
|
||||
}
|
||||
|
||||
static void print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000)
|
||||
{
|
||||
int i;
|
||||
ptc a[1];
|
||||
ac x[1];
|
||||
|
||||
for (i = 1; i < 16; i++)
|
||||
{
|
||||
/* A := Identity Element */
|
||||
memset (a, 0, sizeof (ptc));
|
||||
a->y->word[0] = 1;
|
||||
a->z->word[0] = 1;
|
||||
|
||||
if ((i & 1))
|
||||
ed_add_25638 (a, a, a0001);
|
||||
if ((i & 2))
|
||||
ed_add_25638 (a, a, a0010);
|
||||
if ((i & 4))
|
||||
ed_add_25638 (a, a, a0100);
|
||||
if ((i & 8))
|
||||
ed_add_25638 (a, a, a1000);
|
||||
|
||||
ptc_to_ac_25519 (x, a);
|
||||
print_point (x);
|
||||
}
|
||||
|
||||
fputs ("\n", stdout);
|
||||
}
|
||||
|
||||
static void compute_and_print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000)
|
||||
{
|
||||
ptc a[1];
|
||||
|
||||
memcpy (a, a0001, sizeof (ac));
|
||||
memset (a->z, 0, sizeof (bn256));
|
||||
a->z->word[0] = 1;
|
||||
power_2 (a0010, a, 63);
|
||||
power_2 (a0100, a, 63);
|
||||
power_2 (a1000, a, 63);
|
||||
print_table (a0001, a0010, a0100, a1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
#ifdef TESTING_EDDSA
|
||||
uint8_t hash[64];
|
||||
bn256 a[1];
|
||||
uint8_t r_s[64];
|
||||
bn256 pk[1];
|
||||
bn256 *r, *s;
|
||||
|
||||
const bn256 sk[1] = {
|
||||
{{ 0x9db1619d, 0x605afdef, 0xf44a84ba, 0xc42cec92,
|
||||
0x69c54944, 0x1969327b, 0x03ac3b70, 0x607fae1c }} };
|
||||
|
||||
const bn256 r_expected[1] = {
|
||||
{{ 0x004356e5, 0x72ac60c3, 0xcce28690, 0x8a826e80,
|
||||
0x1e7f8784, 0x74d9e5b8, 0x65e073d8, 0x55014922 }} };
|
||||
|
||||
const bn256 s_expected[1] = {
|
||||
{{ 0x1582b85f, 0xac3ba390, 0x70391ec6, 0x6bb4f91c,
|
||||
0xf0f55bd2, 0x24be5b59, 0x43415165, 0x0b107a8e }} };
|
||||
|
||||
r = (bn256 *)r_s;
|
||||
s = (bn256 *)(r_s+32);
|
||||
|
||||
sha512 ((uint8_t *)sk, sizeof (bn256), hash);
|
||||
hash[0] &= 248;
|
||||
hash[31] &= 127;
|
||||
hash[31] |= 64;
|
||||
memcpy (a, hash, sizeof (bn256));
|
||||
|
||||
eddsa_public_key_25519 (pk, a);
|
||||
eddsa_sign_25519 ((const uint8_t *)"", 0, r_s, a, hash+32, pk);
|
||||
|
||||
if (memcmp (r, r_expected, sizeof (bn256)) != 0
|
||||
|| memcmp (s, s_expected, sizeof (bn256)) != 0)
|
||||
{
|
||||
print_bn256 (r);
|
||||
print_bn256 (s);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
ac a0001[1], a0010[1], a0100[1], a1000[1];
|
||||
ptc a[1];
|
||||
|
||||
memcpy (a, G, sizeof (ptc));
|
||||
ptc_to_ac_25519 (a0001, a);
|
||||
compute_and_print_table (a0001, a0010, a0100, a1000);
|
||||
|
||||
memcpy (a, a0001, sizeof (ac));
|
||||
memset (a->z, 0, sizeof (bn256));
|
||||
a->z->word[0] = 1;
|
||||
power_2 (a0001, a, 21);
|
||||
compute_and_print_table (a0001, a0010, a0100, a1000);
|
||||
|
||||
memcpy (a, a0001, sizeof (ac));
|
||||
memset (a->z, 0, sizeof (bn256));
|
||||
a->z->word[0] = 1;
|
||||
power_2 (a0001, a, 21);
|
||||
compute_and_print_table (a0001, a0010, a0100, a1000);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
196
src/ecc-mont.c
Normal file
196
src/ecc-mont.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ecc-mont.c - Elliptic curve computation for
|
||||
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "mod25638.h"
|
||||
#include "mod.h"
|
||||
|
||||
/*
|
||||
* References:
|
||||
*
|
||||
* [1] D. J. Bernstein. Curve25519: new Diffie-Hellman speed records.
|
||||
* Proceedings of PKC 2006, to appear.
|
||||
* http://cr.yp.to/papers.html#curve25519. Date: 2006.02.09.
|
||||
*
|
||||
* [2] D. J. Bernstein. Can we avoid tests for zero in fast
|
||||
* elliptic-curve arithmetic?
|
||||
* http://cr.yp.to/papers.html#curvezero. Date: 2006.07.26.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* IMPLEMENTATION NOTE
|
||||
*
|
||||
* (0) We assume that the processor has no cache, nor branch target
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* We don't avoid conditional jump if both cases have same timing,
|
||||
* either.
|
||||
*
|
||||
* (1) We use Radix-32 field arithmetic. It's a representation like
|
||||
* 2^256-38, but it's more redundant. For example, "1" can be
|
||||
* represented in three ways in 256-bit: 1, 2^255-18, and
|
||||
* 2^256-37.
|
||||
*
|
||||
* (2) We use Montgomery double-and-add.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BN256_C_IMPLEMENTATION
|
||||
#define ASM_IMPLEMENTATION 1
|
||||
#endif
|
||||
/*
|
||||
*
|
||||
* 121665 = 0x1db41
|
||||
* 1 1101 1011 0100 0001
|
||||
*/
|
||||
static void
|
||||
mod25638_mul_121665 (bn256 *x, const bn256 *a)
|
||||
{
|
||||
#if ASM_IMPLEMENTATION
|
||||
#include "muladd_256.h"
|
||||
const uint32_t *s;
|
||||
uint32_t *d;
|
||||
uint32_t w;
|
||||
uint32_t c;
|
||||
|
||||
s = a->word;
|
||||
d = x->word;
|
||||
w = 121665;
|
||||
MULADD_256_ASM (s, d, w, c);
|
||||
#else
|
||||
uint32_t c, c1;
|
||||
bn256 m[1];
|
||||
|
||||
c = c1 = bn256_shift (m, a, 6); c += bn256_add (x, a, m);
|
||||
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
|
||||
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
|
||||
#endif
|
||||
c = bn256_add_uint (x, x, c*38);
|
||||
x->word[0] += c * 38;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 z[1];
|
||||
} pt;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Process Montgomery double-and-add
|
||||
*
|
||||
* With Q0, Q1, DIF (= Q0 - Q1), compute PRD = 2Q0, SUM = Q0 + Q1
|
||||
* Q0 and Q1 are clobbered.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
mont_d_and_a (pt *prd, pt *sum, pt *q0, pt *q1, const bn256 *dif_x)
|
||||
{
|
||||
mod25638_add (sum->x, q1->x, q1->z);
|
||||
mod25638_sub (q1->z, q1->x, q1->z);
|
||||
mod25638_add (prd->x, q0->x, q0->z);
|
||||
mod25638_sub (q0->z, q0->x, q0->z);
|
||||
mod25638_mul (q1->x, q0->z, sum->x);
|
||||
mod25638_mul (q1->z, prd->x, q1->z);
|
||||
mod25638_sqr (q0->x, prd->x);
|
||||
mod25638_sqr (q0->z, q0->z);
|
||||
mod25638_add (sum->x, q1->x, q1->z);
|
||||
mod25638_sub (q1->z, q1->x, q1->z);
|
||||
mod25638_mul (prd->x, q0->x, q0->z);
|
||||
mod25638_sub (q0->z, q0->x, q0->z);
|
||||
mod25638_sqr (sum->x, sum->x);
|
||||
mod25638_sqr (sum->z, q1->z);
|
||||
mod25638_mul_121665 (prd->z, q0->z);
|
||||
mod25638_mul (sum->z, sum->z, dif_x);
|
||||
mod25638_add (prd->z, q0->x, prd->z);
|
||||
mod25638_mul (prd->z, prd->z, q0->z);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief RES = x-coordinate of [n]Q
|
||||
*
|
||||
* @param N Scalar N (three least significant bits are 000)
|
||||
* @param Q_X x-coordinate of Q
|
||||
*
|
||||
*/
|
||||
void
|
||||
compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
|
||||
{
|
||||
int i, j;
|
||||
pt p0[1], p1[1], p0_[1], p1_[1];
|
||||
|
||||
/* P0 = O = (1:0) */
|
||||
memset (p0->x, 0, sizeof (bn256));
|
||||
p0->x->word[0] = 1;
|
||||
memset (p0->z, 0, sizeof (bn256));
|
||||
|
||||
/* P1 = (X:1) */
|
||||
memcpy (p1->x, q_x, sizeof (bn256));
|
||||
memset (p1->z, 0, sizeof (bn256));
|
||||
p1->z->word[0] = 1;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t u = n->word[7-i];
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
pt *q0, *q1;
|
||||
pt *sum_n, *prd_n;
|
||||
|
||||
if ((u & 0x80000000))
|
||||
q0 = p1, q1 = p0, sum_n = p0_, prd_n = p1_;
|
||||
else
|
||||
q0 = p0, q1 = p1, sum_n = p1_, prd_n = p0_;
|
||||
mont_d_and_a (prd_n, sum_n, q0, q1, q_x);
|
||||
|
||||
if ((u & 0x40000000))
|
||||
q0 = p1_, q1 = p0_, sum_n = p0, prd_n = p1;
|
||||
else
|
||||
q0 = p0_, q1 = p1_, sum_n = p1, prd_n = p0;
|
||||
mont_d_and_a (prd_n, sum_n, q0, q1, q_x);
|
||||
|
||||
u <<= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* We know the LSB of N is always 0. Thus, result is always in P0. */
|
||||
/*
|
||||
* p0->z may be zero here, but our mod_inv doesn't raise error for 0,
|
||||
* but returns 0 (like the implementation of z^(p-2)), thus, RES will
|
||||
* be 0 in that case, which is correct value.
|
||||
*/
|
||||
mod_inv (res, p0->z, p25519);
|
||||
mod25638_mul (res, res, p0->x);
|
||||
mod25519_reduce (res);
|
||||
}
|
||||
@@ -169,7 +169,7 @@ point_is_on_the_curve (const ac *P)
|
||||
MFNC(sqr) (s, P->x);
|
||||
MFNC(mul) (s, s, P->x);
|
||||
|
||||
#ifdef COEFFICIENT_A_IS_ZERO
|
||||
#ifndef COEFFICIENT_A_IS_ZERO
|
||||
MFNC(mul) (t, coefficient_a, P->x);
|
||||
MFNC(add) (s, s, t);
|
||||
#endif
|
||||
@@ -311,7 +311,7 @@ FUNC(compute_kP) (ac *X, const bn256 *K, const ac *P)
|
||||
}
|
||||
|
||||
dst = k_is_even ? Q : tmp;
|
||||
FUNC(jpc_add_ac) (dst, Q, &precomputed_KG[0]);
|
||||
FUNC(jpc_add_ac) (dst, Q, P);
|
||||
|
||||
return FUNC(jpc_to_ac) (X, Q);
|
||||
}
|
||||
|
||||
134
src/fe25519.c
134
src/fe25519.c
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* fe25519.c -- 2^255-19 field element computation
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The field is \Z/(2^255-19)
|
||||
*
|
||||
* We use radix-32. During computation, it's not reduced to 2^255-19,
|
||||
* but it is represented in 256-bit (it is redundant representation).
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "fe25519.h"
|
||||
|
||||
#define ADDWORD_256(d_,w_,c_) \
|
||||
asm ( "ldmia %[d], { r4, r5, r6, r7 } \n\t" \
|
||||
"adds r4, r4, %[w] \n\t" \
|
||||
"adcs r5, r5, #0 \n\t" \
|
||||
"adcs r6, r6, #0 \n\t" \
|
||||
"adcs r7, r7, #0 \n\t" \
|
||||
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
|
||||
"ldmia %[d], { r4, r5, r6, r7 } \n\t" \
|
||||
"adcs r4, r4, #0 \n\t" \
|
||||
"adcs r5, r5, #0 \n\t" \
|
||||
"adcs r6, r6, #0 \n\t" \
|
||||
"adcs r7, r7, #0 \n\t" \
|
||||
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
|
||||
"mov %[c], #0 \n\t" \
|
||||
"adc %[c], %[c], #0" \
|
||||
: [d] "=&r" (d_), [c] "=&r" (c_) \
|
||||
: "[d]" (d_), [w] "r" (w_) \
|
||||
: "r4", "r5", "r6", "r7", "memory", "cc" )
|
||||
|
||||
#define MULADD_256(s_,d_,w_,c_) do { \
|
||||
asm ( "ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
"umull r4, r8, %[w], r8 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, r8 \n\t" \
|
||||
"umull r4, r8, %[w], r9 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r6, r6, r4 \n\t" \
|
||||
"adcs r7, r7, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r10 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r7, r7, r4 \n\t" \
|
||||
"stmia %[d]!, { r5, r6, r7 } \n\t" \
|
||||
"ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
"adcs r5, r5, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r8 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r9 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r6, r6, r4 \n\t" \
|
||||
"adcs r7, r7, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r10 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r7, r7, r4 \n\t" \
|
||||
"stmia %[d]!, { r5, r6, r7 } \n\t" \
|
||||
"ldmia %[s]!, { r8, r9 } \n\t" \
|
||||
"ldmia %[d], { r5, r6 } \n\t" \
|
||||
"adcs r5, r5, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r8 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, %[c] \n\t" \
|
||||
"umull r4, r8, %[w], r9 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r6, r6, r4 \n\t" \
|
||||
"adc %[c], %[c], #0 \n\t" \
|
||||
"stmia %[d]!, { r5, r6 }" \
|
||||
: [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \
|
||||
: "[s]" (s_), "[d]" (d_), [w] "r" (w_) \
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
|
||||
"memory", "cc" ); \
|
||||
*d_ = c_; \
|
||||
} while (0)
|
||||
|
||||
static void mul_hlp (const uint32_t *s, uint32_t *d, uint32_t w)
|
||||
{
|
||||
uint32_t c;
|
||||
|
||||
MULADD_256 (s, d, w, c);
|
||||
}
|
||||
|
||||
|
||||
void fe_mul (fe25519 *X, const fe25519 *A, const fe25519 *B)
|
||||
{
|
||||
uint32_t word[FE25519_WORDS*2];
|
||||
const uint32_t *s;
|
||||
uint32_t *d;
|
||||
uint32_t w;
|
||||
uint32_t c, c0;
|
||||
|
||||
memset (word, 0, sizeof (uint32_t)*FE25519_WORDS);
|
||||
|
||||
s = A->word; d = &word[0]; w = B->word[0]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[1]; w = B->word[1]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[2]; w = B->word[2]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[3]; w = B->word[3]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[4]; w = B->word[4]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[5]; w = B->word[5]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[6]; w = B->word[6]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &word[7]; w = B->word[7]; MULADD_256 (s, d, w, c);
|
||||
s = &word[8]; d = &word[0]; w = 38; MULADD_256 (s, d, w, c);
|
||||
c0 = word[8] * 38;
|
||||
s = word;
|
||||
ADDWORD_256 (s, c0, c);
|
||||
word[0] += c * 38;
|
||||
memcpy (X->word, word, sizeof X->word);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#define FE25519_WORDS 8
|
||||
typedef struct fe25519 {
|
||||
uint32_t word[FE25519_WORDS]; /* Little endian */
|
||||
} fe25519;
|
||||
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
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -57,13 +57,15 @@
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
* _keystore_pool
|
||||
* three flash pages for keystore (single: 512-byte (p, q and N))
|
||||
* 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
|
||||
*/
|
||||
#define KEY_SIZE 512 /* P, Q and N */
|
||||
|
||||
#define FLASH_DATA_POOL_HEADER_SIZE 2
|
||||
#define FLASH_DATA_POOL_SIZE (FLASH_PAGE_SIZE*2)
|
||||
#define FLASH_KEYSTORE_SIZE (FLASH_PAGE_SIZE*3)
|
||||
|
||||
static const uint8_t *data_pool;
|
||||
extern uint8_t _keystore_pool;
|
||||
@@ -78,6 +80,25 @@ const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
/* Linker set this symbol */
|
||||
extern uint8_t _data_pool;
|
||||
|
||||
static int key_available_at (const uint8_t *k, int key_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < key_size; i++)
|
||||
if (k[i])
|
||||
break;
|
||||
if (i == key_size) /* It's ZERO. Released key. */
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < key_size; i++)
|
||||
if (k[i] != 0xff)
|
||||
break;
|
||||
if (i == key_size) /* It's FULL. Unused key. */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
flash_init (void)
|
||||
{
|
||||
@@ -100,6 +121,33 @@ flash_init (void)
|
||||
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
}
|
||||
|
||||
void
|
||||
flash_init_keys (void)
|
||||
{
|
||||
const uint8_t *p;
|
||||
int i;
|
||||
|
||||
/* For each key, find its address. */
|
||||
p = &_keystore_pool;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
const uint8_t *k;
|
||||
int key_size = gpg_get_algo_attr_key_size (i, GPG_KEY_STORAGE);
|
||||
|
||||
kd[i].pubkey = NULL;
|
||||
for (k = p; k < p + FLASH_PAGE_SIZE; k += key_size)
|
||||
if (key_available_at (k, key_size))
|
||||
{
|
||||
int prv_len = gpg_get_algo_attr_key_size (i, GPG_KEY_PRIVATE);
|
||||
|
||||
kd[i].pubkey = k + prv_len;
|
||||
break;
|
||||
}
|
||||
|
||||
p += FLASH_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash data pool managenent
|
||||
*
|
||||
@@ -114,6 +162,7 @@ flash_init (void)
|
||||
* 123-counter
|
||||
* 14-bit counter
|
||||
* bool object
|
||||
* small enum
|
||||
*
|
||||
* Format of a Data Object:
|
||||
* NR: 8-bit tag_number
|
||||
@@ -269,34 +318,41 @@ flash_do_release (const uint8_t *do_data)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
flash_key_alloc (void)
|
||||
static uint8_t *
|
||||
flash_key_getpage (enum kind_of_key kk)
|
||||
{
|
||||
uint8_t *k;
|
||||
int i;
|
||||
/* There is a page for each KK. */
|
||||
return &_keystore_pool + (FLASH_PAGE_SIZE * kk);
|
||||
}
|
||||
|
||||
/* Seek empty keystore. */
|
||||
k = &_keystore_pool;
|
||||
while (k < &_keystore_pool + FLASH_KEYSTORE_SIZE)
|
||||
uint8_t *
|
||||
flash_key_alloc (enum kind_of_key kk)
|
||||
{
|
||||
uint8_t *k, *k0 = flash_key_getpage (kk);
|
||||
int i;
|
||||
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
|
||||
|
||||
/* Seek free space in the page. */
|
||||
for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += key_size)
|
||||
{
|
||||
const uint32_t *p = (const uint32_t *)k;
|
||||
|
||||
for (i = 0; i < KEY_SIZE/4; i++)
|
||||
for (i = 0; i < key_size/4; i++)
|
||||
if (p[i] != 0xffffffff)
|
||||
break;
|
||||
|
||||
if (i == KEY_SIZE/4) /* Yes, it's empty. */
|
||||
if (i == key_size/4) /* Yes, it's empty. */
|
||||
return k;
|
||||
|
||||
k += KEY_SIZE;
|
||||
}
|
||||
|
||||
/* Should not happen as we have enough space, but just in case. */
|
||||
/* Should not happen as we have enough free space all time, but just
|
||||
in case. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
flash_key_write (uint8_t *key_addr,
|
||||
const uint8_t *key_data, int key_data_len,
|
||||
const uint8_t *pubkey, int pubkey_len)
|
||||
{
|
||||
uint16_t hw;
|
||||
@@ -304,7 +360,7 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)key_addr;
|
||||
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
|
||||
for (i = 0; i < key_data_len/2; i ++)
|
||||
{
|
||||
hw = key_data[i*2] | (key_data[i*2+1]<<8);
|
||||
if (flash_program_halfword (addr, hw) != 0)
|
||||
@@ -324,14 +380,14 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
}
|
||||
|
||||
static int
|
||||
flash_check_all_other_keys_released (const uint8_t *key_addr)
|
||||
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);
|
||||
const uint32_t *p = (const uint32_t *)start;
|
||||
|
||||
while (p < (const uint32_t *)(start + FLASH_PAGE_SIZE))
|
||||
if (p == (const uint32_t *)key_addr)
|
||||
p += KEY_SIZE/4;
|
||||
p += key_size/4;
|
||||
else
|
||||
if (*p)
|
||||
return 0;
|
||||
@@ -342,22 +398,28 @@ flash_check_all_other_keys_released (const uint8_t *key_addr)
|
||||
}
|
||||
|
||||
static void
|
||||
flash_key_fill_zero_as_released (uint8_t *key_addr)
|
||||
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
int i;
|
||||
uint32_t addr = (uint32_t)key_addr;
|
||||
|
||||
for (i = 0; i < KEY_SIZE/2; i++)
|
||||
for (i = 0; i < key_size/2; i++)
|
||||
flash_program_halfword (addr + i*2, 0);
|
||||
}
|
||||
|
||||
void
|
||||
flash_key_release (uint8_t *key_addr)
|
||||
flash_key_release (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
if (flash_check_all_other_keys_released (key_addr))
|
||||
if (flash_check_all_other_keys_released (key_addr, key_size))
|
||||
flash_erase_page (((uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1)));
|
||||
else
|
||||
flash_key_fill_zero_as_released (key_addr);
|
||||
flash_key_fill_zero_as_released (key_addr, key_size);
|
||||
}
|
||||
|
||||
void
|
||||
flash_key_release_page (enum kind_of_key kk)
|
||||
{
|
||||
flash_erase_page ((uint32_t)flash_key_getpage (kk));
|
||||
}
|
||||
|
||||
|
||||
@@ -425,6 +487,38 @@ flash_bool_write (uint8_t nr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flash_enum_clear (const uint8_t **addr_p)
|
||||
{
|
||||
flash_bool_clear (addr_p);
|
||||
}
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
flash_enum_write (uint8_t nr, uint8_t v)
|
||||
{
|
||||
uint8_t *p;
|
||||
uint16_t hw = nr | (v << 8);
|
||||
|
||||
p = flash_data_pool_allocate (2);
|
||||
if (p == NULL)
|
||||
{
|
||||
DEBUG_INFO ("enum allocation failure.\r\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
flash_cnt123_get_value (const uint8_t *p)
|
||||
{
|
||||
@@ -552,7 +646,7 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
}
|
||||
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
{
|
||||
maxsize = KEY_CONTENT_LEN;
|
||||
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. */
|
||||
|
||||
300
src/gnuk.h
300
src/gnuk.h
@@ -36,10 +36,10 @@ void ccid_card_change_signal (int how);
|
||||
#define EV_VERIFY_CMD_AVAILABLE (8)
|
||||
#define EV_MODIFY_CMD_AVAILABLE (16)
|
||||
|
||||
/* Maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
|
||||
#define MAX_CMD_APDU_DATA_SIZE (22+4+128+128) /* without header */
|
||||
/* Maximum res apdu data is public key 5+9+256 (gpg_do_public_key) */
|
||||
#define MAX_RES_APDU_DATA_SIZE (5+9+256) /* without trailer */
|
||||
/* 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 */
|
||||
/* Maximum res apdu data is public key 5+9+512 (gpg_do_public_key) */
|
||||
#define MAX_RES_APDU_DATA_SIZE (5+9+512) /* without trailer */
|
||||
|
||||
#define ICC_MSG_HEADER_SIZE 10
|
||||
|
||||
@@ -49,8 +49,7 @@ void ccid_card_change_signal (int how);
|
||||
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
|
||||
#define USB_LL_BUF_SIZE 64
|
||||
|
||||
enum icc_state
|
||||
{
|
||||
enum icc_state {
|
||||
ICC_STATE_NOCARD, /* No card available */
|
||||
ICC_STATE_START, /* Initial */
|
||||
ICC_STATE_WAIT, /* Waiting APDU */
|
||||
@@ -63,6 +62,8 @@ enum icc_state
|
||||
ICC_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
#define CCID_CARD_INIT CARD_CHANGE_INSERT
|
||||
|
||||
extern enum icc_state *icc_state_p;
|
||||
|
||||
extern volatile uint8_t auth_status;
|
||||
@@ -76,40 +77,46 @@ extern volatile uint8_t auth_status;
|
||||
#define PW_ERR_PW1 0
|
||||
#define PW_ERR_RC 1
|
||||
#define PW_ERR_PW3 2
|
||||
extern int gpg_pw_get_retry_counter (int who);
|
||||
extern int gpg_pw_locked (uint8_t which);
|
||||
extern void gpg_pw_reset_err_counter (uint8_t which);
|
||||
extern void gpg_pw_increment_err_counter (uint8_t which);
|
||||
int gpg_pw_get_retry_counter (int who);
|
||||
int gpg_pw_locked (uint8_t which);
|
||||
void gpg_pw_reset_err_counter (uint8_t which);
|
||||
void gpg_pw_increment_err_counter (uint8_t which);
|
||||
|
||||
extern int ac_check_status (uint8_t ac_flag);
|
||||
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
||||
extern int verify_other (const uint8_t *pw, int pw_len);
|
||||
extern int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
|
||||
int pw_len_known, const uint8_t *ks_pw1, int saveks);
|
||||
extern int verify_admin (const uint8_t *pw, int pw_len);
|
||||
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw3, int saveks);
|
||||
int ac_check_status (uint8_t ac_flag);
|
||||
int verify_pso_cds (const uint8_t *pw, int pw_len);
|
||||
int verify_other (const uint8_t *pw, int pw_len);
|
||||
int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
|
||||
int pw_len_known, const uint8_t *ks_pw1, int saveks);
|
||||
int verify_admin (const uint8_t *pw, int pw_len);
|
||||
int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw3, int saveks);
|
||||
|
||||
extern void ac_reset_pso_cds (void);
|
||||
extern void ac_reset_other (void);
|
||||
extern void ac_reset_admin (void);
|
||||
extern void ac_fini (void);
|
||||
void ac_reset_pso_cds (void);
|
||||
void ac_reset_other (void);
|
||||
void ac_reset_admin (void);
|
||||
void ac_fini (void);
|
||||
|
||||
|
||||
extern void set_res_sw (uint8_t sw1, uint8_t sw2);
|
||||
void set_res_sw (uint8_t sw1, uint8_t sw2);
|
||||
extern uint16_t data_objects_number_of_bytes;
|
||||
|
||||
#define CHALLENGE_LEN 32
|
||||
|
||||
extern void gpg_data_scan (const uint8_t *p);
|
||||
extern void gpg_data_copy (const uint8_t *p);
|
||||
extern void gpg_do_get_data (uint16_t tag, int with_tag);
|
||||
extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
|
||||
extern void gpg_do_public_key (uint8_t kk_byte);
|
||||
extern void gpg_do_keygen (uint8_t kk_byte);
|
||||
void gpg_data_scan (const uint8_t *p);
|
||||
void gpg_data_copy (const uint8_t *p);
|
||||
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);
|
||||
|
||||
extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
|
||||
/* Constants: algo+size */
|
||||
#define ALGO_RSA4K 0
|
||||
#define ALGO_NISTP256R1 1
|
||||
#define ALGO_SECP256K1 2
|
||||
#define ALGO_ED25519 3
|
||||
#define ALGO_RSA2K 255
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNING = 0,
|
||||
@@ -117,17 +124,29 @@ enum kind_of_key {
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
};
|
||||
|
||||
extern const uint8_t *flash_init (void);
|
||||
extern void flash_do_release (const uint8_t *);
|
||||
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||
extern uint8_t *flash_key_alloc (void);
|
||||
extern void flash_key_release (uint8_t *);
|
||||
extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
const uint8_t *pubkey, int pubkey_len);
|
||||
extern void flash_set_data_pool_last (const uint8_t *p);
|
||||
extern void flash_clear_halfword (uint32_t addr);
|
||||
extern void flash_increment_counter (uint8_t counter_tag_nr);
|
||||
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
enum size_of_key {
|
||||
GPG_KEY_STORAGE = 0, /* PUBKEY + PRVKEY rounded to 2^N */
|
||||
GPG_KEY_PUBLIC,
|
||||
GPG_KEY_PRIVATE,
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
const uint8_t *flash_init (void);
|
||||
void flash_init_keys (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);
|
||||
void flash_key_release (uint8_t *, int);
|
||||
void flash_key_release_page (enum kind_of_key);
|
||||
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_increment_counter (uint8_t counter_tag_nr);
|
||||
void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
|
||||
#define FILEID_SERIAL_NO 0
|
||||
#define FILEID_UPDATE_KEY_0 1
|
||||
@@ -135,8 +154,9 @@ extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
#define FILEID_UPDATE_KEY_2 3
|
||||
#define FILEID_UPDATE_KEY_3 4
|
||||
#define FILEID_CH_CERTIFICATE 5
|
||||
extern int flash_erase_binary (uint8_t file_id);
|
||||
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
||||
int flash_erase_binary (uint8_t file_id);
|
||||
int flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
uint16_t len, uint16_t offset);
|
||||
|
||||
#define FLASH_CH_CERTIFICATE_SIZE 2048
|
||||
|
||||
@@ -144,22 +164,19 @@ extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t le
|
||||
extern uint8_t ch_certificate_start;
|
||||
extern uint8_t random_bits_start;
|
||||
|
||||
#define KEY_CONTENT_LEN 256 /* p and q */
|
||||
#define FIRMWARE_UPDATE_KEY_CONTENT_LEN 256 /* RSA-2048 (p and q) */
|
||||
|
||||
#define INITIAL_VECTOR_SIZE 16
|
||||
#define DATA_ENCRYPTION_KEY_SIZE 16
|
||||
|
||||
/* encrypted data content */
|
||||
struct key_data {
|
||||
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
|
||||
};
|
||||
#define MAX_PRVKEY_LEN 512 /* Maximum is the case for RSA 4096-bit. */
|
||||
|
||||
struct key_data_internal {
|
||||
uint32_t data[KEY_CONTENT_LEN/4]; /* p and q */
|
||||
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
|
||||
struct key_data {
|
||||
const uint8_t *pubkey; /* Pointer to public key */
|
||||
uint8_t data[MAX_PRVKEY_LEN]; /* decrypted private key data content */
|
||||
};
|
||||
|
||||
struct prvkey_data {
|
||||
const uint8_t *key_addr;
|
||||
/*
|
||||
* IV: Initial Vector
|
||||
*/
|
||||
@@ -202,14 +219,14 @@ void s2k (const unsigned char *salt, size_t slen,
|
||||
#define KS_GET_SALT(ks) (ks + KEYSTRING_PASSLEN_SIZE)
|
||||
#define KS_GET_KEYSTRING(ks) (ks + KS_META_SIZE)
|
||||
|
||||
extern void gpg_do_clear_prvkey (enum kind_of_key kk);
|
||||
extern int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
|
||||
extern int gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
void gpg_do_clear_prvkey (enum kind_of_key kk);
|
||||
int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
|
||||
int gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
|
||||
extern int gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
int gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
|
||||
extern struct key_data kd[3];
|
||||
|
||||
@@ -218,13 +235,13 @@ extern struct key_data kd[3];
|
||||
/*
|
||||
* Debug functions in debug.c
|
||||
*/
|
||||
extern void put_byte (uint8_t b);
|
||||
extern void put_byte_with_no_nl (uint8_t b);
|
||||
extern void put_short (uint16_t x);
|
||||
extern void put_word (uint32_t x);
|
||||
extern void put_int (uint32_t x);
|
||||
extern void put_string (const char *s);
|
||||
extern void put_binary (const char *s, int len);
|
||||
void put_byte (uint8_t b);
|
||||
void put_byte_with_no_nl (uint8_t b);
|
||||
void put_short (uint16_t x);
|
||||
void put_word (uint32_t x);
|
||||
void put_int (uint32_t x);
|
||||
void put_string (const char *s);
|
||||
void put_binary (const char *s, int len);
|
||||
|
||||
#define DEBUG_INFO(msg) put_string (msg)
|
||||
#define DEBUG_WORD(w) put_word (w)
|
||||
@@ -239,27 +256,36 @@ extern void put_binary (const char *s, int len);
|
||||
#define DEBUG_BINARY(s,len)
|
||||
#endif
|
||||
|
||||
extern int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *);
|
||||
extern uint8_t *modulus_calc (const uint8_t *, int);
|
||||
extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
|
||||
extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash,
|
||||
const uint8_t *signature);
|
||||
extern uint8_t *rsa_genkey (void);
|
||||
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
|
||||
uint8_t *modulus_calc (const uint8_t *, int);
|
||||
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);
|
||||
|
||||
extern int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
extern uint8_t *ecdsa_compute_public_p256r1 (const uint8_t *key_data);
|
||||
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 ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
extern int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
extern uint8_t *ecdsa_compute_public_p256k1 (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 ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
||||
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||
extern void gpg_increment_digital_signature_counter (void);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
extern void fatal (uint8_t code) __attribute__ ((noreturn));
|
||||
void fatal (uint8_t code) __attribute__ ((noreturn));
|
||||
#define FATAL_FLASH 1
|
||||
#define FATAL_RANDOM 2
|
||||
|
||||
@@ -267,7 +293,6 @@ extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
extern uint8_t admin_authorized;
|
||||
|
||||
/*** Flash memory tag values ***/
|
||||
#define NR_NONE 0x00
|
||||
/* Data objects */
|
||||
/*
|
||||
* Representation of data object:
|
||||
@@ -275,28 +300,27 @@ extern uint8_t admin_authorized;
|
||||
* <-1 halfword-> <--len/2 halfwords->
|
||||
* <-tag-><-len-> <---data content--->
|
||||
*/
|
||||
#define NR_DO__FIRST__ 0x01
|
||||
#define NR_DO_SEX 0x01
|
||||
#define NR_DO_FP_SIG 0x02
|
||||
#define NR_DO_FP_DEC 0x03
|
||||
#define NR_DO_FP_AUT 0x04
|
||||
#define NR_DO_CAFP_1 0x05
|
||||
#define NR_DO_CAFP_2 0x06
|
||||
#define NR_DO_CAFP_3 0x07
|
||||
#define NR_DO_KGTIME_SIG 0x08
|
||||
#define NR_DO_KGTIME_DEC 0x09
|
||||
#define NR_DO_KGTIME_AUT 0x0a
|
||||
#define NR_DO_LOGIN_DATA 0x0b
|
||||
#define NR_DO_URL 0x0c
|
||||
#define NR_DO_NAME 0x0d
|
||||
#define NR_DO_LANGUAGE 0x0e
|
||||
#define NR_DO_PRVKEY_SIG 0x0f
|
||||
#define NR_DO_PRVKEY_DEC 0x10
|
||||
#define NR_DO_PRVKEY_AUT 0x11
|
||||
#define NR_DO_KEYSTRING_PW1 0x12
|
||||
#define NR_DO_KEYSTRING_RC 0x13
|
||||
#define NR_DO_KEYSTRING_PW3 0x14
|
||||
#define NR_DO__LAST__ 21 /* == 0x15 */
|
||||
#define NR_DO_SEX 0x00
|
||||
#define NR_DO_FP_SIG 0x01
|
||||
#define NR_DO_FP_DEC 0x02
|
||||
#define NR_DO_FP_AUT 0x03
|
||||
#define NR_DO_CAFP_1 0x04
|
||||
#define NR_DO_CAFP_2 0x05
|
||||
#define NR_DO_CAFP_3 0x06
|
||||
#define NR_DO_KGTIME_SIG 0x07
|
||||
#define NR_DO_KGTIME_DEC 0x08
|
||||
#define NR_DO_KGTIME_AUT 0x09
|
||||
#define NR_DO_LOGIN_DATA 0x0a
|
||||
#define NR_DO_URL 0x0b
|
||||
#define NR_DO_NAME 0x0c
|
||||
#define NR_DO_LANGUAGE 0x0d
|
||||
#define NR_DO_PRVKEY_SIG 0x0e
|
||||
#define NR_DO_PRVKEY_DEC 0x0f
|
||||
#define NR_DO_PRVKEY_AUT 0x10
|
||||
#define NR_DO_KEYSTRING_PW1 0x11
|
||||
#define NR_DO_KEYSTRING_RC 0x12
|
||||
#define NR_DO_KEYSTRING_PW3 0x13
|
||||
#define NR_DO__LAST__ 20 /* == 0x14 */
|
||||
/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */
|
||||
/*
|
||||
* Representation of 14-bit counter:
|
||||
@@ -315,7 +339,10 @@ extern uint8_t admin_authorized;
|
||||
* 1023: 0xc3ff
|
||||
*/
|
||||
#define NR_COUNTER_DS_LSB 0xc0 /* ..0xc3 */
|
||||
/* 8-bit int or Boolean objects: Recorded in flash memory by 1-halfword (2-byte) */
|
||||
/*
|
||||
* Boolean object, small enum, or 8-bit integer:
|
||||
* Recorded in flash memory by 1-halfword (2-byte)
|
||||
*/
|
||||
/*
|
||||
* Representation of Boolean object:
|
||||
* 0: No record in flash memory
|
||||
@@ -323,7 +350,20 @@ extern uint8_t admin_authorized;
|
||||
*/
|
||||
#define NR_BOOL_PW1_LIFETIME 0xf0
|
||||
/*
|
||||
* NR_BOOL_SOMETHING, NR_UINT_SOMETHING could be here... Use 0xf?
|
||||
* Representation of algorithm attribute object:
|
||||
* RSA-2048: No record in flash memory
|
||||
* RSA-4096: 0xf?00
|
||||
* ECC p256r1: 0xf?01
|
||||
* ECC p256k1: 0xf?02
|
||||
* ECC Ed25519: 0xf?03
|
||||
* ECC Curve25519: 0xf?04
|
||||
* where <?> == 1 (signature), 2 (decryption) or 3 (authentication)
|
||||
*/
|
||||
#define NR_KEY_ALGO_ATTR_SIG 0xf1
|
||||
#define NR_KEY_ALGO_ATTR_DEC 0xf2
|
||||
#define NR_KEY_ALGO_ATTR_AUT 0xf3
|
||||
/*
|
||||
* NR_UINT_SOMETHING could be here... Use 0xf[456789abcd]
|
||||
*/
|
||||
/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */
|
||||
/*
|
||||
@@ -352,18 +392,22 @@ extern uint8_t admin_authorized;
|
||||
|
||||
extern const uint8_t openpgpcard_aid[14];
|
||||
|
||||
extern void flash_bool_clear (const uint8_t **addr_p);
|
||||
extern const uint8_t *flash_bool_write (uint8_t nr);
|
||||
extern int flash_cnt123_get_value (const uint8_t *p);
|
||||
extern void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p);
|
||||
extern void flash_cnt123_clear (const uint8_t **addr_p);
|
||||
extern void flash_put_data (uint16_t hw);
|
||||
extern void flash_warning (const char *msg);
|
||||
void flash_bool_clear (const uint8_t **addr_p);
|
||||
const uint8_t *flash_bool_write (uint8_t nr);
|
||||
void flash_enum_clear (const uint8_t **addr_p);
|
||||
const uint8_t *flash_enum_write (uint8_t nr, uint8_t v);
|
||||
int flash_cnt123_get_value (const uint8_t *p);
|
||||
void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p);
|
||||
void flash_cnt123_clear (const uint8_t **addr_p);
|
||||
void flash_put_data (uint16_t hw);
|
||||
void flash_warning (const char *msg);
|
||||
|
||||
extern void flash_put_data_internal (const uint8_t *p, uint16_t hw);
|
||||
extern void flash_bool_write_internal (const uint8_t *p, int nr);
|
||||
extern void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
|
||||
extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
|
||||
void flash_put_data_internal (const uint8_t *p, uint16_t hw);
|
||||
void flash_bool_write_internal (const uint8_t *p, int nr);
|
||||
void flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v);
|
||||
void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
|
||||
void flash_do_write_internal (const uint8_t *p, int nr,
|
||||
const uint8_t *data, int len);
|
||||
|
||||
extern const uint8_t gnukStringSerial[];
|
||||
|
||||
@@ -373,20 +417,20 @@ extern const uint8_t gnukStringSerial[];
|
||||
#define LED_START_COMMAND (8)
|
||||
#define LED_FINISH_COMMAND (16)
|
||||
#define LED_FATAL (32)
|
||||
extern void led_blink (int spec);
|
||||
void led_blink (int spec);
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
# if defined(PINPAD_CIR_SUPPORT)
|
||||
extern void cir_init (void);
|
||||
void cir_init (void);
|
||||
# elif defined(PINPAD_DIAL_SUPPORT)
|
||||
extern void dial_sw_disable (void);
|
||||
extern void dial_sw_enable (void);
|
||||
void dial_sw_disable (void);
|
||||
void dial_sw_enable (void);
|
||||
# elif defined(PINPAD_DND_SUPPORT)
|
||||
extern void msc_init (void);
|
||||
extern void msc_media_insert_change (int available);
|
||||
extern int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size);
|
||||
extern int msc_scsi_read (uint32_t lba, const uint8_t **sector_p);
|
||||
extern void msc_scsi_stop (uint8_t code);
|
||||
void msc_init (void);
|
||||
void msc_media_insert_change (int available);
|
||||
int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size);
|
||||
int msc_scsi_read (uint32_t lba, const uint8_t **sector_p);
|
||||
void msc_scsi_stop (uint8_t code);
|
||||
# endif
|
||||
#define PIN_INPUT_CURRENT 1
|
||||
#define PIN_INPUT_NEW 2
|
||||
@@ -395,7 +439,7 @@ extern void msc_scsi_stop (uint8_t code);
|
||||
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||
extern uint8_t pin_input_len;
|
||||
|
||||
extern int pinpad_getline (int msg_code, uint32_t timeout_usec);
|
||||
int pinpad_getline (int msg_code, uint32_t timeout_usec);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/* HAL configuration file for ChibiOS/RT */
|
||||
|
||||
#ifndef _HALCONF_H_
|
||||
#define _HALCONF_H_
|
||||
|
||||
#include "mcuconf.h"
|
||||
|
||||
#define HAL_USE_PAL TRUE
|
||||
#define HAL_USE_ADC FALSE
|
||||
#define HAL_USE_CAN FALSE
|
||||
#define HAL_USE_EXT FALSE
|
||||
#define HAL_USE_GPT FALSE
|
||||
#define HAL_USE_I2C FALSE
|
||||
#define HAL_USE_ICU FALSE
|
||||
#define HAL_USE_MAC FALSE
|
||||
#define HAL_USE_MMC_SPI FALSE
|
||||
#define HAL_USE_PWM FALSE
|
||||
#define HAL_USE_RTC FALSE
|
||||
#define HAL_USE_SDC FALSE
|
||||
#define HAL_USE_SERIAL FALSE
|
||||
#define HAL_USE_SERIAL_USB FALSE
|
||||
#define HAL_USE_SPI FALSE
|
||||
#define HAL_USE_UART FALSE
|
||||
#define HAL_USE_USB FALSE
|
||||
|
||||
/* Define manually, as we implement ADC driver by ourselves. */
|
||||
#define STM32_DMA_REQUIRED 1
|
||||
|
||||
#endif /* _HALCONF_H_ */
|
||||
@@ -8,15 +8,6 @@ typedef struct
|
||||
bn256 z[1];
|
||||
} jpc;
|
||||
|
||||
/**
|
||||
* @brief Affin coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
} ac;
|
||||
|
||||
void jpc_double_p256k1 (jpc *X, const jpc *A);
|
||||
void jpc_add_ac_p256k1 (jpc *X, const jpc *A, const ac *B);
|
||||
void jpc_add_ac_signed_p256k1 (jpc *X, const jpc *A, const ac *B, int minus);
|
||||
|
||||
@@ -8,15 +8,6 @@ typedef struct
|
||||
bn256 z[1];
|
||||
} jpc;
|
||||
|
||||
/**
|
||||
* @brief Affin coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
} ac;
|
||||
|
||||
void jpc_double_p256r1 (jpc *X, const jpc *A);
|
||||
void jpc_add_ac_p256r1 (jpc *X, const jpc *A, const ac *B);
|
||||
void jpc_add_ac_signed_p256r1 (jpc *X, const jpc *A, const ac *B, int minus);
|
||||
|
||||
@@ -185,9 +185,11 @@ FUNC(jpc_to_ac) (ac *X, const jpc *A)
|
||||
{
|
||||
bn256 z_inv[1], z_inv_sqr[1];
|
||||
|
||||
if (MFNC(inv) (z_inv, A->z) < 0)
|
||||
if (bn256_is_zero (A->z))
|
||||
return -1;
|
||||
|
||||
mod_inv (z_inv, A->z, CONST_P256);
|
||||
|
||||
MFNC(sqr) (z_inv_sqr, z_inv);
|
||||
MFNC(mul) (z_inv, z_inv, z_inv_sqr);
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "mod.h"
|
||||
#include "modp256k1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
|
||||
#define FIELD p256k1
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "mod.h"
|
||||
#include "modp256r1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
|
||||
#define FIELD p256r1
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* main.c - main routine of Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -290,6 +291,7 @@ const size_t __stacksize_usb = (size_t)&__process4_stack_size__;
|
||||
|
||||
#define PRIO_CCID 3
|
||||
#define PRIO_USB 4
|
||||
#define PRIO_MAIN 5
|
||||
|
||||
extern void *usb_intr (void *arg);
|
||||
|
||||
@@ -343,6 +345,8 @@ main (int argc, char *argv[])
|
||||
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
|
||||
usb_intr, NULL);
|
||||
|
||||
chopstx_main_init (PRIO_MAIN);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bDeviceState != UNCONNECTED)
|
||||
|
||||
16
src/mod.c
16
src/mod.c
@@ -134,12 +134,22 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
#undef borrow
|
||||
}
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
* Donald E. Knuth, The Art of Computer Programming, Vol. 2:
|
||||
* Seminumerical Algorithms, 3rd ed. Reading, MA: Addison-Wesley, 1998
|
||||
*
|
||||
* Max loop: X=0x8000...0000 and N=0xffff...ffff
|
||||
*/
|
||||
#define MAX_GCD_STEPS_BN256 (3*256-2)
|
||||
|
||||
/**
|
||||
* @brief C = X^(-1) mod N
|
||||
*
|
||||
* Assume X and N are co-prime (or N is prime).
|
||||
* NOTE: If X==0, it return 0.
|
||||
*
|
||||
*/
|
||||
#define MAX_N_BITS 256
|
||||
|
||||
void
|
||||
mod_inv (bn256 *C, const bn256 *X, const bn256 *N)
|
||||
{
|
||||
@@ -147,7 +157,7 @@ mod_inv (bn256 *C, const bn256 *X, const bn256 *N)
|
||||
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
int n = MAX_N_BITS * 3;
|
||||
int n = MAX_GCD_STEPS_BN256;
|
||||
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, X, sizeof (bn256));
|
||||
|
||||
287
src/mod25638.c
Normal file
287
src/mod25638.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* mod25638.c -- modulo arithmetic of 2^256-38 for 2^255-19 field
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The field is \Z/(2^255-19)
|
||||
*
|
||||
* We use radix-32. During computation, it's not reduced to 2^255-19,
|
||||
* but it is represented in 256-bit (it is redundant representation),
|
||||
* that is, something like 2^256-38.
|
||||
*
|
||||
* The idea is, keeping within 256-bit until it will be converted to
|
||||
* affine coordinates.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "mod25638.h"
|
||||
|
||||
#ifndef BN256_C_IMPLEMENTATION
|
||||
#define ASM_IMPLEMENTATION 1
|
||||
#endif
|
||||
|
||||
#if ASM_IMPLEMENTATION
|
||||
#include "muladd_256.h"
|
||||
#define ADDWORD_256(d_,s_,w_,c_) \
|
||||
asm ( "ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \
|
||||
"adds r4, r4, %[w] \n\t" \
|
||||
"adcs r5, r5, #0 \n\t" \
|
||||
"adcs r6, r6, #0 \n\t" \
|
||||
"adcs r7, r7, #0 \n\t" \
|
||||
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
|
||||
"ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \
|
||||
"adcs r4, r4, #0 \n\t" \
|
||||
"adcs r5, r5, #0 \n\t" \
|
||||
"adcs r6, r6, #0 \n\t" \
|
||||
"adcs r7, r7, #0 \n\t" \
|
||||
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
|
||||
"mov %[c], #0 \n\t" \
|
||||
"adc %[c], %[c], #0" \
|
||||
: [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \
|
||||
: "[s]" (s_), "[d]" (d_), [w] "r" (w_) \
|
||||
: "r4", "r5", "r6", "r7", "memory", "cc" )
|
||||
#endif
|
||||
|
||||
/*
|
||||
256 224 192 160 128 96 64 32 0
|
||||
2^256
|
||||
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 16
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffff0
|
||||
2^256 - 16 - 2
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffee
|
||||
2^256 - 16 - 2 - 1
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffed
|
||||
*/
|
||||
const bn256 p25519[1] = {
|
||||
{{ 0xffffffed, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }} };
|
||||
|
||||
|
||||
/*
|
||||
* Implementation Note.
|
||||
*
|
||||
* It's not always modulo n25638. The representation is redundant
|
||||
* during computation. For example, when we add the number - 1 and 1,
|
||||
* it won't overflow to 2^256, and the result is represented within
|
||||
* 256-bit.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = (A + B) mod 2^256-38
|
||||
*/
|
||||
void
|
||||
mod25638_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t carry;
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
carry = bn256_add_uint (X, X, carry*38);
|
||||
X->word[0] += carry * 38;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A - B) mod 2^256-38
|
||||
*/
|
||||
void
|
||||
mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
borrow = bn256_sub_uint (X, X, borrow*38);
|
||||
X->word[0] -= borrow * 38;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = A mod 2^256-38
|
||||
*
|
||||
* Note that the second argument is not "const bn512 *".
|
||||
* A is modified during the computation of modulo.
|
||||
*
|
||||
* It's not precisely modulo 2^256-38 for all cases,
|
||||
* but result may be redundant.
|
||||
*/
|
||||
static void
|
||||
mod25638_reduce (bn256 *X, bn512 *A)
|
||||
{
|
||||
const uint32_t *s;
|
||||
uint32_t *d;
|
||||
uint32_t w;
|
||||
|
||||
#if ASM_IMPLEMENTATION
|
||||
uint32_t c, c0;
|
||||
|
||||
s = &A->word[8]; d = &A->word[0]; w = 38; MULADD_256 (s, d, w, c);
|
||||
c0 = A->word[8] * 38;
|
||||
d = &X->word[0];
|
||||
s = &A->word[0];
|
||||
ADDWORD_256 (d, s, c0, c);
|
||||
X->word[0] += c * 38;
|
||||
#else
|
||||
s = &A->word[8]; d = &A->word[0]; w = 38;
|
||||
{
|
||||
int i;
|
||||
uint64_t r;
|
||||
uint32_t carry;
|
||||
|
||||
r = 0;
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
uint64_t uv;
|
||||
|
||||
r += d[i];
|
||||
carry = (r < d[i]);
|
||||
|
||||
uv = ((uint64_t)s[i])*w;
|
||||
r += uv;
|
||||
carry += (r < uv);
|
||||
|
||||
d[i] = (uint32_t)r;
|
||||
r = ((r >> 32) | ((uint64_t)carry << 32));
|
||||
}
|
||||
|
||||
carry = bn256_add_uint (X, (bn256 *)A, r * 38);
|
||||
X->word[0] += carry * 38;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A * B) mod 2^256-38
|
||||
*/
|
||||
void
|
||||
mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
bn512 tmp[1];
|
||||
|
||||
bn256_mul (tmp, A, B);
|
||||
mod25638_reduce (X, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A * A mod 2^256-38
|
||||
*/
|
||||
void
|
||||
mod25638_sqr (bn256 *X, const bn256 *A)
|
||||
{
|
||||
bn512 tmp[1];
|
||||
|
||||
bn256_sqr (tmp, A);
|
||||
mod25638_reduce (X, tmp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod 2^256-38
|
||||
* @note shift < 32
|
||||
*/
|
||||
void
|
||||
mod25638_shift (bn256 *X, const bn256 *A, int shift)
|
||||
{
|
||||
uint32_t carry;
|
||||
bn256 tmp[1];
|
||||
|
||||
carry = bn256_shift (X, A, shift);
|
||||
if (shift < 0)
|
||||
return;
|
||||
|
||||
memset (tmp, 0, sizeof (bn256));
|
||||
tmp->word[0] = (carry << 1);
|
||||
/* tmp->word[1] = (carry >> 31); always zero. */
|
||||
tmp->word[0] = tmp->word[0] + (carry << 2);
|
||||
tmp->word[1] = (tmp->word[0] < (carry << 2)) + (carry >> 30);
|
||||
tmp->word[0] = tmp->word[0] + (carry << 5);
|
||||
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 5)) + (carry >> 27);
|
||||
|
||||
mod25638_add (X, X, tmp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @brief X = A mod 2^255-19
|
||||
*
|
||||
* It's precisely modulo 2^255-19 (unlike mod25638_reduce).
|
||||
*/
|
||||
void
|
||||
mod25519_reduce (bn256 *X)
|
||||
{
|
||||
uint32_t q;
|
||||
bn256 r0[1], r1[1];
|
||||
int flag;
|
||||
|
||||
memcpy (r0, X, sizeof (bn256));
|
||||
q = (r0->word[7] >> 31);
|
||||
r0->word[7] &= 0x7fffffff;
|
||||
if (q)
|
||||
{
|
||||
bn256_add_uint (r0, r0, 19);
|
||||
q = (r0->word[7] >> 31);
|
||||
r0->word[7] &= 0x7fffffff;
|
||||
if (q)
|
||||
{
|
||||
bn256_add_uint (r1, r0, 19);
|
||||
q = (r1->word[7] >> 31);
|
||||
r1->word[7] &= 0x7fffffff;
|
||||
flag = 0;
|
||||
}
|
||||
else
|
||||
flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_add_uint (r1, r0, 19);
|
||||
q = (r1->word[7] >> 31); /* dummy */
|
||||
r1->word[7] &= 0x7fffffff; /* dummy */
|
||||
if (q)
|
||||
flag = 2;
|
||||
else
|
||||
flag = 3;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
bn256_add_uint (r1, r0, 19);
|
||||
q = (r1->word[7] >> 31);
|
||||
r1->word[7] &= 0x7fffffff;
|
||||
if (q)
|
||||
memcpy (X, r1, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, r0, sizeof (bn256));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
asm volatile ("" : : "r" (q) : "memory");
|
||||
memcpy (X, r1, sizeof (bn256));
|
||||
asm volatile ("" : : "r" (q) : "memory");
|
||||
}
|
||||
else
|
||||
memcpy (X, r1, sizeof (bn256));
|
||||
}
|
||||
}
|
||||
7
src/mod25638.h
Normal file
7
src/mod25638.h
Normal file
@@ -0,0 +1,7 @@
|
||||
extern const bn256 p25519[1];
|
||||
|
||||
void mod25638_add (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void mod25638_sqr (bn256 *X, const bn256 *A);
|
||||
void mod25519_reduce (bn256 *X);
|
||||
194
src/modp256k1.c
194
src/modp256k1.c
@@ -52,6 +52,17 @@
|
||||
const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } };
|
||||
|
||||
/*
|
||||
* Implementation Note.
|
||||
*
|
||||
* It's not always modulo p256k1. The representation is redundant
|
||||
* during computation. For example, when we add the prime - 1 and 1,
|
||||
* it won't overflow to 2^256, and the result is represented within
|
||||
* 256-bit.
|
||||
*
|
||||
* It is guaranteed that modp256k1_reduce reduces to modulo p256k1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief X = (A + B) mod p256k1
|
||||
*/
|
||||
@@ -273,191 +284,10 @@ modp256k1_sqr (bn256 *X, const bn256 *A)
|
||||
modp256k1_reduce (X, AA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief C = (1 / a) mod p256k1
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
#define MAX_N_BITS 256
|
||||
|
||||
int
|
||||
modp256k1_inv (bn256 *C, const bn256 *a)
|
||||
{
|
||||
bn256 u[1], v[1], tmp[1];
|
||||
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
|
||||
uint32_t carry;
|
||||
int n = MAX_N_BITS * 3;
|
||||
|
||||
if (bn256_is_zero (a))
|
||||
return -1;
|
||||
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, a, sizeof (bn256));
|
||||
memcpy (v, P256K1, sizeof (bn256));
|
||||
|
||||
while (n--)
|
||||
{
|
||||
int c = (bn256_is_even (u) << 1) + bn256_is_even (v);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 3:
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
{
|
||||
bn256_add (tmp, A, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, P256K1);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
{
|
||||
bn256_add (tmp, C, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, P256K1);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256K1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
{
|
||||
bn256_add (tmp, C, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, P256K1);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
{
|
||||
bn256_add (tmp, A, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, P256K1);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256K1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256k1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256K1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256K1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256K1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (u, v))
|
||||
{
|
||||
bn256_sub (u, u, v);
|
||||
modp256k1_sub (A, A, C);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (v, v, u);
|
||||
modp256k1_sub (C, C, A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod p256k1
|
||||
* @note shift <= 32
|
||||
* @note shift < 32
|
||||
*/
|
||||
void
|
||||
modp256k1_shift (bn256 *X, const bn256 *A, int shift)
|
||||
|
||||
@@ -7,4 +7,3 @@ void modp256k1_reduce (bn256 *X, const bn512 *A);
|
||||
void modp256k1_mul (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256k1_sqr (bn256 *X, const bn256 *A);
|
||||
void modp256k1_shift (bn256 *X, const bn256 *A, int shift);
|
||||
int modp256k1_inv (bn256 *C, const bn256 *a);
|
||||
|
||||
194
src/modp256r1.c
194
src/modp256r1.c
@@ -46,6 +46,17 @@
|
||||
const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0xffffffff} };
|
||||
|
||||
/*
|
||||
* Implementation Note.
|
||||
*
|
||||
* It's not always modulo p256r1. The representation is redundant
|
||||
* during computation. For example, when we add the prime - 1 and 1,
|
||||
* it won't overflow to 2^256, and the result is represented within
|
||||
* 256-bit.
|
||||
*
|
||||
* It is guaranteed that modp256r1_reduce reduces to modulo p256r1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief X = (A + B) mod p256r1
|
||||
*/
|
||||
@@ -229,191 +240,10 @@ modp256r1_sqr (bn256 *X, const bn256 *A)
|
||||
modp256r1_reduce (X, AA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief C = (1 / a) mod p256r1
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
#define MAX_N_BITS 256
|
||||
|
||||
int
|
||||
modp256r1_inv (bn256 *C, const bn256 *a)
|
||||
{
|
||||
bn256 u[1], v[1], tmp[1];
|
||||
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
|
||||
uint32_t carry;
|
||||
int n = MAX_N_BITS * 3;
|
||||
|
||||
if (bn256_is_zero (a))
|
||||
return -1;
|
||||
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, a, sizeof (bn256));
|
||||
memcpy (v, P256R1, sizeof (bn256));
|
||||
|
||||
while (n--)
|
||||
{
|
||||
int c = (bn256_is_even (u) << 1) + bn256_is_even (v);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 3:
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
{
|
||||
bn256_add (tmp, A, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, P256R1);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
{
|
||||
bn256_add (tmp, C, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, P256R1);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256R1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
{
|
||||
bn256_add (tmp, C, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, P256R1);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
{
|
||||
bn256_add (tmp, A, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, P256R1);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256R1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
modp256r1_sub (tmp, tmp, A);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256R1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, P256R1);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, P256R1);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (u, v))
|
||||
{
|
||||
bn256_sub (u, u, v);
|
||||
modp256r1_sub (A, A, C);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (v, v, u);
|
||||
modp256r1_sub (C, C, A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod p256r1
|
||||
* @note shift <= 32
|
||||
* @note shift < 32
|
||||
*/
|
||||
void
|
||||
modp256r1_shift (bn256 *X, const bn256 *A, int shift)
|
||||
|
||||
@@ -7,4 +7,3 @@ void modp256r1_reduce (bn256 *X, const bn512 *A);
|
||||
void modp256r1_mul (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256r1_sqr (bn256 *X, const bn256 *A);
|
||||
void modp256r1_shift (bn256 *X, const bn256 *A, int shift);
|
||||
int modp256r1_inv (bn256 *C, const bn256 *a);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define MULADD_256(s_,d_,w_,c_) do { \
|
||||
#define MULADD_256_ASM(s_,d_,w_,c_) \
|
||||
asm ( "ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
"umull r4, r8, %[w], r8 \n\t" \
|
||||
@@ -42,6 +42,9 @@
|
||||
: [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \
|
||||
: "[s]" (s_), "[d]" (d_), [w] "r" (w_) \
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
|
||||
"memory", "cc" ); \
|
||||
*d_ = c_; \
|
||||
"memory", "cc" )
|
||||
|
||||
#define MULADD_256(s__,d__,w__,c__) do { \
|
||||
MULADD_256_ASM(s__,d__,w__,c__); \
|
||||
*d__ = c__; \
|
||||
} while (0)
|
||||
|
||||
757
src/openpgp-do.c
757
src/openpgp-do.c
File diff suppressed because it is too large
Load Diff
313
src/openpgp.c
313
src/openpgp.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -107,6 +107,7 @@ gpg_init (void)
|
||||
file_selection = FILE_NONE;
|
||||
flash_data_start = flash_init ();
|
||||
gpg_data_scan (flash_data_start);
|
||||
flash_init_keys ();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -634,7 +635,7 @@ gpg_get_firmware_update_key (uint8_t keyno)
|
||||
extern uint8_t _updatekey_store;
|
||||
const uint8_t *p;
|
||||
|
||||
p = &_updatekey_store + keyno * KEY_CONTENT_LEN;
|
||||
p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -693,8 +694,8 @@ cmd_read_binary (void)
|
||||
else
|
||||
{
|
||||
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
|
||||
res_APDU_size = KEY_CONTENT_LEN;
|
||||
memcpy (res_APDU, p, KEY_CONTENT_LEN);
|
||||
res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
@@ -808,18 +809,31 @@ cmd_get_data (void)
|
||||
#define ECDSA_HASH_LEN 32
|
||||
#define ECDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
#define EDDSA_HASH_LEN_MAX 256
|
||||
#define EDDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
#define ECC_CIPHER_DO_HEADER_SIZE 7
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
int r = -1;
|
||||
int attr;
|
||||
int pubkey_len;
|
||||
unsigned int result_len = 0;
|
||||
|
||||
DEBUG_INFO (" - PSO: ");
|
||||
DEBUG_WORD ((uint32_t)&r);
|
||||
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a)
|
||||
{
|
||||
attr = gpg_get_algo_attr (GPG_KEY_FOR_SIGNING);
|
||||
pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_SIGNING,
|
||||
GPG_KEY_PUBLIC);
|
||||
|
||||
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
@@ -827,64 +841,85 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RSA_SIG
|
||||
/* Check size of digestInfo */
|
||||
if (len != 34 /* MD5 */
|
||||
&& len != 35 /* SHA1 / RIPEMD-160 */
|
||||
&& len != 47 /* SHA224 */
|
||||
&& len != 51 /* SHA256 */
|
||||
&& len != 67 /* SHA384 */
|
||||
&& len != 83) /* SHA512 */
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
DEBUG_SHORT (len);
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
||||
/* Check size of digestInfo */
|
||||
if (len != 34 /* MD5 */
|
||||
&& len != 35 /* SHA1 / RIPEMD-160 */
|
||||
&& len != 47 /* SHA224 */
|
||||
&& len != 51 /* SHA256 */
|
||||
&& len != 67 /* SHA384 */
|
||||
&& len != 83) /* SHA512 */
|
||||
{
|
||||
DEBUG_INFO (" wrong length");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, pubkey_len);
|
||||
|
||||
result_len = pubkey_len;
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_SIGNING]);
|
||||
if (r < 0)
|
||||
{
|
||||
ac_reset_pso_cds ();
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
&kd[GPG_KEY_FOR_SIGNING], pubkey_len);
|
||||
}
|
||||
#else
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
/* ECDSA with p256r1/p256k1 for signature */
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO (" wrong length");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
else /* ALGO_SECP256K1 */
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
kd[GPG_KEY_FOR_SIGNING].data,
|
||||
kd[GPG_KEY_FOR_SIGNING].data+32,
|
||||
kd[GPG_KEY_FOR_SIGNING].pubkey);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
if (r < 0)
|
||||
{
|
||||
ac_reset_pso_cds ();
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
DEBUG_INFO ("unknown algo.");
|
||||
GPG_FUNCTION_NOT_SUPPORTED ();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
res_APDU_size = result_len;
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
else /* Failure */
|
||||
ac_reset_pso_cds ();
|
||||
}
|
||||
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||
attr = gpg_get_algo_attr (GPG_KEY_FOR_DECRYPTION);
|
||||
pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_DECRYPTION,
|
||||
GPG_KEY_PUBLIC);
|
||||
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, pubkey_len);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
@@ -893,19 +928,54 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip padding 0x00 */
|
||||
len--;
|
||||
if (len != KEY_CONTENT_LEN)
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
/* Skip padding 0x00 */
|
||||
len--;
|
||||
if (len != pubkey_len)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_DECRYPTION], &result_len);
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
int header_size = -1;
|
||||
|
||||
if (len == 65)
|
||||
header_size = 0;
|
||||
else if (len == 65 + ECC_CIPHER_DO_HEADER_SIZE)
|
||||
header_size = ECC_CIPHER_DO_HEADER_SIZE;
|
||||
|
||||
/* Format is in big endian MPI: 04 || x || y */
|
||||
if (header_size < 0 || apdu.cmd_apdu_data[header_size] != 4)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = 65;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header_size, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
else
|
||||
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header_size, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_DECRYPTION]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
DEBUG_INFO ("unknown algo.");
|
||||
GPG_FUNCTION_NOT_SUPPORTED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
res_APDU_size = result_len;
|
||||
}
|
||||
else
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
@@ -918,70 +988,52 @@ cmd_pso (void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#define MAX_DIGEST_INFO_LEN 102 /* 40% */
|
||||
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
int attr = gpg_get_algo_attr (GPG_KEY_FOR_AUTHENTICATION);
|
||||
int pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_AUTHENTICATION,
|
||||
GPG_KEY_PUBLIC);
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
int r = -1;
|
||||
unsigned int result_len = 0;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||
if (P1 (apdu) != 0x00 || P2 (apdu) != 0x00)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
DEBUG_SHORT (len);
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > MAX_DIGEST_INFO_LEN)
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
if (len > MAX_RSA_DIGEST_INFO_LEN)
|
||||
{
|
||||
DEBUG_INFO ("input is too long.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = pubkey_len;
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#else
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
@@ -989,24 +1041,50 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
else if (attr == ALGO_SECP256K1)
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
res_APDU_size = result_len;
|
||||
else
|
||||
GPG_ERROR ();
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define MBD_OPRATION_WRITE 0
|
||||
#define MBD_OPRATION_UPDATE 1
|
||||
@@ -1157,7 +1235,8 @@ cmd_external_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
r = rsa_verify (pubkey, challenge, signature);
|
||||
r = rsa_verify (pubkey, FIRMWARE_UPDATE_KEY_CONTENT_LEN,
|
||||
challenge, signature);
|
||||
random_bytes_free (challenge);
|
||||
challenge = NULL;
|
||||
|
||||
|
||||
71
src/sys.c
71
src/sys.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* sys.c - system routines for the initial page for STM32F103.
|
||||
*
|
||||
* Copyright (C) 2013 Flying Stone Technology
|
||||
* Copyright (C) 2013, 2014 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* Copying and distribution of this file, with or without modification,
|
||||
@@ -24,7 +24,9 @@
|
||||
#define STM32_USB_IRQ_PRIORITY 11
|
||||
|
||||
|
||||
#define STM32_SW_HSI (0 << 0)
|
||||
#define STM32_SW_PLL (2 << 0)
|
||||
#define STM32_PLLSRC_HSI (0 << 16)
|
||||
#define STM32_PLLSRC_HSE (1 << 16)
|
||||
|
||||
#define STM32_PLLXTPRE_DIV1 (0 << 17)
|
||||
@@ -32,6 +34,7 @@
|
||||
|
||||
#define STM32_HPRE_DIV1 (0 << 4)
|
||||
|
||||
#define STM32_PPRE1_DIV1 (0 << 8)
|
||||
#define STM32_PPRE1_DIV2 (4 << 8)
|
||||
|
||||
#define STM32_PPRE2_DIV1 (0 << 11)
|
||||
@@ -44,23 +47,23 @@
|
||||
|
||||
#define STM32_MCO_NOCLOCK (0 << 24)
|
||||
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV2
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_FLASHBITS 0x00000012
|
||||
#define STM32_PLLCLKIN (STM32_HSECLK / 1)
|
||||
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV1
|
||||
#define STM32_ADCPRE STM32_ADCPRE_DIV6
|
||||
#define STM32_MCOSEL STM32_MCO_NOCLOCK
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||
|
||||
#define STM32_PLLCLKIN (STM32_HSECLK / 1)
|
||||
#define STM32_PLLMUL ((STM32_PLLMUL_VALUE - 2) << 18)
|
||||
#define STM32_PLLCLKOUT (STM32_PLLCLKIN * STM32_PLLMUL_VALUE)
|
||||
#define STM32_SYSCLK STM32_PLLCLKOUT
|
||||
#define STM32_HCLK (STM32_SYSCLK / 1)
|
||||
|
||||
#define STM32_FLASHBITS 0x00000012
|
||||
|
||||
struct NVIC {
|
||||
uint32_t ISER[8];
|
||||
uint32_t unused1[24];
|
||||
@@ -92,8 +95,10 @@ nvic_enable_vector (uint32_t n, uint32_t prio)
|
||||
|
||||
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APBPERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
@@ -127,6 +132,18 @@ static struct RCC *const RCC = ((struct RCC *const)RCC_BASE);
|
||||
|
||||
#define RCC_AHBENR_CRCEN 0x0040
|
||||
|
||||
#define RCC_APB2RSTR_AFIORST 0x00000001
|
||||
#define RCC_APB2RSTR_IOPARST 0x00000004
|
||||
#define RCC_APB2RSTR_IOPBRST 0x00000008
|
||||
#define RCC_APB2RSTR_IOPCRST 0x00000010
|
||||
#define RCC_APB2RSTR_IOPDRST 0x00000020
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN 0x00000001
|
||||
#define RCC_APB2ENR_IOPAEN 0x00000004
|
||||
#define RCC_APB2ENR_IOPBEN 0x00000008
|
||||
#define RCC_APB2ENR_IOPCEN 0x00000010
|
||||
#define RCC_APB2ENR_IOPDEN 0x00000020
|
||||
|
||||
struct FLASH {
|
||||
volatile uint32_t ACR;
|
||||
volatile uint32_t KEYR;
|
||||
@@ -149,7 +166,8 @@ clock_init (void)
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
while (!(RCC->CR & RCC_CR_HSIRDY))
|
||||
;
|
||||
RCC->CR &= RCC_CR_HSITRIM | RCC_CR_HSION;
|
||||
/* Reset HSEON, HSEBYP, CSSON, and PLLON, not touching RCC_CR_HSITRIM */
|
||||
RCC->CR &= (RCC_CR_HSITRIM | RCC_CR_HSION);
|
||||
RCC->CFGR = 0;
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
@@ -169,6 +187,10 @@ clock_init (void)
|
||||
RCC->CFGR = STM32_MCOSEL | STM32_USBPRE | STM32_PLLMUL | STM32_PLLXTPRE
|
||||
| STM32_PLLSRC | STM32_ADCPRE | STM32_PPRE2 | STM32_PPRE1 | STM32_HPRE;
|
||||
|
||||
/*
|
||||
* We don't touch RCC->CR2, RCC->CFGR2, RCC->CFGR3, and RCC->CIR.
|
||||
*/
|
||||
|
||||
/* Flash setup */
|
||||
FLASH->ACR = STM32_FLASHBITS;
|
||||
|
||||
@@ -181,18 +203,6 @@ clock_init (void)
|
||||
;
|
||||
}
|
||||
|
||||
#define RCC_APB2RSTR_AFIORST 0x00000001
|
||||
#define RCC_APB2RSTR_IOPARST 0x00000004
|
||||
#define RCC_APB2RSTR_IOPBRST 0x00000008
|
||||
#define RCC_APB2RSTR_IOPCRST 0x00000010
|
||||
#define RCC_APB2RSTR_IOPDRST 0x00000020
|
||||
|
||||
#define RCC_APB2ENR_AFIOEN 0x00000001
|
||||
#define RCC_APB2ENR_IOPAEN 0x00000004
|
||||
#define RCC_APB2ENR_IOPBEN 0x00000008
|
||||
#define RCC_APB2ENR_IOPCEN 0x00000010
|
||||
#define RCC_APB2ENR_IOPDEN 0x00000020
|
||||
|
||||
|
||||
struct AFIO
|
||||
{
|
||||
@@ -231,8 +241,10 @@ struct GPIO {
|
||||
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
|
||||
#define GPIOE ((struct GPIO *) GPIOE_BASE)
|
||||
|
||||
static struct GPIO *const GPIO_USB = ((struct GPIO *const) GPIO_USB_BASE);
|
||||
static struct GPIO *const GPIO_LED = ((struct GPIO *const) GPIO_LED_BASE);
|
||||
#ifdef GPIO_USB_BASE
|
||||
static struct GPIO *const GPIO_USB = ((struct GPIO *const) GPIO_USB_BASE);
|
||||
#endif
|
||||
#ifdef GPIO_OTHER_BASE
|
||||
static struct GPIO *const GPIO_OTHER = ((struct GPIO *const) GPIO_OTHER_BASE);
|
||||
#endif
|
||||
@@ -241,8 +253,8 @@ static void
|
||||
gpio_init (void)
|
||||
{
|
||||
/* Enable GPIO clock. */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOP_EN;
|
||||
RCC->APB2RSTR = RCC_APB2RSTR_IOP_RST;
|
||||
RCC->APB2ENR |= RCC_ENR_IOP_EN;
|
||||
RCC->APB2RSTR = RCC_RSTR_IOP_RST;
|
||||
RCC->APB2RSTR = 0;
|
||||
|
||||
#ifdef AFIO_MAPR_SOMETHING
|
||||
@@ -578,10 +590,13 @@ reset (void)
|
||||
{
|
||||
extern const unsigned long *FT0, *FT1, *FT2;
|
||||
|
||||
/*
|
||||
* This code may not be at the start of flash ROM, because of DFU.
|
||||
* So, we take the address from PC.
|
||||
*/
|
||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
||||
"mov.w r0, #0xed00\n\t" /* r0 = SCR */
|
||||
"movt r0, #0xe000\n\t"
|
||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||
"ldr r0, 1f\n\t" /* r0 = SCR */
|
||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||
"mov r2, #0x1000\n\t"
|
||||
"add r1, r1, r2\n\t"
|
||||
"sub r2, r2, #1\n\t"
|
||||
@@ -590,7 +605,9 @@ reset (void)
|
||||
"ldr r0, [r1], #4\n\t"
|
||||
"msr MSP, r0\n\t" /* Main (exception handler) stack. */
|
||||
"ldr r0, [r1]\n\t" /* Reset handler. */
|
||||
"bx r0\n"
|
||||
"bx r0\n\t"
|
||||
".align 2\n"
|
||||
"1: .word 0xe000ed00"
|
||||
: /* no output */ : /* no input */ : "memory");
|
||||
|
||||
/* Never reach here. */
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* usb-icc.c -- USB CCID protocol handling
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -138,6 +139,7 @@ static uint8_t icc_buffer[USB_BUF_SIZE];
|
||||
#define ICC_SLOT_STATUS 0x65 /* non-ICCD command */
|
||||
#define ICC_SECURE 0x69 /* non-ICCD command */
|
||||
#define ICC_GET_PARAMS 0x6C /* non-ICCD command */
|
||||
#define ICC_RESET_PARAMS 0x6D /* non-ICCD command */
|
||||
#define ICC_XFR_BLOCK 0x6F
|
||||
#define ICC_DATA_BLOCK_RET 0x80
|
||||
#define ICC_SLOT_STATUS_RET 0x81 /* non-ICCD result */
|
||||
@@ -252,7 +254,7 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo,
|
||||
{
|
||||
icc_state_p = &c->icc_state;
|
||||
|
||||
c->icc_state = ICC_STATE_START;
|
||||
c->icc_state = ICC_STATE_NOCARD;
|
||||
c->state = APDU_STATE_WAIT_COMMAND;
|
||||
/*
|
||||
* Note: a is not yet initialized yet, we can't use c->a->cmd_apdu_data here.
|
||||
@@ -467,21 +469,18 @@ static int end_cmd_apdu_head (struct ep_out *epo, size_t orig_len)
|
||||
}
|
||||
|
||||
if (epo->cnt == 4)
|
||||
{
|
||||
/* No Lc and Le */
|
||||
c->a->cmd_apdu_data_len = 0;
|
||||
c->a->expected_res_size = 0;
|
||||
}
|
||||
/* No Lc and Le */
|
||||
c->a->expected_res_size = 0;
|
||||
else if (epo->cnt == 5)
|
||||
{
|
||||
/* No Lc but Le */
|
||||
c->a->cmd_apdu_data_len = 0;
|
||||
c->a->expected_res_size = c->a->cmd_apdu_head[4];
|
||||
if (c->a->expected_res_size == 0)
|
||||
c->a->expected_res_size = 256;
|
||||
c->a->cmd_apdu_head[4] = 0;
|
||||
}
|
||||
|
||||
c->a->cmd_apdu_data_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -516,6 +515,8 @@ static int end_cmd_apdu_data (struct ep_out *epo, size_t orig_len)
|
||||
{
|
||||
/* it has Le field*/
|
||||
c->a->expected_res_size = epo->buf[-1];
|
||||
if (c->a->expected_res_size == 0)
|
||||
c->a->expected_res_size = 256;
|
||||
len--;
|
||||
}
|
||||
else
|
||||
@@ -1178,7 +1179,8 @@ icc_handle_data (struct ccid *c)
|
||||
}
|
||||
}
|
||||
else if (c->icc_header.msg_type == ICC_SET_PARAMS
|
||||
|| c->icc_header.msg_type == ICC_GET_PARAMS)
|
||||
|| c->icc_header.msg_type == ICC_GET_PARAMS
|
||||
|| c->icc_header.msg_type == ICC_RESET_PARAMS)
|
||||
icc_send_params (c);
|
||||
else if (c->icc_header.msg_type == ICC_SECURE)
|
||||
{
|
||||
@@ -1297,6 +1299,8 @@ icc_handle_timeout (struct ccid *c)
|
||||
return next_state;
|
||||
}
|
||||
|
||||
static struct ccid ccid;
|
||||
|
||||
/*
|
||||
* Another Tx done callback
|
||||
*/
|
||||
@@ -1308,8 +1312,6 @@ EP2_IN_Callback (void)
|
||||
|
||||
#define USB_ICC_TIMEOUT (1950*1000)
|
||||
|
||||
static struct ccid ccid;
|
||||
|
||||
#define GPG_THREAD_TERMINATED 0xffff
|
||||
|
||||
static void *ccid_thread (chopstx_t) __attribute__ ((noinline));
|
||||
@@ -1336,6 +1338,8 @@ ccid_card_change_signal (int how)
|
||||
}
|
||||
|
||||
|
||||
#define NOTIFY_SLOT_CHANGE 0x50
|
||||
|
||||
static void * __attribute__ ((noinline))
|
||||
ccid_thread (chopstx_t thd)
|
||||
{
|
||||
@@ -1343,7 +1347,9 @@ ccid_thread (chopstx_t thd)
|
||||
struct ep_out *epo = &endpoint_out;
|
||||
struct ccid *c = &ccid;
|
||||
struct apdu *a = &apdu;
|
||||
int card_change_requested = 0;
|
||||
uint8_t int_msg[2];
|
||||
|
||||
int_msg[0] = NOTIFY_SLOT_CHANGE;
|
||||
|
||||
epi_init (epi, ENDP1, notify_tx, c);
|
||||
epo_init (epo, ENDP1, notify_icc, c);
|
||||
@@ -1359,34 +1365,26 @@ ccid_thread (chopstx_t thd)
|
||||
|
||||
if (m == EV_CARD_CHANGE)
|
||||
{
|
||||
if (card_change_requested)
|
||||
{
|
||||
uint8_t notify_slot_change[2] = { 0x50, 0x02 };
|
||||
|
||||
led_blink (LED_TWOSHOTS);
|
||||
|
||||
if (c->icc_state == ICC_STATE_NOCARD)
|
||||
{ /* Inserted! */
|
||||
c->icc_state = ICC_STATE_START;
|
||||
notify_slot_change[1] |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c->application)
|
||||
{
|
||||
eventflag_signal (&c->openpgp_comm, EV_EXIT);
|
||||
chopstx_join (c->application, NULL);
|
||||
c->application = 0;
|
||||
}
|
||||
|
||||
c->icc_state = ICC_STATE_NOCARD;
|
||||
}
|
||||
|
||||
card_change_requested = 0;
|
||||
usb_lld_write (ENDP2, notify_slot_change, 2);
|
||||
if (c->icc_state == ICC_STATE_NOCARD)
|
||||
{ /* Inserted! */
|
||||
c->icc_state = ICC_STATE_START;
|
||||
int_msg[1] = 0x03;
|
||||
}
|
||||
else
|
||||
card_change_requested = 1;
|
||||
{ /* Removed! */
|
||||
if (c->application)
|
||||
{
|
||||
eventflag_signal (&c->openpgp_comm, EV_EXIT);
|
||||
chopstx_join (c->application, NULL);
|
||||
c->application = 0;
|
||||
}
|
||||
|
||||
c->icc_state = ICC_STATE_NOCARD;
|
||||
int_msg[1] = 0x02;
|
||||
}
|
||||
|
||||
usb_lld_write (ENDP2, int_msg, sizeof int_msg);
|
||||
led_blink (LED_TWOSHOTS);
|
||||
}
|
||||
else if (m == EV_RX_DATA_READY)
|
||||
c->icc_state = icc_handle_data (c);
|
||||
@@ -1444,10 +1442,7 @@ ccid_thread (chopstx_t thd)
|
||||
icc_prepare_receive (c);
|
||||
}
|
||||
else /* Timeout */
|
||||
{
|
||||
c->icc_state = icc_handle_timeout (c);
|
||||
card_change_requested = 0;
|
||||
}
|
||||
c->icc_state = icc_handle_timeout (c);
|
||||
}
|
||||
|
||||
if (c->application)
|
||||
|
||||
@@ -4,6 +4,29 @@
|
||||
#define __USB_CONF_H
|
||||
|
||||
#define NUM_STRING_DESC 7
|
||||
#define ICC_NUM_INTERFACES 1
|
||||
#define ICC_INTERFACE 0
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_NUM_INTERFACES 1
|
||||
#define HID_INTERFACE 1
|
||||
#else
|
||||
#define HID_NUM_INTERFACES 0
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#define VCOM_INTERFACE_0 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES)
|
||||
#define VCOM_INTERFACE_1 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + 1)
|
||||
#else
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#define MSC_INTERFACE (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + VCOM_NUM_INTERFACES)
|
||||
#else
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
|
||||
|
||||
#if defined(USB_SELF_POWERED)
|
||||
#define USB_INITIAL_FEATURE 0xC0 /* bmAttributes: self powered */
|
||||
|
||||
@@ -103,22 +103,12 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#else
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#include "usb-msc.h"
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#else
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#define NUM_INTERFACES (2+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES)
|
||||
#define MSC_INTERFACE_NO (2+VCOM_NUM_INTERFACES)
|
||||
|
||||
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
|
||||
#define USB_HID_REQ_GET_REPORT 1
|
||||
@@ -142,7 +132,7 @@ static uint16_t hid_report;
|
||||
static void
|
||||
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
{
|
||||
if (interface == 0)
|
||||
if (interface == ICC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
@@ -158,7 +148,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (interface == 1)
|
||||
else if (interface == HID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
|
||||
@@ -167,14 +157,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (interface == 2)
|
||||
else if (interface == VCOM_INTERFACE_0)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
|
||||
else
|
||||
usb_lld_stall_tx (ENDP4);
|
||||
}
|
||||
else if (interface == 3)
|
||||
else if (interface == VCOM_INTERFACE_1)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
@@ -190,7 +180,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (interface == MSC_INTERFACE_NO)
|
||||
else if (interface == MSC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
|
||||
@@ -231,8 +221,7 @@ usb_cb_device_reset (void)
|
||||
#define USB_CCID_REQ_GET_CLOCK_FREQUENCIES 0x02
|
||||
#define USB_CCID_REQ_GET_DATA_RATES 0x03
|
||||
|
||||
static const uint8_t freq_table[] = { 0xf3, 0x0d, 0, 0, }; /* dwDefaultClock */
|
||||
|
||||
static const uint8_t freq_table[] = { 0xa0, 0x0f, 0, 0, }; /* dwDefaultClock */
|
||||
static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
|
||||
|
||||
#if defined(PINPAD_DND_SUPPORT)
|
||||
@@ -328,7 +317,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == 0)
|
||||
if (index == ICC_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
{
|
||||
@@ -353,7 +342,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (index == 1)
|
||||
else if (index == HID_INTERFACE)
|
||||
{
|
||||
switch (req_no)
|
||||
{
|
||||
@@ -386,11 +375,11 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (index == 2)
|
||||
else if (index == VCOM_INTERFACE_0)
|
||||
return vcom_port_data_setup (req, req_no, value);
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (index == MSC_INTERFACE_NO)
|
||||
else if (index == MSC_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
{
|
||||
@@ -433,7 +422,7 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == 1 && req_no == USB_HID_REQ_SET_REPORT)
|
||||
if (index == HID_INTERFACE && req_no == USB_HID_REQ_SET_REPORT)
|
||||
{
|
||||
if ((hid_report ^ hid_report_saved) & HID_LED_STATUS_CARDCHANGE)
|
||||
ccid_card_change_signal (CARD_CHANGE_TOGGLE);
|
||||
@@ -465,6 +454,7 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
|
||||
usb_lld_set_configuration (value);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 0);
|
||||
ccid_card_change_signal (CCID_CARD_INIT);
|
||||
bDeviceState = CONFIGURED;
|
||||
}
|
||||
else if (current_conf != value)
|
||||
|
||||
@@ -75,37 +75,27 @@ static const uint8_t gnukDeviceDescriptor[] = {
|
||||
};
|
||||
|
||||
#define ICC_TOTAL_LENGTH (9+9+54+7+7+7)
|
||||
#define ICC_NUM_INTERFACES 1
|
||||
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_TOTAL_LENGTH (9+9+7)
|
||||
#define HID_NUM_INTERFACES 1
|
||||
#else
|
||||
#define HID_TOTAL_LENGTH 0
|
||||
#define HID_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#else
|
||||
#define VCOM_TOTAL_LENGTH 0
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#define MSC_TOTAL_LENGTH (9+7+7)
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#else
|
||||
#define MSC_TOTAL_LENGTH 0
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH \
|
||||
+ VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
|
||||
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
|
||||
|
||||
|
||||
|
||||
/* Configuation Descriptor */
|
||||
@@ -122,7 +112,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0, /* bInterfaceNumber: Index of this interface */
|
||||
ICC_INTERFACE, /* bInterfaceNumber: Index of this interface */
|
||||
0, /* Alternate setting for this interface */
|
||||
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
|
||||
USB_ICC_INTERFACE_CLASS,
|
||||
@@ -135,42 +125,36 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
0x21, /* bDescriptorType: USBDESCR_ICC */
|
||||
0x10, 0x01, /* bcdCCID: revision 1.1 (of CCID) */
|
||||
0, /* bMaxSlotIndex: */
|
||||
1, /* bVoltageSupport: FIXED VALUE */
|
||||
1, /* bVoltageSupport: 5V-only */
|
||||
0x02, 0, 0, 0, /* dwProtocols: T=1 */
|
||||
0xf3, 0x0d, 0, 0, /* dwDefaultClock: 3571 (non-ICCD): 3580 (ICCD) */
|
||||
0xf3, 0x0d, 0, 0, /* dwMaximumClock: 3571 (non-ICCD): 3580 (ICCD) */
|
||||
1, /* bNumClockSupported: FIXED VALUE */
|
||||
0x80, 0x25, 0, 0, /* dwDataRate: 9600: FIXED VALUE */
|
||||
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600: FIXED VALUE */
|
||||
1, /* bNumDataRateSupported: FIXED VALUE */
|
||||
0xa0, 0x0f, 0, 0, /* dwDefaultClock: 4000 */
|
||||
0xa0, 0x0f, 0, 0, /* dwMaximumClock: 4000 */
|
||||
0, /* bNumClockSupported: 0x00 */
|
||||
0x80, 0x25, 0, 0, /* dwDataRate: 9600 */
|
||||
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600 */
|
||||
0, /* bNumDataRateSupported: 0x00 */
|
||||
0xfe, 0, 0, 0, /* dwMaxIFSD: 254 */
|
||||
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
|
||||
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
|
||||
/*
|
||||
* According to Specification for USB ICCD (revision 1.0),
|
||||
* dwFeatures should be 0x00040840.
|
||||
*
|
||||
* It is different now for better interaction to GPG's in-stock
|
||||
* ccid-driver.
|
||||
*/
|
||||
0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
|
||||
* Short APDU level : 0x20000 *
|
||||
* (what? means ICCD?) : 0x00800 *
|
||||
* Automatic IFSD : 0x00400
|
||||
0, 0, 0, 0, /* dwSynchProtocols: 0 */
|
||||
0, 0, 0, 0, /* dwMechanical: 0 */
|
||||
0x7a, 0x04, 0x02, 0x00, /* dwFeatures:
|
||||
* Short and extended APDU level: 0x40000 ----
|
||||
* Short APDU level : 0x20000 *
|
||||
* (ICCD?) : 0x00800 ----
|
||||
* Automatic IFSD : 0x00400 *
|
||||
* NAD value other than 0x00 : 0x00200
|
||||
* Can set ICC in clock stop : 0x00100
|
||||
* Automatic PPS CUR : 0x00080
|
||||
* Automatic PPS PROP : 0x00040 *
|
||||
* Auto baud rate change : 0x00020
|
||||
* Auto clock change : 0x00010
|
||||
* Auto voltage selection : 0x00008
|
||||
* Auto baud rate change : 0x00020 *
|
||||
* Auto clock change : 0x00010 *
|
||||
* Auto voltage selection : 0x00008 *
|
||||
* Auto activaction of ICC : 0x00004
|
||||
* Automatic conf. based on ATR : 0x00002 g
|
||||
* Automatic conf. based on ATR : 0x00002 *
|
||||
*/
|
||||
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
|
||||
0xff, /* bClassGetResponse: */
|
||||
0xff, /* bClassEnvelope: */
|
||||
0, 0, /* wLCDLayout: FIXED VALUE */
|
||||
0xff, /* bClassGetResponse: 0xff */
|
||||
0x00, /* bClassEnvelope: 0 */
|
||||
0, 0, /* wLCDLayout: 0 */
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
|
||||
1, /* bPinSupport: with PIN pad (verify) */
|
||||
@@ -200,14 +184,14 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
0x82, /* bEndpointAddress: (IN2) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
4, 0x00, /* wMaxPacketSize: */
|
||||
0x04, 0x00, /* wMaxPacketSize: 4 */
|
||||
0xFF, /* bInterval (255ms) */
|
||||
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
HID_INTERFACE, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoint used */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
@@ -236,7 +220,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0x02, /* bInterfaceNumber: Number of Interface */
|
||||
VCOM_INTERFACE_0, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
@@ -247,14 +231,13 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
5, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
0x10, 0x01, /* bcdCDC: spec release number */
|
||||
/*Call Managment Functional Descriptor*/
|
||||
5, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x03, /* bmCapabilities: D0+D1 */
|
||||
0x02, /* bDataInterface: 2 */
|
||||
VCOM_INTERFACE_1, /* bDataInterface */
|
||||
/*ACM Functional Descriptor*/
|
||||
4, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
@@ -264,8 +247,8 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
5, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x01, /* bMasterInterface: Communication class interface */
|
||||
0x02, /* bSlaveInterface0: Data Class Interface */
|
||||
VCOM_INTERFACE_0, /* bMasterInterface: Communication class interface */
|
||||
VCOM_INTERFACE_1, /* bSlaveInterface0: Data Class Interface */
|
||||
/*Endpoint 4 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
@@ -277,7 +260,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/*Data class interface descriptor*/
|
||||
9, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
0x03, /* bInterfaceNumber: Number of Interface */
|
||||
VCOM_INTERFACE_1, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
@@ -303,11 +286,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor.*/
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
0x04, /* bInterfaceNumber. */
|
||||
#else
|
||||
0x02, /* bInterfaceNumber. */
|
||||
#endif
|
||||
MSC_INTERFACE, /* bInterfaceNumber. */
|
||||
0x00, /* bAlternateSetting. */
|
||||
0x02, /* bNumEndpoints. */
|
||||
0x08, /* bInterfaceClass (Mass Stprage). */
|
||||
|
||||
@@ -90,50 +90,33 @@ enum DEVICE_STATE
|
||||
};
|
||||
|
||||
|
||||
extern void usb_lld_init (uint8_t feature);
|
||||
|
||||
extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
|
||||
|
||||
extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
|
||||
|
||||
extern void usb_lld_stall_tx (int ep_num);
|
||||
|
||||
extern void usb_lld_stall_rx (int ep_num);
|
||||
|
||||
extern int usb_lld_tx_data_len (int ep_num);
|
||||
|
||||
extern void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
|
||||
|
||||
extern void usb_lld_tx_enable (int ep_num, size_t len);
|
||||
|
||||
extern void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
|
||||
|
||||
extern void usb_lld_rx_enable (int ep_num);
|
||||
|
||||
extern int usb_lld_rx_data_len (int ep_num);
|
||||
|
||||
extern void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
|
||||
|
||||
extern void usb_lld_reset (void);
|
||||
|
||||
extern 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);
|
||||
|
||||
extern void usb_lld_set_configuration (uint8_t config);
|
||||
|
||||
extern uint8_t usb_lld_current_configuration (void);
|
||||
|
||||
extern void usb_lld_set_feature (uint8_t feature);
|
||||
|
||||
extern void usb_lld_set_data_to_send (const void *p, size_t len);
|
||||
void usb_lld_init (uint8_t feature);
|
||||
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
|
||||
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
|
||||
void usb_lld_stall_tx (int ep_num);
|
||||
void usb_lld_stall_rx (int ep_num);
|
||||
int usb_lld_tx_data_len (int ep_num);
|
||||
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
|
||||
void usb_lld_tx_enable (int ep_num, size_t len);
|
||||
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
|
||||
void usb_lld_rx_enable (int ep_num);
|
||||
int usb_lld_rx_data_len (int ep_num);
|
||||
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
|
||||
void usb_lld_reset (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_set_configuration (uint8_t config);
|
||||
uint8_t usb_lld_current_configuration (void);
|
||||
void usb_lld_set_feature (uint8_t feature);
|
||||
void usb_lld_set_data_to_send (const void *p, size_t len);
|
||||
|
||||
extern inline void usb_lld_set_data_to_recv (void *p, size_t len)
|
||||
{
|
||||
usb_lld_set_data_to_send ((const void *)p, len);
|
||||
}
|
||||
|
||||
extern void usb_lld_prepare_shutdown (void);
|
||||
extern void usb_lld_shutdown (void);
|
||||
void usb_lld_prepare_shutdown (void);
|
||||
void usb_lld_shutdown (void);
|
||||
|
||||
extern void usb_interrupt_handler (void);
|
||||
void usb_interrupt_handler (void);
|
||||
|
||||
31
test/ecc_nistp256_keys.py
Normal file
31
test/ecc_nistp256_keys.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Data taken from:
|
||||
# A. Jivsov, Sample Keys and Messages:
|
||||
# https://sites.google.com/site/brainhub/pgpecckeys
|
||||
|
||||
# uid ec_dsa_dh_256 <openpgp@brainhub.org>
|
||||
# sign key:
|
||||
# nistp256/BAA59D9C 2010-09-17
|
||||
# keygrip: 8E06A180EFFE4C65B812150CAF19BF30C0689A4C
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[0] = (0x0bc7a7baebd5f08c74c77b71ee44e7bb0b5a18317b996da5393e33acc52932c6,
|
||||
0xd2f60f4d1efe35a0b9fb8d3787ed4bee97ca012d07b8f5835be7093545d532e6,
|
||||
0xd8f28c530c99821faa5ee2ff4dd8d1df01995d4e98fb45f8768cb65abd4adaa9)
|
||||
|
||||
# decryption key:
|
||||
# sub nistp256/4089AB73 2010-09-17 nistp256
|
||||
# keygrip: E4403F3FD7A443FAC29FEF288FA0D20AC212851E
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[1] = (0x7f70c0a8184cdcaea5db20ba8fed17e47bdefb744d575ec449130af37edade65,
|
||||
0x8ae7ee35d20e8897911c9f564be33d9a94bc1e5c927b1aa07ff750d2d11c2971,
|
||||
0xa05cd14749bea3f3d14c92dc438e45e351efe860360c431705b7d42410581843)
|
||||
|
||||
# auth key from: uid ec_dsa_dh_256_no_pass <openpgp@brainhub.org>
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[2] = (0x81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6,
|
||||
0x5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff,
|
||||
0xa355916f8665eb99c1af48d9560b5c6889e5287bc75aa693aaae9bdb15e8b3fd)
|
||||
|
||||
# This file is here to extend the test suite for ECC.
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
|
||||
28
test/features/003_keyattr_change.feature
Normal file
28
test/features/003_keyattr_change.feature
Normal file
@@ -0,0 +1,28 @@
|
||||
@keyattr
|
||||
Feature: key attribute change
|
||||
In order to use a token with multiple different kind of key algorighm
|
||||
A token should support key attribute change
|
||||
|
||||
Scenario: key attribute data object write: algorithm for signature (RSA-4K)
|
||||
Given cmd_put_data with c1 and "\x01\x10\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
|
||||
Scenario: key attribute data object write: algorithm for signature (RSA-2K)
|
||||
Given cmd_put_data with c1 and "\x01\x08\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
|
||||
Scenario: key attribute data object write: algorithm for decryption (RSA-4K)
|
||||
Given cmd_put_data with c2 and "\x01\x10\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
|
||||
Scenario: key attribute data object write: algorithm for decryption (RSA-2K)
|
||||
Given cmd_put_data with c2 and "\x01\x08\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
|
||||
Scenario: key attribute data object write: algorithm for authentication (RSA-4K)
|
||||
Given cmd_put_data with c3 and "\x01\x10\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
|
||||
Scenario: key attribute data object write: algorithm for authentication (RSA-2K)
|
||||
Given cmd_put_data with c3 and "\x01\x08\x00\x00\x20\x00"
|
||||
Then it should get success
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: \x70\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
|
||||
189
tool/add_openpgp_authkey_from_gpgssh.py
Normal file
189
tool/add_openpgp_authkey_from_gpgssh.py
Normal file
@@ -0,0 +1,189 @@
|
||||
"""
|
||||
add_openpgp_authkey_from_gpgssh.py
|
||||
|
||||
Copyright (C) 2014 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from gpg_agent import gpg_agent
|
||||
from binascii import hexlify, unhexlify
|
||||
from sexp import sexp
|
||||
from time import time
|
||||
from struct import pack, unpack
|
||||
from hashlib import sha1, sha256
|
||||
import re
|
||||
|
||||
ALGO_RSA=1
|
||||
DIGEST_SHA256=8
|
||||
OPENPGP_VERSION=4
|
||||
|
||||
def count_bits(mpi_bytes):
|
||||
return ord(mpi_bytes[0]).bit_length()+(len(mpi_bytes)-1)*8
|
||||
|
||||
class rsa_key(object):
|
||||
def __init__(self, timestamp, n, e):
|
||||
self.__timestamp = timestamp
|
||||
self.__n = n
|
||||
self.__e = e
|
||||
|
||||
def hash_pubkey_key(self, md):
|
||||
hl = 6 + len(self.__n) + 2 + len(self.__e) + 2
|
||||
md.update(pack('>BHBLB', 0x99, hl, 4, self.__timestamp, ALGO_RSA))
|
||||
md.update(pack('>H', count_bits(self.__n)) + self.__n)
|
||||
md.update(pack('>H', count_bits(self.__e)) + self.__e)
|
||||
|
||||
def compose_public_subkey_packet(self):
|
||||
psp = pack('>BLB', OPENPGP_VERSION, self.__timestamp, ALGO_RSA)
|
||||
psp += pack('>H', count_bits(self.__n)) + self.__n
|
||||
psp += pack('>H', count_bits(self.__e)) + self.__e
|
||||
return '\xB9' + pack('>H', len(psp)) + psp
|
||||
|
||||
def compute_keygrip(self):
|
||||
md = sha1("\x00" + self.__n)
|
||||
return md.digest()
|
||||
|
||||
def compute_fpr(self):
|
||||
md = sha1()
|
||||
self.hash_pubkey_key(md)
|
||||
return md.digest()
|
||||
|
||||
def compose_binding_signature_packet(g, primary_key, subkey, sig_timestamp):
|
||||
# Binding signature packet consists of: subpackets of hashed and unhashed
|
||||
# (1) hashed subpacket: this subpacket is the target to calculate digest
|
||||
sig_subp_hashed = pack('>B', 5) + '\x02' + pack('>L', sig_timestamp)
|
||||
sig_subp_hashed += pack('>B', 2) + '\x1b' + '\x20' # Usage AUTH
|
||||
# (2) unhashed subpacket: this subpacket is _not_ the target for digest
|
||||
sig_subp_unhashed = pack('>B', 9) + '\x10' + primary_key.compute_fpr()[-8:]
|
||||
#
|
||||
md = sha256()
|
||||
primary_key.hash_pubkey_key(md)
|
||||
subkey.hash_pubkey_key(md)
|
||||
# Start building binding signature packet, starting OPENPGP_VERSION...
|
||||
sigp = pack('>BBBB', OPENPGP_VERSION, 0x18, ALGO_RSA, DIGEST_SHA256)
|
||||
sigp += pack('>H', len(sig_subp_hashed)) + sig_subp_hashed
|
||||
# And feed it to digest calculator
|
||||
md.update(sigp)
|
||||
md.update(pack('>BBL', OPENPGP_VERSION, 0xff, len(sig_subp_hashed)+6))
|
||||
digest = md.digest()
|
||||
# Then, add unhashed subpacket and first two bytes of digest
|
||||
sigp += pack('>H', len(sig_subp_unhashed)) + sig_subp_unhashed
|
||||
sigp += digest[0:2]
|
||||
print("Digest 2-byte: %s" % hexlify(digest[0:2]))
|
||||
# Ask signing to this digest by the corresponding secret key to PRIMARY_KEY
|
||||
signature = do_sign(g, primary_key, DIGEST_SHA256, digest)
|
||||
# Then, add the signature to the binding signature packet
|
||||
sigp += pack('>H', count_bits(signature)) + signature
|
||||
# Prepending header, it's the binding signature packet
|
||||
return '\x89' + pack('>H', len(sigp)) + sigp
|
||||
|
||||
def build_rsakey_from_ssh_key_under_gpg_agent(g, timestamp=None):
|
||||
# (1) Get the list of available key specifying '--with-ssh'
|
||||
g.send_command("KEYINFO --list --with-ssh --data\n")
|
||||
kl_str = g.get_response()
|
||||
kl_str = kl_str[0:-1]
|
||||
kl = kl_str.split('\n')
|
||||
# (2) Select SSH key(s)
|
||||
kl_ssh = [kg for kg in kl if re.search("S$", kg)] # Select SSH key
|
||||
# (3) Use the first entry of the list (in future, use all???)
|
||||
print("KEYINFO: %s" % kl_ssh[0])
|
||||
# KG: The keygrip of key in question
|
||||
kg = kl_ssh[0].split(' ')[0]
|
||||
# By READKEY command, get the public key information of KG
|
||||
g.send_command("READKEY %s\n" % kg)
|
||||
pubkey_info_str = g.get_response()
|
||||
# The information is in SEXP format, extract N and E
|
||||
s = sexp(pubkey_info_str)
|
||||
if s[0] != 'public-key':
|
||||
print s
|
||||
exit(1)
|
||||
rsa = s[1]
|
||||
if rsa[0] != 'rsa':
|
||||
print rsa
|
||||
exit(1)
|
||||
n_x = rsa[1]
|
||||
if n_x[0] != 'n':
|
||||
print n_x
|
||||
exit(1)
|
||||
n_byte_str = n_x[1]
|
||||
while n_byte_str[0] == '\x00':
|
||||
n_byte_str = n_byte_str[1:]
|
||||
n = n_byte_str
|
||||
e_x = rsa[2]
|
||||
if e_x[0] != 'e':
|
||||
print e_x
|
||||
exit(1)
|
||||
e = e_x[1]
|
||||
if not timestamp:
|
||||
timestamp = int(time())
|
||||
# Compose our RSA_KEY by TIMESTAMP, N, and E
|
||||
return rsa_key(timestamp,n,e)
|
||||
|
||||
BUFSIZE=1024
|
||||
def build_rsakey_from_openpgp_file(filename):
|
||||
f = open(filename, "rb")
|
||||
openpgp_bytes = f.read(BUFSIZE)
|
||||
f.close()
|
||||
header_tag, packet_len, version, timestamp, algo, n_bitlen = \
|
||||
unpack('>BHBLBH', openpgp_bytes[:11])
|
||||
if header_tag != 0x99:
|
||||
print ("openpgp: 0x99 expected (0x%02x)" % header_tag)
|
||||
exit(1)
|
||||
n_len = (n_bitlen + 7) / 8
|
||||
n = openpgp_bytes[11:11+n_len]
|
||||
e_bitlen = unpack('>H', openpgp_bytes[11+n_len:11+n_len+2])[0]
|
||||
e_len = (e_bitlen + 7) / 8
|
||||
e = openpgp_bytes[11+n_len+2:11+n_len+2+e_len]
|
||||
return rsa_key(timestamp,n,e)
|
||||
|
||||
def do_sign(g, pubkey, digest_algo, digest):
|
||||
g.send_command('SIGKEY %s\n' % hexlify(pubkey.compute_keygrip()))
|
||||
if digest_algo == DIGEST_SHA256:
|
||||
g.send_command('SETHASH --hash=sha256 %s\n' % hexlify(digest))
|
||||
else:
|
||||
raise('Unknown digest algorithm', digest_algo)
|
||||
g.send_command('PKSIGN\n')
|
||||
sig_result_str = g.get_response()
|
||||
sig_sexp = sexp(sig_result_str) # [ "sig-val" [ "rsa" [ "s" "xxx" ] ] ]
|
||||
return sig_sexp[1][1][1]
|
||||
|
||||
import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
#
|
||||
filename = sys.argv[1]
|
||||
# Connect to GPG-agent:
|
||||
g = gpg_agent()
|
||||
print("GPG-agent says: %s" % g.read_line())
|
||||
#
|
||||
primary_key = build_rsakey_from_openpgp_file(filename)
|
||||
print("Primary key fingerprint: %s" % hexlify(primary_key.compute_fpr()))
|
||||
print("Primary keygrip: %s" % hexlify(primary_key.compute_keygrip()))
|
||||
#
|
||||
subkey = build_rsakey_from_ssh_key_under_gpg_agent(g)
|
||||
print("Subkey fingerprint: %s" % hexlify(subkey.compute_fpr()))
|
||||
print("Subkey keygrip: %s" % hexlify(subkey.compute_keygrip()))
|
||||
#
|
||||
openpgp_subkey_packet = subkey.compose_public_subkey_packet()
|
||||
openpgp_sig_packet = compose_binding_signature_packet(g, primary_key, subkey, int(time()))
|
||||
# Query to GPG-agent finished
|
||||
g.close()
|
||||
# Append OpenPGP packets to file
|
||||
f = open(filename, "ab")
|
||||
f.write(openpgp_subkey_packet)
|
||||
f.write(openpgp_sig_packet)
|
||||
f.close()
|
||||
@@ -123,15 +123,16 @@ class gnuk_token(object):
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
def download(self, start, data, verbose=False):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x20000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
print("start %08x" % addr)
|
||||
print("end %08x" % addr_end)
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d : %d" % (addr, i, 256)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, 256))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
@@ -141,7 +142,8 @@ class gnuk_token(object):
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, residue))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:],
|
||||
@@ -157,7 +159,7 @@ class gnuk_token(object):
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print msg
|
||||
print(msg)
|
||||
raise ValueError("icc_get_result")
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
@@ -491,15 +493,16 @@ class regnual(object):
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
def download(self, start, data, verbose=False):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x08000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
print("start %08x" % addr)
|
||||
print("end %08x" % addr_end)
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d: %d : %d" % (addr, i, j, 256)
|
||||
if verbose:
|
||||
print("# %08x: %d: %d : %d" % (addr, i, j, 256))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
@@ -510,7 +513,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
print("failure")
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
@@ -521,13 +524,14 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
print("failure")
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, residue))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:],
|
||||
@@ -538,7 +542,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
print("failure")
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
@@ -549,7 +553,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
print("failure")
|
||||
|
||||
def protect(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 4,
|
||||
@@ -561,7 +565,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "protection failure"
|
||||
print("protection failure")
|
||||
|
||||
def finish(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
|
||||
@@ -611,9 +615,9 @@ def get_gnuk_device():
|
||||
for (dev, config, intf) in gnuk_devices():
|
||||
try:
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
print "Device: ", dev.filename
|
||||
print "Configuration: ", config.value
|
||||
print "Interface: ", intf.interfaceNumber
|
||||
print("Device: %s" % dev.filename)
|
||||
print("Configuration: %d" % config.value)
|
||||
print("Interface: %d" % intf.interfaceNumber)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"""
|
||||
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
|
||||
|
||||
Copyright (C) 2012 Free Software Initiative of Japan
|
||||
Copyright (C) 2012, 2015 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -31,354 +31,7 @@ import sys, time, os, binascii, string
|
||||
|
||||
import usb
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
|
||||
def icc_compose(msg_type, data_len, slot, seq, param, data):
|
||||
return pack('<BiBBBH', msg_type, data_len, slot, seq, 0, param) + data
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data, cls=0x00):
|
||||
data_len = len(data)
|
||||
if data_len == 0:
|
||||
return pack('>BBBB', cls, ins, p1, p2)
|
||||
else:
|
||||
return pack('>BBBBB', cls, ins, p1, p2, data_len) + data
|
||||
|
||||
class regnual(object):
|
||||
def __init__(self, dev):
|
||||
conf = dev.configurations[0]
|
||||
intf_alt = conf.interfaces[0]
|
||||
intf = intf_alt[0]
|
||||
if intf.interfaceClass != 0xff:
|
||||
raise ValueError, "Wrong interface class"
|
||||
self.__devhandle = dev.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(conf)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(intf)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
value = 0, index = 0, buffer = 8,
|
||||
timeout = 10000)
|
||||
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x08000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d: %d : %d" % (addr, i, j, 256)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
timeout = 10000)
|
||||
crc32code = crc32(data[j*256:j*256+256])
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.010)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:],
|
||||
timeout = 10000)
|
||||
crc32code = crc32(data[j*256:].ljust(256,chr(255)))
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.010)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
|
||||
def protect(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 4,
|
||||
value = 0, index = 0, buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.100)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "protection failure"
|
||||
|
||||
def finish(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
|
||||
value = 0, index = 0, buffer = None,
|
||||
timeout = 10000)
|
||||
|
||||
def reset_device(self):
|
||||
try:
|
||||
self.__devhandle.reset()
|
||||
except:
|
||||
pass
|
||||
|
||||
# This class only supports Gnuk (for now)
|
||||
class gnuk_token(object):
|
||||
def __init__(self, device, configuration, interface):
|
||||
"""
|
||||
__init__(device, configuration, interface) -> None
|
||||
Initialize the device.
|
||||
device: usb.Device object.
|
||||
configuration: configuration number.
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != CCID_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
if interface.interfaceSubClass != CCID_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
self.__devhandle = device.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
self.__conf = configuration
|
||||
|
||||
self.__bulkout = 1
|
||||
self.__bulkin = 0x81
|
||||
|
||||
self.__timeout = 10000
|
||||
self.__seq = 0
|
||||
|
||||
def reset_device(self):
|
||||
try:
|
||||
self.__devhandle.reset()
|
||||
except:
|
||||
pass
|
||||
|
||||
def stop_gnuk(self):
|
||||
self.__devhandle.releaseInterface()
|
||||
self.__devhandle.setConfiguration(0)
|
||||
return
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
value = 0, index = 0, buffer = 8,
|
||||
timeout = 10)
|
||||
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x20000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d : %d" % (addr, i, 256)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
timeout = 10)
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:],
|
||||
timeout = 10)
|
||||
|
||||
def execute(self, last_addr):
|
||||
i = (last_addr - 0x20000000) / 0x100
|
||||
o = (last_addr - 0x20000000) % 0x100
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 2,
|
||||
value = i, index = o, buffer = None,
|
||||
timeout = 10)
|
||||
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
raise ValueError, "icc_get_result"
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data)
|
||||
|
||||
def icc_get_status(self):
|
||||
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_power_on(self):
|
||||
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check status, chain
|
||||
return data # ATR
|
||||
|
||||
def icc_power_off(self):
|
||||
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_send_data_block(self, data):
|
||||
msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data)
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
return self.icc_get_result()
|
||||
|
||||
def icc_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.icc_send_data_block(data)
|
||||
if chain == 0:
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data_rcv = self.icc_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd chain"
|
||||
return d
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd"
|
||||
|
||||
def cmd_get_response(self, expected_len):
|
||||
cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len)
|
||||
response = self.icc_send_cmd(cmd_data)
|
||||
return response[:-2]
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, sw
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def cmd_external_authenticate(self, signed):
|
||||
cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[0:128], cls=0x10)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[128:])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def cmd_get_challenge(self):
|
||||
cmd_data = iso7816_compose(0x84, 0x00, 0x00, '')
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if sw[0] != 0x61:
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
return self.cmd_get_response(sw[1])
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
i = 0
|
||||
for d in data_original:
|
||||
if ord(d) != data_in_device[i]:
|
||||
raise ValueError, "verify failed at %08x" % i
|
||||
i += 1
|
||||
|
||||
def ccid_devices():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
if alt.interfaceClass == CCID_CLASS and \
|
||||
alt.interfaceSubClass == CCID_SUBCLASS and \
|
||||
alt.interfaceProtocol == CCID_PROTOCOL_0:
|
||||
yield dev, config, alt
|
||||
|
||||
USB_VENDOR_FSIJ=0x234b
|
||||
USB_PRODUCT_GNUK=0x0000
|
||||
|
||||
def gnuk_devices():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
if dev.idVendor != USB_VENDOR_FSIJ:
|
||||
continue
|
||||
if dev.idProduct != USB_PRODUCT_GNUK:
|
||||
continue
|
||||
yield dev
|
||||
from gnuk_token import *
|
||||
|
||||
def to_string(t):
|
||||
result = ""
|
||||
@@ -420,24 +73,17 @@ def gpg_sign(keygrip, hash):
|
||||
pos = signed.index("D ") + 2
|
||||
signed = signed[pos:-4] # \nOK\n
|
||||
if len(signed) != 256:
|
||||
raise ValueError, binascii.hexlify(signed)
|
||||
raise ValueError(binascii.hexlify(signed))
|
||||
return signed
|
||||
|
||||
def UNSIGNED(n):
|
||||
return n & 0xffffffff
|
||||
|
||||
def crc32(bytestr):
|
||||
crc = binascii.crc32(bytestr)
|
||||
return UNSIGNED(crc)
|
||||
|
||||
def main(keygrip, data_regnual, data_upgrade):
|
||||
def main(keyno,keygrip, data_regnual, data_upgrade):
|
||||
l = len(data_regnual)
|
||||
if (l & 0x03) != 0:
|
||||
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
|
||||
crc32code = crc32(data_regnual)
|
||||
print "CRC32: %04x\n" % crc32code
|
||||
data_regnual += pack('<I', crc32code)
|
||||
for (dev, config, intf) in ccid_devices():
|
||||
for (dev, config, intf) in gnuk_devices():
|
||||
try:
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
print "Device: ", dev.filename
|
||||
@@ -447,13 +93,13 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
except:
|
||||
icc = None
|
||||
if icc.icc_get_status() == 2:
|
||||
raise ValueError, "No ICC present"
|
||||
raise ValueError("No ICC present")
|
||||
elif icc.icc_get_status() == 1:
|
||||
icc.icc_power_on()
|
||||
icc.cmd_select_openpgp()
|
||||
challenge = icc.cmd_get_challenge()
|
||||
signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge)))
|
||||
icc.cmd_external_authenticate(signed)
|
||||
icc.cmd_external_authenticate(keyno, signed)
|
||||
icc.stop_gnuk()
|
||||
mem_info = icc.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
@@ -471,7 +117,7 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
time.sleep(3)
|
||||
# Then, send upgrade program...
|
||||
reg = None
|
||||
for dev in gnuk_devices():
|
||||
for dev in gnuk_devices_by_vidpid():
|
||||
try:
|
||||
reg = regnual(dev)
|
||||
print "Device: ", dev.filename
|
||||
@@ -489,6 +135,7 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyno = 0
|
||||
keygrip = None
|
||||
if sys.argv[1] == '-k':
|
||||
sys.argv.pop(1)
|
||||
@@ -504,4 +151,4 @@ if __name__ == '__main__':
|
||||
data_upgrade = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_upgrade, len(data_upgrade))
|
||||
main(keygrip, data_regnual, data_upgrade[4096:])
|
||||
main(keyno, keygrip, data_regnual, data_upgrade[4096:])
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token
|
||||
which is just shipped from factory
|
||||
|
||||
Copyright (C) 2012, 2013 Free Software Initiative of Japan
|
||||
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -37,7 +37,7 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
if (l & 0x03) != 0:
|
||||
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
|
||||
crc32code = crc32(data_regnual)
|
||||
print "CRC32: %04x\n" % crc32code
|
||||
print("CRC32: %04x\n" % crc32code)
|
||||
data_regnual += pack('<I', crc32code)
|
||||
|
||||
rsa_key = rsa.read_key_from_file('rsa_example.key')
|
||||
@@ -55,11 +55,11 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
gnuk.cmd_external_authenticate(keyno, signed_bytes)
|
||||
gnuk.stop_gnuk()
|
||||
mem_info = gnuk.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
print("%08x:%08x" % mem_info)
|
||||
|
||||
print "Downloading flash upgrade program..."
|
||||
print("Downloading flash upgrade program...")
|
||||
gnuk.download(mem_info[0], data_regnual)
|
||||
print "Run flash upgrade program..."
|
||||
print("Run flash upgrade program...")
|
||||
gnuk.execute(mem_info[0] + len(data_regnual) - 4)
|
||||
#
|
||||
time.sleep(3)
|
||||
@@ -67,51 +67,56 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
del gnuk
|
||||
gnuk = None
|
||||
#
|
||||
print "Wait 3 seconds..."
|
||||
print("Wait 3 seconds...")
|
||||
time.sleep(3)
|
||||
# Then, send upgrade program...
|
||||
reg = None
|
||||
for dev in gnuk_devices_by_vidpid():
|
||||
try:
|
||||
reg = regnual(dev)
|
||||
print "Device: ", dev.filename
|
||||
print("Device: %s" % dev.filename)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
mem_info = reg.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
print "Downloading the program"
|
||||
print("%08x:%08x" % mem_info)
|
||||
print("Downloading the program")
|
||||
reg.download(mem_info[0], data_upgrade)
|
||||
reg.protect()
|
||||
reg.finish()
|
||||
reg.reset_device()
|
||||
return 0
|
||||
|
||||
from getpass import getpass
|
||||
|
||||
if __name__ == '__main__':
|
||||
if os.getcwd() != os.path.dirname(os.path.abspath(__file__)):
|
||||
print "Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__))
|
||||
print("Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__)))
|
||||
exit(1)
|
||||
|
||||
passwd = DEFAULT_PW3
|
||||
keyno = 0
|
||||
passwd = None
|
||||
while len(sys.argv) > 3:
|
||||
option = sys.argv[1]
|
||||
sys.argv.pop(1)
|
||||
if option == '-p':
|
||||
from getpass import getpass
|
||||
passwd = getpass("Admin password: ")
|
||||
elif option == '-k':
|
||||
if option == '-f': # F for Factory setting
|
||||
passwd = DEFAULT_PW3
|
||||
elif option == '-k': # K for Key number
|
||||
keyno = int(sys.argv[1])
|
||||
sys.argv.pop(1)
|
||||
else:
|
||||
raise ValueError("unknown option", option)
|
||||
if not passwd:
|
||||
passwd = getpass("Admin password: ")
|
||||
filename_regnual = sys.argv[1]
|
||||
filename_upgrade = sys.argv[2]
|
||||
f = open(filename_regnual)
|
||||
data_regnual = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_regnual, len(data_regnual))
|
||||
print("%s: %d" % (filename_regnual, len(data_regnual)))
|
||||
f = open(filename_upgrade)
|
||||
data_upgrade = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_upgrade, len(data_upgrade))
|
||||
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
|
||||
# First 4096-byte in data_upgrade is SYS, so, skip it.
|
||||
main(keyno, passwd, data_regnual, data_upgrade[4096:])
|
||||
|
||||
Reference in New Issue
Block a user