Compare commits
95 Commits
polarssl-f
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
fb8cb58c5c | ||
|
|
db2187835c | ||
|
|
653868c00b | ||
|
|
ede98fbe7e | ||
|
|
2accc339e2 | ||
|
|
9feeeb308b | ||
|
|
01806c2e5e | ||
|
|
a32f577dfa | ||
|
|
deaf340687 | ||
|
|
f5e8e94bf7 | ||
|
|
df4e8c5481 | ||
|
|
888eb2aa31 | ||
|
|
1436223320 | ||
|
|
13a52a0862 | ||
|
|
ea73e1ee7e | ||
|
|
8ca0416be8 | ||
|
|
d42eba5cb0 | ||
|
|
60820f5a5f | ||
|
|
2c8f1cb0ce | ||
|
|
2e80472f1c | ||
|
|
8f60b1568f | ||
|
|
91ca2d9827 | ||
|
|
6d2f9f8df1 | ||
|
|
42251eea8e | ||
|
|
fc5df5019f | ||
|
|
e18df3af6b | ||
|
|
4b65ed1a5b | ||
|
|
f4e10311c7 | ||
|
|
78ffb4179e | ||
|
|
36541838f9 | ||
|
|
29e76d0ba7 | ||
|
|
c29bd10555 | ||
|
|
5c01e92c20 | ||
|
|
94508ae5d9 | ||
|
|
251760d5da | ||
|
|
6a69c31c3b | ||
|
|
486f20bfd4 | ||
|
|
8d05addc87 | ||
|
|
9f0e2eabd1 | ||
|
|
f21a89588c | ||
|
|
af66c5fa08 | ||
|
|
0e7078bacb | ||
|
|
df8434db59 | ||
|
|
80d935d913 | ||
|
|
007eada502 | ||
|
|
3bb3c6e9d8 | ||
|
|
4f154cc61d | ||
|
|
38f8b91335 | ||
|
|
b35765d58b | ||
|
|
932e6acd40 | ||
|
|
62863d52b2 | ||
|
|
26db39b1b7 | ||
|
|
1774563184 | ||
|
|
a89ae40e89 | ||
|
|
4427227284 | ||
|
|
141d345cfe | ||
|
|
cc7221e5cb | ||
|
|
34fe062548 | ||
|
|
72e67d81a3 | ||
|
|
e8896ecb4d |
308
ChangeLog
308
ChangeLog
@@ -1,7 +1,315 @@
|
||||
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.
|
||||
|
||||
2014-02-25 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_do_public_key): Don't put OID.
|
||||
|
||||
* src/configure [certdo] (gnuk.ld): Add TIM_SIZE and EXT_SIZE.
|
||||
Thanks to Vasily Evseenko for the bug report.
|
||||
|
||||
2014-02-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc.c (compute_kG): Compute higer index at first.
|
||||
(point_is_on_the_curve): Don't use coefficient_a if it's zero.
|
||||
|
||||
* src/jpc.c (jpc_double): Care coefficient A.
|
||||
|
||||
* src/ec_p256r1.c (COEFFICIENT_A_IS_MINUS_3): New.
|
||||
* src/ec_p256k1.c (COEFFICIENT_A_IS_ZERO): New.
|
||||
* src/jpc_p256r1.c (COEFFICIENT_A_IS_MINUS_3): Likewise.
|
||||
* src/jpc_p256k1.c (COEFFICIENT_A_IS_MINUS_3): Likewise.
|
||||
|
||||
* src/modp256k1.c (modp256k1_shift): Bug fix.
|
||||
|
||||
2014-02-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/Makefile.in (CSRC): Add files of p256k1.
|
||||
|
||||
* src/openpgp.c (cmd_pso): Support p256k1 for signature.
|
||||
|
||||
* src/openpgp-do.c (algorithm_attr_p256k1): New.
|
||||
(gpg_do_write_prvkey): Support p256k1 for signature.
|
||||
(proc_key_import, gpg_do_table, gpg_do_public_key): Likewise.
|
||||
|
||||
* src/Makefile.in (DEFS): Add -DRSA_SIG.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_write_prvkey): Use _p256r1.
|
||||
* src/openpgp.c (cmd_internal_authenticate): Likewise.
|
||||
|
||||
* src/call-ec_p256k1.c: New. Use call-ec.c.
|
||||
* src/call-ec_p256r1.c: Use call-ec.c.
|
||||
* src/call-ec.c: New.
|
||||
(ecdsa_sign): Change the signature.
|
||||
|
||||
2014-02-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* tool/calc_precompute_table_ecc.py: New.
|
||||
|
||||
* src/ec_p256k1.c: New. Use ecc.c.
|
||||
* src/ec_p256k1.h: New.
|
||||
* src/ec_p256r1.c: Use ecc.c.
|
||||
* src/ecc.c: New.
|
||||
|
||||
2014-02-18 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/jpc_p256k1.c: New. Use jpc.c.
|
||||
* src/jpc_p256r1.c: Use jpc.c.
|
||||
* src/jpc.c: New.
|
||||
|
||||
* src/sha256.c (memcpy_output_bswap32): Bug fix.
|
||||
|
||||
* src/modp256k1.h, src/modp256k1.c: New.
|
||||
|
||||
2014-02-17 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/Makefile.in (CSRC): Follow the changes of filenames.
|
||||
|
||||
* src/modp256r1.c (modp256r1_add, modp256r1_sub, S3)
|
||||
(modp256r1_mul, modp256r1_sqr, modp256r1_inv, modp256r1_shift):
|
||||
Use new function names.
|
||||
* src/jpc_p256r1.c (jpc_double_p256r1, jpc_add_ac_signed_p256r1)
|
||||
(jpc_to_ac_p256r1): Likewise.
|
||||
* src/ec_p256r1.c (point_is_on_the_curve)
|
||||
(compute_kG_p256r1, compute_kP_p256r1): Likewise.
|
||||
* src/call-ec_p256r1.c (ecdsa_sign): Likewise.
|
||||
|
||||
* src/modp256r1.h: Rename from modp256.h.
|
||||
* src/jpc-ac_p256r1.h: Rename from jpc-ac.h.
|
||||
* src/ec_p256r1.h: Rename from ec_p256.h.
|
||||
|
||||
* src/modp256r1.c: Rename from modp256.c.
|
||||
* src/jpc_p256r1.c: Rename from jpc.c.
|
||||
* src/ec_p256r1.c: Rename from ec_p256.c.
|
||||
* src/call-ec_p256r1.c: Rename from call-ec_p256.c.
|
||||
|
||||
2014-02-05 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/sha512.h, src/sha512.c: New.
|
||||
|
||||
* src/sha256.c (initial_state): Don't export, it's internal.
|
||||
(memcpy_output_bswap32): Rename and remove last argument.
|
||||
|
||||
2014-01-28 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/muladd_256.h: New.
|
||||
* src/bn.c (bn256_mul, bn256_sqr): Assembler implementation.
|
||||
|
||||
* src/ec_p256.c (get_vk_kP): Bug fix.
|
||||
(compute_kP): Bug fix for index table.
|
||||
|
||||
2014-01-27 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ec_p256.c (get_vk_kP): New.
|
||||
(naf4_257_set, naf4_257_get, compute_naf4_257): Remove.
|
||||
(compute_kP): Change the argument, fixing for constant time.
|
||||
|
||||
2014-01-24 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ec_p256.c (get_vk): New.
|
||||
(compute_kG): Fix for constant time.
|
||||
(compute_kP): Simplify.
|
||||
|
||||
2014-01-23 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/jpc.c (jpc_add_ac_signed): Fix for constant time.
|
||||
|
||||
* src/ec_p256.c (ecdsa): Bug fix for k selection.
|
||||
|
||||
2014-01-22 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/modp256.c (modp256_inv): Fix for constant time.
|
||||
|
||||
* src/bn.c (bn256_sqr): Fix for constant time.
|
||||
|
||||
* src/mod.c (mod_inv): Fix for constant time.
|
||||
|
||||
* src/ec_p256.c (compute_kG): Simplify.
|
||||
|
||||
* src/jpc.c (jpc_double): Support calling with A = infinity.
|
||||
|
||||
2014-01-21 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/jpc.c (jpc_add_ac_signed): Bug fix for A check.
|
||||
|
||||
* src/ec_p256.c (ecdsa): Fix for constant time.
|
||||
|
||||
* src/modp256.c (modp256_add, modp256_sub, modp256_reduce)
|
||||
(modp256_shift): Fix for constant time.
|
||||
(modp256_inv): Likewise (not fully constant time, yet).
|
||||
|
||||
* src/mod.c (mod_reduce): Fix for constant time.
|
||||
(mod_inv): Likewise (not fully constant time, yet).
|
||||
|
||||
* src/bn.h (bn256, bn512): words -> word.
|
||||
* src/ec_p256.h (naf4_257): Likewise.
|
||||
|
||||
2014-01-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/fe25519.h, src/fe25519.c: New.
|
||||
|
||||
2014-01-15 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/bn.c (bn256_is_zero, bn256_is_ge, bn256_cmp): Computation
|
||||
should be constant time.
|
||||
|
||||
2013-12-25 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.1.
|
||||
|
||||
* tool/gnuk_token.py (gnuk_token.__init__, regnual.__init__): Fix
|
||||
the argument of setAltInterface.
|
||||
* tool/gnuk_upgrade.py: Likewise.
|
||||
* tool/dfuse.py (DFU_STM32.__init__): Likewise.
|
||||
* tool/stlinkv2.py (stlinkv2.__init__): Likewise.
|
||||
|
||||
2013-12-24 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* polarssl/include/polarssl/bn_mul.h (MULADDC_1024_CORE)
|
||||
(MULADDC_1024_LOOP): Use younger number registers more for shorter
|
||||
instructions and better performance.
|
||||
* polarssl/library/bignum.c (mpi_montsqr): Likewise. Change loop
|
||||
structure and conditional branch for better performance.
|
||||
|
||||
2013-12-23 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* polarssl/library/bignum.c (mpi_montmul): Computation
|
||||
time should not depends on input.
|
||||
(mpi_montmul, mpi_montred, mpi_montsqr): Change the API.
|
||||
(mpi_exp_mod): Follow the change of the API. Allocate memory on
|
||||
stack instead of malloc.
|
||||
|
||||
* src/gnuk.ld.in (__process3_stack_size__): Increase stack size.
|
||||
|
||||
2013-12-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
|
||||
33
NEWS
33
NEWS
@@ -1,5 +1,38 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
* 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
|
||||
|
||||
** Experimental ECC support for secp256k1.
|
||||
After configure, you can edit the DEFS variable in src/Makefile, so
|
||||
that Gnuk can support ECDSA with NIST P256 (for authentication), and
|
||||
ECDSA with secp256k1 (for signature). Note that this is pretty much
|
||||
experimental, and subjects to change.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.1
|
||||
|
||||
Released 2013-12-25, by NIIBE Yutaka
|
||||
|
||||
** Tools and test suite now work with PyUSB 1.0, too.
|
||||
It only worked with PyUSB 0.4.3, but it works with PyUSB 1.0 too.
|
||||
|
||||
** Improved RSA routine
|
||||
Working memory for RSA computation is taken from stack instead of
|
||||
malloc (mostly).
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.0
|
||||
|
||||
Released 2013-12-20, by NIIBE Yutaka
|
||||
|
||||
48
README
48
README
@@ -1,18 +1,23 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.1.0
|
||||
2013-12-20
|
||||
Version 1.1.3
|
||||
2014-04-16
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Warning
|
||||
=======
|
||||
|
||||
This is an experimental release of Gnuk 1.1.0, 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.
|
||||
This is another experimental release of Gnuk, version 1.1.3, 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 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.
|
||||
|
||||
|
||||
What's Gnuk?
|
||||
@@ -52,7 +57,8 @@ A0: Good points of Gnuk are:
|
||||
"for Free Software"; Gnuk supports GnuPG.
|
||||
|
||||
Q1: What kind of key algorithm is supported?
|
||||
A1: Gnuk version 1 only supports 2048-bit RSA.
|
||||
A1: Gnuk version 1.0 only supports 2048-bit RSA.
|
||||
Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so.
|
||||
@@ -122,11 +128,14 @@ Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
|
||||
Release notes
|
||||
=============
|
||||
|
||||
This is an experimental release in version 1.1 series of Gnuk.
|
||||
This is third experimental release in version 1.1 series of Gnuk.
|
||||
|
||||
While it is daily use for a year and a half, some newly introduced
|
||||
features (including key generation and firmware upgrade) should be
|
||||
considered experimental.
|
||||
While it is daily use by its developer, some newly introduced features
|
||||
(including ECDSA/EdDSA, key generation and firmware upgrade) should be
|
||||
considered experimental. ECDSA/EdDSA is really experimental. The
|
||||
feature even requires manual edit of Makefile after 'configure'.
|
||||
More, EdDSA is much experimental. You won't be able to keep using
|
||||
the EdDSA key, as it is subject to change.
|
||||
|
||||
Tested features are:
|
||||
|
||||
@@ -218,7 +227,7 @@ External source code
|
||||
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* chopstx/ -- Chopstx 0.04
|
||||
* chopstx/ -- Chopstx 0.03 (+ STBee support)
|
||||
|
||||
We use Chopstx as the kernel for Gnuk.
|
||||
|
||||
@@ -465,7 +474,7 @@ How to configure
|
||||
================
|
||||
|
||||
You need python and pyscard (python-pyscard package in Debian) or
|
||||
PyUSB (python-usb package in Debian).
|
||||
PyUSB 0.4.3 (python-usb package in Debian).
|
||||
|
||||
(1) [pyscard] Stop scdaemon
|
||||
[PyUSB] Stop the pcsc daemon.
|
||||
@@ -581,10 +590,19 @@ Git Repositories
|
||||
|
||||
Please use: http://gitorious.org/gnuk
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://gitorious.org/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
|
||||
|
||||
We migrated from ChibiOS/RT to Chopstix. If you have old code of
|
||||
I put Chopstx as a submodule of Git. Please do this:
|
||||
|
||||
$ git submodule init
|
||||
$ git submodule update
|
||||
|
||||
We have migrated from ChibiOS/RT to Chopstx. If you have old code of
|
||||
ChibiOS/RT, you need:
|
||||
|
||||
Edit .git/config to remove chibios reference
|
||||
|
||||
1
THANKS
1
THANKS
@@ -19,4 +19,5 @@ NAGAMI Takeshi nagami-takeshi@aist.go.jp
|
||||
Nguyễn Hồng Quân quannguyen@mbm.vn
|
||||
Paul Bakker polarssl_maintainer@polarssl.org
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
Vasily Evseenko
|
||||
Werner Koch wk@gnupg.org
|
||||
|
||||
@@ -38,7 +38,7 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
There is "gcc-arm-embedded" project. See:
|
||||
https://launchpad.net/gcc-arm-embedded/
|
||||
|
||||
It is based on GCC 4.7 (as of October, 2013). We are using "-O3 -Os"
|
||||
It is based on GCC 4.8 (as of December, 2013). We are using "-O3 -Os"
|
||||
for compiler option.
|
||||
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ Then, GnuPG generate keys. It takes some time. ::
|
||||
Not enough random bytes available. Please do some other work to give
|
||||
the OS a chance to collect more entropy! (Need 15 more bytes)
|
||||
...+++++
|
||||
gpg: key 28C0CD7C marked as ultimately trusted
|
||||
gpg: key 4CA7BABE marked as ultimately trusted
|
||||
public and secret key created and signed.
|
||||
|
||||
gpg: checking the trustdb
|
||||
|
||||
@@ -44,7 +44,6 @@ and type ``1`` to say it's signature key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Really move the primary key? (y/N) y
|
||||
gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00'
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
@@ -56,7 +56,6 @@ and type ``1`` to say it's signature key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Really move the primary key? (y/N) y
|
||||
gpg: detected reader `FSIJ Gnuk (0.12-38FF6A06) 00 00'
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
@@ -28,27 +28,38 @@ Set up PW1, PW3 and reset code
|
||||
Invoke GnuPG with the option ``--card-edit``. ::
|
||||
|
||||
$ gpg --card-edit
|
||||
gpg: detected reader `FSIJ Gnuk (0.12-34006E06) 00 00'
|
||||
Application ID ...: D276000124010200F517000000010000
|
||||
Version ..........: 2.0
|
||||
Manufacturer .....: FSIJ
|
||||
Serial number ....: 00000001
|
||||
Name of cardholder: [not set]
|
||||
Language prefs ...: [not set]
|
||||
Sex ..............: unspecified
|
||||
URL of public key : [not set]
|
||||
Login data .......: [not set]
|
||||
Signature PIN ....: forced
|
||||
Name of cardholder: Yutaka Niibe
|
||||
Language prefs ...: ja
|
||||
Sex ..............: male
|
||||
URL of public key : http://www.gniibe.org/gniibe.asc
|
||||
Login data .......: gniibe
|
||||
Signature PIN ....: not forced
|
||||
Key attributes ...: 2048R 2048R 2048R
|
||||
Max. PIN lengths .: 127 127 127
|
||||
PIN retry counter : 3 3 3
|
||||
Signature counter : 0
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
General key info..: [none]
|
||||
Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
|
||||
created ....: 2010-10-15 06:46:33
|
||||
Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF
|
||||
created ....: 2010-10-15 06:46:33
|
||||
Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC
|
||||
created ....: 2010-10-22 06:06:36
|
||||
General key info..:
|
||||
pub 2048R/4CA7BABE 2010-10-15 NIIBE Yutaka <gniibe@fsij.org>
|
||||
sec> 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb> 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb> 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
card-no: F517 00000001
|
||||
|
||||
It shows the status of the card (as same as the output of ``gpg --card-status``). It shows token's name and its USB serial string (0.12-34006E06) from PC/SC-lite.
|
||||
gpg/card>
|
||||
|
||||
It shows the status of the card (as same as the output of ``gpg --card-status``).
|
||||
|
||||
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``.
|
||||
|
||||
@@ -83,8 +94,13 @@ please change admin-password at first.
|
||||
Then, the token works as same as OpenPGPcard specification
|
||||
with regards to PW1 and PW3.)
|
||||
|
||||
Lastly, I setup reset code. This is optional. ::
|
||||
Lastly, I setup reset code, entering admin mode.
|
||||
Having reset code, you can unblock PIN when the token will be blocked
|
||||
(by wrong attempt to entering PIN). This is optional step. ::
|
||||
|
||||
gpg/card> admin
|
||||
Admin commands are allowed
|
||||
|
||||
gpg/card> passwd
|
||||
gpg: OpenPGP card no. D276000124010200F517000000010000 detected
|
||||
|
||||
|
||||
@@ -9,11 +9,10 @@ Personalize your Gnuk Token
|
||||
Invoke GnuPG with the option ``--card-edit``. ::
|
||||
|
||||
$ gpg --card-edit
|
||||
gpg: detected reader `FSIJ Gnuk (0.12-34006E06) 00 00'
|
||||
Application ID ...: D276000124010200F517000000010000
|
||||
Application ID ...: D276000124010200FFFE330069060000
|
||||
Version ..........: 2.0
|
||||
Manufacturer .....: FSIJ
|
||||
Serial number ....: 00000001
|
||||
Manufacturer .....: unmanaged S/N range
|
||||
Serial number ....: 33006906
|
||||
Name of cardholder: [not set]
|
||||
Language prefs ...: [not set]
|
||||
Sex ..............: unspecified
|
||||
@@ -28,8 +27,10 @@ Invoke GnuPG with the option ``--card-edit``. ::
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
General key info..: [none]
|
||||
|
||||
gpg/card>
|
||||
|
||||
It shows the status of the card (as same as the output of ``gpg --card-status``). It shows token's name and its USB serial string (0.12-34006E06) from PC/SC-lite.
|
||||
It shows the status of the card (as same as the output of ``gpg --card-status``).
|
||||
|
||||
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg/card>``.
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ Host prerequisites for using Gnuk Token
|
||||
|
||||
* [Optional] PC/SC lite (pcscd, libccid)
|
||||
|
||||
* SSH: openssh
|
||||
* [Optional] SSH: openssh
|
||||
|
||||
* [optional] Web: scute, firefox
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ It is important to collect enough entropy. Perhaps, it would
|
||||
be possible to get entropy from USB traffic (of other devices).
|
||||
|
||||
|
||||
* RSA
|
||||
* [Mostly DONE] RSA
|
||||
|
||||
It would be good not to use malloc.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +18,6 @@ key reference (to the token) in ``.gnupg``.
|
||||
To do that, invoke GnuPG with ``--card-edit`` option. ::
|
||||
|
||||
$ gpg --card-edit
|
||||
gpg: detected reader `FSIJ Gnuk (0.12-37006A06) 00 00'
|
||||
Application ID ...: D276000124010200F517000000010000
|
||||
Version ..........: 2.0
|
||||
Manufacturer .....: FSIJ
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -496,64 +496,64 @@
|
||||
|
||||
#if defined(__arm__)
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %0!, { r5, r6, r7 } \n\t" \
|
||||
"ldmia %1, { r8, r9, r10 } \n\t" \
|
||||
"adcs r8, r8, %2 \n\t" \
|
||||
"umull r11, r12, r5, %4 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r8, r8, r11 \n\t" \
|
||||
"adcs r9, r9, %2 \n\t" \
|
||||
"umull r11, r12, r6, %4 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r9, r9, r11 \n\t" \
|
||||
"adcs r10, r10, %2 \n\t" \
|
||||
"umull r11, r12, r7, %4 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r10, r10, r11 \n\t" \
|
||||
"stmia %1!, { r8, r9, r10 } \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, r8, %[b] \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, %[c] \n\t" \
|
||||
"umull r4, r8, r9, %[b] \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r6, r6, r4 \n\t" \
|
||||
"adcs r7, r7, %[c] \n\t" \
|
||||
"umull r4, r8, r10, %[b] \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r7, r7, r4 \n\t" \
|
||||
"stmia %[d]!, { r5, r6, r7 } \n\t"
|
||||
|
||||
#define MULADDC_1024_LOOP \
|
||||
asm( "tst %3, #0xfe0 \n\t" \
|
||||
"beq 0f \n" \
|
||||
"1: sub %3, %3, #32 \n\t" \
|
||||
"ldmia %0!, { r5, r6, r7 } \n\t" \
|
||||
"ldmia %1, { r8, r9, r10 } \n\t" \
|
||||
"adds r8, r8, %2 \n\t" \
|
||||
"umull r11, r12, %4, r5 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r8, r8, r11 \n\t" \
|
||||
"adcs r9, r9, %2 \n\t" \
|
||||
"umull r11, r12, %4, r6 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r9, r9, r11 \n\t" \
|
||||
"adcs r10, r10, %2 \n\t" \
|
||||
"umull r11, r12, %4, r7 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r10, r10, r11 \n\t" \
|
||||
"stmia %1!, { r8, r9, r10 } \n\t" \
|
||||
asm( "tst %[i], #0xfe0 \n\t" \
|
||||
"beq 0f \n" \
|
||||
"1: ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
"sub %[i], %[i], #32 \n\t" \
|
||||
"adds r5, r5, %[c] \n\t" \
|
||||
"umull r4, r8, %[b], r8 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, %[c] \n\t" \
|
||||
"umull r4, r8, %[b], r9 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r6, r6, r4 \n\t" \
|
||||
"adcs r7, r7, %[c] \n\t" \
|
||||
"umull r4, r8, %[b], r10 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r7, r7, r4 \n\t" \
|
||||
"stmia %[d]!, { r5, r6, r7 } \n\t" \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE \
|
||||
"ldmia %0!, { r5, r6 } \n\t" \
|
||||
"ldmia %1, { r8, r9 } \n\t" \
|
||||
"adcs r8, r8, %2 \n\t" \
|
||||
"umull r11, r12, %4, r5 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r8, r8, r11 \n\t" \
|
||||
"adcs r9, r9, %2 \n\t" \
|
||||
"umull r11, r12, %4, r6 \n\t" \
|
||||
"adc %2, r12, #0 \n\t" \
|
||||
"adds r9, r9, r11 \n\t" \
|
||||
"stmia %1!, { r8, r9 } \n\t" \
|
||||
"adc %2, %2, #0 \n\t" \
|
||||
"tst %3, #0xfe0 \n\t" \
|
||||
"bne 1b \n" \
|
||||
"ldmia %[s]!, { r8, r9 } \n\t" \
|
||||
"ldmia %[d], { r5, r6 } \n\t" \
|
||||
"adcs r5, r5, %[c] \n\t" \
|
||||
"umull r4, r8, %[b], r8 \n\t" \
|
||||
"adc %[c], r8, #0 \n\t" \
|
||||
"adds r5, r5, r4 \n\t" \
|
||||
"adcs r6, r6, %[c] \n\t" \
|
||||
"umull r4, r8, %[b], 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 } \n\t" \
|
||||
"tst %[i], #0xfe0 \n\t" \
|
||||
"bne 1b \n" \
|
||||
"0:" \
|
||||
: "=r" (s), "=r" (d), "=r" (c), "=r" (i) \
|
||||
: "r" (b), "0" (s), "1" (d), "2" (c), "3" (i) \
|
||||
: "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory", "cc" );
|
||||
: [s] "=r" (s), [d] "=r" (d), [c] "=r" (c), [i] "=r" (i) \
|
||||
: [b] "r" (b), "[s]" (s), "[d]" (d), "[c]" (c), "[i]" (i) \
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
|
||||
|
||||
/* Just for reference (dead code) */
|
||||
#define MULADDC_HUIT \
|
||||
|
||||
@@ -1382,15 +1382,13 @@ static void mpi_montg_init( t_uint *mm, const mpi *N )
|
||||
|
||||
/*
|
||||
* Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
|
||||
* A is placed at the upper half of T.
|
||||
* A is placed at the upper half of D.
|
||||
*/
|
||||
static void mpi_montmul( const mpi *B, const mpi *N, t_uint mm, mpi *T )
|
||||
static void mpi_montmul( size_t n, const t_uint *np, t_uint mm, t_uint *d,
|
||||
const t_uint *bp )
|
||||
{
|
||||
size_t i, n;
|
||||
t_uint u0, u1, *d, c = 0;
|
||||
|
||||
d = T->p;
|
||||
n = N->n;
|
||||
size_t i;
|
||||
t_uint u0, u1, c = 0;
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
@@ -1399,31 +1397,28 @@ static void mpi_montmul( const mpi *B, const mpi *N, t_uint mm, mpi *T )
|
||||
*/
|
||||
u0 = d[n];
|
||||
d[n] = c;
|
||||
u1 = ( d[0] + u0 * B->p[0] ) * mm;
|
||||
u1 = ( d[0] + u0 * bp[0] ) * mm;
|
||||
|
||||
mpi_mul_hlp( n, B->p, d, u0 );
|
||||
c = mpi_mul_hlp( n, N->p, d, u1 );
|
||||
mpi_mul_hlp( n, bp, d, u0 );
|
||||
c = mpi_mul_hlp( n, np, d, u1 );
|
||||
d++;
|
||||
}
|
||||
|
||||
/* prevent timing attacks */
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, N->p ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, N->p, d );
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, np ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, np, d );
|
||||
else
|
||||
mpi_sub_hlp( n, T->p, T->p);
|
||||
mpi_sub_hlp( n, d - n, d - n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Montgomery reduction: A = A * R^-1 mod N
|
||||
* A is placed at the upper half of T.
|
||||
* A is placed at the upper half of D.
|
||||
*/
|
||||
static void mpi_montred( const mpi *N, t_uint mm, mpi *T )
|
||||
static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
{
|
||||
size_t i, j, n;
|
||||
t_uint u0, u1, *d, c = 0;
|
||||
|
||||
d = T->p;
|
||||
n = N->n;
|
||||
size_t i, j;
|
||||
t_uint u0, u1, c = 0;
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
@@ -1441,116 +1436,106 @@ static void mpi_montred( const mpi *N, t_uint mm, mpi *T )
|
||||
d[j] += c; c = ( d[j] < c );
|
||||
}
|
||||
|
||||
c = mpi_mul_hlp( n, N->p, d, u1 );
|
||||
c = mpi_mul_hlp( n, np, d, u1 );
|
||||
d++;
|
||||
}
|
||||
|
||||
/* prevent timing attacks */
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, N->p ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, N->p, d );
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, np ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, np, d );
|
||||
else
|
||||
mpi_sub_hlp( n, T->p, T->p);
|
||||
mpi_sub_hlp( n, d - n, d - n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Montgomery square: A = A * A * R^-1 mod N
|
||||
* A is placed at the upper half of T.
|
||||
* A is placed at the upper half of D.
|
||||
*/
|
||||
static void mpi_montsqr( const mpi *N, t_uint mm, mpi *T )
|
||||
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
{
|
||||
size_t n, i;
|
||||
t_uint c = 0, *d;
|
||||
|
||||
d = T->p;
|
||||
n = N->n;
|
||||
size_t i;
|
||||
register t_uint c = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
t_uint *wij = &d[i*2];
|
||||
t_uint *xj = &d[i+n];
|
||||
t_uint u, x_i;
|
||||
t_uint x_i;
|
||||
|
||||
x_i = *xj;
|
||||
*xj++ = c;
|
||||
asm ("mov r8, #0\n\t" /* R8 := 0, the constant ZERO from here. */
|
||||
/* (C,U,R9) := w_i_i + x_i*x_i; w_i_i := R9; */
|
||||
"ldr r9, [%[wij]]\n\t" /* R9 := w_i_i; */
|
||||
"mov %[c], r8\n\t"
|
||||
"umull r11, r12, %[x_i], %[x_i]\n\t"
|
||||
"adds r9, r9, r11\n\t"
|
||||
"adc %[u], r8, r12\n\t"
|
||||
"str r9, [%[wij]], #4\n\t"
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
"mov r4, %[c]\n\t"
|
||||
"umlal r5, r4, %[x_i], %[x_i]\n\t"
|
||||
"str r5, [%[wij]], #4\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bhi 0f\n\t"
|
||||
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
|
||||
"beq 1f\n"
|
||||
"2:\n\t"
|
||||
"ldmia %[xj]!, { r7, r8 }\n\t"
|
||||
"ldmia %[wij], { r5, r6 }\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umull r7, r12, %[x_i], r7\n\t"
|
||||
"adds r5, r5, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"adds r6, r6, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"umull r7, r12, %[x_i], r8\n\t"
|
||||
"adds r6, r6, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r6, r6, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
/**/
|
||||
"subs r9, %[xj_max], %[xj]\n\t"
|
||||
"bls 1f\n\t"
|
||||
/**/
|
||||
"tst r9, #4\n\t"
|
||||
"beq 0f\n\t"
|
||||
/* (C,U,R9) := (C,U) + w_i_j + 2*x_i*x_j; */
|
||||
"ldr r10, [%[xj]], #4\n\t"
|
||||
"ldr r9, [%[wij]]\n\t"
|
||||
"adds r9, r9, %[u]\n\t"
|
||||
"adc %[u], %[c], r8\n\t"
|
||||
"umull r11, r12, %[x_i], r10\n\t"
|
||||
"adds r9, r9, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], r8, r8\n\t"
|
||||
"adds r9, r9, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], %[c], r8\n\t"
|
||||
"str r9, [%[wij]], #4\n\t"
|
||||
/**/
|
||||
"subs r9, %[xj_max], %[xj]\n\t"
|
||||
"bls 1f\n"
|
||||
"0:\n\t"
|
||||
"ldmia %[xj]!, { r6, r7 }\n\t"
|
||||
"ldmia %[wij], { r9, r10 }\n\t"
|
||||
/* (C,U,R9) := (C,U) + w_i_j + 2*x_i*x_j; */
|
||||
"umull r11, r12, %[x_i], r6\n\t"
|
||||
"adds r9, r9, %[u]\n\t"
|
||||
"adc %[u], %[c], r8\n\t"
|
||||
"adds r9, r9, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], r8, r8\n\t"
|
||||
"adds r9, r9, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], %[c], r8\n\t"
|
||||
/* (C,U,R10) := (C,U) + w_i_j + 2*x_i*x_j; */
|
||||
"adds r10, r10, %[u]\n\t"
|
||||
"adc %[u], %[c], r8\n\t"
|
||||
"umull r11, r12, %[x_i], r7\n\t"
|
||||
"adds r10, r10, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], r8, r8\n\t"
|
||||
"adds r10, r10, r11\n\t"
|
||||
"adcs %[u], %[u], r12\n\t"
|
||||
"adc %[c], %[c], r8\n\t"
|
||||
/**/
|
||||
"stmia %[wij]!, { r9, r10 }\n\t"
|
||||
/**/
|
||||
"cmp %[xj], %[xj_max]\n\t"
|
||||
"bcc 0b\n"
|
||||
"stmia %[wij]!, { r5, r6 }\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bcc 2b\n\t"
|
||||
"bne 0f\n"
|
||||
"1:\n\t"
|
||||
"ldr r9, [%[wij]]\n\t"
|
||||
"adds %[u], %[u], r9\n\t"
|
||||
"adc %[c], %[c], r8\n\t"
|
||||
"str %[u], [%[wij]]"
|
||||
: [c] "=&r" (c), [u] "=&r" (u), [wij] "=r" (wij), [xj] "=r" (xj)
|
||||
: [x_i] "r" (x_i), [xj_max] "r" (&d[n*2]),
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"ldr r6, [%[xj]], #4\n\t"
|
||||
"adds r5, r5, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"umull r7, r12, %[x_i], r6\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
"str r5, [%[wij]], #4\n"
|
||||
"0:\n\t"
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"adds r4, r4, r5\n\t"
|
||||
"adc %[c], %[c], #0\n\t"
|
||||
"str r4, [%[wij]]"
|
||||
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r6", "r7", "r8", "r9", "r10", "r11", "r12", "memory", "cc" );
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
|
||||
|
||||
u = d[i] * mm;
|
||||
c += mpi_mul_hlp( n, N->p, &d[i], u );
|
||||
c += mpi_mul_hlp( n, np, &d[i], d[i] * mm );
|
||||
}
|
||||
|
||||
d = T->p + n;
|
||||
d += n;
|
||||
|
||||
/* prevent timing attacks */
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, N->p ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, N->p, d );
|
||||
if( ((mpi_cmp_abs_limbs ( n, d, np ) >= 0) | c) )
|
||||
mpi_sub_hlp( n, np, d );
|
||||
else
|
||||
mpi_sub_hlp( n, T->p, T->p);
|
||||
mpi_sub_hlp( n, d - n, d - n);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1559,12 +1544,17 @@ static void mpi_montsqr( const mpi *N, t_uint mm, mpi *T )
|
||||
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
{
|
||||
int ret;
|
||||
size_t wbits, wsize, one = 1;
|
||||
size_t i, j, nblimbs;
|
||||
size_t i = mpi_msb( E );
|
||||
size_t wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
|
||||
size_t wbits, one = 1;
|
||||
size_t nblimbs;
|
||||
size_t bufsize, nbits;
|
||||
t_uint ei, mm, state;
|
||||
mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos;
|
||||
int neg;
|
||||
mpi RR;
|
||||
t_uint d[N->n*2];
|
||||
t_uint w1[N->n];
|
||||
t_uint wn[(one << (wsize - 1))][N->n];
|
||||
|
||||
if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
|
||||
return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
|
||||
@@ -1572,97 +1562,76 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
if( mpi_cmp_int( E, 0 ) < 0 )
|
||||
return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
|
||||
|
||||
if( A->s == -1 )
|
||||
return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* Init temps and window size
|
||||
*/
|
||||
mpi_montg_init( &mm, N );
|
||||
mpi_init( &RR ); mpi_init( &T );
|
||||
memset( W, 0, sizeof( W ) );
|
||||
|
||||
i = mpi_msb( E );
|
||||
|
||||
wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
|
||||
|
||||
if( wsize > POLARSSL_MPI_WINDOW_SIZE )
|
||||
wsize = POLARSSL_MPI_WINDOW_SIZE;
|
||||
|
||||
j = N->n;
|
||||
MPI_CHK( mpi_grow( X, N->n ) );
|
||||
MPI_CHK( mpi_grow( &W[1], N->n ) );
|
||||
MPI_CHK( mpi_grow( &T, N->n * 2 ) ); /* T = 0 here. */
|
||||
|
||||
/*
|
||||
* Compensate for negative A (and correct at the end)
|
||||
*/
|
||||
neg = ( A->s == -1 );
|
||||
|
||||
mpi_init( &Apos );
|
||||
if( neg )
|
||||
{
|
||||
MPI_CHK( mpi_copy( &Apos, A ) );
|
||||
Apos.s = 1;
|
||||
A = &Apos;
|
||||
}
|
||||
|
||||
/*
|
||||
* If 1st call, pre-compute R^2 mod N
|
||||
*/
|
||||
if( _RR == NULL || _RR->p == NULL )
|
||||
{
|
||||
/* T->p is all zero here. */
|
||||
mpi_sub_hlp( N->n, N->p, T.p + N->n);
|
||||
mpi T;
|
||||
|
||||
mpi_init( &RR );
|
||||
T.s = 1; T.n = N->n * 2; T.p = d;
|
||||
memset (d, 0, 2 * N->n * ciL); /* Set D zero. */
|
||||
mpi_sub_hlp( N->n, N->p, d + N->n);
|
||||
MPI_CHK( mpi_mod_mpi( &RR, &T, N ) );
|
||||
|
||||
if( _RR != NULL )
|
||||
memcpy( _RR, &RR, sizeof( mpi ) );
|
||||
|
||||
/* The condition of "the lower half of T is all zero" is kept. */
|
||||
/* The condition of "the lower half of D is all zero" is kept. */
|
||||
}
|
||||
else
|
||||
else {
|
||||
memcpy( &RR, _RR, sizeof( mpi ) );
|
||||
memset (d, 0, N->n * ciL); /* Set lower half of D zero. */
|
||||
}
|
||||
|
||||
/*
|
||||
* W[1] = A * R^2 * R^-1 mod N = A * R mod N
|
||||
*/
|
||||
if( mpi_cmp_mpi( A, N ) >= 0 )
|
||||
mpi_mod_mpi( &W[1], A, N );
|
||||
else mpi_copy( &W[1], A );
|
||||
if( mpi_cmp_mpi( A, N ) >= 0 ) {
|
||||
mpi W1;
|
||||
W1.s = 1; W1.n = N->n; W1.p = d + N->n;
|
||||
mpi_mod_mpi( &W1, A, N );
|
||||
} else {
|
||||
memset (d + N->n, 0, N->n * ciL);
|
||||
memcpy (d + N->n, A->p, A->n * ciL);
|
||||
}
|
||||
|
||||
memcpy ( T.p + N->n, W[1].p, N->n * ciL);
|
||||
mpi_montmul( &RR, N, mm, &T );
|
||||
memcpy ( W[1].p, T.p + N->n, N->n * ciL);
|
||||
mpi_montmul( N->n, N->p, mm, d, RR.p );
|
||||
memcpy (w1, d + N->n, N->n * ciL);
|
||||
|
||||
if( wsize > 1 )
|
||||
{
|
||||
/*
|
||||
* W[1 << (wsize - 1)] = W[1] ^ ( 2 ^ (wsize - 1) )
|
||||
*/
|
||||
j = one << (wsize - 1);
|
||||
|
||||
MPI_CHK( mpi_grow( &W[j], N->n ) );
|
||||
|
||||
for( i = 0; i < wsize - 1; i++ )
|
||||
mpi_montsqr( N, mm, &T );
|
||||
memcpy ( W[j].p, T.p + N->n, N->n * ciL);
|
||||
mpi_montsqr( N->n, N->p, mm, d );
|
||||
memcpy (wn[0], d + N->n, N->n * ciL);
|
||||
|
||||
/*
|
||||
* W[i] = W[i - 1] * W[1]
|
||||
*/
|
||||
for( i = j + 1; i < (one << wsize); i++ )
|
||||
for( i = 1; i < (one << (wsize - 1)); i++ )
|
||||
{
|
||||
MPI_CHK( mpi_grow( &W[i], N->n ) );
|
||||
|
||||
mpi_montmul( &W[1], N, mm, &T );
|
||||
memcpy ( W[i].p, T.p + N->n, N->n * ciL);
|
||||
mpi_montmul( N->n, N->p, mm, d, w1 );
|
||||
memcpy (wn[i], d + N->n, N->n * ciL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* X = R^2 * R^-1 mod N = R mod N
|
||||
*/
|
||||
memcpy ( T.p + N->n, RR.p, N->n * ciL);
|
||||
mpi_montred( N, mm, &T );
|
||||
memcpy (d + N->n, RR.p, N->n * ciL);
|
||||
mpi_montred( N->n, N->p, mm, d );
|
||||
|
||||
nblimbs = E->n;
|
||||
bufsize = 0;
|
||||
@@ -1695,7 +1664,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
/*
|
||||
* out of window, square X
|
||||
*/
|
||||
mpi_montsqr( N, mm, &T );
|
||||
mpi_montsqr( N->n, N->p, mm, d );
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1713,12 +1682,12 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
* X = X^wsize R^-1 mod N
|
||||
*/
|
||||
for( i = 0; i < wsize; i++ )
|
||||
mpi_montsqr( N, mm, &T );
|
||||
mpi_montsqr( N->n, N->p, mm, d );
|
||||
|
||||
/*
|
||||
* X = X * W[wbits] R^-1 mod N
|
||||
*/
|
||||
mpi_montmul( &W[wbits], N, mm, &T );
|
||||
mpi_montmul( N->n, N->p, mm, d, wn[wbits - (one << (wsize - 1))]);
|
||||
|
||||
state--;
|
||||
nbits = 0;
|
||||
@@ -1731,33 +1700,22 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
*/
|
||||
for( i = 0; i < nbits; i++ )
|
||||
{
|
||||
mpi_montsqr( N, mm, &T );
|
||||
mpi_montsqr( N->n, N->p, mm, d );
|
||||
|
||||
wbits <<= 1;
|
||||
|
||||
if( (wbits & (one << wsize)) != 0 )
|
||||
mpi_montmul( &W[1], N, mm, &T );
|
||||
mpi_montmul( N->n, N->p, mm, d, w1);
|
||||
}
|
||||
|
||||
/*
|
||||
* X = A^E * R * R^-1 mod N = A^E mod N
|
||||
*/
|
||||
mpi_montred( N, mm, &T );
|
||||
memcpy ( X->p, T.p + N->n, N->n * ciL);
|
||||
|
||||
if( neg )
|
||||
{
|
||||
X->s = -1;
|
||||
mpi_add_mpi( X, N, X );
|
||||
}
|
||||
mpi_montred( N->n, N->p, mm, d );
|
||||
memcpy (X->p, d + N->n, N->n * ciL);
|
||||
|
||||
cleanup:
|
||||
|
||||
for( i = (one << (wsize - 1)); i < (one << wsize); i++ )
|
||||
mpi_free( &W[i] );
|
||||
|
||||
mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos );
|
||||
|
||||
if( _RR == NULL )
|
||||
mpi_free( &RR );
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ CSRC = main.c usb_stm32f103.c adc_stm32f103.c \
|
||||
usb_desc.c usb_ctrl.c \
|
||||
call-rsa.c \
|
||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \
|
||||
bn.c modp256.c jpc.c mod.c ec_p256.c call-ec_p256.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 =
|
||||
@@ -52,7 +55,7 @@ OBJCOPY = $(CROSS)objcopy
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
# DEFS: Add
|
||||
DEFS = -DCHX_PRIO_MAIN=5 -DRSA_AUTH @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
DEFS = -DCHX_PRIO_MAIN=5 -DRSA_AUTH -DRSA_SIG @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
|
||||
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;
|
||||
213
src/bn.c
213
src/bn.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* bn.c -- 256-bit (and 512-bit) bignum calculation
|
||||
*
|
||||
* Copyright (C) 2011, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 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.
|
||||
@@ -22,28 +22,32 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.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;
|
||||
|
||||
px = X->words;
|
||||
pa = A->words;
|
||||
pb = B->words;
|
||||
px = X->word;
|
||||
pa = A->word;
|
||||
pb = B->word;
|
||||
|
||||
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,21 +60,23 @@ 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;
|
||||
|
||||
px = X->words;
|
||||
pa = A->words;
|
||||
pb = B->words;
|
||||
px = X->word;
|
||||
pa = A->word;
|
||||
pb = B->word;
|
||||
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
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++;
|
||||
@@ -87,8 +93,8 @@ bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
uint32_t *px;
|
||||
const uint32_t *pa;
|
||||
|
||||
px = X->words;
|
||||
pa = A->words;
|
||||
px = X->word;
|
||||
pa = A->word;
|
||||
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
@@ -115,8 +121,8 @@ bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
uint32_t *px;
|
||||
const uint32_t *pa;
|
||||
|
||||
px = X->words;
|
||||
pa = A->words;
|
||||
px = X->word;
|
||||
pa = A->word;
|
||||
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
@@ -138,9 +144,30 @@ bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w)
|
||||
return borrow;
|
||||
}
|
||||
|
||||
#ifndef BN256_C_IMPLEMENTATION
|
||||
#define ASM_IMPLEMENTATION 1
|
||||
#endif
|
||||
void
|
||||
bn256_mul (bn512 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
#if ASM_IMPLEMENTATION
|
||||
#include "muladd_256.h"
|
||||
const uint32_t *s;
|
||||
uint32_t *d;
|
||||
uint32_t w;
|
||||
uint32_t c;
|
||||
|
||||
memset (X->word, 0, sizeof (uint32_t)*BN256_WORDS*2);
|
||||
|
||||
s = A->word; d = &X->word[0]; w = B->word[0]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[1]; w = B->word[1]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[2]; w = B->word[2]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[3]; w = B->word[3]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[4]; w = B->word[4]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[5]; w = B->word[5]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[6]; w = B->word[6]; MULADD_256 (s, d, w, c);
|
||||
s = A->word; d = &X->word[7]; w = B->word[7]; MULADD_256 (s, d, w, c);
|
||||
#else
|
||||
int i, j, k;
|
||||
int i_beg, i_end;
|
||||
uint32_t r0, r1, r2;
|
||||
@@ -167,7 +194,7 @@ bn256_mul (bn512 *X, const bn256 *A, const bn256 *B)
|
||||
|
||||
j = k - i;
|
||||
|
||||
uv = ((uint64_t )A->words[i])*((uint64_t )B->words[j]);
|
||||
uv = ((uint64_t )A->word[i])*((uint64_t )B->word[j]);
|
||||
v = uv;
|
||||
u = (uv >> 32);
|
||||
r0 += v;
|
||||
@@ -179,18 +206,96 @@ bn256_mul (bn512 *X, const bn256 *A, const bn256 *B)
|
||||
r2 += carry;
|
||||
}
|
||||
|
||||
X->words[k] = r0;
|
||||
X->word[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
X->words[k] = r0;
|
||||
X->word[k] = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bn256_sqr (bn512 *X, const bn256 *A)
|
||||
{
|
||||
#if ASM_IMPLEMENTATION
|
||||
int i;
|
||||
|
||||
memset (X->word, 0, sizeof (bn512));
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
uint32_t *wij = &X->word[i*2];
|
||||
const uint32_t *xj = &A->word[i];
|
||||
uint32_t x_i = *xj++;
|
||||
uint32_t c;
|
||||
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
"mov r4, %[c]\n\t"
|
||||
"umlal r5, r4, %[x_i], %[x_i]\n\t"
|
||||
"str r5, [%[wij]], #4\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bhi 0f\n\t"
|
||||
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
|
||||
"beq 1f\n"
|
||||
"2:\n\t"
|
||||
"ldmia %[xj]!, { r7, r8 }\n\t"
|
||||
"ldmia %[wij], { r5, r6 }\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umull r7, r12, %[x_i], r7\n\t"
|
||||
"adds r5, r5, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"adds r6, r6, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"umull r7, r12, %[x_i], r8\n\t"
|
||||
"adds r6, r6, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r6, r6, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
/**/
|
||||
"stmia %[wij]!, { r5, r6 }\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bcc 2b\n\t"
|
||||
"bne 0f\n"
|
||||
"1:\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"ldr r6, [%[xj]], #4\n\t"
|
||||
"adds r5, r5, r4\n\t"
|
||||
"adc r4, %[c], r9\n\t"
|
||||
"umull r7, r12, %[x_i], r6\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], r9, r9\n\t"
|
||||
"adds r5, r5, r7\n\t"
|
||||
"adcs r4, r4, r12\n\t"
|
||||
"adc %[c], %[c], r9\n\t"
|
||||
"str r5, [%[wij]], #4\n"
|
||||
"0:\n\t"
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"adds r4, r4, r5\n\t"
|
||||
"adc %[c], %[c], #0\n\t"
|
||||
"str r4, [%[wij]], #4"
|
||||
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&A->word[BN256_WORDS-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
|
||||
|
||||
if (i < BN256_WORDS - 1)
|
||||
*wij = c;
|
||||
}
|
||||
#else
|
||||
int i, j, k;
|
||||
int i_beg, i_end;
|
||||
uint32_t r0, r1, r2;
|
||||
@@ -217,11 +322,10 @@ bn256_sqr (bn512 *X, const bn256 *A)
|
||||
|
||||
j = k - i;
|
||||
|
||||
uv = ((uint64_t )A->words[i])*((uint64_t )A->words[j]);
|
||||
uv = ((uint64_t )A->word[i])*((uint64_t )A->word[j]);
|
||||
if (i < j)
|
||||
{
|
||||
if ((uv >> 63) != 0)
|
||||
r2++;
|
||||
r2 += ((uv >> 63) != 0);
|
||||
uv <<= 1;
|
||||
}
|
||||
v = uv;
|
||||
@@ -235,13 +339,14 @@ bn256_sqr (bn512 *X, const bn256 *A)
|
||||
r2 += carry;
|
||||
}
|
||||
|
||||
X->words[k] = r0;
|
||||
X->word[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
X->words[k] = r0;
|
||||
X->word[k] = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -254,8 +359,8 @@ bn256_shift (bn256 *X, const bn256 *A, int shift)
|
||||
{
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
next_carry = A->words[i] >> (32 - shift);
|
||||
X->words[i] = (A->words[i] << shift) | carry;
|
||||
next_carry = A->word[i] >> (32 - shift);
|
||||
X->word[i] = (A->word[i] << shift) | carry;
|
||||
carry = next_carry;
|
||||
}
|
||||
}
|
||||
@@ -265,8 +370,8 @@ bn256_shift (bn256 *X, const bn256 *A, int shift)
|
||||
|
||||
for (i = BN256_WORDS - 1; i >= 0; i--)
|
||||
{
|
||||
next_carry = A->words[i] & ((1 << shift) - 1);
|
||||
X->words[i] = (A->words[i] >> shift) | (carry << (32 - shift));
|
||||
next_carry = A->word[i] & ((1 << shift) - 1);
|
||||
X->word[i] = (A->word[i] >> shift) | (carry << (32 - shift));
|
||||
carry = next_carry;
|
||||
}
|
||||
}
|
||||
@@ -278,63 +383,59 @@ int
|
||||
bn256_is_zero (const bn256 *X)
|
||||
{
|
||||
int i;
|
||||
int r = 1;
|
||||
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
if (X->words[i] != 0)
|
||||
return 0;
|
||||
r &= (X->word[i] == 0);
|
||||
|
||||
return 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
bn256_is_even (const bn256 *X)
|
||||
{
|
||||
return !(X->words[0] & 1);
|
||||
return !(X->word[0] & 1);
|
||||
}
|
||||
|
||||
int
|
||||
bn256_is_ge (const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int i;
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
|
||||
for (i = BN256_WORDS - 1; i >= 0; i--)
|
||||
if (A->words[i] > B->words[i])
|
||||
return 1;
|
||||
else if (A->words[i] < B->words[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
borrow = bn256_sub (tmp, A, B);
|
||||
return borrow == 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bn256_cmp (const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int i;
|
||||
uint32_t borrow;
|
||||
int is_zero;
|
||||
bn256 tmp[1];
|
||||
|
||||
for (i = BN256_WORDS - 1; i >= 0; i--)
|
||||
if (A->words[i] > B->words[i])
|
||||
return 1;
|
||||
else if (A->words[i] < B->words[i])
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
borrow = bn256_sub (tmp, A, B);
|
||||
is_zero = bn256_is_zero (tmp);
|
||||
return is_zero ? 0 : (borrow ? -1 : 1);
|
||||
}
|
||||
|
||||
|
||||
#ifndef BN256_NO_RANDOM
|
||||
void
|
||||
bn256_random (bn256 *X)
|
||||
{
|
||||
const uint8_t *rand = random_bytes_get ();
|
||||
|
||||
X->words[7] = ((uint32_t *)rand)[7];
|
||||
X->words[6] = ((uint32_t *)rand)[6];
|
||||
X->words[5] = ((uint32_t *)rand)[5];
|
||||
X->words[4] = ((uint32_t *)rand)[4];
|
||||
X->words[3] = ((uint32_t *)rand)[3];
|
||||
X->words[2] = ((uint32_t *)rand)[2];
|
||||
X->words[1] = ((uint32_t *)rand)[1];
|
||||
X->words[0] = ((uint32_t *)rand)[0];
|
||||
X->word[7] = ((uint32_t *)rand)[7];
|
||||
X->word[6] = ((uint32_t *)rand)[6];
|
||||
X->word[5] = ((uint32_t *)rand)[5];
|
||||
X->word[4] = ((uint32_t *)rand)[4];
|
||||
X->word[3] = ((uint32_t *)rand)[3];
|
||||
X->word[2] = ((uint32_t *)rand)[2];
|
||||
X->word[1] = ((uint32_t *)rand)[1];
|
||||
X->word[0] = ((uint32_t *)rand)[0];
|
||||
|
||||
random_bytes_free (rand);
|
||||
}
|
||||
#endif
|
||||
|
||||
4
src/bn.h
4
src/bn.h
@@ -1,11 +1,11 @@
|
||||
#define BN256_WORDS 8
|
||||
typedef struct bn256 {
|
||||
uint32_t words[ BN256_WORDS ]; /* Little endian */
|
||||
uint32_t word[ BN256_WORDS ]; /* Little endian */
|
||||
} bn256;
|
||||
|
||||
#define BN512_WORDS 16
|
||||
typedef struct bn512 {
|
||||
uint32_t words[ BN512_WORDS ]; /* Little endian */
|
||||
uint32_t word[ BN512_WORDS ]; /* Little endian */
|
||||
} bn512;
|
||||
|
||||
uint32_t bn256_add (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* call-ec_p256.c - interface between Gnuk and Elliptic curve over GF(p256)
|
||||
* call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
|
||||
*
|
||||
* Copyright (C) 2013 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
@@ -21,24 +21,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "jpc-ac.h"
|
||||
#include "ec_p256.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gnuk.h"
|
||||
#include "field-group-select.h"
|
||||
|
||||
/* We are little endian. */
|
||||
|
||||
#define ECDSA_BYTE_SIZE 32
|
||||
|
||||
int
|
||||
ecdsa_sign (const uint8_t *hash, uint8_t *output,
|
||||
const struct key_data *kd)
|
||||
FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data)
|
||||
{
|
||||
int i;
|
||||
bn256 r[1], s[1], z[1], d[1];
|
||||
@@ -46,13 +37,13 @@ ecdsa_sign (const uint8_t *hash, uint8_t *output,
|
||||
|
||||
p = (uint8_t *)d;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = kd->data[i];
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
|
||||
|
||||
p = (uint8_t *)z;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = hash[i];
|
||||
|
||||
ecdsa (r, s, z, d);
|
||||
FUNC(ecdsa) (r, s, z, d);
|
||||
p = (uint8_t *)r;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
*output++ = p[ECDSA_BYTE_SIZE - i - 1];
|
||||
@@ -63,7 +54,7 @@ ecdsa_sign (const uint8_t *hash, uint8_t *output,
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
ecdsa_compute_public (const uint8_t *key_data)
|
||||
FUNC(ecdsa_compute_public) (const uint8_t *key_data)
|
||||
{
|
||||
uint8_t *p0, *p, *p1;
|
||||
ac q[1];
|
||||
@@ -77,7 +68,7 @@ ecdsa_compute_public (const uint8_t *key_data)
|
||||
p = (uint8_t *)k;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
|
||||
if (compute_kG (q, k) < 0)
|
||||
if (FUNC(compute_kG) (q, k) < 0)
|
||||
{
|
||||
free (p0);
|
||||
return NULL;
|
||||
35
src/call-ec_p256k1.c
Normal file
35
src/call-ec_p256k1.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* call-ec_p256k1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256k1)
|
||||
*
|
||||
* 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 "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
#include "ec_p256k1.h"
|
||||
|
||||
#define FIELD p256k1
|
||||
|
||||
#include "call-ec.c"
|
||||
35
src/call-ec_p256r1.c
Normal file
35
src/call-ec_p256r1.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* call-ec_p256r1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256r1)
|
||||
*
|
||||
* 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 "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
#include "ec_p256r1.h"
|
||||
|
||||
#define FIELD p256r1
|
||||
|
||||
#include "call-ec.c"
|
||||
2
src/configure
vendored
2
src/configure
vendored
@@ -321,6 +321,8 @@ if test "$certdo" = "yes"; then
|
||||
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
||||
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
|
||||
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
|
||||
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
|
||||
< gnuk.ld.in > gnuk.ld
|
||||
else
|
||||
sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/* Non-adjacent form */
|
||||
typedef struct naf4_257 {
|
||||
uint32_t words[ BN256_WORDS*4 ]; /* Little endian */
|
||||
uint8_t last_nibble; /* most significant nibble */
|
||||
} naf4_257;
|
||||
|
||||
void compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K);
|
||||
int compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P);
|
||||
|
||||
int compute_kG (ac *X, const bn256 *K);
|
||||
void ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
|
||||
|
||||
225
src/ec_p256k1.c
Normal file
225
src/ec_p256k1.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ec_p256k1.c - Elliptic curve over GF(p256k1)
|
||||
*
|
||||
* 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 "modp256k1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
#include "mod.h"
|
||||
#include "ec_p256k1.h"
|
||||
|
||||
#define FIELD p256k1
|
||||
#define COEFFICIENT_A_IS_ZERO 1
|
||||
|
||||
/*
|
||||
* a = 0, b = 7
|
||||
*/
|
||||
static const bn256 coefficient_a[1] = {
|
||||
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
};
|
||||
|
||||
static const bn256 coefficient_b[1] = {
|
||||
{{ 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
};
|
||||
|
||||
|
||||
static const ac precomputed_KG[15] = {
|
||||
{
|
||||
{{{ 0x16f81798, 0x59f2815b, 0x2dce28d9, 0x029bfcdb,
|
||||
0xce870b07, 0x55a06295, 0xf9dcbbac, 0x79be667e }}},
|
||||
{{{ 0xfb10d4b8, 0x9c47d08f, 0xa6855419, 0xfd17b448,
|
||||
0x0e1108a8, 0x5da4fbfc, 0x26a3c465, 0x483ada77 }}}
|
||||
}, {
|
||||
{{{ 0x42d0e6bd, 0x13b7e0e7, 0xdb0f5e53, 0xf774d163,
|
||||
0x104d6ecb, 0x82a2147c, 0x243c4e25, 0x3322d401 }}},
|
||||
{{{ 0x6c28b2a0, 0x24f3a2e9, 0xa2873af6, 0x2805f63e,
|
||||
0x4ddaf9b7, 0xbfb019bc, 0xe9664ef5, 0x56e70797 }}}
|
||||
}, {
|
||||
{{{ 0x829d122a, 0xdca81127, 0x67e99549, 0x8f17f314,
|
||||
0x6a8a9e73, 0x9b889085, 0x846dd99d, 0x583fdfd9 }}},
|
||||
{{{ 0x63c4eac4, 0xf3c7719e, 0xb734b37a, 0xb44685a3,
|
||||
0x572a47a6, 0x9f92d2d6, 0x2ff57d81, 0xabc6232f }}}
|
||||
}, {
|
||||
{{{ 0x9ec4c0da, 0x1b7b444c, 0x723ea335, 0xe88c5678,
|
||||
0x981f162e, 0x9239c1ad, 0xf63b5f33, 0x8f68b9d2 }}},
|
||||
{{{ 0x501fff82, 0xf23cbf79, 0x95510bfd, 0xbbea2cfe,
|
||||
0xb6be215d, 0xde1d90c2, 0xba063986, 0x662a9f2d }}}
|
||||
}, {
|
||||
{{{ 0x114cbf09, 0x63c5e885, 0x7be77e3e, 0x2f27ce93,
|
||||
0xf54a3e33, 0xdaa6d12d, 0x3eff872c, 0x8b300e51 }}},
|
||||
{{{ 0xb3b10a39, 0x26c6ff28, 0x9aaf7169, 0x08f6a7aa,
|
||||
0x6b8238ea, 0x446f0d46, 0x7f43c0cc, 0x1cec3067 }}}
|
||||
}, {
|
||||
{{{ 0x075e9070, 0xba16ce6a, 0x9b5cfe37, 0xbc26893d,
|
||||
0x9c510774, 0xe1ddadfe, 0xfe3ae2f4, 0x90922d88 }}},
|
||||
{{{ 0x5c08824a, 0x653943cc, 0xfce8f4bc, 0x06d74475,
|
||||
0x533c615d, 0x8d101fa7, 0x742108a9, 0x7b1903f6 }}}
|
||||
}, {
|
||||
{{{ 0x6ebdc96c, 0x1bcfa45c, 0x1c7584ba, 0xe400bc04,
|
||||
0x74cf531f, 0x6395e20e, 0xc5131b30, 0x1edd0bb1 }}},
|
||||
{{{ 0xe358cf9e, 0xa117161b, 0x2724d11c, 0xe490d6f0,
|
||||
0xee6dd8c9, 0xf75062f6, 0xfba373e4, 0x31e03b2b }}}
|
||||
}, {
|
||||
{{{ 0x2120e2b3, 0x7f3b58fa, 0x7f47f9aa, 0x7a58fdce,
|
||||
0x4ce6e521, 0xe7be4ae3, 0x1f51bdba, 0xeaa649f2 }}},
|
||||
{{{ 0xba5ad93d, 0xd47a5305, 0xf13f7e59, 0x01a6b965,
|
||||
0x9879aa5a, 0xc69a80f8, 0x5bbbb03a, 0xbe3279ed }}}
|
||||
}, {
|
||||
{{{ 0x27bb4d71, 0xcf291a33, 0x33524832, 0x6caf7d6b,
|
||||
0x766584ee, 0x6e0ee131, 0xd064c589, 0x160cb0f6 }}},
|
||||
{{{ 0x17136e8d, 0x9d5de554, 0x1aab720e, 0xe3f2d468,
|
||||
0xccf75cc2, 0xd1378b49, 0xc4ff16e1, 0x6920c375 }}}
|
||||
}, {
|
||||
{{{ 0x1a9ee611, 0x3eef9e96, 0x9cc37faf, 0xfe4d7bf3,
|
||||
0xb321d965, 0x462aa9b3, 0x208736c5, 0x1702da3e }}},
|
||||
{{{ 0x3a545ceb, 0xfba57bbf, 0x7ea858f5, 0x6dbcd766,
|
||||
0x680d92f1, 0x088e897c, 0xbc626c80, 0x468c1fd8 }}}
|
||||
}, {
|
||||
{{{ 0xb188660a, 0xb40f85c7, 0x99bc3c36, 0xc5873c19,
|
||||
0x7f33b54c, 0x3c7b4541, 0x1f8c9bf8, 0x4cd3a93c }}},
|
||||
{{{ 0x33099cb0, 0xf8dce380, 0x2edd2f33, 0x7a167dd6,
|
||||
0x0ffe35b7, 0x576d8987, 0xc68ace5c, 0xd2de0386 }}}
|
||||
}, {
|
||||
{{{ 0x6658bb08, 0x9a9e0a72, 0xc589607b, 0xe23c5f2a,
|
||||
0xf2bfb4c8, 0xa048ca14, 0xc62c2291, 0x4d9a0f89 }}},
|
||||
{{{ 0x0f827294, 0x427b5f31, 0x9f2c35cd, 0x1ea7a8b5,
|
||||
0x85a3c00f, 0x95442e56, 0x9b57975a, 0x8cb83121 }}}
|
||||
}, {
|
||||
{{{ 0x51f5cf67, 0x4333f0da, 0xf4f0d3cb, 0x6d3ea47c,
|
||||
0xa05a831f, 0x442fda14, 0x016d3e81, 0x6a496013 }}},
|
||||
{{{ 0xe52e0f48, 0xf647318c, 0x4a0d5ff1, 0x5ff3a66e,
|
||||
0x61199ba8, 0x046ed81a, 0x3e79c23a, 0x578edf08 }}}
|
||||
}, {
|
||||
{{{ 0x3ea01ea7, 0xb8f996f8, 0x7497bb15, 0xc0045d33,
|
||||
0x6205647c, 0xc4749dc9, 0x0efd22c9, 0xd8946054 }}},
|
||||
{{{ 0x12774ad5, 0x062dcb09, 0x8be06e3a, 0xcb13f310,
|
||||
0x235de1a9, 0xca281d35, 0x69c3645c, 0xaf8a7412 }}}
|
||||
}, {
|
||||
{{{ 0xbeb8b1e2, 0x8808ca5f, 0xea0dda76, 0x0262b204,
|
||||
0xddeb356b, 0xb6fffffc, 0xfbb83870, 0x52de253a }}},
|
||||
{{{ 0x8f8d21ea, 0x961f40c0, 0x002f03ed, 0x89686278,
|
||||
0x38e421ea, 0x0ff834d7, 0xd36fb8db, 0x3a270d6f }}}
|
||||
}
|
||||
};
|
||||
|
||||
static const ac precomputed_2E_KG[15] = {
|
||||
{
|
||||
{{{ 0x39a48db0, 0xefd7835b, 0x9b3c03bf, 0x9f1215a2,
|
||||
0x9b7bde45, 0x2791d0a0, 0x696e7167, 0x100f44da }}},
|
||||
{{{ 0x2bc65a09, 0x0fbd5cd6, 0xff5195ac, 0xb7ff4a18,
|
||||
0x0c090666, 0x2ec8f330, 0x92a00b77, 0xcdd9e131 }}}
|
||||
}, {
|
||||
{{{ 0x40fb27b6, 0x32427e28, 0xbe430576, 0xc76e3db2,
|
||||
0x61686aa5, 0x10f238ad, 0xbe778b1b, 0xfea74e3d }}},
|
||||
{{{ 0xf23cb96f, 0x701d3db7, 0x973f7b77, 0x126b596b,
|
||||
0xccb6af93, 0x7cf674de, 0x9b0b1329, 0x6e0568db }}}
|
||||
}, {
|
||||
{{{ 0x2c8118bc, 0x6cac5154, 0x399ddd98, 0x19bd4b34,
|
||||
0x2e9c8949, 0x47248a8d, 0x2cefa3b1, 0x734cb6a8 }}},
|
||||
{{{ 0x1e410fd5, 0xf1b340ad, 0xc4873539, 0xa2982bee,
|
||||
0xd4de4530, 0x7b5a3ea4, 0x42202574, 0xae46e10e }}}
|
||||
}, {
|
||||
{{{ 0xac1f98cd, 0xcbfc99c8, 0x4d7f0308, 0x52348905,
|
||||
0x1cc66021, 0xfaed8a9c, 0x4a474870, 0x9c3919a8 }}},
|
||||
{{{ 0xd4fc599d, 0xbe7e5e03, 0x6c64c8e6, 0x905326f7,
|
||||
0xf260e641, 0x584f044b, 0x4a4ddd57, 0xddb84f0f }}}
|
||||
}, {
|
||||
{{{ 0xed7cebed, 0xc4aacaa8, 0x4fae424e, 0xb75d2dce,
|
||||
0xba20735e, 0xa01585a2, 0xba122399, 0x3d75f24b }}},
|
||||
{{{ 0xd5570dce, 0xcbe4606f, 0x2da192c2, 0x9d00bfd7,
|
||||
0xa57b7265, 0x9c3ce86b, 0xec4edf5e, 0x987a22f1 }}}
|
||||
}, {
|
||||
{{{ 0x73ea0665, 0x211b9715, 0xf3a1abbb, 0x86f485d4,
|
||||
0xcd076f0e, 0xabd242d8, 0x0ba5dc88, 0x862332ab }}},
|
||||
{{{ 0x7b784911, 0x09af505c, 0xcaf4fae7, 0xc89544e8,
|
||||
0xae9a32eb, 0x256625f6, 0x606d1a3f, 0xe2532b72 }}}
|
||||
}, {
|
||||
{{{ 0x0deaf885, 0x79e9f313, 0x46df21c9, 0x938ff76e,
|
||||
0xa953bb2c, 0x1968f5fb, 0x29155f27, 0xdff538bf }}},
|
||||
{{{ 0x31d5d020, 0xf7bae0b1, 0x1a676a8d, 0x5afdc787,
|
||||
0xfa9d53ff, 0x11b4f032, 0xc5959167, 0x86ba433e }}}
|
||||
}, {
|
||||
{{{ 0x9475b7ba, 0x884fdff0, 0xe4918b3d, 0xe039e730,
|
||||
0xf5018cdb, 0x3d3e57ed, 0x1943785c, 0x95939698 }}},
|
||||
{{{ 0x7524f2fd, 0xe9b8abf8, 0xc8709385, 0x9c653f64,
|
||||
0x4b9cd684, 0x8ba0386a, 0x88c331dd, 0x2e7e5528 }}}
|
||||
}, {
|
||||
{{{ 0xeefe79e5, 0x940bef53, 0xbe9b87f3, 0xc518d286,
|
||||
0x7833042c, 0x9e0c7c76, 0x11fbe152, 0x104e2cb5 }}},
|
||||
{{{ 0x50bbec83, 0xc0d35e0f, 0x4acd0fcc, 0xee4879be,
|
||||
0x006085ee, 0xc8d80f5d, 0x72fe1ac1, 0x3c51bc1c }}}
|
||||
}, {
|
||||
{{{ 0xb2de976e, 0x06187f61, 0xf5e4b4b6, 0x52869e18,
|
||||
0x38d332ca, 0x74d4facd, 0xb3a2f8d9, 0x5c1c90b4 }}},
|
||||
{{{ 0xdaa37893, 0x98644d09, 0xabe39818, 0x682435a8,
|
||||
0x469c53a0, 0x17e46617, 0x77dc2e64, 0x642f9632 }}}
|
||||
}, {
|
||||
{{{ 0x222f6c54, 0xad2101c5, 0xfa74785e, 0xb05c7a58,
|
||||
0x489bcdaf, 0xce55fa79, 0xffe88d54, 0xc1f920fd }}},
|
||||
{{{ 0x9065e490, 0x32553ab0, 0x35329f74, 0x7611b9af,
|
||||
0xab7b24c0, 0x57df19ef, 0x6181c447, 0xb9a78749 }}}
|
||||
}, {
|
||||
{{{ 0xa80b7ea8, 0x392f156f, 0x8ae4a8bf, 0x57ab7ca0,
|
||||
0x50c4b178, 0xac320747, 0x0e781feb, 0x146041b9 }}},
|
||||
{{{ 0x845279b2, 0xd343f075, 0x7387afa5, 0x2d4fe757,
|
||||
0xa72f3c39, 0x151e0948, 0x550da168, 0x41a6d54e }}}
|
||||
}, {
|
||||
{{{ 0x075a0010, 0xb3134ed3, 0x7ae93e23, 0x9fa76f4b,
|
||||
0x7bb4daaa, 0xc0db256f, 0x464dd8a3, 0x7668dc27 }}},
|
||||
{{{ 0x9f5da977, 0x150063f5, 0x05efce00, 0x3acac5c8,
|
||||
0x884493fe, 0xc8e12ffc, 0x88f06bd2, 0x4ab936d8 }}}
|
||||
}, {
|
||||
{{{ 0x5d09ea98, 0x996fde77, 0x4145da58, 0x16ddf512,
|
||||
0xdc2fb225, 0xa97a6ca8, 0xfbdcdf5a, 0xc7331f30 }}},
|
||||
{{{ 0x86a86e52, 0x838f99e0, 0x77795edd, 0x68d39b29,
|
||||
0x9f412aaa, 0xe4e4f97e, 0x30d25352, 0xe5cc2c0a }}}
|
||||
}, {
|
||||
{{{ 0x9c21ff71, 0xb3d68650, 0xddbe3884, 0x11e7589d,
|
||||
0x423bac67, 0x7efd4055, 0x46957425, 0x587a7293 }}},
|
||||
{{{ 0x8f5a8fc6, 0x360adc2e, 0xbd69f12e, 0x6f8bbafb,
|
||||
0x0a3f3b4d, 0xf671f423, 0x59942dc3, 0xb49acb47 }}}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* N: order of G
|
||||
* 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||
*/
|
||||
static const bn256 N[1] = {
|
||||
{{ 0xd0364141, 0xbfd25e8c, 0xaf48a03b, 0xbaaedce6,
|
||||
0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff }}
|
||||
};
|
||||
|
||||
/*
|
||||
* MU = 2^512 / N
|
||||
* MU = ( (1 << 256) | MU_lower )
|
||||
*/
|
||||
static const bn256 MU_lower[1] = {
|
||||
{{ 0x2fc9bec0, 0x402da173, 0x50b75fc4, 0x45512319,
|
||||
0x1, 0x0, 0x0, 0x0 }}
|
||||
};
|
||||
|
||||
|
||||
#include "ecc.c"
|
||||
4
src/ec_p256k1.h
Normal file
4
src/ec_p256k1.h
Normal file
@@ -0,0 +1,4 @@
|
||||
int compute_kP_p256k1 (ac *X, const bn256 *K, const ac *P);
|
||||
|
||||
int compute_kG_p256k1 (ac *X, const bn256 *K);
|
||||
void ecdsa_p256k1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ec_p256.c - Elliptic curve over GF(p256)
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ec_p256r1.c - Elliptic curve over GF(p256r1)
|
||||
*
|
||||
* Copyright (C) 2011, 2013 Free Software Initiative of Japan
|
||||
* 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.
|
||||
@@ -21,45 +21,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* References:
|
||||
*
|
||||
* [1] Suite B Implementer's Guide to FIPS 186-3 (ECDSA), February 3, 2010.
|
||||
*
|
||||
* [2] Michael Brown, Darrel Hankerson, Julio López, and Alfred Menezes,
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields,
|
||||
* Proceedings of the 2001 Conference on Topics in Cryptology: The
|
||||
* Cryptographer's Track at RSA
|
||||
* Pages 250-265, Springer-Verlag London, UK, 2001
|
||||
* ISBN:3-540-41898-9
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "modp256.h"
|
||||
#include "jpc-ac.h"
|
||||
#include "modp256r1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
#include "mod.h"
|
||||
#include "ec_p256.h"
|
||||
|
||||
#if TEST
|
||||
/*
|
||||
* Generator of Elliptic curve over GF(p256)
|
||||
*/
|
||||
const bn256 Gx[1] = {
|
||||
{{ 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
|
||||
0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2 }}
|
||||
};
|
||||
|
||||
const bn256 Gy[1] = {
|
||||
{{ 0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357,
|
||||
0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2 }}
|
||||
};
|
||||
#endif
|
||||
#include "ec_p256r1.h"
|
||||
|
||||
#define FIELD p256r1
|
||||
#define COEFFICIENT_A_IS_MINUS_3 1
|
||||
|
||||
/*
|
||||
* a = -3 mod p256
|
||||
* a = -3 mod p256r1
|
||||
*/
|
||||
static const bn256 coefficient_a[1] = {
|
||||
{{ 0xfffffffc, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
@@ -72,13 +47,6 @@ static const bn256 coefficient_b[1] = {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* w = 4
|
||||
* m = 256
|
||||
* d = 64
|
||||
* e = 32
|
||||
*/
|
||||
|
||||
static const ac precomputed_KG[15] = {
|
||||
{
|
||||
{{{ 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
|
||||
@@ -237,271 +205,6 @@ static const ac precomputed_2E_KG[15] = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief X = k * G
|
||||
*
|
||||
* @param K scalar k
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
int
|
||||
compute_kG (ac *X, const bn256 *K)
|
||||
{
|
||||
int i;
|
||||
int q_is_infinite = 1;
|
||||
jpc Q[1];
|
||||
|
||||
for (i = 31; i >= 0; i--)
|
||||
{
|
||||
int k_i, k_i_e;
|
||||
|
||||
if (!q_is_infinite)
|
||||
jpc_double (Q, Q);
|
||||
|
||||
k_i = (((K->words[6] >> i) & 1) << 3)
|
||||
| (((K->words[4] >> i) & 1) << 2)
|
||||
| (((K->words[2] >> i) & 1) << 1)
|
||||
| ((K->words[0] >> i) & 1);
|
||||
k_i_e = (((K->words[7] >> i) & 1) << 3)
|
||||
| (((K->words[5] >> i) & 1) << 2)
|
||||
| (((K->words[3] >> i) & 1) << 1)
|
||||
| ((K->words[1] >> i) & 1);
|
||||
|
||||
if (k_i)
|
||||
{
|
||||
if (q_is_infinite)
|
||||
{
|
||||
memcpy (Q->x, (&precomputed_KG[k_i - 1])->x, sizeof (bn256));
|
||||
memcpy (Q->y, (&precomputed_KG[k_i - 1])->y, sizeof (bn256));
|
||||
Q->z->words[0] = 1;
|
||||
Q->z->words[1] = Q->z->words[2] = Q->z->words[3]
|
||||
= Q->z->words[4] = Q->z->words[5] = Q->z->words[6]
|
||||
= Q->z->words[7] = 0;
|
||||
q_is_infinite = 0;
|
||||
}
|
||||
else
|
||||
jpc_add_ac (Q, Q, &precomputed_KG[k_i - 1]);
|
||||
}
|
||||
if (k_i_e)
|
||||
{
|
||||
if (q_is_infinite)
|
||||
{
|
||||
memcpy (Q->x, (&precomputed_2E_KG[k_i_e - 1])->x, sizeof (bn256));
|
||||
memcpy (Q->y, (&precomputed_2E_KG[k_i_e - 1])->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->words[0] = 1;
|
||||
q_is_infinite = 0;
|
||||
}
|
||||
else
|
||||
jpc_add_ac (Q, Q, &precomputed_2E_KG[k_i_e - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
return jpc_to_ac (X, Q);
|
||||
}
|
||||
|
||||
|
||||
#define NAF_K_SIGN(k) (k&8)
|
||||
#define NAF_K_INDEX(k) ((k&7)-1)
|
||||
|
||||
static void
|
||||
naf4_257_set (naf4_257 *NAF_K, int i, int ki)
|
||||
{
|
||||
if (ki != 0)
|
||||
{
|
||||
if (ki > 0)
|
||||
ki = (ki+1)/2;
|
||||
else
|
||||
ki = (1-ki)/2 | 8;
|
||||
}
|
||||
|
||||
if (i == 256)
|
||||
NAF_K->last_nibble = ki;
|
||||
else
|
||||
{
|
||||
NAF_K->words[i/8] &= ~(0x0f << ((i & 0x07)*4));
|
||||
NAF_K->words[i/8] |= (ki << ((i & 0x07)*4));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
naf4_257_get (const naf4_257 *NAF_K, int i)
|
||||
{
|
||||
int ki;
|
||||
|
||||
if (i == 256)
|
||||
ki = NAF_K->last_nibble;
|
||||
else
|
||||
{
|
||||
ki = NAF_K->words[i/8] >> ((i & 0x07)*4);
|
||||
ki &= 0x0f;
|
||||
}
|
||||
|
||||
return ki;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* convert 256-bit bignum into non-adjacent form (NAF)
|
||||
*/
|
||||
void
|
||||
compute_naf4_257 (naf4_257 *NAF_K, const bn256 *K)
|
||||
{
|
||||
int i = 0;
|
||||
bn256 K_tmp[1];
|
||||
uint32_t carry = 0;
|
||||
|
||||
memcpy (K_tmp, K, sizeof (bn256));
|
||||
memset (NAF_K, 0, sizeof (naf4_257));
|
||||
|
||||
while (!bn256_is_zero (K_tmp))
|
||||
{
|
||||
if (bn256_is_even (K_tmp))
|
||||
naf4_257_set (NAF_K, i, 0);
|
||||
else
|
||||
{
|
||||
int ki = (K_tmp->words[0]) & 0x0f;
|
||||
|
||||
if ((ki & 0x08))
|
||||
{
|
||||
carry = bn256_add_uint (K_tmp, K_tmp, 16 - ki);
|
||||
ki = ki - 16;
|
||||
}
|
||||
else
|
||||
K_tmp->words[0] &= 0xfffffff0;
|
||||
|
||||
naf4_257_set (NAF_K, i, ki);
|
||||
}
|
||||
|
||||
bn256_shift (K_tmp, K_tmp, -1);
|
||||
if (carry)
|
||||
{
|
||||
K_tmp->words[7] |= 0x80000000;
|
||||
carry = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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];
|
||||
|
||||
/* Elliptic curve: y^2 = x^3 + a*x + b */
|
||||
modp256_sqr (s, P->x);
|
||||
modp256_mul (s, s, P->x);
|
||||
|
||||
modp256_mul (t, coefficient_a, P->x);
|
||||
modp256_add (s, s, t);
|
||||
modp256_add (s, s, coefficient_b);
|
||||
|
||||
modp256_sqr (t, P->y);
|
||||
if (bn256_cmp (s, t) == 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = k * P
|
||||
*
|
||||
* @param NAF_K NAF representation of k
|
||||
* @param P P in affine coordiate
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*
|
||||
* For the curve (cofactor is 1 and n is prime), possible error cases are:
|
||||
*
|
||||
* P is not on the curve.
|
||||
* P = G, k = n
|
||||
* Something wrong in the code.
|
||||
*
|
||||
* Mathmatically, k=1 and P=O is another possible case, but O cannot be
|
||||
* represented by affine coordinate.
|
||||
*/
|
||||
int
|
||||
compute_kP (ac *X, const naf4_257 *NAF_K, const ac *P)
|
||||
{
|
||||
int i;
|
||||
int q_is_infinite = 1;
|
||||
jpc Q[1];
|
||||
ac P3[1], P5[1], P7[1];
|
||||
const ac *p_Pi[4];
|
||||
|
||||
if (point_is_on_the_curve (P) < 0)
|
||||
return -1;
|
||||
|
||||
p_Pi[0] = P;
|
||||
p_Pi[1] = P3;
|
||||
p_Pi[2] = P5;
|
||||
p_Pi[3] = P7;
|
||||
|
||||
{
|
||||
jpc Q1[1];
|
||||
|
||||
memcpy (Q->x, P->x, sizeof (bn256));
|
||||
memcpy (Q->y, P->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->words[0] = 1;
|
||||
|
||||
jpc_double (Q, Q);
|
||||
jpc_add_ac (Q1, Q, P);
|
||||
if (jpc_to_ac (P3, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
jpc_double (Q, Q);
|
||||
jpc_add_ac (Q1, Q, P);
|
||||
if (jpc_to_ac (P5, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
|
||||
memcpy (Q->x, P3->x, sizeof (bn256));
|
||||
memcpy (Q->y, P3->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->words[0] = 1;
|
||||
jpc_double (Q, Q);
|
||||
jpc_add_ac (Q1, Q, P);
|
||||
if (jpc_to_ac (P7, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 256; i >= 0; i--)
|
||||
{
|
||||
int k_i;
|
||||
|
||||
if (!q_is_infinite)
|
||||
jpc_double (Q, Q);
|
||||
|
||||
k_i = naf4_257_get (NAF_K, i);
|
||||
if (k_i)
|
||||
{
|
||||
if (q_is_infinite)
|
||||
{
|
||||
memcpy (Q->x, p_Pi[NAF_K_INDEX(k_i)]->x, sizeof (bn256));
|
||||
if (NAF_K_SIGN (k_i))
|
||||
bn256_sub (Q->y, P256, p_Pi[NAF_K_INDEX(k_i)]->y);
|
||||
else
|
||||
memcpy (Q->y, p_Pi[NAF_K_INDEX(k_i)]->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->words[0] = 1;
|
||||
q_is_infinite = 0;
|
||||
}
|
||||
else
|
||||
jpc_add_ac_signed (Q, Q, p_Pi[NAF_K_INDEX(k_i)], NAF_K_SIGN (k_i));
|
||||
}
|
||||
}
|
||||
|
||||
return jpc_to_ac (X, Q);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* N: order of G
|
||||
*/
|
||||
@@ -520,46 +223,4 @@ static const bn256 MU_lower[1] = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compute signature (r,s) of hash string z with secret key d
|
||||
*/
|
||||
void
|
||||
ecdsa (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
|
||||
{
|
||||
bn256 k[1];
|
||||
ac KG[1];
|
||||
bn512 tmp[1];
|
||||
bn256 k_inv[1];
|
||||
uint32_t carry;
|
||||
|
||||
#define tmp_k k_inv
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
bn256_random (k);
|
||||
if (bn256_sub (tmp_k, k, N) == 0) /* > N, it's too big. */
|
||||
continue;
|
||||
if (bn256_add_uint (tmp_k, tmp_k, 2)) /* > N - 2, still big. */
|
||||
continue;
|
||||
bn256_add_uint (k, k, 1);
|
||||
compute_kG (KG, k);
|
||||
if (bn256_is_ge (KG->x, N))
|
||||
bn256_sub (r, KG->x, N);
|
||||
else
|
||||
memcpy (r, KG->x, sizeof (bn256));
|
||||
}
|
||||
while (bn256_is_zero (r));
|
||||
|
||||
mod_inv (k_inv, k, N);
|
||||
bn256_mul (tmp, r, d);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
carry = bn256_add (s, s, z);
|
||||
if (carry)
|
||||
bn256_sub (s, s, N);
|
||||
bn256_mul (tmp, s, k_inv);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
}
|
||||
while (bn256_is_zero (s));
|
||||
}
|
||||
#include "ecc.c"
|
||||
5
src/ec_p256r1.h
Normal file
5
src/ec_p256r1.h
Normal file
@@ -0,0 +1,5 @@
|
||||
int compute_kP_p256r1 (ac *X, const bn256 *K, const ac *P);
|
||||
|
||||
int compute_kG_p256r1 (ac *X, const bn256 *K);
|
||||
void ecdsa_p256r1 (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d);
|
||||
|
||||
965
src/ecc-edwards.c
Normal file
965
src/ecc-edwards.c
Normal file
@@ -0,0 +1,965 @@
|
||||
/* -*- 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)
|
||||
{
|
||||
uint32_t borrow;
|
||||
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: E - D = -(C+D) : Y3_tmp */
|
||||
mod25638_add (X->y, e, d);
|
||||
/* Negation: it can result borrow, as it is in redundant representation. */
|
||||
borrow = bn256_sub (X->y, n25638, X->y);
|
||||
if (borrow)
|
||||
bn256_add (X->y, X->y, n25638); /* carry ignored */
|
||||
else
|
||||
bn256_add (X->x, X->y, n25638); /* dummy calculation */
|
||||
|
||||
/* Compute: F = E + D = D - C; where a = -1 : E */
|
||||
mod25638_sub (e, d, e);
|
||||
|
||||
/* Compute: H = Z1^2 : D */
|
||||
mod25638_sqr (d, A->z);
|
||||
|
||||
/* Compute: J = F - 2*H : D */
|
||||
mod25638_add (d, d, d);
|
||||
mod25638_sub (d, e, d);
|
||||
|
||||
/* Compute: X3 = (B-C-D)*J = (B+Y3_tmp)*J */
|
||||
mod25638_add (X->x, b, X->y);
|
||||
mod25638_mul (X->x, X->x, d);
|
||||
|
||||
/* Compute: Y3 = F*(E-D) = 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
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
179
src/ecc-mont.c
Normal file
179
src/ecc-mont.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* -*- 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* 121665 = 0x1db41
|
||||
* 1 1101 1011 0100 0001
|
||||
*/
|
||||
static void
|
||||
mod25638_mul_121665 (bn256 *x, const bn256 *a)
|
||||
{
|
||||
uint32_t c;
|
||||
bn256 m[1];
|
||||
|
||||
c = 0;
|
||||
memcpy (x, a, sizeof (bn256)); /* X = A */
|
||||
c += bn256_shift (m, a, 6); c += bn256_add (x, x, m); /* X += A << 6 */
|
||||
c += bn256_shift (m, a, 8); c += bn256_add (x, x, m); /* X += A << 8 */
|
||||
c += bn256_shift (m, a, 9); c += bn256_add (x, x, m); /* X += A << 9 */
|
||||
c += bn256_shift (m, a, 11); c += bn256_add (x, x, m); /* X += A << 11 */
|
||||
c += bn256_shift (m, a, 12); c += bn256_add (x, x, m); /* X += A << 12 */
|
||||
c += bn256_shift (m, a, 14); c += bn256_add (x, x, m); /* X += A << 14 */
|
||||
c += bn256_shift (m, a, 15); c += bn256_add (x, x, m); /* X += A << 15 */
|
||||
c += bn256_shift (m, a, 16); c += bn256_add (x, x, m); /* X += A << 16 */
|
||||
|
||||
c *= 38;
|
||||
c = bn256_add_uint (x, x, c);
|
||||
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. */
|
||||
mod_inv (res, p0->z, p25519);
|
||||
mod25638_mul (res, res, p0->x);
|
||||
mod25519_reduce (res);
|
||||
}
|
||||
368
src/ecc.c
Normal file
368
src/ecc.c
Normal file
@@ -0,0 +1,368 @@
|
||||
/* -*- coding: utf-8 -*-
|
||||
* ecc.c - Elliptic curve over GF(prime)
|
||||
*
|
||||
* Copyright (C) 2011, 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.
|
||||
*
|
||||
* 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] Suite B Implementer's Guide to FIPS 186-3 (ECDSA), February 3, 2010.
|
||||
*
|
||||
* [2] Michael Brown, Darrel Hankerson, Julio López, and Alfred Menezes,
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields,
|
||||
* Proceedings of the 2001 Conference on Topics in Cryptology: The
|
||||
* Cryptographer's Track at RSA
|
||||
* Pages 250-265, Springer-Verlag London, UK, 2001
|
||||
* ISBN:3-540-41898-9
|
||||
*
|
||||
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
|
||||
* A comb method to render ECC resistant against Side Channel Attacks,
|
||||
* 2004
|
||||
*/
|
||||
|
||||
#include "field-group-select.h"
|
||||
|
||||
/*
|
||||
* Coefficients
|
||||
*/
|
||||
/*
|
||||
* static const bn256 *coefficient_a;
|
||||
* static const bn256 *coefficient_b;
|
||||
*/
|
||||
/*
|
||||
* N: order of G
|
||||
*/
|
||||
/*
|
||||
* static const bn256 N[1];
|
||||
*/
|
||||
/*
|
||||
* MU = 2^512 / N
|
||||
* MU = ( (1 << 256) | MU_lower )
|
||||
*/
|
||||
/*
|
||||
* static const bn256 MU_lower[1];
|
||||
*/
|
||||
|
||||
/*
|
||||
* w = 4
|
||||
* m = 256
|
||||
* d = 64
|
||||
* e = 32
|
||||
*/
|
||||
|
||||
/*
|
||||
* static const ac precomputed_KG[15];
|
||||
* static const ac precomputed_2E_KG[15];
|
||||
*/
|
||||
|
||||
#if TEST
|
||||
/*
|
||||
* Generator of Elliptic curve over GF(p256)
|
||||
*/
|
||||
const ac *G = &precomputed_KG[0];
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
get_vk (const bn256 *K, int i)
|
||||
{
|
||||
uint32_t w0, w1, w2, w3;
|
||||
|
||||
if (i < 32)
|
||||
{
|
||||
w3 = K->word[6]; w2 = K->word[4]; w1 = K->word[2]; w0 = K->word[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
w3 = K->word[7]; w2 = K->word[5]; w1 = K->word[3]; w0 = K->word[1];
|
||||
i -= 32;
|
||||
}
|
||||
|
||||
w3 >>= i; w2 >>= i; w1 >>= i; w0 >>= i;
|
||||
return ((w3 & 1) << 3) | ((w2 & 1) << 2) | ((w1 & 1) << 1) | (w0 & 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = k * G
|
||||
*
|
||||
* @param K scalar k
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
int
|
||||
FUNC(compute_kG) (ac *X, const bn256 *K)
|
||||
{
|
||||
uint8_t index[64]; /* Lower 4-bit for index absolute value, msb is
|
||||
for sign (encoded as: 0 means 1, 1 means -1). */
|
||||
bn256 K_dash[1];
|
||||
jpc Q[1], tmp[1], *dst;
|
||||
int i;
|
||||
int vk;
|
||||
uint32_t k_is_even = bn256_is_even (K);
|
||||
|
||||
bn256_sub_uint (K_dash, K, k_is_even);
|
||||
/* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */
|
||||
|
||||
/* Fill index. */
|
||||
vk = get_vk (K_dash, 0);
|
||||
for (i = 1; i < 64; i++)
|
||||
{
|
||||
int vk_next, is_zero;
|
||||
|
||||
vk_next = get_vk (K_dash, i);
|
||||
is_zero = (vk_next == 0);
|
||||
index[i-1] = (vk - 1) | (is_zero << 7);
|
||||
vk = (is_zero ? vk : vk_next);
|
||||
}
|
||||
index[63] = vk - 1;
|
||||
|
||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||
for (i = 31; i >= 0; i--)
|
||||
{
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_add_ac_signed) (Q, Q, &precomputed_2E_KG[index[i+32]&0x0f],
|
||||
index[i+32] >> 7);
|
||||
FUNC(jpc_add_ac_signed) (Q, Q, &precomputed_KG[index[i]&0x0f],
|
||||
index[i] >> 7);
|
||||
}
|
||||
|
||||
dst = k_is_even ? Q : tmp;
|
||||
FUNC(jpc_add_ac) (dst, Q, &precomputed_KG[0]);
|
||||
|
||||
return FUNC(jpc_to_ac) (X, Q);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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];
|
||||
|
||||
/* Elliptic curve: y^2 = x^3 + a*x + b */
|
||||
MFNC(sqr) (s, P->x);
|
||||
MFNC(mul) (s, s, P->x);
|
||||
|
||||
#ifdef COEFFICIENT_A_IS_ZERO
|
||||
MFNC(mul) (t, coefficient_a, P->x);
|
||||
MFNC(add) (s, s, t);
|
||||
#endif
|
||||
MFNC(add) (s, s, coefficient_b);
|
||||
|
||||
MFNC(sqr) (t, P->y);
|
||||
if (bn256_cmp (s, t) == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_vk_kP (const bn256 *K, int i)
|
||||
{
|
||||
uint32_t w;
|
||||
uint8_t blk = i/32;
|
||||
uint8_t pos = i%32;
|
||||
uint8_t col = 3*(pos % 11) + (pos >= 11) + (pos >= 22);
|
||||
uint8_t word_index = (blk * 3) + (pos / 11);
|
||||
|
||||
w = ((K->word[word_index] >> col) & 7);
|
||||
if (word_index < 7 && (pos == 10 || pos == 21))
|
||||
{
|
||||
uint8_t mask;
|
||||
uint8_t shift;
|
||||
|
||||
word_index++;
|
||||
if (pos == 10)
|
||||
{
|
||||
shift = 2;
|
||||
mask = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift = 1;
|
||||
mask = 6;
|
||||
}
|
||||
|
||||
w |= ((K->word[word_index] << shift) & mask);
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = k * P
|
||||
*
|
||||
* @param K scalar k
|
||||
* @param P P in affine coordiate
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*
|
||||
* For the curve (cofactor is 1 and n is prime), possible error cases are:
|
||||
*
|
||||
* P is not on the curve.
|
||||
* P = G, k = n
|
||||
* Something wrong in the code.
|
||||
*
|
||||
* Mathmatically, k=1 and P=O is another possible case, but O cannot be
|
||||
* represented by affine coordinate.
|
||||
*/
|
||||
int
|
||||
FUNC(compute_kP) (ac *X, const bn256 *K, const ac *P)
|
||||
{
|
||||
uint8_t index[86]; /* Lower 2-bit for index absolute value, msb is
|
||||
for sign (encoded as: 0 means 1, 1 means -1). */
|
||||
bn256 K_dash[1];
|
||||
uint32_t k_is_even = bn256_is_even (K);
|
||||
jpc Q[1], tmp[1], *dst;
|
||||
int i;
|
||||
int vk;
|
||||
ac P3[1], P5[1], P7[1];
|
||||
const ac *p_Pi[4];
|
||||
|
||||
if (point_is_on_the_curve (P) < 0)
|
||||
return -1;
|
||||
|
||||
if (bn256_sub (K_dash, K, N) == 0) /* >= N, it's too big. */
|
||||
return -1;
|
||||
|
||||
bn256_sub_uint (K_dash, K, k_is_even);
|
||||
/* It keeps the condition: 1 <= K' <= N - 2, and K' is odd. */
|
||||
|
||||
p_Pi[0] = P;
|
||||
p_Pi[1] = P3;
|
||||
p_Pi[2] = P5;
|
||||
p_Pi[3] = P7;
|
||||
|
||||
{
|
||||
jpc Q1[1];
|
||||
|
||||
memcpy (Q->x, P->x, sizeof (bn256));
|
||||
memcpy (Q->y, P->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->word[0] = 1;
|
||||
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_add_ac) (Q1, Q, P);
|
||||
if (FUNC(jpc_to_ac) (P3, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_add_ac) (Q1, Q, P);
|
||||
if (FUNC(jpc_to_ac) (P5, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
|
||||
memcpy (Q->x, P3->x, sizeof (bn256));
|
||||
memcpy (Q->y, P3->y, sizeof (bn256));
|
||||
memset (Q->z, 0, sizeof (bn256));
|
||||
Q->z->word[0] = 1;
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_add_ac) (Q1, Q, P);
|
||||
if (FUNC(jpc_to_ac) (P7, Q1) < 0) /* Never occurs, except coding errors. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill index. */
|
||||
vk = get_vk_kP (K_dash, 0);
|
||||
for (i = 1; i < 86; i++)
|
||||
{
|
||||
int vk_next, is_even;
|
||||
|
||||
vk_next = get_vk_kP (K_dash, i);
|
||||
is_even = ((vk_next & 1) == 0);
|
||||
index[i-1] = (is_even << 7) | ((is_even?7-vk:vk-1) >> 1);
|
||||
vk = vk_next + is_even;
|
||||
}
|
||||
index[85] = ((vk - 1) >> 1);
|
||||
|
||||
memset (Q->z, 0, sizeof (bn256)); /* infinity */
|
||||
for (i = 85; i >= 0; i--)
|
||||
{
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_double) (Q, Q);
|
||||
FUNC(jpc_add_ac_signed) (Q, Q, p_Pi[index[i]&0x03], index[i] >> 7);
|
||||
}
|
||||
|
||||
dst = k_is_even ? Q : tmp;
|
||||
FUNC(jpc_add_ac) (dst, Q, &precomputed_KG[0]);
|
||||
|
||||
return FUNC(jpc_to_ac) (X, Q);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Compute signature (r,s) of hash string z with secret key d
|
||||
*/
|
||||
void
|
||||
FUNC(ecdsa) (bn256 *r, bn256 *s, const bn256 *z, const bn256 *d)
|
||||
{
|
||||
bn256 k[1];
|
||||
ac KG[1];
|
||||
bn512 tmp[1];
|
||||
bn256 k_inv[1];
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
#define tmp_k k_inv
|
||||
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
bn256_random (k);
|
||||
if (bn256_add_uint (k, k, 1))
|
||||
continue;
|
||||
if (bn256_sub (tmp_k, k, N) == 0) /* >= N, it's too big. */
|
||||
continue;
|
||||
/* 1 <= k <= N - 1 */
|
||||
FUNC(compute_kG) (KG, k);
|
||||
borrow = bn256_sub (r, KG->x, N);
|
||||
if (borrow)
|
||||
memcpy (r, KG->x, sizeof (bn256));
|
||||
else
|
||||
memcpy (KG->x, r, sizeof (bn256));
|
||||
}
|
||||
while (bn256_is_zero (r));
|
||||
|
||||
mod_inv (k_inv, k, N);
|
||||
bn256_mul (tmp, r, d);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
carry = bn256_add (s, s, z);
|
||||
if (carry)
|
||||
bn256_sub (s, s, N);
|
||||
else
|
||||
bn256_sub ((bn256 *)tmp, s, N);
|
||||
bn256_mul (tmp, s, k_inv);
|
||||
mod_reduce (s, tmp, N, MU_lower);
|
||||
}
|
||||
while (bn256_is_zero (s));
|
||||
|
||||
#undef tmp_k
|
||||
#undef borrow
|
||||
}
|
||||
7
src/field-group-select.h
Normal file
7
src/field-group-select.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#define CONCAT0(a,b) a##b
|
||||
#define CONCAT1(a,b) CONCAT0(a,b)
|
||||
#define CONCAT2(a,b,c) CONCAT1(a,b##c)
|
||||
#define CONCAT3(a,b,c) CONCAT2(a,b,c)
|
||||
|
||||
#define FUNC(func) CONCAT1(func##_,FIELD)
|
||||
#define MFNC(func) CONCAT3(mod,FIELD,_##func)
|
||||
56
src/flash.c
56
src/flash.c
@@ -63,7 +63,6 @@
|
||||
|
||||
#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,12 +77,33 @@ 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 (uint8_t *k)
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint16_t gen0, gen1;
|
||||
uint16_t *gen0_p = (uint16_t *)&_data_pool;
|
||||
uint16_t *gen1_p = (uint16_t *)(&_data_pool + FLASH_PAGE_SIZE);
|
||||
uint8_t *p;
|
||||
int i;
|
||||
|
||||
/* Check data pool generation and choose the page */
|
||||
gen0 = *gen0_p;
|
||||
@@ -97,6 +117,23 @@ flash_init (void)
|
||||
else
|
||||
data_pool = &_data_pool;
|
||||
|
||||
/* For each key, find its address. */
|
||||
p = &_keystore_pool;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
uint8_t *k;
|
||||
|
||||
kd[i].key_addr = NULL;
|
||||
for (k = p; k < p + FLASH_PAGE_SIZE; k += KEY_SIZE)
|
||||
if (key_available_at (k))
|
||||
{
|
||||
kd[i].key_addr = k;
|
||||
break;
|
||||
}
|
||||
|
||||
p += FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
}
|
||||
|
||||
@@ -270,14 +307,16 @@ flash_do_release (const uint8_t *do_data)
|
||||
|
||||
|
||||
uint8_t *
|
||||
flash_key_alloc (void)
|
||||
flash_key_alloc (enum kind_of_key kk)
|
||||
{
|
||||
uint8_t *k;
|
||||
uint8_t *k0, *k;
|
||||
int i;
|
||||
|
||||
/* Seek empty keystore. */
|
||||
k = &_keystore_pool;
|
||||
while (k < &_keystore_pool + FLASH_KEYSTORE_SIZE)
|
||||
/* There is a page for each KK. */
|
||||
k0 = &_keystore_pool + (FLASH_PAGE_SIZE * kk);
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -287,11 +326,10 @@ flash_key_alloc (void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
28
src/gnuk.h
28
src/gnuk.h
@@ -120,7 +120,7 @@ enum kind_of_key {
|
||||
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 uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
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);
|
||||
@@ -148,18 +148,20 @@ extern uint8_t random_bits_start;
|
||||
#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 */
|
||||
uint8_t *key_addr; /* Pointer to encrypted data, and public */
|
||||
uint8_t data[KEY_CONTENT_LEN]; /* decrypted data content */
|
||||
};
|
||||
|
||||
struct key_data_internal {
|
||||
uint32_t data[KEY_CONTENT_LEN/4]; /* p and q */
|
||||
uint32_t data[KEY_CONTENT_LEN/4]; /*
|
||||
* Secret key data.
|
||||
* RSA: p and q, ECDSA: d, EdDSA: a+seed
|
||||
*/
|
||||
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
|
||||
};
|
||||
|
||||
struct prvkey_data {
|
||||
const uint8_t *key_addr;
|
||||
/*
|
||||
* IV: Initial Vector
|
||||
*/
|
||||
@@ -246,9 +248,19 @@ extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash,
|
||||
const uint8_t *signature);
|
||||
extern uint8_t *rsa_genkey (void);
|
||||
|
||||
extern int ecdsa_sign (const uint8_t *hash, uint8_t *output,
|
||||
const struct key_data *kd);
|
||||
extern uint8_t *ecdsa_compute_public (const uint8_t *key_data);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
extern 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);
|
||||
extern uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
|
||||
|
||||
extern const uint8_t *gpg_do_read_simple (uint8_t);
|
||||
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||
|
||||
@@ -5,7 +5,7 @@ __main_stack_size__ = 0x0100; /* Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* main */
|
||||
__process1_stack_size__ = 0x0140; /* ccid */
|
||||
__process2_stack_size__ = 0x0180; /* rng */
|
||||
__process3_stack_size__ = 0x0b00; /* gpg */
|
||||
__process3_stack_size__ = 0x1600; /* gpg */
|
||||
__process4_stack_size__ = 0x0100; /* intr: usb */
|
||||
__process5_stack_size__ = @MSC_SIZE@; /* msc */
|
||||
__process6_stack_size__ = @TIM_SIZE@; /* intr: timer */
|
||||
|
||||
23
src/jpc-ac.h
23
src/jpc-ac.h
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* @brief Jacobian projective coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
bn256 z[1];
|
||||
} jpc;
|
||||
|
||||
/**
|
||||
* @brief Affin coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
} ac;
|
||||
|
||||
void jpc_double (jpc *X, const jpc *A);
|
||||
void jpc_add_ac (jpc *X, const jpc *A, const ac *B);
|
||||
void jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus);
|
||||
int jpc_to_ac (ac *X, const jpc *A);
|
||||
14
src/jpc-ac_p256k1.h
Normal file
14
src/jpc-ac_p256k1.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @brief Jacobian projective coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
bn256 z[1];
|
||||
} jpc;
|
||||
|
||||
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);
|
||||
int jpc_to_ac_p256k1 (ac *X, const jpc *A);
|
||||
14
src/jpc-ac_p256r1.h
Normal file
14
src/jpc-ac_p256r1.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @brief Jacobian projective coordinates
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bn256 x[1];
|
||||
bn256 y[1];
|
||||
bn256 z[1];
|
||||
} jpc;
|
||||
|
||||
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);
|
||||
int jpc_to_ac_p256r1 (ac *X, const jpc *A);
|
||||
152
src/jpc.c
152
src/jpc.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* jpc.c -- arithmetic on Jacobian projective coordinates and Affin coordinates
|
||||
* jpc.c -- arithmetic on Jacobian projective coordinates.
|
||||
*
|
||||
* Copyright (C) 2011, 2013 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
@@ -21,11 +21,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "modp256.h"
|
||||
#include "jpc-ac.h"
|
||||
#include "field-group-select.h"
|
||||
|
||||
/**
|
||||
* @brief X = 2 * A
|
||||
@@ -34,36 +30,48 @@
|
||||
* @param A JPC
|
||||
*/
|
||||
void
|
||||
jpc_double (jpc *X, const jpc *A)
|
||||
FUNC(jpc_double) (jpc *X, const jpc *A)
|
||||
{
|
||||
bn256 a[1], b[1], c[1], tmp0[1];
|
||||
bn256 *d = X->x;
|
||||
bn256 *d;
|
||||
|
||||
modp256_sqr (a, A->y);
|
||||
if (bn256_is_zero (A->z)) /* A is infinite */
|
||||
return;
|
||||
|
||||
d = X->x;
|
||||
MFNC(sqr) (a, A->y);
|
||||
memcpy (b, a, sizeof (bn256));
|
||||
modp256_mul (a, a, A->x);
|
||||
modp256_shift (a, a, 2);
|
||||
MFNC(mul) (a, a, A->x);
|
||||
MFNC(shift) (a, a, 2);
|
||||
|
||||
modp256_sqr (b, b);
|
||||
modp256_shift (b, b, 3);
|
||||
MFNC(sqr) (b, b);
|
||||
MFNC(shift) (b, b, 3);
|
||||
|
||||
modp256_sqr (tmp0, A->z);
|
||||
modp256_sub (c, A->x, tmp0);
|
||||
modp256_add (tmp0, tmp0, A->x);
|
||||
modp256_mul (tmp0, tmp0, c);
|
||||
modp256_shift (c, tmp0, 1);
|
||||
modp256_add (c, c, tmp0);
|
||||
#if defined(COEFFICIENT_A_IS_MINUS_3)
|
||||
MFNC(sqr) (tmp0, A->z);
|
||||
MFNC(sub) (c, A->x, tmp0);
|
||||
MFNC(add) (tmp0, tmp0, A->x);
|
||||
MFNC(mul) (tmp0, tmp0, c);
|
||||
MFNC(shift) (c, tmp0, 1);
|
||||
MFNC(add) (c, c, tmp0);
|
||||
#elif defined (COEFFICIENT_A_IS_ZERO)
|
||||
MFNC(sqr) (tmp0, A->x);
|
||||
MFNC(shift) (c, tmp0, 1);
|
||||
MFNC(add) (c, c, tmp0);
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
|
||||
modp256_sqr (d, c);
|
||||
modp256_shift (tmp0, a, 1);
|
||||
modp256_sub (d, d, tmp0);
|
||||
MFNC(sqr) (d, c);
|
||||
MFNC(shift) (tmp0, a, 1);
|
||||
MFNC(sub) (d, d, tmp0);
|
||||
|
||||
modp256_mul (X->z, A->y, A->z);
|
||||
modp256_shift (X->z, X->z, 1);
|
||||
MFNC(mul) (X->z, A->y, A->z);
|
||||
MFNC(shift) (X->z, X->z, 1);
|
||||
|
||||
modp256_sub (tmp0, a, d);
|
||||
modp256_mul (tmp0, c, tmp0);
|
||||
modp256_sub (X->y, tmp0, b);
|
||||
MFNC(sub) (tmp0, a, d);
|
||||
MFNC(mul) (tmp0, c, tmp0);
|
||||
MFNC(sub) (X->y, tmp0, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,9 +83,9 @@ jpc_double (jpc *X, const jpc *A)
|
||||
* @param MINUS if 1 subtraction, addition otherwise.
|
||||
*/
|
||||
void
|
||||
jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus)
|
||||
FUNC(jpc_add_ac_signed) (jpc *X, const jpc *A, const ac *B, int minus)
|
||||
{
|
||||
bn256 a[1], b[1], c[1], d[1];
|
||||
bn256 a[1], b[1], c[1], d[1], tmp[1];
|
||||
#define minus_B_y c
|
||||
#define c_sqr a
|
||||
#define c_cube b
|
||||
@@ -88,58 +96,66 @@ jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus)
|
||||
#define y3_tmp c
|
||||
#define y1_c_cube a
|
||||
|
||||
if (A->z == 0) /* A is infinite */
|
||||
if (bn256_is_zero (A->z)) /* A is infinite */
|
||||
{
|
||||
memcpy (X->x, B->x, sizeof (bn256));
|
||||
if (minus)
|
||||
bn256_sub (X->y, P256, B->y);
|
||||
{
|
||||
memcpy (tmp, B->y, sizeof (bn256));
|
||||
bn256_sub (X->y, CONST_P256, B->y);
|
||||
}
|
||||
else
|
||||
memcpy (X->y, B->y, sizeof (bn256));
|
||||
{
|
||||
memcpy (X->y, B->y, sizeof (bn256));
|
||||
bn256_sub (tmp, CONST_P256, B->y);
|
||||
}
|
||||
memset (X->z, 0, sizeof (bn256));
|
||||
X->z->words[0] = 1;
|
||||
X->z->word[0] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
modp256_sqr (a, A->z);
|
||||
MFNC(sqr) (a, A->z);
|
||||
memcpy (b, a, sizeof (bn256));
|
||||
modp256_mul (a, a, B->x);
|
||||
MFNC(mul) (a, a, B->x);
|
||||
|
||||
modp256_mul (b, b, A->z);
|
||||
MFNC(mul) (b, b, A->z);
|
||||
if (minus)
|
||||
{
|
||||
bn256_sub (minus_B_y, P256, B->y);
|
||||
modp256_mul (b, b, minus_B_y);
|
||||
bn256_sub (minus_B_y, CONST_P256, B->y);
|
||||
MFNC(mul) (b, b, minus_B_y);
|
||||
}
|
||||
else
|
||||
modp256_mul (b, b, B->y);
|
||||
{
|
||||
bn256_sub (tmp, CONST_P256, B->y);
|
||||
MFNC(mul) (b, b, B->y);
|
||||
}
|
||||
|
||||
if (bn256_cmp (A->x, a) == 0)
|
||||
if (bn256_cmp (A->y, b) == 0)
|
||||
{
|
||||
jpc_double (X, A);
|
||||
return;
|
||||
}
|
||||
if (bn256_cmp (A->x, a) == 0 && bn256_cmp (A->y, b) == 0)
|
||||
{
|
||||
FUNC(jpc_double) (X, A);
|
||||
return;
|
||||
}
|
||||
|
||||
modp256_sub (c, a, A->x);
|
||||
modp256_sub (d, b, A->y);
|
||||
MFNC(sub) (c, a, A->x);
|
||||
MFNC(sub) (d, b, A->y);
|
||||
|
||||
modp256_mul (X->z, A->z, c);
|
||||
MFNC(mul) (X->z, A->z, c);
|
||||
|
||||
modp256_sqr (c_sqr, c);
|
||||
modp256_mul (c_cube, c_sqr, c);
|
||||
MFNC(sqr) (c_sqr, c);
|
||||
MFNC(mul) (c_cube, c_sqr, c);
|
||||
|
||||
modp256_mul (x1_c_sqr, A->x, c_sqr);
|
||||
MFNC(mul) (x1_c_sqr, A->x, c_sqr);
|
||||
|
||||
modp256_sqr (X->x, d);
|
||||
MFNC(sqr) (X->x, d);
|
||||
memcpy (x1_c_sqr_copy, x1_c_sqr, sizeof (bn256));
|
||||
modp256_shift (x1_c_sqr_2, x1_c_sqr, 1);
|
||||
modp256_add (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube);
|
||||
modp256_sub (X->x, X->x, c_cube_plus_x1_c_sqr_2);
|
||||
MFNC(shift) (x1_c_sqr_2, x1_c_sqr, 1);
|
||||
MFNC(add) (c_cube_plus_x1_c_sqr_2, x1_c_sqr_2, c_cube);
|
||||
MFNC(sub) (X->x, X->x, c_cube_plus_x1_c_sqr_2);
|
||||
|
||||
modp256_sub (y3_tmp, x1_c_sqr_copy, X->x);
|
||||
modp256_mul (y3_tmp, y3_tmp, d);
|
||||
modp256_mul (y1_c_cube, A->y, c_cube);
|
||||
modp256_sub (X->y, y3_tmp, y1_c_cube);
|
||||
MFNC(sub) (y3_tmp, x1_c_sqr_copy, X->x);
|
||||
MFNC(mul) (y3_tmp, y3_tmp, d);
|
||||
MFNC(mul) (y1_c_cube, A->y, c_cube);
|
||||
MFNC(sub) (X->y, y3_tmp, y1_c_cube);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,9 +166,9 @@ jpc_add_ac_signed (jpc *X, const jpc *A, const ac *B, int minus)
|
||||
* @param B AC
|
||||
*/
|
||||
void
|
||||
jpc_add_ac (jpc *X, const jpc *A, const ac *B)
|
||||
FUNC(jpc_add_ac) (jpc *X, const jpc *A, const ac *B)
|
||||
{
|
||||
jpc_add_ac_signed (X, A, B, 0);
|
||||
FUNC(jpc_add_ac_signed) (X, A, B, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,17 +181,19 @@ jpc_add_ac (jpc *X, const jpc *A, const ac *B)
|
||||
* Return 0 on success.
|
||||
*/
|
||||
int
|
||||
jpc_to_ac (ac *X, const jpc *A)
|
||||
FUNC(jpc_to_ac) (ac *X, const jpc *A)
|
||||
{
|
||||
bn256 z_inv[1], z_inv_sqr[1];
|
||||
|
||||
if (modp256_inv (z_inv, A->z) < 0)
|
||||
if (bn256_is_zero (A->z))
|
||||
return -1;
|
||||
|
||||
modp256_sqr (z_inv_sqr, z_inv);
|
||||
modp256_mul (z_inv, z_inv, z_inv_sqr);
|
||||
mod_inv (z_inv, A->z, CONST_P256);
|
||||
|
||||
modp256_mul (X->x, A->x, z_inv_sqr);
|
||||
modp256_mul (X->y, A->y, z_inv);
|
||||
MFNC(sqr) (z_inv_sqr, z_inv);
|
||||
MFNC(mul) (z_inv, z_inv, z_inv_sqr);
|
||||
|
||||
MFNC(mul) (X->x, A->x, z_inv_sqr);
|
||||
MFNC(mul) (X->y, A->y, z_inv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
36
src/jpc_p256k1.c
Normal file
36
src/jpc_p256k1.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* jpc_p256k1.c -- arithmetic on Jacobian projective coordinates for p256k1.
|
||||
*
|
||||
* 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 "mod.h"
|
||||
#include "modp256k1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256k1.h"
|
||||
|
||||
#define FIELD p256k1
|
||||
#define CONST_P256 P256K1
|
||||
#define COEFFICIENT_A_IS_ZERO 1
|
||||
|
||||
#include "jpc.c"
|
||||
36
src/jpc_p256r1.c
Normal file
36
src/jpc_p256r1.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* jpc_p256r1.c -- arithmetic on Jacobian projective coordinates for p256r1.
|
||||
*
|
||||
* 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 "mod.h"
|
||||
#include "modp256r1.h"
|
||||
#include "affine.h"
|
||||
#include "jpc-ac_p256r1.h"
|
||||
|
||||
#define FIELD p256r1
|
||||
#define CONST_P256 P256R1
|
||||
#define COEFFICIENT_A_IS_MINUS_3 1
|
||||
|
||||
#include "jpc.c"
|
||||
367
src/mod.c
367
src/mod.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* mod.c -- modulo arithmetic
|
||||
*
|
||||
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -39,157 +39,316 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
uint32_t borrow_next;
|
||||
|
||||
memset (q, 0, sizeof (bn256));
|
||||
q->words[0] = A->words[15];
|
||||
q->word[0] = A->word[15];
|
||||
bn256_mul (tmp, q, MU_lower);
|
||||
tmp->words[8] += A->words[15];
|
||||
carry = (tmp->words[8] < A->words[15]);
|
||||
tmp->words[9] += carry;
|
||||
tmp->word[8] += A->word[15];
|
||||
carry = (tmp->word[8] < A->word[15]);
|
||||
tmp->word[9] += carry;
|
||||
|
||||
q->words[7] = A->words[14];
|
||||
q->words[6] = A->words[13];
|
||||
q->words[5] = A->words[12];
|
||||
q->words[4] = A->words[11];
|
||||
q->words[3] = A->words[10];
|
||||
q->words[2] = A->words[9];
|
||||
q->words[1] = A->words[8];
|
||||
q->words[0] = A->words[7];
|
||||
q->word[7] = A->word[14];
|
||||
q->word[6] = A->word[13];
|
||||
q->word[5] = A->word[12];
|
||||
q->word[4] = A->word[11];
|
||||
q->word[3] = A->word[10];
|
||||
q->word[2] = A->word[9];
|
||||
q->word[1] = A->word[8];
|
||||
q->word[0] = A->word[7];
|
||||
bn256_mul (q_big, q, MU_lower);
|
||||
bn256_add ((bn256 *)&q_big->words[8], (bn256 *)&q_big->words[8], q);
|
||||
bn256_add ((bn256 *)&q_big->word[8], (bn256 *)&q_big->word[8], q);
|
||||
|
||||
q->words[0] = q_big->words[9] + tmp->words[1];
|
||||
carry = (q->words[0] < tmp->words[1]);
|
||||
q->word[0] = q_big->word[9] + tmp->word[1];
|
||||
carry = (q->word[0] < tmp->word[1]);
|
||||
|
||||
q->words[1] = q_big->words[10] + carry;
|
||||
carry = (q->words[1] < carry);
|
||||
q->words[1] += tmp->words[2];
|
||||
carry += (q->words[1] < tmp->words[2]);
|
||||
q->word[1] = q_big->word[10] + carry;
|
||||
carry = (q->word[1] < carry);
|
||||
q->word[1] += tmp->word[2];
|
||||
carry += (q->word[1] < tmp->word[2]);
|
||||
|
||||
q->words[2] = q_big->words[11] + carry;
|
||||
carry = (q->words[2] < carry);
|
||||
q->words[2] += tmp->words[3];
|
||||
carry += (q->words[2] < tmp->words[3]);
|
||||
q->word[2] = q_big->word[11] + carry;
|
||||
carry = (q->word[2] < carry);
|
||||
q->word[2] += tmp->word[3];
|
||||
carry += (q->word[2] < tmp->word[3]);
|
||||
|
||||
q->words[3] = q_big->words[12] + carry;
|
||||
carry = (q->words[3] < carry);
|
||||
q->words[3] += tmp->words[4];
|
||||
carry += (q->words[3] < tmp->words[4]);
|
||||
q->word[3] = q_big->word[12] + carry;
|
||||
carry = (q->word[3] < carry);
|
||||
q->word[3] += tmp->word[4];
|
||||
carry += (q->word[3] < tmp->word[4]);
|
||||
|
||||
q->words[4] = q_big->words[13] + carry;
|
||||
carry = (q->words[4] < carry);
|
||||
q->words[4] += tmp->words[5];
|
||||
carry += (q->words[4] < tmp->words[5]);
|
||||
q->word[4] = q_big->word[13] + carry;
|
||||
carry = (q->word[4] < carry);
|
||||
q->word[4] += tmp->word[5];
|
||||
carry += (q->word[4] < tmp->word[5]);
|
||||
|
||||
q->words[5] = q_big->words[14] + carry;
|
||||
carry = (q->words[5] < carry);
|
||||
q->words[5] += tmp->words[6];
|
||||
carry += (q->words[5] < tmp->words[6]);
|
||||
q->word[5] = q_big->word[14] + carry;
|
||||
carry = (q->word[5] < carry);
|
||||
q->word[5] += tmp->word[6];
|
||||
carry += (q->word[5] < tmp->word[6]);
|
||||
|
||||
q->words[6] = q_big->words[15] + carry;
|
||||
carry = (q->words[6] < carry);
|
||||
q->words[6] += tmp->words[7];
|
||||
carry += (q->words[6] < tmp->words[7]);
|
||||
q->word[6] = q_big->word[15] + carry;
|
||||
carry = (q->word[6] < carry);
|
||||
q->word[6] += tmp->word[7];
|
||||
carry += (q->word[6] < tmp->word[7]);
|
||||
|
||||
q->words[7] = carry;
|
||||
q->words[7] += tmp->words[8];
|
||||
carry = (q->words[7] < tmp->words[8]);
|
||||
q->word[7] = carry;
|
||||
q->word[7] += tmp->word[8];
|
||||
carry = (q->word[7] < tmp->word[8]);
|
||||
|
||||
memset (q_big, 0, sizeof (bn512));
|
||||
q_big->words[8] = A->words[8];
|
||||
q_big->words[7] = A->words[7];
|
||||
q_big->words[6] = A->words[6];
|
||||
q_big->words[5] = A->words[5];
|
||||
q_big->words[4] = A->words[4];
|
||||
q_big->words[3] = A->words[3];
|
||||
q_big->words[2] = A->words[2];
|
||||
q_big->words[1] = A->words[1];
|
||||
q_big->words[0] = A->words[0];
|
||||
q_big->word[8] = A->word[8];
|
||||
q_big->word[7] = A->word[7];
|
||||
q_big->word[6] = A->word[6];
|
||||
q_big->word[5] = A->word[5];
|
||||
q_big->word[4] = A->word[4];
|
||||
q_big->word[3] = A->word[3];
|
||||
q_big->word[2] = A->word[2];
|
||||
q_big->word[1] = A->word[1];
|
||||
q_big->word[0] = A->word[0];
|
||||
|
||||
bn256_mul (tmp, q, B);
|
||||
tmp->word[8] += carry * B->word[0];
|
||||
tmp->word[15] = tmp->word[14] = tmp->word[13] = tmp->word[12]
|
||||
= tmp->word[11] = tmp->word[10] = tmp->word[9] = 0;
|
||||
|
||||
borrow = bn256_sub (X, (bn256 *)&q_big->word[0], (bn256 *)&tmp->word[0]);
|
||||
borrow_next = (q_big->word[8] < borrow);
|
||||
q_big->word[8] -= borrow;
|
||||
borrow_next += (q_big->word[8] < tmp->word[8]);
|
||||
q_big->word[8] -= tmp->word[8];
|
||||
|
||||
carry = q_big->word[8];
|
||||
if (carry)
|
||||
tmp->words[8] += B->words[0];
|
||||
tmp->words[15] = tmp->words[14] = tmp->words[13] = tmp->words[12]
|
||||
= tmp->words[11] = tmp->words[10] = tmp->words[9] = 0;
|
||||
carry -= bn256_sub (X, X, B);
|
||||
else
|
||||
bn256_sub (q, X, B);
|
||||
|
||||
borrow = bn256_sub (X, (bn256 *)&q_big->words[0], (bn256 *)&tmp->words[0]);
|
||||
borrow_next = (q_big->words[8] < borrow);
|
||||
q_big->words[8] -= borrow;
|
||||
borrow_next += (q_big->words[8] < tmp->words[8]);
|
||||
q_big->words[8] -= tmp->words[8];
|
||||
if (carry)
|
||||
carry -= bn256_sub (X, X, B);
|
||||
else
|
||||
bn256_sub (q, X, B);
|
||||
|
||||
carry = q_big->words[8];
|
||||
while (carry)
|
||||
{
|
||||
borrow_next = bn256_sub (X, X, B);
|
||||
carry -= borrow_next;
|
||||
}
|
||||
|
||||
if (bn256_is_ge (X, B))
|
||||
bn256_sub (X, X, B);
|
||||
borrow = bn256_sub (q, X, B);
|
||||
if (borrow)
|
||||
memcpy (q, X, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, q, sizeof (bn256));
|
||||
#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).
|
||||
* If N==0, return 0.
|
||||
*
|
||||
*/
|
||||
void
|
||||
mod_inv (bn256 *C, const bn256 *X, const bn256 *N)
|
||||
{
|
||||
bn256 u[1], v[1];
|
||||
bn256 u[1], v[1], tmp[1];
|
||||
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
int n = MAX_GCD_STEPS_BN256;
|
||||
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, X, sizeof (bn256));
|
||||
memcpy (v, N, sizeof (bn256));
|
||||
|
||||
while (!bn256_is_zero (u))
|
||||
while (n--)
|
||||
{
|
||||
while (bn256_is_even (u))
|
||||
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_shift (A, A, -1);
|
||||
else
|
||||
{
|
||||
int carry = bn256_add (A, A, N);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
if (carry)
|
||||
A->words[7] |= 0x80000000;
|
||||
bn256_add (tmp, A, N);
|
||||
carry = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, N);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
while (bn256_is_even (v))
|
||||
{
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
bn256_shift (C, C, -1);
|
||||
{
|
||||
bn256_add (tmp, C, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, N);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, A, N);
|
||||
}
|
||||
else
|
||||
{
|
||||
int carry = bn256_add (C, C, N);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
if (carry)
|
||||
C->words[7] |= 0x80000000;
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, tmp, N);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
if (bn256_is_ge (u, v))
|
||||
{
|
||||
int borrow;
|
||||
case 1:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, N);
|
||||
|
||||
bn256_sub (u, u, v);
|
||||
borrow = bn256_sub (A, A, C);
|
||||
if (borrow)
|
||||
bn256_add (A, A, N);
|
||||
}
|
||||
else
|
||||
{
|
||||
int borrow;
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_sub (v, v, u);
|
||||
borrow = bn256_sub (C, C, A);
|
||||
if (borrow)
|
||||
bn256_add (C, C, N);
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
{
|
||||
bn256_add (tmp, C, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (C, C, N);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
C->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, A, N);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, tmp, N);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
{
|
||||
bn256_add (tmp, A, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (A, A, N);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
A->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, N);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (tmp, tmp))
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, A, N);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (tmp, tmp, tmp);
|
||||
borrow = bn256_sub (tmp, tmp, tmp);
|
||||
if (borrow)
|
||||
bn256_add (tmp, tmp, tmp);
|
||||
else
|
||||
bn256_add (tmp, tmp, N);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, N);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
if (bn256_is_even (tmp))
|
||||
{
|
||||
bn256_add (tmp, tmp, N);
|
||||
carry = 0;
|
||||
}
|
||||
else
|
||||
carry = bn256_add (tmp, tmp, N);
|
||||
|
||||
bn256_shift (tmp, tmp, -1);
|
||||
tmp->word[7] |= carry * 0x80000000;
|
||||
|
||||
if (bn256_is_ge (u, v))
|
||||
{
|
||||
bn256_sub (u, u, v);
|
||||
borrow = bn256_sub (A, A, C);
|
||||
if (borrow)
|
||||
bn256_add (A, A, N);
|
||||
else
|
||||
bn256_add (tmp, A, N);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (v, v, u);
|
||||
borrow = bn256_sub (C, C, A);
|
||||
if (borrow)
|
||||
bn256_add (C, C, N);
|
||||
else
|
||||
bn256_add (tmp, C, N);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef borrow
|
||||
}
|
||||
|
||||
312
src/mod25638.c
Normal file
312
src/mod25638.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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_,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" )
|
||||
#endif
|
||||
|
||||
/*
|
||||
256 224 192 160 128 96 64 32 0
|
||||
2^256
|
||||
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 32
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffe0
|
||||
2^256 - 32 - 4
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffdc
|
||||
2^256 - 32 - 4 - 2
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffda
|
||||
*/
|
||||
const bn256 n25638[1] = {
|
||||
{{0xffffffda, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }} };
|
||||
|
||||
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;
|
||||
bn256 tmp[1];
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, n25638);
|
||||
else
|
||||
bn256_sub (tmp, X, n25638);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A - B) mod 2^256-38
|
||||
*/
|
||||
void
|
||||
mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, n25638);
|
||||
else
|
||||
bn256_add (tmp, X, n25638);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
s = &A->word[0];
|
||||
ADDWORD_256 (s, c0, c);
|
||||
A->word[0] += c * 38;
|
||||
memcpy (X, A, sizeof (bn256));
|
||||
#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));
|
||||
}
|
||||
d[i] = (uint32_t)r;
|
||||
|
||||
carry = bn256_add_uint ((bn256 *)A, (bn256 *)A, A->word[8] * 38);
|
||||
A->word[0] += carry * 38;
|
||||
}
|
||||
|
||||
memcpy (X, A, sizeof (bn256));
|
||||
#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);
|
||||
}
|
||||
|
||||
static void
|
||||
add19 (bn256 *r, bn256 *x)
|
||||
{
|
||||
uint32_t v;
|
||||
int i;
|
||||
|
||||
v = 19;
|
||||
for (i = 0; i < BN256_WORDS; i++)
|
||||
{
|
||||
r->word[i] = x->word[i] + v;
|
||||
v = (r->word[i] < v);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @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)
|
||||
{
|
||||
add19 (r0, r0);
|
||||
q = (r0->word[7] >> 31);
|
||||
r0->word[7] &= 0x7fffffff;
|
||||
if (q)
|
||||
{
|
||||
add19 (r1, r0);
|
||||
q = (r1->word[7] >> 31);
|
||||
r1->word[7] &= 0x7fffffff;
|
||||
flag = 0;
|
||||
}
|
||||
else
|
||||
flag = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
add19 (r1, r0); /* dummy */
|
||||
q = (r1->word[7] >> 31); /* dummy */
|
||||
r1->word[7] &= 0x7fffffff; /* dummy */
|
||||
if (q)
|
||||
flag = 2;
|
||||
else
|
||||
flag = 3;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
add19 (r1, r0);
|
||||
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));
|
||||
}
|
||||
}
|
||||
8
src/mod25638.h
Normal file
8
src/mod25638.h
Normal file
@@ -0,0 +1,8 @@
|
||||
extern const bn256 n25638[1];
|
||||
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);
|
||||
305
src/modp256.c
305
src/modp256.c
@@ -1,305 +0,0 @@
|
||||
/*
|
||||
* modp256.c -- modulo P256 arithmetic
|
||||
*
|
||||
* Copyright (C) 2011, 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* p256 = 2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "modp256.h"
|
||||
|
||||
/*
|
||||
256 224 192 160 128 96 64 32 0
|
||||
2^256
|
||||
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224
|
||||
0 ffffffff 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192
|
||||
0 ffffffff 00000001 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192 + 2^96
|
||||
0 ffffffff 00000001 00000000 00000000 00000001 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
0 ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
|
||||
*/
|
||||
const bn256 p256 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0xffffffff} };
|
||||
|
||||
/**
|
||||
* @brief X = (A + B) mod p256
|
||||
*/
|
||||
void
|
||||
modp256_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int carry;
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, P256);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A - B) mod p256
|
||||
*/
|
||||
void
|
||||
modp256_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
int borrow;
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, P256);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A mod p256
|
||||
*/
|
||||
void
|
||||
modp256_reduce (bn256 *X, const bn512 *A)
|
||||
{
|
||||
bn256 tmp[1];
|
||||
|
||||
#define S1 X
|
||||
#define S2 tmp
|
||||
#define S3 tmp
|
||||
#define S4 tmp
|
||||
#define S5 tmp
|
||||
#define S6 tmp
|
||||
#define S7 tmp
|
||||
#define S8 tmp
|
||||
#define S9 tmp
|
||||
|
||||
S1->words[7] = A->words[7];
|
||||
S1->words[6] = A->words[6];
|
||||
S1->words[5] = A->words[5];
|
||||
S1->words[4] = A->words[4];
|
||||
S1->words[3] = A->words[3];
|
||||
S1->words[2] = A->words[2];
|
||||
S1->words[1] = A->words[1];
|
||||
S1->words[0] = A->words[0];
|
||||
/* X = S1 */
|
||||
|
||||
S2->words[7] = A->words[15];
|
||||
S2->words[6] = A->words[14];
|
||||
S2->words[5] = A->words[13];
|
||||
S2->words[4] = A->words[12];
|
||||
S2->words[3] = A->words[11];
|
||||
S2->words[2] = S2->words[1] = S2->words[0] = 0;
|
||||
/* X += 2 * S2 */
|
||||
modp256_add (X, X, S2);
|
||||
modp256_add (X, X, S2);
|
||||
|
||||
S3->words[7] = 0;
|
||||
S3->words[6] = A->words[15];
|
||||
S3->words[5] = A->words[14];
|
||||
S3->words[4] = A->words[13];
|
||||
S3->words[3] = A->words[12];
|
||||
S3->words[2] = S3->words[1] = S3->words[0] = 0;
|
||||
/* X += 2 * S3 */
|
||||
modp256_add (X, X, S3);
|
||||
modp256_add (X, X, S3);
|
||||
|
||||
S4->words[7] = A->words[15];
|
||||
S4->words[6] = A->words[14];
|
||||
S4->words[5] = S4->words[4] = S4->words[3] = 0;
|
||||
S4->words[2] = A->words[10];
|
||||
S4->words[1] = A->words[9];
|
||||
S4->words[0] = A->words[8];
|
||||
/* X += S4 */
|
||||
modp256_add (X, X, S4);
|
||||
|
||||
S5->words[7] = A->words[8];
|
||||
S5->words[6] = A->words[13];
|
||||
S5->words[5] = A->words[15];
|
||||
S5->words[4] = A->words[14];
|
||||
S5->words[3] = A->words[13];
|
||||
S5->words[2] = A->words[11];
|
||||
S5->words[1] = A->words[10];
|
||||
S5->words[0] = A->words[9];
|
||||
/* X += S5 */
|
||||
modp256_add (X, X, S5);
|
||||
|
||||
S6->words[7] = A->words[10];
|
||||
S6->words[6] = A->words[8];
|
||||
S6->words[5] = S6->words[4] = S6->words[3] = 0;
|
||||
S6->words[2] = A->words[13];
|
||||
S6->words[1] = A->words[12];
|
||||
S6->words[0] = A->words[11];
|
||||
/* X -= S6 */
|
||||
modp256_sub (X, X, S6);
|
||||
|
||||
S7->words[7] = A->words[11];
|
||||
S7->words[6] = A->words[9];
|
||||
S7->words[5] = S7->words[4] = 0;
|
||||
S7->words[3] = A->words[15];
|
||||
S7->words[2] = A->words[14];
|
||||
S7->words[1] = A->words[13];
|
||||
S7->words[0] = A->words[12];
|
||||
/* X -= S7 */
|
||||
modp256_sub (X, X, S7);
|
||||
|
||||
S8->words[7] = A->words[12];
|
||||
S8->words[6] = 0;
|
||||
S8->words[5] = A->words[10];
|
||||
S8->words[4] = A->words[9];
|
||||
S8->words[3] = A->words[8];
|
||||
S8->words[2] = A->words[15];
|
||||
S8->words[1] = A->words[14];
|
||||
S8->words[0] = A->words[13];
|
||||
/* X -= S8 */
|
||||
modp256_sub (X, X, S8);
|
||||
|
||||
S9->words[7] = A->words[13];
|
||||
S9->words[6] = 0;
|
||||
S9->words[5] = A->words[11];
|
||||
S9->words[4] = A->words[10];
|
||||
S9->words[3] = A->words[9];
|
||||
S9->words[2] = 0;
|
||||
S9->words[1] = A->words[15];
|
||||
S9->words[0] = A->words[14];
|
||||
/* X -= S9 */
|
||||
modp256_sub (X, X, S9);
|
||||
|
||||
if (bn256_is_ge (X, P256))
|
||||
bn256_sub (X, X, P256);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A * B) mod p256
|
||||
*/
|
||||
void
|
||||
modp256_mul (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
bn512 AB[1];
|
||||
|
||||
bn256_mul (AB, A, B);
|
||||
modp256_reduce (X, AB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A * A mod p256
|
||||
*/
|
||||
void
|
||||
modp256_sqr (bn256 *X, const bn256 *A)
|
||||
{
|
||||
bn512 AA[1];
|
||||
|
||||
bn256_sqr (AA, A);
|
||||
modp256_reduce (X, AA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief C = (1 / a) mod p256
|
||||
*
|
||||
* Return -1 on error.
|
||||
* Return 0 on success.
|
||||
*/
|
||||
int
|
||||
modp256_inv (bn256 *C, const bn256 *a)
|
||||
{
|
||||
bn256 u[1], v[1];
|
||||
bn256 A[1] = { { { 1, 0, 0, 0, 0, 0, 0, 0 } } };
|
||||
|
||||
if (bn256_is_zero (a))
|
||||
return -1;
|
||||
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, a, sizeof (bn256));
|
||||
memcpy (v, P256, sizeof (bn256));
|
||||
|
||||
while (!bn256_is_zero (u))
|
||||
{
|
||||
while (bn256_is_even (u))
|
||||
{
|
||||
bn256_shift (u, u, -1);
|
||||
if (bn256_is_even (A))
|
||||
bn256_shift (A, A, -1);
|
||||
else
|
||||
{
|
||||
int carry = bn256_add (A, A, P256);
|
||||
|
||||
bn256_shift (A, A, -1);
|
||||
if (carry)
|
||||
A->words[7] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
while (bn256_is_even (v))
|
||||
{
|
||||
bn256_shift (v, v, -1);
|
||||
if (bn256_is_even (C))
|
||||
bn256_shift (C, C, -1);
|
||||
else
|
||||
{
|
||||
int carry = bn256_add (C, C, P256);
|
||||
|
||||
bn256_shift (C, C, -1);
|
||||
if (carry)
|
||||
C->words[7] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
if (bn256_is_ge (u, v))
|
||||
{
|
||||
bn256_sub (u, u, v);
|
||||
modp256_sub (A, A, C);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn256_sub (v, v, u);
|
||||
modp256_sub (C, C, A);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod p256
|
||||
* @note shift <= 32
|
||||
*/
|
||||
void
|
||||
modp256_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->words[7] = carry;
|
||||
tmp->words[0] = carry;
|
||||
modp256_add (X, X, tmp);
|
||||
|
||||
tmp->words[7] = 0;
|
||||
tmp->words[0] = 0;
|
||||
tmp->words[6] = carry;
|
||||
tmp->words[3] = carry;
|
||||
modp256_sub (X, X, tmp);
|
||||
|
||||
if (bn256_is_ge (X, P256))
|
||||
bn256_sub (X, X, P256);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
extern const bn256 p256;
|
||||
#define P256 (&p256)
|
||||
|
||||
void modp256_add (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256_sub (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256_reduce (bn256 *X, const bn512 *A);
|
||||
void modp256_mul (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256_sqr (bn256 *X, const bn256 *A);
|
||||
void modp256_shift (bn256 *X, const bn256 *A, int shift);
|
||||
int modp256_inv (bn256 *C, const bn256 *a);
|
||||
315
src/modp256k1.c
Normal file
315
src/modp256k1.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* modp256k1.c -- modulo arithmetic for p256k1
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* p256k1 = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "modp256k1.h"
|
||||
|
||||
/*
|
||||
256 224 192 160 128 96 64 32 0
|
||||
2^256
|
||||
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^32
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 00000000
|
||||
2^256 - 2^32 - 2^9
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffe00
|
||||
2^256 - 2^32 - 2^9 - 2^8
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffd00
|
||||
2^256 - 2^32 - 2^9 - 2^8 - 2^7
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc80
|
||||
2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc40
|
||||
2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc30
|
||||
2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
|
||||
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void
|
||||
modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t carry;
|
||||
bn256 tmp[1];
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, P256K1);
|
||||
else
|
||||
bn256_sub (tmp, X, P256K1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A - B) mod p256
|
||||
*/
|
||||
void
|
||||
modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, P256K1);
|
||||
else
|
||||
bn256_add (tmp, X, P256K1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A mod p256k1
|
||||
*/
|
||||
void
|
||||
modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
{
|
||||
bn256 tmp[1];
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
uint32_t s0, s1;
|
||||
#define s00 tmp->word[0]
|
||||
#define s01 tmp->word[1]
|
||||
#define s02 tmp->word[2]
|
||||
|
||||
#define W0 X
|
||||
#define W1 tmp
|
||||
#define W2 tmp
|
||||
#define W3 tmp
|
||||
#define W4 tmp
|
||||
#define W5 tmp
|
||||
#define W6 tmp
|
||||
#define W7 tmp
|
||||
#define S tmp
|
||||
|
||||
/*
|
||||
* Suppose: P256K1 = 2^256 - CONST
|
||||
* Then, compute: W = A_low + A_high * CONST
|
||||
* 256-bit W0 = W mod 2^256
|
||||
* 64-bit (S1, S0) = W / 2^256
|
||||
* where: CONST = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1
|
||||
*/
|
||||
|
||||
/* W0 = A_low */
|
||||
/* W7 = A_high */
|
||||
/* W0 += W7 */
|
||||
carry = bn256_add (W0, (const bn256 *)&A->word[8], (const bn256 *)A);
|
||||
|
||||
/* W6 = W7 << 4 */
|
||||
/* W0 += W6 */
|
||||
bn256_shift (W6, (const bn256 *)&A->word[8], 4);
|
||||
carry += bn256_add (W0, W0, W6);
|
||||
|
||||
/* W5 = W6 << 2 */
|
||||
/* W0 += W5 */
|
||||
bn256_shift (W5, W6, 2);
|
||||
carry += bn256_add (W0, W0, W5);
|
||||
|
||||
/* W4 = W5 << 1 */
|
||||
/* W0 += W4 */
|
||||
bn256_shift (W4, W5, 1);
|
||||
carry += bn256_add (W0, W0, W4);
|
||||
|
||||
/* W3 = W4 << 1 */
|
||||
/* W0 += W3 */
|
||||
bn256_shift (W3, W4, 1);
|
||||
carry += bn256_add (W0, W0, W3);
|
||||
|
||||
/* W2 = W3 << 1 */
|
||||
/* W0 += W2 */
|
||||
bn256_shift (W2, W3, 1);
|
||||
carry += bn256_add (W0, W0, W2);
|
||||
|
||||
/* W1 = A_high << 32 */
|
||||
/* W0 += W1 */
|
||||
W1->word[7] = A->word[14];
|
||||
W1->word[6] = A->word[13];
|
||||
W1->word[5] = A->word[12];
|
||||
W1->word[4] = A->word[11];
|
||||
W1->word[3] = A->word[10];
|
||||
W1->word[2] = A->word[9];
|
||||
W1->word[1] = A->word[8];
|
||||
W1->word[0] = 0;
|
||||
carry += bn256_add (W0, W0, W1);
|
||||
|
||||
/* (S1, S0) = W / 2^256 */
|
||||
s0 = A->word[15];
|
||||
carry += (s0 >> 28) + (s0 >> 26) + (s0 >> 25) + (s0 >> 24) + (s0 >> 23);
|
||||
carry += s0;
|
||||
s1 = (carry < s0) ? 1 : 0;
|
||||
s0 = carry;
|
||||
|
||||
/*
|
||||
* Compute: S:=(S02, S01, S00), S = (S1,S0)*CONST
|
||||
*/
|
||||
S->word[7] = S->word[6] = S->word[5] = S->word[4] = S->word[3] = 0;
|
||||
|
||||
/* (S02, S01, S00) = (S1, S0) + (S1, S0)*2^32 */
|
||||
s00 = s0;
|
||||
s01 = s0 + s1;
|
||||
s02 = s1 + ((s01 < s0)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^9 */
|
||||
carry = (s0 >> 23) + s01;
|
||||
s02 += (s1 >> 23) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 9) + carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
s00 += (s0 << 9);
|
||||
carry = ((s00 < (s0 << 9))? 1 : 0);
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^8 */
|
||||
carry = (s0 >> 24) + s01;
|
||||
s02 += (s1 >> 24) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 8) + carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
s00 += (s0 << 8);
|
||||
carry = ((s00 < (s0 << 8))? 1 : 0);
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^7 */
|
||||
carry = (s0 >> 25) + s01;
|
||||
s02 += (s1 >> 25) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 7) + carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
s00 += (s0 << 7);
|
||||
carry = ((s00 < (s0 << 7))? 1 : 0);
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^6 */
|
||||
carry = (s0 >> 26) + s01;
|
||||
s02 += (s1 >> 26) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 6) + carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
s00 += (s0 << 6);
|
||||
carry = ((s00 < (s0 << 6))? 1 : 0);
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^4 */
|
||||
carry = (s0 >> 28) + s01;
|
||||
s02 += (s1 >> 28) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 4) + carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
s00 += (s0 << 4);
|
||||
carry = ((s00 < (s0 << 4))? 1 : 0);
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* W0 += S */
|
||||
modp256k1_add (W0, W0, S);
|
||||
|
||||
borrow = bn256_sub (tmp, W0, P256K1);
|
||||
if (borrow)
|
||||
memcpy (tmp, W0, sizeof (bn256));
|
||||
else
|
||||
memcpy (W0, tmp, sizeof (bn256));
|
||||
|
||||
#undef W0
|
||||
#undef W1
|
||||
#undef W2
|
||||
#undef W3
|
||||
#undef W4
|
||||
#undef W5
|
||||
#undef W6
|
||||
#undef W7
|
||||
#undef S
|
||||
#undef s00
|
||||
#undef s01
|
||||
#undef s02
|
||||
#undef borrow
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A * B) mod p256k1
|
||||
*/
|
||||
void
|
||||
modp256k1_mul (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
bn512 AB[1];
|
||||
|
||||
bn256_mul (AB, A, B);
|
||||
modp256k1_reduce (X, AB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A * A mod p256k1
|
||||
*/
|
||||
void
|
||||
modp256k1_sqr (bn256 *X, const bn256 *A)
|
||||
{
|
||||
bn512 AA[1];
|
||||
|
||||
bn256_sqr (AA, A);
|
||||
modp256k1_reduce (X, AA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod p256k1
|
||||
* @note shift < 32
|
||||
*/
|
||||
void
|
||||
modp256k1_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 + (carry << 9);
|
||||
tmp->word[1] = carry + (tmp->word[0] < (carry << 9)) + (carry >> 23);
|
||||
tmp->word[0] = tmp->word[0] + (carry << 8);
|
||||
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 8)) + (carry >> 24);
|
||||
tmp->word[0] = tmp->word[0] + (carry << 7);
|
||||
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 7)) + (carry >> 25);
|
||||
tmp->word[0] = tmp->word[0] + (carry << 6);
|
||||
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 6)) + (carry >> 26);
|
||||
tmp->word[0] = tmp->word[0] + (carry << 4);
|
||||
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 4)) + (carry >> 28);
|
||||
|
||||
modp256k1_add (X, X, tmp);
|
||||
}
|
||||
9
src/modp256k1.h
Normal file
9
src/modp256k1.h
Normal file
@@ -0,0 +1,9 @@
|
||||
extern const bn256 p256k1;
|
||||
#define P256K1 (&p256k1)
|
||||
|
||||
void modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
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);
|
||||
276
src/modp256r1.c
Normal file
276
src/modp256r1.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* modp256r1.c -- modulo arithmetic for p256r1
|
||||
*
|
||||
* Copyright (C) 2011, 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.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* p256 = 2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
#include "modp256r1.h"
|
||||
|
||||
/*
|
||||
256 224 192 160 128 96 64 32 0
|
||||
2^256
|
||||
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224
|
||||
0 ffffffff 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192
|
||||
0 ffffffff 00000001 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192 + 2^96
|
||||
0 ffffffff 00000001 00000000 00000000 00000001 00000000 00000000 00000000
|
||||
2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
0 ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
|
||||
*/
|
||||
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
|
||||
*/
|
||||
void
|
||||
modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t carry;
|
||||
bn256 tmp[1];
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, P256R1);
|
||||
else
|
||||
bn256_sub (tmp, X, P256R1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A - B) mod p256r1
|
||||
*/
|
||||
void
|
||||
modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, P256R1);
|
||||
else
|
||||
bn256_add (tmp, X, P256R1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A mod p256r1
|
||||
*/
|
||||
void
|
||||
modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
{
|
||||
bn256 tmp[1];
|
||||
uint32_t borrow;
|
||||
|
||||
#define S1 X
|
||||
#define S2 tmp
|
||||
#define S3 tmp
|
||||
#define S4 tmp
|
||||
#define S5 tmp
|
||||
#define S6 tmp
|
||||
#define S7 tmp
|
||||
#define S8 tmp
|
||||
#define S9 tmp
|
||||
|
||||
S1->word[7] = A->word[7];
|
||||
S1->word[6] = A->word[6];
|
||||
S1->word[5] = A->word[5];
|
||||
S1->word[4] = A->word[4];
|
||||
S1->word[3] = A->word[3];
|
||||
S1->word[2] = A->word[2];
|
||||
S1->word[1] = A->word[1];
|
||||
S1->word[0] = A->word[0];
|
||||
/* X = S1 */
|
||||
|
||||
S2->word[7] = A->word[15];
|
||||
S2->word[6] = A->word[14];
|
||||
S2->word[5] = A->word[13];
|
||||
S2->word[4] = A->word[12];
|
||||
S2->word[3] = A->word[11];
|
||||
S2->word[2] = S2->word[1] = S2->word[0] = 0;
|
||||
/* X += 2 * S2 */
|
||||
modp256r1_add (X, X, S2);
|
||||
modp256r1_add (X, X, S2);
|
||||
|
||||
S3->word[7] = 0;
|
||||
S3->word[6] = A->word[15];
|
||||
S3->word[5] = A->word[14];
|
||||
S3->word[4] = A->word[13];
|
||||
S3->word[3] = A->word[12];
|
||||
S3->word[2] = S3->word[1] = S3->word[0] = 0;
|
||||
/* X += 2 * S3 */
|
||||
modp256r1_add (X, X, S3);
|
||||
modp256r1_add (X, X, S3);
|
||||
|
||||
S4->word[7] = A->word[15];
|
||||
S4->word[6] = A->word[14];
|
||||
S4->word[5] = S4->word[4] = S4->word[3] = 0;
|
||||
S4->word[2] = A->word[10];
|
||||
S4->word[1] = A->word[9];
|
||||
S4->word[0] = A->word[8];
|
||||
/* X += S4 */
|
||||
modp256r1_add (X, X, S4);
|
||||
|
||||
S5->word[7] = A->word[8];
|
||||
S5->word[6] = A->word[13];
|
||||
S5->word[5] = A->word[15];
|
||||
S5->word[4] = A->word[14];
|
||||
S5->word[3] = A->word[13];
|
||||
S5->word[2] = A->word[11];
|
||||
S5->word[1] = A->word[10];
|
||||
S5->word[0] = A->word[9];
|
||||
/* X += S5 */
|
||||
modp256r1_add (X, X, S5);
|
||||
|
||||
S6->word[7] = A->word[10];
|
||||
S6->word[6] = A->word[8];
|
||||
S6->word[5] = S6->word[4] = S6->word[3] = 0;
|
||||
S6->word[2] = A->word[13];
|
||||
S6->word[1] = A->word[12];
|
||||
S6->word[0] = A->word[11];
|
||||
/* X -= S6 */
|
||||
modp256r1_sub (X, X, S6);
|
||||
|
||||
S7->word[7] = A->word[11];
|
||||
S7->word[6] = A->word[9];
|
||||
S7->word[5] = S7->word[4] = 0;
|
||||
S7->word[3] = A->word[15];
|
||||
S7->word[2] = A->word[14];
|
||||
S7->word[1] = A->word[13];
|
||||
S7->word[0] = A->word[12];
|
||||
/* X -= S7 */
|
||||
modp256r1_sub (X, X, S7);
|
||||
|
||||
S8->word[7] = A->word[12];
|
||||
S8->word[6] = 0;
|
||||
S8->word[5] = A->word[10];
|
||||
S8->word[4] = A->word[9];
|
||||
S8->word[3] = A->word[8];
|
||||
S8->word[2] = A->word[15];
|
||||
S8->word[1] = A->word[14];
|
||||
S8->word[0] = A->word[13];
|
||||
/* X -= S8 */
|
||||
modp256r1_sub (X, X, S8);
|
||||
|
||||
S9->word[7] = A->word[13];
|
||||
S9->word[6] = 0;
|
||||
S9->word[5] = A->word[11];
|
||||
S9->word[4] = A->word[10];
|
||||
S9->word[3] = A->word[9];
|
||||
S9->word[2] = 0;
|
||||
S9->word[1] = A->word[15];
|
||||
S9->word[0] = A->word[14];
|
||||
/* X -= S9 */
|
||||
modp256r1_sub (X, X, S9);
|
||||
|
||||
borrow = bn256_sub (tmp, X, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp, X, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
|
||||
#undef S1
|
||||
#undef S2
|
||||
#undef S3
|
||||
#undef S4
|
||||
#undef S5
|
||||
#undef S6
|
||||
#undef S7
|
||||
#undef S8
|
||||
#undef S9
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = (A * B) mod p256r1
|
||||
*/
|
||||
void
|
||||
modp256r1_mul (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
bn512 AB[1];
|
||||
|
||||
bn256_mul (AB, A, B);
|
||||
modp256r1_reduce (X, AB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief X = A * A mod p256r1
|
||||
*/
|
||||
void
|
||||
modp256r1_sqr (bn256 *X, const bn256 *A)
|
||||
{
|
||||
bn512 AA[1];
|
||||
|
||||
bn256_sqr (AA, A);
|
||||
modp256r1_reduce (X, AA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief X = (A << shift) mod p256r1
|
||||
* @note shift < 32
|
||||
*/
|
||||
void
|
||||
modp256r1_shift (bn256 *X, const bn256 *A, int shift)
|
||||
{
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
bn256 tmp[1];
|
||||
|
||||
carry = bn256_shift (X, A, shift);
|
||||
if (shift < 0)
|
||||
return;
|
||||
|
||||
memset (tmp, 0, sizeof (bn256));
|
||||
tmp->word[7] = carry;
|
||||
tmp->word[0] = carry;
|
||||
modp256r1_add (X, X, tmp);
|
||||
|
||||
tmp->word[7] = 0;
|
||||
tmp->word[0] = 0;
|
||||
tmp->word[6] = carry;
|
||||
tmp->word[3] = carry;
|
||||
modp256r1_sub (X, X, tmp);
|
||||
|
||||
borrow = bn256_sub (tmp, X, P256R1);
|
||||
if (borrow)
|
||||
memcpy (tmp, X, sizeof (bn256));
|
||||
else
|
||||
memcpy (X, tmp, sizeof (bn256));
|
||||
#undef borrow
|
||||
}
|
||||
9
src/modp256r1.h
Normal file
9
src/modp256r1.h
Normal file
@@ -0,0 +1,9 @@
|
||||
extern const bn256 p256r1;
|
||||
#define P256R1 (&p256r1)
|
||||
|
||||
void modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
void modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B);
|
||||
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);
|
||||
47
src/muladd_256.h
Normal file
47
src/muladd_256.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#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)
|
||||
288
src/openpgp-do.c
288
src/openpgp-do.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -34,15 +34,7 @@
|
||||
#include "random.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/aes.h"
|
||||
|
||||
/* Handles possible unaligned access. */
|
||||
static uint32_t
|
||||
fetch_four_bytes (const void *addr)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)addr;
|
||||
|
||||
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
||||
}
|
||||
#include "sha512.h"
|
||||
|
||||
|
||||
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
|
||||
@@ -142,12 +134,26 @@ static const uint8_t algorithm_attr_rsa[] __attribute__ ((aligned (1))) = {
|
||||
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
|
||||
};
|
||||
|
||||
static const uint8_t algorithm_attr_ecdsa[] __attribute__ ((aligned (1))) = {
|
||||
static const uint8_t algorithm_attr_p256r1[] __attribute__ ((aligned (1))) = {
|
||||
9,
|
||||
0x13, /* ECDSA */
|
||||
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 /* OID of NIST curve P-256 */
|
||||
};
|
||||
|
||||
static const uint8_t algorithm_attr_p256k1[] __attribute__ ((aligned (1))) = {
|
||||
6,
|
||||
0x13, /* ECDSA */
|
||||
0x2b, 0x81, 0x04, 0x00, 0x0a /* OID of curve secp256k1 */
|
||||
};
|
||||
|
||||
static const uint8_t algorithm_attr_ed25519[] __attribute__ ((aligned (1))) = {
|
||||
10,
|
||||
0x69, /* EdDSA (experimental) */
|
||||
/* OID of the curve Ed25519 */
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Representation of PW1_LIFETIME:
|
||||
* 0: PW1_LIEFTIME_P == NULL : PW1 is valid for single PSO:CDS command
|
||||
@@ -618,7 +624,7 @@ encrypt (const uint8_t *key, const uint8_t *iv, uint8_t *data, int len)
|
||||
aes_crypt_cfb128 (&aes, AES_ENCRYPT, len, &iv_offset, iv0, data, data);
|
||||
}
|
||||
|
||||
/* Signing, Decryption, and Authentication */
|
||||
/* For three keys: Signing, Decryption, and Authentication */
|
||||
struct key_data kd[3];
|
||||
|
||||
static void
|
||||
@@ -673,7 +679,7 @@ get_do_ptr_nr_for_kk (enum kind_of_key kk)
|
||||
void
|
||||
gpg_do_clear_prvkey (enum kind_of_key kk)
|
||||
{
|
||||
memset ((void *)&kd[kk], 0, sizeof (struct key_data));
|
||||
memset (kd[kk].data, 0, KEY_CONTENT_LEN);
|
||||
}
|
||||
|
||||
|
||||
@@ -716,12 +722,12 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
if (do_data == NULL)
|
||||
return 0;
|
||||
|
||||
key_addr = (const uint8_t *)fetch_four_bytes (&do_data[1]);
|
||||
key_addr = kd[kk].key_addr;
|
||||
memcpy (kdi.data, key_addr, KEY_CONTENT_LEN);
|
||||
iv = do_data+5;
|
||||
iv = &do_data[1];
|
||||
memcpy (kdi.checksum, iv + INITIAL_VECTOR_SIZE, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
memcpy (dek, do_data+5+16*(who+1), DATA_ENCRYPTION_KEY_SIZE);
|
||||
memcpy (dek, iv+16*(who+1), DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt_dek (keystring, dek);
|
||||
|
||||
decrypt (dek, iv, (uint8_t *)&kdi, sizeof (struct key_data_internal));
|
||||
@@ -733,7 +739,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
}
|
||||
|
||||
memcpy (kd[kk].data, kdi.data, KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (&kd[kk], KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (kd[kk].data, KEY_CONTENT_LEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -750,10 +756,11 @@ gpg_do_delete_prvkey (enum kind_of_key kk)
|
||||
if (do_data == NULL)
|
||||
return;
|
||||
|
||||
key_addr = (uint8_t *)fetch_four_bytes (&do_data[1]);
|
||||
flash_key_release (key_addr);
|
||||
do_ptr[nr - NR_DO__FIRST__] = NULL;
|
||||
flash_do_release (do_data);
|
||||
key_addr = kd[kk].key_addr;
|
||||
kd[kk].key_addr = NULL;
|
||||
flash_key_release (key_addr);
|
||||
|
||||
if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING)
|
||||
{ /* Recover admin keystring DO. */
|
||||
@@ -805,10 +812,22 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
/* Delete it first, if any. */
|
||||
gpg_do_delete_prvkey (kk);
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
if (key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
#else /* ECDSA for authentication */
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk != GPG_KEY_FOR_SIGNING && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
pubkey_len = key_len * 2;
|
||||
if (key_len != 32)
|
||||
return -1;
|
||||
}
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
#if defined(ECDSA_AUTH)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
@@ -817,6 +836,19 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
if (key_len != 32)
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION && key_len != KEY_CONTENT_LEN)
|
||||
return -1;
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
{
|
||||
pubkey_len = key_len / 2;
|
||||
if (key_len != 64)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
@@ -825,13 +857,30 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
|
||||
if (pubkey == NULL)
|
||||
{
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#else /* ECDSA for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
pubkey_allocated_here = ecdsa_compute_public (key_data);
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
pubkey_allocated_here = ecdsa_compute_public_p256k1 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
#if defined(ECDSA_AUTH)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
pubkey_allocated_here = ecdsa_compute_public_p256r1 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#else
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
|
||||
else
|
||||
pubkey_allocated_here = modulus_calc (key_data, key_len);
|
||||
#endif
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
if (pubkey_allocated_here == NULL)
|
||||
{
|
||||
@@ -841,7 +890,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
}
|
||||
|
||||
DEBUG_INFO ("Getting keystore address...\r\n");
|
||||
key_addr = flash_key_alloc ();
|
||||
key_addr = flash_key_alloc (kk);
|
||||
if (key_addr == NULL)
|
||||
{
|
||||
if (pubkey_allocated_here)
|
||||
@@ -852,15 +901,27 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
free (pd);
|
||||
return -1;
|
||||
}
|
||||
kd[kk].key_addr = key_addr;
|
||||
|
||||
num_prv_keys++;
|
||||
|
||||
DEBUG_INFO ("key_addr: ");
|
||||
DEBUG_WORD ((uint32_t)key_addr);
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#else /* ECDSA for authentication */
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
memcpy (kdi.data, key_data, key_len);
|
||||
memset ((uint8_t *)kdi.data + key_len, 0, KEY_CONTENT_LEN - key_len);
|
||||
}
|
||||
else
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk == GPG_KEY_FOR_AUTHENTICATION)
|
||||
{
|
||||
memcpy (kdi.data, key_data, key_len);
|
||||
@@ -868,6 +929,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
}
|
||||
else
|
||||
memcpy (kdi.data, key_data, KEY_CONTENT_LEN);
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
compute_key_data_checksum (&kdi, 0);
|
||||
|
||||
@@ -910,7 +973,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
return r;
|
||||
}
|
||||
|
||||
pd->key_addr = key_addr;
|
||||
memcpy (pd->iv, iv, INITIAL_VECTOR_SIZE);
|
||||
memcpy (pd->checksum_encrypted, kdi.checksum, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
@@ -974,7 +1036,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
|
||||
memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
|
||||
|
||||
dek_p = ((uint8_t *)pd) + 4 + INITIAL_VECTOR_SIZE
|
||||
dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE
|
||||
+ DATA_ENCRYPTION_KEY_SIZE * who_old;
|
||||
memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE);
|
||||
if (who_new == 0) /* Remove */
|
||||
@@ -1016,24 +1078,39 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static enum kind_of_key
|
||||
kkb_to_kk (uint8_t kk_byte)
|
||||
{
|
||||
enum kind_of_key kk;
|
||||
|
||||
if (kk_byte == 0xb6)
|
||||
kk = GPG_KEY_FOR_SIGNING;
|
||||
else if (kk_byte == 0xb8)
|
||||
kk = GPG_KEY_FOR_DECRYPTION;
|
||||
else /* 0xa4 */
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
return kk;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSA:
|
||||
* 4d, xx, xx, xx: Extended Header List
|
||||
* b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT)
|
||||
* 7f48, xx: cardholder private key template
|
||||
* 91 xx: length of E
|
||||
* 92 xx xx: length of P
|
||||
* 93 xx xx: length of Q
|
||||
* 91 L<E>: L<E>: 91=tag of E, L<E>: length of E
|
||||
* 92 Lh<P> Ll<P>: 92=tag of P, L<P>: length of P
|
||||
* 93 Lh<Q> Ll<Q>: 93=tag of Q, L<Q>: length of Q
|
||||
* 5f48, xx xx xx: cardholder private key
|
||||
* <E: 4-byte>, <P: 128-byte>, <Q: 128-byte>
|
||||
*
|
||||
* ECDSA:
|
||||
* ECDSA / EdDSA:
|
||||
* 4d, xx: Extended Header List
|
||||
* a4 00 (AUT)
|
||||
* 7f48, xx: cardholder private key template
|
||||
* 91 xx: length of d
|
||||
* 9x LEN: 9x=tag of private key d, LEN=length of d
|
||||
* 5f48, xx : cardholder private key
|
||||
* <d>
|
||||
* <d: 32-byte>
|
||||
*/
|
||||
static int
|
||||
proc_key_import (const uint8_t *data, int len)
|
||||
@@ -1061,35 +1138,48 @@ proc_key_import (const uint8_t *data, int len)
|
||||
else
|
||||
p += 1;
|
||||
|
||||
if (*p == 0xb6)
|
||||
kk = kkb_to_kk (*p);
|
||||
if (kk == GPG_KEY_FOR_SIGNING)
|
||||
{
|
||||
kk = GPG_KEY_FOR_SIGNING;
|
||||
ac_reset_pso_cds ();
|
||||
gpg_reset_digital_signature_counter ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == 0xb8)
|
||||
kk = GPG_KEY_FOR_DECRYPTION;
|
||||
else /* 0xa4 */
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
ac_reset_other ();
|
||||
}
|
||||
ac_reset_other ();
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
if (len <= 22)
|
||||
#else /* ECDSA for authentication */
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if ((kk != GPG_KEY_FOR_SIGNING && len <= 22)
|
||||
|| (kk == GPG_KEY_FOR_SIGNING && len <= 12))
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if ((kk != GPG_KEY_FOR_AUTHENTICATION && len <= 22)
|
||||
|| (kk == GPG_KEY_FOR_AUTHENTICATION && len <= 12))
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
{ /* Deletion of the key */
|
||||
gpg_do_delete_prvkey (kk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
|
||||
#else /* ECDSA for authentication */
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk != GPG_KEY_FOR_SIGNING)
|
||||
{ /* RSA */
|
||||
/* It should starts with 00 01 00 01 (E) */
|
||||
/* Skip E, 4-byte */
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
|
||||
}
|
||||
else
|
||||
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
#if defined(ECDSA_AUTH)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION)
|
||||
{ /* RSA */
|
||||
/* It should starts with 00 01 00 01 (E) */
|
||||
@@ -1098,6 +1188,30 @@ proc_key_import (const uint8_t *data, int len)
|
||||
}
|
||||
else
|
||||
r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
|
||||
#else /* EdDSA */
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk != GPG_KEY_FOR_AUTHENTICATION)
|
||||
{ /* RSA */
|
||||
/* It should starts with 00 01 00 01 (E) */
|
||||
/* Skip E, 4-byte */
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t hash[64];
|
||||
|
||||
if (len - 12 != 32)
|
||||
return 1; /* Error. */
|
||||
|
||||
sha512 (&data[12], 32, hash);
|
||||
hash[0] &= 248;
|
||||
hash[31] &= 127;
|
||||
hash[31] |= 64;
|
||||
r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
|
||||
if (r < 0)
|
||||
@@ -1161,12 +1275,20 @@ gpg_do_table[] = {
|
||||
rw_pw_status },
|
||||
/* Fixed data */
|
||||
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
|
||||
#ifdef RSA_SIG
|
||||
{ GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa },
|
||||
{ GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa },
|
||||
#ifdef RSA_AUTH
|
||||
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa },
|
||||
#else
|
||||
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_ecdsa },
|
||||
{ GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_p256k1 },
|
||||
#endif
|
||||
{ GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa },
|
||||
#if defined(RSA_AUTH)
|
||||
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa },
|
||||
#elif defined(ECDSA_AUTH)
|
||||
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_p256r1 },
|
||||
#elif defined(EDDSA_AUTH)
|
||||
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_ed25519 },
|
||||
#else
|
||||
#error "Not supported (AUTH)."
|
||||
#endif
|
||||
/* Compound data: Read access only */
|
||||
{ GPG_DO_CH_DATA, DO_CMP_READ, AC_ALWAYS, AC_NEVER, cmp_ch_data },
|
||||
@@ -1583,54 +1705,65 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
||||
void
|
||||
gpg_do_public_key (uint8_t kk_byte)
|
||||
{
|
||||
const uint8_t *do_data;
|
||||
const uint8_t *key_addr;
|
||||
enum kind_of_key kk;
|
||||
|
||||
DEBUG_INFO ("Public key\r\n");
|
||||
DEBUG_BYTE (kk_byte);
|
||||
|
||||
if (kk_byte == 0xb6)
|
||||
do_data = do_ptr[NR_DO_PRVKEY_SIG - NR_DO__FIRST__];
|
||||
else if (kk_byte == 0xb8)
|
||||
do_data = do_ptr[NR_DO_PRVKEY_DEC - NR_DO__FIRST__];
|
||||
else /* 0xa4 */
|
||||
do_data = do_ptr[NR_DO_PRVKEY_AUT - NR_DO__FIRST__];
|
||||
|
||||
if (do_data == NULL)
|
||||
kk = kkb_to_kk (kk_byte);
|
||||
key_addr = kd[kk].key_addr;
|
||||
if (key_addr == NULL)
|
||||
{
|
||||
DEBUG_INFO ("none.\r\n");
|
||||
GPG_NO_RECORD ();
|
||||
return;
|
||||
}
|
||||
|
||||
key_addr = (const uint8_t *)fetch_four_bytes (&do_data[1]);
|
||||
|
||||
res_p = res_APDU;
|
||||
|
||||
/* TAG */
|
||||
*res_p++ = 0x7f; *res_p++ = 0x49;
|
||||
|
||||
#ifndef RSA_AUTH /* ECDSA for authentication */
|
||||
#if defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
if (0)
|
||||
#elif defined(RSA_AUTH) && !defined(RSA_SIG)
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (kk_byte == 0xb6)
|
||||
#elif !defined(RSA_AUTH) && defined(RSA_SIG)
|
||||
/* ECDSA with p256r1 for authentication */
|
||||
/* EdDSA with Ed25519 for authentication */
|
||||
if (kk_byte == 0xa4)
|
||||
#else
|
||||
#error "not supported."
|
||||
#endif
|
||||
#if defined(ECDSA_AUTH)
|
||||
{ /* ECDSA */
|
||||
/* LEN */
|
||||
*res_p++ = 2 + 8 + 2 + 1 + 64;
|
||||
*res_p++ = 2 + 1 + 64;
|
||||
{
|
||||
/*TAG*/ /* LEN = 8 */
|
||||
*res_p++ = 0x06; *res_p++ = 0x08;
|
||||
memcpy (res_p, algorithm_attr_ecdsa+2, 8);
|
||||
res_p += 8;
|
||||
|
||||
/*TAG*/ /* LEN = 1+64 */
|
||||
*res_p++ = 0x86; *res_p++ = 0x41;
|
||||
*res_p++ = 0x04; /* No compression of EC point. */
|
||||
/* 64-byte binary (big endian) */
|
||||
/* 64-byte binary (big endian): X || Y */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, 64);
|
||||
res_p += 64;
|
||||
}
|
||||
}
|
||||
else
|
||||
#else /* EDDSA_AUTH */
|
||||
{ /* EdDSA */
|
||||
/* LEN */
|
||||
*res_p++ = 2 + 32;
|
||||
{
|
||||
/*TAG*/ /* LEN = 32 */
|
||||
*res_p++ = 0x86; *res_p++ = 0x20;
|
||||
/* 32-byte binary (little endian): Y with parity */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, 32);
|
||||
res_p += 32;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{ /* RSA */
|
||||
/* LEN = 9+256 */
|
||||
*res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x09;
|
||||
@@ -1704,13 +1837,7 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
DEBUG_INFO ("Keygen\r\n");
|
||||
DEBUG_BYTE (kk_byte);
|
||||
|
||||
if (kk_byte == 0xb6)
|
||||
kk = GPG_KEY_FOR_SIGNING;
|
||||
else if (kk_byte == 0xb8)
|
||||
kk = GPG_KEY_FOR_DECRYPTION;
|
||||
else /* 0xa4 */
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
|
||||
kk = kkb_to_kk (kk_byte);
|
||||
if (admin_authorized == BY_ADMIN)
|
||||
keystring_admin = keystring_md_pw3;
|
||||
else
|
||||
@@ -1745,6 +1872,7 @@ gpg_do_keygen (uint8_t kk_byte)
|
||||
/* GnuPG expects it's ready for signing. */
|
||||
/* Don't call ac_reset_pso_cds here, but load the private key */
|
||||
|
||||
gpg_reset_digital_signature_counter ();
|
||||
s2k (NULL, 0, pw, strlen (OPENPGP_CARD_INITIAL_PW1), keystring);
|
||||
gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
}
|
||||
|
||||
101
src/openpgp.c
101
src/openpgp.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -805,6 +805,12 @@ cmd_get_data (void)
|
||||
gpg_do_get_data (tag, 0);
|
||||
}
|
||||
|
||||
#define ECDSA_HASH_LEN 32
|
||||
#define ECDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
#define EDDSA_HASH_LEN_MAX 256
|
||||
#define EDDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
@@ -824,6 +830,7 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RSA_SIG
|
||||
/* Check size of digestInfo */
|
||||
if (len != 34 /* MD5 */
|
||||
&& len != 35 /* SHA1 / RIPEMD-160 */
|
||||
@@ -839,7 +846,7 @@ cmd_pso (void)
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, KEY_CONTENT_LEN);
|
||||
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_SIGNING]);
|
||||
@@ -852,11 +859,35 @@ cmd_pso (void)
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
#else
|
||||
/* ECDSA with p256k1 for signature */
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
}
|
||||
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 ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
|
||||
{
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_DECRYPTION].data, KEY_CONTENT_LEN);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
@@ -890,7 +921,7 @@ cmd_pso (void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef RSA_AUTH
|
||||
#if defined(RSA_AUTH)
|
||||
#define MAX_DIGEST_INFO_LEN 102 /* 40% */
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
@@ -934,10 +965,7 @@ cmd_internal_authenticate (void)
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#else
|
||||
#define ECDSA_P256_HASH_LEN 32
|
||||
#define ECDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
#elif defined(ECDSA_AUTH)
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
@@ -957,7 +985,7 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (len != ECDSA_P256_HASH_LEN)
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
@@ -965,8 +993,8 @@ cmd_internal_authenticate (void)
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign (apdu.cmd_apdu_data, res_APDU,
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION]);
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
@@ -981,6 +1009,57 @@ cmd_internal_authenticate (void)
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#elif defined(EDDSA_AUTH)
|
||||
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)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
DEBUG_SHORT (len);
|
||||
|
||||
if (!ac_check_status (AC_OTHER_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("security error.");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = 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].key_addr + KEY_CONTENT_LEN);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#else
|
||||
#error "Authentication not defined."
|
||||
#endif
|
||||
|
||||
#define MBD_OPRATION_WRITE 0
|
||||
|
||||
18
src/sha256.c
18
src/sha256.c
@@ -52,13 +52,17 @@
|
||||
|
||||
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
|
||||
|
||||
static void memcpy_bswap32 (void *dst, const uint32_t *p, int n)
|
||||
static void memcpy_output_bswap32 (unsigned char *dst, const uint32_t *p)
|
||||
{
|
||||
uint32_t *q = (uint32_t *)dst;
|
||||
int i;
|
||||
uint32_t q = 0;
|
||||
|
||||
n >>= 2;
|
||||
while (n--)
|
||||
q[n] = __builtin_bswap32 (p[n]); /* bswap32 is GCC extention */
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if ((i & 3) == 0)
|
||||
q = __builtin_bswap32 (p[i >> 2]); /* bswap32 is GCC extention */
|
||||
dst[i] = q >> ((i & 3) * 8);
|
||||
}
|
||||
}
|
||||
|
||||
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
|
||||
@@ -193,11 +197,11 @@ sha256_finish (sha256_context *ctx, unsigned char output[32])
|
||||
ctx->wbuf[15] = __builtin_bswap32 (ctx->total[0] << 3);
|
||||
sha256_process (ctx);
|
||||
|
||||
memcpy_bswap32 (output, ctx->state, SHA256_DIGEST_SIZE);
|
||||
memcpy_output_bswap32 (output, ctx->state);
|
||||
memset (ctx, 0, sizeof (sha256_context));
|
||||
}
|
||||
|
||||
const uint32_t initial_state[8] =
|
||||
static const uint32_t initial_state[8] =
|
||||
{
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
|
||||
216
src/sha512.c
Normal file
216
src/sha512.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* sha512.c -- Compute SHA-512 hash (for little endian architecture).
|
||||
*
|
||||
* This module is written by gniibe, following the API of sha256.c.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
*
|
||||
* [1] FIPS PUB 180-4: Secure hash Standard (SHS), March, 2012.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha512.h"
|
||||
|
||||
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
|
||||
|
||||
static void memcpy_output_bswap64 (unsigned char dst[64], const uint64_t *p)
|
||||
{
|
||||
int i;
|
||||
uint64_t q = 0;
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if ((i & 7) == 0)
|
||||
q = __builtin_bswap64 (p[i >> 3]); /* bswap64 is GCC extention */
|
||||
dst[i] = q >> ((i & 7) * 8);
|
||||
}
|
||||
}
|
||||
|
||||
#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n)))
|
||||
|
||||
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
|
||||
|
||||
/* round transforms for SHA512 compression functions */
|
||||
#define vf(n,i) v[(n - i) & 7]
|
||||
|
||||
#define hf(i) (p[i & 15] += \
|
||||
g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15]))
|
||||
|
||||
#define v_cycle0(i) \
|
||||
p[i] = __builtin_bswap64 (p[i]); \
|
||||
vf(7,i) += p[i] + k_0[i] \
|
||||
+ s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \
|
||||
vf(3,i) += vf(7,i); \
|
||||
vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))
|
||||
|
||||
#define v_cycle(i, j) \
|
||||
vf(7,i) += hf(i) + k_0[i+j] \
|
||||
+ s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \
|
||||
vf(3,i) += vf(7,i); \
|
||||
vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))
|
||||
|
||||
#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
|
||||
#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
|
||||
#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
|
||||
#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
|
||||
#define k_0 k512
|
||||
|
||||
/* Taken from section 4.2.3 of [1]. */
|
||||
static const uint64_t k512[80] = {
|
||||
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
|
||||
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
|
||||
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
|
||||
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
|
||||
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
|
||||
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
|
||||
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
|
||||
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
|
||||
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
|
||||
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
|
||||
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
|
||||
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
|
||||
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
|
||||
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
|
||||
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
|
||||
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
|
||||
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
|
||||
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
|
||||
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
|
||||
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
|
||||
};
|
||||
|
||||
void
|
||||
sha512_process (sha512_context *ctx)
|
||||
{
|
||||
uint32_t i;
|
||||
uint64_t *p = ctx->wbuf;
|
||||
uint64_t v[8];
|
||||
|
||||
memcpy (v, ctx->state, 8 * sizeof (uint64_t));
|
||||
|
||||
v_cycle0 ( 0); v_cycle0 ( 1); v_cycle0 ( 2); v_cycle0 ( 3);
|
||||
v_cycle0 ( 4); v_cycle0 ( 5); v_cycle0 ( 6); v_cycle0 ( 7);
|
||||
v_cycle0 ( 8); v_cycle0 ( 9); v_cycle0 (10); v_cycle0 (11);
|
||||
v_cycle0 (12); v_cycle0 (13); v_cycle0 (14); v_cycle0 (15);
|
||||
|
||||
for (i = 16; i < 80; i += 16)
|
||||
{
|
||||
v_cycle ( 0, i); v_cycle ( 1, i); v_cycle ( 2, i); v_cycle ( 3, i);
|
||||
v_cycle ( 4, i); v_cycle ( 5, i); v_cycle ( 6, i); v_cycle ( 7, i);
|
||||
v_cycle ( 8, i); v_cycle ( 9, i); v_cycle (10, i); v_cycle (11, i);
|
||||
v_cycle (12, i); v_cycle (13, i); v_cycle (14, i); v_cycle (15, i);
|
||||
}
|
||||
|
||||
ctx->state[0] += v[0];
|
||||
ctx->state[1] += v[1];
|
||||
ctx->state[2] += v[2];
|
||||
ctx->state[3] += v[3];
|
||||
ctx->state[4] += v[4];
|
||||
ctx->state[5] += v[5];
|
||||
ctx->state[6] += v[6];
|
||||
ctx->state[7] += v[7];
|
||||
}
|
||||
|
||||
void
|
||||
sha512_update (sha512_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen)
|
||||
{
|
||||
uint32_t left = (ctx->total[0] & SHA512_MASK);
|
||||
uint32_t fill = SHA512_BLOCK_SIZE - left;
|
||||
|
||||
ctx->total[0] += ilen;
|
||||
if (ctx->total[0] < ilen)
|
||||
ctx->total[1]++;
|
||||
|
||||
while (ilen >= fill)
|
||||
{
|
||||
memcpy (((unsigned char*)ctx->wbuf) + left, input, fill);
|
||||
sha512_process (ctx);
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
fill = SHA512_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
memcpy (((unsigned char*)ctx->wbuf) + left, input, ilen);
|
||||
}
|
||||
|
||||
void
|
||||
sha512_finish (sha512_context *ctx, unsigned char output[64])
|
||||
{
|
||||
uint32_t last = (ctx->total[0] & SHA512_MASK);
|
||||
|
||||
ctx->wbuf[last >> 3] = __builtin_bswap64 (ctx->wbuf[last >> 3]);
|
||||
ctx->wbuf[last >> 3] &= 0xffffffffffffff80LL << (8 * (~last & 7));
|
||||
ctx->wbuf[last >> 3] |= 0x0000000000000080LL << (8 * (~last & 7));
|
||||
ctx->wbuf[last >> 3] = __builtin_bswap64 (ctx->wbuf[last >> 3]);
|
||||
|
||||
if (last > SHA512_BLOCK_SIZE - 17)
|
||||
{
|
||||
if (last < 120)
|
||||
ctx->wbuf[15] = 0;
|
||||
sha512_process (ctx);
|
||||
last = 0;
|
||||
}
|
||||
else
|
||||
last = (last >> 3) + 1;
|
||||
|
||||
while (last < 14)
|
||||
ctx->wbuf[last++] = 0;
|
||||
|
||||
ctx->wbuf[14] = __builtin_bswap64 ((ctx->total[0] >> 61) | (ctx->total[1] << 3));
|
||||
ctx->wbuf[15] = __builtin_bswap64 (ctx->total[0] << 3);
|
||||
sha512_process (ctx);
|
||||
|
||||
memcpy_output_bswap64 (output, ctx->state);
|
||||
memset (ctx, 0, sizeof (sha512_context));
|
||||
}
|
||||
|
||||
/* Taken from section 5.3.5 of [1]. */
|
||||
static const uint64_t initial_state[8] = {
|
||||
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
|
||||
};
|
||||
|
||||
void
|
||||
sha512_start (sha512_context *ctx)
|
||||
{
|
||||
ctx->total[0] = ctx->total[1] = 0;
|
||||
memcpy (ctx->state, initial_state, 8 * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void
|
||||
sha512 (const unsigned char *input, unsigned int ilen,
|
||||
unsigned char output[64])
|
||||
{
|
||||
sha512_context ctx;
|
||||
|
||||
sha512_start (&ctx);
|
||||
sha512_update (&ctx, input, ilen);
|
||||
sha512_finish (&ctx, output);
|
||||
}
|
||||
17
src/sha512.h
Normal file
17
src/sha512.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#define SHA512_DIGEST_SIZE 64
|
||||
#define SHA512_BLOCK_SIZE 128
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t total[2];
|
||||
uint64_t state[8];
|
||||
uint64_t wbuf[16];
|
||||
} sha512_context;
|
||||
|
||||
void sha512 (const unsigned char *input, unsigned int ilen,
|
||||
unsigned char output[64]);
|
||||
void sha512_start (sha512_context *ctx);
|
||||
void sha512_finish (sha512_context *ctx, unsigned char output[64]);
|
||||
void sha512_update (sha512_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen);
|
||||
void sha512_process (sha512_context *ctx);
|
||||
28
tool/calc_precompute_table_ecc.py
Normal file
28
tool/calc_precompute_table_ecc.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from ecdsa import curves, ecdsa
|
||||
G = ecdsa.generator_secp256k1
|
||||
# G = ecdsa.generator_256
|
||||
|
||||
def print_nG(n):
|
||||
nG = n*G
|
||||
nGx_str = "%064x" % nG.x()
|
||||
nGy_str = "%064x" % nG.y()
|
||||
print256(nGx_str)
|
||||
print256(nGy_str)
|
||||
print
|
||||
|
||||
def print256(s):
|
||||
print("0x%s, 0x%s, 0x%s, 0x%s," % (s[56:64], s[48:56], s[40:48], s[32:40]))
|
||||
print("0x%s, 0x%s, 0x%s, 0x%s" % (s[24:32], s[16:24], s[8:16], s[0:8]))
|
||||
print
|
||||
|
||||
|
||||
for i in range(1,16):
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000L + (i & 4) * 0x40000000000000000000000000000000L + (i & 8) * 0x200000000000000000000000000000000000000000000000L
|
||||
print "%064x" % n
|
||||
print_nG(n)
|
||||
|
||||
for i in range(1,16):
|
||||
n = (i & 1) + (i & 2) * 0x8000000000000000L + (i & 4) * 0x40000000000000000000000000000000L + (i & 8) * 0x200000000000000000000000000000000000000000000000L
|
||||
n = n * 0x100000000L
|
||||
print "%064x" % n
|
||||
print_nG(n)
|
||||
@@ -111,7 +111,7 @@ class DFU_STM32(object):
|
||||
self.__devhandle = device.open()
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
|
||||
@@ -73,7 +73,7 @@ class gnuk_token(object):
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
@@ -481,7 +481,7 @@ class regnual(object):
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(intf)
|
||||
self.__devhandle.setAltInterface(intf)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
|
||||
@@ -59,7 +59,7 @@ class regnual(object):
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(intf)
|
||||
self.__devhandle.setAltInterface(intf)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
@@ -172,7 +172,7 @@ class gnuk_token(object):
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(interface)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
|
||||
@@ -146,7 +146,7 @@ class stlinkv2(object):
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(intf)
|
||||
# self.__devhandle.setAltInterface(intf) # This is not good for libusb-win32
|
||||
# self.__devhandle.setAltInterface(0) # This was not good for libusb-win32 with wrong arg intf, new correct value 0 would be OK
|
||||
|
||||
def shutdown(self):
|
||||
self.__devhandle.releaseInterface()
|
||||
|
||||
@@ -94,7 +94,6 @@ if __name__ == '__main__':
|
||||
|
||||
passwd = DEFAULT_PW3
|
||||
keyno = 0
|
||||
print sys.argv
|
||||
while len(sys.argv) > 3:
|
||||
option = sys.argv[1]
|
||||
sys.argv.pop(1)
|
||||
|
||||
Reference in New Issue
Block a user