Compare commits

..

266 Commits

Author SHA1 Message Date
NIIBE Yutaka
32779b6f96 Version 1.2.3. 2017-02-02 16:33:30 +09:00
NIIBE Yutaka
55c1015faa Increase CCID thread stack size by 0x20 for newer GCC. 2017-02-02 14:11:11 +09:00
NIIBE Yutaka
0932465f0b Update Chopstx to 1.3. 2017-02-02 13:07:35 +09:00
NIIBE Yutaka
4417799a51 Update README 2017-02-01 17:16:54 +09:00
Szczepan Zalega
b424cecf1e Regnual update tool: do not allow other than binary formats (upgrade_by_passwd)
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2017-02-01 15:40:56 +09:00
NIIBE Yutaka
7ef417ae36 tool: Improve tool/*.py.
--

Szczepan Zalega's idea of using the file GNUK_USB_DEVICE_ID would
good, but not merged yet.  Because it makes difficult to distribute
the scripts.  We need to consider installing tools and the file
like GNUK_USB_DEVICE_ID altogether.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2017-02-01 12:34:35 +09:00
NIIBE Yutaka
d4469c24ec fix NIST P-256 / secp256k1 key generation. 2016-10-21 15:30:07 +09:00
NIIBE Yutaka
e4333c6580 Version 1.2.2 2016-10-15 20:18:20 +09:00
NIIBE Yutaka
d2261d53e3 fix scripts 2016-10-15 20:14:18 +09:00
NIIBE Yutaka
27bd37781a Fix flash initialization 2016-10-15 19:29:23 +09:00
NIIBE Yutaka
bed43d4049 Add tests/ accessing DO 6E 2016-10-15 19:28:57 +09:00
NIIBE Yutaka
f7d857b527 fix stack usage of CCID 2016-10-15 18:37:22 +09:00
NIIBE Yutaka
350528e1f4 tests/ update for signature counter 2016-10-15 18:35:21 +09:00
NIIBE Yutaka
4de605ed63 Add pubkey tests 2016-10-15 16:55:22 +09:00
NIIBE Yutaka
ffa9bf1f94 support factory_reset. 2016-10-14 08:45:01 +09:00
NIIBE Yutaka
34d0b34144 add factory reset support (not-full yet) 2016-10-13 15:06:19 +09:00
NIIBE Yutaka
5795dc9877 rename status-code.h 2016-10-13 11:03:50 +09:00
NIIBE Yutaka
c8b17a8759 Update to Chopstx 1.2 2016-10-13 10:35:22 +09:00
NIIBE Yutaka
38d70e277b Fix difference between original OpenPGP card 2016-10-13 10:33:02 +09:00
NIIBE Yutaka
b00bab8dbf tests/ update 2016-10-13 10:04:27 +09:00
NIIBE Yutaka
3c91dce8b7 fix tests/ 2016-10-12 19:42:22 +09:00
NIIBE Yutaka
f1773c146b fix test/ 2016-10-12 15:32:51 +09:00
NIIBE Yutaka
979992c046 fix test/ 2016-10-12 14:56:57 +09:00
NIIBE Yutaka
50700e3887 more tests (incomplete) 2016-10-12 10:22:57 +09:00
NIIBE Yutaka
b0ee8b4452 TPDU reader works now 2016-10-07 16:39:20 +09:00
NIIBE Yutaka
a73f8cf4fd implement TPDU card reader 2016-10-05 20:00:22 +09:00
NIIBE Yutaka
c1cc75f5b0 New test suite for OpenPGP card 2016-09-30 16:38:27 +09:00
NIIBE Yutaka
47150b5c98 minor fix for configure 2016-09-30 16:20:19 +09:00
NIIBE Yutaka
f46880d2a8 Add Gnuk logo of PNG 2016-09-02 11:01:55 +09:00
NIIBE Yutaka
23bbc9c755 Fix test setup 2016-08-24 10:39:27 +09:00
NIIBE Yutaka
2b784cb3b9 Upgrade tool/hub_ctrl.py 2016-08-03 21:19:34 +09:00
NIIBE Yutaka
452c15c908 Version 1.2.1 2016-07-11 16:20:55 +09:00
NIIBE Yutaka
dc568422b1 Cleanup openpgp_thread. 2016-07-11 13:06:30 +09:00
NIIBE Yutaka
5edcf32bb7 Update document 2016-07-11 12:55:09 +09:00
NIIBE Yutaka
2647797348 Fix for PIN DND 2016-07-11 12:47:06 +09:00
NIIBE Yutaka
9697694e45 pin CIR fixes 2016-07-11 11:32:14 +09:00
NIIBE Yutaka
f5cbc71a54 doc fix 2016-07-11 11:28:08 +09:00
NIIBE Yutaka
5099bfee88 Update chopstx to 1.1 2016-07-01 13:09:42 +09:00
NIIBE Yutaka
691e16c605 doc update 2016-06-21 14:44:51 +09:00
Niibe Yutaka
eabcec107e Update to Chopstx 1.0 2016-06-17 14:54:52 +09:00
Niibe Yutaka
73c698c67e tweak thread size 2016-06-15 15:14:03 +09:00
Niibe Yutaka
d035c53b9c update chopstx 2016-06-14 16:48:31 +09:00
Niibe Yutaka
a96a3eefe6 Update Chopstx, follow the change of USB API 2016-06-14 14:29:17 +09:00
NIIBE Yutaka
fd08a853fd Fix regnual for new Chopstx 2016-06-02 11:03:59 +09:00
NIIBE Yutaka
f882acc1b4 Fix USB usage in tool/ 2016-06-01 09:49:28 +09:00
NIIBE Yutaka
907d8c7a8e Add ccid_notify_slot_change for the interrupt transfer 2016-06-01 07:52:56 +09:00
NIIBE Yutaka
d636bf314c Remove sys, adc and usb (use Chopstx's) 2016-05-31 21:18:08 +09:00
NIIBE Yutaka
0212328a6a USB handling improvement 2016-05-31 20:29:31 +09:00
NIIBE Yutaka
eb90074e11 ICC->CCID 2016-05-31 19:51:07 +09:00
NIIBE Yutaka
38d164360c Update to Chopstx 0.12 2016-05-31 18:16:51 +09:00
NIIBE Yutaka
ff190a8053 Fix LED blinking protocol. 2016-05-21 10:56:49 +09:00
NIIBE Yutaka
f86f97cdbe Version 1.2.0 2016-05-20 14:10:39 +09:00
NIIBE Yutaka
1e004bec78 Fix reGNUal upgrade 2016-05-19 17:34:38 +09:00
NIIBE Yutaka
d68bee21e5 mv usb-icc.c usb-ccid.c 2016-05-19 16:58:52 +09:00
NIIBE Yutaka
2903e88986 Update Chopstx to 0.11 2016-05-19 14:04:31 +09:00
NIIBE Yutaka
25fed157e1 Follow the change of eventflag change, fixining long-standing bug of LED 2016-05-19 11:50:13 +09:00
NIIBE Yutaka
d5c5571423 LED blink change 2016-05-18 21:57:34 +09:00
NIIBE Yutaka
51d4b754e6 integrate ccid and usb threads 2016-05-18 21:34:14 +09:00
NIIBE Yutaka
48905155c5 Follow Chopstx change 2016-05-18 19:43:47 +09:00
NIIBE Yutaka
772071d1ba Update reGNUal wrt sys 3.0 2016-05-18 13:32:00 +09:00
NIIBE Yutaka
1fa45e3273 Fix reGNUal 2016-05-16 22:43:51 +09:00
NIIBE Yutaka
1a5eb0ec3b update from Chopstx 2016-05-16 22:37:23 +09:00
NIIBE Yutaka
106b042e75 neug follow update of chopstx 2016-05-13 22:31:09 +09:00
NIIBE Yutaka
eebd40d946 usb call back moved to usb_ctrl.c 2016-05-13 22:30:47 +09:00
NIIBE Yutaka
5e37c7722a Update chopstx 2016-05-12 21:57:53 +09:00
NIIBE Yutaka
b1a582e87c Fix USB stack a bit 2016-03-08 11:58:43 +09:00
NIIBE Yutaka
3f1ee534fe Support VERIFY reset feature 2016-02-09 14:19:36 +09:00
NIIBE Yutaka
522ec3299e Bignum fixes 2016-02-09 14:13:13 +09:00
NIIBE Yutaka
34e2099b23 change of S2K 2016-02-09 14:01:07 +09:00
NIIBE Yutaka
baf09ecac9 Fix the implementation for NIST P-256 and secp256k1 2016-02-08 11:24:55 +09:00
NIIBE Yutaka
db23a1d051 submodule check in configure 2016-02-08 10:11:02 +09:00
NIIBE Yutaka
3f8c4d1f17 Fix offset of bConfirmPIN 2015-11-30 13:38:00 +09:00
NIIBE Yutaka
1648a538df Version 1.1.9 2015-09-18 21:27:50 +09:00
NIIBE Yutaka
3ffac57509 Version 1.1.8 2015-09-17 17:41:27 +09:00
NIIBE Yutaka
1654a83366 Update THANKS 2015-09-16 15:22:35 +09:00
NIIBE Yutaka
022bb44f12 more tuning of stack size 2015-09-15 13:10:44 +09:00
NIIBE Yutaka
03c024f8f6 fix main and upgrade to Chopstx 0.10 2015-09-15 10:45:22 +09:00
NIIBE Yutaka
9b7d400550 usb reset doesn't cause ccid exit 2015-09-15 10:17:40 +09:00
NIIBE Yutaka
c53bd96eb8 usb reset bug fix 2015-09-15 10:04:59 +09:00
NIIBE Yutaka
1f9e8ca77f usb bug fix 2015-09-15 10:00:09 +09:00
NIIBE Yutaka
deeb8aad1c stack size tune 2015-09-15 09:55:12 +09:00
NIIBE Yutaka
f02d7d8565 cleanup for upgrade 2015-09-14 18:41:28 +09:00
NIIBE Yutaka
a5f7072a64 chopstx fix 2015-09-11 17:09:58 +09:00
NIIBE Yutaka
2c79280441 fix tool/upgrade_by_passwd.py 2015-09-11 17:09:28 +09:00
NIIBE Yutaka
d4d36bebab fix changelog 2015-09-10 16:45:32 +09:00
NIIBE Yutaka
d423678f59 fix cleanup_pop 2015-09-10 14:23:07 +09:00
NIIBE Yutaka
4b7cfd04af Update sys.h from chopstx 2015-09-10 14:20:29 +09:00
NIIBE Yutaka
115a7ba67a fix cancellation 2015-09-10 14:14:37 +09:00
NIIBE Yutaka
d0e7aad11e Update adc_stm32f103.c from NeuG 2015-09-09 19:19:23 +09:00
NIIBE Yutaka
645f42a890 allow cancelling execution of commands which take long time 2015-09-09 19:14:19 +09:00
NIIBE Yutaka
f505dea314 USB Reset handling 2015-09-09 18:49:01 +09:00
NIIBE Yutaka
748c3cac6c CDC DTR 2015-09-09 13:13:05 +09:00
NIIBE Yutaka
fa8bc533a3 Upgrade chopstx 2015-09-08 17:54:19 +09:00
NIIBE Yutaka
00062a0ac7 Add ST_DONGLE and ST_NUCLEO_F103 2015-09-08 17:51:31 +09:00
NIIBE Yutaka
c9f88bb9f1 card serial number change 2015-09-04 17:03:52 +09:00
NIIBE Yutaka
482742394d update chopstx 2015-09-04 16:54:26 +09:00
Mateusz Zalega
05867d84f6 GNUK_USB_DEVICE_ID: add Nitrokey Start 2015-09-04 16:53:39 +09:00
NIIBE Yutaka
92cbb5364a Fix 'verndor' 2015-08-11 12:35:35 +09:00
NIIBE Yutaka
61e4551b76 Version 1.1.7 2015-08-05 09:56:20 +09:00
NIIBE Yutaka
254742bc6d more change for Python 2015-08-04 12:32:56 +09:00
NIIBE Yutaka
a6fd40d4fd update Chopstx and ADC driver 2015-08-04 11:11:20 +09:00
NIIBE Yutaka
9a11e954d8 More PythonUSB change 2015-08-04 11:11:03 +09:00
NIIBE Yutaka
b2ca03dc19 Python3 fixes 2015-08-03 19:51:50 +09:00
NIIBE Yutaka
0fb6853fc7 more python3 fix 2015-08-03 19:22:02 +09:00
NIIBE Yutaka
94d6208542 More python3 fixes 2015-08-03 16:44:38 +09:00
NIIBE Yutaka
eb62609c86 Add pinpadtest info from Thomas Jarosch 2015-07-31 23:12:01 +09:00
NIIBE Yutaka
d596493831 fix sed script in configure 2015-07-31 23:00:34 +09:00
NIIBE Yutaka
70463566bf update regnual 2015-07-31 16:13:06 +09:00
NIIBE Yutaka
99c55fce60 support ST-Link/V2-1 2015-07-31 16:10:47 +09:00
NIIBE Yutaka
ec2a2e049f stlinkv2.py now works with newer PyUSB 2015-07-28 23:02:33 +09:00
NIIBE Yutaka
43331cbeaf fix for python3 2015-07-28 14:45:18 +09:00
NIIBE Yutaka
fbdac6a96a More USB driver change 2015-07-28 10:18:39 +09:00
NIIBE Yutaka
9e3af06141 USB driver update 2015-07-27 21:16:28 +09:00
NIIBE Yutaka
1de2f33d23 remove PC/SC tools 2015-07-27 18:55:10 +09:00
NIIBE Yutaka
06b364b1ac fix quote in sed scripts 2015-07-23 12:14:18 +09:00
NIIBE Yutaka
9786da7009 Use for \n 2015-07-23 11:18:50 +09:00
NIIBE Yutaka
55ee1cd30f version 1.1.6 2015-07-21 09:25:06 +09:00
NIIBE Yutaka
5f21a44058 ECC keygen 2015-07-20 18:01:21 +09:00
NIIBE Yutaka
edf1a0cdd7 always enable keygen 2015-07-18 13:55:28 +09:00
NIIBE Yutaka
be5c052531 cleanup USB string things 2015-07-16 10:35:08 +09:00
NIIBE Yutaka
e041a2aa7d configure update 2015-07-16 10:19:12 +09:00
NIIBE Yutaka
31c7a42c73 common binary support fix 2015-07-16 09:31:44 +09:00
NIIBE Yutaka
8ddcc1e896 support Board 2015-07-15 16:37:19 +09:00
NIIBE Yutaka
6a8f8dffcb common binary support 2015-07-15 14:29:37 +09:00
NIIBE Yutaka
f2744bec30 upgrade to chopstx 0.07 2015-07-15 14:09:36 +09:00
NIIBE Yutaka
074f479962 update 2015-07-15 14:02:49 +09:00
NIIBE Yutaka
a60fe371a4 improve stlinkv2.py 2015-07-15 14:01:40 +09:00
NIIBE Yutaka
3ea5e54eb9 Add debug test files 2015-07-15 14:01:22 +09:00
NIIBE Yutaka
ed8c41a0ca Support STM32 Primer 2 2015-07-11 17:49:52 +09:00
NIIBE Yutaka
9ed3bb5353 Fix stlinkv2 for STM32F103xE 2015-07-11 17:46:50 +09:00
NIIBE Yutaka
9bbca07033 Curve25519 support 2015-07-08 08:49:05 +09:00
NIIBE Yutaka
9ba59de212 stlinkv2.py: merge Cortex-M0 support for FSM-55 2015-07-06 15:52:04 +09:00
NIIBE Yutaka
35c880fc0c remove boards/ since we have now STM32 Primer2 and CQ STARM 2015-07-06 12:46:45 +09:00
NIIBE Yutaka
7b116d614e update chopstx 2015-06-30 16:07:46 +09:00
NIIBE Yutaka
a73d04cf82 serial number change 2015-06-30 16:03:00 +09:00
NIIBE Yutaka
2471616f74 version 1.1.5 2015-06-03 17:22:56 +09:00
NIIBE Yutaka
3926f42647 add test/ecc_nistp256_keys.py 2015-06-03 16:27:41 +09:00
NIIBE Yutaka
ce070f85ff Improve tool/ 2015-06-03 16:27:15 +09:00
NIIBE Yutaka
bd02cbfdb0 OpenPGPcard spec v3.0 change 2015-06-02 20:46:30 +09:00
NIIBE Yutaka
16149ff960 show MAPLE_MINI in help message 2015-06-02 20:44:38 +09:00
NIIBE Yutaka
c4a5681f35 upgrade Chopstx 0.05 2015-06-02 20:44:09 +09:00
NIIBE Yutaka
3d5a776ab1 works on Windows 2015-04-19 09:55:51 +09:00
NIIBE Yutaka
9f4671eaf6 ccid_card_change_signal change 2015-04-18 14:34:53 +09:00
NIIBE Yutaka
5af5d18310 Use chopstx_main_init. 2015-04-18 14:13:00 +09:00
NIIBE Yutaka
3765c9233b shell syntax fix 2015-04-18 12:30:21 +09:00
NIIBE Yutaka
0bd0af1fe1 USB clean up 2015-03-31 14:05:52 +09:00
NIIBE Yutaka
92189e2d12 Update README and THANKS 2015-03-12 14:52:41 +09:00
NIIBE Yutaka
6dcd5aa00c doc fix 2015-03-06 16:14:12 +09:00
NIIBE Yutaka
09d3068222 fix EdDSA auth 2015-03-06 16:13:57 +09:00
NIIBE Yutaka
0f11d320e6 bug fix of OPENPGP.3 singing 2015-02-25 10:03:41 +09:00
NIIBE Yutaka
365308f374 Fix the doc. Thanks to Micah 2015-02-18 10:19:10 +09:00
NIIBE Yutaka
0e510b32c1 Fix EdDSA signature counter 2015-02-10 09:58:45 +09:00
NIIBE Yutaka
a9244d9b13 Fix the bug of EdDSA signing 2015-02-09 16:28:26 +09:00
NIIBE Yutaka
c268e59813 fix doc: Thanks to Micah 2015-01-19 11:08:13 +09:00
NIIBE Yutaka
e7e8b9f5ca version 1.1.4 2014-12-15 14:05:46 +09:00
NIIBE Yutaka
d6e70ab0f4 fix key page release 2014-12-15 12:12:54 +09:00
NIIBE Yutaka
3cca2798b0 RSA can be a bit faster with -O3 (no -Os) 2014-12-12 17:20:06 +09:00
NIIBE Yutaka
a695ad03ab configure default change 2014-12-12 15:39:15 +09:00
NIIBE Yutaka
41f5145fe1 remove support of STBee Mini for ChibiOS/RT 2014-12-12 15:39:02 +09:00
NIIBE Yutaka
b6db3b449e Modify test suite 2014-12-12 15:06:22 +09:00
NIIBE Yutaka
c54bb0c559 fix USB 2014-12-12 15:00:51 +09:00
NIIBE Yutaka
91222b5e22 Upgrade Chopstx 2014-12-12 14:26:58 +09:00
NIIBE Yutaka
f89b9ef8b7 Remove useless files 2014-12-12 14:23:57 +09:00
NIIBE Yutaka
4e984276e3 ECC change finished 2014-12-12 14:22:13 +09:00
NIIBE Yutaka
abde30b943 fixes for ECC 2014-12-12 14:17:35 +09:00
NIIBE Yutaka
8d56a4bff5 Change required by RSA-4096 support 2014-12-12 14:06:16 +09:00
NIIBE Yutaka
fd8543f092 proc_key_import supports key algo attrs 2014-12-12 13:57:00 +09:00
NIIBE Yutaka
9cba1e2a8e Support modifiable key algo attrs and divert on runtime 2014-12-12 13:53:29 +09:00
NIIBE Yutaka
8f33df9819 Implement writable key algorithm attributes 2014-12-12 13:12:06 +09:00
NIIBE Yutaka
ff3df302e4 Extended capabilities change 2014-12-12 13:10:33 +09:00
NIIBE Yutaka
75e8de2df1 Add new records in flash for writable key attributes 2014-12-12 13:09:37 +09:00
NIIBE Yutaka
8e6fa1a627 Variable length keysize supported in flash.c 2014-12-12 11:53:51 +09:00
NIIBE Yutaka
14e2633c52 Remove non-needed 'extern' in gnuk.h 2014-12-12 11:23:15 +09:00
NIIBE Yutaka
0d59d31230 Don't use fixed len for RSA computation 2014-12-12 11:19:24 +09:00
NIIBE Yutaka
f82206e7d5 Fix/add comment to clarify. 2014-06-19 12:48:13 +09:00
NIIBE Yutaka
9ea262ffde Add new tool/add_openpgp_authkey_from_gpgssh.py 2014-06-05 13:02:05 +09:00
NIIBE Yutaka
1309527c3c fix submodule for both of gniibe and gitorious 2014-05-22 13:48:59 +09:00
NIIBE Yutaka
df08bb473c relative path is required for submodule 2014-05-22 13:23:12 +09:00
NIIBE Yutaka
d7c3441dd4 Fixed .gitmodules again. 2014-05-22 11:46:50 +09:00
NIIBE Yutaka
cd06bada05 Fixed .gitmodules to relative for anonymous user of git.gniibe.org 2014-05-22 11:42:29 +09:00
NIIBE Yutaka
e25f50eabc more. 2014-04-17 17:28:08 +09:00
NIIBE Yutaka
62a59b56fe more minor improvement around 2^256-38. 2014-04-17 12:21:00 +09:00
NIIBE Yutaka
4f1343e154 minor improvement. 2014-04-16 21:07:11 +09:00
NIIBE Yutaka
272875ee76 version 1.1.3 2014-04-16 13:26:47 +09:00
NIIBE Yutaka
85b2698bb3 Add curve25519 computation. 2014-04-15 10:28:17 +09:00
NIIBE Yutaka
4d6f59079a minor fixes. 2014-04-14 18:37:25 +09:00
NIIBE Yutaka
53aa3de9b4 cleanup mod_inv. 2014-04-08 10:57:46 +09:00
NIIBE Yutaka
afa0683495 EdDSA-sha512 means SHA512 implicitly. 2014-04-07 14:42:59 +09:00
NIIBE Yutaka
a7f3a3e260 now EdDSA works. 2014-04-03 16:06:42 +09:00
NIIBE Yutaka
9cd4a1a47f fix EdDSA 2014-04-03 16:02:56 +09:00
NIIBE Yutaka
f9ed79f644 gpg_do_write_prvkey for ed25519 2014-04-01 11:09:17 +09:00
NIIBE Yutaka
c7a6370b74 proc_key_import for ed25519 2014-03-31 17:12:07 +09:00
NIIBE Yutaka
dc4584a8a5 gpg_do_public_key for ed25519 2014-03-31 16:58:48 +09:00
NIIBE Yutaka
89f0af1496 Add attribute for ed25519 2014-03-31 16:54:29 +09:00
NIIBE Yutaka
28a5799cf7 eddsa_sign_25519 2014-03-31 16:46:40 +09:00
NIIBE Yutaka
07b960009a flash private key handling. 2014-03-31 15:23:37 +09:00
NIIBE Yutaka
b37a1e728e clean up. 2014-03-29 07:59:31 +09:00
NIIBE Yutaka
c5bdc370dd Change API of eddsa_25519 2014-03-28 16:04:00 +09:00
NIIBE Yutaka
9c5eb9ea4b Add implementation note 2014-03-27 15:12:21 +09:00
NIIBE Yutaka
356a9cc615 eddsa_25519: API change 2014-03-27 12:04:03 +09:00
NIIBE Yutaka
5882b37b58 simplify compute_kG_25519 2014-03-27 11:52:30 +09:00
NIIBE Yutaka
1920c5fc69 improve a bit 2014-03-26 18:37:38 +09:00
NIIBE Yutaka
fc53d507ce fix wrong comment 2014-03-25 16:24:31 +09:00
NIIBE Yutaka
da027eb67f add test code 2014-03-25 14:30:51 +09:00
NIIBE Yutaka
fcf6c60336 cleanup 2014-03-25 11:23:33 +09:00
NIIBE Yutaka
cbf896a61b Implemented EdDSA 2014-03-25 11:05:26 +09:00
NIIBE Yutaka
adbb67deb8 compute_kG_25519 2014-03-20 19:53:38 +09:00
NIIBE Yutaka
129d1b0d30 add precomputed tables. 2014-03-20 17:15:53 +09:00
NIIBE Yutaka
25e71cb29b use 64-bit for mul 2014-03-20 15:51:55 +09:00
NIIBE Yutaka
7d8696946a more bn fix 2014-03-20 15:42:32 +09:00
NIIBE Yutaka
2bb12e55c2 fix 2014-03-19 23:47:59 +09:00
NIIBE Yutaka
fa10e78344 fix bn.c 2014-03-19 23:47:19 +09:00
NIIBE Yutaka
116486affa Add ecc-edwards.c 2014-03-19 17:07:49 +09:00
NIIBE Yutaka
53bf87acf5 fix 2014-03-19 17:07:04 +09:00
NIIBE Yutaka
22bc67959e add comments 2014-03-19 11:12:36 +09:00
NIIBE Yutaka
971ee94d8f affine.h 2014-03-18 15:13:56 +09:00
NIIBE Yutaka
a3504e8510 mod25638 2014-03-18 14:18:39 +09:00
NIIBE Yutaka
bfe0466bd2 move fe25519 2014-03-14 13:07:51 +09:00
NIIBE Yutaka
fb8cb58c5c version 1.1.2 2014-03-07 15:43:05 +09:00
NIIBE Yutaka
db2187835c don't put OID for public key info. 2014-02-25 11:06:11 +09:00
NIIBE Yutaka
653868c00b fix configure for certdo 2014-02-25 09:25:49 +09:00
NIIBE Yutaka
ede98fbe7e bug fixes for secp256k1 2014-02-21 17:24:19 +09:00
NIIBE Yutaka
2accc339e2 fix modp256k1_shift 2014-02-21 11:36:15 +09:00
NIIBE Yutaka
9feeeb308b Add RSA_SIG (disable to use p256k1) 2014-02-20 12:02:44 +09:00
NIIBE Yutaka
01806c2e5e authentication with ecdsa p256r1 2014-02-20 10:58:51 +09:00
NIIBE Yutaka
a32f577dfa add call-ec_p256k1 2014-02-20 10:55:20 +09:00
NIIBE Yutaka
deaf340687 add ec_p256k1 2014-02-19 14:51:09 +09:00
NIIBE Yutaka
f5e8e94bf7 fix ec_p256r1 2014-02-19 11:36:27 +09:00
NIIBE Yutaka
df4e8c5481 Use CPP for jpc_p256[kr]1 2014-02-18 15:54:28 +09:00
NIIBE Yutaka
888eb2aa31 minor fix 2014-02-18 14:07:25 +09:00
NIIBE Yutaka
1436223320 sha256 bug fix 2014-02-18 14:01:57 +09:00
NIIBE Yutaka
13a52a0862 minor fixes 2014-02-18 14:01:34 +09:00
NIIBE Yutaka
ea73e1ee7e bugfic for modp256k1 2014-02-18 14:01:04 +09:00
NIIBE Yutaka
8ca0416be8 Add modp256k1.[ch] 2014-02-18 12:07:33 +09:00
NIIBE Yutaka
d42eba5cb0 Use P256R1 2014-02-18 11:00:28 +09:00
NIIBE Yutaka
60820f5a5f name change p256 -> p256r1 2014-02-17 13:49:35 +09:00
NIIBE Yutaka
2c8f1cb0ce sha improvement 2014-02-05 16:33:21 +09:00
NIIBE Yutaka
2e80472f1c Add sha512 2014-02-05 16:20:26 +09:00
NIIBE Yutaka
8f60b1568f fix sha256 2014-02-05 13:33:58 +09:00
NIIBE Yutaka
91ca2d9827 Assembler MUL/SQR 2014-01-28 11:31:52 +09:00
NIIBE Yutaka
6d2f9f8df1 bug fix for compute_kP 2014-01-28 09:59:26 +09:00
NIIBE Yutaka
42251eea8e Fix for constant time: compute_kP (for ECDH in future) 2014-01-27 16:27:51 +09:00
NIIBE Yutaka
fc5df5019f clean up 2014-01-27 11:26:58 +09:00
NIIBE Yutaka
e18df3af6b clean up 2014-01-27 11:17:10 +09:00
NIIBE Yutaka
4b65ed1a5b simplify compute_kP 2014-01-24 16:16:41 +09:00
NIIBE Yutaka
f4e10311c7 Fix for constant time (step 10): ECDSA done 2014-01-24 14:49:38 +09:00
NIIBE Yutaka
78ffb4179e Fix for constant time (step 9) 2014-01-24 11:05:49 +09:00
NIIBE Yutaka
36541838f9 bug fix 2014-01-23 14:59:55 +09:00
NIIBE Yutaka
29e76d0ba7 cosmetic change 2014-01-22 16:57:19 +09:00
NIIBE Yutaka
c29bd10555 bug fix 2014-01-22 15:53:13 +09:00
NIIBE Yutaka
5c01e92c20 bug fix for ecdsa 2014-01-22 14:34:46 +09:00
NIIBE Yutaka
94508ae5d9 Fix for constant time (step 8) 2014-01-22 14:33:40 +09:00
NIIBE Yutaka
251760d5da Fix for constant time (step 7) 2014-01-22 14:26:41 +09:00
NIIBE Yutaka
6a69c31c3b Fix for constant time (step 6) 2014-01-22 14:09:55 +09:00
NIIBE Yutaka
486f20bfd4 more fix on ecc 2014-01-22 10:02:08 +09:00
NIIBE Yutaka
8d05addc87 bug fix for inf check 2014-01-22 09:58:59 +09:00
NIIBE Yutaka
9f0e2eabd1 bug fix for mod.c change 2014-01-21 21:02:03 +09:00
NIIBE Yutaka
f21a89588c Fix for constant time (step 5) 2014-01-21 14:40:58 +09:00
NIIBE Yutaka
af66c5fa08 format 2014-01-21 14:26:31 +09:00
NIIBE Yutaka
0e7078bacb Fix for constant time (step 4) 2014-01-21 14:14:39 +09:00
NIIBE Yutaka
df8434db59 Fix for constant time (step 3) 2014-01-21 13:58:01 +09:00
NIIBE Yutaka
80d935d913 Fix for constant time (step 2) 2014-01-21 13:31:23 +09:00
NIIBE Yutaka
007eada502 Fix for constant time (step 1) 2014-01-21 13:25:30 +09:00
NIIBE Yutaka
3bb3c6e9d8 member name change 2014-01-21 13:07:20 +09:00
NIIBE Yutaka
4f154cc61d add fe25519 2014-01-20 16:14:10 +09:00
NIIBE Yutaka
38f8b91335 bn.c: constant time 2014-01-15 22:05:18 +09:00
158 changed files with 12368 additions and 9151 deletions

2
.gitignore vendored
View File

@@ -12,3 +12,5 @@ regnual/regnual.bin
regnual/regnual.hex
regnual/regnual.elf
doc/_build
tests/.cache
tests/__pycache__

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "chopstx"]
path = chopstx
url = git@gitorious.org:chopstx/chopstx.git
url = ../../chopstx/chopstx.git

31
AUTHORS
View File

@@ -1,35 +1,10 @@
Kaz Kojima:
Added STM32 Primer2 support:
boards/STM32_PRIMER2/board.c
boards/STM32_PRIMER2/board.h
boards/STM32_PRIMER2/mcuconf.h
Added STM32 Primer2 support.
NIIBE Yutaka:
Founder of the project.
Added FST_01 support:
boards/FST_01/board.c
boards/FST_01/board.h
boards/FST_01/mcuconf.h
Added FST_01_00 support:
boards/FST_01_00/board.c
boards/FST_01_00/board.h
boards/FST_01_00/mcuconf.h
Added STBee support:
boards/STBEE/board.c
boards/STBEE/board.h
boards/STBEE/mcuconf.h
Added STM8S Discovery Kit support:
boards/STM8S_DISCOVERY/board.c
boards/STM8S_DISCOVERY/board.h
boards/STM8S_DISCOVERY/mcuconf.h
Added STBee Mini support:
boards/STBEE_MINI/board.c
boards/STBEE_MINI/board.h
boards/STBEE_MINI/mcuconf.h
Added CQ STARM support:
boards/CQ_STARM/board.c
boards/CQ_STARM/board.h
boards/CQ_STARM/mcuconf.h
Wrote tools for STLink/V2:
tool/stlinkv2.py
Wrote tools for DfuSe:
tool/dfuse.py
tool/dump_mem.py

1147
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
# VID:PID bcdDev Product_STRING Vender_STRING
# VID:PID bcdDev Product_STRING Vendor_STRING
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
20a0:4211 0200 Nitrokey Start Nitrokey
##########<TAB> ##<TAB> ##########<TAB> #################

186
NEWS
View File

@@ -1,5 +1,191 @@
Gnuk NEWS - User visible changes
* Major changes in Gnuk 1.2.3
Released 2017-02-02, by NIIBE Yutaka
** ECC key generation on the device
Bug fixed.
** Upgrade of Chopstx
We use Chopstx 1.3.
* Major changes in Gnuk 1.2.2
Released 2016-10-15, by NIIBE Yutaka
** Change of SELECT FILE behavior
Gnuk used to reply AID upon SELECT FILE command. Now, to be compatible
to original OpenPGP card, it returns nothing but status code of 9000.
** Added feature of Factory Reset as compile time option
Original OpenPGP card has the feature, and Gnuk is now configurable to
support the feature.
** Upgrade of Chopstx
We use Chopstx 1.2.
* Major changes in Gnuk 1.2.1
Released 2016-07-11, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 1.1.
* Major changes in Gnuk 1.2.0
Released 2016-05-20, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.11.
** Support authentication status reset by VERIFY command.
This feature is described in the OpenPGPcard specification V2.2 and
V3.1, which allow user to reset authentication status.
** S2K algorithm tweak to defeat "copycat" service of MCU.
Even if the existence of some services copying MCU, your private key
will not be controled by others, in some cases.
** Bug fix for secp256k1 and NIST P-256.
Bugs in basic computation were fixed.
** Bug fix for bignum routines.
Bignum routine update from upstream (failure doesn't occur for our RSA
computation, though). Another fix for mpi_exp_mod.
* Major changes in Gnuk 1.1.9
Released 2015-09-18, by NIIBE Yutaka
** Bug fix for Ed25519 and Curve25519
When registering key, wrong operations were not detected correctly.
This is fixed.
* Major changes in Gnuk 1.1.8
Released 2015-09-17, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.10, which supports Nitrokey-Start.
** Card serial number
The way to determine a serial number of Gnuk Token for card has been
changed. It uses the 96-bit unique bits of MCU, but the portion for
use is changed.
** USB Reset handling
USB reset lets Gnuk Token restart. It would not be perfect, when it's
during computation of some function, but most parts are protected by
Chopstx's feature of cancellation.
* Major changes in Gnuk 1.1.7
Released 2015-08-05, by NIIBE Yutaka
** Upgrade of Chopstx
We use Chopstx 0.08, which supports STM32 Nucleo and ST Dongle.
* Major changes in Gnuk 1.1.6
Released 2015-07-21, by NIIBE Yutaka
** USB SerialNumber String
The way to determine a serial number of Gnuk Token has been changed.
It uses the 96-bit unique bits of MCU, but the portion for use is
changed.
** Upgrade of Chopstx
We use Chopstx 0.07, which supports STM32 Primer2 and CQ STARM, too.
** Experimental Curve25519 support.
Gnuk can support Curve25519 (for decryption). Note that this is
pretty much experimental, and subjects to change. The low level code
is somehow stable, but there are no consensus in higer level.
Especially, OID in the key attribute would be changed in future.
** No --enable-keygen option
It is now standard feature included always. Note that it doesn't mean
this feature is stable now. It is becoming stable, hopefully.
* Major changes in Gnuk 1.1.5
Released 2015-06-03, by NIIBE Yutaka
** upgrade_by_passwd.py is not so noisy any more.
Since it's getting stable, no debug output any more.
** Maple mini support.
Although its random number generation is not tested, Maple mini
support is added.
** Windows interoperability fix.
1.1.x (0 to 4) didn't work with Windows because of INTERRUPT transfer.
It's fixed and it works now.
** OpenPGPcard specification v3.0 compatibility.
OpenPGPcard specification v3.0 now include NIST curves (and other
curves) and ECDSA and ECDH operations are defined. Gnuk follows
this specification.
* Major changes in Gnuk 1.1.4
Released 2014-12-15, by NIIBE Yutaka
** Experimental RSA-4096 support.
Although it takes too long (more than 8.7 second), RSA-4096
is now implemented.
** ECDH support.
ECDH is now supported. You need development branch (master)
of GnuPG to use this feature.
** ECDSA and EdDSA is not that experimental.
You don't need to edit DEFS variable in src/Makefile.
** STM8S_DISCOVERY is not supported any more.
It's flash ROM size (64KiB) is a bit small to have all features of
Gnuk now. If you manually edit code to limit the size of executable,
it still could run Gnuk, though.
** configure's default target is now FST-01.
Receiving reports from those who complain default target, I
reconsidered. Those who has Olimex STM32 H103 usually has JTAG
debugger, while FST-01 users don't. So, to be safe, the default
target is now FST-01, instead of Olimex STM32 H103.
* Major changes in Gnuk 1.1.3
Released 2014-04-16, by NIIBE Yutaka
** Experimental EdDSA support.
After configure, you can edit the DEFS variable in src/Makefile, so
that Gnuk can support EdDSA with Ed25519 (for authentication). Note
that this is pretty much experimental, and subjects to change.
* Major changes in Gnuk 1.1.2
Released 2014-03-07, by NIIBE Yutaka
** 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

284
README
View File

@@ -1,25 +1,34 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.1.1
2013-12-25
Version 1.2.3
2017-02-02
Niibe Yutaka
Free Software Initiative of Japan
Warning
=======
Release Notes
=============
This is another experimental release of Gnuk 1.1.1, which has
This is the release of Gnuk, version 1.2.3, which has major
incompatible changes to Gnuk 1.0.x. Specifically, it now supports
overriding key import, but importing keys (or generating keys) results
password reset. Please update your documentation for Gnuk Token, so
that the instruction of importing keys won't cause any confusion.
It has supports of EdDSA, ECDSA (with NIST P256 and secp256k1), and
ECDH (with X25519, NIST P256 and secp256k1), but this ECC feature is
somehow experimental, and it requires modern GnuPG 2.1 with libgcrypt
1.7.0 or later.
It also supports RSA-4096, but users should know that it takes more
than 8 seconds to sign/decrypt. Key generation of RSA-4096 just fails,
because the device doesn't have enough memory.
What's Gnuk?
============
Gnuk is an implementation of USB cryptographic token for GNU Privacy
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
STM32F103 processor.
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
@@ -37,9 +46,9 @@ FAQ
===
Q0: How Gnuk USB Token is superior than other solutions (OpenPGP
card 2.0, GPF Crypto Stick, etc.) ?
http://www.g10code.de/p-card.html
http://www.privacyfoundation.de/crypto_stick/
card 2.0, YubiKey, etc.) ?
https://www.g10code.de/p-card.html
https://www.yubico.com/
A0: Good points of Gnuk are:
* If you have skill of electronics and like DIY, you can build
Gnuk Token cheaper (see Q8-A8).
@@ -52,25 +61,28 @@ 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 RSA-2048.
Gnuk version 1.2.x supports 255-bit EdDSA, as well as RSA-4096.
(Note that it takes long time to sign with RSA-4096.)
Q2: How long does it take for digital signing?
A2: It takes a second and a half or so.
A2: It takes a second and a half or so for RSA-2048.
It takes more than 8 secondd for RSA-4096.
Q3: What's your recommendation for target board?
A3: Orthodox choice is Olimex STM32-H103.
If you have skill of electronics and like DIY, STM32 part of STM8S
Discovery Kit might be the best choice.
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
kind of the best choice, hopefully.
If you have a skill of electronics, STM32 Nucleo F103 is the best
choice for experiment.
Q4: What's version of GnuPG are you using?
A4: In Debian GNU/Linux system, I use gnupg 1.4.12-7 and gnupg-agent
2.0.20-1.
A4: In Debian GNU/Linux system, I use GnuPG modern 2.1.18 in
unstable.
Q5: What's version of pcscd and libccid are you using?
A5: I don't use them, pcscd and libccid are optional, you can use Gnuk
without them.
Token without them.
I tested pcscd 1.5.5-4 and libccid 1.3.11-2 which were in Debian
squeeze.
@@ -84,13 +96,10 @@ Q7: How much does it cost?
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
Q8: How much does it cost for DIY version?
A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build
your own JTAG debugger using FTDI2232 module (1450 JPY), see:
http://www.fsij.org/gnuk/jtag_dongle_ftdi2232
A8: STM32 Nucleo F103 costs about $10 USD.
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
A9: Older GnuPG's SCDaemon has problems for handling insertion/removal of
card/reader. When your newly inserted token is not found by
GnuPG, try killing scdaemon and let it to be invoked again. I do:
@@ -106,7 +115,7 @@ Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
Qb: With GNOME 3, I can't use Gnuk Token at all. Why?
Qb: With GNOME 3.0, I can't use Gnuk Token at all. Why?
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
$ gnome-session-properties
@@ -114,21 +123,30 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
and at the tab of "Startup Programs", disable check buttons for
"GPG Password Agent" and "SSH Key Agent".
Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program.
Qc: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
Ac: That's because gnome-keyring-daemon interferes GnuPG. Please
disable the invocation of gnome-keyring-daemon. In Debian
wheezy, it's in the files /etc/xdg/autostart/gnome-keyring-ssh.desktop
and /etc/xdg/autostart/gnome-keyring-gpg.desktop.
We have a line something like:
OnlyShowIn=GNOME;Unity;MATE;
Please edit this line to:
OnlyShowIn=
Qd: Do you know a good SWD debugger to connect FST-01 or something?
Ad: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program. STM32 Nucleo F103 comes with the valiant of
ST-Link/V2. However, the firmware of ST-Link/V2 is proprietary.
Now, I develop BBG-SWD, SWD debugger by BeagleBone Green.
Release notes
=============
Tested features
===============
This is another experimental release in version 1.1 series of Gnuk.
While it is daily use for more than two years, some newly introduced
features (including key generation and firmware upgrade) should be
considered experimental.
Tested features are:
Gnuk is tested by test suite. Please see the test directory.
* Personalization of the card
* Changing Login name, URL, Name, Sex, Language, etc.
@@ -145,10 +163,10 @@ Tested features are:
* Modify with pin pad
* Card holder certificate (read)
* Removal of keys
* Key generation on device side
* Key generation on device side for RSA-2048
* Overriding key import
Original features of Gnuk, tested lightly:
Original features of Gnuk, tested manually lightly:
* OpenPGP card serial number setup
* Card holder certificate (write by UPDATE BINARY)
@@ -156,36 +174,48 @@ Original features of Gnuk, tested lightly:
It is known not-working well:
* It is known that the combination of libccid 1.4.1 (or newer)
with libusb 1.0.8 (or older) has a minor problem. It is
rare but it is possible for USB communication to be failed,
because of a bug in libusb implementation. Use libusbx
1.0.9 or newer, or don't use PC/SC, but use internal CCID
driver of GnuPG.
* It is known that the specific combination of libccid 1.4.1
(or newer) with libusb 1.0.8 (or older) had a minor problem.
It is rare but it is possible for USB communication to be
failed, because of a bug in libusb implementation. Use
libusbx 1.0.9 or newer, or don't use PC/SC, but use internal
CCID driver of GnuPG.
Targets
=======
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01). We
also use STM32 part of STM8S Discovery Kit.
We use Olimex STM32-H103 board and Flying Stone Tiny 01 (FST-01).
With DfuSe support, STBee is also our targets. But this target with
DfuSe is for experiment only, because it is impossible for DfuSe to
disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger.
For PIN-pad support, I connect a consumer IR receive module to FST-01
and STM8S Discovery Kit, and use controller for TV. PIN verification
is supported by this configuration. Yes, it is not secure at all,
since it is very easy to monitor IR output of the controllers. It is
just an experiment. Note that hardware needed for this experiment is
only a consumer IR receive module which is as cheap as 50 JPY.
For experimental PIN-pad support, I connect a consumer IR receive
module to FST-01, and use controller for TV. PIN verification is
supported by this configuration. Yes, it is not secure at all, since
it is very easy to monitor IR output of the controllers. It is just
an experiment. Note that hardware needed for this experiment is only
a consumer IR receive module which is as cheap as 50 JPY.
Note that you need pinpad support for GnuPG to use PIN-pad enabled
Gnuk. The pinpad support for GnuPG is only available in version 2.
Build system and Host system
============================
Makefile is written for GNU make. You need Bash 4.x for configure.
If your bash is not installed as /bin/bash, you need to run configure
script prepending 'bash' before './configure'.
Some tools are written in Python. If your Python is not installed as
/usr/bin/python, please prepend 'python' for your command invocation.
Python 2.7 and PyUSB 0.4.3 is assumed.
Souce code
==========
@@ -218,14 +248,14 @@ External source code
Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 0.03 (+ STBee support)
* chopstx/ -- Chopstx 1.3
We use Chopstx as the kernel for Gnuk.
Chopstx is distributed under GPLv3+ (with a special exception).
* polarssl/ -- PolarSSL 1.2.10
* polarssl/ -- based on PolarSSL 1.2.10 (now mbedTLS)
Souce code taken from: http://polarssl.org/
@@ -271,7 +301,7 @@ Gnuk is distributed with external source code.
USB vendor ID and product ID (USB device ID)
============================================
When you have a vender ID and assign a product ID for Gnuk, edit the
When you have a vendor ID and assign a product ID for Gnuk, edit the
file GNUK_USB_DEVICE_ID and add an entry for yours. In this case,
please contact Niibe, so that it is listed to the file in the official
release of the source code.
@@ -328,10 +358,16 @@ How to compile
You need GNU toolchain and newlib for 'arm-none-eabi' target.
There is "gcc-arm-embedded" project. See:
On Debian we can install the packages of gcc-arm-none-eabi,
gdb-arm-none-eabi and its friends. I'm using:
https://launchpad.net/gcc-arm-embedded/
binutils-arm-none-eabi 2.27-9+9
gcc-arm-none-eabi 15:5.4.1+svn241155-1
gdb-arm-none-eabi 7.11.1-2+9+b1
libnewlib-arm-none-eabi 2.4.0.20160527-2
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
Change directory to `src':
@@ -345,7 +381,8 @@ Here, you need to specify USB vendor ID and product ID. For FSIJ's,
it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and
product ID' above.
Type:
Then, type:
$ make
@@ -358,76 +395,26 @@ How to install
Olimex STM32-H103 board
-----------------------
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD
and write "gnuk.elf" to Flash ROM:
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg \
-f board/olimex_stm32_h103.cfg \
-c "program build/gnuk.elf verify reset exit"
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
Command invocation is assumed in src/ directory.
Flying Stone Tiny 01
--------------------
If you are using Flying Stone Tiny 01, you need a SWD writer. I am
using revision 946 of Simon Qian's Versaloon.
If you are using Flying Stone Tiny 01, you need a SWD writer.
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
For OpenOCD, we need unofficial patch.
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c "program build/gnuk.elf verify reset exit"
See the article of Versaloon Forum:
http://www.versaloon.com/bbs/viewtopic.php?p=16179
Type following to invoke OpenOCD:
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
OpenOCD 0.6.1 now supports ST-Link/V2. We can use it:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg
But it doesn't support option bytes handling (protection) yet.
STM8S Discovery Kit
-------------------
If you are using FTDI-2232D module and the connection is standard, type:
$ openocd -f interface/openocd-usb.cfg -f target/stm32f1x.cfg
Initially, the flash ROM of the chip is protected. you need to do:
$ telnet localhost 4444
> reset halt
> stm32f1x unlock 0
> reset
> shutdown
$
and re-connect the board. Note that power-off / power-on sequence is
required to reset flash ROM.
Then, invoke OpenOCD again and telnet to connect OpenCD and write
image as above example of Olimex STM32-H103.
STBee
@@ -445,27 +432,33 @@ Then, reset the board.
How to protect flash ROM
========================
Invoke your OpenOCD and type:
To protect, invoke OpenOCD like (for FST-01):
$ telnet localhost 4444
> reset halt
> stm32f1x lock 0
> reset
> shutdown
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x lock 0" -c reset -c exit
After power-off / power-on sequence, the contents of flash ROM cannot
be accessible from JTAG debugger.
Unprotecting is:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x unlock 0" -c reset -c exit
Upon unprotection, flash is erased.
Note that it would be still possible for some implementation of DfuSe
to access the contents. If you want to protect, killing DfuSe and
accessing by JTAG debugger is recommended.
to access the contents, even if it's protected. If you really want to
protect, killing DfuSe and accessing by JTAG debugger is recommended.
How to configure
================
(Optional) Configure serial number and X.509 certificate
========================================================
You need python and pyscard (python-pyscard package in Debian) or
PyUSB (python-usb package in Debian).
This is completely optional.
For this procedure, you need python and pyscard (python-pyscard
package in Debian) or PyUSB 0.4.3 (python-usb package in Debian).
(1) [pyscard] Stop scdaemon
[PyUSB] Stop the pcsc daemon.
@@ -484,7 +477,7 @@ In case of PyUSB tool, you need to stop pcscd.
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary.py -s ../GNUK_SERIAL_NUMBER
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary_usb.py -s ../GNUK_SERIAL_NUMBER
Writing serial number
...
@@ -492,7 +485,7 @@ If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
If you have card holder certificate binary file, you can do:
$ ../tool/gnuk_put_binary.py ../../<YOUR-CERTIFICATE>.bin
$ ../tool/gnuk_put_binary_usb.py ../../<YOUR-CERTIFICATE>.bin
../../<YOUR-CERTIFICATE>.bin: <LENGTH-OF-YOUR-CERTIFICATE>
Updating card holder certificate
...
@@ -559,6 +552,10 @@ Inside GDB, we can connect OpenOCD by:
(gdb) target remote localhost:3333
or
(gdb) target extended-remote localhost:3333
You can see the output of PCSCD:
@@ -579,25 +576,25 @@ See doc/note/firmware-update.
Git Repositories
================
Please use: http://gitorious.org/gnuk
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
You can get it by:
$ git clone git://gitorious.org/gnuk/gnuk.git
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
It's also available at: www.gniibe.org
You can browse at: http://www.gniibe.org/gitweb?p=gnuk.git;a=summary
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
I put Chopstx as a submodule of Git. Please do this:
$ git submodule init
$ git submodule update
$ git submodule update --init
We have migrated from ChibiOS/RT to Chopstx. If you have old code of
Gnuk 1.0 uses ChibiOS/RT, and then, we have migrated from to Chopstx
in the development phase of Gnuk 1.1. If you have old code of
ChibiOS/RT, you need:
Edit .git/config to remove chibios reference
git rm --cached chibios
Edit .git/config to remove chibios reference and
$ git rm --cached chibios
Information on the Web
@@ -605,15 +602,24 @@ Information on the Web
Please visit: http://www.fsij.org/gnuk/
Please see the FST-01 support pages:
https://www.gniibe.org/category/fst-01.html
Please consider to join Gnuk-users mailing list:
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
Your Contributions
==================
FSIJ welcomes your contributions. Please assign your copyright
to FSIJ (if possible).
to FSIJ (if possible), as I do.
Foot note
==========
* NUK(R) is a registered trademark owend by MAPA GmbH, Germany.
--

17
THANKS
View File

@@ -8,15 +8,32 @@ encouraging the development, testing the implementation, suggesting
improvements, or fixing bugs. Here is a list of those people.
Achim Pietig achim@pietig.com
Aidan Thornton
Anibal Monsalve Salazar anibal@debian.org
Andre Zepezauer andre.zepezauer@student.uni-halle.de
Bertrand Jacquin bertrand@jacquin.bzh
Clint Adams clint@softwarefreedom.org
Daniel Kahn Gillmor dkg@fifthhorseman.net
Elliott Mitchell
Hironobu SUZUKI hironobu@h2np.net
Jan Suhr jan@suhr.info
Jonathan McDowell noodles@earth.li
Kaz Kojima kkojima@rr.iij4u.or.jp
Kenji Rikitake
Ludovic Rousseau ludovic.rousseau@free.fr
Luis Felipe R. Murillo luisfelipe@ucla.edu
Mateusz Zalega mateusz@nitrokey.com
MATSUU Takuto matsuu@gentoo.org
Micah Anderson micah@debian.org
NAGAMI Takeshi nagami-takeshi@aist.go.jp
Nguyễn Hồng Quân quannguyen@mbm.vn
Nico Rikken nico@nicorikken.eu
NOKUBI Takatsugu knok@daionet.gr.jp
Paul Fertser
Paul Bakker polarssl_maintainer@polarssl.org
Santiago Ruano Rincón santiago@debian.org
Shane Coughlan scoughlan@openinventionnetwork.com
Szczepan Zalega szczepan@nitrokey.com
Vasily Evseenko
Werner Koch wk@gnupg.org
Yuji Imai ug@xcast.jp

View File

@@ -1 +1 @@
release/1.1.1
release/1.2.3

View File

@@ -1,10 +0,0 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
/*
* Board-specific initialization code.
*/
void boardInit(void)
{
}

View File

@@ -1,163 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for the CQ STARM board.
*/
#undef SET_USB_CONDITION /* No functionality to disconnect USB */
#define SET_LED_CONDITION(on) on /* To emit light, call palSetPad */
#define GPIO_LED GPIOC_LED
#define IOPORT_LED GPIOC
/*
* Board identifier.
*/
#define BOARD_CQ_STARM
#define BOARD_NAME "CQ STARM"
/*
* Board frequencies.
*/
#define STM32_LSECLK 32768
#define STM32_HSECLK 8000000
/*
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
* native STM32 HAL.
*/
#define STM32F10X_MD
/*
* IO pins assignments.
*/
#define GPIOC_LED 6
#if 0
#define GPIOA_BUTTON 0
#define GPIOA_SPI1NSS 4
#define GPIOB_SPI2NSS 12
#define GPIOC_MMCWP 6
#define GPIOC_MMCCP 7
#define GPIOC_CANCNTL 10
#define GPIOC_DISC 11
#endif
/*
* I/O ports initial setup, this configuration is established soon after reset
* in the initialization code.
*
* The digits have the following meaning:
* 0 - Analog input.
* 1 - Push Pull output 10MHz.
* 2 - Push Pull output 2MHz.
* 3 - Push Pull output 50MHz.
* 4 - Digital input.
* 5 - Open Drain output 10MHz.
* 6 - Open Drain output 2MHz.
* 7 - Open Drain output 50MHz.
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
* 9 - Alternate Push Pull output 10MHz.
* A - Alternate Push Pull output 2MHz.
* B - Alternate Push Pull output 50MHz.
* C - Reserved.
* D - Alternate Open Drain output 10MHz.
* E - Alternate Open Drain output 2MHz.
* F - Alternate Open Drain output 50MHz.
* Please refer to the STM32 Reference Manual for details.
*/
/*
* Port A setup.
* Everything input with pull-up except:
* PA4 - Normal input (ADC_IN4 : VoutX of LIS344ALH).
* PA5 - Alternate output (MMC SPI1 SCK).
* PA6 - Normal input (MMC SPI1 MISO).
* PA7 - Alternate output (MMC SPI1 MOSI).
* PA11 - (USBDM)
* PA12 - (USBDP)
*/
#define VAL_GPIOACRL 0xB4B48888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFF
/*
* Port B setup.
* Everything input with pull-up except:
* PB13 - Alternate output (MMC SPI2 SCK).
* PB14 - Normal input (MMC SPI2 MISO).
* PB15 - Alternate output (MMC SPI2 MOSI).
*/
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0xB4B88888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
* PC4 - Normal input (ADC_IN14 : VoutY of LIS344ALH).
* PC5 - Normal input (ADC_IN15 : VoutZ of LIS344ALH).
* PC6 - Push Pull output (LED).
* (PC9 - SDCard CD)
* (PC12 - SDCard CS)
* PC14 - Normal input (XTAL).
* PC15 - Normal input (XTAL).
*/
#define VAL_GPIOCCRL 0x83448888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x44888888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* (PD9 - USB_DC)
*/
#define VAL_GPIODCRL 0x88888888 /* PD7...PD0 */
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
#define VAL_GPIODODR 0xFFFFFFFF
/*
* Port E setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
#define VAL_GPIOEODR 0xFFFFFFFF
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@@ -1,14 +0,0 @@
/*
* HAL driver system settings.
*/
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 9
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -1,151 +0,0 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
/*
* Board-specific initialization code.
*/
void boardInit(void)
{
#if !defined(DFU_SUPPORT)
if (palReadPad (IOPORT3, GPIOC_BUTTON) == 0)
/*
* Since LEDs are connected to JTMS/SWDIO and JTDI pin,
* we can't use LED to let know users in this state.
*/
for (;;); /* Wait for JTAG debugger connection */
#endif
#if defined(PINPAD_SUPPORT) && !defined(DFU_SUPPORT)
palWritePort(IOPORT2, 0x7fff); /* Only clear GPIOB_7SEG_DP */
while (palReadPad (IOPORT2, GPIOB_BUTTON) != 0)
; /* Wait for JTAG debugger connection */
palWritePort(IOPORT2, 0xffff); /* All set */
#endif
#if defined(PINPAD_CIR_SUPPORT)
/* EXTI0 <= PB0 */
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
EXTI->IMR = 0;
EXTI->FTSR = EXTI_FTSR_TR0;
NVICEnableVector(EXTI0_IRQn,
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
/* TIM3 */
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
RCC->APB1RSTR = RCC_APB1RSTR_TIM3RST;
RCC->APB1RSTR = 0;
NVICEnableVector(TIM3_IRQn,
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
TIM3->CR1 = TIM_CR1_URS | TIM_CR1_ARPE; /* Don't enable TIM3 for now */
TIM3->CR2 = TIM_CR2_TI1S;
TIM3->SMCR = TIM_SMCR_TS_0 | TIM_SMCR_TS_2 | TIM_SMCR_SMS_2;
TIM3->DIER = 0; /* Disable interrupt for now */
TIM3->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_3
| TIM_CCMR1_CC2S_1 | TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_3;
TIM3->CCMR2 = 0;
TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
TIM3->PSC = 72 - 1; /* 1 MHz */
TIM3->ARR = 18000; /* 18 ms */
/* Generate UEV to upload PSC and ARR */
TIM3->EGR = TIM_EGR_UG;
#elif defined(PINPAD_DIAL_SUPPORT)
/* EXTI2 <= PB2 */
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI2_PB;
EXTI->IMR = 0;
EXTI->FTSR = EXTI_FTSR_TR2;
NVICEnableVector(EXTI2_IRQn,
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
/* TIM4 */
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
RCC->APB1RSTR = RCC_APB1RSTR_TIM4RST;
RCC->APB1RSTR = 0;
TIM4->CR1 = TIM_CR1_URS | TIM_CR1_ARPE | TIM_CR1_CKD_1;
TIM4->CR2 = 0;
TIM4->SMCR = TIM_SMCR_SMS_0;
TIM4->DIER = 0; /* no interrupt */
TIM4->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0
| TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 | TIM_CCMR1_IC1F_3
| TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_IC2F_2 | TIM_CCMR1_IC2F_3;
TIM4->CCMR2 = 0;
TIM4->CCER = 0;
TIM4->PSC = 0;
TIM4->ARR = 31;
/* Generate UEV to upload PSC and ARR */
TIM4->EGR = TIM_EGR_UG;
#endif
/*
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
*/
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_DISABLE;
/* We use LED2 as optional "error" indicator */
palSetPad (IOPORT1, GPIOA_LED2);
}
#if defined(PINPAD_CIR_SUPPORT)
void
cir_ext_disable (void)
{
EXTI->PR = EXTI_PR_PR0;
EXTI->IMR &= ~EXTI_IMR_MR0;
}
void
cir_ext_enable (void)
{
EXTI->IMR |= EXTI_IMR_MR0;
}
extern void cir_ext_interrupt (void);
extern void cir_timer_interrupt (void);
CH_IRQ_HANDLER (EXTI0_IRQHandler)
{
CH_IRQ_PROLOGUE ();
chSysLockFromIsr ();
cir_ext_interrupt ();
chSysUnlockFromIsr ();
CH_IRQ_EPILOGUE ();
}
CH_IRQ_HANDLER (TIM3_IRQHandler)
{
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
cir_timer_interrupt ();
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
#elif defined(PINPAD_DIAL_SUPPORT)
void
dial_sw_disable (void)
{
EXTI->PR = EXTI_PR_PR2;
EXTI->IMR &= ~EXTI_IMR_MR2;
}
void
dial_sw_enable (void)
{
EXTI->IMR |= EXTI_IMR_MR2;
}
extern void dial_sw_interrupt (void);
CH_IRQ_HANDLER (EXTI2_IRQHandler)
{
CH_IRQ_PROLOGUE ();
chSysLockFromIsr ();
dial_sw_interrupt ();
chSysUnlockFromIsr ();
CH_IRQ_EPILOGUE ();
}
#endif

View File

@@ -1,205 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#include "config.h"
/*
* Setup for the STBee Mini board.
*/
#define SET_USB_CONDITION(en) (en) /* To connect USB, call palSetPad */
#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */
#define GPIO_USB GPIOA_USB_ENABLE
#define IOPORT_USB GPIOA
#define GPIO_LED GPIOA_LED1
#define IOPORT_LED GPIOA
#define NEUG_ADC_SETTING2_SMPR1 0
#define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5) \
| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5)
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1) \
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2)
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
/*
* Board identifier.
*/
#define BOARD_STBEE_MINI
#define BOARD_NAME "STBee Mini"
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
#define HAVE_7SEGLED 1
/*
* Timer assignment for CIR
*/
#define TIMx TIM3
#endif
/*
* Board frequencies.
*/
#define STM32_LSECLK 32768
#define STM32_HSECLK 12000000
/*
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
* native STM32 HAL.
*/
#define STM32F10X_MD
/*
* IO pins assignments.
*/
#define GPIOA_LED1 13
#define GPIOA_USB_ENABLE 14
#define GPIOA_LED2 15
#define GPIOC_BUTTON 13
/*
* I/O ports initial setup, this configuration is established soon after reset
* in the initialization code.
*
* The digits have the following meaning:
* 0 - Analog input.
* 1 - Push Pull output 10MHz.
* 2 - Push Pull output 2MHz.
* 3 - Push Pull output 50MHz.
* 4 - Digital input.
* 5 - Open Drain output 10MHz.
* 6 - Open Drain output 2MHz.
* 7 - Open Drain output 50MHz.
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
* 9 - Alternate Push Pull output 10MHz.
* A - Alternate Push Pull output 2MHz.
* B - Alternate Push Pull output 50MHz.
* C - Reserved.
* D - Alternate Open Drain output 10MHz.
* E - Alternate Open Drain output 2MHz.
* F - Alternate Open Drain output 50MHz.
* Please refer to the STM32 Reference Manual for details.
*/
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DIAL_SUPPORT)
/*
* Port A setup.
* PA1 - Digital input with PullUp. AN1 for NeuG
* PA2 - Digital input with PullUp. AN2 for NeuG
* PA6 - (TIM3_CH1) input with pull-up
* PA7 - (TIM3_CH2) input with pull-down
* PA11 - input with pull-up (USBDM)
* PA12 - input with pull-up (USBDP)
* Everything input with pull-up except:
* PA13 - Open Drain output (LED1 0:ON 1:OFF)
* PA14 - Push pull output (USB ENABLE 0:DISABLE 1:ENABLE)
* PA15 - Open Drain output (LED2 0:ON 1:OFF)
*/
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x63688888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFF7F
/* Port B setup. */
#define GPIOB_CIR 0
#define GPIOB_BUTTON 2
#define GPIOB_ROT_A 6
#define GPIOB_ROT_B 7
#define GPIOB_7SEG_DP 15
#define GPIOB_7SEG_A 14
#define GPIOB_7SEG_B 13
#define GPIOB_7SEG_C 12
#define GPIOB_7SEG_D 11
#define GPIOB_7SEG_E 10
#define GPIOB_7SEG_F 9
#define GPIOB_7SEG_G 8
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0x66666666 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
#else
/*
* Port A setup.
* PA1 - Digital input with PullUp. AN1 for NeuG
* PA2 - Digital input with PullUp. AN2 for NeuG
* PA11 - input with pull-up (USBDM)
* PA12 - input with pull-up (USBDP)
* Everything input with pull-up except:
* PA13 - Open Drain output (LED1 0:ON 1:OFF)
* PA14 - Push pull output (USB ENABLE 0:DISABLE 1:ENABLE)
* PA15 - Open Drain output (LED2 0:ON 1:OFF)
*/
#define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */
#define VAL_GPIOACRH 0x63688888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFFFF
/* Port B setup. */
/* Everything input with pull-up */
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
#endif
/*
* Port C setup.
* Everything input with pull-up except:
* PC13 - Normal input.
* PC14 - Normal input.
* PC15 - Normal input.
*/
#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x44488888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* PD0 - Normal input (XTAL).
* PD1 - Normal input (XTAL).
*/
#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
#define VAL_GPIODODR 0xFFFFFFFF
/*
* Port E setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
#define VAL_GPIOEODR 0xFFFFFFFF
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@@ -1,14 +0,0 @@
/*
* HAL driver system settings.
*/
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE 6
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -1,15 +0,0 @@
#include "config.h"
#include "ch.h"
#include "hal.h"
/*
* Board-specific initialization code.
*/
void boardInit(void)
{
/*
* Clear LED and SHUTDOWN output.
*/
palClearPad (IOPORT5, GPIOE_LED);
palClearPad (IOPORT3, GPIOC_SHUTDOWN);
}

View File

@@ -1,175 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for the STM32 Primer2.
*/
#define SET_USB_CONDITION(en) (!en) /* To connect USB, call palClearPad */
#define SET_LED_CONDITION(on) (!on) /* To emit light, call palClearPad */
#define GPIO_USB GPIOD_DISC
#define IOPORT_USB GPIOD
#define GPIO_LED GPIOE_LEDR
#define IOPORT_LED GPIOE
/* NeuG settings for ADC2. */
/*
* Board identifier.
*/
#define BOARD_STM32_PRIMER2
#define BOARD_NAME "STM32 Primer2"
/*
* Board frequencies.
*/
#define STM32_LSECLK 32768
#define STM32_HSECLK 12000000
/*
* MCU type, this macro is used by both the ST library and the ChibiOS/RT
* native STM32 HAL.
*/
#define STM32F10X_MD
/*
* IO pins assignments.
*/
#define GPIOA_BUTTON 8
#define GPIOC_SHUTDOWN 13
#define GPIOD_DISC 3
#define GPIOE_LED 0
#define GPIOE_LEDR 1
/*
* I/O ports initial setup, this configuration is established soon after reset
* in the initialization code.
*
* The digits have the following meaning:
* 0 - Analog input.
* 1 - Push Pull output 10MHz.
* 2 - Push Pull output 2MHz.
* 3 - Push Pull output 50MHz.
* 4 - Digital input.
* 5 - Open Drain output 10MHz.
* 6 - Open Drain output 2MHz.
* 7 - Open Drain output 50MHz.
* 8 - Digital input with PullUp or PullDown resistor depending on ODR.
* 9 - Alternate Push Pull output 10MHz.
* A - Alternate Push Pull output 2MHz.
* B - Alternate Push Pull output 50MHz.
* C - Reserved.
* D - Alternate Open Drain output 10MHz.
* E - Alternate Open Drain output 2MHz.
* F - Alternate Open Drain output 50MHz.
* Please refer to the STM32 Reference Manual for details.
*/
/*
* Port A setup.
* Everything input with pull-up except:
* PA0 - Digital input with PullUp. AN0
* PA1 - Digital input with PullUp. AN1
* PA2 - Alternate output (USART2 TX).
* PA3 - Normal input (USART2 RX).
* PA8 - Input with pull-down (PBUTTON).
*/
#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */
#define VAL_GPIOACRH 0x88888888 /* PA15...PA8 */
#define VAL_GPIOAODR 0xFFFFFEFF
/*
* Port B setup.
* Everything input with pull-up except:
* PB13 - Alternate output (AUDIO SPI2 SCK).
* PB14 - Normal input (AUDIO SPI2 MISO).
* PB15 - Alternate output (AUDIO SPI2 MOSI).
*/
#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
#define VAL_GPIOBCRH 0xB4B88888 /* PB15...PB8 */
#define VAL_GPIOBODR 0xFFFFFFFF
/*
* Port C setup.
* Everything input with pull-up except:
* PC6 - Normal input because there is an external resistor.
* PC7 - Normal input because there is an external resistor.
* PC13 - Push Pull output (SHUTDOWN)
*/
#define VAL_GPIOCCRL 0x44888888 /* PC7...PC0 */
#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */
#define VAL_GPIOCODR 0xFFFFFFFF
/*
* Port D setup.
* Everything input with pull-up except:
* PD3 - Push Pull output (USB_DISCONNECT)
*/
#define VAL_GPIODCRL 0x88883888 /* PD7...PD0 */
#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
#define VAL_GPIODODR 0xFFFFFFFF
/*
* Port E setup.
* Everything input with pull-up except:
* PE0 - Push Pull output (LED0).
* PD1 - Push Pull output (LED1).
*/
#define VAL_GPIOECRL 0x88888833 /* PE7...PE0 */
#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
#define VAL_GPIOEODR 0xFFFFFFFF
#if 0
/*
* Port F setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOFCRL 0x88888888 /* PF7...PF0 */
#define VAL_GPIOFCRH 0x88888888 /* PF15...PF8 */
#define VAL_GPIOFODR 0xFFFFFFFF
/*
* Port G setup.
* Everything input with pull-up except:
*/
#define VAL_GPIOGCRL 0x88888888 /* PG7...PG0 */
#define VAL_GPIOGCRH 0x88888888 /* PG15...PG8 */
#define VAL_GPIOGODR 0xFFFFFFFF
#endif
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@@ -1,14 +0,0 @@
/*
* HAL driver system settings.
*/
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSE
#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV2
#define STM32_PLLMUL_VALUE 12
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV2
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_ADCPRE STM32_ADCPRE_DIV6
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
#include "mcuconf-common.h"

View File

@@ -1,69 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
#include "ch.h"
#include "hal.h"
#include "config.h"
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
#if HAL_USE_PAL || defined(__DOXYGEN__)
const PALConfig pal_default_config =
{
{VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH},
{VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH},
{VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH},
{VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH},
{VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH},
#if defined(STM32F10X_HD)
{VAL_GPIOFODR, VAL_GPIOFCRL, VAL_GPIOFCRH},
{VAL_GPIOGODR, VAL_GPIOGCRL, VAL_GPIOGCRH},
#endif
};
#endif
/*
* Early initialization code.
* This initialization must be performed just after stack setup and before
* any other initialization.
*/
void
__early_init(void)
{
stm32_clock_init();
}
const uint8_t *
unique_device_id (void)
{
/* STM32F103 has 96-bit unique device identifier */
const uint8_t *addr = (const uint8_t *)0x1ffff7e8;
return addr;
}

View File

@@ -1,116 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes ChibiOS/RT, without being obliged to provide
the source code for any proprietary components. See the file exception.txt
for full details of how and when the exception can be applied.
*/
/*
* STM32 drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the driver
* is enabled in halconf.h.
*
* IRQ priorities:
* 15...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_HSI_ENABLED TRUE
#define STM32_LSI_ENABLED FALSE
#define STM32_HSE_ENABLED TRUE
#define STM32_LSE_ENABLED FALSE
#define STM32_USB_CLOCK_REQUIRED TRUE
#define STM32_USBPRE STM32_USBPRE_DIV1P5
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
/*
* ADC driver system settings.
*/
#define USE_STM32_ADC1 TRUE
#define STM32_ADC1_DMA_PRIORITY 3
#define STM32_ADC1_IRQ_PRIORITY 5
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
/*
* CAN driver system settings.
*/
#define USE_STM32_CAN1 FALSE
#define STM32_CAN1_IRQ_PRIORITY 11
/*
* PWM driver system settings.
*/
#define USE_STM32_PWM1 FALSE
#define USE_STM32_PWM2 FALSE
#define USE_STM32_PWM3 FALSE
#define USE_STM32_PWM4 FALSE
#define STM32_PWM1_IRQ_PRIORITY 7
#define STM32_PWM2_IRQ_PRIORITY 7
#define STM32_PWM3_IRQ_PRIORITY 7
#define STM32_PWM4_IRQ_PRIORITY 7
/*
* SERIAL driver system settings.
*/
#define USE_STM32_USART1 FALSE
#define USE_STM32_USART2 FALSE
#define USE_STM32_USART3 FALSE
#if defined(STM32F10X_HD) || defined(STM32F10X_CL)
#define USE_STM32_UART4 FALSE
#define USE_STM32_UART5 FALSE
#endif
#define STM32_USART1_PRIORITY 12
#define STM32_USART2_PRIORITY 12
#define STM32_USART3_PRIORITY 12
#if defined(STM32F10X_HD) || defined(STM32F10X_CL)
#define STM32_UART4_PRIORITY 12
#define STM32_UART5_PRIORITY 12
#endif
/*
* SPI driver system settings.
*/
#define USE_STM32_SPI1 FALSE
#define USE_STM32_SPI2 FALSE
#define STM32_SPI1_DMA_PRIORITY 2
#define STM32_SPI2_DMA_PRIORITY 2
#define STM32_SPI1_IRQ_PRIORITY 10
#define STM32_SPI2_IRQ_PRIORITY 10
#define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt()
/*
* USB driver system settings.
*/
#define STM32_USB_USE_USB1 TRUE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY 6
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14

Submodule chopstx updated: f344d926c1...89eb54929e

View File

@@ -25,7 +25,7 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode']
extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

View File

@@ -22,24 +22,19 @@ tool/stlinkv2.py.
OpenOCD
-------
For JTAG/SWD debugger, we can use OpenOCD somehow.
Note that ST-Link/V2 was *not* supported by OpenOCD 0.5.0.
It is supported by version 0.6 or later somehow, but still, you can't
enable protection of flash ROM with OpenOCD using ST-Link/V2.
For JTAG/SWD debugger, we can use OpenOCD.
GNU Toolchain
-------------
You need GNU toolchain and newlib for 'arm-none-eabi' target.
In Debian, we can just apt-get packages of: gcc-arm-none-eabi, binutils-arm-none-eabi, gdb-arm-none-eabi and libnewlib-arm-none-eabi.
There is "gcc-arm-embedded" project. See:
For other distributiions, there is "gcc-arm-embedded" project. See:
https://launchpad.net/gcc-arm-embedded/
It is based on GCC 4.8 (as of December, 2013). We are using "-O3 -Os"
for compiler option.
We are using "-O3 -Os" for compiler option.
Building Gnuk

View File

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

487
doc/generating-key.rst Normal file
View File

@@ -0,0 +1,487 @@
====================
Generating key pairs
====================
In this section, we describe how to generate 2048-bit RSA keys.
You would like to use newer ECC keys instead of RSA keys. It is also described.
Key length of RSA
=================
In 2005, NIST (National Institute of Standards and Technology, USA)
issued the first revision of NIST Special Publication 800-57,
"Recommendation for Key Management".
In 800-57, NIST advises that 1024-bit RSA keys will no longer be
viable after 2010 and advises moving to 2048-bit RSA keys. NIST
advises that 2048-bit keys should be viable until 2030.
As of 2016, GnuPG's default for generating RSA key is 2048-bit.
Some people have preference on RSA 4096-bit keys, considering "longer is better".
However, "longer is better" is not always true. When it's long, it
requires more computational resource, memory, and storage. Further,
it consumes more power for nomal usages. These days, many people has
enough computational resource, that would be true, but less is better
for power consumption, isn't it?
For security, the key length is just a single factor. We had and will have
algorithm issues, too. It is true that it's difficult to update
our public keys, but this problem wouldn't be solved by just having
longer keys.
We deliberately recommend use of RSA 2048-bit keys for Gnuk,
considering device computation power and host software constraints.
Thus, the key size is 2048-bit in the examples below.
When/If your environment allows use of newer ECC keys, newer ECC keys are recommended.
Generating RSA keys on host PC
==============================
Here is the example session to generate main key and a subkey for encryption.
I invoke GnuPG with ``--quick-gen-key`` option. ::
$ gpg --quick-gen-key "Niibe Yutaka <gniibe@fsij.org>"
About to create a key for:
"Niibe Yutaka <gniibe@fsij.org>"
Continue? (Y/n) y
It askes passphrase for this **key on host PC**.
Note that this is a passphrase for the key on host PC.
It is different thing to the passphrase of Gnuk Token.
We enter two same inputs two times
(once for passphrase input, and another for confirmation),
<PASSWORD-KEY-ON-PC>.
Then, GnuPG generate keys. It takes some time. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 76A9392B02CD15D1 marked as ultimately trusted
gpg: revocation certificate stored as '/home/gniibe.gnupg/openpgp-revocs.d/36CE0B8408CFE5CD07F94ACF76A9392B02CD15D1.rev'
public and secret key created and signed.
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub rsa2048 2016-06-20 [S]
36CE0B8408CFE5CD07F94ACF76A9392B02CD15D1
uid [ultimate] Niibe Yutaka <gniibe@fsij.org>
sub rsa2048 2016-06-20 []
Done.
Then, we create authentication subkey.
Authentication subkey is not that common,
but very useful (for SSH authentication).
As it is not that common, we need ``--expert`` option for GnuPG. ::
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
sec rsa2048/76A9392B02CD15D1
created: 2016-06-20 expires: never usage: SC
trust: ultimate validity: ultimate
ssb rsa2048/4BD1EB26F0E607E6
created: 2016-06-20 expires: never usage: E
[ultimate] (1). Niibe Yutaka <gniibe@fsij.org>
gpg>
Here, it displays that there are main key and a subkey.
It prompts sub-command with ``gpg>`` .
Here, we enter ``addkey`` sub-command.
gpg> addkey
GnuPG asks kind of key. We select ``RSA (set your own capabilities)``. ::
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
Your selection? 8
And select ``Authenticate`` for the capabilities for this key.
Initially, it's ``Sign`` and ``Encrypt``.
I need to deselect ``Sign`` and ``Encrypt``, and select ``Authenticate``.
To do that, I enter ``s``, ``e``, and ``a``. ::
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? e
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? a
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
OK, we set the capability of ``Authenticate``.
We enter ``q`` to finish setting capabilities. ::
Your selection? q
GnuPG asks bitsize and expiration, we enter 2048 for bitsize and no expiration.
Then, we confirm that we really create the key. ::
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
Then, it askes the passphrase, it is the passphrase of **key on host PC**.
It's the one we entered above as <PASSWORD-KEY-ON-PC>.
Then, GnuPG generate the key. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec rsa2048/76A9392B02CD15D1
created: 2016-06-20 expires: never usage: SC
trust: ultimate validity: ultimate
ssb rsa2048/4BD1EB26F0E607E6
created: 2016-06-20 expires: never usage: E
ssb rsa2048/F3BA52C64012198D
created: 2016-06-20 expires: never usage: A
[ultimate] (1). Niibe Yutaka <gniibe@fsij.org>
gpg>
We save the key (to the storage of the host PC). ::
gpg> save
$
Now, we have three keys (one primary key for signature and certification,
subkey for encryption, and another subkey for authentication).
Publishing public key
=====================
We make a file for the public key by ``--export`` option of GnuPG. ::
$ gpg --armor --output <YOUR-KEY>.asc --export <YOUR-KEY-ID>
We can publish the file by web server. Or we can publish the key
to a keyserver, by invoking GnuPG with ``--send-keys`` option. ::
$ gpg --keyserver pool.sks-keyservers.net --send-keys <YOUR-KEY-ID>
Here, pool.sks-keyservers.net is a keyserver, which is widely used.
Backup the private key
======================
There are some ways to back up private key, such that backup .gnupg
directory entirely, or use of paperkey, etc.
Here, we describe backup by ASCII file.
ASCII file is good, because it has less risk on transfer.
Binary file has a risk to be modified on transfer.
Note that the key on host PC is protected by passphrase (which
is <PASSWORD-KEY-ON-PC> in the example above). Using the key
from the backup needs this passphrase. It is common that
people will forget passphrase for backup. Never forget it.
You have been warned.
To make ASCII backup for private key,
invokde GnuPG with ``--armor`` option and ``--export-secret-keys``
specifying the key identifier. ::
$ gpg --armor --output <YOUR-SECRET>.asc --export-secret-keys <YOUR-KEY-ID>
From the backup,
we can recover privet key by invoking GnuPG with ``--import`` option. ::
$ gpg --import <YOUR-SECRET>.asc
Generating ECC keys on host PC
==============================
Here is an example session log to create newer ECC keys. You need
libgcrypt 1.7 or newer and GnuPG 2.1.8 or newer.
Next, we invoke gpg frontend with ``--expert`` and ``--full-gen-key`` option. ::
$ gpg --expert --full-gen-key
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Then, we input ``9`` to select ECC primary key and ECC encryption subkey. ::
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
Your selection? 9
Next is the important selection. We input ``1`` to select "Curve25519". ::
Please select which elliptic curve you want:
(1) Curve 25519
(2) NIST P-256
(3) NIST P-384
(4) NIST P-521
(5) Brainpool P-256
(6) Brainpool P-384
(7) Brainpool P-512
(8) secp256k1
Your selection? 1
You may see WARNING (it depends on version of GnuPG) and may been asked. Since it is what you want, please answer with 'y'. ::
gpg: WARNING: Curve25519 is not yet part of the OpenPGP standard.
Use this curve anyway? (y/N) y
It asks about expiration of key. ::
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
Then, it asks about a user ID. ::
GnuPG needs to construct a user ID to identify your key.
Real name: Kunisada Chuji
Email address: chuji@gniibe.org
Comment:
You selected this USER-ID:
"Kunisada Chuji <chuji@gniibe.org>"
Lastly, it asks confirmation. ::
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
Then, it goes like this. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
It asks the passphrase for keys by pop-up window, and then, finishes. ::
gpg: key 17174C1A7C406DB5 marked as ultimately trusted
gpg: revocation certificate stored as '/home/gniibe.gnupg/openpgp-revocs.d/1719874a4fe5a1d8c465277d5a1bb27e3000f4ff.rev'
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 6 signed: 67 trust: 0-, 0q, 0n, 0m, 0f, 6u
gpg: depth: 1 valid: 67 signed: 40 trust: 67-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2016-10-05
pub ed25519 2016-07-08
F478770235B60A230BE78005006A236C292C31D7
uid [ultimate] Kunisada Chuji <chuji@gniibe.org>
sub cv25519 2016-07-08
$
We have the primary key with ed25519, and encryption subkey with cv25519.
Next, we add authentication subkey which can be used with OpenSSH.
We invoke gpg frontend with ``--edit-key`` and the key ID. ::
$ gpg2 --expert --edit-key 17174C1A7C406DB5
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
sec ed25519/17174C1A7C406DB5
created: 2016-07-08 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/37A03183DF7B31B1
created: 2016-07-08 expires: never usage: E
[ultimate] (1). Kunisada Chuji <chuji@gniibe.org>
We invoke ``addkey`` subcommand. ::
gpg> addkey
It asks a kind of key, we input ``11`` to select ECC for authentication. ::
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
Your selection? 11
and then, we specify "Authenticate" capability. ::
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? a
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign Authenticate
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? q
Then, it asks which curve. We input ``1`` for "Curve25519". ::
Please select which elliptic curve you want:
(1) Curve 25519
(2) NIST P-256
(3) NIST P-384
(4) NIST P-521
(5) Brainpool P-256
(6) Brainpool P-384
(7) Brainpool P-512
(8) secp256k1
Your selection? 1
It may ask confirmation with WARNING (depends on version). We say ``y``. ::
gpg: WARNING: Curve25519 is not yet part of the OpenPGP standard.
Use this curve anyway? (y/N) y
It asks expiration of the key. ::
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
And the confirmation. ::
Really create? (y/N) y
It goes. ::
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
It asks the passphrase. And done. ::
sec ed25519/17174C1A7C406DB5
created: 2016-09-08 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/37A03183DF7B31B1
created: 2016-09-08 expires: never usage: E
ssb ed25519/4AD7D2428679DF5F
created: 2016-09-08 expires: never usage: A
[ultimate] (1). Kunisada Chuji <chuji@gniibe.org>
We type ``save`` to exit form gpg. ::
gpg> save
$

View File

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

View File

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

View File

@@ -22,33 +22,31 @@ See `another document`_ to import keys to the Token from copied directory.
After personalization, I put my keys into the Token.
Here is the log.
Here is the session log.
I invoke GnuPG with my key (4ca7babe). ::
I invoke GnuPG with my key (249CB3771750745D5CDD323CE267B052364F028D). ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
$ gpg --edit-key 249CB3771750745D5CDD323CE267B052364F028D
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@debian.org>
[ultimate] (2) NIIBE Yutaka <gniibe@fsij.org>
gpg>
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``.
To enable ``keytocard`` command, I type ``toggle`` command. ::
gpg> toggle
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
Firstly, I import my primary key into Gnuk Token.
I type ``keytocard`` command, answer ``y`` to confirm keyimport,
@@ -56,135 +54,129 @@ and type ``1`` to say it's signature key. ::
gpg> keytocard
Really move the primary key? (y/N) y
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
Then, GnuPG asks two passwords. One is the passphrase of **keys on PC**
and another is the password of **Gnuk Token**. Note that the password of
the token and the password of the keys on PC are different things,
Then, GnuPG asks two kinds of passphrases. One is the passphrase of **keys on PC**
and another is the passphrase of **Gnuk Token**. Note that the passphrase of
the token and the passphrase of the keys on PC are different things,
although they can be same.
Here, I assume that Gnuk Token's admin password of factory setting (12345678).
Here, I assume that Gnuk Token's admin passphrase of factory setting (12345678).
I enter these passwords. ::
I enter these passphrases. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
gpg: 3 Admin PIN attempts remaining before card is permanently locked
Please enter your passphrase, so that the secret key can be unlocked for this session
<PASSWORD-KEY-ON-PC>
Please enter the Admin PIN
Enter Admin PIN: 12345678
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
The primary key is now on the Token and GnuPG says its card-no (F517 00000001),
where F517 is the vendor ID of FSIJ.
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
Secondly, I import my subkey of encryption. I select key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb* cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
You can see that the subkey is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``2`` as it's encryption key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(2) Encryption key
Your selection? 2
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 084239CF, created 2010-10-15
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
Please enter your passphrase, so that the secret key can be unlocked for this session
<PASSWORD-KEY-ON-PC>
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb* cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
The sub key is now on the Token.
The sub key is now on the Token and GnuPG says its card-no for it.
I type ``key 1`` to deselect key number '1'. ::
gpg> key 1
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
Thirdly, I select sub key of authentication which has key number '2'. ::
gpg> key 2
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
(1) NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb* ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
You can see that the subkey number '2' is marked by '*'.
I type ``keytocard`` command to import this subkey to Gnuk Token.
I select ``3`` as it's authentication key. ::
gpg> keytocard
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
Please select where to store the key:
(3) Authentication key
Your selection? 3
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
You need a passphrase to unlock the secret key for
user: "NIIBE Yutaka <gniibe@fsij.org>"
2048-bit RSA key, ID 5BB065DC, created 2010-10-22
<PASSWORD-KEY-4CA7BABE>
gpg: writing new key
Please enter your passphrase, so that the secret key can be unlocked for this session
<PASSWORD-KEY-ON-PC>
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
card-no: F517 00000001
(1) NIIBE Yutaka <gniibe@fsij.org>
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
ssb* ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
The sub key is now on the Token and GnuPG says its card-no for it.
The sub key is now on the Token.
Lastly, I save changes of **keys on PC** and quit GnuPG. ::

View File

@@ -22,41 +22,40 @@ Besides, some people sometimes prefer the word "passphrase" to
same thing and it just refer user-password or admin-password.
Set up PW1, PW3 and reset code
==============================
Set up PW1 and PW3
==================
Invoke GnuPG with the option ``--card-edit``. ::
$ gpg --card-edit
Application ID ...: D276000124010200F517000000010000
Reader ...........: 234B:0000:FSIJ-1.2.0-87193059:0
Application ID ...: D276000124010200FFFE871930590000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Manufacturer .....: unmanaged S/N range
Serial number ....: 87193059
Name of cardholder: Yutaka Niibe
Language prefs ...: ja
Sex ..............: male
URL of public key : http://www.gniibe.org/gniibe.asc
URL of public key : http://www.gniibe.org/gniibe-20150813.asc
Login data .......: gniibe
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
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
Signature key ....: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
created ....: 2015-08-12 07:10:48
Encryption key....: E228 AB42 0F73 3B1D 712D E50C 850A F040 D619 F240
created ....: 2015-08-12 07:10:48
Authentication key: E63F 31E6 F203 20B5 D796 D266 5F91 0521 FAA8 05B1
created ....: 2015-08-12 07:16:14
General key info..: pub ed25519/E267B052364F028D 2015-08-12 NIIBE Yutaka <gniibe@fsij.org>
sec> ed25519/E267B052364F028D created: 2015-08-12 expires: never
card-no: FFFE 87193059
ssb> cv25519/850AF040D619F240 created: 2015-08-12 expires: never
card-no: FFFE 87193059
ssb> ed25519/5F910521FAA805B1 created: 2015-08-12 expires: never
card-no: FFFE 87193059
gpg/card>
It shows the status of the card (as same as the output of ``gpg --card-status``).
@@ -71,7 +70,7 @@ Note that *the length of PIN should be more than (or equals to) 8* for
"admin less mode". ::
gpg/card> passwd
gpg: OpenPGP card no. D276000124010200F517000000010000 detected
gpg: OpenPGP card no. D276000124010200FFFE871930590000 detected
Please enter the PIN
Enter PIN: 123456
@@ -94,15 +93,24 @@ 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, 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. ::
Set up of reset code (optional)
===============================
Lastly, we can setup reset code, entering admin mode.
Having reset code, we can unblock the token when the token will be blocked
(by wrong attempts to entering passphrase). Note that this is optional step.
When reset code is known to someone, that person can try to guess your passphrase of PW1 more times by unblocking the token. So, I don't use this feature by myself.
If we do, here is the interaction. ::
gpg/card> admin
Admin commands are allowed
gpg/card> passwd
gpg: OpenPGP card no. D276000124010200F517000000010000 detected
gpg: OpenPGP card no. D276000124010200FFFE871930590000 detected
1 - change PIN
2 - unblock PIN
@@ -135,4 +143,4 @@ Then, I quit. ::
gpg/card> quit
That's all.
That's all in this step.

View File

@@ -9,17 +9,19 @@ Personalize your Gnuk Token
Invoke GnuPG with the option ``--card-edit``. ::
$ gpg --card-edit
Application ID ...: D276000124010200FFFE330069060000
Reader ...........: 234B:0000:FSIJ-1.2.0-87193059:0
Application ID ...: D276000124010200FFFE871930590000
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 33006906
Serial number ....: 87193059
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
@@ -58,7 +60,7 @@ login, and URL. URL specifies the place where I put my public keys. ::
Sex ((M)ale, (F)emale or space): m
gpg/card> url
URL to retrieve public key: http://www.gniibe.org/gniibe.asc
URL to retrieve public key: http://www.gniibe.org/gniibe-20150813.asc
gpg/card> login
Login data (account name): gniibe
@@ -72,4 +74,4 @@ Then, I quit. ::
gpg/card> quit
That's all.
That's all in this step.

View File

@@ -27,19 +27,15 @@ Make sure there is no ``scdaemon`` for configuring Gnuk Token. You can kill ``
Serial Number (optional)
========================
Note that this is completely optional step. I don't know anyone other than me, do this. Even for me, I only do that for a single device among multiple devices I use. I do that to test the feature.
In the file ``GNUK_SERIAL_NUMBER``, each line has email and 6-byte serial number. The first two bytes are organization number (F5:17 is for FSIJ). Last four bytes are number for tokens.
The tool ``../tool/gnuk_put_binary_libusb.py`` examines environment variable of ``EMAIL``, and writes corresponding serial number to Gnuk Token. ::
$ ../tool/gnuk_put_binary_libusb.py -s ../GNUK_SERIAL_NUMBER
Writing serial number
Device: 006
Device:
Configuration: 1
Interface: 0
d2 76 00 01 24 01 02 00 f5 17 00 00 00 01 00 00
The example above is the case of libusb version.
Use the tool ``../tool/gnuk_put_binary.py`` instead , for PC/SC Lite.
You need PyScard for this.

View File

@@ -12,35 +12,38 @@ Here is my GnuPG settings.
I create ``.gnupg/gpg.conf`` file with the following content. ::
use-agent
personal-digest-preferences SHA256
cert-digest-algo SHA256
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
default-key 0xE267B052364F028D
default-key 0x4ca7babe
In addition to the ``use-agent`` option, set preferences on algorithms, and specify my default key.
In addition to the ``use-agent`` option, I specify my default key.
The ``use-agent`` option is for GnuPG 1.4.x and it means using gpg-agent if available.
If no option, GnuPG 1.4.x directly connects to Gnuk Token by itself, instead of through scdaemon. When GnuPG 1.4.x tries to access Gnuk Token and scdaemon is running, there are conflicts.
We recommend to specify the ``use-agent`` option for GnuPG 1.4.x to access Gnuk Token through gpg-agent and scdaemon.
For GnuPG 2.0.x, gpg-agent is always used, so there is no need to specify the ``use-agent`` option, but having this option is no harm, anyway.
For GnuPG 2.0 and 2.1, gpg-agent is always used, so, there is no need to specify the ``use-agent`` option, but having this option is no harm, anyway.
Let gpg-agent manage SSH key
============================
I deactivate seahose-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
I edit the file /etc/X11/Xsession.options and comment out use-ssh-agent line.
Then, I create ``.gnupg/gpg-agent.conf`` file with the following content. ::
I create ``.gnupg/gpg-agent.conf`` file with the following content. ::
enable-ssh-support
I edit the file /etc/X11/Xsession.options and comment out use-ssh-agent line,
so that Xsession doesn't invoke original ssh-agent. We use gpg-agent as ssh-agent.
In the files /etc/xdg/autostart/gnome-keyring-ssh.desktop,
I have a line something like: ::
OnlyShowIn=GNOME;Unity;MATE;
I edit this line to: ::
OnlyShowIn=
So that no desktop environment enables gnome-keyring for ssh.
References
==========

View File

@@ -2,8 +2,8 @@
sphinx-quickstart on Wed Jul 4 15:29:05 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Copyright (C) 2012, 2013 NIIBE Yutaka
Copyright (C) 2012, 2013 Free Software Initiative of Japan
Copyright (C) 2012, 2013, 2016 NIIBE Yutaka
Copyright (C) 2012, 2013, 2016 Free Software Initiative of Japan
This document is licensed under a CC-BY-SA 3.0 Unported License
Gnuk Documentation
@@ -20,12 +20,11 @@ Contents:
udev-rules.rst
gnuk-token-initial-configuration.rst
gnuk-personalization.rst
generating-2048-RSA-key.rst
generating-key.rst
gnuk-keytocard.rst
gnuk-keytocard-noremoval.rst
gnuk-passphrase-setting.rst
using-gnuk-token-with-another-computer.rst
gnome3-gpg-settings.rst
development.rst

View File

@@ -9,6 +9,8 @@ Gnuk is an implementation of USB cryptographic token for GNU Privacy
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
STM32F103 processor.
This document explains about Gnuk 1.2, which comes with ECC algorithm.
Cryptographic token and feature of Gnuk
---------------------------------------
@@ -31,15 +33,15 @@ Target boards for running Gnuk
------------------------------
Hardware requirement for Gnuk is the micro controller STM32F103.
In version 1.1.x, Gnuk supports following boards.
In version 1.2, Gnuk supports following boards.
* FST-01 (Flying Stone Tiny ZERO-ONE)
* Olimex STM32-H103
* STM32 part of STM8S Discovery Kit
* ST Nucleo F103
* STBee
* Nitrokey Start
Host prerequisites for using Gnuk Token
@@ -49,11 +51,9 @@ Host prerequisites for using Gnuk Token
* libusb
* [Optional] PC/SC lite (pcscd, libccid)
* [Optional] SSH: openssh
* [optional] Web: scute, firefox
* [experimental] Web: scute, firefox
Usages
@@ -62,4 +62,4 @@ Usages
* Sign with GnuPG
* Decrypt with GnuPG
* Use with OpenSSH through gpg-agent (as ssh-agent)
* Use with Firefox through Scute for X.509 client certificate authentication
* [experimental] Use with Firefox through Scute for X.509 client certificate authentication

View File

@@ -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

View File

@@ -48,9 +48,9 @@ I have three keys in my token.
With the script below, I extract public key of the keygrip
5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin::
$ ./get_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
$ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
Here is the script, get_public_key.py::
Here is the script, get_raw_public_key.py::
#! /usr/bin/python

131
doc/note/firmware-update-2 Normal file
View File

@@ -0,0 +1,131 @@
Please refer:
How can I reflash FST-01 with SWD port?:
http://www.gniibe.org/FST-01/q_and_a/swd-debugger.html
Installing newer version of Gnuk onto FST-01 with Gnuk 1.0.1
============================================================
Please note that the feature of firmware upgrade is somewhat
experimental. I haven't got any success reports yet, but it's only
used by me, so far. When you will get some failure during your
firmware installation, you will need SWD debugger. YOU HAVE BEEN
WARNED. It is best to try firmware upgrade after you get a SWD
debugger.
The firmare upgrade feature of Gnuk
------------------------------------
Gnuk supports firmware upgrade by reGNUal. It works in the following
steps.
1. User registers RSA public key to Gnuk Token for firmware upgrade
2. When User wants firmware upgrade, user sends
the GET_CHALLENGE command then the EXTERNAL_AUTHENTICATE command
to Gnuk Token from host PC to authenticate.
The EXTERNAL_AUTHENTICATE command message consists of
signature (of challenge) by corresponding RSA private key.
3. When Gnuk Token receives the EXTERNAL_AUTHENTICATE command message
and validates signature successfully, Gnuk finishes its normal
operation and goes to enter mode of loading special program onto RAM.
4. Host PC sends reflashing program (reGNUal) to Gnuk Token.
5. Gnuk clears up all content of flash ROM (but first 4KiB of system)
at the end of receiving special program and transfers its control
to reGNUal.
6. reGNUal on Gnuk Token receives new firmware image from host PC and writes
to each page.
7. Done.
Host PC setting for Gnuk
------------------------
You need proper configuration for permission of Gnuk Token (udev
setting). It should have lines something like: ::
# Gnuk Token by FSIJ
SUBSYSTEMS=="usb", ACTION=="add", \
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
I have those lines in /etc/udev/rules.d/69-gnuk.rules.
Building another version (newer) of Gnuk
----------------------------------------
Please see README of Gnuk for detail, but it's like configure
and make: ::
$ pwd
/home/user/src/gnuk
$ cd src
$ ./configure --vidpid=234b:0000
$ make
Please take care of configure options. The default target in 1.0.x
series is Olimex STM32 H103 (not FST-01). The default target in 1.1.8
is FST-01.
Then you get build/gnuk.elf and build/gnuk.bin.
Invoking configure with FSIJ's USB ID (234b:0000) means that you are
using FSIJ's USB ID (for reGNUal in this case). Please note that FSIJ
only allows use of its USB ID for specific situations. Please read
README of Gnuk about that.
Bulding reGNUal
---------------
You need to compile reGNUal. ::
$ cd ../regnual
$ make
Then, you should have regnual.bin. Note that 'configure' of Gnuk
itself is needed before compiling reGNUal.
upgrade_by_passwd.py
--------------------
In the source code distribution of 1.0.4 (or current development
version) of Gnuk, there is a tool named 'upgrade_by_passwd.py'.
This is an easy tool to hide lengthy steps from user and to allow user
firmware upgrade only by password of Gnuk Token.
Before running the script, you need to kill scdaemon: ::
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
The command line invokation above assumes that you properly configure
your environment for Gnuk Token.
How to run the script: ::
$ cd tool
$ ./upgrade_by_passwd.py ../regnual/regnual.bin ../src/build/gnuk.bin
Then, the script on your host PC invoke the steps described above, and
you will get new version of Gnuk installed.
You can also specify -p option to enter your password (other than
factory setting).
If you already have configured another upgrade key installed, you can
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0
to 3.
--

View File

@@ -28,10 +28,16 @@ To stop SCDAEMON and let it exit, type::
Then, you can confirm that there is no SCDAEMON any more by ``ps``
command.
Or, you can use ``gpgconf`` command. Type::
$ gpgconf --reload scdameon
will do the samething.
Let GPG-AGENT/SCDAEMON learn
============================
To let gpg-agent/scdaemon learn from Gnuk Token, type::
To let gpg-agent/scdaemon "learn" from Gnuk Token, type::
$ gpg-connect-agent learn /bye

View File

@@ -10,10 +10,13 @@ PC/SC Lite, as it has its own device configuration.
udev rules for Gnuk Token
=========================
In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules,
when you install "gnupg" package. This is the place we need to
change, if your installation is older (than jessie). Newer "gnupg"
package (1.4.15-1 or later) has already supported Gnuk Token.
In case of Debian, there is a file /lib/udev/rules.d/60-gnupg.rules
(or /lib/udev/rules.d/60-scdamon.rules for newer version),
when you install "gnupg" package (or "scdaemon" package).
This is the place we need to
change, if your installation is older than jessie. Newer "gnupg"
package (1.4.15-1 or later) or "scdaemon" package has already
supported Gnuk Token.
If needed, please add lines for Gnuk Token to give a desktop user the
permission to use the device. We specify USB ID of Gnuk Token (by
@@ -30,7 +33,7 @@ FSIJ)::
+
LABEL="gnupg_rules_end"
When we install "gnupg2" package only (with no "gnupg" package),
When we only install "gnupg2" package for 2.0 (with no "gnupg" package),
there will be no udev rules (there is a bug report #543217 for this issue).
In this case, we need something like this in /etc/udev/rules.d/60-gnuk.rules::

View File

@@ -12,90 +12,90 @@ while ``.gnupg`` directory contains keyrings and trustdb, too.
Fetch the public key and connect it to the Token
================================================
Using the Token, we need to put the public key and the secret
key reference (to the token) in ``.gnupg``.
In order to use the Token, we need to put the public key and the secret
key references (to the token) under ``.gnupg`` directory.
To do that, invoke GnuPG with ``--card-edit`` option. ::
$ gpg --card-edit
Application ID ...: D276000124010200F517000000010000
Reader ...........: 234B:0000:FSIJ-1.2.0-87193059:0
Application ID ...: D276000124010200FFFE871930590000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Manufacturer .....: unmanaged S/N range
Serial number ....: 87193059
Name of cardholder: Yutaka Niibe
Language prefs ...: ja
Sex ..............: male
URL of public key : http://www.gniibe.org/gniibe.asc
URL of public key : http://www.gniibe.org/gniibe-20150813.asc
Login data .......: gniibe
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 6
Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
created ....: 2010-10-15 06:46:33
Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF
created ....: 2010-10-15 06:46:33
Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC
created ....: 2010-10-22 06:06:36
Signature counter : 0
Signature key ....: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
created ....: 2015-08-12 07:10:48
Encryption key....: E228 AB42 0F73 3B1D 712D E50C 850A F040 D619 F240
created ....: 2015-08-12 07:10:48
Authentication key: E63F 31E6 F203 20B5 D796 D266 5F91 0521 FAA8 05B1
created ....: 2015-08-12 07:16:14
General key info..: [none]
gpg/card>
It says, there is no key info related to this token on your PC (``[none]``).
Here, the secret key references (to the token) are created under ``.gnupg/private-keys-v1.d`` directory. It can be also created when I do ``--card-status`` by GnuPG.
Fetch the public key from URL specified in the Token. ::
Still, it says that there is no key info related to this token on my PC (``[none]`` for General key info), because I don't have the public key on this PC yet.
So, I fetch the public key from URL specified in the Token. ::
gpg/card> fetch
gpg: requesting key 4CA7BABE from http server www.gniibe.org
gpg: key 4CA7BABE: public key "NIIBE Yutaka <gniibe@fsij.org>" imported
gpg: no ultimately trusted keys found
gpg: requesting key E267B052364F028D from http server www.gniibe.org
gpg: key E267B052364F028D: public key "NIIBE Yutaka <gniibe@fsij.org>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg: imported: 1
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 6 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 6u
gpg/card>
Good. The public key is now in ``.gnupg``. We can examine by ``gpg --list-keys``.
Good. The public key is now under ``.gnupg`` directory. We can examine by ``gpg --list-keys``.
However, the secret key reference (to the token) is not in ``.gnupg`` yet.
When I type return at the ``gpg/card>`` prompt, now, I can see: ::
It will be generated when I do ``--card-status`` by GnuPG with
correspoinding public key in ``.gnupg``, or just type return
at the ``gpg/card>`` prompt. ::
gpg/card>
Application ID ...: D276000124010200F517000000010000
Reader ...........: 234B:0000:FSIJ-1.2.0-87193059:0
Application ID ...: D276000124010200FFFE871930590000
Version ..........: 2.0
Manufacturer .....: FSIJ
Serial number ....: 00000001
Manufacturer .....: unmanaged S/N range
Serial number ....: 87193059
Name of cardholder: Yutaka Niibe
Language prefs ...: ja
Sex ..............: male
URL of public key : http://www.gniibe.org/gniibe.asc
URL of public key : http://www.gniibe.org/gniibe-20150813.asc
Login data .......: gniibe
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 6
Signature key ....: 1241 24BD 3B48 62AF 7A0A 42F1 00B4 5EBD 4CA7 BABE
created ....: 2010-10-15 06:46:33
Encryption key....: 42E1 E805 4E6F 1F30 26F2 DC79 79A7 9093 0842 39CF
created ....: 2010-10-15 06:46:33
Authentication key: B4D9 7142 C42D 6802 F5F7 4E70 9C33 B6BA 5BB0 65DC
created ....: 2010-10-22 06:06:36
General key info..:
pub 2048R/4CA7BABE 2010-10-15 NIIBE Yutaka <gniibe@fsij.org>
sec> 2048R/4CA7BABE created: 2010-10-15 expires: never
card-no: F517 00000001
ssb> 2048R/084239CF created: 2010-10-15 expires: never
card-no: F517 00000001
ssb> 2048R/5BB065DC created: 2010-10-22 expires: never
card-no: F517 00000001
Signature counter : 0
Signature key ....: 249C B377 1750 745D 5CDD 323C E267 B052 364F 028D
created ....: 2015-08-12 07:10:48
Encryption key....: E228 AB42 0F73 3B1D 712D E50C 850A F040 D619 F240
created ....: 2015-08-12 07:10:48
Authentication key: E63F 31E6 F203 20B5 D796 D266 5F91 0521 FAA8 05B1
created ....: 2015-08-12 07:16:14
General key info..: pub ed25519/E267B052364F028D 2015-08-12 NIIBE Yutaka <gniibe@fsij.org>
sec> ed25519/E267B052364F028D created: 2015-08-12 expires: never
card-no: FFFE 87193059
ssb> cv25519/850AF040D619F240 created: 2015-08-12 expires: never
card-no: FFFE 87193059
ssb> ed25519/5F910521FAA805B1 created: 2015-08-12 expires: never
card-no: FFFE 87193059
gpg/card>
Note that, it displays the information about "General key info".
OK, now I can use the Token on this computer.
@@ -103,33 +103,43 @@ Update trustdb for the key on Gnuk Token
========================================
Yes, I can use the Token by the public key and the secret
key reference to the card. More, I need to update the trustdb.
key references to the card. More, I need to update the trustdb.
To do that I do: ::
To do that, I do: ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
$ ./gpg --edit-key E267B052364F028D
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: unknown validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
card-no: FFFE 87193059
trust: unknown validity: unknown
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
card-no: FFFE 87193059
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
card-no: FFFE 87193059
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
gpg>
See, the key is ``unknown`` state. Add trust for that. ::
See, the key is ``unknown`` state. Add trust for that, because it's the key under my control. ::
gpg> trust
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: unknown validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
card-no: FFFE 87193059
trust: unknown validity: unknown
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
card-no: FFFE 87193059
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
card-no: FFFE 87193059
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
@@ -146,32 +156,49 @@ See, the key is ``unknown`` state. Add trust for that. ::
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: unknown
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
card-no: FFFE 87193059
trust: ultimate validity: unknown
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
card-no: FFFE 87193059
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
card-no: FFFE 87193059
[ unknown] (1). NIIBE Yutaka <gniibe@fsij.org>
[ unknown] (2) NIIBE Yutaka <gniibe@debian.org>
Please note that the shown key validity is not necessarily correct
unless you restart the program.
$
gpg>
Next time I invoke GnuPG, it will be ``ultimate`` key. Let's see: ::
And I quit from gpg. Then, when I invoke GnuPG, it will be ``ultimate`` key. Let's see: ::
$ gpg --edit-key 4ca7babe
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
$ ./gpg --edit-key E267B052364F028D
gpg (GnuPG) 2.1.13; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 7 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 7u
sec ed25519/E267B052364F028D
created: 2015-08-12 expires: never usage: SC
card-no: FFFE 87193059
trust: ultimate validity: ultimate
ssb cv25519/850AF040D619F240
created: 2015-08-12 expires: never usage: E
card-no: FFFE 87193059
ssb ed25519/5F910521FAA805B1
created: 2015-08-12 expires: never usage: A
card-no: FFFE 87193059
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
[ultimate] (2) NIIBE Yutaka <gniibe@debian.org>
gpg> quit
$
$
OK, all set. I'm ready to use my Gnuk Token on this PC.

BIN
gnuk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

220
misc/debug-bn.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* debug-bn.c - Debug Bignum
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "bn.h"
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 ("");
}
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];
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;
}

398
misc/t-eddsa.c Normal file
View 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;
}

92
misc/t-mont.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* 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 -DBN256_C_IMPLEMENTATION ecc-mont.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 t-mont.c
gcc -Wall -c debug-bn.c
gcc -o t-mont t-mont.o ecc-mont.o bn.o mod.o mod25638.o debug-bn.o
*
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "bn.h"
const uint8_t k[32] = {
0x30, 0x01, 0x33, 0xE7, 0xDC, 0x52, 0xAD, 0x9F,
0x89, 0xFE, 0xC0, 0x59, 0x4A, 0x6D, 0x65, 0xE5,
0xF8, 0x7A, 0xD6, 0xA9, 0xA4, 0x89, 0x00, 0xB1,
0x93, 0x7E, 0xD3, 0x6F, 0x09, 0x1E, 0xB7, 0x76,
};
int
main (int argc, char *argv[])
{
int all_good = 1;
int r;
bn256 *pk;
bn256 a[1];
uint8_t out[32];
extern void ecdh_decrypt_curve25519 (const uint8_t *input,
uint8_t *output,
const bn256 *k);
extern uint8_t *ecdh_compute_public_25519 (const uint8_t*k);
extern void print_le_bn256 (const bn256 *X);
while (1)
{
#if 0
hash[0] &= 248;
hash[31] &= 127;
hash[31] |= 64;
memcpy (a, hash, sizeof (bn256)); /* Lower half of hash */
#endif
pk = ecdh_compute_public_25519 (k);
print_le_bn256 (pk);
return 0;
#if 0
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;
}
ecdh_decrypt_25519 (msg, out, a);
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);
#endif
}
return all_good == 1?0:1;
}

View File

@@ -209,9 +209,7 @@
*
* Enable the RSA prime-number generation code.
*/
#ifdef KEYGEN_SUPPORT
#define POLARSSL_GENPRIME
#endif
/**
* \def POLARSSL_FS_IO

View File

@@ -179,15 +179,15 @@ static const unsigned char FSb[256] =
V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
#define V(a,b,c,d) 0x##a##b##c##d
const uint32_t FT0[256] __attribute__((section(".sys.0"))) = { FT };
const uint32_t FT0[256] __attribute__((weak,section(".sys.0"))) = { FT };
#undef V
#define V(a,b,c,d) 0x##b##c##d##a
const uint32_t FT1[256] __attribute__((section(".sys.1"))) = { FT };
const uint32_t FT1[256] __attribute__((weak,section(".sys.1"))) = { FT };
#undef V
#define V(a,b,c,d) 0x##c##d##a##b
const uint32_t FT2[256] __attribute__((section(".sys.2"))) = { FT };
const uint32_t FT2[256] __attribute__((weak,section(".sys.2"))) = { FT };
#undef V
#define V(a,b,c,d) 0x##d##a##b##c

View File

@@ -223,6 +223,24 @@ size_t mpi_lsb( const mpi *X )
return( 0 );
}
/*
* Count leading zero bits in a given integer
*/
static size_t int_clz( const t_uint x )
{
size_t j;
t_uint mask = (t_uint) 1 << (biL - 1);
for( j = 0; j < biL; j++ )
{
if( x & mask ) break;
mask >>= 1;
}
return j;
}
/*
* Return the number of most significant bits
*/
@@ -1102,6 +1120,100 @@ int mpi_mul_int( mpi *X, const mpi *A, t_sint b )
return( mpi_mul_mpi( X, A, &_B ) );
}
/*
* Unsigned integer divide - 64bit dividend and 32bit divisor
*/
static t_uint int_div_int(t_uint u1, t_uint u0, t_uint d, t_uint *r)
{
#if defined(POLARSSL_HAVE_UDBL)
t_udbl dividend, quotient;
#else
const t_uint radix = (t_uint) 1 << biH;
const t_uint uint_halfword_mask = ( (t_uint) 1 << biH ) - 1;
t_uint d0, d1, q0, q1, rAX, r0, quotient;
t_uint u0_msw, u0_lsw;
size_t s;
#endif
/*
* Check for overflow
*/
if(( 0 == d ) || ( u1 >= d ))
{
if (r != NULL) *r = (~0);
return (~0);
}
#if defined(POLARSSL_HAVE_UDBL)
dividend = (t_udbl) u1 << biL;
dividend |= (t_udbl) u0;
quotient = dividend / d;
if( quotient > ( (t_udbl) 1 << biL ) - 1 )
quotient = ( (t_udbl) 1 << biL ) - 1;
if( r != NULL )
*r = (t_uint)( dividend - (quotient * d ) );
return (t_uint) quotient;
#else
/*
* Algorithm D, Section 4.3.1 - The Art of Computer Programming
* Vol. 2 - Seminumerical Algorithms, Knuth
*/
/*
* Normalize the divisor, d, and dividend, u0, u1
*/
s = int_clz( d );
d = d << s;
u1 = u1 << s;
u1 |= ( u0 >> ( biL - s ) ) & ( -(t_sint)s >> ( biL - 1 ) );
u0 = u0 << s;
d1 = d >> biH;
d0 = d & uint_halfword_mask;
u0_msw = u0 >> biH;
u0_lsw = u0 & uint_halfword_mask;
/*
* Find the first quotient and remainder
*/
q1 = u1 / d1;
r0 = u1 - d1 * q1;
while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
{
q1 -= 1;
r0 += d1;
if ( r0 >= radix ) break;
}
rAX = (u1 * radix) + (u0_msw - q1 * d);
q0 = rAX / d1;
r0 = rAX - q0 * d1;
while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
{
q0 -= 1;
r0 += d1;
if ( r0 >= radix ) break;
}
if (r != NULL)
*r = (rAX * radix + u0_lsw - q0 * d) >> s;
quotient = q1 * radix + q0;
return quotient;
#endif
}
/*
* Division by mpi: A = Q * B + R (HAC 14.20)
*/
@@ -1159,57 +1271,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Z.p[i - t - 1] = ~0;
else
{
#if defined(POLARSSL_HAVE_UDBL)
t_udbl r;
r = (t_udbl) X.p[i] << biL;
r |= (t_udbl) X.p[i - 1];
r /= Y.p[t];
if( r > ((t_udbl) 1 << biL) - 1)
r = ((t_udbl) 1 << biL) - 1;
Z.p[i - t - 1] = (t_uint) r;
#else
/*
* __udiv_qrnnd_c, from gmp/longlong.h
*/
t_uint q0, q1, r0, r1;
t_uint d0, d1, d, m;
d = Y.p[t];
d0 = ( d << biH ) >> biH;
d1 = ( d >> biH );
q1 = X.p[i] / d1;
r1 = X.p[i] - d1 * q1;
r1 <<= biH;
r1 |= ( X.p[i - 1] >> biH );
m = q1 * d0;
if( r1 < m )
{
q1--, r1 += d;
while( r1 >= d && r1 < m )
q1--, r1 += d;
}
r1 -= m;
q0 = r1 / d1;
r0 = r1 - d1 * q0;
r0 <<= biH;
r0 |= ( X.p[i - 1] << biH ) >> biH;
m = q0 * d0;
if( r0 < m )
{
q0--, r0 += d;
while( r0 >= d && r0 < m )
q0--, r0 += d;
}
r0 -= m;
Z.p[i - t - 1] = ( q1 << biH ) | q0;
#endif
Z.p[i - t - 1] = int_div_int( X.p[i], X.p[i-1], Y.p[t], NULL);
}
Z.p[i - t - 1]++;
@@ -1545,7 +1607,8 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
{
int ret;
size_t i = mpi_msb( E );
size_t wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
size_t wbits, one = 1;
size_t nblimbs;
@@ -1583,6 +1646,7 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
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 ) );
MPI_CHK( mpi_grow( &RR, N->n ) );
if( _RR != NULL )
memcpy( _RR, &RR, sizeof( mpi ) );

View File

@@ -671,14 +671,14 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
size_t ilen, pad_count = 0;
unsigned char *p, *q;
unsigned char bt;
unsigned char buf[POLARSSL_MPI_MAX_SIZE];
unsigned char buf[ctx->len];
if( ctx->padding != RSA_PKCS_V15 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
if( ilen < 16 || ilen > sizeof( buf ) )
if( ilen < 16)
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == RSA_PUBLIC )

View File

@@ -2,7 +2,7 @@
PROJECT = regnual
OBJS = regnual.o usb_stm32f103.o sys.o
OBJS = regnual.o usb-stm32f103.o reset.o
LDSCRIPT= regnual.ld
###################################
@@ -23,7 +23,7 @@ DEFS = -DFREE_STANDING
CFLAGS = -O2 -g
CFLAGS += -Wa,-alms=$(notdir $(<:.c=.lst)) -fpie
CFLAGS += $(CWARN) -I . -I ../src -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
CFLAGS += $(CWARN) -I . -I ../chopstx -fno-common $(MCFLAGS) $(TOPT) $(DEFS)
LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
@@ -32,19 +32,19 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
all: regnual.hex
regnual.o: regnual.c ../src/sys.h
regnual.o: regnual.c ../chopstx/sys.h ../chopstx/usb_lld.h
regnual.hex: regnual.elf
$(OBJCOPY) -Obinary regnual.elf regnual.bin
$(OBJCOPY) -Oihex regnual.elf regnual.hex
usb_stm32f103.o: ../src/usb_stm32f103.c
$(CC) $(CFLAGS) -c -o usb_stm32f103.o ../src/usb_stm32f103.c
usb-stm32f103.o: ../chopstx/mcu/usb-stm32f103.c
$(CC) $(CFLAGS) -c -o usb-stm32f103.o ../chopstx/mcu/usb-stm32f103.c
regnual.elf: $(OBJS) $(LDSCRIPT)
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
clean:
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin *.lst
distclean: clean

View File

@@ -1,7 +1,8 @@
/*
* regnual.c -- Firmware installation for STM32F103 Flash ROM
*
* Copyright (C) 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2012, 2013, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -32,19 +33,25 @@
extern void *memset (void *s, int c, size_t n);
extern void set_led (int);
extern uint8_t _flash_start, _flash_end;
extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
extern int flash_protect (void);
extern void nvic_system_reset (void);
#define FLASH_START_ADDR 0x08000000 /* Fixed for all STM32F1. */
#define FLASH_OFFSET 0x1000 /* First pages are not-writable. */
#define FLASH_START (FLASH_START_ADDR+FLASH_OFFSET)
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
static uint32_t flash_end;
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
/* USB Standard Device Descriptor */
static const uint8_t regnual_device_desc[] = {
18, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
DEVICE_DESCRIPTOR, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */
0xFF, /* bDeviceClass: VENDOR */
0x00, /* bDeviceSubClass */
@@ -57,24 +64,26 @@ static const uint8_t regnual_device_desc[] = {
0x01 /* bNumConfigurations */
};
#if defined(USB_SELF_POWERED)
#define REGNUAL_FEATURE_INIT 0xC0 /* self powered */
#else
#define REGNUAL_FEATURE_INIT 0x80 /* bus powered */
#endif
static const uint8_t regnual_config_desc[] = {
9,
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
18, 0, /* wTotalLength: no of returned bytes */
1, /* bNumInterfaces: single vender interface */
CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
18, 0, /* wTotalLength: no of returned bytes */
1, /* bNumInterfaces: single vendor interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: None */
#if defined(USB_SELF_POWERED)
0xC0, /* bmAttributes: self powered */
#else
0x80, /* bmAttributes: bus powered */
#endif
50, /* MaxPower 100 mA */
REGNUAL_FEATURE_INIT, /* bmAttributes: bus powered */
50, /* MaxPower 100 mA */
/* Interface Descriptor */
9,
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0, /* bInterfaceNumber: Index of this interface */
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
0, /* bInterfaceNumber: Index of this interface */
0, /* Alternate setting for this interface */
0, /* bNumEndpoints: None */
0xFF,
@@ -85,7 +94,7 @@ static const uint8_t regnual_config_desc[] = {
static const uint8_t regnual_string_lang_id[] = {
4, /* bLength */
USB_STRING_DESCRIPTOR_TYPE,
STRING_DESCRIPTOR,
0x09, 0x04 /* LangID = 0x0409: US-English */
};
@@ -93,23 +102,17 @@ static const uint8_t regnual_string_lang_id[] = {
static const uint8_t regnual_string_serial[] = {
8*2+2,
USB_STRING_DESCRIPTOR_TYPE,
STRING_DESCRIPTOR,
/* FSIJ-0.0 */
'F', 0, 'S', 0, 'I', 0, 'J', 0, '-', 0,
'0', 0, '.', 0, '0', 0,
};
void
usb_cb_device_reset (void)
static void
usb_device_reset (struct usb_dev *dev)
{
/* Set DEVICE as not configured */
usb_lld_set_configuration (0);
/* Current Feature initialization */
usb_lld_set_feature (regnual_config_desc[7]);
usb_lld_reset ();
usb_lld_reset (dev, REGNUAL_FEATURE_INIT);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
@@ -166,108 +169,101 @@ static uint32_t calc_crc32 (void)
}
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
uint16_t index, uint16_t len)
static void
usb_ctrl_write_finish (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
&& USB_SETUP_SET (arg->type))
{
if (req_no == USB_REGNUAL_SEND && value == 0)
if (arg->request == USB_REGNUAL_SEND && arg->value == 0)
result = calc_crc32 ();
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
else if (arg->request == USB_REGNUAL_FLASH)
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
result = flash_write (dst_addr, (const uint8_t *)mem, 256);
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
else if (arg->request == USB_REGNUAL_PROTECT && arg->value == 0)
result = flash_protect ();
else if (req_no == USB_REGNUAL_FINISH && len == 0
&& value == 0 && index == 0)
else if (arg->request == USB_REGNUAL_FINISH && arg->value == 0)
nvic_system_reset ();
}
}
int
usb_cb_setup (uint8_t req, uint8_t req_no,
uint16_t value, uint16_t index, uint16_t len)
static int
usb_setup (struct usb_dev *dev)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
struct device_req *arg = &dev->dev_req;
uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT))
{
if (USB_SETUP_GET (req))
if (USB_SETUP_GET (arg->type))
{
if (req_no == USB_REGNUAL_MEMINFO)
if (arg->request == USB_REGNUAL_MEMINFO)
{
static const uint8_t *mem_info[2];
const uint8_t *mem_info[2];
mem_info[0] = &_flash_start;
mem_info[1] = &_flash_end;
usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
return USB_SUCCESS;
}
else if (req_no == USB_REGNUAL_RESULT)
{
usb_lld_set_data_to_send (&result, sizeof (uint32_t));
return USB_SUCCESS;
mem_info[0] = (const uint8_t *)FLASH_START;
mem_info[1] = (const uint8_t *)flash_end;
return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
}
else if (arg->request == USB_REGNUAL_RESULT)
return usb_lld_ctrl_send (dev, &result, sizeof (uint32_t));
}
else /* SETUP_SET */
{
if (req_no == USB_REGNUAL_SEND)
if (arg->request == USB_REGNUAL_SEND)
{
if (value != 0 || index + len > 256)
return USB_UNSUPPORT;
if (arg->value != 0 || arg->index + arg->len > 256)
return -1;
if (index + len < 256)
memset ((uint8_t *)mem + index + len, 0xff,
256 - (index + len));
if (arg->index + arg->len < 256)
memset ((uint8_t *)mem + arg->index + arg->len, 0xff,
256 - (arg->index + arg->len));
usb_lld_set_data_to_recv (mem + index, len);
return USB_SUCCESS;
return usb_lld_ctrl_recv (dev, mem + arg->index, arg->len);
}
else if (req_no == USB_REGNUAL_FLASH && len == 0 && index == 0)
else if (arg->request == USB_REGNUAL_FLASH && arg->len == 0
&& arg->index == 0)
{
uint32_t dst_addr = (0x08000000 + value * 0x100);
uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
if (dst_addr + 256 <= (uint32_t)&_flash_end)
return USB_SUCCESS;
if (dst_addr + 256 <= flash_end)
return usb_lld_ctrl_ack (dev);
}
else if (req_no == USB_REGNUAL_PROTECT && len == 0
&& value == 0 && index == 0)
return USB_SUCCESS;
else if (req_no == USB_REGNUAL_FINISH && len == 0
&& value == 0 && index == 0)
return USB_SUCCESS;
else if (arg->request == USB_REGNUAL_PROTECT && arg->len == 0
&& arg->value == 0 && arg->index == 0)
return usb_lld_ctrl_ack (dev);
else if (arg->request == USB_REGNUAL_FINISH && arg->len == 0
&& arg->value == 0 && arg->index == 0)
return usb_lld_ctrl_ack (dev);
}
}
return USB_UNSUPPORT;
return -1;
}
int
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
uint16_t index)
static int
usb_get_descriptor (struct usb_dev *dev)
{
(void)index;
struct device_req *arg = &dev->dev_req;
uint8_t rcp = arg->type & RECIPIENT;
uint8_t desc_type = (arg->value >> 8);
uint8_t desc_index = (arg->value & 0xff);
if (rcp != DEVICE_RECIPIENT)
return USB_UNSUPPORT;
return -1;
if (desc_type == DEVICE_DESCRIPTOR)
{
usb_lld_set_data_to_send (regnual_device_desc,
sizeof (regnual_device_desc));
return USB_SUCCESS;
}
return usb_lld_ctrl_send (dev, regnual_device_desc,
sizeof (regnual_device_desc));
else if (desc_type == CONFIG_DESCRIPTOR)
{
usb_lld_set_data_to_send (regnual_config_desc,
sizeof (regnual_config_desc));
return USB_SUCCESS;
}
return usb_lld_ctrl_send (dev, regnual_config_desc,
sizeof (regnual_config_desc));
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -280,48 +276,50 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
size = sizeof (regnual_string_lang_id);
break;
case 1:
str = gnukStringVendor;
size = sizeof (gnukStringVendor);
str = gnuk_string_vendor;
size = sizeof (gnuk_string_vendor);
break;
case 2:
str = gnukStringProduct;
size = sizeof (gnukStringProduct);
str = gnuk_string_product;
size = sizeof (gnuk_string_product);
break;
case 3:
str = regnual_string_serial;
size = sizeof (regnual_string_serial);
break;
default:
return USB_UNSUPPORT;
return -1;
}
usb_lld_set_data_to_send (str, size);
return USB_SUCCESS;
return usb_lld_ctrl_send (dev, str, size);
}
return USB_UNSUPPORT;
return -1;
}
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
static int
usb_set_configuration (struct usb_dev *dev)
{
(void)value;
uint8_t current_conf;
switch (event_type)
current_conf = usb_lld_current_configuration (dev);
if (current_conf == 0)
{
case USB_EVENT_ADDRESS:
case USB_EVENT_CONFIG:
return USB_SUCCESS;
default:
break;
if (dev->dev_req.value != 1)
return -1;
usb_lld_set_configuration (dev, 1);
}
else if (current_conf != dev->dev_req.value)
{
if (dev->dev_req.value != 0)
return -1;
usb_lld_set_configuration (dev, 0);
}
return USB_UNSUPPORT;
}
int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
{
(void)cmd; (void)interface; (void)alt;
return USB_UNSUPPORT;
/* Do nothing when current_conf == value */
return usb_lld_ctrl_ack (dev);
}
@@ -335,6 +333,31 @@ static void wait (int count)
#define WAIT 2400000
/* NVIC: Nested Vectored Interrupt Controller. */
struct NVIC {
volatile uint32_t ISER[8];
uint32_t unused1[24];
volatile uint32_t ICER[8];
uint32_t unused2[24];
volatile uint32_t ISPR[8];
uint32_t unused3[24];
volatile uint32_t ICPR[8];
uint32_t unused4[24];
volatile uint32_t IABR[8];
uint32_t unused5[56];
volatile uint32_t IPR[60];
};
static struct NVIC *const NVIC = (struct NVIC *const)0xE000E100;
#define NVIC_ISER(n) (NVIC->ISER[n >> 5])
static void nvic_enable_intr (uint8_t irq_num)
{
NVIC_ISER (irq_num) = 1 << (irq_num & 0x1f);
}
#define USB_LP_CAN1_RX0_IRQn 20
static struct usb_dev dev;
int
main (int argc, char *argv[])
{
@@ -342,7 +365,15 @@ main (int argc, char *argv[])
set_led (0);
usb_lld_init (regnual_config_desc[7]);
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
/*
* NVIC interrupt priority was set by Gnuk.
* USB interrupt is disabled by NVIC setting.
* We enable the interrupt again by nvic_enable_intr.
*/
usb_lld_init (&dev, REGNUAL_FEATURE_INIT);
nvic_enable_intr (USB_LP_CAN1_RX0_IRQn);
while (1)
{
@@ -352,3 +383,69 @@ main (int argc, char *argv[])
wait (WAIT);
}
}
void
usb_interrupt_handler (void)
{
uint8_t ep_num;
int e;
e = usb_lld_event_handler (&dev);
ep_num = USB_EVENT_ENDP (e);
if (ep_num == 0)
switch (USB_EVENT_ID (e))
{
case USB_EVENT_DEVICE_RESET:
usb_device_reset (&dev);
break;
case USB_EVENT_DEVICE_ADDRESSED:
break;
case USB_EVENT_GET_DESCRIPTOR:
if (usb_get_descriptor (&dev) < 0)
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_SET_CONFIGURATION:
if (usb_set_configuration (&dev) < 0)
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_SET_INTERFACE:
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_CTRL_REQUEST:
/* Device specific device request. */
if (usb_setup (&dev) < 0)
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_GET_STATUS_INTERFACE:
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_GET_INTERFACE:
usb_lld_ctrl_error (&dev);
break;
case USB_EVENT_SET_FEATURE_DEVICE:
case USB_EVENT_SET_FEATURE_ENDPOINT:
case USB_EVENT_CLEAR_FEATURE_DEVICE:
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
usb_lld_ctrl_ack (&dev);
break;
case USB_EVENT_CTRL_WRITE_FINISH:
/* Control WRITE transfer finished. */
usb_ctrl_write_finish (&dev);
break;
case USB_EVENT_OK:
case USB_EVENT_DEVICE_SUSPEND:
default:
break;
}
}

View File

@@ -12,8 +12,6 @@ MEMORY
}
vector = 0x08000000;
_flash_start = 0x08001000;
_flash_end = 0x08020000;
__ram_start__ = ORIGIN(ram0);
__ram_size__ = 20k;

View File

@@ -8,12 +8,14 @@ CHOPSTX = ../chopstx
# Define linker script file here
LDSCRIPT= gnuk.ld
CSRC = main.c usb_stm32f103.c adc_stm32f103.c \
usb_desc.c usb_ctrl.c \
CSRC = main.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 \
random.c neug.c sha256.c sys.c
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
bn.c mod.c \
modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
mod25638.c ecc-edwards.c ecc-mont.c sha512.c \
random.c neug.c sha256.c
INCDIR =
@@ -43,6 +45,11 @@ ifeq ($(ENABLE_PINPAD),dnd)
CSRC += usb-msc.c
endif
CHIP=stm32f103
USE_SYS = yes
USE_USB = yes
USE_ADC = yes
###################################
CROSS = arm-none-eabi-
CC = $(CROSS)gcc
@@ -52,7 +59,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 = @USE_SYS3@
OPT = -O3 -Os -g
LIBS =
@@ -65,6 +72,8 @@ board.h:
sys.c: board.h
build/bignum.o: OPT = -O3 -g
distclean: clean
-rm -f gnuk.ld config.h board.h Makefile \
usb-strings.c.inc usb-vid-pid-ver.c.inc

View File

@@ -169,7 +169,7 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
pw_len = ks[0] & PW_LEN_MASK;
salt = KS_GET_SALT (ks);
salt_len = SALT_SIZE;
if ((pw_len_known >= 0 && pw_len_known != pw_len) || buf_len < pw_len)
return -1;

View File

@@ -1,16 +0,0 @@
extern chopstx_mutex_t adc_mtx;
extern chopstx_cond_t adc_cond;
extern int adc_waiting;
extern int adc_data_available;
void adc_init (void);
void adc_start (void);
void adc_stop (void);
#define ADC_SAMPLE_MODE 0
#define ADC_CRC32_MODE 1
extern uint32_t adc_buf[64];
void adc_start_conversion (int offset, int count);
int adc_wait_completion (chopstx_intr_t *intr);

View File

@@ -1,266 +0,0 @@
/*
* adc_stm32f103.c - ADC driver for STM32F103
* In this ADC driver, there are NeuG specific parts.
* You need to modify to use this as generic ADC driver.
*
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a True Random Number Generator
* implementation based on quantization error of ADC (for STM32F103).
*
* NeuG 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.
*
* NeuG is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <chopstx.h>
#include "neug.h"
#include "stm32f103.h"
#include "adc.h"
#define NEUG_CRC32_COUNTS 4
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define ADC_SMPR1_SMP_VREF(n) ((n) << 21)
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)
#define ADC_SMPR1_SMP_AN10(n) ((n) << 0)
#define ADC_SMPR1_SMP_AN11(n) ((n) << 3)
#define ADC_SMPR2_SMP_AN0(n) ((n) << 0)
#define ADC_SMPR2_SMP_AN1(n) ((n) << 3)
#define ADC_SMPR2_SMP_AN2(n) ((n) << 6)
#define ADC_SMPR2_SMP_AN9(n) ((n) << 27)
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
#define ADC_SQR3_SQ1_N(n) ((n) << 0)
#define ADC_SQR3_SQ2_N(n) ((n) << 5)
#define ADC_SQR3_SQ3_N(n) ((n) << 10)
#define ADC_SQR3_SQ4_N(n) ((n) << 15)
#define ADC_SAMPLE_1P5 0
#define ADC_CHANNEL_IN0 0
#define ADC_CHANNEL_IN1 1
#define ADC_CHANNEL_IN2 2
#define ADC_CHANNEL_IN9 9
#define ADC_CHANNEL_IN10 10
#define ADC_CHANNEL_IN11 11
#define ADC_CHANNEL_SENSOR 16
#define ADC_CHANNEL_VREFINT 17
#define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
#define DELIBARATELY_DO_IT_WRONG_START_STOP
#ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
#define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
#else
#define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
#endif
#define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
#define NEUG_DMA_MODE \
( STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY) \
| STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD \
| STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE \
| STM32_DMA_CR_TEIE )
#define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF) \
| ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
#define NEUG_ADC_SETTING1_SMPR2 0
#define NEUG_ADC_SETTING1_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT) \
| ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR) \
| ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR) \
| ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
#define NEUG_ADC_SETTING1_NUM_CHANNELS 4
#if !defined(NEUG_ADC_SETTING2_SMPR1)
#define NEUG_ADC_SETTING2_SMPR1 0
#define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5) \
| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
#define NEUG_ADC_SETTING2_SQR3 ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0) \
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1)
#define NEUG_ADC_SETTING2_NUM_CHANNELS 2
#endif
/*
* Do calibration for both of ADCs.
*/
void adc_init (void)
{
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST);
RCC->APB2RSTR = 0;
ADC1->CR1 = 0;
ADC1->CR2 = ADC_CR2_ADON;
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
;
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
;
ADC1->CR2 = 0;
ADC2->CR1 = 0;
ADC2->CR2 = ADC_CR2_ADON;
ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
;
ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
;
ADC2->CR2 = 0;
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
}
void adc_start (void)
{
/* Use DMA channel 1. */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
DMA1->IFCR = 0xffffffff;
RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
| ADC_CR1_SCAN);
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
ADC1->SQR2 = 0;
ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
| ADC_CR1_SCAN);
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC2->SMPR1 = NEUG_ADC_SETTING2_SMPR1;
ADC2->SMPR2 = NEUG_ADC_SETTING2_SMPR2;
ADC2->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING2_NUM_CHANNELS);
ADC2->SQR2 = 0;
ADC2->SQR3 = NEUG_ADC_SETTING2_SQR3;
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
/*
* We could just let ADC run continuously always and only enable DMA
* to receive stable data from ADC. But our purpose is not to get
* correct data but noise. In fact, we can get more noise when we
* start/stop ADC each time.
*/
ADC2->CR2 = 0;
ADC1->CR2 = 0;
#else
/* Start conversion. */
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}
uint32_t adc_buf[64];
void adc_start_conversion (int offset, int count)
{
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; /* SetPeripheral */
DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0 */
DMA1_Channel1->CNDTR = count; /* Counter */
DMA1_Channel1->CCR = NEUG_DMA_MODE | DMA_CCR1_EN; /* Mode */
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
/* Power on */
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
/*
* Start conversion. tSTAB is 1uS, but we don't follow the spec, to
* get more noise.
*/
ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
| ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}
static void adc_stop_conversion (void)
{
DMA1_Channel1->CCR &= ~DMA_CCR1_EN;
#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
ADC2->CR2 = 0;
ADC1->CR2 = 0;
#endif
}
void adc_stop (void)
{
ADC1->CR1 = 0;
ADC1->CR2 = 0;
ADC2->CR1 = 0;
ADC2->CR2 = 0;
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
}
static uint32_t adc_err;
/*
* Return 0 on success.
* Return 1 on error.
*/
int adc_wait_completion (chopstx_intr_t *intr)
{
uint32_t flags;
while (1)
{
chopstx_intr_wait (intr);
flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause. */
/*
* Clear interrupt cause of channel 1.
*
* Note that CGIFx=0, as CGIFx=1 clears all of GIF, HTIF, TCIF
* and TEIF.
*/
DMA1->IFCR = (flags & ~1);
if ((flags & STM32_DMA_ISR_TEIF) != 0) /* DMA errors */
{
/* Should never happened. If any, it's coding error. */
/* Access an unmapped address space or alignment violation. */
adc_err++;
adc_stop_conversion ();
return 1;
}
else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
{
adc_stop_conversion ();
return 0;
}
}
}

8
src/affine.h Normal file
View File

@@ -0,0 +1,8 @@
/**
* @brief Affine coordinates
*/
typedef struct
{
bn256 x[1];
bn256 y[1];
} ac;

232
src/bn.c
View File

@@ -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++;
@@ -83,23 +89,17 @@ uint32_t
bn256_add_uint (bn256 *X, const bn256 *A, uint32_t w)
{
int i;
uint32_t carry = 0;
uint32_t carry = w;
uint32_t *px;
const uint32_t *pa;
px = X->words;
pa = A->words;
px = X->word;
pa = A->word;
for (i = 0; i < BN256_WORDS; i++)
{
*px = *pa + carry;
carry = (*px < carry);
if (i == 0)
{
*px += w;
carry += (*px < w);
}
px++;
pa++;
}
@@ -111,26 +111,19 @@ uint32_t
bn256_sub_uint (bn256 *X, const bn256 *A, uint32_t w)
{
int i;
uint32_t borrow = 0;
uint32_t borrow = w;
uint32_t *px;
const uint32_t *pa;
px = X->words;
pa = A->words;
px = X->word;
pa = A->word;
for (i = 0; i < BN256_WORDS; i++)
{
uint32_t borrow0 = (*pa < borrow);
*px = *pa - borrow;
if (i == 0)
{
borrow = (*px < w) + borrow0;
*px -= w;
}
else
borrow = borrow0;
borrow = borrow0;
px++;
pa++;
}
@@ -138,9 +131,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 +181,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 +193,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 +309,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 +326,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 +346,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 +357,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 +370,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

View File

@@ -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);

View File

@@ -1,7 +1,7 @@
/*
* 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
* Copyright (C) 2013, 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -21,24 +21,16 @@
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bn.h"
#include "jpc-ac.h"
#include "ec_p256.h"
#include "field-group-select.h"
#include "config.h"
#include "gnuk.h"
/* We are little endian. */
/* We are little-endian in the computation, but the protocol is big-endian. */
#define ECDSA_BYTE_SIZE 32
#define ECDH_BYTE_SIZE 32
int
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 +38,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 +55,7 @@ ecdsa_sign (const uint8_t *hash, uint8_t *output,
}
uint8_t *
ecdsa_compute_public (const uint8_t *key_data)
FUNC(ecc_compute_public) (const uint8_t *key_data)
{
uint8_t *p0, *p, *p1;
ac q[1];
@@ -77,7 +69,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;
@@ -93,3 +85,59 @@ ecdsa_compute_public (const uint8_t *key_data)
return p0;
}
int
FUNC(ecdh_decrypt) (const uint8_t *input, uint8_t *output,
const uint8_t *key_data)
{
bn256 k[1];
ac X[1], P[1];
int i;
uint8_t *p0;
const uint8_t *p1;
int r;
p0 = (uint8_t *)k;
for (i = 0; i < ECDH_BYTE_SIZE; i++)
p0[ECDH_BYTE_SIZE - i - 1] = key_data[i];
p1 = input+1; /* skip '04' */
p0 = (uint8_t *)P->x;
for (i = 0; i < ECDH_BYTE_SIZE; i++)
p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
p0 = (uint8_t *)P->y;
for (i = 0; i < ECDH_BYTE_SIZE; i++)
p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
r = FUNC(compute_kP) (X, k, P);
if (r == 0)
{
p0 = output;
p1 = (const uint8_t *)X->x;
*p0++ = 4;
for (i = 0; i < ECDH_BYTE_SIZE; i++)
*p0++ = p1[ECDH_BYTE_SIZE - i - 1];
p1 = (const uint8_t *)X->y;
for (i = 0; i < ECDH_BYTE_SIZE; i++)
*p0++ = p1[ECDH_BYTE_SIZE - i - 1];
}
return r;
}
/**
* @brief Check if a secret d0 is valid or not
*
* @param D0 scalar D0: secret
* @param D1 scalar D1: secret candidate N-D0
*
* Return 0 on error.
* Return -1 when D1 should be used as the secret
* Return 1 when D0 should be used as the secret
*/
int
FUNC(ecc_check_secret) (const uint8_t *d0, uint8_t *d1)
{
return FUNC(check_secret) ((const bn256 *)d0, (bn256 *)d1);
}

35
src/call-ec_p256k1.c Normal file
View 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
View 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"

View File

@@ -1,7 +1,8 @@
/*
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
*
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -24,37 +25,44 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <chopstx.h>
#include "config.h"
#include "gnuk.h"
#include "openpgp.h"
#include "status-code.h"
#include "random.h"
#include "polarssl/config.h"
#include "polarssl/rsa.h"
#define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
/* 256 byte == 2048-bit */
/* 128 byte == 1024-bit */
static rsa_context rsa_ctx;
static struct chx_cleanup clp;
static void
rsa_cleanup (void *arg)
{
free (arg);
rsa_free (&rsa_ctx);
}
int
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
struct key_data *kd)
struct key_data *kd, int pubkey_len)
{
mpi P1, Q1, H;
int ret = 0;
unsigned char temp[RSA_SIGNATURE_LENGTH];
unsigned char temp[pubkey_len];
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
rsa_ctx.len = KEY_CONTENT_LEN;
rsa_ctx.len = pubkey_len;
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
rsa_ctx.len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], pubkey_len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[pubkey_len / 2],
pubkey_len / 2) );
#if 0
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
#endif
@@ -69,12 +77,20 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
mpi_free (&P1); mpi_free (&Q1); mpi_free (&H);
if (ret == 0)
{
DEBUG_INFO ("RSA sign...");
int cs;
DEBUG_INFO ("RSA sign...");
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
ret = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, temp);
memcpy (output, temp, RSA_SIGNATURE_LENGTH);
memcpy (output, temp, pubkey_len);
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
rsa_free (&rsa_ctx);
@@ -86,7 +102,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
}
else
{
res_APDU_size = RSA_SIGNATURE_LENGTH;
DEBUG_INFO ("done.\r\n");
GPG_SUCCESS ();
return 0;
@@ -123,14 +138,13 @@ modulus_calc (const uint8_t *p, int len)
int
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
struct key_data *kd)
struct key_data *kd, unsigned int *output_len_p)
{
mpi P1, Q1, H;
int ret;
unsigned int output_len;
DEBUG_INFO ("RSA decrypt:");
DEBUG_WORD ((uint32_t)&output_len);
DEBUG_WORD ((uint32_t)&ret);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
@@ -139,9 +153,8 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
DEBUG_WORD (msg_len);
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
KEY_CONTENT_LEN / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], msg_len / 2) );
MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[msg_len / 2], msg_len / 2) );
#if 0
MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
#endif
@@ -156,10 +169,19 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
mpi_free (&P1); mpi_free (&Q1); mpi_free (&H);
if (ret == 0)
{
int cs;
DEBUG_INFO ("RSA decrypt ...");
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = NULL;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
RSA_PRIVATE, &output_len, input,
RSA_PRIVATE, output_len_p, input,
output, MAX_RES_APDU_DATA_SIZE);
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
}
rsa_free (&rsa_ctx);
@@ -171,7 +193,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
}
else
{
res_APDU_size = output_len;
DEBUG_INFO ("done.\r\n");
GPG_SUCCESS ();
return 0;
@@ -179,14 +200,15 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
}
int
rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
rsa_verify (const uint8_t *pubkey, int pubkey_len,
const uint8_t *hash, const uint8_t *sig)
{
int ret;
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = KEY_CONTENT_LEN;
rsa_ctx.len = pubkey_len;
MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN) );
MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, pubkey_len) );
DEBUG_INFO ("RSA verify...");
@@ -210,16 +232,17 @@ rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig)
#define RSA_EXPONENT 0x10001
#ifdef KEYGEN_SUPPORT
uint8_t *
rsa_genkey (void)
rsa_genkey (int pubkey_len)
{
int ret;
uint8_t index = 0;
uint8_t *p_q_modulus = (uint8_t *)malloc (KEY_CONTENT_LEN*2);
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
uint8_t *p = p_q_modulus;
uint8_t *q = p_q_modulus + KEY_CONTENT_LEN/2;
uint8_t *modulus = p_q_modulus + KEY_CONTENT_LEN;
uint8_t *q = p_q_modulus + pubkey_len / 2;
uint8_t *modulus = p_q_modulus + pubkey_len;
int cs;
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
extern void neug_flush (void);
@@ -229,26 +252,34 @@ rsa_genkey (void)
neug_flush ();
prng_seed (random_gen, &index);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index,
KEY_CONTENT_LEN * 8, RSA_EXPONENT) );
clp.next = NULL;
clp.routine = rsa_cleanup;
clp.arg = (void *)p_q_modulus;
chopstx_cleanup_push (&clp);
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
RSA_EXPONENT) );
if (ret != 0)
{
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
free (p_q_modulus);
rsa_free (&rsa_ctx);
return NULL;
}
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, KEY_CONTENT_LEN/2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, KEY_CONTENT_LEN/2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, KEY_CONTENT_LEN) );
MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
cleanup:
chopstx_setcancelstate (cs);
chopstx_cleanup_pop (0);
rsa_free (&rsa_ctx);
if (ret != 0)
return NULL;
else
return p_q_modulus;
}
#endif

View File

@@ -1,74 +0,0 @@
/* ChibiOS/RT configuration file */
#ifndef _CHCONF_H_
#define _CHCONF_H_
#include <config.h>
#ifdef DFU_SUPPORT
#define CORTEX_VTOR_INIT (0x00003000+0x00001000)
#else
#define CORTEX_VTOR_INIT 0x00001000
#endif
#define CH_FREQUENCY 1000
#define CH_TIME_QUANTUM 20
#define CH_USE_NESTED_LOCKS FALSE
#define CH_MEMCORE_SIZE 0 /* Whole RAM */
#define CH_NO_IDLE_THREAD FALSE
#define CH_OPTIMIZE_SPEED TRUE
#define CH_USE_REGISTRY TRUE
#define CH_USE_WAITEXIT TRUE
#define CH_USE_SEMAPHORES TRUE
#define CH_USE_SEMAPHORES_PRIORITY FALSE
#define CH_USE_SEMSW FALSE
#define CH_USE_MUTEXES TRUE
#define CH_USE_CONDVARS TRUE
#define CH_USE_CONDVARS_TIMEOUT TRUE
#define CH_USE_EVENTS TRUE /* We use this! */
#define CH_USE_EVENTS_TIMEOUT TRUE /* We use this! */
#define CH_USE_MESSAGES FALSE
#define CH_USE_MESSAGES_PRIORITY FALSE
#define CH_USE_MAILBOXES FALSE
#define CH_USE_QUEUES FALSE
#define CH_USE_MEMCORE TRUE
#define CH_USE_HEAP TRUE
#define CH_USE_MALLOC_HEAP FALSE
#define CH_USE_MEMPOOLS FALSE
#define CH_USE_DYNAMIC TRUE
/* Debug options */
#define CH_DBG_ENABLE_CHECKS FALSE
#define CH_DBG_ENABLE_ASSERTS FALSE
#define CH_DBG_ENABLE_TRACE FALSE
#define CH_DBG_ENABLE_STACK_CHECK TRUE
#define CH_DBG_FILL_THREADS FALSE
#define CH_DBG_THREADS_PROFILING FALSE
#define THREAD_EXT_FIELDS \
/* Add threads custom fields here.*/ \
#define THREAD_EXT_INIT(tp) { \
/* Add threads initialization code here.*/ \
}
#define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* System halt code here.*/ \
}
#define THREAD_EXT_EXIT(tp) { \
/* Add threads finalization code here.*/ \
}
#define IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
#define SYSTEM_TICK_EVENT_HOOK() { \
/* System tick event code here.*/ \
}
#define SYSTEM_HALT_HOOK() { \
/* System halt code here.*/ \
}
#endif /* _CHCONF_H_ */

View File

@@ -7,4 +7,5 @@
@PINPAD_MORE_DEFINE@
@CERTDO_DEFINE@
@HID_CARD_CHANGE_DEFINE@
@SERIALNO_STR_LEN@
@SERIALNO_STR_LEN_DEFINE@
@LIFE_CYCLE_MANAGEMENT_DEFINE@

231
src/configure vendored
View File

@@ -1,9 +1,13 @@
#! /bin/bash
# This is bash which supports ANSI-C Quoting
nl=$'\n'
#
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
#
# Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
# Free Software Initiative of Japan
#
# This file is a part of Gnuk, a GnuPG USB Token implementation.
# Gnuk is free software: you can redistribute it and/or modify it
@@ -19,18 +23,34 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Submodule check
#
if ! test -f ../chopstx/rules.mk; then
echo "Submodule 'chopstx' not found" >&2
echo "You might need: git submodule update --init" >&2
exit 1
fi
# Default settings
help=no
vidpid=none
target=OLIMEX_STM32_H103
target=FST_01
verbose=no
with_dfu=default
debug=no
sys1_compat=yes
pinpad=no
certdo=no
keygen=no
sys1_compat=yes
hid_card_change=no
factory_reset=no
# Revision number
if test -e ../.git; then
REVISION=`git describe --dirty="-modified"`
else
REVISION=`cat ../VERSION`
fi
# Process each option
for option; do
@@ -60,18 +80,18 @@ for option; do
certdo=yes ;;
--disable-certdo)
certdo=no ;;
--enable-keygen)
keygen=yes ;;
--disable-keygen)
keygen=no ;;
--enable-sys1-compat)
sys1_compat = yes ;;
--disable-sys1-compat)
sys1_compat = no ;;
--enable-hid-card-change)
hid_card_change = yes ;;
hid_card_change=yes ;;
--disable-hid-card-change)
hid_card_change = no ;;
hid_card_change=no ;;
--enable-sys1-compat)
sys1_compat=yes ;;
--disable-sys1-compat)
sys1_compat=no ;;
--enable-factory-reset)
factory_reset=yes ;;
--disable-factory-reset)
factory_reset=no ;;
--with-dfu)
with_dfu=yes ;;
--without-dfu)
@@ -93,40 +113,49 @@ Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit [no]
--vidpid=VID:PID specify vendor/product ID [<NONE>]
--target=TARGET specify target [OLIMEX_STM32_H103]
--target=TARGET specify target [FST_01]
supported targets are:
OLIMEX_STM32_H103
STM8S_DISCOVERY
FST_01
FST_01_00
FST_01G
OLIMEX_STM32_H103
MAPLE_MINI
ST_DONGLE
ST_NUCLEO_F103
NITROKEY_START
BLUE_PILL
CQ_STARM
STM32_PRIMER2
STBEE
STBEE_MINI
FST_01_00 (unreleased version with 8MHz XTAL)
--enable-debug debug with virtual COM port [no]
--enable-pinpad=cir
PIN entry support [no]
--enable-certdo support CERT.3 data object [no]
--enable-keygen support key generation [no]
--enable-sys1-compat enable SYS 1.0 compatibility [yes]
executable is target dependent
--disable-sys1-compat disable SYS 1.0 compatibility [no]
executable is target independent
but requires SYS 2.0 or newer
--enable-factory-reset
support life cycle management [no]
--with-dfu build image for DFU [<target specific>]
EOF
exit 0
fi
if test "$vidpid" = "none"; then
echo "Please specify Vendor ID and Product ID by --vidpid option."
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
exit 1
fi
TARGET_DEFINE="#define BOARD_$target 1"
BOARD_HEADER_FILE=board-`echo $target | tr '_[:upper:]' '-[:lower:]'`.h
echo Header file is: $BOARD_HEADER_FILE
ln -sf ../chopstx/board/$BOARD_HEADER_FILE board.h
# Flash page size in byte
FLASH_PAGE_SIZE=1024
# Flash memory size in KB
# Flash memory size in KiB
FLASH_SIZE=128
# Memory size in KiB
MEMORY_SIZE=20
@@ -169,6 +198,11 @@ fi
# --with-dfu option
if test "$with_dfu" = "yes"; then
if test "$target" = "FST_01" -o "$target" = "FST_01G" \
-o "$target" = "FST_01_00"; then
echo "FST-01 doesn't have DFU loader, you should not use --with-dfu." >&2
exit 1
fi
echo "Configured for DFU"
ORIGIN=0x08003000
FLASH_SIZE=`expr $FLASH_SIZE - 12`
@@ -213,15 +247,6 @@ else
echo "CERT.3 Data Object is NOT supported"
fi
# --enable-keygen option
if test "$keygen" = "yes"; then
KEYGEN_SUPPORT="-DKEYGEN_SUPPORT"
echo "Key generation on device is supported"
else
KEYGEN_SUPPORT=""
echo "Key generation on device is NOT supported"
fi
# --enable-hid-card-change option
if test "$hid_card_change" = "yes"; then
HID_CARD_CHANGE_DEFINE="#define HID_CARD_CHANGE_SUPPORT 1"
@@ -231,10 +256,13 @@ else
echo "Card insert/removal by HID device is NOT supported"
fi
if test -d ../.git; then
REVISION=`git describe --dirty="-modified"`
# --enable-factory-reset option
if test "$factory_reset" = "yes"; then
LIFE_CYCLE_MANAGEMENT_DEFINE="#define LIFE_CYCLE_MANAGEMENT_SUPPORT 1"
echo "Life cycle management is supported"
else
REVISION=`cat ../VERSION`
LIFE_CYCLE_MANAGEMENT_DEFINE="#undef LIFE_CYCLE_MANAGEMENT_SUPPORT"
echo "Life cycle management is NOT supported"
fi
### !!! Replace following string of "FSIJ" to yours !!! ####
@@ -243,76 +271,100 @@ SERIALNO="FSIJ-`cat ../VERSION | sed -e 's%^[^/]*/%%'`-"
SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:keygen=$keygen"
if test "$sys1_compat" = "yes"; then
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo"
else
if test "$with_dfu" = "yes"; then
echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
exit 1
fi
# Override settings for common binary. Safer side.
FLASH_PAGE_SIZE=2048
FLASH_SIZE=128
MEMORY_SIZE=20
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo"
fi
output_vid_pid_version () {
echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\\${nl} 0x\4, 0x\3, /* idProduct */%p"
echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
}
output_vendor_product_serial_strings () {
prefix=$1
echo "static const uint8_t ${prefix}string_vendor[] = {"
echo " ${#VENDOR}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Manufacturer: \"$VENDOR\" */"
echo $VENDOR | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}string_product[] = {"
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
if test -n "$prefix"; then
echo
echo "const uint8_t ${prefix}string_serial[] = {"
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo '};'
echo
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo "static const uint8_t ${prefix}revision_detail[] = {"
echo " ${#REVISION}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo
echo "static const uint8_t ${prefix}config_options[] = {"
echo " ${#CONFIG}*2+2, /* bLength */"
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
echo '};'
echo '#endif'
fi
}
if !(IFS=" "
while read VIDPID VERSION PRODUCT VENDOR; do
if test "$vidpid" = "$VIDPID"; then
(echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\n 0x\4, 0x\3, /* idProduct */%p"
echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
) > usb-vid-pid-ver.c.inc
(echo 'static const uint8_t gnukStringVendor[] = {'
echo " ${#VENDOR}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Manufacturer: \"$VENDOR\" */"
echo $VENDOR | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo '};'
echo
echo 'static const uint8_t gnukStringProduct[] = {'
echo " ${#PRODUCT}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Product name: \"$PRODUCT\" */"
echo $PRODUCT | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo '};'
echo
echo 'const uint8_t gnukStringSerial[] = {'
echo " ${#SERIALNO}*2+2+16, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* Serial number: \"$SERIALNO\" */"
echo $SERIALNO | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
echo '};'
echo
echo '#ifdef USB_STRINGS_FOR_GNUK'
echo 'static const uint8_t gnuk_revision_detail[] = {'
echo " ${#REVISION}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* revision detail: \"$REVISION\" */"
echo $REVISION | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo '};'
echo
echo 'static const uint8_t gnuk_config_options[] = {'
echo " ${#CONFIG}*2+2, /* bLength */"
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
echo " /* configure options: \"$CONFIG\" */"
echo $CONFIG | sed -n -e "s/\(........\)/\1\n/gp" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "s/ $//p"
echo '};'
echo '#endif'
) >usb-strings.c.inc
output_vid_pid_version > usb-vid-pid-ver.c.inc
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
exit 0
fi
done; exit 1) < ../GNUK_USB_DEVICE_ID
then
echo "Please specify valid Vendor ID and Product ID."
echo "Check ../GNUK_USB_DEVICE_ID."
echo "Please specify valid Vendor ID and Product ID." >&2
echo "Check ../GNUK_USB_DEVICE_ID." >&2
exit 1
fi
if test "$sys1_compat" = "no"; then
# Disable when you are sure that it's sys version 2.0.
# Note that Gnuk 1.0 and Neug (until 0.06) uses sys version 1.0.
# Disabling the compatibility, executable will be target independent,
# assuming the clock initialization will be done by SYS (before entry).
have_sys_h="-DHAVE_SYS_H"
# Disable when you are sure that it's sys version 3.0 or later.
# Note that Gnuk 1.0 and NeuG (until 0.06) uses sys version 1.0.
# Disabling the compatibility, executable will be target independent,
# assuming the clock initialization will be done by clock_init in
# SYS.
use_sys3="-DUSE_SYS3"
else
have_sys_h=""
use_sys3=""
fi
sed -e "s%@HAVE_SYS_H@%$have_sys_h%" \
sed -e "s%@USE_SYS3@%$use_sys3%" \
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
-e "s%@KEYGEN_SUPPORT@%$KEYGEN_SUPPORT%" \
-e "s%@HEXOUTPUT_MAKE_OPTION@%$HEXOUTPUT_MAKE_OPTION%" \
< Makefile.in > Makefile
if test "$certdo" = "yes"; then
@@ -321,6 +373,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" \
@@ -338,6 +392,7 @@ sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_DEFINE/" \
-e "s/@SERIALNO_STR_LEN@/$SERIALNO_STR_LEN_DEFINE/" \
-e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
< config.h.in > config.h
exit 0

View File

@@ -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);

231
src/ec_p256k1.c Normal file
View File

@@ -0,0 +1,231 @@
/* -*- 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/>.
*
*/
/*
* Note: we don't take advantage of the specific feature of this curve,
* but use same method of computation as NIST P-256 curve. That's due
* to some software patent(s).
*/
#include <stdint.h>
#include <string.h>
#include "bn.h"
#include "modp256k1.h"
#include "affine.h"
#include "jpc-ac_p256k1.h"
#include "mod.h"
#include "ec_p256k1.h"
#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
View 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);
int check_secret_p256k1 (const bn256 *q, bn256 *d1);

View File

@@ -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"

4
src/ec_p256r1.h Normal file
View File

@@ -0,0 +1,4 @@
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);
int check_secret_p256r1 (const bn256 *q, bn256 *d1);

View File

@@ -1,76 +0,0 @@
/*
* ecc-cdh.c - One-Pass Diffie-Hellman method implementation
* C(1, 1, ECC CDH) for EC DH of OpenPGP ECC
*
* Copyright (C) 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* References:
*
* [1] A. Jivsov, Elliptic Curve Cryptography (ECC) in OpenPGP, RFC 6637,
* June 2012.
*
* [2] Suite B Implementer's Guide to NIST SP 800-56A, July 28, 2009.
*
*/
static const char param[] = {
/**/
curve_OID_len,
curve_OID,
public-key_alg_ID, /*ecdh*/
0x03,
0x01,
KDF_hash_ID, /*sha256*/
KEK_alg_ID, /*aes128*/
"Anonymous Sender ",
my_finger_print /*20-byte*/
};
/*
*
*/
int
ecdh (unsigned char *key,
const unsigned char *key_encrypted, const ac *P,
const naf4_257 *naf_d, const unsigned char *fp)
{
ac S[1];
sha256_context ctx;
unsigned char kek[32];
unsigned char x[32];
int i;
const unsigned char *p;
compute_kP (S, naf_d, P); /* Get shared secret. */
/* Endian change from big to little. */
p = (const unsigned char *)S->x;
for (i = 0; i < 32; i++)
x[31-i] = p[i];
/* kdf (kek, S, parameter) */
sha256_start (&ctx);
sha256_update (&ctx, "\x00\x00\x00\x01", 4);
sha256_update (&ctx, x, size of x);
sha256_update (&ctx, (const char *)param, size of param);
sha256_finish (&ctx, kek);
}

960
src/ecc-edwards.c Normal file
View File

@@ -0,0 +1,960 @@
/* -*- coding: utf-8 -*-
* ecc-edwards.c - Elliptic curve computation for
* the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "bn.h"
#include "mod.h"
#include "mod25638.h"
#include "sha512.h"
/*
* References:
*
* [1] Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin Yang.
* High-speed high-security signatures.
* Journal of Cryptographic Engineering 2 (2012), 77--89.
* http://cr.yp.to/papers.html#ed25519
*
* [2] Daniel J. Bernstein, Peter Birkner, Marc Joye, Tanja Lange,
* Christiane Peters.
* Twisted Edwards curves.
* Pages 389--405 in Progress in cryptology---AFRICACRYPT 2008.
* http://cr.yp.to/papers.html#twisted
*/
/*
* IMPLEMENTATION NOTE
*
* (0) We assume that the processor has no cache, nor branch target
* prediction. Thus, we don't avoid indexing by secret value.
* We don't avoid conditional jump if both cases have same timing,
* either.
*
* (1) We use Radix-32 field arithmetic. It's a representation like
* 2^256-38, but it's more redundant. For example, "1" can be
* represented in three ways in 256-bit: 1, 2^255-18, and
* 2^256-37.
*
* (2) We use fixed base comb multiplication. Scalar is 252-bit.
* There are various possible choices for 252 = 2 * 2 * 3 * 3 * 7.
* Current choice of total size is 3KB. We use three tables, and
* a table has 16 points (3 * 1KB).
*
* Window size W = 4-bit, E = 21.
* <--21-bit-
* <---42-bit----------
* [ ][########][////////][ ][########][////////]
* <-------63-bit----------------
* <-----------84-bit----------------------
* <--------------105-bit----------------------------
*
* [ ][########][////////][ ][########][////////]
* <-126-bit-
* <-147-bit-
* <----168-bit--------
*
* <-------189-bit---------------
* <----------210-bit----------------------
* <-------------231-bit-----------------------------
*/
/*
* Identity element: (0,1)
* Negation: -(x,y) = (-x,y)
*
* d: -0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A
* order:
* 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED
* Gx: 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A
* Gy: 0x6666666666666666666666666666666666666666666666666666666666666658
*/
/* d + 2^255 - 19 */
static const bn256 coefficient_d[1] = {
{{ 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d,
0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee }} };
/**
* @brief Projective Twisted Coordinates
*/
typedef struct
{
bn256 x[1];
bn256 y[1];
bn256 z[1];
} ptc;
#include "affine.h"
static int
mod25519_is_neg (const bn256 *a)
{
return (a->word[0] & 1);
}
/**
* @brief X = 2 * A
*
* Compute (X3 : Y3 : Z3) = 2 * (X1 : Y1 : Z1)
*/
static void
point_double (ptc *X, const ptc *A)
{
bn256 b[1], d[1], e[1];
/* Compute: B = (X1 + Y1)^2 */
mod25638_add (b, A->x, A->y);
mod25638_sqr (b, b);
/* Compute: C = X1^2 : E */
mod25638_sqr (e, A->x);
/* Compute: D = Y1^2 */
mod25638_sqr (d, A->y);
/* E = aC; where a = -1 */
/* Compute: D - E = D + C : Y3_tmp */
mod25638_add (X->y, e, d);
/* Compute: -F = -(E + D) = C - D; where a = -1 : E */
mod25638_sub (e, e, d);
/* Compute: H = Z1^2 : D */
mod25638_sqr (d, A->z);
/* Compute: -J = 2*H - F : D */
mod25638_add (d, d, d);
mod25638_add (d, d, e);
/* Compute: X3 = (B-C-D)*J = -J*(C+D-B) = -J*(Y3_tmp-B) */
mod25638_sub (X->x, X->y, b);
mod25638_mul (X->x, X->x, d);
/* Compute: Y3 = -F*(D-E) = -F*Y3_tmp */
mod25638_mul (X->y, X->y, e);
/* Z3 = -F*-J */
mod25638_mul (X->z, e, d);
}
/**
* @brief X = A + B
*
* @param X Destination PTC
* @param A PTC
* @param B AC
*
* Compute: (X3 : Y3 : Z3) = (X1 : Y1 : Z1) + (X2 : Y2 : 1)
*/
static void
point_add (ptc *X, const ptc *A, const ac *B)
{
bn256 c[1], d[1], e[1], tmp[1];
/* Compute: C = X1 * X2 */
mod25638_mul (c, A->x, B->x);
/* Compute: D = Y1 * Y2 */
mod25638_mul (d, A->y, B->y);
/* Compute: E = d * C * D */
mod25638_mul (e, c, d);
mod25638_mul (e, coefficient_d, e);
/* Compute: C_1 = C + D */
mod25638_add (c, c, d);
/* Compute: D_1 = Z1^2 : B */
mod25638_sqr (d, A->z);
/* tmp = D_1 - E : F */
mod25638_sub (tmp, d, e);
/* D_2 = D_1 + E : G */
mod25638_add (d, d, e);
/* X3_final = Z1 * tmp * ((X1 + Y1) * (X2 + Y2) - C_1) */
mod25638_add (X->x, A->x, A->y);
mod25638_add (e, B->x, B->y);
mod25638_mul (e, X->x, e);
mod25638_sub (e, e, c);
mod25638_mul (e, tmp, e);
mod25638_mul (X->x, A->z, e);
/* Y3_final = Z1 * D_2 * C_1 */
mod25638_mul (c, d, c);
mod25638_mul (X->y, A->z, c);
/* Z3_final = tmp * D_2 */
mod25638_mul (X->z, tmp, d);
/* A = Z1 */
/* B = A^2 */
/* C = X1 * X2 */
/* D = Y1 * Y2 */
/* E = d * C * D */
/* F = B - E */
/* G = B + E */
/* X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D) */
/* Y3 = A * G * (D - aC); where a = -1 */
/* Z3 = F * G */
}
/**
* @brief X = convert A
*
* @param X Destination AC
* @param A PTC
*
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
*/
static void
point_ptc_to_ac (ac *X, const ptc *A)
{
bn256 z_inv[1];
/*
* A->z may be bigger than p25519, or two times bigger than p25519.
* But this is no problem for computation of mod_inv.
*/
mod_inv (z_inv, A->z, p25519);
mod25638_mul (X->x, A->x, z_inv);
mod25519_reduce (X->x);
mod25638_mul (X->y, A->y, z_inv);
mod25519_reduce (X->y);
}
static const ac precomputed_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}} },
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
0xa815e038, 0xce0d0064, 0xbca90151, 0x041c030f }}},
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
0x655e5c16, 0xc67dc71c, 0xee43fb7a, 0x72467625 }}} },
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
0x6aeae260, 0x31f39299, 0x5f4a9bb2, 0x6d9e4545 }}},
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
0xa259dc8a, 0xaab95e0b, 0x99013cd0, 0x28bd5fc3 }}} },
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
0xda13ef4b, 0x4583ff4c, 0x95083f85, 0x1f13202c }}},
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
0xfdfd7ffa, 0xf21109e7, 0x6c381b7e, 0x66336d35 }}} },
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
0x1a52df87, 0x0de65625, 0xbd675870, 0x5f0dd494 }}},
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
0xa80e1eb6, 0x497e74bd, 0xe9365b15, 0x1648eaac }}} },
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
0xb34cf697, 0xb75832f4, 0x3a2bce94, 0x7aaf57c5 }}},
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
0x48742dd1, 0xaebd15dd, 0x55d38439, 0x6311bb16 }}} },
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
0x70611a3f, 0x91c1cd94, 0x8075dbcb, 0x1d0c34f6 }}},
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
0x46f167bb, 0x54b1992f, 0xb74a9944, 0x01a11f3c }}} },
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
0x2f6cc814, 0x359c5b5f, 0x7786383d, 0x7b6a5565 }}},
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
0xeddb8571, 0x61d526f6, 0x0eac739a, 0x0cb7acea }}} },
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
0x8397f958, 0x4870f214, 0x8a175fbb, 0x5aa0c67c }}},
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
0x7cbe4e3b, 0x87e293fa, 0xbda72395, 0x17040799 }}} },
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
0x2216fa67, 0x383a533a, 0x684d3925, 0x338bbe0a }}},
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
0x2e30380e, 0xa7c2e708, 0x9e4b3d62, 0x69f13e09 }}} },
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
0x9ebc7613, 0xb642f86a, 0xcb77c3b9, 0x5ce45e73 }}},
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
0xd8782345, 0x55c53916, 0xdb7b202a, 0x6b1dfa87 }}} },
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
0x3a6e8673, 0x0fcafd1d, 0x45d10f48, 0x0d264435 }}},
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
0xd2119aa4, 0x41d5b8eb, 0x8b09b6a5, 0x36bd9ab4 }}} },
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
0xa4730880, 0xefc0dd80, 0x4079fe2f, 0x40617e56 }}},
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
0xda13cdcb, 0xe315c425, 0x67ff5370, 0x37bc6e84 }}} },
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
0xf4085f62, 0x0f540498, 0x0db7bd1b, 0x6f0bb035 }}},
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
0x355facf6, 0x07f45010, 0x3a989a9c, 0x5cd416a9 }}} },
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
0x57aa0119, 0x44afdd5f, 0x430dc946, 0x05d68802 }}},
{{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33,
0x48c51347, 0x37520265, 0x00a21bfb, 0x6f4be0af }}} }
};
static const ac precomputed_2E_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16,
0xedd4d15f, 0xab1c92b8, 0x57d9eada, 0x482a4cdf }}},
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
0x14519298, 0x0b3c5fc6, 0x81c2f7a8, 0x7391de43 }}} },
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
0x63e7328e, 0x44c6e34f, 0xca63ab3e, 0x3f748617 }}},
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
0x1ba9acee, 0x3938a289, 0x420fc47b, 0x0fed89e6 }}} },
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
0x9d128c33, 0xda44186c, 0xbf98c24f, 0x54183ede }}},
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
0xb4ab035d, 0xb3fe651b, 0xa0b0d4e5, 0x426c99c3 }}} },
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
0x24240b15, 0x18795ff8, 0x9989ffcc, 0x13aea184 }}},
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
0x1b25e570, 0xfbddbff2, 0x8ca12b70, 0x0884949c }}} },
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
0xeb17ad71, 0xb6719dfb, 0xc0bc3517, 0x46871ad0 }}},
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
0x884785dc, 0xad295dd0, 0x74a1276a, 0x359debad }}} },
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
0x9c969001, 0xef4c051e, 0x02cb45f4, 0x0d4ea946 }}},
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
0x2b372386, 0x5c12fd04, 0xdbfee11f, 0x1aedbd3e }}} },
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
0xa17dc97e, 0xeea9bddf, 0x3350a2bd, 0x0d12fe3d }}},
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
0x3dbbf921, 0x75c63df4, 0x2958a5a6, 0x545b109c }}} },
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
0x5985dcbe, 0x57a69c0f, 0xeb87a534, 0x3c0c1e7b }}},
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
0x6e2f1973, 0x922c4554, 0xf1347631, 0x74e826b2 }}} },
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
0x2c874953, 0xe298a02e, 0x8932b73f, 0x225093ed }}},
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
0x85dba986, 0xdf41da94, 0xccee8edc, 0x36fe85e7 }}} },
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
0x6a966d2d, 0x8242aa25, 0x4cd36d32, 0x03500a94 }}},
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
0x06eab6b4, 0xd0030f92, 0x62c91d46, 0x2dc80d5f }}} },
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
0x8159db27, 0x4591b980, 0xd3d84740, 0x36c6533c }}},
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
0x71b9dc16, 0xbd306903, 0xf88f8d32, 0x7edd5a95 }}} },
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
0x02b56105, 0x67c9d9d0, 0x5971b456, 0x4d318012 }}},
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
0x00607ea0, 0x4dbeaa6f, 0x6959e688, 0x115c221d }}} },
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
0xc2e9d5f4, 0xefa699bb, 0x021da209, 0x2469e813 }}},
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
0x2fb3ec8f, 0xd21b75e4, 0xd72a7545, 0x10dd726a }}} },
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
0x44f1161f, 0xbda6f3ee, 0xf339efe5, 0x7680aebf }}},
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
0xa320c916, 0xd81ef6f2, 0x62a3b54d, 0x3e22a1fb }}} },
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
0xea49af98, 0xc0a880b9, 0xf2dfddd0, 0x53bf600b }}},
{{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee,
0x2b9f233c, 0xb17712ae, 0xd0eb909e, 0x71f0b344 }}} }
};
static const ac precomputed_4E_KG[16] = {
{ {{{ 0, 0, 0, 0, 0, 0, 0, 0 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}} },
{ {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283,
0xa9a6eb83, 0x2259174d, 0x45500054, 0x184b48cb }}},
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
0x2380ef73, 0xdd60c268, 0x03dc33a9, 0x3ee0e07a }}} },
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
0xecd898fb, 0xec57038c, 0xb663ed49, 0x2898ffaa }}},
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
0xb9934557, 0xe759d6bc, 0xab6c9477, 0x094f3b96 }}} },
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
0xda17203d, 0xa4850a2b, 0x77289e0f, 0x0062f7a7 }}},
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
0x475795f6, 0x9f38bda4, 0xdece4a4c, 0x560ed4b3 }}} },
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
0xdb08fe30, 0xd7a8d50d, 0xa2851109, 0x7efb45d3 }}},
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
0x9d71f8b7, 0x867091c6, 0x11a1bf56, 0x0fe1198b }}} },
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
0x0140502b, 0xad882043, 0x6ea1e46a, 0x34b5c0cb }}},
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
0xbd4801fb, 0x78b4d622, 0xcf18ae9a, 0x6cf4e146 }}} },
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
0x0205cf0e, 0x71908cc2, 0x32bcd754, 0x0cc15edd }}},
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
0x5e5a9312, 0xf22f64ef, 0x3c5e6155, 0x649b8859 }}} },
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
0x0df500ff, 0xe81faaa4, 0x6f50e615, 0x0792c79b }}},
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
0xc1d02d32, 0xdc57c526, 0x3c8aaa55, 0x5fb9a9a6 }}} },
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
0x446ac562, 0x1f8c510f, 0x2cc6b66e, 0x4676d381 }}},
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
0x457fa0eb, 0x051450a0, 0x744c57b1, 0x7d89e2b7 }}} },
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
0xf4d22d72, 0xd4c2f1a9, 0x4dc516b5, 0x73ecfdf1 }}},
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
0xa098cbb3, 0x9ba84f2e, 0xf9bdd37a, 0x1425aa8b }}} },
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
0xee26f5ff, 0x835dff85, 0xe509e1ea, 0x4927e622 }}},
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
0x682fd457, 0x9b87a676, 0x1a53145f, 0x75f382ff }}} },
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
0x9ccf2dc8, 0xf1c2b116, 0x808283d8, 0x7417e00f }}},
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
0x8f3d5d57, 0x231fc664, 0xe5853194, 0x38141a19 }}} },
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
0xe1dbdd65, 0x65d7f9b9, 0xf7c6698a, 0x7133424c }}},
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
0xb518e3eb, 0xa53e50e0, 0x98a40196, 0x2b4b9267 }}} },
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
0xcd2517af, 0x420cdef8, 0x0b695a8a, 0x513a307e }}},
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
0x973afe12, 0x8f3cbbea, 0x872f2538, 0x005c2350 }}} },
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
0x6e79d539, 0xc1f6d766, 0x795b5248, 0x34ec043f }}},
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
0x1666c1f1, 0xaeac7792, 0x66084bc0, 0x72426e97 }}} },
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
0x69e9b92b, 0xaf0984b4, 0x3ffe9093, 0x5fe6736f }}},
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
0x3c65a606, 0x94f893b1, 0x2d65496f, 0x2fee5e8c }}} }
};
/**
* @brief X = k * G
*
* @param K scalar k
*
* Return -1 on error.
* Return 0 on success.
*/
static void
compute_kG_25519 (ac *X, const bn256 *K)
{
ptc Q[1];
int i;
/* identity element */
memset (Q, 0, sizeof (ptc));
Q->y->word[0] = 1;
Q->z->word[0] = 1;
for (i = 20; i >= 0; i--)
{
int k0, k1, k2;
k0 = ((K->word[0] >> i) & 1)
| (i < 1 ? ((K->word[1] >> 30) & 2)
: (((K->word[2] >> (i-1)) & 1) << 1))
| (i < 2 ? ((K->word[3] >> (i+28)) & 4)
: (((K->word[4] >> (i-2)) & 1) << 2))
| (i < 3 ? ((K->word[5] >> (i+26)) & 8)
: (((K->word[6] >> (i-3)) & 1) << 3));
k1 = (i < 11 ? ((K->word[0] >> (i+21)) & 1)
: ((K->word[1] >> (i-11)) & 1))
| (i < 12 ? ((K->word[2] >> (i+19)) & 2)
: (((K->word[3] >> (i-12)) & 1) << 1))
| (i < 13 ? ((K->word[4] >> (i+17)) & 4)
: (((K->word[5] >> (i-13)) & 1) << 2))
| (i < 14 ? ((K->word[6] >> (i+15)) & 8)
: (((K->word[7] >> (i-14)) & 1) << 3));
k2 = ((K->word[1] >> (i+10)) & 1)
| ((K->word[3] >> (i+8)) & 2)
| ((K->word[5] >> (i+6)) & 4)
| ((K->word[7] >> (i+4)) & 8);
point_double (Q, Q);
point_add (Q, Q, &precomputed_KG[k0]);
point_add (Q, Q, &precomputed_2E_KG[k1]);
point_add (Q, Q, &precomputed_4E_KG[k2]);
}
point_ptc_to_ac (X, Q);
}
#define BN416_WORDS 13
#define BN128_WORDS 4
/* M: The order of the generator G. */
static const bn256 M[1] = {
{{ 0x5CF5D3ED, 0x5812631A, 0xA2F79CD6, 0x14DEF9DE,
0x00000000, 0x00000000, 0x00000000, 0x10000000 }}
};
#define C ((const uint32_t *)M)
static void
bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size)
{
int i, j, k;
int i_beg, i_end;
uint32_t r0, r1, r2;
r0 = r1 = r2 = 0;
for (k = 0; k <= q_size + BN128_WORDS - 2; k++)
{
if (q_size < BN128_WORDS)
if (k < q_size)
{
i_beg = 0;
i_end = k;
}
else
{
i_beg = k - q_size + 1;
i_end = k;
if (i_end > BN128_WORDS - 1)
i_end = BN128_WORDS - 1;
}
else
if (k < BN128_WORDS)
{
i_beg = 0;
i_end = k;
}
else
{
i_beg = k - BN128_WORDS + 1;
i_end = k;
if (i_end > q_size - 1)
i_end = q_size - 1;
}
for (i = i_beg; i <= i_end; i++)
{
uint64_t uv;
uint32_t u, v;
uint32_t carry;
j = k - i;
if (q_size < BN128_WORDS)
uv = ((uint64_t )q[j])*((uint64_t )C[i]);
else
uv = ((uint64_t )q[i])*((uint64_t )C[j]);
v = uv;
u = (uv >> 32);
r0 += v;
carry = (r0 < v);
r1 += carry;
carry = (r1 < carry);
r1 += u;
carry += (r1 < u);
r2 += carry;
}
r[k] = r0;
r0 = r1;
r1 = r2;
r2 = 0;
}
r[k] = r0;
}
/**
* @brief R = A mod M (using M=2^252+C) (Barret reduction)
*
* See HAC 14.47.
*/
static void
mod_reduce_M (bn256 *R, const bn512 *A)
{
uint32_t q[BN256_WORDS+1];
uint32_t tmp[BN416_WORDS];
bn256 r[1];
uint32_t carry, next_carry;
int i;
#define borrow carry
q[8] = A->word[15]>>28;
carry = A->word[15] & 0x0fffffff;
for (i = BN256_WORDS - 1; i >= 0; i--)
{
next_carry = A->word[i+7] & 0x0fffffff;
q[i] = (A->word[i+7] >> 28) | (carry << 4);
carry = next_carry;
}
memcpy (R, A, sizeof (bn256));
R->word[7] &= 0x0fffffff;
/* Q_size: 9 */
bnX_mul_C (tmp, q, 9); /* TMP = Q*C */
/* Q = tmp / 2^252 */
carry = tmp[12] & 0x0fffffff;
for (i = 4; i >= 0; i--)
{
next_carry = tmp[i+7] & 0x0fffffff;
q[i] = (tmp[i+7] >> 28) | (carry << 4);
carry = next_carry;
}
/* R' = tmp % 2^252 */
memcpy (r, tmp, sizeof (bn256));
r->word[7] &= 0x0fffffff;
/* R -= R' */
borrow = bn256_sub (R, R, r);
if (borrow)
bn256_add (R, R, M);
else
bn256_add ((bn256 *)tmp, R, M);
/* Q_size: 5 */
bnX_mul_C (tmp, q, 5); /* TMP = Q*C */
carry = tmp[8] & 0x0fffffff;
q[0] = (tmp[7] >> 28) | (carry << 4);
/* R' = tmp % 2^252 */
memcpy (r, tmp, sizeof (bn256));
r->word[7] &= 0x0fffffff;
/* R += R' */
bn256_add (R, R, r);
borrow = bn256_sub (R, R, M);
if (borrow)
bn256_add (R, R, M);
else
bn256_add ((bn256 *)tmp, R, M);
/* Q_size: 1 */
bnX_mul_C (tmp, q, 1); /* TMP = Q*C */
/* R' = tmp % 2^252 */
memset (((uint8_t *)r)+(sizeof (uint32_t)*5), 0, sizeof (uint32_t)*3);
memcpy (r, tmp, sizeof (uint32_t)*5);
/* R -= R' */
borrow = bn256_sub (R, R, r);
if (borrow)
bn256_add (R, R, M);
else
bn256_add ((bn256 *)tmp, R, M);
#undef borrow
}
int
eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
const bn256 *a, const uint8_t *seed, const bn256 *pk)
{
bn256 *r, *s;
sha512_context ctx;
uint8_t hash[64];
bn256 tmp[1];
ac R[1];
uint32_t carry, borrow;
r = (bn256 *)out;
s = (bn256 *)(out+(32/4));
sha512_start (&ctx);
sha512_update (&ctx, seed, sizeof (bn256)); /* It's upper half of the hash */
sha512_update (&ctx, input, ilen);
sha512_finish (&ctx, hash);
mod_reduce_M (r, (bn512 *)hash);
compute_kG_25519 (R, r);
/* EdDSA encoding. */
memcpy (tmp, R->y, sizeof (bn256));
tmp->word[7] ^= mod25519_is_neg (R->x) * 0x80000000;
sha512_start (&ctx);
sha512_update (&ctx, (uint8_t *)tmp, sizeof (bn256));
sha512_update (&ctx, (uint8_t *)pk, sizeof (bn256));
sha512_update (&ctx, input, ilen);
sha512_finish (&ctx, (uint8_t *)hash);
mod_reduce_M (s, (bn512 *)hash);
bn256_mul ((bn512 *)hash, s, a);
mod_reduce_M (s, (bn512 *)hash);
carry = bn256_add (s, s, r);
borrow = bn256_sub (s, s, M);
memcpy (r, tmp, sizeof (bn256));
if ((borrow && !carry))
bn256_add (s, s, M);
else
bn256_add (tmp, s, M);
return 0;
}
void
eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
{
ac R[1];
ptc X[1];
bn256 a0[1];
bn256_shift (a0, a, -3);
compute_kG_25519 (R, a0);
memcpy (X, R, sizeof (ac));
memset (X->z, 0, sizeof (bn256));
X->z->word[0] = 1;
point_double (X, X);
point_double (X, X);
point_double (X, X);
point_ptc_to_ac (R, X);
/* EdDSA encoding. */
memcpy (pk, R->y, sizeof (bn256));
pk->word[7] ^= mod25519_is_neg (R->x) * 0x80000000;
}
uint8_t *
eddsa_compute_public_25519 (const uint8_t *kd)
{
uint8_t *p0;
const bn256 *a = (const bn256 *)kd;
p0 = (uint8_t *)malloc (sizeof (bn256));
if (p0 == NULL)
return NULL;
eddsa_public_key_25519 ((bn256 *)p0, a);
return p0;
}
#if 0
/**
* check if P is on the curve.
*
* Return -1 on error.
* Return 0 on success.
*/
static int
point_is_on_the_curve (const ac *P)
{
bn256 s[1], t[1];
/* Twisted Edwards curve: a*x^2 + y^2 = 1 + d*x^2*y^2 */
}
int
compute_kP_25519 (ac *X, const bn256 *K, const ac *P);
#endif
#ifdef PRINT_OUT_TABLE
static const ptc G[1] = {{
{{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}},
{{{ 1, 0, 0, 0, 0, 0, 0, 0 }}},
}};
#include <stdio.h>
#ifdef TESTING_EDDSA
static void
print_bn256 (const bn256 *X)
{
int i;
for (i = 7; i >= 0; i--)
printf ("%08x", X->word[i]);
puts ("");
}
#endif
#if 0
static void
print_point (const ac *X)
{
int i;
#ifdef PRINT_OUT_TABLE_AS_C
fputs (" { {{{ ", stdout);
for (i = 0; i < 4; i++)
printf ("0x%08x, ", X->x->word[i]);
fputs ("\n ", stdout);
for (; i < 7; i++)
printf ("0x%08x, ", X->x->word[i]);
printf ("0x%08x }}},\n", X->x->word[i]);
fputs (" {{{ ", stdout);
for (i = 0; i < 4; i++)
printf ("0x%08x, ", X->y->word[i]);
fputs ("\n ", stdout);
for (; i < 7; i++)
printf ("0x%08x, ", X->y->word[i]);
printf ("0x%08x }}} },\n", X->y->word[i]);
#else
puts ("--");
for (i = 7; i >= 0; i--)
printf ("%08x", X->x->word[i]);
puts ("");
for (i = 7; i >= 0; i--)
printf ("%08x", X->y->word[i]);
puts ("");
puts ("--");
#endif
}
static void
print_point_ptc (const ptc *X)
{
int i;
puts ("---");
for (i = 7; i >= 0; i--)
printf ("%08x", X->x->word[i]);
puts ("");
for (i = 7; i >= 0; i--)
printf ("%08x", X->y->word[i]);
puts ("");
for (i = 7; i >= 0; i--)
printf ("%08x", X->z->word[i]);
puts ("");
puts ("---");
}
#endif
#ifndef TESTING_EDDSA
static void power_2 (ac *A, ptc *a, int N)
{
int i;
for (i = 0; i < N; i++)
ed_double_25638 (a, a);
ptc_to_ac_25519 (A, a);
}
static void print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000)
{
int i;
ptc a[1];
ac x[1];
for (i = 1; i < 16; i++)
{
/* A := Identity Element */
memset (a, 0, sizeof (ptc));
a->y->word[0] = 1;
a->z->word[0] = 1;
if ((i & 1))
ed_add_25638 (a, a, a0001);
if ((i & 2))
ed_add_25638 (a, a, a0010);
if ((i & 4))
ed_add_25638 (a, a, a0100);
if ((i & 8))
ed_add_25638 (a, a, a1000);
ptc_to_ac_25519 (x, a);
print_point (x);
}
fputs ("\n", stdout);
}
static void compute_and_print_table (ac *a0001, ac *a0010, ac *a0100, ac *a1000)
{
ptc a[1];
memcpy (a, a0001, sizeof (ac));
memset (a->z, 0, sizeof (bn256));
a->z->word[0] = 1;
power_2 (a0010, a, 63);
power_2 (a0100, a, 63);
power_2 (a1000, a, 63);
print_table (a0001, a0010, a0100, a1000);
}
#endif
int
main (int argc, char *argv[])
{
#ifdef TESTING_EDDSA
uint8_t hash[64];
bn256 a[1];
uint8_t r_s[64];
bn256 pk[1];
bn256 *r, *s;
const bn256 sk[1] = {
{{ 0x9db1619d, 0x605afdef, 0xf44a84ba, 0xc42cec92,
0x69c54944, 0x1969327b, 0x03ac3b70, 0x607fae1c }} };
const bn256 r_expected[1] = {
{{ 0x004356e5, 0x72ac60c3, 0xcce28690, 0x8a826e80,
0x1e7f8784, 0x74d9e5b8, 0x65e073d8, 0x55014922 }} };
const bn256 s_expected[1] = {
{{ 0x1582b85f, 0xac3ba390, 0x70391ec6, 0x6bb4f91c,
0xf0f55bd2, 0x24be5b59, 0x43415165, 0x0b107a8e }} };
r = (bn256 *)r_s;
s = (bn256 *)(r_s+32);
sha512 ((uint8_t *)sk, sizeof (bn256), hash);
hash[0] &= 248;
hash[31] &= 127;
hash[31] |= 64;
memcpy (a, hash, sizeof (bn256));
eddsa_public_key_25519 (pk, a);
eddsa_sign_25519 ((const uint8_t *)"", 0, r_s, a, hash+32, pk);
if (memcmp (r, r_expected, sizeof (bn256)) != 0
|| memcmp (s, s_expected, sizeof (bn256)) != 0)
{
print_bn256 (r);
print_bn256 (s);
return 1;
}
#else
ac a0001[1], a0010[1], a0100[1], a1000[1];
ptc a[1];
memcpy (a, G, sizeof (ptc));
ptc_to_ac_25519 (a0001, a);
compute_and_print_table (a0001, a0010, a0100, a1000);
memcpy (a, a0001, sizeof (ac));
memset (a->z, 0, sizeof (bn256));
a->z->word[0] = 1;
power_2 (a0001, a, 21);
compute_and_print_table (a0001, a0010, a0100, a1000);
memcpy (a, a0001, sizeof (ac));
memset (a->z, 0, sizeof (bn256));
a->z->word[0] = 1;
power_2 (a0001, a, 21);
compute_and_print_table (a0001, a0010, a0100, a1000);
#endif
return 0;
}
#endif

232
src/ecc-mont.c Normal file
View File

@@ -0,0 +1,232 @@
/* -*- coding: utf-8 -*-
* ecc-mont.c - Elliptic curve computation for
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
*
* Copyright (C) 2014, 2015 Free Software Initiative of Japan
* 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 <stdlib.h>
#include "bn.h"
#include "mod25638.h"
#include "mod.h"
/*
* References:
*
* [1] D. J. Bernstein. Curve25519: new Diffie-Hellman speed records.
* Proceedings of PKC 2006, to appear.
* http://cr.yp.to/papers.html#curve25519. Date: 2006.02.09.
*
* [2] D. J. Bernstein. Can we avoid tests for zero in fast
* elliptic-curve arithmetic?
* http://cr.yp.to/papers.html#curvezero. Date: 2006.07.26.
*
*/
/*
* IMPLEMENTATION NOTE
*
* (0) We assume that the processor has no cache, nor branch target
* prediction. Thus, we don't avoid indexing by secret value.
* We don't avoid conditional jump if both cases have same timing,
* either.
*
* (1) We use Radix-32 field arithmetic. It's a representation like
* 2^256-38, but it's more redundant. For example, "1" can be
* represented in three ways in 256-bit: 1, 2^255-18, and
* 2^256-37.
*
* (2) We use Montgomery double-and-add.
*
*/
#ifndef BN256_C_IMPLEMENTATION
#define ASM_IMPLEMENTATION 1
#endif
/*
*
* 121665 = 0x1db41
* 1 1101 1011 0100 0001
*/
static void
mod25638_mul_121665 (bn256 *x, const bn256 *a)
{
#if ASM_IMPLEMENTATION
#include "muladd_256.h"
const uint32_t *s;
uint32_t *d;
uint32_t w;
uint32_t c;
s = a->word;
d = x->word;
memset (d, 0, sizeof (bn256));
w = 121665;
MULADD_256_ASM (s, d, w, c);
#else
uint32_t c, c1;
bn256 m[1];
c = c1 = bn256_shift (m, a, 6); c += bn256_add (x, a, m);
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
c1 <<= 2; c1 |= bn256_shift (m, m, 2); c = c + c1 + bn256_add (x, x, m);
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
c1 <<= 1; c1 |= bn256_shift (m, m, 1); c = c + c1 + bn256_add (x, x, m);
#endif
c = bn256_add_uint (x, x, c*38);
x->word[0] += c * 38;
}
typedef struct
{
bn256 x[1];
bn256 z[1];
} pt;
/**
* @brief Process Montgomery double-and-add
*
* With Q0, Q1, DIF (= Q0 - Q1), compute PRD = 2Q0, SUM = Q0 + Q1
* Q0 and Q1 are clobbered.
*
*/
static void
mont_d_and_a (pt *prd, pt *sum, pt *q0, pt *q1, const bn256 *dif_x)
{
mod25638_add (sum->x, q1->x, q1->z);
mod25638_sub (q1->z, q1->x, q1->z);
mod25638_add (prd->x, q0->x, q0->z);
mod25638_sub (q0->z, q0->x, q0->z);
mod25638_mul (q1->x, q0->z, sum->x);
mod25638_mul (q1->z, prd->x, q1->z);
mod25638_sqr (q0->x, prd->x);
mod25638_sqr (q0->z, q0->z);
mod25638_add (sum->x, q1->x, q1->z);
mod25638_sub (q1->z, q1->x, q1->z);
mod25638_mul (prd->x, q0->x, q0->z);
mod25638_sub (q0->z, q0->x, q0->z);
mod25638_sqr (sum->x, sum->x);
mod25638_sqr (sum->z, q1->z);
mod25638_mul_121665 (prd->z, q0->z);
mod25638_mul (sum->z, sum->z, dif_x);
mod25638_add (prd->z, q0->x, prd->z);
mod25638_mul (prd->z, prd->z, q0->z);
}
/**
* @brief RES = x-coordinate of [n]Q
*
* @param N Scalar N (three least significant bits are 000)
* @param Q_X x-coordinate of Q
*
*/
static void
compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
{
int i, j;
pt p0[1], p1[1], p0_[1], p1_[1];
/* P0 = O = (1:0) */
memset (p0->x, 0, sizeof (bn256));
p0->x->word[0] = 1;
memset (p0->z, 0, sizeof (bn256));
/* P1 = (X:1) */
memcpy (p1->x, q_x, sizeof (bn256));
memset (p1->z, 0, sizeof (bn256));
p1->z->word[0] = 1;
for (i = 0; i < 8; i++)
{
uint32_t u = n->word[7-i];
for (j = 0; j < 16; j++)
{
pt *q0, *q1;
pt *sum_n, *prd_n;
if ((u & 0x80000000))
q0 = p1, q1 = p0, sum_n = p0_, prd_n = p1_;
else
q0 = p0, q1 = p1, sum_n = p1_, prd_n = p0_;
mont_d_and_a (prd_n, sum_n, q0, q1, q_x);
if ((u & 0x40000000))
q0 = p1_, q1 = p0_, sum_n = p0, prd_n = p1;
else
q0 = p0_, q1 = p1_, sum_n = p1, prd_n = p0;
mont_d_and_a (prd_n, sum_n, q0, q1, q_x);
u <<= 2;
}
}
/* We know the LSB of N is always 0. Thus, result is always in P0. */
/*
* p0->z may be zero here, but our mod_inv doesn't raise error for 0,
* but returns 0 (like the implementation of z^(p-2)), thus, RES will
* be 0 in that case, which is correct value.
*/
mod_inv (res, p0->z, p25519);
mod25638_mul (res, res, p0->x);
mod25519_reduce (res);
}
uint8_t *
ecdh_compute_public_25519 (const uint8_t *key_data)
{
uint8_t *p;
bn256 gx[1];
bn256 k[1];
memset (gx, 0, sizeof (bn256));
gx[0].word[0] = 9; /* Gx = 9 */
memcpy (k, key_data, sizeof (bn256));
p = (uint8_t *)malloc (sizeof (bn256));
if (p == NULL)
return NULL;
compute_nQ ((bn256 *)p, k, gx);
return p;
}
int
ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data)
{
bn256 q_x[1];
bn256 k[1];
bn256 shared[1];
memcpy (q_x, input, sizeof (bn256));
memcpy (k, key_data, sizeof (bn256));
compute_nQ (shared, k, q_x);
memcpy (output, shared, sizeof (bn256));
return 0;
}

398
src/ecc.c Normal file
View File

@@ -0,0 +1,398 @@
/* -*- coding: utf-8 -*-
* ecc.c - Elliptic curve over GF(prime)
*
* Copyright (C) 2011, 2013, 2014, 2015
* 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);
#ifndef 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, P);
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
}
/**
* @brief Check if a secret d0 is valid or not
*
* @param D0 scalar D0: secret
* @param D1 scalar D1: secret candidate N-D0
*
* Return 0 on error.
* Return -1 when D1 should be used as the secret
* Return 1 when D0 should be used as the secret
*/
int
FUNC(check_secret) (const bn256 *d0, bn256 *d1)
{
ac Q0[1], Q1[1];
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) != 0)
/* == 0 or >= N, it's not valid. */
return 0;
FUNC(compute_kG) (Q0, d0);
FUNC(compute_kG) (Q1, d1);
/*
* Jivsov compliant key check
*/
return bn256_cmp (Q1[0].y, Q0[0].y);
}

7
src/field-group-select.h Normal file
View 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)

View File

@@ -1,7 +1,7 @@
/*
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
*
* Copyright (C) 2010, 2011, 2012, 2013
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@@ -35,7 +35,6 @@
#include "config.h"
#include "board.h"
#include "sys.h"
#include "gnuk.h"
@@ -57,13 +56,17 @@
* _data_pool
* <two pages>
* _keystore_pool
* three flash pages for keystore (single: 512-byte (p, q and N))
* Three flash pages for keystore
* a page contains a key data of:
* For RSA-2048: 512-byte (p, q and N)
* For RSA-4096: 1024-byte (p, q and N)
* For ECDSA/ECDH and EdDSA, there are padding after public key
*/
#define KEY_SIZE 512 /* P, Q and N */
#define FLASH_DATA_POOL_HEADER_SIZE 2
#define FLASH_DATA_POOL_SIZE (FLASH_PAGE_SIZE*2)
#define FLASH_KEYSTORE_SIZE (FLASH_PAGE_SIZE*3)
#define FLASH_DATA_POOL_SIZE (flash_page_size*2)
static uint16_t flash_page_size;
static const uint8_t *data_pool;
extern uint8_t _keystore_pool;
@@ -72,34 +75,117 @@ static uint8_t *last_p;
/* The first halfword is generation for the data page (little endian) */
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
0x01, 0x00, 0xff, 0xff
0x00, 0x00, 0xff, 0xff
};
/* Linker set this symbol */
extern uint8_t _data_pool;
static int key_available_at (const uint8_t *k, int key_size)
{
int i;
for (i = 0; i < key_size; i++)
if (k[i])
break;
if (i == key_size) /* It's ZERO. Released key. */
return 0;
for (i = 0; i < key_size; i++)
if (k[i] != 0xff)
break;
if (i == key_size) /* It's FULL. Unused key. */
return 0;
return 1;
}
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
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);
uint16_t *gen1_p;
flash_page_size = 1024;
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
flash_page_size = 2048;
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
data_pool = &_data_pool;
/* Check data pool generation and choose the page */
gen0 = *gen0_p;
gen1 = *gen1_p;
if (gen0 == 0xffff && gen1 == 0xffff)
/* It's terminated. */
return NULL;
if (gen0 == 0xffff)
data_pool = &_data_pool + FLASH_PAGE_SIZE;
/* Use another page if a page is erased. */
data_pool = &_data_pool + flash_page_size;
else if (gen1 == 0xffff)
/* Or use different page if another page is erased. */
data_pool = &_data_pool;
else if (gen1 > gen0)
data_pool = &_data_pool + FLASH_PAGE_SIZE;
else
data_pool = &_data_pool;
else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0)
/* When both pages have valid header, use newer page. */
data_pool = &_data_pool + flash_page_size;
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
}
static uint8_t *flash_key_getpage (enum kind_of_key kk);
void
flash_terminate (void)
{
int i;
for (i = 0; i < 3; i++)
flash_erase_page ((uint32_t)flash_key_getpage (i));
flash_erase_page ((uint32_t)&_data_pool);
flash_erase_page ((uint32_t)(&_data_pool + flash_page_size));
data_pool = &_data_pool;
last_p = &_data_pool + FLASH_DATA_POOL_HEADER_SIZE;
}
void
flash_activate (void)
{
flash_program_halfword ((uint32_t)&_data_pool, 0);
}
void
flash_init_keys (void)
{
const uint8_t *p;
int i;
/* For each key, find its address. */
p = &_keystore_pool;
for (i = 0; i < 3; i++)
{
const uint8_t *k;
int key_size = gpg_get_algo_attr_key_size (i, GPG_KEY_STORAGE);
kd[i].pubkey = NULL;
for (k = p; k < p + flash_page_size; k += key_size)
if (key_available_at (k, key_size))
{
int prv_len = gpg_get_algo_attr_key_size (i, GPG_KEY_PRIVATE);
kd[i].pubkey = k + prv_len;
break;
}
p += flash_page_size;
}
}
/*
* Flash data pool managenent
*
@@ -114,6 +200,7 @@ flash_init (void)
* 123-counter
* 14-bit counter
* bool object
* small enum
*
* Format of a Data Object:
* NR: 8-bit tag_number
@@ -140,26 +227,30 @@ flash_copying_gc (void)
if (data_pool == &_data_pool)
{
src = &_data_pool;
dst = &_data_pool + FLASH_PAGE_SIZE;
dst = &_data_pool + flash_page_size;
}
else
{
src = &_data_pool + FLASH_PAGE_SIZE;
src = &_data_pool + flash_page_size;
dst = &_data_pool;
}
generation = *(uint16_t *)src;
data_pool = dst;
gpg_data_copy (data_pool + FLASH_DATA_POOL_HEADER_SIZE);
if (generation == 0xfffe)
generation = 0;
else
generation++;
flash_program_halfword ((uint32_t)dst, generation);
flash_erase_page ((uint32_t)src);
flash_program_halfword ((uint32_t)dst, generation+1);
return 0;
}
static int
is_data_pool_full (size_t size)
{
return last_p + size > data_pool + FLASH_PAGE_SIZE;
return last_p + size > data_pool + flash_page_size;
}
static uint8_t *
@@ -269,34 +360,41 @@ flash_do_release (const uint8_t *do_data)
}
uint8_t *
flash_key_alloc (void)
static uint8_t *
flash_key_getpage (enum kind_of_key kk)
{
uint8_t *k;
int i;
/* There is a page for each KK. */
return &_keystore_pool + (flash_page_size * kk);
}
/* Seek empty keystore. */
k = &_keystore_pool;
while (k < &_keystore_pool + FLASH_KEYSTORE_SIZE)
uint8_t *
flash_key_alloc (enum kind_of_key kk)
{
uint8_t *k, *k0 = flash_key_getpage (kk);
int i;
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
/* Seek free space in the page. */
for (k = k0; k < k0 + flash_page_size; k += key_size)
{
const uint32_t *p = (const uint32_t *)k;
for (i = 0; i < KEY_SIZE/4; i++)
for (i = 0; i < key_size/4; i++)
if (p[i] != 0xffffffff)
break;
if (i == KEY_SIZE/4) /* Yes, it's empty. */
if (i == key_size/4) /* Yes, it's empty. */
return k;
k += KEY_SIZE;
}
/* Should not happen as we have enough space, but just in case. */
/* Should not happen as we have enough free space all time, but just
in case. */
return NULL;
}
int
flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
flash_key_write (uint8_t *key_addr,
const uint8_t *key_data, int key_data_len,
const uint8_t *pubkey, int pubkey_len)
{
uint16_t hw;
@@ -304,7 +402,7 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
int i;
addr = (uint32_t)key_addr;
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
for (i = 0; i < key_data_len/2; i ++)
{
hw = key_data[i*2] | (key_data[i*2+1]<<8);
if (flash_program_halfword (addr, hw) != 0)
@@ -324,14 +422,14 @@ flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
}
static int
flash_check_all_other_keys_released (const uint8_t *key_addr)
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
{
uint32_t start = (uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1);
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
const uint32_t *p = (const uint32_t *)start;
while (p < (const uint32_t *)(start + FLASH_PAGE_SIZE))
while (p < (const uint32_t *)(start + flash_page_size))
if (p == (const uint32_t *)key_addr)
p += KEY_SIZE/4;
p += key_size/4;
else
if (*p)
return 0;
@@ -342,22 +440,28 @@ flash_check_all_other_keys_released (const uint8_t *key_addr)
}
static void
flash_key_fill_zero_as_released (uint8_t *key_addr)
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
{
int i;
uint32_t addr = (uint32_t)key_addr;
for (i = 0; i < KEY_SIZE/2; i++)
for (i = 0; i < key_size/2; i++)
flash_program_halfword (addr + i*2, 0);
}
void
flash_key_release (uint8_t *key_addr)
flash_key_release (uint8_t *key_addr, int key_size)
{
if (flash_check_all_other_keys_released (key_addr))
flash_erase_page (((uint32_t)key_addr & ~(FLASH_PAGE_SIZE - 1)));
if (flash_check_all_other_keys_released (key_addr, key_size))
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
else
flash_key_fill_zero_as_released (key_addr);
flash_key_fill_zero_as_released (key_addr, key_size);
}
void
flash_key_release_page (enum kind_of_key kk)
{
flash_erase_page ((uint32_t)flash_key_getpage (kk));
}
@@ -425,6 +529,38 @@ flash_bool_write (uint8_t nr)
}
void
flash_enum_clear (const uint8_t **addr_p)
{
flash_bool_clear (addr_p);
}
void
flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v)
{
uint16_t hw = nr | (v << 8);
flash_program_halfword ((uint32_t)p, hw);
}
const uint8_t *
flash_enum_write (uint8_t nr, uint8_t v)
{
uint8_t *p;
uint16_t hw = nr | (v << 8);
p = flash_data_pool_allocate (2);
if (p == NULL)
{
DEBUG_INFO ("enum allocation failure.\r\n");
return NULL;
}
flash_program_halfword ((uint32_t)p, hw);
return p;
}
int
flash_cnt123_get_value (const uint8_t *p)
{
@@ -525,9 +661,8 @@ flash_erase_binary (uint8_t file_id)
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
{
flash_erase_page ((uint32_t)p);
#if FLASH_CH_CERTIFICATE_SIZE > FLASH_PAGE_SIZE
flash_erase_page ((uint32_t)p + FLASH_PAGE_SIZE);
#endif
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
flash_erase_page ((uint32_t)p + flash_page_size);
}
return 0;
@@ -552,7 +687,7 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
}
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
{
maxsize = KEY_CONTENT_LEN;
maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
if (len == 0 && offset == 0)
{ /* This means removal of update key. */

View File

@@ -12,8 +12,8 @@ struct apdu {
/* response APDU */
uint16_t sw;
uint8_t *res_apdu_data;
uint16_t res_apdu_data_len;
uint8_t *res_apdu_data;
};
extern struct apdu apdu;
@@ -22,26 +22,29 @@ extern struct apdu apdu;
#define CARD_CHANGE_REMOVE 1
#define CARD_CHANGE_TOGGLE 2
void ccid_card_change_signal (int how);
void ccid_usb_reset (int);
/* CCID thread */
#define EV_RX_DATA_READY (1) /* USB Rx data available */
#define EV_EXEC_FINISHED (2) /* OpenPGP Execution finished */
#define EV_TX_FINISHED (4) /* CCID Tx finished */
#define EV_CARD_CHANGE (8)
#define EV_RX_DATA_READY 1 /* USB Rx data available */
#define EV_EXEC_FINISHED 2 /* OpenPGP Execution finished */
#define EV_TX_FINISHED 4 /* CCID Tx finished */
#define EV_CARD_CHANGE 8
#define EV_USB_SET_INTERFACE 16
#define EV_USB_DEVICE_RESET 32
/* OpenPGPcard thread */
#define EV_PINPAD_INPUT_DONE (1)
#define EV_EXIT (2)
#define EV_CMD_AVAILABLE (4)
#define EV_VERIFY_CMD_AVAILABLE (8)
#define EV_MODIFY_CMD_AVAILABLE (16)
#define EV_PINPAD_INPUT_DONE 1
#define EV_EXIT 2
#define EV_CMD_AVAILABLE 4
#define EV_VERIFY_CMD_AVAILABLE 8
#define EV_MODIFY_CMD_AVAILABLE 16
/* Maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
#define MAX_CMD_APDU_DATA_SIZE (22+4+128+128) /* without header */
/* Maximum res apdu data is public key 5+9+256 (gpg_do_public_key) */
#define MAX_RES_APDU_DATA_SIZE (5+9+256) /* without trailer */
/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */
#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */
/* Maximum res apdu data is public key 5+9+512 (gpg_do_public_key) */
#define MAX_RES_APDU_DATA_SIZE (5+9+512) /* without trailer */
#define ICC_MSG_HEADER_SIZE 10
#define CCID_MSG_HEADER_SIZE 10
#define res_APDU apdu.res_apdu_data
#define res_APDU_size apdu.res_apdu_data_len
@@ -49,21 +52,21 @@ void ccid_card_change_signal (int how);
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
#define USB_LL_BUF_SIZE 64
enum icc_state
{
ICC_STATE_NOCARD, /* No card available */
ICC_STATE_START, /* Initial */
ICC_STATE_WAIT, /* Waiting APDU */
enum ccid_state {
CCID_STATE_NOCARD, /* No card available */
CCID_STATE_START, /* Initial */
CCID_STATE_WAIT, /* Waiting APDU */
/* Busy1, Busy2, Busy3, Busy5 */
ICC_STATE_EXECUTE, /* Busy4 */
ICC_STATE_RECEIVE, /* APDU Received Partially */
ICC_STATE_SEND, /* APDU Sent Partially */
CCID_STATE_EXECUTE, /* Busy4 */
CCID_STATE_RECEIVE, /* APDU Received Partially */
CCID_STATE_SEND, /* APDU Sent Partially */
ICC_STATE_EXITED, /* ICC Thread Terminated */
ICC_STATE_EXEC_REQUESTED, /* Exec requested */
CCID_STATE_EXITED, /* ICC Thread Terminated */
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
};
extern enum icc_state *icc_state_p;
extern enum ccid_state *const ccid_state_p;
extern volatile uint8_t auth_status;
#define AC_NONE_AUTHORIZED 0x00
@@ -76,40 +79,50 @@ extern volatile uint8_t auth_status;
#define PW_ERR_PW1 0
#define PW_ERR_RC 1
#define PW_ERR_PW3 2
extern int gpg_pw_get_retry_counter (int who);
extern int gpg_pw_locked (uint8_t which);
extern void gpg_pw_reset_err_counter (uint8_t which);
extern void gpg_pw_increment_err_counter (uint8_t which);
int gpg_pw_get_retry_counter (int who);
int gpg_pw_locked (uint8_t which);
void gpg_pw_reset_err_counter (uint8_t which);
void gpg_pw_increment_err_counter (uint8_t which);
extern int ac_check_status (uint8_t ac_flag);
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
extern int verify_other (const uint8_t *pw, int pw_len);
extern int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
int pw_len_known, const uint8_t *ks_pw1, int saveks);
extern int verify_admin (const uint8_t *pw, int pw_len);
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks_pw3, int saveks);
int ac_check_status (uint8_t ac_flag);
int verify_pso_cds (const uint8_t *pw, int pw_len);
int verify_other (const uint8_t *pw, int pw_len);
int verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len,
int pw_len_known, const uint8_t *ks_pw1, int saveks);
int verify_admin (const uint8_t *pw, int pw_len);
int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
const uint8_t *ks_pw3, int saveks);
extern void ac_reset_pso_cds (void);
extern void ac_reset_other (void);
extern void ac_reset_admin (void);
extern void ac_fini (void);
void ac_reset_pso_cds (void);
void ac_reset_other (void);
void ac_reset_admin (void);
void ac_fini (void);
extern void set_res_sw (uint8_t sw1, uint8_t sw2);
void set_res_sw (uint8_t sw1, uint8_t sw2);
extern uint8_t file_selection;
extern const uint8_t historical_bytes[];
extern uint16_t data_objects_number_of_bytes;
#define CHALLENGE_LEN 32
extern void gpg_data_scan (const uint8_t *p);
extern void gpg_data_copy (const uint8_t *p);
extern void gpg_do_get_data (uint16_t tag, int with_tag);
extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
extern void gpg_do_public_key (uint8_t kk_byte);
extern void gpg_do_keygen (uint8_t kk_byte);
void gpg_data_scan (const uint8_t *p);
void gpg_data_copy (const uint8_t *p);
void gpg_do_terminate (void);
void gpg_do_get_data (uint16_t tag, int with_tag);
void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
void gpg_do_public_key (uint8_t kk_byte);
void gpg_do_keygen (uint8_t kk_byte);
extern const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
/* Constants: algo+size */
#define ALGO_RSA4K 0
#define ALGO_NISTP256R1 1
#define ALGO_SECP256K1 2
#define ALGO_ED25519 3
#define ALGO_CURVE25519 4
#define ALGO_RSA2K 255
enum kind_of_key {
GPG_KEY_FOR_SIGNING = 0,
@@ -117,17 +130,31 @@ enum kind_of_key {
GPG_KEY_FOR_AUTHENTICATION,
};
extern const uint8_t *flash_init (void);
extern void flash_do_release (const uint8_t *);
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
extern uint8_t *flash_key_alloc (void);
extern void flash_key_release (uint8_t *);
extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
const uint8_t *pubkey, int pubkey_len);
extern void flash_set_data_pool_last (const uint8_t *p);
extern void flash_clear_halfword (uint32_t addr);
extern void flash_increment_counter (uint8_t counter_tag_nr);
extern void flash_reset_counter (uint8_t counter_tag_nr);
enum size_of_key {
GPG_KEY_STORAGE = 0, /* PUBKEY + PRVKEY rounded to 2^N */
GPG_KEY_PUBLIC,
GPG_KEY_PRIVATE,
};
int gpg_get_algo_attr (enum kind_of_key kk);
int gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s);
const uint8_t *flash_init (void);
void flash_terminate (void);
void flash_activate (void);
void flash_init_keys (void);
void flash_do_release (const uint8_t *);
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
uint8_t *flash_key_alloc (enum kind_of_key);
void flash_key_release (uint8_t *, int);
void flash_key_release_page (enum kind_of_key);
int flash_key_write (uint8_t *key_addr,
const uint8_t *key_data, int key_data_len,
const uint8_t *pubkey, int pubkey_len);
void flash_set_data_pool_last (const uint8_t *p);
void flash_clear_halfword (uint32_t addr);
void flash_increment_counter (uint8_t counter_tag_nr);
void flash_reset_counter (uint8_t counter_tag_nr);
#define FILEID_SERIAL_NO 0
#define FILEID_UPDATE_KEY_0 1
@@ -135,31 +162,28 @@ extern void flash_reset_counter (uint8_t counter_tag_nr);
#define FILEID_UPDATE_KEY_2 3
#define FILEID_UPDATE_KEY_3 4
#define FILEID_CH_CERTIFICATE 5
extern int flash_erase_binary (uint8_t file_id);
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
int flash_erase_binary (uint8_t file_id);
int flash_write_binary (uint8_t file_id, const uint8_t *data,
uint16_t len, uint16_t offset);
#define FLASH_CH_CERTIFICATE_SIZE 2048
/* Linker set these two symbols */
extern uint8_t ch_certificate_start;
extern uint8_t random_bits_start;
#define KEY_CONTENT_LEN 256 /* p and q */
#define FIRMWARE_UPDATE_KEY_CONTENT_LEN 256 /* RSA-2048 (p and q) */
#define INITIAL_VECTOR_SIZE 16
#define DATA_ENCRYPTION_KEY_SIZE 16
/* encrypted data content */
struct key_data {
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
};
#define MAX_PRVKEY_LEN 512 /* Maximum is the case for RSA 4096-bit. */
struct key_data_internal {
uint32_t data[KEY_CONTENT_LEN/4]; /* p and q */
uint32_t checksum[DATA_ENCRYPTION_KEY_SIZE/4];
struct key_data {
const uint8_t *pubkey; /* Pointer to public key */
uint8_t data[MAX_PRVKEY_LEN]; /* decrypted private key data content */
};
struct prvkey_data {
const uint8_t *key_addr;
/*
* IV: Initial Vector
*/
@@ -202,29 +226,30 @@ void s2k (const unsigned char *salt, size_t slen,
#define KS_GET_SALT(ks) (ks + KEYSTRING_PASSLEN_SIZE)
#define KS_GET_KEYSTRING(ks) (ks + KS_META_SIZE)
extern void gpg_do_clear_prvkey (enum kind_of_key kk);
extern int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
extern int gpg_do_chks_prvkey (enum kind_of_key kk,
int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks);
void gpg_do_clear_prvkey (enum kind_of_key kk);
int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
int gpg_do_chks_prvkey (enum kind_of_key kk,
int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks);
extern int gpg_change_keystring (int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks);
int gpg_change_keystring (int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks);
extern struct key_data kd[3];
#ifdef DEBUG
void stdout_init (void);
#define DEBUG_MORE 1
/*
* Debug functions in debug.c
*/
extern void put_byte (uint8_t b);
extern void put_byte_with_no_nl (uint8_t b);
extern void put_short (uint16_t x);
extern void put_word (uint32_t x);
extern void put_int (uint32_t x);
extern void put_string (const char *s);
extern void put_binary (const char *s, int len);
void put_byte (uint8_t b);
void put_byte_with_no_nl (uint8_t b);
void put_short (uint16_t x);
void put_word (uint32_t x);
void put_int (uint32_t x);
void put_string (const char *s);
void put_binary (const char *s, int len);
#define DEBUG_INFO(msg) put_string (msg)
#define DEBUG_WORD(w) put_word (w)
@@ -239,23 +264,41 @@ extern void put_binary (const char *s, int len);
#define DEBUG_BINARY(s,len)
#endif
extern int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *);
extern uint8_t *modulus_calc (const uint8_t *, int);
extern int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
extern int rsa_verify (const uint8_t *pubkey, const uint8_t *hash,
const uint8_t *signature);
extern uint8_t *rsa_genkey (void);
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
uint8_t *modulus_calc (const uint8_t *, int);
int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *,
unsigned int *);
int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *);
uint8_t *rsa_genkey (int);
extern int ecdsa_sign (const uint8_t *hash, uint8_t *output,
const struct key_data *kd);
extern uint8_t *ecdsa_compute_public (const uint8_t *key_data);
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
extern const uint8_t *gpg_do_read_simple (uint8_t);
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
extern void gpg_increment_digital_signature_counter (void);
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
const uint8_t *key_data);
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1);
int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
const uint8_t *sk_a, const uint8_t *seed,
const uint8_t *pk);
uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
const uint8_t *key_data);
const uint8_t *gpg_do_read_simple (uint8_t);
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
void gpg_increment_digital_signature_counter (void);
extern void fatal (uint8_t code) __attribute__ ((noreturn));
void fatal (uint8_t code) __attribute__ ((noreturn));
#define FATAL_FLASH 1
#define FATAL_RANDOM 2
@@ -263,7 +306,6 @@ extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
extern uint8_t admin_authorized;
/*** Flash memory tag values ***/
#define NR_NONE 0x00
/* Data objects */
/*
* Representation of data object:
@@ -271,28 +313,27 @@ extern uint8_t admin_authorized;
* <-1 halfword-> <--len/2 halfwords->
* <-tag-><-len-> <---data content--->
*/
#define NR_DO__FIRST__ 0x01
#define NR_DO_SEX 0x01
#define NR_DO_FP_SIG 0x02
#define NR_DO_FP_DEC 0x03
#define NR_DO_FP_AUT 0x04
#define NR_DO_CAFP_1 0x05
#define NR_DO_CAFP_2 0x06
#define NR_DO_CAFP_3 0x07
#define NR_DO_KGTIME_SIG 0x08
#define NR_DO_KGTIME_DEC 0x09
#define NR_DO_KGTIME_AUT 0x0a
#define NR_DO_LOGIN_DATA 0x0b
#define NR_DO_URL 0x0c
#define NR_DO_NAME 0x0d
#define NR_DO_LANGUAGE 0x0e
#define NR_DO_PRVKEY_SIG 0x0f
#define NR_DO_PRVKEY_DEC 0x10
#define NR_DO_PRVKEY_AUT 0x11
#define NR_DO_KEYSTRING_PW1 0x12
#define NR_DO_KEYSTRING_RC 0x13
#define NR_DO_KEYSTRING_PW3 0x14
#define NR_DO__LAST__ 21 /* == 0x15 */
#define NR_DO_SEX 0x00
#define NR_DO_FP_SIG 0x01
#define NR_DO_FP_DEC 0x02
#define NR_DO_FP_AUT 0x03
#define NR_DO_CAFP_1 0x04
#define NR_DO_CAFP_2 0x05
#define NR_DO_CAFP_3 0x06
#define NR_DO_KGTIME_SIG 0x07
#define NR_DO_KGTIME_DEC 0x08
#define NR_DO_KGTIME_AUT 0x09
#define NR_DO_LOGIN_DATA 0x0a
#define NR_DO_URL 0x0b
#define NR_DO_NAME 0x0c
#define NR_DO_LANGUAGE 0x0d
#define NR_DO_PRVKEY_SIG 0x0e
#define NR_DO_PRVKEY_DEC 0x0f
#define NR_DO_PRVKEY_AUT 0x10
#define NR_DO_KEYSTRING_PW1 0x11
#define NR_DO_KEYSTRING_RC 0x12
#define NR_DO_KEYSTRING_PW3 0x13
#define NR_DO__LAST__ 20 /* == 0x14 */
/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */
/*
* Representation of 14-bit counter:
@@ -311,7 +352,10 @@ extern uint8_t admin_authorized;
* 1023: 0xc3ff
*/
#define NR_COUNTER_DS_LSB 0xc0 /* ..0xc3 */
/* 8-bit int or Boolean objects: Recorded in flash memory by 1-halfword (2-byte) */
/*
* Boolean object, small enum, or 8-bit integer:
* Recorded in flash memory by 1-halfword (2-byte)
*/
/*
* Representation of Boolean object:
* 0: No record in flash memory
@@ -319,7 +363,20 @@ extern uint8_t admin_authorized;
*/
#define NR_BOOL_PW1_LIFETIME 0xf0
/*
* NR_BOOL_SOMETHING, NR_UINT_SOMETHING could be here... Use 0xf?
* Representation of algorithm attribute object:
* RSA-2048: No record in flash memory
* RSA-4096: 0xf?00
* ECC p256r1: 0xf?01
* ECC p256k1: 0xf?02
* ECC Ed25519: 0xf?03
* ECC Curve25519: 0xf?04
* where <?> == 1 (signature), 2 (decryption) or 3 (authentication)
*/
#define NR_KEY_ALGO_ATTR_SIG 0xf1
#define NR_KEY_ALGO_ATTR_DEC 0xf2
#define NR_KEY_ALGO_ATTR_AUT 0xf3
/*
* NR_UINT_SOMETHING could be here... Use 0xf[456789abcd]
*/
/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */
/*
@@ -348,41 +405,47 @@ extern uint8_t admin_authorized;
extern const uint8_t openpgpcard_aid[14];
extern void flash_bool_clear (const uint8_t **addr_p);
extern const uint8_t *flash_bool_write (uint8_t nr);
extern int flash_cnt123_get_value (const uint8_t *p);
extern void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p);
extern void flash_cnt123_clear (const uint8_t **addr_p);
extern void flash_put_data (uint16_t hw);
extern void flash_warning (const char *msg);
void flash_bool_clear (const uint8_t **addr_p);
const uint8_t *flash_bool_write (uint8_t nr);
void flash_enum_clear (const uint8_t **addr_p);
const uint8_t *flash_enum_write (uint8_t nr, uint8_t v);
int flash_cnt123_get_value (const uint8_t *p);
void flash_cnt123_increment (uint8_t which, const uint8_t **addr_p);
void flash_cnt123_clear (const uint8_t **addr_p);
void flash_put_data (uint16_t hw);
void flash_warning (const char *msg);
extern void flash_put_data_internal (const uint8_t *p, uint16_t hw);
extern void flash_bool_write_internal (const uint8_t *p, int nr);
extern void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
void flash_put_data_internal (const uint8_t *p, uint16_t hw);
void flash_bool_write_internal (const uint8_t *p, int nr);
void flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v);
void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
void flash_do_write_internal (const uint8_t *p, int nr,
const uint8_t *data, int len);
extern const uint8_t gnukStringSerial[];
extern const uint8_t gnuk_string_serial[];
#define LED_ONESHOT (1)
#define LED_TWOSHOTS (2)
#define LED_SHOW_STATUS (4)
#define LED_START_COMMAND (8)
#define LED_FINISH_COMMAND (16)
#define LED_FATAL (32)
extern void led_blink (int spec);
#define LED_ONESHOT 1
#define LED_TWOSHOTS 2
#define LED_SHOW_STATUS 4
#define LED_FATAL 8
#define LED_SYNC 16
#define LED_GNUK_EXEC 32
#define LED_START_COMMAND 64
#define LED_FINISH_COMMAND 128
void led_blink (int spec);
#if defined(PINPAD_SUPPORT)
# if defined(PINPAD_CIR_SUPPORT)
extern void cir_init (void);
void cir_init (void);
# elif defined(PINPAD_DIAL_SUPPORT)
extern void dial_sw_disable (void);
extern void dial_sw_enable (void);
void dial_sw_disable (void);
void dial_sw_enable (void);
# elif defined(PINPAD_DND_SUPPORT)
extern void msc_init (void);
extern void msc_media_insert_change (int available);
extern int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size);
extern int msc_scsi_read (uint32_t lba, const uint8_t **sector_p);
extern void msc_scsi_stop (uint8_t code);
void msc_init (void);
void msc_media_insert_change (int available);
int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size);
int msc_scsi_read (uint32_t lba, const uint8_t **sector_p);
void msc_scsi_stop (uint8_t code);
# endif
#define PIN_INPUT_CURRENT 1
#define PIN_INPUT_NEW 2
@@ -391,7 +454,7 @@ extern void msc_scsi_stop (uint8_t code);
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
extern uint8_t pin_input_len;
extern int pinpad_getline (int msg_code, uint32_t timeout_usec);
int pinpad_getline (int msg_code, uint32_t timeout_usec);
#endif

View File

@@ -1,12 +1,12 @@
/*
* ST32F103 memory setup.
*/
__main_stack_size__ = 0x0100; /* Exception handlers */
__main_stack_size__ = 0x0080; /* Exception handlers */
__process0_stack_size__ = 0x0100; /* main */
__process1_stack_size__ = 0x0140; /* ccid */
__process1_stack_size__ = 0x01a0; /* ccid */
__process2_stack_size__ = 0x0180; /* rng */
__process3_stack_size__ = 0x1600; /* gpg */
__process4_stack_size__ = 0x0100; /* intr: usb */
__process3_stack_size__ = 0x1640; /* gpg */
__process4_stack_size__ = 0; /* --- */
__process5_stack_size__ = @MSC_SIZE@; /* msc */
__process6_stack_size__ = @TIM_SIZE@; /* intr: timer */
__process7_stack_size__ = @EXT_SIZE@; /* intr: ext */
@@ -18,10 +18,6 @@ MEMORY
ram : org = 0x20000000, len = @MEMORY_SIZE@k
}
/* __flash_start__: flash ROM start address regardless of DFU_SUPPORT */
__flash_start__ = 0x08001000;
__flash_end__ = ORIGIN(flash) + LENGTH(flash);
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
@@ -32,18 +28,20 @@ SECTIONS
.sys : ALIGN(4) SUBALIGN(4)
{
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
*(.sys.version)
build/sys.o(.text)
build/sys.o(.text.*)
build/sys.o(.rodata)
build/sys.o(.rodata.*)
. = ALIGN(1024);
*(.sys.0)
*(.sys.1)
*(.sys.2)
_sys = .;
KEEP(*(.vectors))
. = ALIGN(16);
KEEP(*(.sys.version))
KEEP(*(.sys.board_id))
KEEP(*(.sys.board_name))
build/sys-*.o(.text)
build/sys-*.o(.text.*)
build/sys-*.o(.rodata)
build/sys-*.o(.rodata.*)
. = ALIGN(1024);
*(.sys.0)
*(.sys.1)
*(.sys.2)
} > flash0
_text = .;
@@ -64,6 +62,7 @@ SECTIONS
*(.glue_7t)
*(.glue_7)
*(.gcc*)
. = ALIGN(8);
} > flash
.ARM.extab : {*(.ARM.extab* .gnu.linkonce.armextab.*)} > flash

View File

@@ -1,29 +0,0 @@
/* HAL configuration file for ChibiOS/RT */
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
#define HAL_USE_PAL TRUE
#define HAL_USE_ADC FALSE
#define HAL_USE_CAN FALSE
#define HAL_USE_EXT FALSE
#define HAL_USE_GPT FALSE
#define HAL_USE_I2C FALSE
#define HAL_USE_ICU FALSE
#define HAL_USE_MAC FALSE
#define HAL_USE_MMC_SPI FALSE
#define HAL_USE_PWM FALSE
#define HAL_USE_RTC FALSE
#define HAL_USE_SDC FALSE
#define HAL_USE_SERIAL FALSE
#define HAL_USE_SERIAL_USB FALSE
#define HAL_USE_SPI FALSE
#define HAL_USE_UART FALSE
#define HAL_USE_USB FALSE
/* Define manually, as we implement ADC driver by ourselves. */
#define STM32_DMA_REQUIRED 1
#endif /* _HALCONF_H_ */

View File

@@ -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
View 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
View 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
View File

@@ -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
View 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
View 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"

View File

@@ -1,7 +1,8 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -27,7 +28,6 @@
#include <eventflag.h>
#include "config.h"
#include "board.h"
#include "sys.h"
#include "adc.h"
@@ -35,87 +35,12 @@
#include "usb_lld.h"
#include "usb-cdc.h"
#include "random.h"
#include "stm32f103.h"
#include "mcu/stm32f103.h"
#ifdef DEBUG
#include "debug.h"
struct stdout stdout;
static void
stdout_init (void)
{
chopstx_mutex_init (&stdout.m);
chopstx_mutex_init (&stdout.m_dev);
chopstx_cond_init (&stdout.cond_dev);
stdout.connected = 0;
}
void
_write (const char *s, int len)
{
int packet_len;
if (len == 0)
return;
chopstx_mutex_lock (&stdout.m);
chopstx_mutex_lock (&stdout.m_dev);
if (!stdout.connected)
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
do
{
packet_len =
(len < VIRTUAL_COM_PORT_DATA_SIZE) ? len : VIRTUAL_COM_PORT_DATA_SIZE;
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_write (ENDP3, s, packet_len);
chopstx_cond_wait (&stdout.cond_dev, &stdout.m_dev);
chopstx_mutex_unlock (&stdout.m_dev);
s += packet_len;
len -= packet_len;
}
/* Send a Zero-Length-Packet if the last packet is full size. */
while (len != 0 || packet_len == VIRTUAL_COM_PORT_DATA_SIZE);
chopstx_mutex_unlock (&stdout.m);
}
void
EP3_IN_Callback (void)
{
chopstx_mutex_lock (&stdout.m_dev);
chopstx_cond_signal (&stdout.cond_dev);
chopstx_mutex_unlock (&stdout.m_dev);
}
void
EP5_OUT_Callback (void)
{
chopstx_mutex_lock (&stdout.m_dev);
usb_lld_rx_enable (ENDP5);
chopstx_mutex_unlock (&stdout.m_dev);
}
#else
void
_write (const char *s, int size)
{
(void)s;
(void)size;
}
#endif
extern void *USBthread (void *arg);
/*
* main thread does 1-bit LED display output
*/
#define MAIN_TIMEOUT_INTERVAL (5000*1000)
#define LED_TIMEOUT_INTERVAL (75*1000)
#define LED_TIMEOUT_ZERO (25*1000)
#define LED_TIMEOUT_ONE (100*1000)
@@ -126,7 +51,7 @@ extern void *USBthread (void *arg);
static void
device_initialize_once (void)
{
const uint8_t *p = &gnukStringSerial[ID_OFFSET];
const uint8_t *p = &gnuk_string_serial[ID_OFFSET];
if (p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff)
{
@@ -134,12 +59,12 @@ device_initialize_once (void)
* This is the first time invocation.
* Setup serial number by unique device ID.
*/
const uint8_t *u = unique_device_id ();
const uint8_t *u = unique_device_id () + 8;
int i;
for (i = 0; i < 4; i++)
{
uint8_t b = u[i];
uint8_t b = u[3-i];
uint8_t nibble;
nibble = (b >> 4);
@@ -195,70 +120,50 @@ static void display_fatal_code (void)
static uint8_t led_inverted;
static eventmask_t emit_led (int on_time, int off_time)
static void emit_led (int on_time, int off_time)
{
eventmask_t m;
set_led (!led_inverted);
m = eventflag_wait_timeout (&led_event, on_time);
chopstx_usec_wait (on_time);
set_led (led_inverted);
if (m) return m;
if ((m = eventflag_wait_timeout (&led_event, off_time)))
return m;
return 0;
chopstx_usec_wait (off_time);
}
static eventmask_t display_status_code (void)
static void display_status_code (void)
{
enum icc_state icc_state;
eventmask_t m;
enum ccid_state ccid_state = *ccid_state_p;
if (icc_state_p == NULL)
icc_state = ICC_STATE_START;
if (ccid_state == CCID_STATE_START)
emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
else
icc_state = *icc_state_p;
if (icc_state == ICC_STATE_START)
return emit_led (LED_TIMEOUT_ONE, LED_TIMEOUT_STOP);
else
/* OpenPGP card thread running */
/* OpenPGP card thread is running */
{
if ((m = emit_led ((auth_status & AC_ADMIN_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led ((auth_status & AC_OTHER_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led ((auth_status & AC_PSO_CDS_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_INTERVAL)))
return m;
emit_led ((auth_status & AC_ADMIN_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
emit_led ((auth_status & AC_OTHER_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
emit_led ((auth_status & AC_PSO_CDS_AUTHORIZED)?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_INTERVAL);
if (icc_state == ICC_STATE_WAIT)
{
if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP * 2)))
return m;
}
if (ccid_state == CCID_STATE_WAIT)
chopstx_usec_wait (LED_TIMEOUT_STOP * 2);
else
{
if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL)))
return m;
if ((m = emit_led (icc_state == ICC_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO,
LED_TIMEOUT_STOP)))
return m;
chopstx_usec_wait (LED_TIMEOUT_INTERVAL);
emit_led (ccid_state == CCID_STATE_RECEIVE?
LED_TIMEOUT_ONE : LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
}
return 0;
}
}
void
led_blink (int spec)
{
if (spec == LED_START_COMMAND || spec == LED_FINISH_COMMAND)
{
led_inverted = (spec == LED_START_COMMAND);
spec = LED_SYNC;
}
eventflag_signal (&led_event, spec);
}
@@ -279,19 +184,14 @@ calculate_regnual_entry_address (const uint8_t *addr)
return v;
}
extern uint8_t __process1_stack_base__, __process1_stack_size__;
extern uint8_t __process4_stack_base__, __process4_stack_size__;
const uint32_t __stackaddr_ccid = (uint32_t)&__process1_stack_base__;
const size_t __stacksize_ccid = (size_t)&__process1_stack_size__;
const uint32_t __stackaddr_usb = (uint32_t)&__process4_stack_base__;
const size_t __stacksize_usb = (size_t)&__process4_stack_size__;
extern uint8_t __process1_stack_base__[], __process1_stack_size__[];
#define STACK_ADDR_CCID ((uint32_t)__process1_stack_base__)
#define STACK_SIZE_CCID ((uint32_t)__process1_stack_size__)
#define PRIO_CCID 3
#define PRIO_USB 4
#define PRIO_MAIN 5
extern void *usb_intr (void *arg);
extern void *ccid_thread (void *arg);
static void gnuk_malloc_init (void);
@@ -300,16 +200,11 @@ extern uint32_t bDeviceState;
/*
* Entry point.
*
* NOTE: the main function is already a thread in the system on entry.
* See the hwinit1_common function.
*/
int
main (int argc, char *argv[])
{
unsigned int count = 0;
uint32_t entry;
chopstx_t usb_thd;
chopstx_t ccid_thd;
(void)argc;
@@ -322,7 +217,7 @@ main (int argc, char *argv[])
adc_init ();
eventflag_init (&led_event, chopstx_main);
eventflag_init (&led_event);
random_init ();
@@ -330,8 +225,8 @@ main (int argc, char *argv[])
stdout_init ();
#endif
ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid,
__stacksize_ccid, USBthread, NULL);
ccid_thd = chopstx_create (PRIO_CCID, STACK_ADDR_CCID, STACK_SIZE_CCID,
ccid_thread, NULL);
#ifdef PINPAD_CIR_SUPPORT
cir_init ();
@@ -340,8 +235,7 @@ main (int argc, char *argv[])
msc_init ();
#endif
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
usb_intr, NULL);
chopstx_setpriority (PRIO_MAIN);
while (1)
{
@@ -355,56 +249,34 @@ main (int argc, char *argv[])
{
eventmask_t m;
if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED)
break;
m = eventflag_wait_timeout (&led_event, MAIN_TIMEOUT_INTERVAL);
got_it:
count++;
m = eventflag_wait (&led_event);
switch (m)
{
case LED_ONESHOT:
if ((m = emit_led (100*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it;
emit_led (100*1000, LED_TIMEOUT_STOP);
break;
case LED_TWOSHOTS:
if ((m = emit_led (50*1000, 50*1000))) goto got_it;
if ((m = emit_led (50*1000, MAIN_TIMEOUT_INTERVAL))) goto got_it;
emit_led (50*1000, 50*1000);
emit_led (50*1000, LED_TIMEOUT_STOP);
break;
case LED_SHOW_STATUS:
if ((count & 0x07) != 0) continue; /* Display once for eight times */
if ((m = display_status_code ())) goto got_it;
break;
case LED_START_COMMAND:
set_led (1);
led_inverted = 1;
break;
case LED_FINISH_COMMAND:
m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP);
led_inverted = 0;
set_led (0);
if (m)
goto got_it;
display_status_code ();
break;
case LED_FATAL:
display_fatal_code ();
break;
case LED_SYNC:
set_led (led_inverted);
break;
case LED_GNUK_EXEC:
goto exec;
default:
if ((m = emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP)))
goto got_it;
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP);
break;
}
#ifdef DEBUG_MORE
if (stdout.connected && (count % 10) == 0)
{
DEBUG_SHORT (count / 10);
_write ("\r\nThis is Gnuk on STM32F103.\r\n"
"Testing USB driver.\n\n"
"Hello world\r\n\r\n", 30+21+15);
}
#endif
}
exec:
random_fini ();
set_led (1);
@@ -413,24 +285,26 @@ main (int argc, char *argv[])
/* Finish application. */
chopstx_join (ccid_thd, NULL);
chopstx_cancel (usb_thd);
chopstx_join (usb_thd, NULL);
/* Set vector */
SCB->VTOR = (uint32_t)&_regnual_start;
entry = calculate_regnual_entry_address (&_regnual_start);
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
{
extern uint8_t _sys;
uint32_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
uint32_t flash_page_size = 1024; /* 1KiB default */
if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
flash_page_size = 2048; /* It's 2KiB. */
/* Kill DFU */
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
addr += FLASH_PAGE_SIZE)
addr += flash_page_size)
flash_erase_page (addr);
/* copy system service routines */
@@ -452,6 +326,8 @@ main (int argc, char *argv[])
void
fatal (uint8_t code)
{
extern void _write (const char *s, int len);
fatal_code = code;
eventflag_signal (&led_event, LED_FATAL);
_write ("fatal\r\n", 7);

371
src/mod.c
View File

@@ -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.
@@ -27,7 +27,7 @@
/**
* @brief X = A mod B (using MU=(1<<(256)+MU_lower)) (Barret reduction)
*
*
*/
void
mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
@@ -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).
* NOTE: If X==0, it 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
}

287
src/mod25638.c Normal file
View File

@@ -0,0 +1,287 @@
/*
* mod25638.c -- modulo arithmetic of 2^256-38 for 2^255-19 field
*
* Copyright (C) 2014 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
*
* Gnuk is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* The field is \Z/(2^255-19)
*
* We use radix-32. During computation, it's not reduced to 2^255-19,
* but it is represented in 256-bit (it is redundant representation),
* that is, something like 2^256-38.
*
* The idea is, keeping within 256-bit until it will be converted to
* affine coordinates.
*/
#include <stdint.h>
#include <string.h>
#include "bn.h"
#include "mod25638.h"
#ifndef BN256_C_IMPLEMENTATION
#define ASM_IMPLEMENTATION 1
#endif
#if ASM_IMPLEMENTATION
#include "muladd_256.h"
#define ADDWORD_256(d_,s_,w_,c_) \
asm ( "ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \
"adds r4, r4, %[w] \n\t" \
"adcs r5, r5, #0 \n\t" \
"adcs r6, r6, #0 \n\t" \
"adcs r7, r7, #0 \n\t" \
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
"ldmia %[s]!, { r4, r5, r6, r7 } \n\t" \
"adcs r4, r4, #0 \n\t" \
"adcs r5, r5, #0 \n\t" \
"adcs r6, r6, #0 \n\t" \
"adcs r7, r7, #0 \n\t" \
"stmia %[d]!, { r4, r5, r6, r7 }\n\t" \
"mov %[c], #0 \n\t" \
"adc %[c], %[c], #0" \
: [s] "=&r" (s_), [d] "=&r" (d_), [c] "=&r" (c_) \
: "[s]" (s_), "[d]" (d_), [w] "r" (w_) \
: "r4", "r5", "r6", "r7", "memory", "cc" )
#endif
/*
256 224 192 160 128 96 64 32 0
2^256
1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
2^256 - 16
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffff0
2^256 - 16 - 2
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffee
2^256 - 16 - 2 - 1
0 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffed
*/
const bn256 p25519[1] = {
{{ 0xffffffed, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }} };
/*
* Implementation Note.
*
* It's not always modulo n25638. The representation is redundant
* during computation. For example, when we add the number - 1 and 1,
* it won't overflow to 2^256, and the result is represented within
* 256-bit.
*/
/**
* @brief X = (A + B) mod 2^256-38
*/
void
mod25638_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t carry;
carry = bn256_add (X, A, B);
carry = bn256_add_uint (X, X, carry*38);
X->word[0] += carry * 38;
}
/**
* @brief X = (A - B) mod 2^256-38
*/
void
mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t borrow;
borrow = bn256_sub (X, A, B);
borrow = bn256_sub_uint (X, X, borrow*38);
X->word[0] -= borrow * 38;
}
/**
* @brief X = A mod 2^256-38
*
* Note that the second argument is not "const bn512 *".
* A is modified during the computation of modulo.
*
* It's not precisely modulo 2^256-38 for all cases,
* but result may be redundant.
*/
static void
mod25638_reduce (bn256 *X, bn512 *A)
{
const uint32_t *s;
uint32_t *d;
uint32_t w;
#if ASM_IMPLEMENTATION
uint32_t c, c0;
s = &A->word[8]; d = &A->word[0]; w = 38; MULADD_256 (s, d, w, c);
c0 = A->word[8] * 38;
d = &X->word[0];
s = &A->word[0];
ADDWORD_256 (d, s, c0, c);
X->word[0] += c * 38;
#else
s = &A->word[8]; d = &A->word[0]; w = 38;
{
int i;
uint64_t r;
uint32_t carry;
r = 0;
for (i = 0; i < BN256_WORDS; i++)
{
uint64_t uv;
r += d[i];
carry = (r < d[i]);
uv = ((uint64_t)s[i])*w;
r += uv;
carry += (r < uv);
d[i] = (uint32_t)r;
r = ((r >> 32) | ((uint64_t)carry << 32));
}
carry = bn256_add_uint (X, (bn256 *)A, r * 38);
X->word[0] += carry * 38;
}
#endif
}
/**
* @brief X = (A * B) mod 2^256-38
*/
void
mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B)
{
bn512 tmp[1];
bn256_mul (tmp, A, B);
mod25638_reduce (X, tmp);
}
/**
* @brief X = A * A mod 2^256-38
*/
void
mod25638_sqr (bn256 *X, const bn256 *A)
{
bn512 tmp[1];
bn256_sqr (tmp, A);
mod25638_reduce (X, tmp);
}
/**
* @brief X = (A << shift) mod 2^256-38
* @note shift < 32
*/
void
mod25638_shift (bn256 *X, const bn256 *A, int shift)
{
uint32_t carry;
bn256 tmp[1];
carry = bn256_shift (X, A, shift);
if (shift < 0)
return;
memset (tmp, 0, sizeof (bn256));
tmp->word[0] = (carry << 1);
/* tmp->word[1] = (carry >> 31); always zero. */
tmp->word[0] = tmp->word[0] + (carry << 2);
tmp->word[1] = (tmp->word[0] < (carry << 2)) + (carry >> 30);
tmp->word[0] = tmp->word[0] + (carry << 5);
tmp->word[1] = tmp->word[1] + (tmp->word[0] < (carry << 5)) + (carry >> 27);
mod25638_add (X, X, tmp);
}
/*
* @brief X = A mod 2^255-19
*
* It's precisely modulo 2^255-19 (unlike mod25638_reduce).
*/
void
mod25519_reduce (bn256 *X)
{
uint32_t q;
bn256 r0[1], r1[1];
int flag;
memcpy (r0, X, sizeof (bn256));
q = (r0->word[7] >> 31);
r0->word[7] &= 0x7fffffff;
if (q)
{
bn256_add_uint (r0, r0, 19);
q = (r0->word[7] >> 31);
r0->word[7] &= 0x7fffffff;
if (q)
{
bn256_add_uint (r1, r0, 19);
q = (r1->word[7] >> 31);
r1->word[7] &= 0x7fffffff;
flag = 0;
}
else
flag = 1;
}
else
{
bn256_add_uint (r1, r0, 19);
q = (r1->word[7] >> 31); /* dummy */
r1->word[7] &= 0x7fffffff; /* dummy */
if (q)
flag = 2;
else
flag = 3;
}
if (flag)
{
bn256_add_uint (r1, r0, 19);
q = (r1->word[7] >> 31);
r1->word[7] &= 0x7fffffff;
if (q)
memcpy (X, r1, sizeof (bn256));
else
memcpy (X, r0, sizeof (bn256));
}
else
{
if (q)
{
asm volatile ("" : : "r" (q) : "memory");
memcpy (X, r1, sizeof (bn256));
asm volatile ("" : : "r" (q) : "memory");
}
else
memcpy (X, r1, sizeof (bn256));
}
}

7
src/mod25638.h Normal file
View File

@@ -0,0 +1,7 @@
extern const bn256 p25519[1];
void mod25638_add (bn256 *X, const bn256 *A, const bn256 *B);
void mod25638_sub (bn256 *X, const bn256 *A, const bn256 *B);
void mod25638_mul (bn256 *X, const bn256 *A, const bn256 *B);
void mod25638_sqr (bn256 *X, const bn256 *A);
void mod25519_reduce (bn256 *X);

View File

@@ -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);
}

View File

@@ -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);

318
src/modp256k1.c Normal file
View File

@@ -0,0 +1,318 @@
/*
* modp256k1.c -- modulo arithmetic for p256k1
*
* Copyright (C) 2014, 2016 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 always modulo p256k1.
*
* Once, I tried redundant representation which caused wrong
* calculation. Implementation could be correct with redundant
* representation, but it found that it's more expensive.
*
*/
/**
* @brief X = (A + B) mod p256k1
*/
void
modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t cond;
bn256 tmp[1];
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256K1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
memcpy (X, tmp, sizeof (bn256));
}
/**
* @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);
bn256_add (tmp, X, P256K1);
if (borrow)
memcpy (X, tmp, sizeof (bn256));
else
memcpy (tmp, tmp, sizeof (bn256));
}
/**
* @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
View 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);

300
src/modp256r1.c Normal file
View File

@@ -0,0 +1,300 @@
/*
* modp256r1.c -- modulo arithmetic for p256r1
*
* Copyright (C) 2011, 2013, 2014, 2016
* 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 always modulo p256r1.
*
* Once, I tried redundant representation which caused wrong
* calculation. Implementation could be correct with redundant
* representation, but it found that it's more expensive.
*
*/
/**
* @brief X = (A + B) mod p256r1
*/
void
modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
{
uint32_t cond;
bn256 tmp[1];
cond = (bn256_add (X, A, B) == 0);
cond &= bn256_sub (tmp, X, P256R1);
if (cond)
/* No-carry AND borrow */
memcpy (tmp, tmp, sizeof (bn256));
else
memcpy (X, tmp, sizeof (bn256));
}
/**
* @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);
bn256_add (tmp, X, P256R1);
if (borrow)
memcpy (X, tmp, sizeof (bn256));
else
memcpy (tmp, tmp, sizeof (bn256));
}
/**
* @brief X = A mod p256r1
*/
void
modp256r1_reduce (bn256 *X, const bn512 *A)
{
bn256 tmp[1], tmp0[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];
borrow = bn256_sub (tmp0, S1, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S1, tmp0, sizeof (bn256));
/* 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];
borrow = bn256_sub (tmp0, S5, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S5, tmp0, sizeof (bn256));
/* 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];
borrow = bn256_sub (tmp0, S6, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S6, tmp0, sizeof (bn256));
/* 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];
borrow = bn256_sub (tmp0, S7, P256R1);
if (borrow)
memcpy (tmp0, tmp0, sizeof (bn256));
else
memcpy (S7, tmp0, sizeof (bn256));
/* 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
View 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);

50
src/muladd_256.h Normal file
View File

@@ -0,0 +1,50 @@
#define MULADD_256_ASM(s_,d_,w_,c_) \
asm ( "ldmia %[s]!, { r8, r9, r10 } \n\t" \
"ldmia %[d], { r5, r6, r7 } \n\t" \
"umull r4, r8, %[w], r8 \n\t" \
"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" )
#define MULADD_256(s__,d__,w__,c__) do { \
MULADD_256_ASM(s__,d__,w__,c__); \
*d__ = c__; \
} while (0)

View File

@@ -1,7 +1,8 @@
/*
* neug.c - true random number generation
*
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2011, 2012, 2013, 2016
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a True Random Number Generator
@@ -28,19 +29,13 @@
#include "sys.h"
#include "neug.h"
#include "stm32f103.h"
#include "mcu/stm32f103.h"
#include "adc.h"
#include "sha256.h"
static chopstx_mutex_t mode_mtx;
static chopstx_cond_t mode_cond;
/*
* ADC finish interrupt
*/
#define INTR_REQ_DMA1_Channel1 11
static sha256_context sha256_ctx_data;
static uint32_t sha256_output[SHA256_DIGEST_SIZE/sizeof (uint32_t)];
@@ -215,7 +210,7 @@ static int ep_process (int mode)
CRC->DR = adc_buf[i*4 + 1];
CRC->DR = adc_buf[i*4 + 2];
CRC->DR = adc_buf[i*4 + 3];
v = CRC->DR & 0xff;
v = CRC->DR & 0xff; /* First byte of CRC->DR is used here. */
noise_source_continuous_test (v);
sha256_ctx_data.wbuf[i] = v;
ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
@@ -280,8 +275,6 @@ uint16_t neug_rc_max;
uint16_t neug_p64_max;
uint16_t neug_p4k_max;
#include "board.h"
static void noise_source_cnt_max_reset (void)
{
neug_err_cnt = neug_err_cnt_rc = neug_err_cnt_p64 = neug_err_cnt_p4k = 0;
@@ -576,7 +569,6 @@ static void *
rng (void *arg)
{
struct rng_rb *rb = (struct rng_rb *)arg;
chopstx_intr_t adc_intr;
int mode = neug_mode;
rng_should_terminate = 0;
@@ -585,7 +577,6 @@ rng (void *arg)
/* Enable ADCs */
adc_start ();
chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
ep_init (mode);
while (!rng_should_terminate)
@@ -593,7 +584,7 @@ rng (void *arg)
int err;
int n;
err = adc_wait_completion (&adc_intr);
err = adc_wait_completion ();
chopstx_mutex_lock (&mode_mtx);
if (err || mode != neug_mode)
@@ -643,16 +634,15 @@ rng (void *arg)
}
adc_stop ();
chopstx_release_irq (&adc_intr);
return NULL;
}
static struct rng_rb the_ring_buffer;
extern uint8_t __process2_stack_base__, __process2_stack_size__;
const uint32_t __stackaddr_rng = (uint32_t)&__process2_stack_base__;
const size_t __stacksize_rng = (size_t)&__process2_stack_size__;
extern uint8_t __process2_stack_base__[], __process2_stack_size__[];
#define STACK_ADDR_RNG ((uint32_t)__process2_stack_base__)
#define STACK_SIZE_RNG ((uint32_t)__process2_stack_size__)
#define PRIO_RNG 2
/**
@@ -678,7 +668,7 @@ neug_init (uint32_t *buf, uint8_t size)
neug_mode = NEUG_MODE_CONDITIONED;
rb_init (rb, buf, size);
rng_thread = chopstx_create (PRIO_RNG, __stackaddr_rng, __stacksize_rng,
rng_thread = chopstx_create (PRIO_RNG, STACK_ADDR_RNG, STACK_SIZE_RNG,
rng, rb);
}

View File

@@ -3,9 +3,9 @@
#define NEUG_PRE_LOOP 32
#define NEUG_MODE_CONDITIONED 0
#define NEUG_MODE_RAW 1
#define NEUG_MODE_RAW_DATA 2
#define NEUG_MODE_CONDITIONED 0 /* Conditioned data. */
#define NEUG_MODE_RAW 1 /* CRC-32 filtered sample data. */
#define NEUG_MODE_RAW_DATA 2 /* Sample data directly. */
extern uint8_t neug_mode;
extern uint16_t neug_err_cnt;

File diff suppressed because it is too large Load Diff

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