Compare commits
402 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
| 2519f799fd | |||
| 32f563a28d | |||
| 7b471948b4 | |||
| d2363c8ad8 | |||
| 9306ad5043 | |||
| 54d031bc27 | |||
| 6909e0359c | |||
| 5acd8a23d9 | |||
| d5a539986e | |||
| 8a19a2cb66 | |||
| 5e4a264ac0 | |||
| a9079e8b5c | |||
| 057920600f | |||
| 7d1b5e4b71 | |||
| fe66b67317 | |||
| 14f0acd749 | |||
| 9ccbd5804a | |||
| b4b82e1557 | |||
| 357a4b3510 | |||
| 1fdb74eb10 | |||
| 977a09f69f | |||
| cd271fbeb5 | |||
| 7e17548610 | |||
| fd7a7c7dfa | |||
| 8de235b26f | |||
| 53cbb62738 | |||
| 511f6de8b1 | |||
| 0132723c7a | |||
| a37f7aca5c | |||
| 531be827dd | |||
| d6c040400a | |||
| b8ada80163 | |||
| 1d63372017 | |||
| 8dfbf63452 | |||
| b9f6c3be7a | |||
|
|
9d3c08bd2b | ||
|
|
a909502388 | ||
|
|
286b620648 | ||
|
|
cce65c6d34 | ||
|
|
57fdadf283 | ||
|
|
870de72ee2 | ||
|
|
fa667b04f7 | ||
|
|
2a72f3df08 | ||
|
|
db2527459f | ||
|
|
1ca3bbdaae | ||
|
|
98119dc991 | ||
|
|
03cca1e451 | ||
|
|
3f65bf73e8 | ||
|
|
07be37f45e | ||
|
|
dcef6e0ffa | ||
|
|
d31687ebd6 | ||
|
|
92443f8f07 | ||
|
|
4af98308e0 | ||
|
|
baec3a1c1e | ||
|
|
4f1325794d | ||
|
|
0acf6485ae | ||
|
|
4d15700580 | ||
|
|
8822fcae77 | ||
|
|
20a2f99691 | ||
|
|
acfccb729d | ||
|
|
5283506755 | ||
|
|
c688df7c2c | ||
|
|
594896ac57 | ||
|
|
dfe046e08d | ||
|
|
c66b01e74b | ||
|
|
21a46306ae | ||
|
|
e5158572ee | ||
|
|
2142d0aa35 | ||
|
|
dd47cf4312 | ||
|
|
ffbb754fc0 | ||
|
|
d85750d791 | ||
|
|
d20e9e9b1e | ||
|
|
bf30144144 | ||
|
|
934daf3585 | ||
|
|
22420ed1f4 | ||
|
|
e97e3b1810 | ||
|
|
49f2544918 | ||
|
|
d156fc6261 | ||
|
|
81d6945081 | ||
|
|
c3e9db14e8 | ||
|
|
9180c35420 | ||
|
|
cc0d59cfe6 | ||
|
|
9c1368fdd0 | ||
|
|
2dd5a76002 | ||
|
|
f68ff0bddc | ||
|
|
add3299306 | ||
|
|
e28ec2c4c4 | ||
|
|
1ba05a0f0f | ||
|
|
2d50795d0a | ||
|
|
fd493562c3 | ||
|
|
16c6af215a | ||
|
|
177ef67edf | ||
|
|
126283b1ac | ||
|
|
076d727061 | ||
|
|
41fa424450 | ||
|
|
940332c47f | ||
|
|
aedf8267ec | ||
|
|
e9d9de3ae2 | ||
|
|
fc109fd8af | ||
|
|
3d06051a32 | ||
|
|
b7368e41e9 | ||
|
|
e760d5b780 | ||
|
|
b57c33c204 | ||
|
|
ca3312eb25 | ||
|
|
6a1f50abda | ||
|
|
66f39c57cd | ||
|
|
4b5f93624e | ||
|
|
0ef687ea4c | ||
|
|
786b4adc42 | ||
|
|
385261c9a0 | ||
|
|
65689199e7 | ||
|
|
8d15086d06 | ||
|
|
c17fd5401b | ||
|
|
56cd4ae7b5 | ||
|
|
fc36773c6a | ||
|
|
7249775c17 | ||
|
|
980cff0a2f | ||
|
|
8f44f5d3c6 | ||
|
|
37a84ed218 | ||
|
|
6c72147248 | ||
|
|
3d37003d8c | ||
|
|
becf8fabc5 | ||
|
|
17492287f3 | ||
|
|
c800dee95e | ||
|
|
2c390dc763 | ||
|
|
5aee75fd4b | ||
|
|
69e8c0f334 | ||
|
|
317cc2036d | ||
|
|
312d15c3fa | ||
|
|
d356f1b1e0 | ||
|
|
9cb6591491 | ||
|
|
ebec8ee156 | ||
|
|
f810fb83d3 | ||
|
|
12079974fd | ||
|
|
ca79f5421f | ||
|
|
c438367d67 | ||
|
|
4c6511231c | ||
|
|
ba750d153d | ||
|
|
72647f01d0 | ||
|
|
c6e32a36fb | ||
|
|
c3a0eb1439 | ||
|
|
030a9c576d | ||
|
|
8a5e0eb783 | ||
|
|
bce53546e7 | ||
|
|
b2b19e1ad4 | ||
|
|
58fa773bb7 | ||
|
|
ea88c3da66 | ||
|
|
b905b4802f | ||
|
|
40f2c6c49e | ||
|
|
61a7f9602b | ||
|
|
5465fda927 | ||
|
|
f7c46a6c55 | ||
|
|
4550458806 | ||
|
|
93a2bac94b | ||
|
|
24adc09406 | ||
|
|
bf9fc628b3 | ||
|
|
d76534dd3a | ||
|
|
d9c5dcf206 | ||
|
|
26448d58ee | ||
|
|
9cfeb817bd | ||
|
|
b6534dceba | ||
|
|
b47bd693ba | ||
|
|
1a7d3a698f | ||
|
|
f7b03f7fb5 | ||
|
|
44971541fe | ||
|
|
53ed5e0a42 | ||
|
|
63eccda0a1 | ||
|
|
f430c90715 | ||
|
|
1f18ec1d63 | ||
|
|
ec7423f493 | ||
|
|
e50dda28d1 | ||
|
|
8ad176921f | ||
|
|
d71b116be8 | ||
|
|
d9d3f35ac3 | ||
|
|
7cc8d8930e | ||
|
|
6446a5bd89 | ||
|
|
8b0cb8be65 | ||
|
|
c73bb0548e | ||
|
|
40b1d453dc | ||
|
|
3b965fafc0 | ||
|
|
35edbdc731 | ||
|
|
d4c776e308 | ||
|
|
6c0c510347 | ||
|
|
704d8a5cf1 | ||
|
|
55781cb7bb | ||
|
|
de24655920 | ||
|
|
7bfe0f5427 | ||
|
|
ec058537ed | ||
|
|
abeb1015ec | ||
|
|
c5f20dc355 | ||
|
|
4ff0b3c5f8 | ||
|
|
4e517778d0 | ||
|
|
c81544fffd | ||
|
|
ad42010272 | ||
|
|
8ce91267be | ||
|
|
b5c2ace2ae | ||
|
|
4cbc661fb7 | ||
|
|
543f28574e | ||
|
|
fe94e1885b | ||
|
|
ce82b347f9 | ||
|
|
d54712c04c | ||
|
|
9c63c874d0 | ||
|
|
bb9b31166f | ||
|
|
e417846408 | ||
|
|
21a481060c | ||
|
|
d4c9d6653b | ||
|
|
f00306627b | ||
|
|
f4b36b7503 | ||
|
|
e85527d302 | ||
|
|
bd58997dc9 | ||
|
|
9d5834d47b | ||
|
|
36ecf67694 | ||
|
|
c9b1e511ba | ||
|
|
01b5aa5984 | ||
|
|
b735c02ec2 | ||
|
|
2ecb104ae4 | ||
|
|
6b4f3c9934 | ||
|
|
660aaeb04b | ||
|
|
1022534c02 | ||
|
|
46cc64cf03 | ||
|
|
effc65381a | ||
|
|
6cbf5a4822 | ||
|
|
8ff3865890 | ||
|
|
43009f39e8 | ||
|
|
56fb5002bf | ||
|
|
3bb5097031 | ||
|
|
8319f4a14b | ||
|
|
f7cf0a3461 | ||
|
|
5ac52d3f2f | ||
|
|
209d459d09 | ||
|
|
ad704edc4e | ||
|
|
97a1870e6e | ||
|
|
f72e132967 | ||
|
|
a22b695f96 | ||
|
|
0c901d8052 | ||
|
|
a1b8e7f40c | ||
|
|
dccda32b93 | ||
|
|
75049ce949 | ||
|
|
be80a3ef2f | ||
|
|
94424e85c3 | ||
|
|
43980d1c81 | ||
|
|
183cec8a04 | ||
|
|
7bae61f300 | ||
|
|
7e4ee2b361 | ||
|
|
30fde2a0f0 | ||
|
|
eee8d046a9 | ||
|
|
550010f25f | ||
|
|
3adbe30c4d | ||
|
|
d9ec8778fc | ||
|
|
eff0c7077d | ||
|
|
289d3db8c4 | ||
|
|
7c5eb7efd2 | ||
|
|
6f1fbdd82d | ||
|
|
cbedf98a52 | ||
|
|
15689b5b86 | ||
|
|
8170b60ee2 | ||
|
|
ca7f4c8758 | ||
|
|
0b4099d6d1 | ||
|
|
65fee7eb2a | ||
|
|
0c229f5712 | ||
|
|
5948f6ec50 | ||
|
|
7b1ea00307 | ||
|
|
277be86958 | ||
|
|
a6b90ad648 | ||
|
|
547e263d6b | ||
|
|
7004453669 | ||
|
|
81b18f2db4 | ||
|
|
86715dd4fe | ||
|
|
62f27f319c | ||
|
|
7345f3c241 | ||
|
|
f4b9073b11 | ||
|
|
6678ac28c2 | ||
|
|
83414a747a | ||
|
|
8a615d087b | ||
|
|
967b949967 | ||
|
|
11afbdde14 | ||
|
|
328766af12 | ||
|
|
2b340ee1c5 | ||
|
|
86e6adf47e | ||
|
|
eea011fe70 | ||
|
|
e736227de7 | ||
|
|
22156ea7f9 | ||
|
|
db45e62ebe | ||
|
|
3270740631 | ||
|
|
e4e72a29ae | ||
|
|
25d3f021c1 | ||
|
|
ae76d66d53 | ||
|
|
10c5010141 | ||
|
|
d12483c3c9 | ||
|
|
67acb670d1 | ||
|
|
a44244b27e | ||
|
|
2622840e27 | ||
|
|
a51ac8593b | ||
|
|
de81caba3e | ||
|
|
fa69a85826 | ||
|
|
5c3c3e3001 | ||
|
|
6dcb4dd027 | ||
|
|
fa08f44cac | ||
|
|
4c2294ea6c | ||
|
|
86eaa26d32 | ||
|
|
9e52789203 | ||
|
|
702bc8cbde | ||
|
|
2cfce76d91 | ||
|
|
207652246a | ||
|
|
32779b6f96 | ||
|
|
55c1015faa | ||
|
|
0932465f0b | ||
|
|
4417799a51 | ||
|
|
b424cecf1e | ||
|
|
7ef417ae36 | ||
|
|
d4469c24ec | ||
|
|
e4333c6580 | ||
|
|
d2261d53e3 | ||
|
|
27bd37781a | ||
|
|
bed43d4049 | ||
|
|
f7d857b527 | ||
|
|
350528e1f4 | ||
|
|
4de605ed63 | ||
|
|
ffa9bf1f94 | ||
|
|
34d0b34144 | ||
|
|
5795dc9877 | ||
|
|
c8b17a8759 | ||
|
|
38d70e277b | ||
|
|
b00bab8dbf | ||
|
|
3c91dce8b7 | ||
|
|
f1773c146b | ||
|
|
979992c046 | ||
|
|
50700e3887 | ||
|
|
b0ee8b4452 | ||
|
|
a73f8cf4fd | ||
|
|
c1cc75f5b0 | ||
|
|
47150b5c98 | ||
|
|
f46880d2a8 | ||
|
|
23bbc9c755 | ||
|
|
2b784cb3b9 | ||
|
|
452c15c908 | ||
|
|
dc568422b1 | ||
|
|
5edcf32bb7 | ||
|
|
2647797348 | ||
|
|
9697694e45 | ||
|
|
f5cbc71a54 | ||
|
|
5099bfee88 | ||
|
|
691e16c605 | ||
|
|
eabcec107e | ||
|
|
73c698c67e | ||
|
|
d035c53b9c | ||
|
|
a96a3eefe6 | ||
|
|
fd08a853fd | ||
|
|
f882acc1b4 | ||
|
|
907d8c7a8e | ||
|
|
d636bf314c | ||
|
|
0212328a6a | ||
|
|
eb90074e11 | ||
|
|
38d164360c | ||
|
|
ff190a8053 | ||
|
|
f86f97cdbe | ||
|
|
1e004bec78 | ||
|
|
d68bee21e5 | ||
|
|
2903e88986 | ||
|
|
25fed157e1 | ||
|
|
d5c5571423 | ||
|
|
51d4b754e6 | ||
|
|
48905155c5 | ||
|
|
772071d1ba | ||
|
|
1fa45e3273 | ||
|
|
1a5eb0ec3b | ||
|
|
106b042e75 | ||
|
|
eebd40d946 | ||
|
|
5e37c7722a | ||
|
|
b1a582e87c | ||
|
|
3f1ee534fe | ||
|
|
522ec3299e | ||
|
|
34e2099b23 | ||
|
|
baf09ecac9 | ||
|
|
db23a1d051 | ||
|
|
3f8c4d1f17 | ||
|
|
1648a538df | ||
|
|
3ffac57509 | ||
|
|
1654a83366 | ||
|
|
022bb44f12 | ||
|
|
03c024f8f6 | ||
|
|
9b7d400550 | ||
|
|
c53bd96eb8 | ||
|
|
1f9e8ca77f | ||
|
|
deeb8aad1c | ||
|
|
f02d7d8565 | ||
|
|
a5f7072a64 | ||
|
|
2c79280441 | ||
|
|
d4d36bebab | ||
|
|
d423678f59 | ||
|
|
4b7cfd04af | ||
|
|
115a7ba67a | ||
|
|
d0e7aad11e | ||
|
|
645f42a890 | ||
|
|
f505dea314 | ||
|
|
748c3cac6c | ||
|
|
fa8bc533a3 | ||
|
|
00062a0ac7 | ||
|
|
c9f88bb9f1 | ||
|
|
482742394d | ||
|
|
05867d84f6 | ||
|
|
92cbb5364a |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,14 +1,20 @@
|
||||
*.lst
|
||||
*.o
|
||||
*.pyc
|
||||
regnual/regnual-no-vidpid.elf
|
||||
src/.dep
|
||||
src/Makefile
|
||||
src/config.mk
|
||||
src/config.h
|
||||
src/gnuk.ld
|
||||
src/stdaln-sys.ld
|
||||
src/board.h
|
||||
src/build/*
|
||||
src/*.inc
|
||||
src/put-vid-pid-ver.sh
|
||||
regnual/regnual.bin
|
||||
regnual/regnual.hex
|
||||
regnual/regnual.elf
|
||||
doc/_build
|
||||
tests/.cache
|
||||
tests/__pycache__
|
||||
tests/.pytest_cache
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "chopstx"]
|
||||
path = chopstx
|
||||
url = ../../chopstx/chopstx.git
|
||||
url = ../chopstx.git
|
||||
|
||||
50
AUTHORS
50
AUTHORS
@@ -1,50 +0,0 @@
|
||||
Kaz Kojima:
|
||||
Added STM32 Primer2 support.
|
||||
|
||||
NIIBE Yutaka:
|
||||
Founder of the project.
|
||||
Wrote tools for STLink/V2:
|
||||
tool/stlinkv2.py
|
||||
Wrote tools for DfuSe:
|
||||
tool/dfuse.py
|
||||
tool/dump_mem.py
|
||||
tool/intel_hex.py
|
||||
Wrote a tool for Gnuk:
|
||||
tool/gnuk_put_binary.py
|
||||
tool/gnuk_put_binary_libusb.py
|
||||
tool/gnuk_remove_keys.py
|
||||
tool/gnuk_upgrade.py
|
||||
Wrote a tool for USB Hub:
|
||||
tool/hub_ctrl.py
|
||||
Wrote a tool for testing card reader with pinpad:
|
||||
tool/pinpadtest.py
|
||||
Wrote reGNUal implementation:
|
||||
regnual/regnual.c
|
||||
regnual/sys.c
|
||||
Wrote Gnuk implementation:
|
||||
gnuk.svg
|
||||
src/configure
|
||||
src/ac.c
|
||||
src/call-rsa.c
|
||||
src/debug.c
|
||||
src/flash.c
|
||||
src/gnuk.h
|
||||
src/main.c
|
||||
src/neug.c
|
||||
src/openpgp-do.c
|
||||
src/openpgp.c
|
||||
src/openpgp.h
|
||||
src/pin-cir.c
|
||||
src/pin-dial.c
|
||||
src/pin-dnd.c
|
||||
src/random.c
|
||||
src/sys.c
|
||||
src/usb-icc.c
|
||||
src/usb-msc.c
|
||||
src/usb-msc.h
|
||||
src/usb_ctrl.c
|
||||
src/usb_desc.c
|
||||
src/usb_lld.c
|
||||
src/usb_lld.h
|
||||
*
|
||||
and others.
|
||||
2477
ChangeLog-1_0
2477
ChangeLog-1_0
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
# VID:PID bcdDev Product_STRING Vender_STRING
|
||||
# VID:PID bcdDev Product_STRING Vendor_STRING
|
||||
0000:0000 0200 Gnuk Token Free Software Initiative of Japan
|
||||
234b:0000 0200 Gnuk Token Free Software Initiative of Japan
|
||||
20a0:4211 0200 Nitrokey Start Nitrokey
|
||||
1209:2440 0200 Gnuk Token GnuPG e.V.
|
||||
1337:0010 0200 Gnuk Token Deon Spengler
|
||||
##########<TAB> ##<TAB> ##########<TAB> #################
|
||||
|
||||
380
NEWS
380
NEWS
@@ -1,5 +1,376 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.20
|
||||
|
||||
Released 2022-04-22, by NIIBE Yutaka
|
||||
|
||||
** Minor fixes for newer compiler
|
||||
|
||||
For build with newer compiler, Gnuk and regnual are fixed for address
|
||||
calculation and access to object on memory, as well as declarations of
|
||||
function and type in standard C library.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
|
||||
We use Chopstx 1.21. This includes fix to silence compiler warnings.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.19
|
||||
|
||||
Released 2021-10-12, by NIIBE Yutaka
|
||||
|
||||
** KDF Data Object configuration
|
||||
KDF Data Object should be highly recommended for all configurations.
|
||||
Nevertheless, for backward compatibillity, in Gnuk 1.2, it is optional
|
||||
by default; It is up to user to configure KDF Data Object before
|
||||
importing private keys. In this situation, it is not good to
|
||||
introduce new build-time option like --enable-always-require-kdf-do,
|
||||
because it might wrongly encourage use of Gnuk with no KDF Data Object
|
||||
setting, by confusion. If needed, please run configure:
|
||||
|
||||
kdf_do=required ./configure --enable-factory-reset --target...
|
||||
|
||||
or
|
||||
|
||||
kdf_do=optional ./configure --enable-factory-reset --target...
|
||||
|
||||
Please note that such a use of variable by shell command line is not
|
||||
well supported by the configure script (for other variables), but
|
||||
override of kdf_do is needed in some situations.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.20. This enables use with PC/SC for GNU/Linux
|
||||
emulation.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.18
|
||||
|
||||
Released 2021-04-02, by NIIBE Yutaka
|
||||
|
||||
** GNU/Linux emulation bug fix
|
||||
This time, for GNU/Linux emulation, KDF Data Object is required before
|
||||
keygen and key import, really.
|
||||
|
||||
** tool/upgrade_by_passwd.py
|
||||
Now, it checks if the target of binary being written and the
|
||||
configured target of running device are same. This check can be
|
||||
skipped by -s option. Please note that FST-01 and FST-01SZ are
|
||||
different target, as it's MHz is different.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.17
|
||||
|
||||
Released 2021-02-25, by NIIBE Yutaka
|
||||
|
||||
** GNU/Linux: KDF Data Object is required before keygen and key import
|
||||
For GNU/Linux emulation, KDF Data Object is required before keygen and
|
||||
key import.
|
||||
|
||||
** GNU/Linux emulation
|
||||
Since 1.2.10, it was not build-able because of MHZ definition. It is
|
||||
build-able again, and its USB product string is now "Gnuk Token". It
|
||||
has ACK button support using terminal. It now has start-up message,
|
||||
and its driver show useful information to setup USBIP. When no file
|
||||
for the .gnuk-flash-image file, it is automatically created.
|
||||
|
||||
** Removal of tool/gnuk-emulation-setup
|
||||
Because it is automatically created, the tool is not needed any more.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.19.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.16
|
||||
|
||||
Released 2020-09-10, by NIIBE Yutaka
|
||||
|
||||
** New Data Object (Algorithm Information) of OpenPGP card v3.4
|
||||
The tag is 0x00FA. This is useful for user interaction to show which
|
||||
algorithms are supported by the device.
|
||||
|
||||
** Ed25519 signing allowing longer message
|
||||
For OpenPGP, it does hashing on host side before requesting signing to
|
||||
the device. Thus, the length of message to be signed is limited and
|
||||
determined by the hash algorithm. That's good feature of OpenPGP. On
|
||||
the other hand, there is a use case, like OpenSSH certificate signing,
|
||||
where the length of message is a kind of arbitrary. Even though Gnuk
|
||||
(or OpenPGP card protocol itself) has limitation, we removed the
|
||||
length check against EDDSA_HASH_LEN_MAX at cmd_pso.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.15
|
||||
|
||||
Released 2020-01-24, by NIIBE Yutaka
|
||||
|
||||
** Switch to Python3
|
||||
Scripts under tool/ are switched to Python3.
|
||||
Thanks to Bertrand Jacquin.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.18.
|
||||
|
||||
** Tests also support OpenPGPcard
|
||||
Now, a test suite under "tests" may be used to OpenPGPcard.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.14
|
||||
|
||||
Released 2019-03-05, by NIIBE Yutaka
|
||||
|
||||
** Timeout for ACK button support
|
||||
When a user doesn't acknowledge (> 15 seconds), the operation
|
||||
timeouts, and authentication state is cleared.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.14.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.13
|
||||
|
||||
Released 2018-12-26, by NIIBE Yutaka
|
||||
|
||||
** DFU support and its firmware upgrade fix
|
||||
DFU support was not well maintained, and firmware upgrade was not
|
||||
possible for boards with DFU. Now, at least for Maple Mini, it is
|
||||
tested. Note that using Gnuk with DFU on a board is only for an
|
||||
experiment, because DFU can access the content of flash ROM. DFU
|
||||
should be killed by upgrading to normal Gnuk, so that you can have
|
||||
your private keys.
|
||||
|
||||
** Fix for UIF Data Object
|
||||
When flash ROM is full and coping to new page, UIF DO was not properly
|
||||
copied. This bug resulted losing the flag for user interaction. Now,
|
||||
it's properly copied, keeping the setting of the feature.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.13.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.12
|
||||
|
||||
Released 2018-11-25, by NIIBE Yutaka
|
||||
|
||||
** FST-01SZ fixes
|
||||
Fixes for Ack button support and serial number.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.11
|
||||
|
||||
Released 2018-11-12, by NIIBE Yutaka
|
||||
|
||||
** Experimental ACK button support with FST-01SZ
|
||||
While OpenPGP card specification verison 3 has description for the
|
||||
"user interaction" button and data objects, there were no
|
||||
implementation. To evaluate the feature, experimental support is
|
||||
added.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.12, which comes with ACK button driver and supports
|
||||
FST-01SZ.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.10
|
||||
|
||||
Released 2018-05-10, by NIIBE Yutaka
|
||||
|
||||
** No inclusion of VID:PID in gnuk-no-vidpid.elf
|
||||
Now, we have new file named gnuk-no-vidpid.elf with no VID:PID. The
|
||||
file gnuk.elf has the VID:PID, like version 1.2.7 or older.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.9, which supports GD32F103.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.9
|
||||
|
||||
Released 2018-04-05, by NIIBE Yutaka
|
||||
|
||||
** A test suite fix: Clear PW3
|
||||
Until 1.2.8, after running the test suite under "tests", PW3 keystring
|
||||
remained, which affects use of admin-less mode. New test case is
|
||||
added to clear PW3.
|
||||
|
||||
** tool/upgrade_by_passwd.py supports KDF-DO auth
|
||||
With KDF-DO, firmware upgrade didn't work. Now, it's supported.
|
||||
|
||||
** Add "single-salt" support for KDF-DO
|
||||
With KDF-DO, "admin-less" mode didn't work well. With new feature of
|
||||
"single-salt" support, we can use "admin-less" mode with KDF-DO.
|
||||
|
||||
** factory-reset deletes all upgrade public keys
|
||||
By card-edit/factory-reset by GnuPG, it deletes all upgrade public
|
||||
keys, now.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.8
|
||||
|
||||
Released 2018-01-23, by NIIBE Yutaka
|
||||
|
||||
** No inclusion of VID:PID in gnuk.elf
|
||||
|
||||
Distribution of binary image with VID:PID would violate vendor ID
|
||||
agreement to USB Forum. Now, we have new file named gnuk-vidpid.elf
|
||||
for flashing. The file gnuk.elf can be used to generate
|
||||
gnuk-vidpid.elf and we can check if it is reproducible or not.
|
||||
|
||||
** Passphrase length check
|
||||
|
||||
Now, Gnuk checks length of passphrase if it's too short when
|
||||
changing passphrase.
|
||||
|
||||
** Remove unused DEK with BY_ADMIN
|
||||
|
||||
For admin-less mode, DEK by OPENPGP_CARD_INITIAL_PW3 remained on flash
|
||||
ROM. This could be considered a backdoor, if some other person had or
|
||||
kept access to the flash ROM, cheating a user. Now, the DEK is
|
||||
cleared by zero when the token is set to admin-less mode.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.8.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.7
|
||||
|
||||
Released 2017-11-26, by NIIBE Yutaka
|
||||
|
||||
** reGNUal
|
||||
reGNUal enables CRC module by itself.
|
||||
|
||||
** Flash update change
|
||||
CRC module is disabled when Gnuk stops. It's reGNUal which needs to
|
||||
enable CRC module.
|
||||
|
||||
** Support of USB suspend
|
||||
USB suspend and wakeup event are now handled.
|
||||
|
||||
** KDF-DO support and KDF by host
|
||||
KDF-DO is now available. Host can use this feature.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.6.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.6
|
||||
|
||||
Released 2017-10-11, by NIIBE Yutaka
|
||||
|
||||
** Port to GNU/Linux emulation
|
||||
We can "run" Gnuk Token on GNU/Linux by emulation through USBIP.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.5.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.5
|
||||
|
||||
Released 2017-08-11, by NIIBE Yutaka
|
||||
|
||||
** "factory-reset" fix
|
||||
Gnuk's behavior was implemented by referring the gpg implementation.
|
||||
It found that gpg implementation was not good from the viewpoint of
|
||||
the OpenPGP card specification. GnuPG was fixed to match the OpenPGP
|
||||
card specification already. Thus, Gnuk is now fixed.
|
||||
|
||||
** Upgrade of Chopstx
|
||||
We use Chopstx 1.4.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.2.4
|
||||
|
||||
Released 2017-05-12, by NIIBE Yutaka
|
||||
|
||||
** Flash ROM security fix
|
||||
The partial content of flash ROM might be exposed when scanning of
|
||||
data object had a problem. Added boundary check and changed layout of
|
||||
flash ROM.
|
||||
|
||||
|
||||
* 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
|
||||
@@ -22,7 +393,7 @@ We use Chopstx 0.07, which supports STM32 Primer2 and CQ STARM, too.
|
||||
|
||||
** Experimental Curve25519 support.
|
||||
|
||||
Gnuk can support Curve25519 (for deecryption). Note that this is
|
||||
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.
|
||||
@@ -662,6 +1033,7 @@ Gnuk Token could run with GPG4WIN on MS Windows. GPG4WIN runs with
|
||||
|
||||
** This is initial release. Only it supports digital signing.
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
End:
|
||||
|
||||
# Local Variables:
|
||||
# mode: outline
|
||||
# End:
|
||||
|
||||
617
README
617
README
@@ -1,617 +0,0 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.1.7
|
||||
2015-08-05
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Warning
|
||||
=======
|
||||
|
||||
This is another experimental release of Gnuk, version 1.1.7, which has
|
||||
incompatible changes to Gnuk 1.0.x. Specifically, it now supports
|
||||
overriding key import, but importing keys (or generating keys) results
|
||||
password reset. Please update your documentation for Gnuk Token, so
|
||||
that the instruction of importing keys won't cause any confusion. It
|
||||
has supports of ECDSA (with NIST P256 and secp256k1), EdDSA, and ECDH
|
||||
(with NIST P256, secp256k1, and Curve25519), but this ECC feature is
|
||||
pretty much experimental, and it requires development version of GnuPG
|
||||
with newest version of libgcrypt (Further, for Curve25519, it requires
|
||||
additional patches by me).
|
||||
|
||||
It also support RSA-4096 experimentally, but users should know that it
|
||||
takes more than 8 second to sign/decrypt.
|
||||
|
||||
You will not able to keep using Curve25519 keys, as the key format is
|
||||
subject to change.
|
||||
|
||||
|
||||
What's Gnuk?
|
||||
============
|
||||
|
||||
Gnuk is an implementation of USB cryptographic token for GNU Privacy
|
||||
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
|
||||
STM32F103 processor.
|
||||
|
||||
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
|
||||
been nervous of storing secret key(s) on usual secondary storage.
|
||||
There is a solution with OpenPGP card, but it is not the choice for
|
||||
me, as card reader is not common device. With Gnuk, this issue will
|
||||
be solved by a USB token.
|
||||
|
||||
Please look at the graphics of "gnuk.svg" for the software name. My
|
||||
son used to be with his NUK(R), always, everywhere. Now, I am with a
|
||||
USB Cryptographic Token by "Gnuk", always, everywhere.
|
||||
|
||||
|
||||
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/
|
||||
A0: Good points of Gnuk are:
|
||||
* If you have skill of electronics and like DIY, you can build
|
||||
Gnuk Token cheaper (see Q8-A8).
|
||||
* You can study Gnuk to modify and to enhance. For example, you
|
||||
can implement your own authentication method with some sensor
|
||||
such as an acceleration sensor.
|
||||
* It is "of Free Software"; Gnuk is distributed under GPLv3+,
|
||||
"by Free Software"; Gnuk development requires only Free Software
|
||||
(GNU Toolchain, Python, etc.),
|
||||
"for Free Software"; Gnuk supports GnuPG.
|
||||
|
||||
Q1: What kind of key algorithm is supported?
|
||||
A1: Gnuk version 1.0 only supports RSA 2048.
|
||||
Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA,
|
||||
as well as RSA 4096-bit. But it takes long time to sign with RSA 4096.
|
||||
|
||||
Q2: How long does it take for digital signing?
|
||||
A2: It takes a second and a half or so.
|
||||
|
||||
Q3: What's your recommendation for target board?
|
||||
A3: Orthodox choice is Olimex STM32-H103.
|
||||
FST-01 (Flying Stone Tiny 01) is available for sale, and it is a
|
||||
kind of the best choice, hopefully.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
I tested pcscd 1.5.5-4 and libccid 1.3.11-2 which were in Debian
|
||||
squeeze.
|
||||
|
||||
Q6: What kinds of hardware is required for development?
|
||||
A6: You need a target board plus a JTAG/SWD debugger. If you just
|
||||
want to test Gnuk for target boards with DfuSe, JTAG debugger is
|
||||
not the requirement. Note that for real use, you need JTAG/SWD
|
||||
debugger to enable flash ROM protection.
|
||||
|
||||
Q7: How much does it cost?
|
||||
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
|
||||
|
||||
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
|
||||
A9: GnuPG's SCDaemon has problems for handling insertion/removal of
|
||||
card/reader. When your newly inserted token is not found by
|
||||
GnuPG, try killing scdaemon and let it to be invoked again. I do:
|
||||
|
||||
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
|
||||
|
||||
and confirm scdaemon doesn't exist, then,
|
||||
|
||||
$ gpg-connect-agent learn /bye
|
||||
|
||||
Qa: With GNOME 2, I can't use Gnuk Token for SSH. How can we use it for SSH?
|
||||
Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
|
||||
gpg-agant for the role of ssh-agent. For gnome-keyring please do:
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
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
|
||||
|
||||
and at the tab of "Startup Programs", disable check buttons for
|
||||
"GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
Release notes
|
||||
=============
|
||||
|
||||
This is seventh experimental release in version 1.1 series of Gnuk.
|
||||
|
||||
While it is daily use by its developer, some newly introduced features
|
||||
(including ECDSA/EdDSA/ECDH, key generation and firmware upgrade)
|
||||
should be considered experimental. ECDSA/EdDSA/ECDH is really
|
||||
experimental. Further, ECDH on Curve25519 is much experimental. You
|
||||
won't be able to keep using the key, since the key format of GnuPG is
|
||||
not defined and it's subject to change.
|
||||
|
||||
Tested features are:
|
||||
|
||||
* Personalization of the card
|
||||
* Changing Login name, URL, Name, Sex, Language, etc.
|
||||
* Password handling (PW1, RC, PW3)
|
||||
* Key import for three types:
|
||||
* key for digital signing
|
||||
* key for decryption
|
||||
* key for authentication
|
||||
* PSO: Digital Signature
|
||||
* PSO: Decipher
|
||||
* INTERNAL AUTHENTICATE
|
||||
* Changing value of password status bytes (0x00C4): forcesig
|
||||
* Verify with pin pad
|
||||
* Modify with pin pad
|
||||
* Card holder certificate (read)
|
||||
* Removal of keys
|
||||
* Key generation on device side
|
||||
* Overriding key import
|
||||
|
||||
Original features of Gnuk, tested lightly:
|
||||
|
||||
* OpenPGP card serial number setup
|
||||
* Card holder certificate (write by UPDATE BINARY)
|
||||
* Upgrading with "EXTERNAL AUTHENTICATE" by reGNUal
|
||||
|
||||
It is known not-working well:
|
||||
|
||||
* It is known that the combination of libccid 1.4.1 (or newer)
|
||||
with libusb 1.0.8 (or older) has a minor problem. It is
|
||||
rare but it is possible for USB communication to be failed,
|
||||
because of a bug in libusb implementation. Use libusbx
|
||||
1.0.9 or newer, or don't use PC/SC, but use internal CCID
|
||||
driver of GnuPG.
|
||||
|
||||
|
||||
Targets
|
||||
=======
|
||||
|
||||
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 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
|
||||
==========
|
||||
|
||||
Gnuk source code is under src/ directory.
|
||||
|
||||
Note that SHA-2 hash function implementation, src/sha256.c, is based
|
||||
on the original implementation by Dr. Brian Gladman. See:
|
||||
|
||||
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
It is distributed under GNU General Public Licence version 3 or later
|
||||
(GPLv3+). Please see src/COPYING.
|
||||
|
||||
Please note that it is distributed with external source code too.
|
||||
Please read relevant licenses for external source code as well.
|
||||
|
||||
The author(s) of Gnuk expect users of Gnuk will be able to access the
|
||||
source code of Gnuk, so that users can study the code and can modify
|
||||
if needed. This doesn't mean person who has a Gnuk Token should be
|
||||
able to access everything on the Token, regardless of its protections.
|
||||
Private keys, and other information should be protected properly.
|
||||
|
||||
|
||||
External source code
|
||||
====================
|
||||
|
||||
Gnuk is distributed with external source code.
|
||||
|
||||
* chopstx/ -- Chopstx 0.07
|
||||
|
||||
We use Chopstx as the kernel for Gnuk.
|
||||
|
||||
Chopstx is distributed under GPLv3+ (with a special exception).
|
||||
|
||||
|
||||
* polarssl/ -- based on PolarSSL 1.2.10 (now mbedTLS)
|
||||
|
||||
Souce code taken from: http://polarssl.org/
|
||||
|
||||
We use PolarSSL for RSA computation, and AES encryption/decryption.
|
||||
|
||||
PolarSSL is distributed under GPLv2+. We use PolarSSL under GPLv3
|
||||
as our options.
|
||||
|
||||
The file include/polarssl/bn_mul.h is heavily modified for ARM
|
||||
Cortex-M3.
|
||||
|
||||
The function rsa_private in polarssl/library/rsa.c is modified so
|
||||
that it doesn't check T against N. The function rsa_pkcs1_sign is
|
||||
modified to avoid warnings in case of !POLARSSL_PKCS1_V21.
|
||||
|
||||
The functions rsa_pkcs1_verify and rsa_rsassa_pkcs1_v15_verify in
|
||||
include/polarssl/rsa.h and polarssl/library/rsa.c are modified
|
||||
(fixed) for last argument SIG, as the memory at SIG aren't modified
|
||||
by those routines.
|
||||
|
||||
The constant POLARSSL_MPI_MAX_SIZE in include/polarssl/bignum.h is
|
||||
modified for 2048-bit keys only Gnuk.
|
||||
|
||||
The function mpi_mul_hlp in library/bignum.c is modified for more
|
||||
optimization for ARM Cortex-M3. Functions mpi_montred, mpi_sub_hlp,
|
||||
mpi_sub_abs, mpi_mul_mpi, mpi_montmul, and mpi_exp_mod are modified
|
||||
to avoid side channel attacks. Note that we don't use RSA-blinding
|
||||
technique for Gnuk. Function mpi_gen_prime and mpi_is_prime are
|
||||
modified to use Fouque-Tibouchi method. Function mpi_exp_mod is
|
||||
modified to use new function mpi_montsqr for speed up.
|
||||
|
||||
The file library/aes.c is modified so that some constants can
|
||||
go to .sys section.
|
||||
|
||||
The file include/polarssl/config.h are modified not to define
|
||||
POLARSSL_HAVE_LONGLONG to avoid linking libgcc, to define
|
||||
POLARSSL_AES_ROM_TABLES to have AES tables, not to define
|
||||
POLARSSL_CIPHER_MODE_CTR, POLARSSL_FS_IO, POLARSSL_PKCS1_V21,
|
||||
POLARSSL_SELF_TEST, and POLARSSL_PADLOCK_C, and only define
|
||||
POLARSSL_GENPRIME when defined KEYGEN_SUPPORT.
|
||||
|
||||
|
||||
USB vendor ID and product ID (USB device ID)
|
||||
============================================
|
||||
|
||||
When you have a vender 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.
|
||||
|
||||
When you are modifing Gnuk and installing the binary to device, you
|
||||
should replace the vendor string and serial number to yours (in the
|
||||
file GNUK_USB_DEVICE_ID and SERIALNO of the script of src/configure),
|
||||
so that users can see it's not by original vendor, and it is modified
|
||||
version.
|
||||
|
||||
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices
|
||||
with Gnuk under one of following conditions:
|
||||
|
||||
* For everyone for experimental purpose:
|
||||
|
||||
- You must not distribute a binary with FSIJ's USB device ID, but
|
||||
must use the binary by yourself only for your experiment. Note
|
||||
that "Distributing binary" includes distributing a device which
|
||||
holds the binary.
|
||||
|
||||
* For general individuals:
|
||||
|
||||
- You must use your Gnuk device with a card serial number which is
|
||||
*not* by FSIJ. Easy one would be a card serial number generated
|
||||
by chip unique ID.
|
||||
|
||||
* For individuals with explicit permission from FSIJ.
|
||||
|
||||
- You should have an assigned card serial number by FSIJ,
|
||||
please use that number for your device.
|
||||
(There a file 'GNUK_SERIAL_NUMBER' in the official release.)
|
||||
|
||||
FSIJ could give companies or business entities "second source
|
||||
manufacturer" license to use USB device ID of FSIJ for devices with
|
||||
unmodified version of Gnuk, provided they support Free Software and
|
||||
respect users' freedom for computing. Please ask FSIJ for the
|
||||
license.
|
||||
|
||||
Otherwise, companies which want to distribute Gnuk devices, please use
|
||||
your own USB vendor ID and product ID. Please replace vendor string
|
||||
and possibly product string to yours, when you modify Gnuk.
|
||||
|
||||
|
||||
Host Requirements
|
||||
=================
|
||||
|
||||
For GNU/Linux, PC/SC service is an option, you can use GnuPG's
|
||||
internal CCID driver instead. If you chose using PC/SC service,
|
||||
libccid version >= 1.3.11 is recommended for GNU/Linux.
|
||||
|
||||
|
||||
How to compile
|
||||
==============
|
||||
|
||||
You need GNU toolchain and newlib for 'arm-none-eabi' target.
|
||||
|
||||
There is "gcc-arm-embedded" project. See:
|
||||
|
||||
https://launchpad.net/gcc-arm-embedded/
|
||||
|
||||
|
||||
Change directory to `src':
|
||||
|
||||
$ cd gnuk-VERSION/src
|
||||
|
||||
Then, run `configure':
|
||||
|
||||
$ ./configure --vidpid=<VID:PID>
|
||||
|
||||
Here, you need to specify USB vendor ID and product ID. For FSIJ's,
|
||||
it's: --vidpid=234b:0000 . Please read section 'USB vendor ID and
|
||||
product ID' above.
|
||||
|
||||
|
||||
Then, type:
|
||||
|
||||
$ make
|
||||
|
||||
Then, we will have "gnuk.elf" under src/build directory.
|
||||
|
||||
|
||||
How to install
|
||||
==============
|
||||
|
||||
Olimex STM32-H103 board
|
||||
-----------------------
|
||||
|
||||
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
|
||||
|
||||
$ openocd -f interface/ftdi/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
|
||||
|
||||
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> flash write_image erase gnuk.elf
|
||||
> reset
|
||||
> exit
|
||||
$
|
||||
|
||||
|
||||
Flying Stone Tiny 01
|
||||
--------------------
|
||||
|
||||
If you are using Flying Stone Tiny 01, you need a SWD writer.
|
||||
|
||||
OpenOCD 0.9 now supports ST-Link/V2. We can use it:
|
||||
|
||||
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg
|
||||
|
||||
|
||||
|
||||
STBee
|
||||
-----
|
||||
|
||||
Reset the board with "USER" switch pushed. Type following to write
|
||||
to flash:
|
||||
|
||||
# cd ../tool
|
||||
# ./dfuse.py ../src/build/gnuk.hex
|
||||
|
||||
Then, reset the board.
|
||||
|
||||
|
||||
How to protect flash ROM
|
||||
========================
|
||||
|
||||
Invoke your OpenOCD and type:
|
||||
|
||||
$ telnet localhost 4444
|
||||
> reset halt
|
||||
> stm32f1x lock 0
|
||||
> reset
|
||||
> shutdown
|
||||
|
||||
After power-off / power-on sequence, the contents of flash ROM cannot
|
||||
be accessible from JTAG debugger.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
How to configure
|
||||
================
|
||||
|
||||
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.
|
||||
|
||||
If scdaemon is running, please kill it, or you will get "Smartcard
|
||||
Exception" by "Sharing violation".
|
||||
|
||||
$ gpg-connect-agent "SCD KILLSCD" "SCD BYE" /bye
|
||||
|
||||
In case of PyUSB tool, you need to stop pcscd.
|
||||
|
||||
# /etc/init.d/pcscd stop
|
||||
|
||||
|
||||
(2) [Optional] Write fixed serial number
|
||||
|
||||
If you use fixed serial number in the file 'GNUK_SERIAL_NUMBER', you can do:
|
||||
|
||||
$ EMAIL=<YOUR-EMAIL-ADDRESS> ../tool/gnuk_put_binary_usb.py -s ../GNUK_SERIAL_NUMBER
|
||||
Writing serial number
|
||||
...
|
||||
|
||||
(3) [Optional] Write card holder certificate
|
||||
|
||||
If you have card holder certificate binary file, you can do:
|
||||
|
||||
$ ../tool/gnuk_put_binary_usb.py ../../<YOUR-CERTIFICATE>.bin
|
||||
../../<YOUR-CERTIFICATE>.bin: <LENGTH-OF-YOUR-CERTIFICATE>
|
||||
Updating card holder certificate
|
||||
...
|
||||
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
Debug enabled
|
||||
-------------
|
||||
|
||||
If you compiled with --enable-debug option, Gnuk has two interfaces
|
||||
(one is CCID/ICCD device and another is virtual COM port). Open
|
||||
virtual COM port by:
|
||||
|
||||
$ cu -l /dev/ttyACM0
|
||||
|
||||
and you will see debug output of Gnuk.
|
||||
|
||||
|
||||
Testing Gnuk
|
||||
------------
|
||||
|
||||
Type following command to see Gnuk runs:
|
||||
|
||||
$ gpg --card-status
|
||||
|
||||
|
||||
Besides, there is a functionality test under test/ directory. See
|
||||
test/README.
|
||||
|
||||
|
||||
Personalize the Token, import keys, and change the password
|
||||
-----------------------------------------------------------
|
||||
|
||||
You can personalize the token, putting your information like: Name,
|
||||
Login name, Sex, Languages, URL. To do so, GnuPG command is:
|
||||
|
||||
$ gpg --card-edit
|
||||
|
||||
Note that the factory setting of user password is "123456" and admin
|
||||
password is "12345678" as the specification.
|
||||
|
||||
It is recommended to create your keys on your computer, and import
|
||||
them to Gnuk Token. After you create your keys (they must be 2048-bit
|
||||
RSA), you can import them.
|
||||
|
||||
Gnuk supports key generation, but this feature is young and should be
|
||||
considered experimental.
|
||||
|
||||
For detail, please see documentation under doc/. You can see the HTML
|
||||
version at: http://www.fsij.org/doc-gnuk/
|
||||
|
||||
|
||||
How to debug
|
||||
============
|
||||
|
||||
We can use GDB.
|
||||
|
||||
$ arm-none-eabi-gdb gnuk.elf
|
||||
|
||||
|
||||
Inside GDB, we can connect OpenOCD by:
|
||||
|
||||
(gdb) target remote localhost:3333
|
||||
|
||||
|
||||
You can see the output of PCSCD:
|
||||
|
||||
# /etc/init.d/pcscd stop
|
||||
# LIBCCID_ifdLogLevel=7 /usr/sbin/pcscd --debug --foreground
|
||||
|
||||
|
||||
You can observe the traffic of USB using "usbmon". See the file:
|
||||
linux/Documentation/usb/usbmon.txt
|
||||
|
||||
|
||||
Firmware update
|
||||
===============
|
||||
|
||||
See doc/note/firmware-update.
|
||||
|
||||
|
||||
Git Repositories
|
||||
================
|
||||
|
||||
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
|
||||
|
||||
It's also available at: www.gniibe.org
|
||||
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
|
||||
|
||||
I put Chopstx as a submodule of Git. Please do this:
|
||||
|
||||
$ git submodule init
|
||||
$ git submodule update
|
||||
|
||||
We have migrated from ChibiOS/RT to Chopstx. If you have old code of
|
||||
ChibiOS/RT, you need:
|
||||
|
||||
Edit .git/config to remove chibios reference
|
||||
git rm --cached chibios
|
||||
|
||||
|
||||
Information on the Web
|
||||
======================
|
||||
|
||||
Please visit: http://www.fsij.org/gnuk/
|
||||
|
||||
Please see the FST-01 support pages:
|
||||
|
||||
http://www.gniibe.org/category/fst-01.html
|
||||
|
||||
Please consider to join Gnuk-users mailing list:
|
||||
|
||||
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
|
||||
|
||||
|
||||
Your Contributions
|
||||
==================
|
||||
|
||||
FSIJ welcomes your contributions. Please assign your copyright
|
||||
to FSIJ (if possible).
|
||||
|
||||
|
||||
Foot note
|
||||
==========
|
||||
|
||||
* NUK(R) is a registered trademark owend by MAPA GmbH, Germany.
|
||||
--
|
||||
138
README.md
Normal file
138
README.md
Normal file
@@ -0,0 +1,138 @@
|
||||
***Note:*** *This fork of Gnuk fixes some compiling bugs and focuses on using the "ST-Link V2" clone hardware.*
|
||||
|
||||
Here is the link to the original project: <http://git.gniibe.org/cgit/gnuk/gnuk.git/>
|
||||
|
||||
What's Gnuk?
|
||||
============
|
||||
Gnuk is an implementation of a USB cryptographic security token that supports the OpenPGP card protocol version 2. It runs on a STM32F103 processor (and its compatible). In short it allows one to convert a cheap $2 "ST-Link V2" clone device into a hardware security token.
|
||||
|
||||
It has supports of Ed25519 and X25519 (ECDH on Curve25519). It also has experimental support of ECDSA (on NIST P256 and secp256k1) and ECDH (on NIST P256 and secp256k1).
|
||||
|
||||
Gnuk supports the Key Derived Function (KDF) functionality. To use this feature one will need to use GnuPG 2.2.6 or later.
|
||||
|
||||
How to build the Gnuk firmware
|
||||
==============================
|
||||
You will need the GNU toolchain for arm-none-eabi and newlib.
|
||||
|
||||
To clone the source code and compile, use the following commands.
|
||||
```
|
||||
git clone --recursive https://git.spengler.co.za/deon/gnuk.git gnuk
|
||||
cd gnuk/src
|
||||
./configure --vidpid=1337:0010
|
||||
make
|
||||
```
|
||||
|
||||
Then, you will have "gnuk.bin" under src/build directory.
|
||||
|
||||
***Please read section 'USB vendor ID and product ID' below.***
|
||||
|
||||
How to flash the Gnuk firmware
|
||||
==============================
|
||||
In order to flash the firmware ensure that you have openocd installed.
|
||||
|
||||
Execute openocd and connect with telnet
|
||||
```
|
||||
openocd -f ../misc/stm32f103.cfg
|
||||
telnet localhost 4444
|
||||
```
|
||||
|
||||
Use the following commands to unlock, flash the firmware and lock the device again.
|
||||
```
|
||||
reset halt
|
||||
stm32f1x unlock 0
|
||||
reset halt
|
||||
flash write_bank 0 ./build/gnuk.bin 0
|
||||
stm32f1x lock 0
|
||||
reset halt
|
||||
```
|
||||
|
||||
How to reflash the ST-LINK
|
||||
==========================
|
||||
To reflash the ST-LINK, connect the device to a programmer as before while keeping pins 7 and 8 shorted. While the LED is blinking, run openocd. Once it’s running (i.e. it doesn’t show any errors), you can unshort the pins.
|
||||
|
||||
Then use the following to unlock and reflash.
|
||||
```
|
||||
reset halt
|
||||
stm32f1x unlock 0
|
||||
reset halt
|
||||
stm32f1x mass_erase 0
|
||||
flash write_bank 0 ./build/gnuk.bin 0
|
||||
stm32f1x lock 0
|
||||
reset halt
|
||||
```
|
||||
|
||||
***Note: That reprograming will wipe the flash memory and you will lose all key's that was on the device.***
|
||||
|
||||
Testing Gnuk
|
||||
============
|
||||
Type following command to see if GnuPG detects the Gnuk token.
|
||||
```
|
||||
gpg --card-status
|
||||
```
|
||||
|
||||
***See tests/README for functionality tests.***
|
||||
|
||||
Personalize the Token, import keys, and change the password
|
||||
===========================================================
|
||||
You can personalize your token by putting in your information like: Name, Login and Language.
|
||||
|
||||
The KDF setting needs to be enabled before any keys are imported into the Gnuk token. Once a key has been imported the KDF setting can't be changed until the token has been reset.
|
||||
|
||||
***Note:*** That the factory user password is "123456" and admin password is "12345678". It is recommended to create your keys on your computer, and import them into the token. Gnuk supports key generation, but this feature is young and should be considered experimental.
|
||||
|
||||
To configure your Gnuk token use the following command.
|
||||
```
|
||||
gpg --card-edit
|
||||
```
|
||||
|
||||
For further details, please see documentation under doc.
|
||||
|
||||
Firmware update
|
||||
===============
|
||||
See doc/note/firmware-update.
|
||||
|
||||
How to debug
|
||||
============
|
||||
Ensure that you have arm-none-eabi-gdb installed and then you must configure and compile the Gnuk firmware with --enable-debug option. After flashing Gnuk debug firmware one will see two interfaces, one is CCID/ICCD device and the another is a virtual COM port.
|
||||
|
||||
Open the virtual COM with the following command:
|
||||
```
|
||||
picocom /dev/ttyACM0
|
||||
```
|
||||
and you will see debug output of Gnuk firmware.
|
||||
|
||||
You can now use GDB with the following command.
|
||||
```
|
||||
arm-none-eabi-gdb src/build/gnuk.elf
|
||||
```
|
||||
|
||||
Inside GDB, we can connect OpenOCD by:
|
||||
```
|
||||
(gdb) target remote localhost:3333
|
||||
```
|
||||
|
||||
You can see the output of PCSCD with the following command:
|
||||
```
|
||||
/usr/bin/pcscd --debug --foreground
|
||||
```
|
||||
|
||||
You can also observe the traffic of the USB interface using "usbmon".
|
||||
|
||||
USB vendor ID and product ID (USB device ID)
|
||||
============================================
|
||||
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.
|
||||
|
||||
When you are modifing Gnuk and installing the binary to device, you should replace the vendor string and serial number to yours (in the file GNUK_USB_DEVICE_ID and SERIALNO of the script of src/configure), so that users can see it's not by original vendor, and it is modified version.
|
||||
|
||||
FSIJ allows you to use USB device ID of FSIJ (234b:0000) for devices with Gnuk under one of following conditions:
|
||||
* For everyone for experimental purpose:
|
||||
- You must not distribute a binary with FSIJ's USB device ID, but must use the binary by yourself only for your experiment. Note that "Distributing binary" includes distributing a device which holds the binary.
|
||||
* For general individuals:
|
||||
- You must use your Gnuk device with a card serial number which is *not* by FSIJ. Easy one would be a card serial number generated by chip unique ID.
|
||||
* For individuals with explicit permission from FSIJ.
|
||||
- You should have an assigned card serial number by FSIJ, please use that number for your device.
|
||||
(There a file 'GNUK_SERIAL_NUMBER' in the official release.)
|
||||
|
||||
FSIJ could give companies or business entities "second source manufacturer" license to use USB device ID of FSIJ for devices with unmodified version of Gnuk, provided they support Free Software and respect users' freedom for computing. Please ask FSIJ for the license.
|
||||
|
||||
Otherwise, companies which want to distribute Gnuk devices, please use your own USB vendor ID and product ID. Please replace vendor string and possibly product string to yours, when you modify Gnuk.
|
||||
27
THANKS
27
THANKS
@@ -1,27 +0,0 @@
|
||||
-*- coding: utf-8 -*-
|
||||
|
||||
We would like to express our gratitudes to Werner Koch for GnuPG, and
|
||||
Giovanni Di Sirio for ChibiOS/RT.
|
||||
|
||||
Gnuk was originally written by NIIBE Yutaka. People contributed by
|
||||
encouraging the development, testing the implementation, suggesting
|
||||
improvements, or fixing bugs. Here is a list of those people.
|
||||
|
||||
Achim Pietig achim@pietig.com
|
||||
Aidan Thornton
|
||||
Andre Zepezauer andre.zepezauer@student.uni-halle.de
|
||||
Bertrand Jacquin bertrand@jacquin.bzh
|
||||
Hironobu SUZUKI hironobu@h2np.net
|
||||
Jan Suhr jan@suhr.info
|
||||
Kaz Kojima kkojima@rr.iij4u.or.jp
|
||||
Ludovic Rousseau ludovic.rousseau@free.fr
|
||||
Luis Felipe R. Murillo luisfelipe@ucla.edu
|
||||
MATSUU Takuto matsuu@gentoo.org
|
||||
NAGAMI Takeshi nagami-takeshi@aist.go.jp
|
||||
Nguyễn Hồng Quân quannguyen@mbm.vn
|
||||
NOKUBI Takatsugu knok@daionet.gr.jp
|
||||
Paul Bakker polarssl_maintainer@polarssl.org
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
Vasily Evseenko
|
||||
Werner Koch wk@gnupg.org
|
||||
Yuji Imai ug@xcast.jp
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: 218102c5c4...a8e9074faf
@@ -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']
|
||||
|
||||
@@ -22,34 +22,29 @@ 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
|
||||
-------------
|
||||
|
||||
Change directory to ``src``:
|
||||
Change directory to ``src``: ::
|
||||
|
||||
$ cd gnuk-VERSION/src
|
||||
|
||||
Then, run ``configure``:
|
||||
Then, run ``configure``: ::
|
||||
|
||||
$ ./configure --vidpid=<VID:PID>
|
||||
|
||||
@@ -57,8 +52,14 @@ Here, you need to specify USB vendor ID and product ID. For FSIJ's,
|
||||
it's: --vidpid=234b:0000 . Please read the section 'USB vendor ID and
|
||||
product ID' in README.
|
||||
|
||||
Type:
|
||||
Type: ::
|
||||
|
||||
$ make
|
||||
|
||||
Then, we will have "gnuk.elf" under src/build directory.
|
||||
|
||||
If you are not the authorized vendor, please never distribute this
|
||||
file of "gnuk.elf", which includes VID:PID in the image. If you would
|
||||
like to distribute the image (for example, to check if it's
|
||||
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
|
||||
VID:PID.
|
||||
|
||||
@@ -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
487
doc/generating-key.rst
Normal 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
|
||||
$
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
===========================================
|
||||
GnuPG settings for GNOME 3.1x and GNOME 3.0
|
||||
===========================================
|
||||
|
||||
In the section `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
|
||||
|
||||
It was for GNOME 2. The old days was good, we just disabled GNOME-keyrings
|
||||
interference to SSH and customizing our desktop was easy for GNU and UNIX users.
|
||||
|
||||
.. _GnuPG settings: gpg-settings
|
||||
|
||||
|
||||
GNOME keyrings in GNOME 3.1x
|
||||
============================
|
||||
|
||||
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=
|
||||
|
||||
Then, no desktop environment invokes gnome-keyring for ssh and gpg. I think that it is The Right Thing.
|
||||
|
||||
|
||||
GNOME keyrings in GNOME 3.0 by GNOME-SESSION-PROPERTIES
|
||||
=======================================================
|
||||
|
||||
We can't use GNOME configuration tool (like GNOME 2) to disable interference by
|
||||
GNOME keyrings in GNOME 3.0.
|
||||
|
||||
It is GNOME-SESSION-PROPERTIES to disable the interference. Invoking::
|
||||
|
||||
$ gnome-session-properties
|
||||
|
||||
and at the tab of "Startup Programs", I removed radio check buttons
|
||||
for "GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
Then, I can use proper gpg-agent for GnuPG Agent Service and SSH Agent Service with Gnuk Token in GNOME 3.0.
|
||||
@@ -10,7 +10,7 @@ I don't save changes on PC after keytocard.
|
||||
|
||||
For the steps before the last step, please see `keytocard with removing keys on PC`_.
|
||||
|
||||
.. _keytocard removing keys: gnuk-keytocard
|
||||
.. _keytocard with removing keys on PC: gnuk-keytocard
|
||||
|
||||
Here is the session log of the last step.
|
||||
|
||||
@@ -22,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.
|
||||
|
||||
@@ -24,31 +24,29 @@ After personalization, I put my keys into the Token.
|
||||
|
||||
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. ::
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -27,13 +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
|
||||
|
||||
@@ -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 seahorse-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
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
|
||||
==========
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,7 +16,7 @@ In addition to settings of Gnuk, I create a file
|
||||
|
||||
# For updating firmware, permission settings are needed.
|
||||
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
|
||||
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_USB_INTERFACES}=="*:ff0000:*", GROUP="pcscd"
|
||||
|
||||
|
||||
@@ -50,39 +50,9 @@ With the script below, I extract public key of the keygrip
|
||||
|
||||
$ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
||||
|
||||
Here is the script, get_raw_public_key.py::
|
||||
|
||||
#! /usr/bin/python
|
||||
|
||||
import sys, binascii
|
||||
from subprocess import check_output
|
||||
|
||||
def get_gpg_public_key(keygrip):
|
||||
result = check_output(["gpg-connect-agent", "READKEY %s" % keygrip, "/bye"])
|
||||
key = ""
|
||||
while True:
|
||||
i = result.find('%')
|
||||
if i < 0:
|
||||
key += result
|
||||
break
|
||||
hex_str = result[i+1:i+3]
|
||||
key += result[0:i]
|
||||
key += chr(int(hex_str,16))
|
||||
result = result[i+3:]
|
||||
|
||||
pos = key.index("D (10:public-key(3:rsa(1:n257:") + 31 # skip NUL too
|
||||
key = key[pos:-17] # )(1:e3:XYZ)))\nOK\n
|
||||
if len(key) != 256:
|
||||
raise ValueError, binascii.hexlify(key)
|
||||
return key
|
||||
|
||||
if __name__ == '__main__':
|
||||
keygrip = sys.argv[1]
|
||||
k = get_gpg_public_key(keygrip)
|
||||
shorthand = keygrip[0:8] + ".bin"
|
||||
f = open(shorthand,"w")
|
||||
f.write(k)
|
||||
f.close()
|
||||
(The script is available in the directory gnuk/tool. Please note that
|
||||
it was written in the early stage of the development. The quality of
|
||||
the code is somewhat questionable.)
|
||||
|
||||
|
||||
Then, we can put the data of public key into token by::
|
||||
|
||||
136
doc/note/firmware-update-2
Normal file
136
doc/note/firmware-update-2
Normal file
@@ -0,0 +1,136 @@
|
||||
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", \
|
||||
ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
|
||||
|
||||
I have those lines in /etc/udev/rules.d/69-gnuk.rules.
|
||||
|
||||
|
||||
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.2.x
|
||||
is FST-01.
|
||||
|
||||
Then you get build/gnuk.elf.
|
||||
|
||||
If you are not the authorized vendor, please never distribute this
|
||||
file of "gnuk.elf", which includes VID:PID in the image. If you would
|
||||
like to distribute the image (for example, to check if it's
|
||||
reproducible or not), the file "gnuk-no-vidpid.elf" is the one with no
|
||||
VID:PID.
|
||||
|
||||
Invoking configure with FSIJ's USB ID (234b:0000) and generating
|
||||
gnuk.elf means that you are using FSIJ's USB ID (for reGNUal in this
|
||||
case). Please note that FSIJ only allows use of its USB ID for
|
||||
specific situations. Please read README of Gnuk about that.
|
||||
|
||||
|
||||
Bulding reGNUal
|
||||
---------------
|
||||
|
||||
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
|
||||
|
||||
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 -f option to skip entering your password (it
|
||||
assumes the factory setting).
|
||||
|
||||
If you already have configured another upgrade key installed, you can
|
||||
specify different slot by -k ``<slot_no>`` option. SLOT_NO can be 0
|
||||
to 3.
|
||||
--
|
||||
@@ -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 scdaemon
|
||||
|
||||
will do the same thing.
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -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,11 +33,11 @@ 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::
|
||||
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0000", \
|
||||
SUBSYSTEMS=="usb", ATTR{idVendor}=="234b", ATTR{idProduct}=="0000", \
|
||||
ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"
|
||||
|
||||
Usually, udev daemon automatically handles for the changes of configuration
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,553 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
id="svg3961"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="gnuk-sticers.svg">
|
||||
<defs
|
||||
id="defs3">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3967" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="1031.615"
|
||||
x2="240.89818"
|
||||
y1="1031.615"
|
||||
x1="85.996228"
|
||||
id="linearGradient4296"
|
||||
xlink:href="#linearGradient4290"
|
||||
inkscape:collect="always" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective3903" />
|
||||
<filter
|
||||
id="filter3875"
|
||||
inkscape:collect="always">
|
||||
<feBlend
|
||||
id="feBlend3877"
|
||||
in2="BackgroundImage"
|
||||
mode="screen"
|
||||
inkscape:collect="always" />
|
||||
</filter>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective3830" />
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10-5" />
|
||||
<linearGradient
|
||||
id="linearGradient0">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3620" />
|
||||
<stop
|
||||
id="stop3632"
|
||||
offset="0.07"
|
||||
style="stop-color:#c8c8e0;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3630"
|
||||
offset="0.17"
|
||||
style="stop-color:#9696c8;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3628"
|
||||
offset="0.33"
|
||||
style="stop-color:#6464b4;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#3232a0;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop3634" />
|
||||
<stop
|
||||
id="stop3636"
|
||||
offset="0.66"
|
||||
style="stop-color:#282898;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3626"
|
||||
offset="0.85"
|
||||
style="stop-color:#1e1e90;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000088;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3622" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient0"
|
||||
id="radialGradient0"
|
||||
cx="450"
|
||||
cy="750"
|
||||
fx="450"
|
||||
fy="750"
|
||||
r="201.5"
|
||||
gradientTransform="matrix(1,0,0,0.75369458,-1.760006,108.15135)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient1">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop0" />
|
||||
<stop
|
||||
id="stop1"
|
||||
offset="0.0625"
|
||||
style="stop-color:#f8fcff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2"
|
||||
offset="0.17166339"
|
||||
style="stop-color:#f0f8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3"
|
||||
offset="0.30279359"
|
||||
style="stop-color:#ecf4ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e8f0ff;stop-opacity:1;"
|
||||
offset="0.5"
|
||||
id="stop4" />
|
||||
<stop
|
||||
id="stop5"
|
||||
offset="0.65893352"
|
||||
style="stop-color:#e0ecff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6"
|
||||
offset="0.83552629"
|
||||
style="stop-color:#d8e8ff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#d0e0ff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop7" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient1"
|
||||
id="radialGradient1"
|
||||
cx="0"
|
||||
cy="440"
|
||||
fx="0"
|
||||
fy="440"
|
||||
r="80"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter0"
|
||||
x="-0.1423529"
|
||||
width="1.2847058"
|
||||
y="-0.13404847"
|
||||
height="1.2680969">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="2.0538481"
|
||||
id="feGaussianBlur0" />
|
||||
</filter>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
id="perspective2884" />
|
||||
<inkscape:perspective
|
||||
id="perspective10"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
id="linearGradient4290"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4292"
|
||||
offset="0"
|
||||
style="stop-color:#000734;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4294"
|
||||
offset="1"
|
||||
style="stop-color:#000734;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:document-units="mm"
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="-75.714286"
|
||||
inkscape:cy="520"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1122"
|
||||
inkscape:window-height="692"
|
||||
inkscape:window-x="150"
|
||||
inkscape:window-y="51"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(0.5,-946.62598)"
|
||||
id="layer1-63"
|
||||
inkscape:label="Layer1"
|
||||
inkscape:tile-cx="124.59931"
|
||||
inkscape:tile-cy="53.118107"
|
||||
inkscape:tile-w="248.19862"
|
||||
inkscape:tile-h="105.23622"
|
||||
inkscape:tile-x0="0.5"
|
||||
inkscape:tile-y0="0.49999656">
|
||||
<rect
|
||||
y="947.12598"
|
||||
x="0"
|
||||
height="105.23622"
|
||||
width="248.19862"
|
||||
id="rect0"
|
||||
style="fill:#d9fffe;fill-opacity:1;stroke:none" />
|
||||
<line id="line0"
|
||||
x1="0" y1="947.12598" x2="20" y2="947.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line1"
|
||||
x1="248.19862" y1="947.12598" x2="248.19862" y2="957.12598"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line2"
|
||||
x1="248.19862" y1="1052.3622" x2="228.19862" y2="1052.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<line id="line3"
|
||||
x1="0" y1="1052.3622" x2="0" y2="1042.3622"
|
||||
style="stroke:#000044;stroke-width:0.5;stroke-opacity:1;stroke-dasharray:2,1;stroke-dashoffset:1" />
|
||||
<image
|
||||
xlink:href="FSIJ-s.png"
|
||||
width="41.757679"
|
||||
height="28.346457"
|
||||
id="image2886"
|
||||
x="202.27382"
|
||||
y="951.12598" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text2890"
|
||||
y="1014.9048"
|
||||
x="94.433884"
|
||||
style="font-size:52.27830124px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#032b7f;fill-opacity:1;stroke:none;font-family:Courier 10 Pitch;-inkscape-font-specification:Courier 10 Pitch Bold"
|
||||
xml:space="preserve"><tspan
|
||||
y="1014.9048"
|
||||
x="94.433884"
|
||||
id="tspan2892"
|
||||
sodipodi:role="line">GNUK</tspan></text>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-6"
|
||||
transform="matrix(-0.1014557,0,0,0.1014557,90.73972,926.6016)">
|
||||
<path
|
||||
style="fill:#000050;fill-opacity:1;stroke:#000000;stroke-width:2.29999995px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,0 c 0,0 0,0 -76,0 0,0 -8,-9 -12,-12 -18,-15 -48,-48 -36,-84 4,-14 12,-36 12,-36 -10,6 -50,26 -66,54 -8,16 -18,30 -18,54 0,24 25,100 48,108 0,0 0,0 150,0 0,0 0,0 150,0 23,-8 48,-84 48,-108 0,-24 -10,-38 -18,-54 -16,-28 -46,-48 -66,-54 0,0 8,22 12,36 12,36 -18,69 -36,84 C 88,-9 80,0 80,0 z"
|
||||
transform="matrix(-1.76,0,0,1.76,410,560)"
|
||||
id="path0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000040;fill-opacity:1;stroke:none"
|
||||
d="m 411.01194,560.94628 c 0,0 0,0 133.76,0 0,0 14.08,-15.84 21.12,-21.12 31.68,-26.4 84.48,-84.48 63.36,-147.84 -7.04,-24.64 -21.12,-63.36 -21.12,-63.36 17.6,10.56 38,45.76 66.16,95.04 14.08,28.16 19.18,52.8 19.18,95.04 0,42.24 -44,176 -84.48,190.08 0,0 62.5,0 -201.5,0 0,0 62.5,0 -201.5,0 -40.48,-14.08 -84.48,-147.84 -84.48,-190.08 0,-42.24 5.1,-66.88 19.18,-95.04 28.16,-49.28 30.96,-84.48 66.16,-95.04 0,0 -14.08,38.72 -21.12,63.36 -21.12,63.36 31.68,121.44 63.36,147.84 7.04,5.28 21.12,21.12 21.12,21.12 z"
|
||||
id="path0-9"
|
||||
sodipodi:nodetypes="ccccccscccscccccc" />
|
||||
<path
|
||||
style="fill:#c0c0fd;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 409.21999,592 c 0,0 90,0 90,-33 0,-20 -4,-28 -12,-40 -5,-8 -8,-18 -8,-28 -1,-13 -1,-20 8,-36 6,-9 8,-23 5,-33 -5,-14 -19,-23 -33,-25 -16,-5 -35,-4 -50,-5 -15,1 -34,0 -50,5 -14,2 -28,9 -33,25 -3,10 1,24 5,33 9,16 9,23 8,36 0,10 -3,20 -8,28 -8,12 -12,20 -12,40 0,33 90,33 90,33 z"
|
||||
id="path1" />
|
||||
<path
|
||||
style="fill:url(#radialGradient1);fill-opacity:1;fill-rule:evenodd;stroke:#d0e0ff;stroke-width:10px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,592 c 0,0 -90,0 -90,-33 0,-20 4,-28 12,-40 5,-8 8,-18 8,-28 1,-13 1,-20 -8,-36 -6,-9 -8,-23 -5,-33 5,-14 19,-23 33,-25 16,-5 35,-4 50,-5 15,1 34,0 50,5 14,2 28,9 33,25 3,10 -1,24 -5,33 -9,16 -9,23 -8,36 0,10 3,20 8,28 8,12 12,20 12,40 0,33 -90,33 -90,33 z"
|
||||
id="path1-1"
|
||||
transform="matrix(-0.75,0,0,0.8,410,100)" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 344.11439,411.54794 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-2"
|
||||
sodipodi:nodetypes="ccccsc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter0)"
|
||||
d="m 474.68123,406.16125 c 7.16035,-2.82917 12.68023,-7.05316 25.88561,-1.83463 -11.82218,3.36559 -30.19974,8.74598 -28.4554,30.10894 0,1.43822 0.19526,2.84651 0.53302,4.18858 -5.07909,-3.45362 -6.70449,-9.04022 -6.70449,-15.93734 0,-10.74221 5.00989,-12.63545 8.74126,-16.52555 z"
|
||||
id="path1-3"
|
||||
sodipodi:nodetypes="ccccsc"
|
||||
transform="matrix(-1,0,0,1,949.00681,5.38669)" />
|
||||
<path
|
||||
style="fill:#afcfff;fill-opacity:1;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 236.90125,452.90625 C 135.34805,496.35376 97.060607,634.496 151.37,761.4375 c 50.02335,116.92341 158.1859,159.40625 257.75,159.40625 99.5641,0 207.72665,-42.48284 257.75,-159.40625 C 721.17939,634.496 682.89195,496.35376 581.33875,452.90625 526.07714,429.26367 466.8919,524.375 409.12,524.375 c -57.7719,0 -116.77668,-94.67646 -172.21875,-71.46875 z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:url(#radialGradient0);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3"
|
||||
d="m 538.23999,720 a 130,150 0 0 1 -260,0 130,150 0 1 1 260,0 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:4.47213602px;stroke-opacity:1"
|
||||
d="m 538.30032,722.21875 c 56.32313,26.16396 100.82185,68.68738 119.76563,119.4375 33.50451,82.59901 -5.55269,179.72665 -93.67188,230.71875 -89.66782,55.4574 -224.43374,55.4574 -314.10156,0 -88.11919,-50.9921 -127.13733,-148.11974 -93.63281,-230.71875 18.61816,-50.41349 63.06491,-92.92973 119.25781,-119.1875 11.1304,10.32118 18.58377,23.0939 22.34375,36.6875 -5.94376,3.59375 -11.63988,7.47175 -16.99219,11.625 -73.95399,55.19241 -81.85302,155.28934 -18.59375,218.125 47.75721,51.30795 139.68,72.55545 213.4375,46.68755 87.41094,-28.2229 135.47694,-110.93384 113.94531,-183.2813 -9.09953,-36.85675 -36.47131,-70.33241 -73.67187,-92.96875 2.51871,-9.1715 6.69761,-18.00492 12.57812,-26 2.55237,-3.99852 5.70954,-7.71801 9.33594,-11.125 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<text
|
||||
sodipodi:linespacing="85.000002%"
|
||||
id="text3817"
|
||||
y="1038.1145"
|
||||
x="98.368591"
|
||||
style="font-size:18px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:85.00000238%;writing-mode:lr-tb;text-anchor:start;fill:#120054;fill-opacity:1;stroke:none;display:inline;font-family:Gentium Basic;-inkscape-font-specification:Gentium Basic Bold Italic"
|
||||
xml:space="preserve"><tspan
|
||||
y="1038.1145"
|
||||
x="98.368591"
|
||||
style="fill:#120054;fill-opacity:1"
|
||||
id="tspan4288"
|
||||
sodipodi:role="line">GnuPG USB Token</tspan></text>
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
id="use4758" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,105.23622)"
|
||||
id="use4760" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,210.47244)"
|
||||
id="use4762" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,315.70866)"
|
||||
id="use4764" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,420.94489)"
|
||||
id="use4766" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,526.18111)"
|
||||
id="use4768" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,631.41733)"
|
||||
id="use4770" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,736.65355)"
|
||||
id="use4772" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,841.88977)"
|
||||
id="use4774" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(0,947.12599)"
|
||||
id="use4776" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,0)"
|
||||
id="use4778" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,105.23622)"
|
||||
id="use4780" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,210.47244)"
|
||||
id="use4782" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,315.70866)"
|
||||
id="use4784" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,420.94489)"
|
||||
id="use4786" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,526.18111)"
|
||||
id="use4788" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,631.41733)"
|
||||
id="use4790" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,736.65355)"
|
||||
id="use4792" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,841.88977)"
|
||||
id="use4794" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(248.19862,947.12599)"
|
||||
id="use4796" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,0)"
|
||||
id="use4798" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,105.23622)"
|
||||
id="use4800" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,210.47244)"
|
||||
id="use4802" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,315.70866)"
|
||||
id="use4804" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,420.94489)"
|
||||
id="use4806" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,526.18111)"
|
||||
id="use4808" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,631.41733)"
|
||||
id="use4810" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,736.65355)"
|
||||
id="use4812" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,841.88977)"
|
||||
id="use4814" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
inkscape:tiled-clone-of="#layer1-63"
|
||||
xlink:href="#layer1-63"
|
||||
transform="translate(496.39725,947.12599)"
|
||||
id="use4816" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 20 KiB |
4
misc/stm32f103.cfg
Normal file
4
misc/stm32f103.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
telnet_port 4444
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/stm32f1x.cfg]
|
||||
set WORKAREASIZE 0x10000
|
||||
@@ -495,6 +495,67 @@
|
||||
#endif /* TriCore */
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__ARM_FEATURE_DSP)
|
||||
/* The ARM DSP instructions are available on Cortex M4, M7 and
|
||||
Cortex A CPUs */
|
||||
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %[s]!, { r7, r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r3, r4, r5, r6 } \n\t" \
|
||||
"umaal r3, %2, %[b], r7 \n\t" \
|
||||
"umaal r4, %2, %[b], r8 \n\t" \
|
||||
"umaal r5, %2, %[b], r9 \n\t" \
|
||||
"umaal r6, %2, %[b], r10 \n\t" \
|
||||
"stmia %[d]!, {r3, r4, r5, r6} \n\t"
|
||||
|
||||
#define MULADDC_1024_LOOP \
|
||||
asm( "tst %[i], #0xfe0 \n\t" \
|
||||
"beq 0f \n" \
|
||||
"1: sub %[i], %[i], #32 \n\t" \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
MULADDC_1024_CORE MULADDC_1024_CORE \
|
||||
"tst %[i], #0xfe0 \n\t" \
|
||||
"bne 1b \n" \
|
||||
"0:" \
|
||||
: [s] "=r" (s), [d] "=r" (d), [c] "=r" (c), [i] "=r" (i) \
|
||||
: [b] "r" (b), "[s]" (s), "[d]" (d), "[c]" (c), "[i]" (i) \
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
|
||||
|
||||
#define MULADDC_INIT \
|
||||
asm(
|
||||
|
||||
#define MULADDC_CORE \
|
||||
"ldr r0, [%0], #4 \n\t" \
|
||||
"ldr r1, [%1] \n\t" \
|
||||
"umaal r1, %2, %3, r0 \n\t" \
|
||||
"str r1, [%1], #4 \n\t"
|
||||
|
||||
#define MULADDC_HUIT \
|
||||
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
|
||||
"ldmia %1, {r4, r5, r6, r7} \n\t" \
|
||||
"umaal r4, %2, %3, r0 \n\t" \
|
||||
"umaal r5, %2, %3, r1 \n\t" \
|
||||
"umaal r6, %2, %3, r2 \n\t" \
|
||||
"umaal r7, %2, %3, r3 \n\t" \
|
||||
"stmia %1!, {r4, r5, r6, r7} \n\t" \
|
||||
"ldmia %0!, {r0, r1, r2, r3} \n\t" \
|
||||
"ldmia %1, {r4, r5, r6, r7} \n\t" \
|
||||
"umaal r4, %2, %3, r0 \n\t" \
|
||||
"umaal r5, %2, %3, r1 \n\t" \
|
||||
"umaal r6, %2, %3, r2 \n\t" \
|
||||
"umaal r7, %2, %3, r3 \n\t" \
|
||||
"stmia %1!, {r4, r5, r6, r7} \n\t"
|
||||
|
||||
#define MULADDC_STOP \
|
||||
: "=r" (s), "=r" (d), "=r" (c) \
|
||||
: "r" (b), "0" (s), "1" (d), "2" (c) \
|
||||
: "r0", "r1", "r2", "r3", "r4", "r5", \
|
||||
"r6", "r7", "memory");
|
||||
|
||||
#else /* __ARM_FEATURE_DSP */
|
||||
|
||||
#define MULADDC_1024_CORE \
|
||||
"ldmia %[s]!, { r8, r9, r10 } \n\t" \
|
||||
"ldmia %[d], { r5, r6, r7 } \n\t" \
|
||||
@@ -556,7 +617,7 @@
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "memory", "cc" );
|
||||
|
||||
/* Just for reference (dead code) */
|
||||
#define MULADDC_HUIT \
|
||||
#define MULADDC_HUIT_DEAD \
|
||||
"ldmia %0!, { r4, r5 } \n\t" \
|
||||
"ldmia %1, { r8, r9 } \n\t" \
|
||||
"umull r6, r7, %3, r4 \n\t" \
|
||||
@@ -620,6 +681,7 @@
|
||||
: "r" (b), "0" (s), "1" (d), "2" (c) \
|
||||
: "r4", "r5", "r6", "r7", "memory", "cc" );
|
||||
|
||||
#endif /* __ARM_FEATURE_DSP */
|
||||
#endif /* ARMv3 */
|
||||
|
||||
#if defined(__alpha__)
|
||||
@@ -811,8 +873,8 @@
|
||||
#else
|
||||
#define MULADDC_INIT \
|
||||
{ \
|
||||
t_int s0, s1, b0, b1; \
|
||||
t_int r0, r1, rx, ry; \
|
||||
t_uint s0, s1, b0, b1; \
|
||||
t_uint r0, r1, rx, ry; \
|
||||
b0 = ( b << biH ) >> biH; \
|
||||
b1 = ( b >> biH );
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "polarssl/bignum.h"
|
||||
#include "polarssl/bn_mul.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <gnuk-malloc.h>
|
||||
|
||||
#define ciL (sizeof(t_uint)) /* chars in limb */
|
||||
#define biL (ciL << 3) /* bits in limb */
|
||||
@@ -223,6 +223,26 @@ size_t mpi_lsb( const mpi *X )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if !defined(POLARSSL_HAVE_UDBL)
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the number of most significant bits
|
||||
*/
|
||||
@@ -1102,6 +1122,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 = (~0UL);
|
||||
|
||||
return (~0UL);
|
||||
}
|
||||
|
||||
#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)
|
||||
*/
|
||||
@@ -1156,60 +1270,10 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
|
||||
for( i = n; i > t ; i-- )
|
||||
{
|
||||
if( X.p[i] >= Y.p[t] )
|
||||
Z.p[i - t - 1] = ~0;
|
||||
Z.p[i - t - 1] = ~0UL;
|
||||
else
|
||||
{
|
||||
#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]++;
|
||||
@@ -1233,7 +1297,7 @@ int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
|
||||
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
|
||||
MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
|
||||
|
||||
if( mpi_cmp_int( &X, 0 ) < 0 )
|
||||
while( mpi_cmp_int( &X, 0 ) < 0 )
|
||||
{
|
||||
MPI_CHK( mpi_copy( &T1, &Y ) );
|
||||
MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
|
||||
@@ -1450,9 +1514,17 @@ static void mpi_montred( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
/*
|
||||
* Montgomery square: A = A * A * R^-1 mod N
|
||||
* A is placed at the upper half of D.
|
||||
*
|
||||
* n : number of limbs of N
|
||||
* np: pointer to limbs of bignum N
|
||||
* mm: m' = -N^(-1) mod b where b = 2^number-of-bit-in-limb
|
||||
* d (destination): the result [<-- temp -->][<--- A ---->]
|
||||
* lower part upper part
|
||||
* n-limb n-limb
|
||||
*/
|
||||
static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
{
|
||||
#if defined(POLARSSL_HAVE_ASM) && defined(__arm__)
|
||||
size_t i;
|
||||
register t_uint c = 0;
|
||||
|
||||
@@ -1464,6 +1536,52 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
|
||||
x_i = *xj;
|
||||
*xj++ = c;
|
||||
|
||||
#if defined(__ARM_FEATURE_DSP)
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
"mov r4, %[c]\n\t"
|
||||
"umlal r5, r4, %[x_i], %[x_i]\n\t"
|
||||
"str r5, [%[wij]], #4\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bhi 0f\n\t"
|
||||
"mov r9, %[c]\n\t" /* R9 := 0, the constant ZERO from here. */
|
||||
"beq 1f\n"
|
||||
"2:\n\t"
|
||||
"ldmia %[xj]!, { r7, r8 }\n\t"
|
||||
"ldmia %[wij], { r5, r6 }\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umaal r5, r4, %[x_i], r7\n\t"
|
||||
"umlal r5, %[c], %[x_i], r7\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
/* (C,R4,R6) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"umaal r6, r4, %[x_i], r8\n\t"
|
||||
"umlal r6, %[c], %[x_i], r8\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
/**/
|
||||
"stmia %[wij]!, { r5, r6 }\n\t"
|
||||
"cmp %[xj], %[x_max1]\n\t"
|
||||
"bcc 2b\n\t"
|
||||
"bne 0f\n"
|
||||
"1:\n\t"
|
||||
/* (C,R4,R5) := (C,R4) + w_i_j + 2*x_i*x_j; */
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"ldr r6, [%[xj]], #4\n\t"
|
||||
"umaal r5, r4, %[x_i], r6\n\t"
|
||||
"umlal r5, %[c], %[x_i], r6\n\t"
|
||||
"umaal r4, %[c], r9, r9\n\t"
|
||||
"str r5, [%[wij]], #4\n"
|
||||
"0:\n\t"
|
||||
"ldr r5, [%[wij]]\n\t"
|
||||
"adds r4, r4, r5\n\t"
|
||||
"adc %[c], %[c], #0\n\t"
|
||||
"str r4, [%[wij]]"
|
||||
: [c] "=&r" (c), [wij] "=r" (wij), [xj] "=r" (xj)
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "memory", "cc");
|
||||
#else
|
||||
asm (/* (C,R4,R5) := w_i_i + x_i*x_i; w_i_i := R5; */
|
||||
"mov %[c], #0\n\t"
|
||||
"ldr r5, [%[wij]]\n\t" /* R5 := w_i_i; */
|
||||
@@ -1525,6 +1643,7 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
: [x_i] "r" (x_i), [x_max1] "r" (&d[n*2-1]),
|
||||
"[wij]" (wij), "[xj]" (xj)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r12", "memory", "cc");
|
||||
#endif
|
||||
|
||||
c += mpi_mul_hlp( n, np, &d[i], d[i] * mm );
|
||||
}
|
||||
@@ -1536,16 +1655,29 @@ static void mpi_montsqr( size_t n, const t_uint *np, t_uint mm, t_uint *d )
|
||||
mpi_sub_hlp( n, np, d );
|
||||
else
|
||||
mpi_sub_hlp( n, d - n, d - n);
|
||||
#else
|
||||
t_uint a_input[n];
|
||||
|
||||
memcpy (a_input, &d[n], sizeof (a_input));
|
||||
mpi_montmul (n, np, mm, d, a_input);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
|
||||
*/
|
||||
#if MEMORY_SIZE >= 32
|
||||
#define MAX_WSIZE 6
|
||||
#elif MEMORY_SIZE >= 24
|
||||
#define MAX_WSIZE 5
|
||||
#else
|
||||
#define MAX_WSIZE 4
|
||||
#endif
|
||||
int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
{
|
||||
int ret;
|
||||
size_t i = mpi_msb( E );
|
||||
size_t wsize = ( i > 1024 ) ? 4 : /* Because of not enough memory. */
|
||||
size_t wsize = ( i > 1024 ) ? MAX_WSIZE :
|
||||
( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
|
||||
( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
|
||||
size_t wbits, one = 1;
|
||||
@@ -1570,7 +1702,6 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
* Init temps and window size
|
||||
*/
|
||||
mpi_montg_init( &mm, N );
|
||||
MPI_CHK( mpi_grow( X, N->n ) );
|
||||
|
||||
/*
|
||||
* If 1st call, pre-compute R^2 mod N
|
||||
@@ -1584,6 +1715,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 ) );
|
||||
@@ -1595,6 +1727,8 @@ int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
|
||||
memset (d, 0, N->n * ciL); /* Set lower half of D zero. */
|
||||
}
|
||||
|
||||
MPI_CHK( mpi_grow( X, N->n ) );
|
||||
|
||||
/*
|
||||
* W[1] = A * R^2 * R^-1 mod N = A * R mod N
|
||||
*/
|
||||
@@ -1988,17 +2122,19 @@ jkiss (struct jkiss_state *s)
|
||||
static int mpi_fill_pseudo_random ( mpi *X, size_t size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t *p;
|
||||
uint32_t *p, *p_end;
|
||||
|
||||
MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) );
|
||||
MPI_CHK( mpi_lset( X, 0 ) );
|
||||
|
||||
/* Assume little endian. */
|
||||
p = X->p;
|
||||
while (p < X->p + (size/ciL))
|
||||
p = (uint32_t *)X->p;
|
||||
p_end = (uint32_t *)(X->p + (size/sizeof (uint32_t)));
|
||||
while (p < p_end)
|
||||
*p++ = jkiss (&jkiss_state_v);
|
||||
if ((size % ciL))
|
||||
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % ciL))) - 1);
|
||||
|
||||
if ((size%sizeof (uint32_t)))
|
||||
*p = jkiss (&jkiss_state_v) & ((1 << (8*(size % sizeof (uint32_t)))) - 1);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
@@ -2139,10 +2275,24 @@ cleanup:
|
||||
* Value M: multiply all primes up to 701 (except 97) and 797
|
||||
* (so that MAX_A will be convenient value)
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
#define M_LIMBS 16
|
||||
#else
|
||||
#define M_LIMBS 31
|
||||
#endif
|
||||
#define M_SIZE 122
|
||||
|
||||
static const t_uint limbs_M[] = { /* Little endian */
|
||||
#ifdef __LP64__
|
||||
0x9344A6AB84EEB59EUL, 0xEC855CDAFF21529FUL,
|
||||
0x477E991E009BAB38UL, 0x2EEA23579F5B86F3UL,
|
||||
0xAC17D30441D6502FUL, 0x38FF52B90A468A6DUL,
|
||||
0x63630419FD42E5EFUL, 0x48CE17D091DB2572UL,
|
||||
0x708AB00AE3B57D0EUL, 0xF8A9DE08CD723598UL,
|
||||
0x731411374432C93BUL, 0x554DF2612779FAB3UL,
|
||||
0xDEEBDA58953D2BA5UL, 0xD1D66F2F5F57D007UL,
|
||||
0xB85C9607E84E9F2BUL, 0x000000000000401DUL
|
||||
#else
|
||||
0x84EEB59E, 0x9344A6AB, 0xFF21529F, 0xEC855CDA,
|
||||
0x009BAB38, 0x477E991E, 0x9F5B86F3, 0x2EEA2357,
|
||||
0x41D6502F, 0xAC17D304, 0x0A468A6D, 0x38FF52B9,
|
||||
@@ -2151,6 +2301,7 @@ static const t_uint limbs_M[] = { /* Little endian */
|
||||
0x4432C93B, 0x73141137, 0x2779FAB3, 0x554DF261,
|
||||
0x953D2BA5, 0xDEEBDA58, 0x5F57D007, 0xD1D66F2F,
|
||||
0xE84E9F2B, 0xB85C9607, 0x0000401D
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
|
||||
@@ -2158,10 +2309,18 @@ static const mpi M[1] = {{ 1, M_LIMBS, (t_uint *)limbs_M }};
|
||||
/*
|
||||
* MAX_A : 2^1024 / M - 1
|
||||
*/
|
||||
#ifdef __LP64__
|
||||
#define MAX_A_LIMBS 1
|
||||
#else
|
||||
#define MAX_A_LIMBS 2
|
||||
#endif
|
||||
#define MAX_A_FILL_SIZE 6
|
||||
static const t_uint limbs_MAX_A[] = { /* Little endian */
|
||||
#ifdef __LP64__
|
||||
0x0003FE2556A2B35FUL
|
||||
#else
|
||||
0x56A2B35F, 0x0003FE25
|
||||
#endif
|
||||
};
|
||||
|
||||
static const mpi MAX_A[1] = {{ 1, MAX_A_LIMBS, (t_uint *)limbs_MAX_A }};
|
||||
@@ -2211,9 +2370,8 @@ int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag,
|
||||
|
||||
MPI_CHK ( mpi_mul_mpi ( X, X, M ) );
|
||||
MPI_CHK ( mpi_add_abs ( X, X, B ) );
|
||||
if (X->n <= 31 || (X->p[31] & 0xc0000000) == 0)
|
||||
if (X->n <= M_LIMBS || (X->p[M_LIMBS-1] & 0xc0000000) == 0)
|
||||
continue;
|
||||
|
||||
ret = mpi_is_prime ( X );
|
||||
if (ret == 0 || ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE)
|
||||
break;
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "polarssl/md.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Makefile for reGNUal
|
||||
|
||||
PROJECT = regnual
|
||||
PROJECT = regnual-no-vidpid
|
||||
|
||||
OBJS = regnual.o usb-stm32f103.o reset.o
|
||||
|
||||
include ../src/config.mk
|
||||
|
||||
OBJS = regnual.o usb_stm32f103.o sys.o
|
||||
LDSCRIPT= regnual.ld
|
||||
|
||||
###################################
|
||||
@@ -19,11 +22,11 @@ TOPT = -mthumb -DTHUMB -mno-thumb-interwork
|
||||
# Define C warning options here
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
MCFLAGS= -mcpu=$(MCU)
|
||||
DEFS = -DFREE_STANDING
|
||||
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 +35,24 @@ LDFLAGS = -T$(LDSCRIPT) -nostartfiles $(MCFLAGS) $(TOPT)
|
||||
|
||||
all: regnual.hex
|
||||
|
||||
regnual.o: regnual.c ../src/sys.h ../src/usb_lld.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
|
||||
regnual.elf: regnual-no-vidpid.elf
|
||||
cp -p regnual-no-vidpid.elf regnual.elf
|
||||
env FILE="regnual.elf" PATH="../src:$$PATH" bash put-vid-pid-ver.sh
|
||||
|
||||
regnual.elf: $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(LDFLAGS) -o regnual.elf $(OBJS)
|
||||
usb-stm32f103.o: ../chopstx/mcu/usb-stm32f103.c
|
||||
$(CC) $(CFLAGS) -c -o usb-stm32f103.o ../chopstx/mcu/usb-stm32f103.c
|
||||
|
||||
regnual-no-vidpid.elf: $(OBJS) $(LDSCRIPT)
|
||||
$(CC) $(LDFLAGS) -o regnual-no-vidpid.elf $(OBJS)
|
||||
|
||||
clean:
|
||||
-rm -f $(OBJS) regnual.elf regnual.hex regnual.bin
|
||||
-rm -f $(OBJS) regnual-no-vidpid.elf regnual.elf regnual.hex regnual.bin \
|
||||
*.lst
|
||||
|
||||
distclean: clean
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* regnual.c -- Firmware installation for STM32F103 Flash ROM
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2015
|
||||
* Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -26,12 +26,12 @@
|
||||
* ReGNUal
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "usb_lld.h"
|
||||
#include "sys.h"
|
||||
|
||||
extern void *memset (void *s, int c, size_t n);
|
||||
|
||||
extern void set_led (int);
|
||||
extern int flash_write (uint32_t dst_addr, const uint8_t *src, size_t len);
|
||||
extern int flash_protect (void);
|
||||
@@ -51,37 +51,41 @@ static uint32_t flash_end;
|
||||
/* 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 */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
#include "../src/usb-vid-pid-ver.c.inc"
|
||||
0x00, 0x00, /* idVendor (will be replaced) */
|
||||
0x00, 0x00, /* idProduct (will be replaced) */
|
||||
0x00, 0x00, /* bcdDevice (will be replaced) */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
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,
|
||||
@@ -92,7 +96,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 */
|
||||
};
|
||||
|
||||
@@ -100,23 +104,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,
|
||||
@@ -151,19 +149,33 @@ static uint32_t fetch (int i)
|
||||
}
|
||||
|
||||
struct CRC {
|
||||
__IO uint32_t DR;
|
||||
__IO uint8_t IDR;
|
||||
volatile uint32_t DR;
|
||||
volatile uint8_t IDR;
|
||||
uint8_t RESERVED0;
|
||||
uint16_t RESERVED1;
|
||||
__IO uint32_t CR;
|
||||
volatile uint32_t CR;
|
||||
};
|
||||
static struct CRC *const CRC = (struct CRC *)0x40023000;
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
/* ... */
|
||||
};
|
||||
static struct RCC *const RCC = (struct RCC *)0x40021000;
|
||||
#define RCC_AHBENR_CRCEN 0x00000040
|
||||
|
||||
|
||||
#define CRC_CR_RESET 0x01
|
||||
static uint32_t calc_crc32 (void)
|
||||
{
|
||||
struct CRC *CRC = (struct CRC *)0x40023000;
|
||||
int i;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
|
||||
for (i = 0; i < 256/4; i++)
|
||||
@@ -173,94 +185,101 @@ static uint32_t calc_crc32 (void)
|
||||
}
|
||||
|
||||
|
||||
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
|
||||
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)
|
||||
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 && value == 0)
|
||||
else if (arg->request == USB_REGNUAL_PROTECT && arg->value == 0)
|
||||
result = flash_protect ();
|
||||
else if (req_no == USB_REGNUAL_FINISH && value == 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, struct control_info *detail)
|
||||
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)
|
||||
{
|
||||
const uint8_t *mem_info[2];
|
||||
|
||||
mem_info[0] = (const uint8_t *)FLASH_START;
|
||||
mem_info[1] = (const uint8_t *)flash_end;
|
||||
return usb_lld_reply_request (mem_info, sizeof (mem_info), detail);
|
||||
return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
|
||||
}
|
||||
else if (req_no == USB_REGNUAL_RESULT)
|
||||
return usb_lld_reply_request (&result, sizeof (uint32_t), detail);
|
||||
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 (detail->value != 0 || detail->index + detail->len > 256)
|
||||
return USB_UNSUPPORT;
|
||||
if (arg->value != 0 || arg->index + arg->len > 256)
|
||||
return -1;
|
||||
|
||||
if (detail->index + detail->len < 256)
|
||||
memset ((uint8_t *)mem + detail->index + detail->len, 0xff,
|
||||
256 - (detail->index + detail->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 + detail->index, detail->len);
|
||||
return USB_SUCCESS;
|
||||
return usb_lld_ctrl_recv (dev, mem + arg->index, arg->len);
|
||||
}
|
||||
else if (req_no == USB_REGNUAL_FLASH && detail->len == 0
|
||||
&& detail->index == 0)
|
||||
else if (arg->request == USB_REGNUAL_FLASH && arg->len == 0
|
||||
&& arg->index == 0)
|
||||
{
|
||||
uint32_t dst_addr = (0x08000000 + detail->value * 0x100);
|
||||
uint32_t dst_addr = (0x08000000 + arg->value * 0x100);
|
||||
|
||||
if (dst_addr + 256 <= flash_end)
|
||||
return USB_SUCCESS;
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
else if (req_no == USB_REGNUAL_PROTECT && detail->len == 0
|
||||
&& detail->value == 0 && detail->index == 0)
|
||||
return USB_SUCCESS;
|
||||
else if (req_no == USB_REGNUAL_FINISH && detail->len == 0
|
||||
&& detail->value == 0 && detail->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,
|
||||
struct control_info *detail)
|
||||
static int
|
||||
usb_get_descriptor (struct usb_dev *dev)
|
||||
{
|
||||
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)
|
||||
return usb_lld_reply_request (regnual_device_desc,
|
||||
sizeof (regnual_device_desc), detail);
|
||||
return usb_lld_ctrl_send (dev, regnual_device_desc,
|
||||
sizeof (regnual_device_desc));
|
||||
else if (desc_type == CONFIG_DESCRIPTOR)
|
||||
return usb_lld_reply_request (regnual_config_desc,
|
||||
sizeof (regnual_config_desc), detail);
|
||||
return usb_lld_ctrl_send (dev, regnual_config_desc,
|
||||
sizeof (regnual_config_desc));
|
||||
else if (desc_type == STRING_DESCRIPTOR)
|
||||
{
|
||||
const uint8_t *str;
|
||||
@@ -285,35 +304,38 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
||||
size = sizeof (regnual_string_serial);
|
||||
break;
|
||||
default:
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return usb_lld_reply_request (str, size, detail);
|
||||
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, struct control_info *detail)
|
||||
{
|
||||
(void)cmd; (void)detail;
|
||||
return USB_UNSUPPORT;
|
||||
/* Do nothing when current_conf == value */
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +349,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[])
|
||||
{
|
||||
@@ -334,8 +381,19 @@ main (int argc, char *argv[])
|
||||
|
||||
set_led (0);
|
||||
|
||||
#if defined(STM32F103_OVERRIDE_FLASH_SIZE_KB)
|
||||
flash_end = FLASH_START_ADDR + STM32F103_OVERRIDE_FLASH_SIZE_KB*1024;
|
||||
#else
|
||||
flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
usb_lld_init (regnual_config_desc[7]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
@@ -345,3 +403,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
typedef unsigned long size_t;
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define NULL 0
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
110
src/Makefile
Normal file
110
src/Makefile
Normal file
@@ -0,0 +1,110 @@
|
||||
# Makefile for Gnuk
|
||||
|
||||
# Define project name here
|
||||
PROJECT = gnuk
|
||||
|
||||
CHOPSTX = ../chopstx
|
||||
|
||||
CSRC = main.c call-rsa.c \
|
||||
usb_desc.c usb_ctrl.c \
|
||||
usb-ccid.c openpgp.c ac.c openpgp-do.c flash.c \
|
||||
bn.c mod.c \
|
||||
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 =
|
||||
|
||||
CRYPTDIR = ../polarssl
|
||||
CRYPTSRCDIR = $(CRYPTDIR)/library
|
||||
CRYPTINCDIR = $(CRYPTDIR)/include
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
|
||||
|
||||
CSRC += $(CRYPTSRC)
|
||||
INCDIR += $(CRYPTINCDIR)
|
||||
|
||||
include config.mk
|
||||
|
||||
USE_SYS = yes
|
||||
USE_USB = yes
|
||||
USE_ADC = yes
|
||||
USE_EVENTFLAG = yes
|
||||
|
||||
ifeq ($(EMULATION),)
|
||||
DEFS += -DFLASH_UPGRADE_SUPPORT
|
||||
else
|
||||
DEFS += -DBN256_C_IMPLEMENTATION
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_DEBUG),)
|
||||
CSRC += debug.c
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_PINPAD),)
|
||||
CSRC += pin-$(ENABLE_PINPAD).c
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PINPAD),dnd)
|
||||
CSRC += usb-msc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CHIP),stm32f103)
|
||||
CSRC += mcu-stm32f103.c
|
||||
endif
|
||||
|
||||
ifneq ($(USE_DFU),)
|
||||
OBJS_ADD += build/stdaln-sys-bin.o
|
||||
endif
|
||||
|
||||
###################################
|
||||
CC = $(CROSS)gcc
|
||||
LD = $(CROSS)gcc
|
||||
OBJCOPY = $(CROSS)objcopy
|
||||
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
OPT = -O3 -Os -g
|
||||
|
||||
#######################
|
||||
include $(CHOPSTX)/rules.mk
|
||||
|
||||
board.h:
|
||||
@echo Please run configure to have a symbolic link \'board.h\'
|
||||
@exit 1
|
||||
|
||||
sys.c: board.h
|
||||
|
||||
build/bignum.o: OPT = -O3 -g
|
||||
|
||||
build/stdaln-sys.elf: build/sys-$(CHIP).o stdaln-sys.ld
|
||||
@echo
|
||||
$(LD) -v $< $(MCFLAGS) -nostartfiles -Tstdaln-sys.ld -Wl,--no-warn-mismatch,--gc-sections $(LLIBDIR) -o $@
|
||||
|
||||
build/stdaln-sys-bin.o: build/stdaln-sys.elf
|
||||
@echo
|
||||
$(OBJCOPY) -O binary -j .sys $< build/stdaln-sys.bin
|
||||
$(OBJCOPY) -I binary -O default --rename-section .data=.rodata \
|
||||
build/stdaln-sys.bin $@
|
||||
|
||||
distclean: clean
|
||||
-rm -f gnuk.ld stdaln-sys.ld config.h board.h config.mk \
|
||||
usb-strings.c.inc put-vid-pid-ver.sh
|
||||
|
||||
ifeq ($(EMULATION),)
|
||||
build/gnuk.elf: build/gnuk-no-vidpid.elf binary-edit.sh put-vid-pid-ver.sh
|
||||
cp -p build/gnuk-no-vidpid.elf build/gnuk.elf
|
||||
env FILE="build/gnuk.elf" bash put-vid-pid-ver.sh
|
||||
$(OBJCOPY) -O ihex build/gnuk.elf build/gnuk.hex
|
||||
$(OBJCOPY) -O binary build/gnuk.elf build/gnuk.bin
|
||||
else
|
||||
# By specifying DESTDIR on invocation of "make", you can install
|
||||
# program to different ROOT.
|
||||
|
||||
# The variables prefix, exec_prefix, libexecdir are defined in
|
||||
# config.mk.
|
||||
|
||||
install: build/gnuk
|
||||
test -d "$(DESTDIR)$(libexecdir)" || mkdir -p "$(DESTDIR)$(libexecdir)"
|
||||
install -c build/gnuk "$(DESTDIR)$(libexecdir)"
|
||||
|
||||
endif
|
||||
@@ -1,75 +0,0 @@
|
||||
# Makefile for Gnuk
|
||||
|
||||
# Define project name here
|
||||
PROJECT = gnuk
|
||||
|
||||
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 \
|
||||
call-rsa.c \
|
||||
usb-icc.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 sys.c
|
||||
|
||||
INCDIR =
|
||||
|
||||
CRYPTDIR = ../polarssl
|
||||
CRYPTSRCDIR = $(CRYPTDIR)/library
|
||||
CRYPTINCDIR = $(CRYPTDIR)/include
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/aes.c
|
||||
|
||||
CSRC += $(CRYPTSRC)
|
||||
INCDIR += $(CRYPTINCDIR)
|
||||
|
||||
@PINPAD_MAKE_OPTION@
|
||||
@DEBUG_MAKE_OPTION@
|
||||
@HEXOUTPUT_MAKE_OPTION@
|
||||
|
||||
USE_EVENTFLAG = yes
|
||||
|
||||
ifneq ($(ENABLE_DEBUG),)
|
||||
CSRC += debug.c
|
||||
endif
|
||||
|
||||
ifneq ($(ENABLE_PINPAD),)
|
||||
CSRC += pin-$(ENABLE_PINPAD).c
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_PINPAD),dnd)
|
||||
CSRC += usb-msc.c
|
||||
endif
|
||||
|
||||
###################################
|
||||
CROSS = arm-none-eabi-
|
||||
CC = $(CROSS)gcc
|
||||
LD = $(CROSS)gcc
|
||||
OBJCOPY = $(CROSS)objcopy
|
||||
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
# DEFS: Add
|
||||
DEFS = @HAVE_SYS_H@
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
#######################
|
||||
include $(CHOPSTX)/rules.mk
|
||||
|
||||
board.h:
|
||||
@echo Please run configure to have a symbolic link \'board.h\'
|
||||
@exit 1
|
||||
|
||||
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
|
||||
58
src/ac.c
58
src/ac.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ac.c -- Check access condition
|
||||
*
|
||||
* Copyright (C) 2010, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2012, 2013, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -63,7 +63,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks_pw1, int save_ks)
|
||||
{
|
||||
int pw_len;
|
||||
int r1, r2;
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
@@ -73,12 +73,14 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
|
||||
if (ks_pw1 == NULL)
|
||||
{
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
const uint8_t *initial_pw;
|
||||
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
gpg_do_get_initial_pw_setting (0, &pw_len, &initial_pw);
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW1, pw_len))
|
||||
|| memcmp (pw, initial_pw, pw_len))
|
||||
goto failure;
|
||||
}
|
||||
else
|
||||
@@ -97,21 +99,31 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
|
||||
|
||||
if (access == AC_PSO_CDS_AUTHORIZED)
|
||||
{
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
r2 = 0;
|
||||
}
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
else
|
||||
{
|
||||
int r1, r2;
|
||||
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER, keystring);
|
||||
r2 = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER, keystring);
|
||||
|
||||
if (r1 < 0 || r2 < 0)
|
||||
r = -1;
|
||||
else if (r1 == 0)
|
||||
{
|
||||
if (r2 == 0)
|
||||
/* No encryption/authentication keys, then, check signing key. */
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
else
|
||||
r = r2;
|
||||
}
|
||||
else if (r2 == 0)
|
||||
r = r1;
|
||||
else
|
||||
r = 1;
|
||||
}
|
||||
|
||||
if (r1 < 0 || r2 < 0
|
||||
|| (r1 == 0 && r2 == 0 && ks_pw1 != NULL
|
||||
&& ((ks_pw1[0] & PW_LEN_KEYSTRING_BIT) == 0
|
||||
|| memcmp (KS_GET_KEYSTRING (ks_pw1),
|
||||
keystring, KEYSTRING_MD_SIZE) != 0)))
|
||||
if (r < 0)
|
||||
{
|
||||
failure:
|
||||
gpg_pw_increment_err_counter (PW_ERR_PW1);
|
||||
@@ -161,7 +173,7 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
const uint8_t *ks, int save_ks)
|
||||
{
|
||||
int pw_len;
|
||||
int r1, r2;
|
||||
int r;
|
||||
uint8_t keystring[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
@@ -169,7 +181,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;
|
||||
|
||||
@@ -177,12 +189,11 @@ verify_admin_00 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
if (save_ks)
|
||||
memcpy (keystring_md_pw3, keystring, KEYSTRING_MD_SIZE);
|
||||
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
|
||||
r2 = 0;
|
||||
r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_ADMIN, keystring);
|
||||
|
||||
if (r1 < 0 || r2 < 0)
|
||||
if (r < 0)
|
||||
return -1;
|
||||
else if (r1 == 0 && r2 == 0)
|
||||
else if (r == 0)
|
||||
if ((ks[0] & PW_LEN_KEYSTRING_BIT) == 0
|
||||
|| memcmp (KS_GET_KEYSTRING (ks), keystring, KEYSTRING_MD_SIZE) != 0)
|
||||
return -1;
|
||||
@@ -220,6 +231,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t *initial_pw;
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (ks_pw1 != NULL)
|
||||
@@ -237,13 +249,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For the case of empty PW3 (with empty PW1), pass phrase
|
||||
* should be OPENPGP_CARD_INITIAL_PW3
|
||||
* For the case of empty PW3 (with empty PW1), passphrase is
|
||||
* OPENPGP_CARD_INITIAL_PW3, or defined by KDF DO.
|
||||
*/
|
||||
pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
gpg_do_get_initial_pw_setting (1, &pw_len, &initial_pw);
|
||||
if ((pw_len_known >=0 && pw_len_known != pw_len)
|
||||
|| buf_len < pw_len
|
||||
|| strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3, pw_len))
|
||||
|| memcmp (pw, initial_pw, pw_len))
|
||||
goto failure;
|
||||
|
||||
admin_authorized = BY_ADMIN;
|
||||
|
||||
16
src/adc.h
16
src/adc.h
@@ -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);
|
||||
@@ -1,318 +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, 2015
|
||||
* 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
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
#include "sys.h"
|
||||
#if defined(HAVE_SYS_H)
|
||||
# define SYS_BOARD_ID sys_board_id
|
||||
#else
|
||||
# include "board.h"
|
||||
# define SYS_BOARD_ID BOARD_ID
|
||||
#endif
|
||||
|
||||
static void
|
||||
get_adc_config (uint32_t config[4])
|
||||
{
|
||||
config[2] = ADC_SQR1_NUM_CH(2);
|
||||
switch (SYS_BOARD_ID)
|
||||
{
|
||||
case BOARD_ID_FST_01:
|
||||
config[0] = 0;
|
||||
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
|
||||
| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
|
||||
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
|
||||
break;
|
||||
|
||||
case BOARD_ID_OLIMEX_STM32_H103:
|
||||
case BOARD_ID_STBEE:
|
||||
config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
|
||||
| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5);
|
||||
config[1] = 0;
|
||||
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10)
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11);
|
||||
break;
|
||||
|
||||
case BOARD_ID_STBEE_MINI:
|
||||
config[0] = 0;
|
||||
config[1] = ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
|
||||
| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5);
|
||||
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1)
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
|
||||
break;
|
||||
|
||||
case BOARD_ID_CQ_STARM:
|
||||
case BOARD_ID_FST_01_00:
|
||||
case BOARD_ID_MAPLE_MINI:
|
||||
case BOARD_ID_STM32_PRIMER2:
|
||||
case BOARD_ID_STM8S_DISCOVERY:
|
||||
case BOARD_ID_ST_DONGLE:
|
||||
case BOARD_ID_ST_NUCLEO_F103:
|
||||
default:
|
||||
config[0] = 0;
|
||||
config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
|
||||
| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5);
|
||||
config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
|
||||
| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void adc_start (void)
|
||||
{
|
||||
uint32_t config[4];
|
||||
|
||||
get_adc_config (config);
|
||||
|
||||
/* 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 = config[0];
|
||||
ADC2->SMPR2 = config[1];
|
||||
ADC2->SQR1 = config[2];
|
||||
ADC2->SQR2 = 0;
|
||||
ADC2->SQR3 = config[3];
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/binary-edit.sh
Normal file
76
src/binary-edit.sh
Normal file
@@ -0,0 +1,76 @@
|
||||
# This is a Bash script to be included.
|
||||
|
||||
# Idx Name Size VMA LMA File off Algn
|
||||
# =================
|
||||
# 2 .text 00004a40 080010f0 080010f0 000110f0 2**4
|
||||
# 08006550 l O .text 00000012 device_desc
|
||||
# =================
|
||||
# VMA =0x080010f0
|
||||
# FOFF=0x000110f0
|
||||
# ADDR=0x08005ad0
|
||||
# file_off_ADDR = ADDR - VMA + FOFF
|
||||
# = 0x08005ad0 - 0x080010f0 + 0x000110f0 = 0x00015ad0
|
||||
|
||||
function calc_addr () {
|
||||
local line_sym="" VMA FOFF ADDR
|
||||
|
||||
arm-none-eabi-objdump -h -t -j .text $FILE | \
|
||||
egrep -e '(^ +[0-9] +\.text +|device_desc)' | \
|
||||
while read -r F0 F1 F2 F3 F4 F5 F6; do
|
||||
if [ -z "$line_sym" ]; then
|
||||
VMA=$F3
|
||||
FOFF=$F5
|
||||
line_sym="next is a line for the symbol"
|
||||
else
|
||||
ADDR=$F0
|
||||
echo "$((0x$ADDR - 0x$VMA + 0x$FOFF))"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
declare -a OFFSETS
|
||||
OFFSETS=($(calc_addr))
|
||||
file_off_ADDR=${OFFSETS[0]}
|
||||
file_off_fraucheky_ADDR=${OFFSETS[1]}
|
||||
|
||||
echo "Offset is $file_off_ADDR"
|
||||
if [ -n "$file_off_fraucheky_ADDR" ]; then
|
||||
echo "Offset is $file_off_fraucheky_ADDR"
|
||||
fi
|
||||
|
||||
function replace_file_byte_at () {
|
||||
printf "\x$1" | dd of=$FILE bs=1 seek=$2 conv=notrunc >& /dev/null
|
||||
}
|
||||
|
||||
#
|
||||
# vid_lsb: 8
|
||||
# vid_msb: 9
|
||||
# pid_lsb: 10
|
||||
# pid_msb: 11
|
||||
# bcd_device_lsb: 12
|
||||
# bcd_device_msb: 13
|
||||
#
|
||||
|
||||
function replace_vid_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 8))
|
||||
}
|
||||
|
||||
function replace_vid_msb () {
|
||||
replace_file_byte_at $1 $((addr + 9))
|
||||
}
|
||||
|
||||
function replace_pid_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 10))
|
||||
}
|
||||
|
||||
function replace_pid_msb () {
|
||||
replace_file_byte_at $1 $((addr + 11))
|
||||
}
|
||||
|
||||
function replace_bcd_device_lsb () {
|
||||
replace_file_byte_at $1 $((addr + 12))
|
||||
}
|
||||
|
||||
function replace_bcd_device_msb () {
|
||||
replace_file_byte_at $1 $((addr + 13))
|
||||
}
|
||||
23
src/bn.c
23
src/bn.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* bn.c -- 256-bit (and 512-bit) bignum calculation
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2013, 2014, 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -412,17 +413,15 @@ bn256_cmp (const bn256 *A, const bn256 *B)
|
||||
void
|
||||
bn256_random (bn256 *X)
|
||||
{
|
||||
const uint8_t *rand = random_bytes_get ();
|
||||
int i, j;
|
||||
const uint8_t *rand;
|
||||
|
||||
X->word[7] = ((uint32_t *)rand)[7];
|
||||
X->word[6] = ((uint32_t *)rand)[6];
|
||||
X->word[5] = ((uint32_t *)rand)[5];
|
||||
X->word[4] = ((uint32_t *)rand)[4];
|
||||
X->word[3] = ((uint32_t *)rand)[3];
|
||||
X->word[2] = ((uint32_t *)rand)[2];
|
||||
X->word[1] = ((uint32_t *)rand)[1];
|
||||
X->word[0] = ((uint32_t *)rand)[0];
|
||||
|
||||
random_bytes_free (rand);
|
||||
for (i = 0; i < 256/256; i++)
|
||||
{
|
||||
rand = random_bytes_get ();
|
||||
for (j = 0; j < BN256_WORDS; j++)
|
||||
X->word[i*BN256_WORDS+j] = ((uint32_t *)rand)[j];
|
||||
random_bytes_free (rand);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
|
||||
*
|
||||
* Copyright (C) 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2013, 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -54,28 +54,21 @@ FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
FUNC(ecc_compute_public) (const uint8_t *key_data)
|
||||
int
|
||||
FUNC(ecc_compute_public) (const uint8_t *key_data, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p0, *p, *p1;
|
||||
uint8_t *p, *p1;
|
||||
ac q[1];
|
||||
bn256 k[1];
|
||||
int i;
|
||||
|
||||
p0 = (uint8_t *)malloc (ECDSA_BYTE_SIZE * 2);
|
||||
if (p0 == NULL)
|
||||
return NULL;
|
||||
|
||||
p = (uint8_t *)k;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
|
||||
if (FUNC(compute_kG) (q, k) < 0)
|
||||
{
|
||||
free (p0);
|
||||
return NULL;
|
||||
}
|
||||
return -1;
|
||||
|
||||
p = p0;
|
||||
p = pubkey;
|
||||
p1 = (uint8_t *)q->x;
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
|
||||
@@ -83,7 +76,7 @@ FUNC(ecc_compute_public) (const uint8_t *key_data)
|
||||
for (i = 0; i < ECDSA_BYTE_SIZE; i++)
|
||||
*p++ = p1[ECDSA_BYTE_SIZE - i - 1];
|
||||
|
||||
return p0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* call-ec_p256k1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256k1)
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* call-ec_p256r1.c - interface between Gnuk and Elliptic curve over
|
||||
* GF(p256r1)
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bn.h"
|
||||
#include "affine.h"
|
||||
|
||||
100
src/call-rsa.c
100
src/call-rsa.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2017
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -24,16 +24,26 @@
|
||||
|
||||
#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"
|
||||
|
||||
static rsa_context rsa_ctx;
|
||||
static struct chx_cleanup clp;
|
||||
|
||||
static void
|
||||
rsa_cleanup (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
rsa_free (&rsa_ctx);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
@@ -66,12 +76,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, pubkey_len);
|
||||
chopstx_setcancelstate (cs);
|
||||
chopstx_cleanup_pop (0);
|
||||
}
|
||||
|
||||
rsa_free (&rsa_ctx);
|
||||
@@ -92,28 +110,23 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
/*
|
||||
* LEN: length in byte
|
||||
*/
|
||||
uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
int
|
||||
modulus_calc (const uint8_t *p, int len, uint8_t *pubkey)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
int ret;
|
||||
|
||||
modulus = malloc (len);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P); mpi_init (&Q); mpi_init (&N);
|
||||
MPI_CHK( mpi_read_binary (&P, p, len / 2) );
|
||||
MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
|
||||
MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
|
||||
MPI_CHK( mpi_write_binary (&N, modulus, len) );
|
||||
MPI_CHK( mpi_write_binary (&N, pubkey, len) );
|
||||
cleanup:
|
||||
mpi_free (&P); mpi_free (&Q); mpi_free (&N);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
else
|
||||
return modulus;
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +136,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int ret;
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
size_t output_len;
|
||||
#endif
|
||||
|
||||
DEBUG_INFO ("RSA decrypt:");
|
||||
DEBUG_WORD ((uint32_t)&ret);
|
||||
@@ -150,10 +166,26 @@ 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. */
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, &output_len, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
*output_len_p = (unsigned int)output_len;
|
||||
#else
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, output_len_p, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
#endif
|
||||
chopstx_setcancelstate (cs);
|
||||
chopstx_cleanup_pop (0);
|
||||
}
|
||||
|
||||
rsa_free (&rsa_ctx);
|
||||
@@ -204,43 +236,39 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
|
||||
|
||||
#define RSA_EXPONENT 0x10001
|
||||
|
||||
uint8_t *
|
||||
rsa_genkey (int pubkey_len)
|
||||
int
|
||||
rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q)
|
||||
{
|
||||
int ret;
|
||||
uint8_t index = 0;
|
||||
uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
|
||||
uint8_t *p = p_q_modulus;
|
||||
uint8_t *q = p_q_modulus + pubkey_len / 2;
|
||||
uint8_t *modulus = p_q_modulus + pubkey_len;
|
||||
uint8_t *p = p_q;
|
||||
uint8_t *q = p_q + pubkey_len / 2;
|
||||
int cs;
|
||||
|
||||
extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng);
|
||||
extern void neug_flush (void);
|
||||
|
||||
if (p_q_modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
neug_flush ();
|
||||
prng_seed (random_gen, &index);
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
|
||||
clp.next = NULL;
|
||||
clp.routine = rsa_cleanup;
|
||||
clp.arg = NULL;
|
||||
chopstx_cleanup_push (&clp);
|
||||
cs = chopstx_setcancelstate (0); /* Allow cancellation. */
|
||||
MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
|
||||
RSA_EXPONENT) );
|
||||
if (ret != 0)
|
||||
{
|
||||
free (p_q_modulus);
|
||||
rsa_free (&rsa_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) );
|
||||
MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
|
||||
|
||||
cleanup:
|
||||
rsa_free (&rsa_ctx);
|
||||
chopstx_setcancelstate (cs);
|
||||
chopstx_cleanup_pop (1);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
return -1;
|
||||
else
|
||||
return p_q_modulus;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
#define ENABLE_VIRTUAL_COM_PORT 1
|
||||
#endif
|
||||
@DFU_DEFINE@
|
||||
@ORIGIN_DEFINE@
|
||||
@ORIGIN_REAL_DEFINE@
|
||||
@PINPAD_DEFINE@
|
||||
@PINPAD_MORE_DEFINE@
|
||||
@CERTDO_DEFINE@
|
||||
@HID_CARD_CHANGE_DEFINE@
|
||||
@LIFE_CYCLE_MANAGEMENT_DEFINE@
|
||||
@ACKBTN_DEFINE@
|
||||
@SERIALNO_STR_LEN_DEFINE@
|
||||
@KDF_DO_REQUIRED_DEFINE@
|
||||
|
||||
345
src/configure
vendored
345
src/configure
vendored
@@ -6,10 +6,11 @@ nl=$'\n'
|
||||
#
|
||||
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
|
||||
#
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2021
|
||||
# Free Software Initiative of Japan
|
||||
#
|
||||
# This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
#
|
||||
# Gnuk is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -23,37 +24,57 @@ nl=$'\n'
|
||||
# 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=FST_01
|
||||
verbose=no
|
||||
target=ST_DONGLE
|
||||
with_dfu=default
|
||||
debug=no
|
||||
sys1_compat=yes
|
||||
pinpad=no
|
||||
certdo=no
|
||||
hid_card_change=no
|
||||
factory_reset=yes
|
||||
ackbtn_support=yes
|
||||
flash_override=""
|
||||
kdf_do=${kdf_do:-optional}
|
||||
# For emulation
|
||||
prefix=/usr/local
|
||||
exec_prefix='${prefix}'
|
||||
libexecdir='${exec_prefix}/libexec'
|
||||
|
||||
# Revision number
|
||||
if test -d ../.git; then
|
||||
REVISION=`git describe --dirty="-modified"`
|
||||
if test -e ../.git; then
|
||||
if type git >/dev/null 2>&1; then
|
||||
REVISION=$(git describe --dirty="-modified")
|
||||
else
|
||||
# echo 'No git available, please install git'
|
||||
GIT_REVISION=$(sed -e 's/^\(.......\).*$/g\1/' "../.git/$(sed -e 's/^ref: //' ../.git/HEAD)")
|
||||
REVISION=$(cat ../VERSION)-$GIT_REVISION
|
||||
fi
|
||||
else
|
||||
REVISION=`cat ../VERSION`
|
||||
REVISION=$(cat ../VERSION)
|
||||
fi
|
||||
|
||||
# Process each option
|
||||
for option; do
|
||||
case $option in
|
||||
*=*) optarg=`expr "X$option" : '[^=]*=\(.*\)'` ;;
|
||||
*=*) optarg=$(expr "X$option" : '[^=]*=\(.*\)') ;;
|
||||
*) optarg=yes ;;
|
||||
esac
|
||||
|
||||
case $option in
|
||||
-h | --help)
|
||||
help=yes ;;
|
||||
-v | --verbose)
|
||||
verbose=yes ;;
|
||||
--vidpid=*)
|
||||
vidpid=$optarg ;;
|
||||
--target=*)
|
||||
@@ -78,10 +99,23 @@ for option; do
|
||||
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)
|
||||
with_dfu=no ;;
|
||||
#
|
||||
# For emulation
|
||||
#
|
||||
--prefix=*)
|
||||
prefix=optarg ;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=optarg ;;
|
||||
--libexecdir=*)
|
||||
libexecdir=optarg ;;
|
||||
*)
|
||||
echo "Unrecognized option \`$option'" >&2
|
||||
echo "Try \`$0 --help' for more information." >&2
|
||||
@@ -102,13 +136,22 @@ Configuration:
|
||||
--target=TARGET specify target [FST_01]
|
||||
supported targets are:
|
||||
FST_01
|
||||
FST_01G
|
||||
FST_01SZ
|
||||
OLIMEX_STM32_H103
|
||||
MAPLE_MINI
|
||||
ST_DONGLE
|
||||
ST_NUCLEO_F103
|
||||
NITROKEY_START
|
||||
BLUE_PILL
|
||||
STM8S_DISCOVERY
|
||||
CQ_STARM
|
||||
STM32_PRIMER2
|
||||
STBEE
|
||||
STBEE_MINI
|
||||
MAPLE_MINI
|
||||
CQ_STARM
|
||||
FST_01_00 (unreleased version with 8MHz XTAL)
|
||||
--enable-factory-reset
|
||||
support life cycle management [no]
|
||||
--enable-debug debug with virtual COM port [no]
|
||||
--enable-pinpad=cir
|
||||
PIN entry support [no]
|
||||
@@ -123,15 +166,12 @@ EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test "$vidpid" = "none"; then
|
||||
echo "Please specify Vendor ID and Product ID by --vidpid option."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BOARD_HEADER_FILE=board-`echo $target | tr '_[:upper:]' '-[:lower:]'`.h
|
||||
echo Header file is: $BOARD_HEADER_FILE
|
||||
ln -sf ../chopstx/board/$BOARD_HEADER_FILE board.h
|
||||
BOARD_HEADER_FILE=board-$(echo $target | tr '_[:upper:]' '-[:lower:]').h
|
||||
echo "Header file is: $BOARD_HEADER_FILE"
|
||||
ln -sf "../chopstx/board/$BOARD_HEADER_FILE" board.h
|
||||
|
||||
# Frequency
|
||||
MHZ=72
|
||||
# Flash page size in byte
|
||||
FLASH_PAGE_SIZE=1024
|
||||
# Flash memory size in KiB
|
||||
@@ -141,6 +181,10 @@ MEMORY_SIZE=20
|
||||
|
||||
# Settings for TARGET
|
||||
case $target in
|
||||
BLUE_PILL|STM8S_DISCOVERY)
|
||||
# It's 64KB version of STM32F103, but actually has 128KB
|
||||
flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB=128"
|
||||
;;
|
||||
CQ_STARM|STBEE_MINI)
|
||||
if test "$with_dfu" = "default"; then
|
||||
with_dfu=yes;
|
||||
@@ -157,13 +201,57 @@ STBEE)
|
||||
if test "$with_dfu" = "default"; then
|
||||
with_dfu=yes;
|
||||
fi ;;
|
||||
STM8S_DISCOVERY)
|
||||
FLASH_SIZE=64
|
||||
BLUE_PILL_G)
|
||||
MHZ=96
|
||||
;;
|
||||
FST_01SZ)
|
||||
MHZ=96
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
def_mhz="-DMHZ=$MHZ"
|
||||
if test "$target" = "GNU_LINUX"; then
|
||||
ldscript=""
|
||||
chip="gnu-linux"
|
||||
arch="gnu-linux"
|
||||
emulation="yes"
|
||||
cross=""
|
||||
mcu="none"
|
||||
kdf_do=${kdf_do:-required}
|
||||
def_emulation="-DGNU_LINUX_EMULATION"
|
||||
def_memory_size="-DMEMORY_SIZE=1024"
|
||||
enable_hexoutput=""
|
||||
libs="-lpthread"
|
||||
else
|
||||
ldscript="gnuk.ld"
|
||||
chip="stm32f103"
|
||||
arch="cortex-m"
|
||||
emulation=""
|
||||
cross="arm-none-eabi-"
|
||||
mcu="cortex-m3"
|
||||
def_emulation=""
|
||||
def_memory_size="-DMEMORY_SIZE=$MEMORY_SIZE"
|
||||
enable_hexoutput=yes
|
||||
libs=""
|
||||
fi
|
||||
|
||||
if test "$emulation" = "yes"; then
|
||||
if test "$vidpid" = "none"; then
|
||||
vidpid=0000:0000
|
||||
else
|
||||
echo "Please don't specify VID:PID for emulation at compile time;"
|
||||
echo "It is a user who should specify VID:PID at run time."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if test "$vidpid" = "none"; then
|
||||
echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# --enable-debug option
|
||||
if test "$debug" = "yes"; then
|
||||
DEBUG_MAKE_OPTION="ENABLE_DEBUG=1"
|
||||
@@ -175,29 +263,35 @@ else
|
||||
echo "Debug option disabled"
|
||||
fi
|
||||
|
||||
ORIGIN_REAL=0x08000000
|
||||
ORIGIN_REAL_DEFINE="#define ORIGIN_REAL $ORIGIN_REAL"
|
||||
# --with-dfu option
|
||||
if test "$with_dfu" = "yes"; then
|
||||
if test "$target" = "FST_01" -o "$target" = "FST_01_00"; then
|
||||
echo "FST-01 doesn't have DFU loader, you should not use --with-dfu."
|
||||
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`
|
||||
if test "$target" = "MAPLE_MINI"; then
|
||||
# Note that the default bootloader is too large, need for instance
|
||||
# STM32duino for DFU on Maple Mini
|
||||
ORIGIN=0x08002000
|
||||
FLASH_SIZE=$((FLASH_SIZE - 8))
|
||||
else
|
||||
ORIGIN=0x08003000
|
||||
FLASH_SIZE=$((FLASH_SIZE - 12))
|
||||
fi
|
||||
DFU_DEFINE="#define DFU_SUPPORT 1"
|
||||
HEXOUTPUT_MAKE_OPTION="ENABLE_OUTPUT_HEX=yes"
|
||||
else
|
||||
with_dfu=no
|
||||
echo "Configured for bare system (no-DFU)"
|
||||
ORIGIN=0x08000000
|
||||
ORIGIN=${ORIGIN_REAL}
|
||||
DFU_DEFINE="#undef DFU_SUPPORT"
|
||||
HEXOUTPUT_MAKE_OPTION=""
|
||||
fi
|
||||
ORIGIN_DEFINE="#define ORIGIN $ORIGIN"
|
||||
|
||||
# --enable-pinpad option
|
||||
MSC_SIZE="0"
|
||||
TIM_SIZE="0"
|
||||
EXT_SIZE="0"
|
||||
if test "$pinpad" = "no"; then
|
||||
PINPAD_MAKE_OPTION="# ENABLE_PINPAD="
|
||||
PINPAD_DEFINE="#undef PINPAD_SUPPORT"
|
||||
@@ -208,12 +302,6 @@ else
|
||||
PINPAD_DEFINE="#define PINPAD_SUPPORT 1"
|
||||
PINPAD_MORE_DEFINE="#define PINPAD_${pinpad^^[a-z]}_SUPPORT 1"
|
||||
echo "PIN pad option enabled ($pinpad)"
|
||||
if test "$pinpad" = "dnd"; then
|
||||
MSC_SIZE="0x0200"
|
||||
elif test "$pinpad" = "cir"; then
|
||||
TIM_SIZE="0x00c0"
|
||||
EXT_SIZE="0x00c0"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --enable-certdo option
|
||||
@@ -234,70 +322,125 @@ else
|
||||
echo "Card insert/removal by HID device is NOT supported"
|
||||
fi
|
||||
|
||||
# --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
|
||||
LIFE_CYCLE_MANAGEMENT_DEFINE="#undef LIFE_CYCLE_MANAGEMENT_SUPPORT"
|
||||
echo "Life cycle management is NOT supported"
|
||||
fi
|
||||
|
||||
# Acknowledge button support
|
||||
if test "$ackbtn_support" = "yes"; then
|
||||
ACKBTN_DEFINE="#define ACKBTN_SUPPORT 1"
|
||||
echo "Acknowledge button is supported"
|
||||
else
|
||||
ACKBTN_DEFINE="#undef ACKBTN_SUPPORT"
|
||||
echo "Acknowledge button is not supported"
|
||||
fi
|
||||
|
||||
# KDF Data Object is always required for GNU/Linux emulation
|
||||
if test "$kdf_do" = "required"; then
|
||||
KDF_DO_REQUIRED_DEFINE="#define KDF_DO_REQUIRED 1"
|
||||
echo "KDF DO is required before key import/generation"
|
||||
else
|
||||
KDF_DO_REQUIRED_DEFINE="#undef KDF_DO_REQUIRED"
|
||||
fi
|
||||
|
||||
### !!! Replace following string of "FSIJ" to yours !!! ####
|
||||
SERIALNO="FSIJ-`cat ../VERSION | sed -e 's%^[^/]*/%%'`-"
|
||||
SERIALNO="DTS-$(sed -e 's%^[^/]*/%%' <../VERSION)-"
|
||||
|
||||
SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"
|
||||
|
||||
|
||||
if test "$sys1_compat" = "yes"; then
|
||||
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo"
|
||||
CONFIG="$target:dfu=$with_dfu:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
|
||||
else
|
||||
if test "$with_dfu" = "yes"; then
|
||||
echo "Common binary can't support DFU loader, don't use --with-dfu."
|
||||
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"
|
||||
CONFIG="common:debug=$debug:pinpad=$pinpad:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
|
||||
fi
|
||||
|
||||
output_vid_pid_version () {
|
||||
echo $VIDPID | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* idVendor */\\${nl} 0x\4, 0x\3, /* idProduct */%p"
|
||||
echo $VERSION | sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$% 0x\2, 0x\1, /* bcdDevice */%p"
|
||||
echo "$VIDPID" | \
|
||||
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2\t\3\t\4%p" | \
|
||||
while read -r FIRST SECOND THIRD FOURTH; do
|
||||
if test $FIRST != 00; then
|
||||
echo replace_vid_msb $FIRST
|
||||
fi
|
||||
if test $SECOND != 00; then
|
||||
echo replace_vid_lsb $SECOND
|
||||
fi
|
||||
if test $THIRD != 00; then
|
||||
echo replace_pid_msb $THIRD
|
||||
fi
|
||||
if test $FOURTH != 00; then
|
||||
echo replace_pid_lsb $FOURTH
|
||||
fi
|
||||
done
|
||||
echo "$VERSION" | \
|
||||
sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2%p" | \
|
||||
while read -r FIRST SECOND; do
|
||||
if test $FIRST != 00; then
|
||||
echo replace_bcd_device_msb $FIRST
|
||||
fi
|
||||
if test $SECOND != 00; then
|
||||
echo replace_bcd_device_lsb $SECOND
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
output_vendor_product_serial_strings () {
|
||||
prefix=$1
|
||||
name=$1
|
||||
|
||||
echo "static const uint8_t ${prefix}string_vendor[] = {"
|
||||
echo " ${#VENDOR}*2+2, /* bLength */"
|
||||
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}string_vendor[] = {"
|
||||
echo " ${#VENDOR}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Manufacturer: \"$VENDOR\" */"
|
||||
echo $VENDOR | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo "$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 " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}string_product[] = {"
|
||||
echo " ${#PRODUCT}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Product name: \"$PRODUCT\" */"
|
||||
echo $PRODUCT | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo "$PRODUCT" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
|
||||
if test -n "$prefix"; then
|
||||
if test -n "$name"; then
|
||||
echo
|
||||
echo "uint8_t ${prefix}string_serial[] = {"
|
||||
echo " ${#SERIALNO}*2+2+16, /* bLength */"
|
||||
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
|
||||
echo "const uint8_t ${name}string_serial[] = {"
|
||||
echo " ${#SERIALNO}*2+2+16, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* Serial number: \"$SERIALNO\" */"
|
||||
echo $SERIALNO | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
echo "$SERIALNO" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
if test "$emulation" = "yes"; then
|
||||
echo " 'E', 0, 'M', 0, 'U', 0, 'L', 0,"
|
||||
echo " 'A', 0, 'T', 0, 'E', 0, 'D', 0,"
|
||||
else
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
echo " 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
|
||||
fi
|
||||
echo '};'
|
||||
echo
|
||||
echo '#ifdef USB_STRINGS_FOR_GNUK'
|
||||
echo "static const uint8_t ${prefix}revision_detail[] = {"
|
||||
echo " ${#REVISION}*2+2, /* bLength */"
|
||||
echo " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}revision_detail[] = {"
|
||||
echo " ${#REVISION}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* revision detail: \"$REVISION\" */"
|
||||
echo $REVISION | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo "$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 " USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */"
|
||||
echo "static const uint8_t ${name}config_options[] = {"
|
||||
echo " ${#CONFIG}*2+2, /* bLength */"
|
||||
echo " STRING_DESCRIPTOR, /* bDescriptorType */"
|
||||
echo " /* configure options: \"$CONFIG\" */"
|
||||
echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 0, /g" -e "s/^/ /" -e "/^ ./s/ $//p"
|
||||
echo '};'
|
||||
@@ -305,61 +448,89 @@ output_vendor_product_serial_strings () {
|
||||
fi
|
||||
}
|
||||
|
||||
(echo "#! /bin/bash"
|
||||
echo
|
||||
echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh
|
||||
|
||||
if !(IFS=" "
|
||||
while read VIDPID VERSION PRODUCT VENDOR; do
|
||||
while read -r VIDPID VERSION PRODUCT VENDOR; do
|
||||
if test "$vidpid" = "$VIDPID"; then
|
||||
output_vid_pid_version > usb-vid-pid-ver.c.inc
|
||||
echo >> put-vid-pid-ver.sh
|
||||
echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
|
||||
output_vid_pid_version >> put-vid-pid-ver.sh
|
||||
output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
|
||||
exit 0
|
||||
fi
|
||||
done; exit 1) < ../GNUK_USB_DEVICE_ID
|
||||
then
|
||||
echo "Please specify valid Vendor ID and Product ID."
|
||||
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.1.
|
||||
# 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%" \
|
||||
-e "s%@DEBUG_MAKE_OPTION@%$DEBUG_MAKE_OPTION%" \
|
||||
-e "s%@PINPAD_MAKE_OPTION@%$PINPAD_MAKE_OPTION%" \
|
||||
-e "s%@HEXOUTPUT_MAKE_OPTION@%$HEXOUTPUT_MAKE_OPTION%" \
|
||||
< Makefile.in > Makefile
|
||||
(echo "CHIP=$chip";
|
||||
echo "ARCH=$arch";
|
||||
echo "EMULATION=$emulation";
|
||||
echo "CROSS=$cross";
|
||||
echo "MCU=$mcu";
|
||||
echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size $def_mhz";
|
||||
echo "LDSCRIPT=$ldscript";
|
||||
echo "LIBS=$libs";
|
||||
echo "$DEBUG_MAKE_OPTION";
|
||||
echo "$PINPAD_MAKE_OPTION";
|
||||
echo "ENABLE_FRAUCHEKY=$enable_fraucheky";
|
||||
echo "ENABLE_OUTPUT_HEX=$enable_hexoutput"
|
||||
if test "$ackbtn_support" = "yes"; then
|
||||
echo "USE_ACKBTN=yes"
|
||||
fi
|
||||
if test "$with_dfu" = "yes"; then
|
||||
echo "USE_DFU=yes"
|
||||
fi
|
||||
if test "$emulation" = "yes"; then
|
||||
echo "prefix=$prefix"
|
||||
echo "exec_prefix=$exec_prefix"
|
||||
echo "libexecdir=$libexecdir"
|
||||
fi
|
||||
) > config.mk
|
||||
|
||||
if test "$certdo" = "yes"; then
|
||||
sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \
|
||||
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
|
||||
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
||||
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
|
||||
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
|
||||
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
|
||||
< gnuk.ld.in > gnuk.ld
|
||||
else
|
||||
sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \
|
||||
-e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
|
||||
-e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
-e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
|
||||
-e "s/@MSC_SIZE@/$MSC_SIZE/" \
|
||||
-e "s/@TIM_SIZE@/$TIM_SIZE/" \
|
||||
-e "s/@EXT_SIZE@/$EXT_SIZE/" \
|
||||
< gnuk.ld.in > gnuk.ld
|
||||
fi
|
||||
sed -e "s/@ORIGIN_REAL@/$ORIGIN_REAL/" -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
|
||||
< stdaln-sys.ld.in > stdaln-sys.ld
|
||||
sed -e "s/@DEBUG_DEFINE@/$DEBUG_DEFINE/" \
|
||||
-e "s/@DFU_DEFINE@/$DFU_DEFINE/" \
|
||||
-e "s/@ORIGIN_DEFINE@/$ORIGIN_DEFINE/" \
|
||||
-e "s/@ORIGIN_REAL_DEFINE@/$ORIGIN_REAL_DEFINE/" \
|
||||
-e "s/@PINPAD_DEFINE@/$PINPAD_DEFINE/" \
|
||||
-e "s/@PINPAD_MORE_DEFINE@/$PINPAD_MORE_DEFINE/" \
|
||||
-e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
|
||||
-e "s/@HID_CARD_CHANGE_DEFINE@/$HID_CARD_CHANGE_DEFINE/" \
|
||||
-e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
|
||||
-e "s/@ACKBTN_DEFINE@/$ACKBTN_DEFINE/" \
|
||||
-e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
|
||||
-e "s/@KDF_DO_REQUIRED_DEFINE@/$KDF_DO_REQUIRED_DEFINE/" \
|
||||
< config.h.in > config.h
|
||||
exit 0
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
/*
|
||||
* a = 0, b = 7
|
||||
*/
|
||||
#if 0
|
||||
static const bn256 coefficient_a[1] = {
|
||||
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
};
|
||||
#endif
|
||||
|
||||
static const bn256 coefficient_b[1] = {
|
||||
{{ 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* ecc-edwards.c - Elliptic curve computation for
|
||||
* the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bn.h"
|
||||
@@ -50,7 +49,7 @@
|
||||
* IMPLEMENTATION NOTE
|
||||
*
|
||||
* (0) We assume that the processor has no cache, nor branch target
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* We don't avoid conditional jump if both cases have same timing,
|
||||
* either.
|
||||
*
|
||||
@@ -235,7 +234,7 @@ point_add (ptc *X, const ptc *A, const ac *B)
|
||||
* @param X Destination AC
|
||||
* @param A PTC
|
||||
*
|
||||
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
|
||||
* (X1:Y1:Z1) represents the affine point (x=X1/Z1, y=Y1/Z1)
|
||||
*/
|
||||
static void
|
||||
point_ptc_to_ac (ac *X, const ptc *A)
|
||||
@@ -258,195 +257,195 @@ point_ptc_to_ac (ac *X, const ptc *A)
|
||||
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,
|
||||
{ {{{ 0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
|
||||
0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3 }}},
|
||||
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
|
||||
{{{ 0x66666658, 0x66666666, 0x66666666, 0x66666666,
|
||||
0x66666666, 0x66666666, 0x66666666, 0x66666666 }}} },
|
||||
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
|
||||
{ {{{ 0x3713af22, 0xac7137bd, 0xac634604, 0x25ed77a4,
|
||||
0xa815e038, 0xce0d0064, 0xbca90151, 0x041c030f }}},
|
||||
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
|
||||
{{{ 0x0780f989, 0xe9b33fcf, 0x3d4445e7, 0xe4e97c2a,
|
||||
0x655e5c16, 0xc67dc71c, 0xee43fb7a, 0x72467625 }}} },
|
||||
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
|
||||
{ {{{ 0x3ee99893, 0x76a19171, 0x7ba9b065, 0xe647edd9,
|
||||
0x6aeae260, 0x31f39299, 0x5f4a9bb2, 0x6d9e4545 }}},
|
||||
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
|
||||
{{{ 0x94cae280, 0xc41433da, 0x79061211, 0x8e842de8,
|
||||
0xa259dc8a, 0xaab95e0b, 0x99013cd0, 0x28bd5fc3 }}} },
|
||||
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
|
||||
{ {{{ 0x7d23ea24, 0x59e22c56, 0x0460850e, 0x1e745a88,
|
||||
0xda13ef4b, 0x4583ff4c, 0x95083f85, 0x1f13202c }}},
|
||||
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
|
||||
{{{ 0x90275f48, 0xad42025c, 0xb55c4778, 0x0085087e,
|
||||
0xfdfd7ffa, 0xf21109e7, 0x6c381b7e, 0x66336d35 }}} },
|
||||
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
|
||||
{ {{{ 0xd00851f2, 0xaa9476ab, 0x4a61600b, 0xe7838534,
|
||||
0x1a52df87, 0x0de65625, 0xbd675870, 0x5f0dd494 }}},
|
||||
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
|
||||
{{{ 0xe23493ba, 0xf20aec1b, 0x3414b0a8, 0x8f7f2741,
|
||||
0xa80e1eb6, 0x497e74bd, 0xe9365b15, 0x1648eaac }}} },
|
||||
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
|
||||
{ {{{ 0x04ac2b69, 0x5b78dcec, 0x32001a73, 0xecdb66ce,
|
||||
0xb34cf697, 0xb75832f4, 0x3a2bce94, 0x7aaf57c5 }}},
|
||||
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
|
||||
{{{ 0x60fdfc6f, 0xb32ed2ce, 0x757924c6, 0x77bf20be,
|
||||
0x48742dd1, 0xaebd15dd, 0x55d38439, 0x6311bb16 }}} },
|
||||
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
|
||||
{ {{{ 0x42ff5c97, 0x139cdd73, 0xdbd82964, 0xee4c359e,
|
||||
0x70611a3f, 0x91c1cd94, 0x8075dbcb, 0x1d0c34f6 }}},
|
||||
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
|
||||
{{{ 0x5f931219, 0x43eaa549, 0xa23d35a6, 0x3737aba7,
|
||||
0x46f167bb, 0x54b1992f, 0xb74a9944, 0x01a11f3c }}} },
|
||||
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
|
||||
{ {{{ 0xba46b161, 0x67a5310e, 0xd9d67f6c, 0x790f8527,
|
||||
0x2f6cc814, 0x359c5b5f, 0x7786383d, 0x7b6a5565 }}},
|
||||
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
|
||||
{{{ 0x663ab0d3, 0xf1431b60, 0x09995826, 0x14a32d8f,
|
||||
0xeddb8571, 0x61d526f6, 0x0eac739a, 0x0cb7acea }}} },
|
||||
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
|
||||
{ {{{ 0x4a2d009f, 0x5eb1a697, 0xd8df987a, 0xdacb43b4,
|
||||
0x8397f958, 0x4870f214, 0x8a175fbb, 0x5aa0c67c }}},
|
||||
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
|
||||
{{{ 0x78887db3, 0x27dbbd4c, 0x64e322ab, 0xe327b707,
|
||||
0x7cbe4e3b, 0x87e293fa, 0xbda72395, 0x17040799 }}} },
|
||||
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
|
||||
{ {{{ 0x99d1e696, 0xc833a5a2, 0x2d9d5877, 0x969bff8e,
|
||||
0x2216fa67, 0x383a533a, 0x684d3925, 0x338bbe0a }}},
|
||||
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
|
||||
{{{ 0xd6cfb491, 0x35b5aae8, 0xaa12f3f8, 0x4a588279,
|
||||
0x2e30380e, 0xa7c2e708, 0x9e4b3d62, 0x69f13e09 }}} },
|
||||
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
|
||||
{ {{{ 0x27f1cd56, 0xec0dc2ef, 0xdb11cc97, 0x1af11548,
|
||||
0x9ebc7613, 0xb642f86a, 0xcb77c3b9, 0x5ce45e73 }}},
|
||||
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
|
||||
{{{ 0x3eddd6de, 0x5d128786, 0x4859eab7, 0x16f9a6b4,
|
||||
0xd8782345, 0x55c53916, 0xdb7b202a, 0x6b1dfa87 }}} },
|
||||
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
|
||||
{ {{{ 0x19e30528, 0x2461a8ed, 0x665cfb1c, 0xaf756bf9,
|
||||
0x3a6e8673, 0x0fcafd1d, 0x45d10f48, 0x0d264435 }}},
|
||||
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
|
||||
{{{ 0x5431db67, 0x543fd4c6, 0x60932432, 0xc153a5b3,
|
||||
0xd2119aa4, 0x41d5b8eb, 0x8b09b6a5, 0x36bd9ab4 }}} },
|
||||
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
|
||||
{ {{{ 0x21e06738, 0x6d39f935, 0x3765dd86, 0x4e6a7c59,
|
||||
0xa4730880, 0xefc0dd80, 0x4079fe2f, 0x40617e56 }}},
|
||||
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
|
||||
{{{ 0x921439b9, 0xbc83cdff, 0x98833c09, 0xd5cccc06,
|
||||
0xda13cdcb, 0xe315c425, 0x67ff5370, 0x37bc6e84 }}} },
|
||||
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
|
||||
{ {{{ 0xf643b5f5, 0x65e7f028, 0x0ffbf5a8, 0x5b0d4831,
|
||||
0xf4085f62, 0x0f540498, 0x0db7bd1b, 0x6f0bb035 }}},
|
||||
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
|
||||
{{{ 0x9733742c, 0x51f65571, 0xf513409f, 0x2fc047a0,
|
||||
0x355facf6, 0x07f45010, 0x3a989a9c, 0x5cd416a9 }}} },
|
||||
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
|
||||
{ {{{ 0x748f2a67, 0x0bdd7208, 0x415b7f7f, 0x0cf0b80b,
|
||||
0x57aa0119, 0x44afdd5f, 0x430dc946, 0x05d68802 }}},
|
||||
{{{ 0x1a60eeb2, 0x420c46e5, 0x665024f5, 0xc60a9b33,
|
||||
{{{ 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,
|
||||
{ {{{ 0x199c4f7d, 0xec314ac0, 0xb2ebaaf9, 0x66a39c16,
|
||||
0xedd4d15f, 0xab1c92b8, 0x57d9eada, 0x482a4cdf }}},
|
||||
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
|
||||
{{{ 0x6e4eb04b, 0xbd513b11, 0x25e4fd6a, 0x3f115fa5,
|
||||
0x14519298, 0x0b3c5fc6, 0x81c2f7a8, 0x7391de43 }}} },
|
||||
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
|
||||
{ {{{ 0x1254fe02, 0xa57dca18, 0x6da34368, 0xa56a2a14,
|
||||
0x63e7328e, 0x44c6e34f, 0xca63ab3e, 0x3f748617 }}},
|
||||
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
|
||||
{{{ 0x7dc1641e, 0x5a13dc52, 0xee4e9ca1, 0x4cbb2899,
|
||||
0x1ba9acee, 0x3938a289, 0x420fc47b, 0x0fed89e6 }}} },
|
||||
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
|
||||
{ {{{ 0x49cbad08, 0x3c193f32, 0x15e80ef5, 0xdda71ef1,
|
||||
0x9d128c33, 0xda44186c, 0xbf98c24f, 0x54183ede }}},
|
||||
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
|
||||
{{{ 0x93d165c1, 0x2cb483f7, 0x177f44aa, 0x51762ace,
|
||||
0xb4ab035d, 0xb3fe651b, 0xa0b0d4e5, 0x426c99c3 }}} },
|
||||
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
|
||||
{ {{{ 0xef3f3fb1, 0xb3fcf4d8, 0x065060a0, 0x7052292b,
|
||||
0x24240b15, 0x18795ff8, 0x9989ffcc, 0x13aea184 }}},
|
||||
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
|
||||
{{{ 0xc2b81f44, 0x1930c101, 0x10600555, 0x672d6ca4,
|
||||
0x1b25e570, 0xfbddbff2, 0x8ca12b70, 0x0884949c }}} },
|
||||
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
|
||||
{ {{{ 0x00564bbf, 0x9983a033, 0xde61b72d, 0x95587d25,
|
||||
0xeb17ad71, 0xb6719dfb, 0xc0bc3517, 0x46871ad0 }}},
|
||||
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
|
||||
{{{ 0xe95a6693, 0xb034fb61, 0x76eabad9, 0x5b0d8d18,
|
||||
0x884785dc, 0xad295dd0, 0x74a1276a, 0x359debad }}} },
|
||||
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
|
||||
{ {{{ 0xe89fb5ca, 0x2e5a2686, 0x5656c6c5, 0xd3d200ba,
|
||||
0x9c969001, 0xef4c051e, 0x02cb45f4, 0x0d4ea946 }}},
|
||||
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
|
||||
{{{ 0x76d6e506, 0xa6f8a422, 0x63209e23, 0x454c768f,
|
||||
0x2b372386, 0x5c12fd04, 0xdbfee11f, 0x1aedbd3e }}} },
|
||||
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
|
||||
{ {{{ 0x00dbf569, 0x700ab50f, 0xd335b313, 0x9553643c,
|
||||
0xa17dc97e, 0xeea9bddf, 0x3350a2bd, 0x0d12fe3d }}},
|
||||
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
|
||||
{{{ 0xa16a3dee, 0xe5ac35fe, 0xf81950c3, 0x4ae4664a,
|
||||
0x3dbbf921, 0x75c63df4, 0x2958a5a6, 0x545b109c }}} },
|
||||
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
|
||||
{ {{{ 0x0a61b29c, 0xd7a52a98, 0x65aca9ee, 0xe21e0acb,
|
||||
0x5985dcbe, 0x57a69c0f, 0xeb87a534, 0x3c0c1e7b }}},
|
||||
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
|
||||
{{{ 0x6384bd2f, 0xf0a0b50d, 0xc6939e4b, 0xff349a34,
|
||||
0x6e2f1973, 0x922c4554, 0xf1347631, 0x74e826b2 }}} },
|
||||
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
|
||||
{ {{{ 0xa655803c, 0xd7eaa066, 0x38292c5c, 0x09504e76,
|
||||
0x2c874953, 0xe298a02e, 0x8932b73f, 0x225093ed }}},
|
||||
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
|
||||
{{{ 0xe69c3efd, 0xf93e2b4d, 0x8a87c799, 0xa2cbd5fc,
|
||||
0x85dba986, 0xdf41da94, 0xccee8edc, 0x36fe85e7 }}} },
|
||||
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
|
||||
{ {{{ 0x7d742813, 0x78df7dc5, 0x4a193e64, 0x333bcc6d,
|
||||
0x6a966d2d, 0x8242aa25, 0x4cd36d32, 0x03500a94 }}},
|
||||
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
|
||||
{{{ 0x580505d7, 0xd5d110fc, 0xfa11e1e9, 0xb2f47e16,
|
||||
0x06eab6b4, 0xd0030f92, 0x62c91d46, 0x2dc80d5f }}} },
|
||||
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
|
||||
{ {{{ 0x2a75e492, 0x5788b01a, 0xbae31352, 0x992acf54,
|
||||
0x8159db27, 0x4591b980, 0xd3d84740, 0x36c6533c }}},
|
||||
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
|
||||
{{{ 0x103883b5, 0xc44c7c00, 0x515d0820, 0x10329423,
|
||||
0x71b9dc16, 0xbd306903, 0xf88f8d32, 0x7edd5a95 }}} },
|
||||
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
|
||||
{ {{{ 0x005523d7, 0xfd63b1ac, 0xad70dd21, 0x74482e0d,
|
||||
0x02b56105, 0x67c9d9d0, 0x5971b456, 0x4d318012 }}},
|
||||
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
|
||||
{{{ 0x841106df, 0xdc9a6f6d, 0xa326987f, 0x7c52ed9d,
|
||||
0x00607ea0, 0x4dbeaa6f, 0x6959e688, 0x115c221d }}} },
|
||||
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
|
||||
{ {{{ 0xc80f7c16, 0xf8718464, 0xe9930634, 0x05dc8f40,
|
||||
0xc2e9d5f4, 0xefa699bb, 0x021da209, 0x2469e813 }}},
|
||||
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
|
||||
{{{ 0xc602a3c4, 0x75c02845, 0x0a200f9d, 0x49d1b2ce,
|
||||
0x2fb3ec8f, 0xd21b75e4, 0xd72a7545, 0x10dd726a }}} },
|
||||
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
|
||||
{ {{{ 0x63ef1a6c, 0xeda58527, 0x051705e0, 0xb3fc0e72,
|
||||
0x44f1161f, 0xbda6f3ee, 0xf339efe5, 0x7680aebf }}},
|
||||
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
|
||||
{{{ 0xb1b070a7, 0xe8d3fd01, 0xdbfbaaa0, 0xc3ff7dbf,
|
||||
0xa320c916, 0xd81ef6f2, 0x62a3b54d, 0x3e22a1fb }}} },
|
||||
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
|
||||
{ {{{ 0xb1fa18c8, 0xcdbb9187, 0xcb483a17, 0x8ddb5f6b,
|
||||
0xea49af98, 0xc0a880b9, 0xf2dfddd0, 0x53bf600b }}},
|
||||
{{{ 0x9e25b164, 0x4217404c, 0xafb74aa7, 0xfabf06ee,
|
||||
{{{ 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,
|
||||
{ {{{ 0xe388a820, 0xbb6ec091, 0x5182278a, 0xa928b283,
|
||||
0xa9a6eb83, 0x2259174d, 0x45500054, 0x184b48cb }}},
|
||||
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
|
||||
{{{ 0x26e77c33, 0xfe324dba, 0x83faf453, 0x6679a5e3,
|
||||
0x2380ef73, 0xdd60c268, 0x03dc33a9, 0x3ee0e07a }}} },
|
||||
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
|
||||
{ {{{ 0xce974493, 0x403aff28, 0x9bf6f5c4, 0x84076bf4,
|
||||
0xecd898fb, 0xec57038c, 0xb663ed49, 0x2898ffaa }}},
|
||||
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
|
||||
{{{ 0xf335163d, 0xf4b3bc46, 0xfa4fb6c6, 0xe613a0f4,
|
||||
0xb9934557, 0xe759d6bc, 0xab6c9477, 0x094f3b96 }}} },
|
||||
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
|
||||
{ {{{ 0x6afffe9e, 0x168bb5a0, 0xee748c29, 0x950f7ad7,
|
||||
0xda17203d, 0xa4850a2b, 0x77289e0f, 0x0062f7a7 }}},
|
||||
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
|
||||
{{{ 0x4b3829fa, 0x6265d4e9, 0xbdfcd386, 0x4f155ada,
|
||||
0x475795f6, 0x9f38bda4, 0xdece4a4c, 0x560ed4b3 }}} },
|
||||
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
|
||||
{ {{{ 0x141e648a, 0xdad4570a, 0x019b965c, 0x8bbf674c,
|
||||
0xdb08fe30, 0xd7a8d50d, 0xa2851109, 0x7efb45d3 }}},
|
||||
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
|
||||
{{{ 0xd0c28cda, 0x52e818ac, 0xa321d436, 0x792257dd,
|
||||
0x9d71f8b7, 0x867091c6, 0x11a1bf56, 0x0fe1198b }}} },
|
||||
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
|
||||
{ {{{ 0x06137ab1, 0x4e848339, 0x3e6674cc, 0x5673e864,
|
||||
0x0140502b, 0xad882043, 0x6ea1e46a, 0x34b5c0cb }}},
|
||||
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
|
||||
{{{ 0x1d70aa7c, 0x29786814, 0x8cdbb8aa, 0x840ae3f9,
|
||||
0xbd4801fb, 0x78b4d622, 0xcf18ae9a, 0x6cf4e146 }}} },
|
||||
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
|
||||
{ {{{ 0x36297168, 0x95c270ad, 0x942e7812, 0x2303ce80,
|
||||
0x0205cf0e, 0x71908cc2, 0x32bcd754, 0x0cc15edd }}},
|
||||
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
|
||||
{{{ 0x2c7ded86, 0x1db94364, 0xf141b22c, 0xc694e39b,
|
||||
0x5e5a9312, 0xf22f64ef, 0x3c5e6155, 0x649b8859 }}} },
|
||||
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
|
||||
{ {{{ 0xb6417945, 0x0d5611c6, 0xac306c97, 0x9643fdbf,
|
||||
0x0df500ff, 0xe81faaa4, 0x6f50e615, 0x0792c79b }}},
|
||||
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
|
||||
{{{ 0xd2af8c8d, 0xb45bbc49, 0x84f51bfe, 0x16c615ab,
|
||||
0xc1d02d32, 0xdc57c526, 0x3c8aaa55, 0x5fb9a9a6 }}} },
|
||||
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
|
||||
{ {{{ 0xdee40b98, 0x82faa8db, 0x6d520674, 0xff8a5208,
|
||||
0x446ac562, 0x1f8c510f, 0x2cc6b66e, 0x4676d381 }}},
|
||||
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
|
||||
{{{ 0x2e7429f4, 0x8f1aa780, 0x8ed6bdf6, 0x2a95c1bf,
|
||||
0x457fa0eb, 0x051450a0, 0x744c57b1, 0x7d89e2b7 }}} },
|
||||
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
|
||||
{ {{{ 0x3f95ea15, 0xb6bdacd2, 0x2f1a5d69, 0xc9a9d1b1,
|
||||
0xf4d22d72, 0xd4c2f1a9, 0x4dc516b5, 0x73ecfdf1 }}},
|
||||
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
|
||||
{{{ 0x05391e08, 0xa1ce93cd, 0x7b8aac17, 0x98f1e99e,
|
||||
0xa098cbb3, 0x9ba84f2e, 0xf9bdd37a, 0x1425aa8b }}} },
|
||||
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
|
||||
{ {{{ 0x966abfc0, 0x8a385bf4, 0xf081a640, 0x55e5e8bc,
|
||||
0xee26f5ff, 0x835dff85, 0xe509e1ea, 0x4927e622 }}},
|
||||
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
|
||||
{{{ 0x352334b0, 0x164c8dbc, 0xa3fea31f, 0xcac1ad63,
|
||||
0x682fd457, 0x9b87a676, 0x1a53145f, 0x75f382ff }}} },
|
||||
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
|
||||
{ {{{ 0xc3efcb46, 0x16b944f5, 0x68cb184c, 0x1fb55714,
|
||||
0x9ccf2dc8, 0xf1c2b116, 0x808283d8, 0x7417e00f }}},
|
||||
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
|
||||
{{{ 0x930199ba, 0x1ea67a22, 0x718990d8, 0x9fbaf765,
|
||||
0x8f3d5d57, 0x231fc664, 0xe5853194, 0x38141a19 }}} },
|
||||
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
|
||||
{ {{{ 0x2f81290d, 0xb9f00390, 0x04a9ca6c, 0x44877827,
|
||||
0xe1dbdd65, 0x65d7f9b9, 0xf7c6698a, 0x7133424c }}},
|
||||
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
|
||||
{{{ 0xa7cd250f, 0x604cfb3c, 0x5acc18f3, 0x460c3c4b,
|
||||
0xb518e3eb, 0xa53e50e0, 0x98a40196, 0x2b4b9267 }}} },
|
||||
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
|
||||
{ {{{ 0xc5dbd06c, 0x591b0672, 0xaa1eeb65, 0x10d43dca,
|
||||
0xcd2517af, 0x420cdef8, 0x0b695a8a, 0x513a307e }}},
|
||||
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
|
||||
{{{ 0x66503215, 0xee9d6a7b, 0x088fd9a4, 0xdea58720,
|
||||
0x973afe12, 0x8f3cbbea, 0x872f2538, 0x005c2350 }}} },
|
||||
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
|
||||
{ {{{ 0x35af3291, 0xe5024b70, 0x4f5e669a, 0x1d3eec2d,
|
||||
0x6e79d539, 0xc1f6d766, 0x795b5248, 0x34ec043f }}},
|
||||
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
|
||||
{{{ 0x400960b6, 0xb2763511, 0x29e57df0, 0xff7a3d84,
|
||||
0x1666c1f1, 0xaeac7792, 0x66084bc0, 0x72426e97 }}} },
|
||||
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
|
||||
{ {{{ 0x44f826ca, 0x5b1c3199, 0x790aa408, 0x68b00b73,
|
||||
0x69e9b92b, 0xaf0984b4, 0x3ffe9093, 0x5fe6736f }}},
|
||||
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
|
||||
{{{ 0xffd49312, 0xd67f2889, 0x5cb9ed21, 0x3520d747,
|
||||
0x3c65a606, 0x94f893b1, 0x2d65496f, 0x2fee5e8c }}} }
|
||||
};
|
||||
|
||||
@@ -586,7 +585,7 @@ bnX_mul_C (uint32_t *r, const uint32_t *q, int q_size)
|
||||
|
||||
/**
|
||||
* @brief R = A mod M (using M=2^252+C) (Barret reduction)
|
||||
*
|
||||
*
|
||||
* See HAC 14.47.
|
||||
*/
|
||||
static void
|
||||
@@ -708,7 +707,7 @@ eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
|
||||
{
|
||||
ac R[1];
|
||||
@@ -730,18 +729,10 @@ eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
eddsa_compute_public_25519 (const uint8_t *kd)
|
||||
void
|
||||
eddsa_compute_public_25519 (const uint8_t *kd, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p0;
|
||||
const bn256 *a = (const bn256 *)kd;
|
||||
|
||||
p0 = (uint8_t *)malloc (sizeof (bn256));
|
||||
if (p0 == NULL)
|
||||
return NULL;
|
||||
|
||||
eddsa_public_key_25519 ((bn256 *)p0, a);
|
||||
return p0;
|
||||
eddsa_public_key_25519 ((bn256 *)pubkey, (const bn256 *)kd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* ecc-mont.c - Elliptic curve computation for
|
||||
* the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
|
||||
*
|
||||
* Copyright (C) 2014, 2015 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2015, 2017 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "bn.h"
|
||||
#include "mod25638.h"
|
||||
#include "mod.h"
|
||||
@@ -33,7 +32,7 @@
|
||||
* References:
|
||||
*
|
||||
* [1] D. J. Bernstein. Curve25519: new Diffie-Hellman speed records.
|
||||
* Proceedings of PKC 2006, to appear.
|
||||
* 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
|
||||
@@ -46,7 +45,7 @@
|
||||
* IMPLEMENTATION NOTE
|
||||
*
|
||||
* (0) We assume that the processor has no cache, nor branch target
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* prediction. Thus, we don't avoid indexing by secret value.
|
||||
* We don't avoid conditional jump if both cases have same timing,
|
||||
* either.
|
||||
*
|
||||
@@ -198,22 +197,17 @@ compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *
|
||||
ecdh_compute_public_25519 (const uint8_t *key_data)
|
||||
void
|
||||
ecdh_compute_public_25519 (const uint8_t *key_data, uint8_t *pubkey)
|
||||
{
|
||||
uint8_t *p;
|
||||
bn256 gx[1];
|
||||
bn256 k[1];
|
||||
|
||||
memset (gx, 0, sizeof (bn256));
|
||||
gx[0].word[0] = 9; /* Gx = 9 */
|
||||
memcpy (k, key_data, sizeof (bn256));
|
||||
p = (uint8_t *)malloc (sizeof (bn256));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
compute_nQ ((bn256 *)p, k, gx);
|
||||
return p;
|
||||
compute_nQ ((bn256 *)pubkey, k, gx);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
* Pages 250-265, Springer-Verlag London, UK, 2001
|
||||
* ISBN:3-540-41898-9
|
||||
*
|
||||
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
|
||||
* [3] Mustapha Hedabou, Pierre Pinel, Lucien Bénéteau,
|
||||
* A comb method to render ECC resistant against Side Channel Attacks,
|
||||
* 2004
|
||||
*/
|
||||
@@ -384,7 +384,7 @@ FUNC(check_secret) (const bn256 *d0, bn256 *d1)
|
||||
{
|
||||
ac Q0[1], Q1[1];
|
||||
|
||||
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) <= 0)
|
||||
if (bn256_is_zero (d0) || bn256_sub (d1, N, d0) != 0)
|
||||
/* == 0 or >= N, it's not valid. */
|
||||
return 0;
|
||||
|
||||
|
||||
190
src/flash.c
190
src/flash.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -53,33 +53,40 @@
|
||||
* <alignment to page>
|
||||
* ch_certificate_startp
|
||||
* <2048 bytes>
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
* _keystore_pool
|
||||
* Three flash pages for keystore
|
||||
* a page contains a key data of:
|
||||
* For RSA-2048: 512-byte (p, q and N)
|
||||
* For RSA-4096: 1024-byte (p, q and N)
|
||||
* For ECDSA/ECDH and EdDSA, there are padding after public key
|
||||
* _data_pool
|
||||
* <two pages>
|
||||
*/
|
||||
|
||||
#define FLASH_DATA_POOL_HEADER_SIZE 2
|
||||
#define FLASH_DATA_POOL_SIZE (flash_page_size*2)
|
||||
|
||||
static uint16_t flash_page_size;
|
||||
|
||||
static const uint8_t *data_pool;
|
||||
extern uint8_t _keystore_pool;
|
||||
|
||||
static uint8_t *last_p;
|
||||
|
||||
/* The first halfword is generation for the data page (little endian) */
|
||||
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
0x01, 0x00, 0xff, 0xff
|
||||
const uint8_t flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||
0x00, 0x00, 0xff, 0xff
|
||||
};
|
||||
|
||||
/* Linker set this symbol */
|
||||
extern uint8_t _data_pool;
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
extern uint8_t *flash_addr_key_storage_start;
|
||||
extern uint8_t *flash_addr_data_storage_start;
|
||||
#define FLASH_ADDR_KEY_STORAGE_START flash_addr_key_storage_start
|
||||
#define FLASH_ADDR_DATA_STORAGE_START flash_addr_data_storage_start
|
||||
#else
|
||||
/* Linker sets these symbols */
|
||||
extern uint8_t _keystore_pool[];
|
||||
extern uint8_t _data_pool[];
|
||||
#define FLASH_ADDR_KEY_STORAGE_START ((_keystore_pool))
|
||||
#define FLASH_ADDR_DATA_STORAGE_START ((_data_pool))
|
||||
#endif
|
||||
|
||||
static int key_available_at (const uint8_t *k, int key_size)
|
||||
{
|
||||
@@ -102,42 +109,88 @@ static int key_available_at (const uint8_t *k, int key_size)
|
||||
|
||||
|
||||
#define CHIP_ID_REG ((uint32_t *)0xe0042000)
|
||||
const uint8_t *
|
||||
flash_init (void)
|
||||
void
|
||||
flash_do_storage_init (const uint8_t **p_do_start, const uint8_t **p_do_end)
|
||||
{
|
||||
uint16_t gen0, gen1;
|
||||
uint16_t *gen0_p = (uint16_t *)&_data_pool;
|
||||
uint16_t *gen0_p = (uint16_t *)FLASH_ADDR_DATA_STORAGE_START;
|
||||
uint16_t *gen1_p;
|
||||
|
||||
flash_page_size = 1024;
|
||||
#if !defined (GNU_LINUX_EMULATION)
|
||||
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
|
||||
flash_page_size = 2048;
|
||||
#endif
|
||||
|
||||
gen1_p = (uint16_t *)(&_data_pool + flash_page_size);
|
||||
gen1_p = (uint16_t *)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size);
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
|
||||
/* Check data pool generation and choose the page */
|
||||
gen0 = *gen0_p;
|
||||
gen1 = *gen1_p;
|
||||
if (gen0 == 0xffff)
|
||||
data_pool = &_data_pool + flash_page_size;
|
||||
else if (gen1 == 0xffff)
|
||||
data_pool = &_data_pool;
|
||||
else if (gen1 > gen0)
|
||||
data_pool = &_data_pool + flash_page_size;
|
||||
else
|
||||
data_pool = &_data_pool;
|
||||
|
||||
return data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
if (gen0 == 0xffff && gen1 == 0xffff)
|
||||
{
|
||||
/* It's terminated. */
|
||||
*p_do_start = *p_do_end = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gen0 == 0xffff)
|
||||
/* Use another page if a page is erased. */
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
else if (gen1 == 0xffff)
|
||||
/* Or use different page if another page is erased. */
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
else if ((gen0 == 0xfffe && gen1 == 0) || gen1 > gen0)
|
||||
/* When both pages have valid header, use newer page. */
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
|
||||
*p_do_start = data_pool + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
*p_do_end = data_pool + flash_page_size;
|
||||
}
|
||||
|
||||
static uint8_t *flash_key_getpage (enum kind_of_key kk);
|
||||
|
||||
void
|
||||
flash_terminate (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
const uint8_t *p;
|
||||
|
||||
p = gpg_get_firmware_update_key (0);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
#endif
|
||||
for (i = 0; i < 3; i++)
|
||||
flash_erase_page ((uintptr_t)flash_key_getpage (i));
|
||||
flash_erase_page ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START);
|
||||
flash_erase_page ((uintptr_t)(FLASH_ADDR_DATA_STORAGE_START + flash_page_size));
|
||||
data_pool = FLASH_ADDR_DATA_STORAGE_START;
|
||||
last_p = FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_HEADER_SIZE;
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
flash_erase_page ((uintptr_t)&ch_certificate_start);
|
||||
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
|
||||
flash_erase_page ((uintptr_t)(&ch_certificate_start + flash_page_size));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
flash_init_keys (void)
|
||||
flash_activate (void)
|
||||
{
|
||||
flash_program_halfword ((uintptr_t)FLASH_ADDR_DATA_STORAGE_START, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flash_key_storage_init (void)
|
||||
{
|
||||
const uint8_t *p;
|
||||
int i;
|
||||
|
||||
/* For each key, find its address. */
|
||||
p = &_keystore_pool;
|
||||
p = FLASH_ADDR_KEY_STORAGE_START;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
const uint8_t *k;
|
||||
@@ -195,22 +248,26 @@ flash_copying_gc (void)
|
||||
uint8_t *src, *dst;
|
||||
uint16_t generation;
|
||||
|
||||
if (data_pool == &_data_pool)
|
||||
if (data_pool == FLASH_ADDR_DATA_STORAGE_START)
|
||||
{
|
||||
src = &_data_pool;
|
||||
dst = &_data_pool + flash_page_size;
|
||||
src = FLASH_ADDR_DATA_STORAGE_START;
|
||||
dst = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = &_data_pool + flash_page_size;
|
||||
dst = &_data_pool;
|
||||
src = FLASH_ADDR_DATA_STORAGE_START + flash_page_size;
|
||||
dst = FLASH_ADDR_DATA_STORAGE_START;
|
||||
}
|
||||
|
||||
generation = *(uint16_t *)src;
|
||||
data_pool = dst;
|
||||
gpg_data_copy (data_pool + FLASH_DATA_POOL_HEADER_SIZE);
|
||||
flash_erase_page ((uint32_t)src);
|
||||
flash_program_halfword ((uint32_t)dst, generation+1);
|
||||
if (generation == 0xfffe)
|
||||
generation = 0;
|
||||
else
|
||||
generation++;
|
||||
flash_program_halfword ((uintptr_t)dst, generation);
|
||||
flash_erase_page ((uintptr_t)src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -240,10 +297,10 @@ void
|
||||
flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len)
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)p;
|
||||
addr = (uintptr_t)p;
|
||||
hw = nr | (len << 8);
|
||||
if (flash_program_halfword (addr, hw) != 0)
|
||||
flash_warning ("DO WRITE ERROR");
|
||||
@@ -296,13 +353,14 @@ flash_warning (const char *msg)
|
||||
void
|
||||
flash_do_release (const uint8_t *do_data)
|
||||
{
|
||||
uint32_t addr = (uint32_t)do_data - 1;
|
||||
uint32_t addr_tag = addr;
|
||||
uintptr_t addr = (uintptr_t)do_data - 1;
|
||||
uintptr_t addr_tag = addr;
|
||||
int i;
|
||||
int len = do_data[0];
|
||||
|
||||
/* Don't filling zero for data in code (such as ds_count_initial_value) */
|
||||
if (do_data < &_data_pool || do_data > &_data_pool + FLASH_DATA_POOL_SIZE)
|
||||
if (do_data < FLASH_ADDR_DATA_STORAGE_START
|
||||
|| do_data > FLASH_ADDR_DATA_STORAGE_START + FLASH_DATA_POOL_SIZE)
|
||||
return;
|
||||
|
||||
addr += 2;
|
||||
@@ -331,14 +389,14 @@ static uint8_t *
|
||||
flash_key_getpage (enum kind_of_key kk)
|
||||
{
|
||||
/* There is a page for each KK. */
|
||||
return &_keystore_pool + (flash_page_size * kk);
|
||||
return FLASH_ADDR_KEY_STORAGE_START + (flash_page_size * kk);
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
flash_key_alloc (enum kind_of_key kk)
|
||||
{
|
||||
uint8_t *k, *k0 = flash_key_getpage (kk);
|
||||
int i;
|
||||
int i;
|
||||
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
|
||||
|
||||
/* Seek free space in the page. */
|
||||
@@ -365,10 +423,10 @@ flash_key_write (uint8_t *key_addr,
|
||||
const uint8_t *pubkey, int pubkey_len)
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
addr = (uint32_t)key_addr;
|
||||
addr = (uintptr_t)key_addr;
|
||||
for (i = 0; i < key_data_len/2; i ++)
|
||||
{
|
||||
hw = key_data[i*2] | (key_data[i*2+1]<<8);
|
||||
@@ -391,7 +449,7 @@ flash_key_write (uint8_t *key_addr,
|
||||
static int
|
||||
flash_check_all_other_keys_released (const uint8_t *key_addr, int key_size)
|
||||
{
|
||||
uint32_t start = (uint32_t)key_addr & ~(flash_page_size - 1);
|
||||
uintptr_t start = (uintptr_t)key_addr & ~(flash_page_size - 1);
|
||||
const uint32_t *p = (const uint32_t *)start;
|
||||
|
||||
while (p < (const uint32_t *)(start + flash_page_size))
|
||||
@@ -410,7 +468,7 @@ static void
|
||||
flash_key_fill_zero_as_released (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
int i;
|
||||
uint32_t addr = (uint32_t)key_addr;
|
||||
uintptr_t addr = (uintptr_t)key_addr;
|
||||
|
||||
for (i = 0; i < key_size/2; i++)
|
||||
flash_program_halfword (addr + i*2, 0);
|
||||
@@ -420,7 +478,7 @@ void
|
||||
flash_key_release (uint8_t *key_addr, int key_size)
|
||||
{
|
||||
if (flash_check_all_other_keys_released (key_addr, key_size))
|
||||
flash_erase_page (((uint32_t)key_addr & ~(flash_page_size - 1)));
|
||||
flash_erase_page (((uintptr_t)key_addr & ~(flash_page_size - 1)));
|
||||
else
|
||||
flash_key_fill_zero_as_released (key_addr, key_size);
|
||||
}
|
||||
@@ -428,12 +486,12 @@ flash_key_release (uint8_t *key_addr, int key_size)
|
||||
void
|
||||
flash_key_release_page (enum kind_of_key kk)
|
||||
{
|
||||
flash_erase_page ((uint32_t)flash_key_getpage (kk));
|
||||
flash_erase_page ((uintptr_t)flash_key_getpage (kk));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
flash_clear_halfword (uint32_t addr)
|
||||
flash_clear_halfword (uintptr_t addr)
|
||||
{
|
||||
flash_program_halfword (addr, 0);
|
||||
}
|
||||
@@ -442,7 +500,7 @@ flash_clear_halfword (uint32_t addr)
|
||||
void
|
||||
flash_put_data_internal (const uint8_t *p, uint16_t hw)
|
||||
{
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -456,7 +514,7 @@ flash_put_data (uint16_t hw)
|
||||
DEBUG_INFO ("data allocation failure.\r\n");
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
|
||||
@@ -468,14 +526,14 @@ flash_bool_clear (const uint8_t **addr_p)
|
||||
if ((p = *addr_p) == NULL)
|
||||
return;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
*addr_p = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
flash_bool_write_internal (const uint8_t *p, int nr)
|
||||
{
|
||||
flash_program_halfword ((uint32_t)p, nr);
|
||||
flash_program_halfword ((uintptr_t)p, nr);
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
@@ -491,7 +549,7 @@ flash_bool_write (uint8_t nr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -507,7 +565,7 @@ flash_enum_write_internal (const uint8_t *p, int nr, uint8_t v)
|
||||
{
|
||||
uint16_t hw = nr | (v << 8);
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
@@ -523,7 +581,7 @@ flash_enum_write (uint8_t nr, uint8_t v)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -559,14 +617,14 @@ flash_cnt123_write_internal (const uint8_t *p, int which, int v)
|
||||
uint16_t hw;
|
||||
|
||||
hw = NR_COUNTER_123 | (which << 8);
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
|
||||
if (v == 1)
|
||||
return;
|
||||
else if (v == 2)
|
||||
flash_program_halfword ((uint32_t)p+2, 0xc3c3);
|
||||
flash_program_halfword ((uintptr_t)p+2, 0xc3c3);
|
||||
else /* v == 3 */
|
||||
flash_program_halfword ((uint32_t)p+2, 0);
|
||||
flash_program_halfword ((uintptr_t)p+2, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -584,7 +642,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
|
||||
return;
|
||||
}
|
||||
hw = NR_COUNTER_123 | (which << 8);
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
*addr_p = p + 2;
|
||||
}
|
||||
else
|
||||
@@ -599,7 +657,7 @@ flash_cnt123_increment (uint8_t which, const uint8_t **addr_p)
|
||||
else
|
||||
hw = 0;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, hw);
|
||||
flash_program_halfword ((uintptr_t)p, hw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,9 +669,9 @@ flash_cnt123_clear (const uint8_t **addr_p)
|
||||
if ((p = *addr_p) == NULL)
|
||||
return;
|
||||
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
p -= 2;
|
||||
flash_program_halfword ((uint32_t)p, 0);
|
||||
flash_program_halfword ((uintptr_t)p, 0);
|
||||
*addr_p = NULL;
|
||||
}
|
||||
|
||||
@@ -627,9 +685,9 @@ flash_erase_binary (uint8_t file_id)
|
||||
const uint8_t *p = &ch_certificate_start;
|
||||
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
|
||||
{
|
||||
flash_erase_page ((uint32_t)p);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
if (FLASH_CH_CERTIFICATE_SIZE > flash_page_size)
|
||||
flash_erase_page ((uint32_t)p + flash_page_size);
|
||||
flash_erase_page ((uintptr_t)p + flash_page_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -652,17 +710,19 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
maxsize = 6;
|
||||
p = &openpgpcard_aid[8];
|
||||
}
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
{
|
||||
maxsize = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
|
||||
if (len == 0 && offset == 0)
|
||||
{ /* This means removal of update key. */
|
||||
if (flash_program_halfword ((uint32_t)p, 0) != 0)
|
||||
if (flash_program_halfword ((uintptr_t)p, 0) != 0)
|
||||
flash_warning ("DO WRITE ERROR");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
else if (file_id == FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
@@ -678,13 +738,13 @@ flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||
else
|
||||
{
|
||||
uint16_t hw;
|
||||
uint32_t addr;
|
||||
uintptr_t addr;
|
||||
int i;
|
||||
|
||||
if (flash_check_blank (p + offset, len) == 0)
|
||||
return -1;
|
||||
|
||||
addr = (uint32_t)p + offset;
|
||||
addr = (uintptr_t)p + offset;
|
||||
for (i = 0; i < len/2; i++)
|
||||
{
|
||||
hw = data[i*2] | (data[i*2+1]<<8);
|
||||
|
||||
16
src/gnuk-malloc.h
Normal file
16
src/gnuk-malloc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Gnuk uses its own malloc functions.
|
||||
*
|
||||
* The intention is no-dependency to C library. But, we provide
|
||||
* malloc and free here, since RSA routines uses malloc/free
|
||||
* internally.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> /* NULL and size_t */
|
||||
|
||||
#define malloc(size) gnuk_malloc (size)
|
||||
#define free(p) gnuk_free (p)
|
||||
|
||||
void *gnuk_malloc (size_t);
|
||||
void gnuk_free (void *);
|
||||
119
src/gnuk.h
119
src/gnuk.h
@@ -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;
|
||||
@@ -24,24 +24,25 @@ extern struct apdu apdu;
|
||||
void ccid_card_change_signal (int how);
|
||||
|
||||
/* 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_CARD_CHANGE 1
|
||||
#define EV_TX_FINISHED 2 /* CCID Tx finished */
|
||||
#define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */
|
||||
#define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */
|
||||
#define EV_RX_DATA_READY 16 /* USB Rx data available */
|
||||
|
||||
/* OpenPGPcard thread */
|
||||
#define EV_PINPAD_INPUT_DONE (1)
|
||||
#define EV_EXIT (2)
|
||||
#define EV_CMD_AVAILABLE (4)
|
||||
#define EV_VERIFY_CMD_AVAILABLE (8)
|
||||
#define EV_MODIFY_CMD_AVAILABLE (16)
|
||||
#define EV_MODIFY_CMD_AVAILABLE 1
|
||||
#define EV_VERIFY_CMD_AVAILABLE 2
|
||||
#define EV_CMD_AVAILABLE 4
|
||||
#define EV_EXIT 8
|
||||
#define EV_PINPAD_INPUT_DONE 16
|
||||
|
||||
/* Maximum cmd apdu data is key import 24+4+256+256 (proc_key_import) */
|
||||
#define MAX_CMD_APDU_DATA_SIZE (24+4+256+256) /* without header */
|
||||
/* 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,22 +50,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 */
|
||||
/* Busy1, Busy2, Busy3, Busy5 */
|
||||
ICC_STATE_EXECUTE, /* Busy4 */
|
||||
ICC_STATE_RECEIVE, /* APDU Received Partially */
|
||||
ICC_STATE_SEND, /* APDU Sent Partially */
|
||||
enum ccid_state {
|
||||
CCID_STATE_NOCARD, /* No card available */
|
||||
CCID_STATE_START, /* Initial */
|
||||
CCID_STATE_WAIT, /* Waiting APDU */
|
||||
|
||||
ICC_STATE_EXITED, /* ICC Thread Terminated */
|
||||
ICC_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
CCID_STATE_EXECUTE, /* Executing command */
|
||||
CCID_STATE_ACK_REQUIRED_0, /* Ack required (executing)*/
|
||||
CCID_STATE_ACK_REQUIRED_1, /* Waiting user's ACK (execution finished) */
|
||||
|
||||
CCID_STATE_EXITED, /* CCID Thread Terminated */
|
||||
CCID_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
#define CCID_CARD_INIT CARD_CHANGE_INSERT
|
||||
|
||||
extern enum icc_state *icc_state_p;
|
||||
enum ccid_state ccid_get_ccid_state (void);
|
||||
|
||||
extern volatile uint8_t auth_status;
|
||||
#define AC_NONE_AUTHORIZED 0x00
|
||||
@@ -98,16 +98,19 @@ void ac_fini (void);
|
||||
|
||||
|
||||
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
|
||||
|
||||
void gpg_data_scan (const uint8_t *p);
|
||||
void gpg_data_scan (const uint8_t *start, const uint8_t *end);
|
||||
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);
|
||||
void gpg_do_keygen (uint8_t *buf);
|
||||
|
||||
const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
|
||||
@@ -121,8 +124,8 @@ const uint8_t *gpg_get_firmware_update_key (uint8_t keyno);
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNING = 0,
|
||||
GPG_KEY_FOR_DECRYPTION,
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
GPG_KEY_FOR_DECRYPTION = 1,
|
||||
GPG_KEY_FOR_AUTHENTICATION = 2,
|
||||
};
|
||||
|
||||
enum size_of_key {
|
||||
@@ -134,8 +137,10 @@ enum size_of_key {
|
||||
int gpg_get_algo_attr (enum kind_of_key kk);
|
||||
int gpg_get_algo_attr_key_size (enum kind_of_key kk, enum size_of_key s);
|
||||
|
||||
const uint8_t *flash_init (void);
|
||||
void flash_init_keys (void);
|
||||
void flash_do_storage_init (const uint8_t **, const uint8_t **);
|
||||
void flash_terminate (void);
|
||||
void flash_activate (void);
|
||||
void flash_key_storage_init (void);
|
||||
void flash_do_release (const uint8_t *);
|
||||
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
|
||||
uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
@@ -145,7 +150,7 @@ int flash_key_write (uint8_t *key_addr,
|
||||
const uint8_t *key_data, int key_data_len,
|
||||
const uint8_t *pubkey, int pubkey_len);
|
||||
void flash_set_data_pool_last (const uint8_t *p);
|
||||
void flash_clear_halfword (uint32_t addr);
|
||||
void flash_clear_halfword (uintptr_t addr);
|
||||
void flash_increment_counter (uint8_t counter_tag_nr);
|
||||
void flash_reset_counter (uint8_t counter_tag_nr);
|
||||
|
||||
@@ -231,6 +236,7 @@ int gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
extern struct key_data kd[3];
|
||||
|
||||
#ifdef DEBUG
|
||||
void stdout_init (void);
|
||||
#define DEBUG_MORE 1
|
||||
/*
|
||||
* Debug functions in debug.c
|
||||
@@ -257,22 +263,22 @@ void put_binary (const char *s, int len);
|
||||
#endif
|
||||
|
||||
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
|
||||
uint8_t *modulus_calc (const uint8_t *, int);
|
||||
int modulus_calc (const uint8_t *, int, uint8_t *);
|
||||
int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *,
|
||||
unsigned int *);
|
||||
int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *);
|
||||
uint8_t *rsa_genkey (int);
|
||||
int rsa_genkey (int, uint8_t *, uint8_t *);
|
||||
|
||||
int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
|
||||
int ecc_compute_public_p256r1 (const uint8_t *key_data, uint8_t *);
|
||||
int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
|
||||
int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
|
||||
int ecc_compute_public_p256k1 (const uint8_t *key_data, uint8_t *);
|
||||
int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t *d1);
|
||||
int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
@@ -280,19 +286,24 @@ int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
|
||||
int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
|
||||
const uint8_t *sk_a, const uint8_t *seed,
|
||||
const uint8_t *pk);
|
||||
uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
|
||||
uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
|
||||
void eddsa_compute_public_25519 (const uint8_t *a, uint8_t *);
|
||||
void ecdh_compute_public_25519 (const uint8_t *a, uint8_t *);
|
||||
int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
|
||||
const uint8_t *key_data);
|
||||
|
||||
const uint8_t *gpg_do_read_simple (uint8_t);
|
||||
void gpg_do_write_simple (uint8_t, const uint8_t *, int);
|
||||
void gpg_increment_digital_signature_counter (void);
|
||||
void gpg_do_get_initial_pw_setting (int is_pw3, int *r_len,
|
||||
const uint8_t **r_p);
|
||||
int gpg_do_kdf_check (int len, int how_many);
|
||||
int gpg_do_get_uif (enum kind_of_key kk);
|
||||
|
||||
|
||||
void fatal (uint8_t code) __attribute__ ((noreturn));
|
||||
#define FATAL_FLASH 1
|
||||
#define FATAL_RANDOM 2
|
||||
#define FATAL_HEAP 3
|
||||
|
||||
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
extern uint8_t admin_authorized;
|
||||
@@ -325,7 +336,8 @@ extern uint8_t admin_authorized;
|
||||
#define NR_DO_KEYSTRING_PW1 0x11
|
||||
#define NR_DO_KEYSTRING_RC 0x12
|
||||
#define NR_DO_KEYSTRING_PW3 0x13
|
||||
#define NR_DO__LAST__ 20 /* == 0x14 */
|
||||
#define NR_DO_KDF 0x14
|
||||
#define NR_DO__LAST__ 21 /* == 0x15 */
|
||||
/* 14-bit counter for DS: Recorded in flash memory by 1-halfword (2-byte). */
|
||||
/*
|
||||
* Representation of 14-bit counter:
|
||||
@@ -368,7 +380,17 @@ extern uint8_t admin_authorized;
|
||||
#define NR_KEY_ALGO_ATTR_DEC 0xf2
|
||||
#define NR_KEY_ALGO_ATTR_AUT 0xf3
|
||||
/*
|
||||
* NR_UINT_SOMETHING could be here... Use 0xf[456789abcd]
|
||||
* Representation of User Interaction Flag:
|
||||
* 0 (UIF disabled): 0xf?00 or No record in flash memory
|
||||
* 1 (UIF enabled): 0xf?01
|
||||
* 2 (UIF permanently enabled): 0xf?02
|
||||
*
|
||||
*/
|
||||
#define NR_DO_UIF_SIG 0xf6
|
||||
#define NR_DO_UIF_DEC 0xf7
|
||||
#define NR_DO_UIF_AUT 0xf8
|
||||
/*
|
||||
* NR_UINT_SOMETHING could be here... Use 0xf[459abcd]
|
||||
*/
|
||||
/* 123-counters: Recorded in flash memory by 2-halfword (4-byte). */
|
||||
/*
|
||||
@@ -416,12 +438,16 @@ void flash_do_write_internal (const uint8_t *p, int nr,
|
||||
|
||||
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)
|
||||
#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
|
||||
#define LED_WAIT_FOR_BUTTON 256
|
||||
#define LED_OFF LED_FINISH_COMMAND
|
||||
void led_blink (int spec);
|
||||
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
@@ -448,4 +474,7 @@ int pinpad_getline (int msg_code, uint32_t timeout_usec);
|
||||
|
||||
#endif
|
||||
|
||||
extern uint8_t _regnual_start, __heap_end__[];
|
||||
|
||||
extern uint8_t _regnual_start[], __heap_end__[];
|
||||
|
||||
uint8_t * sram_address (uint32_t offset);
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
||||
__process0_stack_size__ = 0x0100; /* main */
|
||||
__process1_stack_size__ = 0x0140; /* ccid */
|
||||
__process2_stack_size__ = 0x0180; /* rng */
|
||||
__process3_stack_size__ = 0x1600; /* gpg */
|
||||
__process4_stack_size__ = 0x0100; /* intr: usb */
|
||||
__process5_stack_size__ = @MSC_SIZE@; /* msc */
|
||||
__process6_stack_size__ = @TIM_SIZE@; /* intr: timer */
|
||||
__process7_stack_size__ = @EXT_SIZE@; /* intr: ext */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = @ORIGIN@, len = 4k
|
||||
@@ -34,10 +24,10 @@ SECTIONS
|
||||
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.*)
|
||||
build/sys-*.o(.text)
|
||||
build/sys-*.o(.text.*)
|
||||
build/sys-*.o(.rodata)
|
||||
build/sys-*.o(.rodata.*)
|
||||
. = ALIGN(1024);
|
||||
*(.sys.0)
|
||||
*(.sys.1)
|
||||
@@ -82,45 +72,18 @@ SECTIONS
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
.stacks :
|
||||
.stacks (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__main_stack_base__ = .;
|
||||
. += __main_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__main_stack_end__ = .;
|
||||
__process0_stack_base__ = .;
|
||||
. += __process0_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process0_stack_end__ = .;
|
||||
__process1_stack_base__ = .;
|
||||
. += __process1_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process1_stack_end__ = .;
|
||||
__process2_stack_base__ = .;
|
||||
. += __process2_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process2_stack_end__ = .;
|
||||
__process3_stack_base__ = .;
|
||||
. += __process3_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process3_stack_end__ = .;
|
||||
__process4_stack_base__ = .;
|
||||
. += __process4_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process4_stack_end__ = .;
|
||||
__process5_stack_base__ = .;
|
||||
. += __process5_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process5_stack_end__ = .;
|
||||
__process6_stack_base__ = .;
|
||||
. += __process6_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process6_stack_end__ = .;
|
||||
__process7_stack_base__ = .;
|
||||
. += __process7_stack_size__;
|
||||
. = ALIGN(8);
|
||||
__process7_stack_end__ = .;
|
||||
*(.main_stack)
|
||||
*(.process_stack.0)
|
||||
*(.process_stack.1)
|
||||
*(.process_stack.2)
|
||||
*(.process_stack.3)
|
||||
*(.process_stack.4)
|
||||
*(.process_stack.5)
|
||||
*(.process_stack.6)
|
||||
*(.process_stack.7)
|
||||
. = ALIGN(8);
|
||||
} > ram
|
||||
|
||||
@@ -171,20 +134,20 @@ SECTIONS
|
||||
.gnuk_flash :
|
||||
{
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
_data_pool = .;
|
||||
KEEP(*(.gnuk_data))
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += @FLASH_PAGE_SIZE@;
|
||||
_keystore_pool = .;
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += 512;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
_updatekey_store = .;
|
||||
. += 1024;
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
_data_pool = .;
|
||||
KEEP(*(.gnuk_data))
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
. += @FLASH_PAGE_SIZE@;
|
||||
} > flash =0xffffffff
|
||||
}
|
||||
|
||||
|
||||
536
src/main.c
536
src/main.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* main.c - main routine of Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018, 2021
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -35,93 +35,54 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb-cdc.h"
|
||||
#include "random.h"
|
||||
#include "stm32f103.h"
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.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);
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define main emulated_main
|
||||
#else
|
||||
void
|
||||
_write (const char *s, int size)
|
||||
{
|
||||
(void)s;
|
||||
(void)size;
|
||||
}
|
||||
#include "mcu/stm32f103.h"
|
||||
#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)
|
||||
#define LED_TIMEOUT_STOP (200*1000)
|
||||
|
||||
#ifdef DFU_SUPPORT
|
||||
static int
|
||||
flash_write_any (uintptr_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
while (len)
|
||||
{
|
||||
uint16_t hw = *src++;
|
||||
|
||||
hw |= (*src++ << 8);
|
||||
status = flash_program_halfword (dst_addr, hw);
|
||||
if (status != 0)
|
||||
return 0; /* error return */
|
||||
|
||||
dst_addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
uint8_t *flash_addr_key_storage_start;
|
||||
uint8_t *flash_addr_data_storage_start;
|
||||
#else
|
||||
#define ID_OFFSET (2+SERIALNO_STR_LEN*2)
|
||||
static void
|
||||
device_initialize_once (void)
|
||||
@@ -134,7 +95,7 @@ device_initialize_once (void)
|
||||
* This is the first time invocation.
|
||||
* Setup serial number by unique device ID.
|
||||
*/
|
||||
const uint8_t *u = unique_device_id () + 8;
|
||||
const uint8_t *u = unique_device_id () + (MHZ < 96 ? 8: 0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
@@ -149,12 +110,66 @@ device_initialize_once (void)
|
||||
nibble += (nibble >= 10 ? ('A' - 10) : '0');
|
||||
flash_put_data_internal (&p[i*4+2], nibble);
|
||||
}
|
||||
|
||||
#ifdef DFU_SUPPORT
|
||||
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
|
||||
/*
|
||||
* Overwrite DFU bootloader with a copy of SYS linked to ORIGIN_REAL.
|
||||
* Then protect flash from readout.
|
||||
*/
|
||||
{
|
||||
extern uint8_t _binary_build_stdaln_sys_bin_start;
|
||||
extern uint8_t _binary_build_stdaln_sys_bin_size;
|
||||
size_t stdaln_sys_size = (size_t) &_binary_build_stdaln_sys_bin_size;
|
||||
extern const uint32_t FT0[256], FT1[256], FT2[256];
|
||||
extern handler vector_table[];
|
||||
uintptr_t addr;
|
||||
uint32_t flash_page_size = 1024; /* 1KiB default */
|
||||
|
||||
if (((*CHIP_ID_REG)&0x07) == 0x04) /* High density device. */
|
||||
flash_page_size = 2048; /* It's 2KiB. */
|
||||
|
||||
/* Kill DFU */
|
||||
for (addr = ORIGIN_REAL; addr < ORIGIN;
|
||||
addr += flash_page_size)
|
||||
flash_erase_page (addr);
|
||||
|
||||
/* Copy SYS */
|
||||
addr = ORIGIN_REAL;
|
||||
flash_write_any(addr, &_binary_build_stdaln_sys_bin_start,
|
||||
stdaln_sys_size);
|
||||
addr += stdaln_sys_size;
|
||||
flash_write_any(addr, (const uint8_t *) &FT0, sizeof(FT0));
|
||||
addr += sizeof(FT0);
|
||||
flash_write_any(addr, (const uint8_t *) &FT1, sizeof(FT1));
|
||||
addr += sizeof(FT1);
|
||||
flash_write_any(addr, (const uint8_t *) &FT2, sizeof(FT2));
|
||||
|
||||
addr = ORIGIN_REAL + 0x1000;
|
||||
if (addr < ORIGIN) {
|
||||
/* Need to patch top of stack and reset vector there */
|
||||
handler *new_vector = (handler *) addr;
|
||||
flash_write((uintptr_t) &new_vector[0], (const uint8_t *)
|
||||
&vector_table[0], sizeof(handler));
|
||||
flash_write((uintptr_t) &new_vector[1], (const uint8_t *)
|
||||
&vector[1], sizeof(handler));
|
||||
}
|
||||
|
||||
flash_protect();
|
||||
nvic_system_reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static volatile uint8_t fatal_code;
|
||||
static struct eventflag led_event;
|
||||
static chopstx_poll_cond_t led_event_poll_desc;
|
||||
static struct chx_poll_head *const led_event_poll[] = {
|
||||
(struct chx_poll_head *)&led_event_poll_desc
|
||||
};
|
||||
|
||||
static void display_fatal_code (void)
|
||||
{
|
||||
@@ -195,104 +210,88 @@ 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 (uint32_t on_time, uint32_t off_time)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
set_led (!led_inverted);
|
||||
m = eventflag_wait_timeout (&led_event, on_time);
|
||||
chopstx_poll (&on_time, 1, led_event_poll);
|
||||
set_led (led_inverted);
|
||||
if (m) return m;
|
||||
if ((m = eventflag_wait_timeout (&led_event, off_time)))
|
||||
return m;
|
||||
return 0;
|
||||
chopstx_poll (&off_time, 1, led_event_poll);
|
||||
}
|
||||
|
||||
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_get_ccid_state ();
|
||||
uint32_t usec;
|
||||
|
||||
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 (ccid_state == CCID_STATE_WAIT)
|
||||
{
|
||||
if ((m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_STOP * 2)))
|
||||
return m;
|
||||
usec = LED_TIMEOUT_STOP * 2;
|
||||
chopstx_poll (&usec, 1, led_event_poll);
|
||||
}
|
||||
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;
|
||||
usec = LED_TIMEOUT_INTERVAL;
|
||||
chopstx_poll (&usec, 1, led_event_poll);
|
||||
emit_led (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);
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/*
|
||||
* In Gnuk 1.0.[12], reGNUal was not relocatable.
|
||||
* Now, it's relocatable, but we need to calculate its entry address
|
||||
* based on it's pre-defined address.
|
||||
*/
|
||||
#define REGNUAL_START_ADDRESS_COMPATIBLE 0x20001400
|
||||
static uint32_t
|
||||
static uintptr_t
|
||||
calculate_regnual_entry_address (const uint8_t *addr)
|
||||
{
|
||||
const uint8_t *p = addr + 4;
|
||||
uint32_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||
uintptr_t v = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24);
|
||||
|
||||
v -= REGNUAL_START_ADDRESS_COMPATIBLE;
|
||||
v += (uint32_t)addr;
|
||||
v += (uintptr_t)addr;
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint8_t __process1_stack_base__, __process1_stack_size__;
|
||||
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__;
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_CCID ((uintptr_t)process1_base)
|
||||
#define STACK_SIZE_CCID (sizeof process1_base)
|
||||
|
||||
#define PRIO_CCID 3
|
||||
#define PRIO_USB 4
|
||||
#define PRIO_MAIN 5
|
||||
#define PRIO_MAIN 5
|
||||
|
||||
extern void *usb_intr (void *arg);
|
||||
extern void *ccid_thread (void *arg);
|
||||
|
||||
static void gnuk_malloc_init (void);
|
||||
|
||||
@@ -301,29 +300,131 @@ 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[])
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
unsigned int count = 0;
|
||||
uint32_t entry;
|
||||
chopstx_t usb_thd;
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
uintptr_t flash_addr;
|
||||
const char *flash_image_path;
|
||||
char *path_string = NULL;
|
||||
#endif
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
uintptr_t entry;
|
||||
#endif
|
||||
chopstx_t ccid_thd;
|
||||
int wait_for_ack = 0;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
chopstx_conf_idle (1);
|
||||
|
||||
gnuk_malloc_init ();
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define FLASH_IMAGE_NAME ".gnuk-flash-image"
|
||||
|
||||
if (argc >= 4 || (argc == 2 && !strcmp (argv[1], "--help")))
|
||||
{
|
||||
fprintf (stdout, "Usage: %s [--vidpid=Vxxx:Pxxx] [flash-image-file]",
|
||||
argv[0]);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strncmp (argv[1], "--debug=", 8))
|
||||
{
|
||||
debug = strtol (&argv[1][8], NULL, 10);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strncmp (argv[1], "--vidpid=", 9))
|
||||
{
|
||||
extern uint8_t device_desc[];
|
||||
uint32_t id;
|
||||
char *p;
|
||||
|
||||
id = (uint32_t)strtol (&argv[1][9], &p, 16);
|
||||
device_desc[8] = (id & 0xff);
|
||||
device_desc[9] = (id >> 8);
|
||||
|
||||
if (p && p[0] == ':')
|
||||
{
|
||||
id = (uint32_t)strtol (&p[1], NULL, 16);
|
||||
device_desc[10] = (id & 0xff);
|
||||
device_desc[11] = (id >> 8);
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
char *p = getenv ("HOME");
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
fprintf (stderr, "Can't find $HOME\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
path_string = malloc (strlen (p) + strlen (FLASH_IMAGE_NAME) + 2);
|
||||
|
||||
p = stpcpy (path_string, p);
|
||||
*p++ = '/';
|
||||
strcpy (p, FLASH_IMAGE_NAME);
|
||||
flash_image_path = path_string;
|
||||
}
|
||||
else
|
||||
flash_image_path = argv[1];
|
||||
|
||||
if (access (flash_image_path, F_OK) < 0)
|
||||
{
|
||||
int fd;
|
||||
char buf[8192];
|
||||
|
||||
memset (buf, 0xff, sizeof buf);
|
||||
memset (buf+4*1024, 0, 2);
|
||||
fd = open (flash_image_path, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror ("creating flash file");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (write (fd, buf, sizeof buf) != sizeof buf)
|
||||
{
|
||||
perror ("initializing flash file");
|
||||
close (fd);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
puts ("Gnuk (emulation with USBIP), a GnuPG USB Token implementation");
|
||||
puts ("Copyright (C) 2021 Free Software Initiative of Japan");
|
||||
puts ("This is free software under GPLv3+.");
|
||||
|
||||
flash_addr = flash_init (flash_image_path);
|
||||
flash_addr_key_storage_start = (uint8_t *)flash_addr;
|
||||
flash_addr_data_storage_start = (uint8_t *)flash_addr + 4096;
|
||||
#else
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#endif
|
||||
|
||||
flash_unlock ();
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
if (path_string)
|
||||
free (path_string);
|
||||
#else
|
||||
device_initialize_once ();
|
||||
#endif
|
||||
|
||||
adc_init ();
|
||||
|
||||
eventflag_init (&led_event, chopstx_main);
|
||||
eventflag_init (&led_event);
|
||||
|
||||
random_init ();
|
||||
|
||||
@@ -331,8 +432,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 ();
|
||||
@@ -341,73 +442,57 @@ main (int argc, char *argv[])
|
||||
msc_init ();
|
||||
#endif
|
||||
|
||||
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
|
||||
usb_intr, NULL);
|
||||
|
||||
chopstx_main_init (PRIO_MAIN);
|
||||
chopstx_setpriority (PRIO_MAIN);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bDeviceState != UNCONNECTED)
|
||||
if (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
|
||||
break;
|
||||
|
||||
chopstx_usec_wait (250*1000);
|
||||
}
|
||||
|
||||
eventflag_prepare_poll (&led_event, &led_event_poll_desc);
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
if (icc_state_p != NULL && *icc_state_p == ICC_STATE_EXEC_REQUESTED)
|
||||
break;
|
||||
if (wait_for_ack)
|
||||
m = eventflag_wait_timeout (&led_event, LED_TIMEOUT_INTERVAL);
|
||||
else
|
||||
m = eventflag_wait (&led_event);
|
||||
|
||||
m = eventflag_wait_timeout (&led_event, MAIN_TIMEOUT_INTERVAL);
|
||||
got_it:
|
||||
count++;
|
||||
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;
|
||||
case LED_WAIT_FOR_BUTTON:
|
||||
wait_for_ack ^= 1;
|
||||
/* fall through */
|
||||
default:
|
||||
if ((m = emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_STOP)))
|
||||
goto got_it;
|
||||
emit_led (LED_TIMEOUT_ZERO, LED_TIMEOUT_ZERO);
|
||||
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);
|
||||
@@ -416,33 +501,15 @@ main (int argc, char *argv[])
|
||||
/* Finish application. */
|
||||
chopstx_join (ccid_thd, NULL);
|
||||
|
||||
chopstx_cancel (usb_thd);
|
||||
chopstx_join (usb_thd, NULL);
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/* Set vector */
|
||||
SCB->VTOR = (uint32_t)&_regnual_start;
|
||||
entry = calculate_regnual_entry_address (&_regnual_start);
|
||||
SCB->VTOR = (uintptr_t)_regnual_start;
|
||||
entry = calculate_regnual_entry_address (_regnual_start);
|
||||
#ifdef DFU_SUPPORT
|
||||
#define FLASH_SYS_START_ADDR 0x08000000
|
||||
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
|
||||
#define CHIP_ID_REG ((uint32_t *)0xE0042000)
|
||||
{
|
||||
extern uint8_t _sys;
|
||||
uint32_t addr;
|
||||
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
|
||||
uint32_t flash_page_size = 1024; /* 1KiB default */
|
||||
|
||||
if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
|
||||
flash_page_size = 2048; /* It's 2KiB. */
|
||||
|
||||
/* Kill DFU */
|
||||
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
|
||||
addr += flash_page_size)
|
||||
flash_erase_page (addr);
|
||||
|
||||
/* copy system service routines */
|
||||
flash_write (FLASH_SYS_START_ADDR, &_sys, 0x1000);
|
||||
/* Use SYS at ORIGIN_REAL instead of the one at ORIGIN */
|
||||
handler *new_vector = (handler *)ORIGIN_REAL;
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void))) new_vector[9];
|
||||
|
||||
/* Leave Gnuk to exec reGNUal */
|
||||
(*func) ((void (*)(void))entry);
|
||||
@@ -452,6 +519,9 @@ main (int argc, char *argv[])
|
||||
/* Leave Gnuk to exec reGNUal */
|
||||
flash_erase_all_and_exec ((void (*)(void))entry);
|
||||
#endif
|
||||
#else
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
/* Never reached */
|
||||
return 0;
|
||||
@@ -460,6 +530,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);
|
||||
@@ -480,39 +552,55 @@ fatal (uint8_t code)
|
||||
* reclaimed to system.
|
||||
*/
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define HEAP_SIZE (32*1024)
|
||||
uint8_t __heap_base__[HEAP_SIZE];
|
||||
|
||||
#define HEAP_START __heap_base__
|
||||
#define HEAP_END (__heap_base__ + HEAP_SIZE)
|
||||
#define HEAP_ALIGNMENT 32
|
||||
#else
|
||||
extern uint8_t __heap_base__[];
|
||||
extern uint8_t __heap_end__[];
|
||||
|
||||
#define MEMORY_END (__heap_end__)
|
||||
#define MEMORY_ALIGNMENT 16
|
||||
#define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
|
||||
#define HEAP_START __heap_base__
|
||||
#define HEAP_END (__heap_end__)
|
||||
#define HEAP_ALIGNMENT 16
|
||||
#define HEAP_SIZE ((uintptr_t)__heap_end__ - (uintptr_t)__heap_base__)
|
||||
#endif
|
||||
|
||||
#define HEAP_ALIGN(n) (((n) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT - 1))
|
||||
|
||||
static uint8_t *heap_p;
|
||||
static chopstx_mutex_t malloc_mtx;
|
||||
|
||||
struct mem_head {
|
||||
uint32_t size;
|
||||
uintptr_t size;
|
||||
/**/
|
||||
struct mem_head *next, *prev; /* free list chain */
|
||||
struct mem_head *neighbor; /* backlink to neighbor */
|
||||
};
|
||||
|
||||
#define MEM_HEAD_IS_CORRUPT(x) \
|
||||
((x)->size != HEAP_ALIGN((x)->size) || (x)->size > HEAP_SIZE)
|
||||
#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
|
||||
|
||||
static struct mem_head *free_list;
|
||||
|
||||
static void
|
||||
gnuk_malloc_init (void)
|
||||
{
|
||||
chopstx_mutex_init (&malloc_mtx);
|
||||
heap_p = __heap_base__;
|
||||
heap_p = HEAP_START;
|
||||
free_list = NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
sbrk (size_t size)
|
||||
gnuk_sbrk (intptr_t size)
|
||||
{
|
||||
void *p = (void *)heap_p;
|
||||
|
||||
if ((size_t)(MEMORY_END - heap_p) < size)
|
||||
if ((HEAP_END - heap_p) < size)
|
||||
return NULL;
|
||||
|
||||
heap_p += size;
|
||||
@@ -537,7 +625,7 @@ gnuk_malloc (size_t size)
|
||||
struct mem_head *m;
|
||||
struct mem_head *m0;
|
||||
|
||||
size = MEMORY_ALIGN (size + sizeof (uint32_t));
|
||||
size = HEAP_ALIGN (size + sizeof (uintptr_t));
|
||||
|
||||
chopstx_mutex_lock (&malloc_mtx);
|
||||
DEBUG_INFO ("malloc: ");
|
||||
@@ -548,12 +636,12 @@ gnuk_malloc (size_t size)
|
||||
{
|
||||
if (m == NULL)
|
||||
{
|
||||
m = (struct mem_head *)sbrk (size);
|
||||
m = (struct mem_head *)gnuk_sbrk (size);
|
||||
if (m)
|
||||
m->size = size;
|
||||
break;
|
||||
}
|
||||
|
||||
MEM_HEAD_CHECK (m);
|
||||
if (m->size == size)
|
||||
{
|
||||
remove_from_free_list (m);
|
||||
@@ -577,8 +665,8 @@ gnuk_malloc (size_t size)
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WORD ((uint32_t)m + sizeof (uint32_t));
|
||||
return (void *)m + sizeof (uint32_t);
|
||||
DEBUG_WORD ((uintptr_t)m + sizeof (uintptr_t));
|
||||
return (void *)m + sizeof (uintptr_t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,18 +674,23 @@ gnuk_malloc (size_t size)
|
||||
void
|
||||
gnuk_free (void *p)
|
||||
{
|
||||
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uint32_t));
|
||||
struct mem_head *m = (struct mem_head *)((void *)p - sizeof (uintptr_t));
|
||||
struct mem_head *m0;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
chopstx_mutex_lock (&malloc_mtx);
|
||||
m0 = free_list;
|
||||
DEBUG_INFO ("free: ");
|
||||
DEBUG_SHORT (m->size);
|
||||
DEBUG_WORD ((uint32_t)p);
|
||||
DEBUG_WORD ((uintptr_t)p);
|
||||
|
||||
MEM_HEAD_CHECK (m);
|
||||
m->neighbor = NULL;
|
||||
while (m0)
|
||||
{
|
||||
MEM_HEAD_CHECK (m0);
|
||||
if ((void *)m + m->size == (void *)m0)
|
||||
m0->neighbor = m;
|
||||
else if ((void *)m0 + m0->size == (void *)m)
|
||||
@@ -613,6 +706,7 @@ gnuk_free (void *p)
|
||||
heap_p -= m->size;
|
||||
while (mn)
|
||||
{
|
||||
MEM_HEAD_CHECK (mn);
|
||||
heap_p -= mn->size;
|
||||
remove_from_free_list (mn);
|
||||
mn = mn->neighbor;
|
||||
|
||||
32
src/mcu-stm32f103.c
Normal file
32
src/mcu-stm32f103.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* mcu-stm32f103.c - STM32F103 specific routines
|
||||
*
|
||||
* Copyright (C) 2017
|
||||
* 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 "mcu/stm32f103.h"
|
||||
|
||||
uint8_t *
|
||||
sram_address (uint32_t offset)
|
||||
{
|
||||
return ((uint8_t *)0x20000000) + offset;
|
||||
}
|
||||
10
src/mod.c
10
src/mod.c
@@ -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)
|
||||
@@ -36,7 +36,6 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
bn512 q_big[1], tmp[1];
|
||||
uint32_t carry;
|
||||
#define borrow carry
|
||||
uint32_t borrow_next;
|
||||
|
||||
memset (q, 0, sizeof (bn256));
|
||||
q->word[0] = A->word[15];
|
||||
@@ -110,9 +109,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
= 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];
|
||||
@@ -122,7 +119,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
bn256_sub (q, X, B);
|
||||
|
||||
if (carry)
|
||||
carry -= bn256_sub (X, X, B);
|
||||
bn256_sub (X, X, B);
|
||||
else
|
||||
bn256_sub (q, X, B);
|
||||
|
||||
@@ -145,7 +142,7 @@ mod_reduce (bn256 *X, const bn512 *A, const bn256 *B, const bn256 *MU_lower)
|
||||
|
||||
/**
|
||||
* @brief C = X^(-1) mod N
|
||||
*
|
||||
*
|
||||
* Assume X and N are co-prime (or N is prime).
|
||||
* NOTE: If X==0, it return 0.
|
||||
*
|
||||
@@ -159,6 +156,7 @@ mod_inv (bn256 *C, const bn256 *X, const bn256 *N)
|
||||
#define borrow carry
|
||||
int n = MAX_GCD_STEPS_BN256;
|
||||
|
||||
memset (tmp, 0, sizeof (bn256));
|
||||
memset (C, 0, sizeof (bn256));
|
||||
memcpy (u, X, sizeof (bn256));
|
||||
memcpy (v, N, sizeof (bn256));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* modp256k1.c -- modulo arithmetic for p256k1
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2014, 2016, 2020 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -55,12 +55,12 @@ const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff,
|
||||
/*
|
||||
* Implementation Note.
|
||||
*
|
||||
* It's not always modulo p256k1. The representation is redundant
|
||||
* during computation. For example, when we add the prime - 1 and 1,
|
||||
* it won't overflow to 2^256, and the result is represented within
|
||||
* 256-bit.
|
||||
* It'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.
|
||||
*
|
||||
* It is guaranteed that modp256k1_reduce reduces to modulo p256k1.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -69,14 +69,14 @@ const bn256 p256k1 = { {0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff,
|
||||
void
|
||||
modp256k1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t carry;
|
||||
uint32_t cond;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, P256K1);
|
||||
else
|
||||
bn256_sub (tmp, X, P256K1);
|
||||
cond = (bn256_add (X, A, B) == 0);
|
||||
cond &= bn256_sub (tmp, X, P256K1);
|
||||
memcpy (cond?dummy:X, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,12 +87,12 @@ modp256k1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, P256K1);
|
||||
else
|
||||
bn256_add (tmp, X, P256K1);
|
||||
bn256_add (tmp, X, P256K1);
|
||||
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,12 +181,12 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
*/
|
||||
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 */
|
||||
/* (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 */
|
||||
/* (S02, S01, S00) += (S1, S0)*2^9 */
|
||||
carry = (s0 >> 23) + s01;
|
||||
s02 += (s1 >> 23) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 9) + carry;
|
||||
@@ -196,7 +196,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^8 */
|
||||
/* (S02, S01, S00) += (S1, S0)*2^8 */
|
||||
carry = (s0 >> 24) + s01;
|
||||
s02 += (s1 >> 24) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 8) + carry;
|
||||
@@ -206,7 +206,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^7 */
|
||||
/* (S02, S01, S00) += (S1, S0)*2^7 */
|
||||
carry = (s0 >> 25) + s01;
|
||||
s02 += (s1 >> 25) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 7) + carry;
|
||||
@@ -216,7 +216,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^6 */
|
||||
/* (S02, S01, S00) += (S1, S0)*2^6 */
|
||||
carry = (s0 >> 26) + s01;
|
||||
s02 += (s1 >> 26) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 6) + carry;
|
||||
@@ -226,7 +226,7 @@ modp256k1_reduce (bn256 *X, const bn512 *A)
|
||||
s01 += carry;
|
||||
s02 += ((s01 < carry)? 1 : 0);
|
||||
|
||||
/* (S02, S01, S00) += (S1, S0)*2^4 */
|
||||
/* (S02, S01, S00) += (S1, S0)*2^4 */
|
||||
carry = (s0 >> 28) + s01;
|
||||
s02 += (s1 >> 28) + ((carry < s01)? 1 : 0);
|
||||
s01 = (s1 << 4) + carry;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* modp256r1.c -- modulo arithmetic for p256r1
|
||||
*
|
||||
* Copyright (C) 2011, 2013, 2014 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2013, 2014, 2016, 2020
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -49,12 +50,12 @@ const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
/*
|
||||
* Implementation Note.
|
||||
*
|
||||
* It's not always modulo p256r1. The representation is redundant
|
||||
* during computation. For example, when we add the prime - 1 and 1,
|
||||
* it won't overflow to 2^256, and the result is represented within
|
||||
* 256-bit.
|
||||
* It'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.
|
||||
*
|
||||
* It is guaranteed that modp256r1_reduce reduces to modulo p256r1.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -63,14 +64,14 @@ const bn256 p256r1 = { {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
void
|
||||
modp256r1_add (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t carry;
|
||||
uint32_t cond;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
carry = bn256_add (X, A, B);
|
||||
if (carry)
|
||||
bn256_sub (X, X, P256R1);
|
||||
else
|
||||
bn256_sub (tmp, X, P256R1);
|
||||
cond = (bn256_add (X, A, B) == 0);
|
||||
cond &= bn256_sub (tmp, X, P256R1);
|
||||
memcpy (cond?dummy:X, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,12 +82,12 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
{
|
||||
uint32_t borrow;
|
||||
bn256 tmp[1];
|
||||
bn256 dummy[1];
|
||||
|
||||
borrow = bn256_sub (X, A, B);
|
||||
if (borrow)
|
||||
bn256_add (X, X, P256R1);
|
||||
else
|
||||
bn256_add (tmp, X, P256R1);
|
||||
bn256_add (tmp, X, P256R1);
|
||||
memcpy (borrow?X:dummy, tmp, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +96,8 @@ modp256r1_sub (bn256 *X, const bn256 *A, const bn256 *B)
|
||||
void
|
||||
modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
{
|
||||
bn256 tmp[1];
|
||||
bn256 tmp[1], tmp0[1];
|
||||
bn256 dummy[1];
|
||||
uint32_t borrow;
|
||||
|
||||
#define S1 X
|
||||
@@ -116,6 +118,9 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S1->word[2] = A->word[2];
|
||||
S1->word[1] = A->word[1];
|
||||
S1->word[0] = A->word[0];
|
||||
borrow = bn256_sub (tmp0, S1, P256R1);
|
||||
memcpy (borrow?dummy:S1, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X = S1 */
|
||||
|
||||
S2->word[7] = A->word[15];
|
||||
@@ -155,6 +160,9 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S5->word[2] = A->word[11];
|
||||
S5->word[1] = A->word[10];
|
||||
S5->word[0] = A->word[9];
|
||||
borrow = bn256_sub (tmp0, S5, P256R1);
|
||||
memcpy (borrow?dummy:S5, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X += S5 */
|
||||
modp256r1_add (X, X, S5);
|
||||
|
||||
@@ -164,6 +172,9 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S6->word[2] = A->word[13];
|
||||
S6->word[1] = A->word[12];
|
||||
S6->word[0] = A->word[11];
|
||||
borrow = bn256_sub (tmp0, S6, P256R1);
|
||||
memcpy (borrow?dummy:S6, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X -= S6 */
|
||||
modp256r1_sub (X, X, S6);
|
||||
|
||||
@@ -174,6 +185,9 @@ modp256r1_reduce (bn256 *X, const bn512 *A)
|
||||
S7->word[2] = A->word[14];
|
||||
S7->word[1] = A->word[13];
|
||||
S7->word[0] = A->word[12];
|
||||
borrow = bn256_sub (tmp0, S7, P256R1);
|
||||
memcpy (borrow?dummy:S7, tmp0, sizeof (bn256));
|
||||
asm ("" : "=m" (dummy) : "m" (dummy) : "memory");
|
||||
/* X -= S7 */
|
||||
modp256r1_sub (X, X, S7);
|
||||
|
||||
|
||||
211
src/neug.c
211
src/neug.c
@@ -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, 2017, 2018
|
||||
* 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,136 @@
|
||||
|
||||
#include "sys.h"
|
||||
#include "neug.h"
|
||||
#include "stm32f103.h"
|
||||
#ifndef GNU_LINUX_EMULATION
|
||||
#include "mcu/stm32f103.h"
|
||||
#endif
|
||||
#include "adc.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
static const uint32_t crc32_rv_table[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
|
||||
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
|
||||
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
|
||||
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
|
||||
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
|
||||
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
|
||||
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
|
||||
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
|
||||
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
|
||||
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
|
||||
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
|
||||
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
|
||||
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
|
||||
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
|
||||
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
|
||||
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
|
||||
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
|
||||
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
|
||||
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
|
||||
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
|
||||
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
static uint32_t crc;
|
||||
|
||||
void
|
||||
crc32_rv_reset (void)
|
||||
{
|
||||
crc = 0xffffffff;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_step (uint32_t v)
|
||||
{
|
||||
crc = crc32_rv_table[(crc ^ (v << 0)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 8)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 16)) >> 24] ^ (crc << 8);
|
||||
crc = crc32_rv_table[(crc ^ (v << 24)) >> 24] ^ (crc << 8);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc32_rv_get (void)
|
||||
{
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rbit (uint32_t v)
|
||||
{
|
||||
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
|
||||
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
|
||||
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
|
||||
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
|
||||
v = ( v >> 16 ) | ( v << 16);
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_stop (void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
void
|
||||
crc32_rv_reset (void)
|
||||
{
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_step (uint32_t v)
|
||||
{
|
||||
CRC->DR = v;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
crc32_rv_get (void)
|
||||
{
|
||||
return CRC->DR;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rbit (uint32_t v)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
crc32_rv_stop (void)
|
||||
{
|
||||
RCC->AHBENR &= ~RCC_AHBENR_CRCEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
static chopstx_mutex_t mode_mtx;
|
||||
static chopstx_cond_t mode_cond;
|
||||
|
||||
/*
|
||||
* 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)];
|
||||
|
||||
@@ -99,11 +217,11 @@ static void noise_source_continuous_test_word (uint8_t b0, uint8_t b1,
|
||||
* Then, three-byte from noise source follows.
|
||||
*
|
||||
* One-byte was used in the previous turn, and we have three bytes in
|
||||
* CRC->DR.
|
||||
* CRC32.
|
||||
*/
|
||||
static void ep_fill_initial_string (void)
|
||||
{
|
||||
uint32_t v = CRC->DR;
|
||||
uint32_t v = crc32_rv_get ();
|
||||
uint8_t b1, b2, b3;
|
||||
|
||||
b3 = v >> 24;
|
||||
@@ -169,11 +287,11 @@ static int ep_process (int mode)
|
||||
sha256_ctx_data.wbuf[1] = adc_buf[1];
|
||||
for (i = 0; i < EP_ROUND_0_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
CRC->DR = adc_buf[i*4 + 4];
|
||||
CRC->DR = adc_buf[i*4 + 5];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
crc32_rv_step (adc_buf[i*4 + 4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 5]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i+2, 1, v);
|
||||
}
|
||||
|
||||
@@ -186,11 +304,11 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_1_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
@@ -203,23 +321,23 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_2_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR & 0xff; /* First byte of CRC->DR is used here. */
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get () & 0xff; /* First byte of CRC32 is used here. */
|
||||
noise_source_continuous_test (v);
|
||||
sha256_ctx_data.wbuf[i] = v;
|
||||
ep_init (NEUG_MODE_CONDITIONED); /* The rest three-byte of
|
||||
CRC->DR is used here. */
|
||||
CRC32 is used here. */
|
||||
n = SHA256_DIGEST_SIZE / 2;
|
||||
memcpy (((uint8_t *)sha256_ctx_data.wbuf) + EP_ROUND_2_INPUTS,
|
||||
sha256_output, n);
|
||||
@@ -231,11 +349,11 @@ static int ep_process (int mode)
|
||||
{
|
||||
for (i = 0; i < EP_ROUND_RAW_INPUTS / 4; i++)
|
||||
{
|
||||
CRC->DR = adc_buf[i*4];
|
||||
CRC->DR = adc_buf[i*4 + 1];
|
||||
CRC->DR = adc_buf[i*4 + 2];
|
||||
CRC->DR = adc_buf[i*4 + 3];
|
||||
v = CRC->DR;
|
||||
crc32_rv_step (adc_buf[i*4]);
|
||||
crc32_rv_step (adc_buf[i*4 + 1]);
|
||||
crc32_rv_step (adc_buf[i*4 + 2]);
|
||||
crc32_rv_step (adc_buf[i*4 + 3]);
|
||||
v = crc32_rv_get ();
|
||||
ep_fill_wbuf_v (i, 1, v);
|
||||
}
|
||||
|
||||
@@ -574,7 +692,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;
|
||||
@@ -583,7 +700,6 @@ rng (void *arg)
|
||||
|
||||
/* Enable ADCs */
|
||||
adc_start ();
|
||||
chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
|
||||
|
||||
ep_init (mode);
|
||||
while (!rng_should_terminate)
|
||||
@@ -591,7 +707,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)
|
||||
@@ -641,16 +757,17 @@ 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__;
|
||||
#define STACK_PROCESS_2
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_RNG ((uintptr_t)process2_base)
|
||||
#define STACK_SIZE_RNG (sizeof process2_base)
|
||||
|
||||
#define PRIO_RNG 2
|
||||
|
||||
/**
|
||||
@@ -663,20 +780,19 @@ neug_init (uint32_t *buf, uint8_t size)
|
||||
struct rng_rb *rb = &the_ring_buffer;
|
||||
int i;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
crc32_rv_reset ();
|
||||
|
||||
/*
|
||||
* This initialization ensures that it generates different sequence
|
||||
* even if all physical conditions are same.
|
||||
*/
|
||||
for (i = 0; i < 3; i++)
|
||||
CRC->DR = *u++;
|
||||
crc32_rv_step (*u++);
|
||||
|
||||
neug_mode = NEUG_MODE_CONDITIONED;
|
||||
rb_init (rb, buf, size);
|
||||
|
||||
rng_thread = chopstx_create (PRIO_RNG, __stackaddr_rng, __stacksize_rng,
|
||||
rng_thread = chopstx_create (PRIO_RNG, STACK_ADDR_RNG, STACK_SIZE_RNG,
|
||||
rng, rb);
|
||||
}
|
||||
|
||||
@@ -789,6 +905,7 @@ neug_fini (void)
|
||||
rng_should_terminate = 1;
|
||||
neug_get (1);
|
||||
chopstx_join (rng_thread, NULL);
|
||||
crc32_rv_stop ();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -26,3 +26,8 @@ void neug_fini (void);
|
||||
void neug_mode_select (uint8_t mode);
|
||||
|
||||
int neug_consume_random (void (*proc) (uint32_t, int));
|
||||
|
||||
void crc32_rv_reset (void);
|
||||
void crc32_rv_step (uint32_t v);
|
||||
uint32_t crc32_rv_get (void);
|
||||
uint32_t rbit (uint32_t v);
|
||||
|
||||
723
src/openpgp-do.c
723
src/openpgp-do.c
File diff suppressed because it is too large
Load Diff
459
src/openpgp.c
459
src/openpgp.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||||
* 2019
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -31,12 +32,13 @@
|
||||
|
||||
#include "gnuk.h"
|
||||
#include "sys.h"
|
||||
#include "openpgp.h"
|
||||
#include "status-code.h"
|
||||
#include "sha256.h"
|
||||
#include "random.h"
|
||||
|
||||
static struct eventflag *openpgp_comm;
|
||||
|
||||
#define USER_PASSWD_MINLEN 6
|
||||
#define ADMIN_PASSWD_MINLEN 8
|
||||
|
||||
#define CLS(a) a.cmd_apdu_head[0]
|
||||
@@ -48,6 +50,7 @@ static struct eventflag *openpgp_comm;
|
||||
#define INS_CHANGE_REFERENCE_DATA 0x24
|
||||
#define INS_PSO 0x2a
|
||||
#define INS_RESET_RETRY_COUNTER 0x2c
|
||||
#define INS_ACTIVATE_FILE 0x44
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_EXTERNAL_AUTHENTICATE 0x82
|
||||
#define INS_GET_CHALLENGE 0x84
|
||||
@@ -59,6 +62,7 @@ static struct eventflag *openpgp_comm;
|
||||
#define INS_UPDATE_BINARY 0xd6
|
||||
#define INS_PUT_DATA 0xda
|
||||
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
||||
#define INS_TERMINATE_DF 0xe6
|
||||
|
||||
static const uint8_t *challenge; /* Random bytes */
|
||||
|
||||
@@ -96,18 +100,25 @@ set_res_sw (uint8_t sw1, uint8_t sw2)
|
||||
#define FILE_EF_UPDATE_KEY_2 7
|
||||
#define FILE_EF_UPDATE_KEY_3 8
|
||||
#define FILE_EF_CH_CERTIFICATE 9
|
||||
#define FILE_CARD_TERMINATED 255
|
||||
|
||||
static uint8_t file_selection;
|
||||
uint8_t file_selection;
|
||||
|
||||
static void
|
||||
gpg_init (void)
|
||||
{
|
||||
const uint8_t *flash_data_start;
|
||||
const uint8_t *flash_do_start;
|
||||
const uint8_t *flash_do_end;
|
||||
|
||||
file_selection = FILE_NONE;
|
||||
flash_data_start = flash_init ();
|
||||
gpg_data_scan (flash_data_start);
|
||||
flash_init_keys ();
|
||||
flash_do_storage_init (&flash_do_start, &flash_do_end);
|
||||
|
||||
if (flash_do_start == NULL)
|
||||
file_selection = FILE_CARD_TERMINATED;
|
||||
else
|
||||
file_selection = FILE_NONE;
|
||||
|
||||
gpg_data_scan (flash_do_start, flash_do_end);
|
||||
flash_key_storage_init ();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -135,13 +146,15 @@ get_pinpad_input (int msg_code)
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_verify (void)
|
||||
cmd_verify (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len;
|
||||
uint8_t p1 = P1 (apdu);
|
||||
uint8_t p2 = P2 (apdu);
|
||||
int r;
|
||||
const uint8_t *pw;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
DEBUG_BYTE (p2);
|
||||
|
||||
@@ -149,22 +162,43 @@ cmd_verify (void)
|
||||
pw = apdu.cmd_apdu_data;
|
||||
|
||||
if (len == 0)
|
||||
{ /* This is to examine status. */
|
||||
if (p2 == 0x81)
|
||||
r = ac_check_status (AC_PSO_CDS_AUTHORIZED);
|
||||
else if (p2 == 0x82)
|
||||
r = ac_check_status (AC_OTHER_AUTHORIZED);
|
||||
else
|
||||
r = ac_check_status (AC_ADMIN_AUTHORIZED);
|
||||
{
|
||||
if (p1 == 0)
|
||||
{ /* This is to examine status. */
|
||||
if (p2 == 0x81)
|
||||
r = ac_check_status (AC_PSO_CDS_AUTHORIZED);
|
||||
else if (p2 == 0x82)
|
||||
r = ac_check_status (AC_OTHER_AUTHORIZED);
|
||||
else
|
||||
r = ac_check_status (AC_ADMIN_AUTHORIZED);
|
||||
|
||||
if (r)
|
||||
GPG_SUCCESS (); /* If authentication done already, return success. */
|
||||
else
|
||||
{ /* If not, return retry counter, encoded. */
|
||||
r = gpg_pw_get_retry_counter (p2);
|
||||
set_res_sw (0x63, 0xc0 | (r&0x0f));
|
||||
if (r)
|
||||
/* If authentication done already, return success. */
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
{ /* If not, return retry counter, encoded. */
|
||||
r = gpg_pw_get_retry_counter (p2);
|
||||
set_res_sw (0x63, 0xc0 | (r&0x0f));
|
||||
}
|
||||
}
|
||||
else if (p1 == 0xff)
|
||||
{ /* Reset the status. */
|
||||
if (p2 == 0x81)
|
||||
ac_reset_pso_cds ();
|
||||
else if (p2 == 0x82)
|
||||
ac_reset_other ();
|
||||
else
|
||||
ac_reset_admin ();
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else
|
||||
GPG_BAD_P1_P2 ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 1) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,7 +277,7 @@ gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_change_password (void)
|
||||
cmd_change_password (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
uint8_t new_ks0[KEYSTRING_SIZE];
|
||||
@@ -263,6 +297,7 @@ cmd_change_password (void)
|
||||
int salt_len;
|
||||
const uint8_t *ks_pw3;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
DEBUG_BYTE (who);
|
||||
|
||||
@@ -275,6 +310,12 @@ cmd_change_password (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 2) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (who == BY_USER) /* PW1 */
|
||||
{
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
@@ -311,8 +352,9 @@ cmd_change_password (void)
|
||||
newpw_len = len - pw_len;
|
||||
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
|
||||
/* Check length of password for admin-less mode. */
|
||||
if (ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
/* Check length of password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
@@ -327,8 +369,24 @@ cmd_change_password (void)
|
||||
|
||||
if (ks_pw3 == NULL)
|
||||
{
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
if (admin_authorized == BY_USER)
|
||||
{
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
if (ks_pw1 == NULL)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
salt = KS_GET_SALT (ks_pw1);
|
||||
salt_len = SALT_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
salt = NULL;
|
||||
salt_len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -352,13 +410,22 @@ cmd_change_password (void)
|
||||
{
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
|
||||
if (newpw_len == 0 && admin_authorized == BY_ADMIN)
|
||||
{
|
||||
newpw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
|
||||
memcpy (newpw, OPENPGP_CARD_INITIAL_PW3, newpw_len);
|
||||
const uint8_t *initial_pw;
|
||||
|
||||
gpg_do_get_initial_pw_setting (1, &newpw_len, &initial_pw);
|
||||
memcpy (newpw, initial_pw, newpw_len);
|
||||
newsalt_len = 0;
|
||||
pw3_null = 1;
|
||||
}
|
||||
else if (newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
who_old = admin_authorized;
|
||||
}
|
||||
@@ -388,11 +455,26 @@ cmd_change_password (void)
|
||||
}
|
||||
else if (r > 0 && who == BY_USER)
|
||||
{
|
||||
/* When it was already admin-less mode, admin_authorized is
|
||||
* BY_USER. If no PW3 keystring, it's becoming admin-less mode,
|
||||
* now. For these two cases, we need to reset admin
|
||||
* authorization status. */
|
||||
if (admin_authorized == BY_USER)
|
||||
ac_reset_admin ();
|
||||
else if (ks_pw3 == NULL)
|
||||
{
|
||||
enum kind_of_key kk0;
|
||||
|
||||
/* Remove keystrings for BY_ADMIN. */
|
||||
for (kk0 = 0; kk0 <= GPG_KEY_FOR_AUTHENTICATION; kk0++)
|
||||
gpg_do_chks_prvkey (kk0, BY_ADMIN, NULL, 0, NULL);
|
||||
|
||||
ac_reset_admin ();
|
||||
}
|
||||
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KS_META_SIZE);
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
if (admin_authorized == BY_USER)
|
||||
ac_reset_admin ();
|
||||
DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -437,9 +519,12 @@ s2k (const unsigned char *salt, size_t slen,
|
||||
{
|
||||
sha256_context ctx;
|
||||
size_t count = S2KCOUNT;
|
||||
const uint8_t *unique = unique_device_id ();
|
||||
|
||||
sha256_start (&ctx);
|
||||
|
||||
sha256_update (&ctx, unique, 12);
|
||||
|
||||
while (count > slen + ilen)
|
||||
{
|
||||
if (slen)
|
||||
@@ -465,7 +550,7 @@ s2k (const unsigned char *salt, size_t slen,
|
||||
|
||||
|
||||
static void
|
||||
cmd_reset_user_password (void)
|
||||
cmd_reset_user_password (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t p1 = P1 (apdu);
|
||||
int len;
|
||||
@@ -476,9 +561,11 @@ cmd_reset_user_password (void)
|
||||
uint8_t new_ks0[KEYSTRING_SIZE];
|
||||
uint8_t *new_ks = KS_GET_KEYSTRING (new_ks0);
|
||||
uint8_t *new_salt = KS_GET_SALT (new_ks0);
|
||||
const uint8_t *ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
const uint8_t *salt;
|
||||
int salt_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO ("Reset PW1\r\n");
|
||||
DEBUG_BYTE (p1);
|
||||
|
||||
@@ -490,6 +577,12 @@ cmd_reset_user_password (void)
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
|
||||
if (gpg_do_kdf_check (len, 2) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_pw_locked (PW_ERR_RC))
|
||||
{
|
||||
DEBUG_INFO ("blocked.\r\n");
|
||||
@@ -509,6 +602,16 @@ cmd_reset_user_password (void)
|
||||
salt_len = SALT_SIZE;
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
|
||||
/* Check length of new password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
random_get_salt (new_salt);
|
||||
s2k (salt, salt_len, pw, pw_len, old_ks);
|
||||
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
@@ -554,8 +657,24 @@ cmd_reset_user_password (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpg_do_kdf_check (len, 1) == 0)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
newpw_len = len;
|
||||
newpw = pw;
|
||||
|
||||
/* Check length of new password */
|
||||
if ((ks_pw3 == NULL && newpw_len < ADMIN_PASSWD_MINLEN)
|
||||
|| newpw_len < USER_PASSWD_MINLEN)
|
||||
{
|
||||
DEBUG_INFO ("new password length is too short.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
random_get_salt (new_salt);
|
||||
s2k (new_salt, SALT_SIZE, newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
@@ -590,17 +709,15 @@ cmd_reset_user_password (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_put_data (void)
|
||||
cmd_put_data (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint16_t tag;
|
||||
int len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - PUT DATA\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
GPG_NO_RECORD();
|
||||
|
||||
tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||
len = apdu.cmd_apdu_data_len;
|
||||
data = apdu.cmd_apdu_data;
|
||||
@@ -608,8 +725,9 @@ cmd_put_data (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_pgp_gakp (void)
|
||||
cmd_pgp_gakp (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
|
||||
@@ -620,19 +738,26 @@ cmd_pgp_gakp (void)
|
||||
{
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
GPG_SECURITY_FAILURE ();
|
||||
gpg_do_keygen (apdu.cmd_apdu_data[0]);
|
||||
#ifdef KDF_DO_REQUIRED
|
||||
else if (!gpg_do_kdf_check (0, 0))
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
#endif
|
||||
else
|
||||
gpg_do_keygen (&apdu.cmd_apdu_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
const uint8_t *
|
||||
gpg_get_firmware_update_key (uint8_t keyno)
|
||||
{
|
||||
extern uint8_t _updatekey_store;
|
||||
extern uint8_t _updatekey_store[1024];
|
||||
const uint8_t *p;
|
||||
|
||||
p = &_updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
p = _updatekey_store + keyno * FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CERTDO_SUPPORT
|
||||
#define FILEID_CH_CERTIFICATE_IS_VALID 1
|
||||
@@ -641,13 +766,13 @@ gpg_get_firmware_update_key (uint8_t keyno)
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_read_binary (void)
|
||||
cmd_read_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int is_short_EF = (P1 (apdu) & 0x80) != 0;
|
||||
uint8_t file_id;
|
||||
const uint8_t *p;
|
||||
uint16_t offset;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Read binary\r\n");
|
||||
|
||||
if (is_short_EF)
|
||||
@@ -655,13 +780,6 @@ cmd_read_binary (void)
|
||||
else
|
||||
file_id = file_selection - FILE_EF_SERIAL_NO + FILEID_SERIAL_NO;
|
||||
|
||||
if ((!FILEID_CH_CERTIFICATE_IS_VALID && file_id == FILEID_CH_CERTIFICATE)
|
||||
|| file_id > FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_short_EF)
|
||||
{
|
||||
file_selection = file_id - FILEID_SERIAL_NO + FILE_EF_SERIAL_NO;
|
||||
@@ -681,22 +799,26 @@ cmd_read_binary (void)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
else if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3)
|
||||
{
|
||||
if (offset != 0)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
else
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
p = gpg_get_firmware_update_key (file_id - FILEID_UPDATE_KEY_0);
|
||||
res_APDU_size = FIRMWARE_UPDATE_KEY_CONTENT_LEN;
|
||||
memcpy (res_APDU, p, FIRMWARE_UPDATE_KEY_CONTENT_LEN);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
else /* file_id == FILEID_CH_CERTIFICATE */
|
||||
else if (file_id == FILEID_CH_CERTIFICATE)
|
||||
{
|
||||
const uint8_t *p;
|
||||
uint16_t len = 256;
|
||||
|
||||
p = &ch_certificate_start;
|
||||
@@ -713,11 +835,17 @@ cmd_read_binary (void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_select_file (void)
|
||||
cmd_select_file (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
if (P1 (apdu) == 4) /* Selection by DF name */
|
||||
{
|
||||
DEBUG_INFO (" - select DF by name\r\n");
|
||||
@@ -733,19 +861,16 @@ cmd_select_file (void)
|
||||
return;
|
||||
}
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
if (file_selection == FILE_CARD_TERMINATED)
|
||||
{
|
||||
gpg_do_get_data (0x004f, 1); /* AID */
|
||||
memmove (res_APDU+2, res_APDU, res_APDU_size);
|
||||
res_APDU[0] = 0x6f;
|
||||
res_APDU[1] = 0x12;
|
||||
res_APDU[2] = 0x84; /* overwrite: DF name */
|
||||
res_APDU_size += 2;
|
||||
GPG_SUCCESS ();
|
||||
GPG_APPLICATION_TERMINATED ();
|
||||
return;
|
||||
}
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
|
||||
/* Behave just like original OpenPGP card. */
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else if (apdu.cmd_apdu_data_len == 2
|
||||
&& apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02)
|
||||
@@ -789,15 +914,13 @@ cmd_select_file (void)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_get_data (void)
|
||||
cmd_get_data (struct eventflag *ccid_comm)
|
||||
{
|
||||
uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - Get Data\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
GPG_NO_RECORD ();
|
||||
|
||||
gpg_do_get_data (tag, 0);
|
||||
}
|
||||
|
||||
@@ -810,13 +933,14 @@ cmd_get_data (void)
|
||||
#define ECC_CIPHER_DO_HEADER_SIZE 7
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
cmd_pso (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r = -1;
|
||||
int attr;
|
||||
int pubkey_len;
|
||||
unsigned int result_len = 0;
|
||||
int cs;
|
||||
|
||||
DEBUG_INFO (" - PSO: ");
|
||||
DEBUG_WORD ((uint32_t)&r);
|
||||
@@ -836,6 +960,11 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
/* Check size of digestInfo */
|
||||
@@ -867,6 +996,7 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
@@ -874,23 +1004,19 @@ cmd_pso (void)
|
||||
else /* ALGO_SECP256K1 */
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
chopstx_setcancelstate (cs);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
kd[GPG_KEY_FOR_SIGNING].data,
|
||||
kd[GPG_KEY_FOR_SIGNING].data+32,
|
||||
kd[GPG_KEY_FOR_SIGNING].pubkey);
|
||||
chopstx_setcancelstate (cs);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
else
|
||||
@@ -923,6 +1049,13 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#else
|
||||
(void)ccid_comm;
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
/* Skip padding 0x00 */
|
||||
@@ -947,6 +1080,7 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = 65;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header, res_APDU,
|
||||
@@ -954,6 +1088,7 @@ cmd_pso (void)
|
||||
else
|
||||
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
chopstx_setcancelstate (cs);
|
||||
}
|
||||
else if (attr == ALGO_CURVE25519)
|
||||
{
|
||||
@@ -965,9 +1100,11 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = 32;
|
||||
r = ecdh_decrypt_curve25519 (apdu.cmd_apdu_data + header, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
chopstx_setcancelstate (cs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -995,7 +1132,7 @@ cmd_pso (void)
|
||||
|
||||
#define MAX_RSA_DIGEST_INFO_LEN 102 /* 40% */
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
cmd_internal_authenticate (struct eventflag *ccid_comm)
|
||||
{
|
||||
int attr = gpg_get_algo_attr (GPG_KEY_FOR_AUTHENTICATION);
|
||||
int pubkey_len = gpg_get_algo_attr_key_size (GPG_KEY_FOR_AUTHENTICATION,
|
||||
@@ -1003,6 +1140,7 @@ cmd_internal_authenticate (void)
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r = -1;
|
||||
unsigned int result_len = 0;
|
||||
int cs;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
@@ -1024,6 +1162,13 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#else
|
||||
(void)ccid_comm;
|
||||
#endif
|
||||
|
||||
if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
|
||||
{
|
||||
if (len > MAX_RSA_DIGEST_INFO_LEN)
|
||||
@@ -1036,7 +1181,7 @@ cmd_internal_authenticate (void)
|
||||
result_len = pubkey_len;
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
|
||||
}
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1)
|
||||
{
|
||||
if (len != ECDSA_HASH_LEN)
|
||||
@@ -1046,9 +1191,11 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
chopstx_setcancelstate (cs);
|
||||
}
|
||||
else if (attr == ALGO_SECP256K1)
|
||||
{
|
||||
@@ -1059,26 +1206,23 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
chopstx_setcancelstate (cs);
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
uint32_t output[64/4]; /* Require 4-byte alignment. */
|
||||
|
||||
if (len > EDDSA_HASH_LEN_MAX)
|
||||
{
|
||||
DEBUG_INFO ("wrong hash length.");
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
cs = chopstx_setcancelstate (0);
|
||||
result_len = EDDSA_SIGNATURE_LENGTH;
|
||||
r = eddsa_sign_25519 (apdu.cmd_apdu_data, len, output,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data+32,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].pubkey);
|
||||
chopstx_setcancelstate (cs);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
|
||||
@@ -1166,6 +1310,7 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (file_id >= FILEID_UPDATE_KEY_0 && file_id <= FILEID_UPDATE_KEY_3
|
||||
&& len == 0 && offset == 0)
|
||||
{
|
||||
@@ -1182,9 +1327,10 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
if (i == 4) /* all update keys are removed */
|
||||
{
|
||||
p = gpg_get_firmware_update_key (0);
|
||||
flash_erase_page ((uint32_t)p);
|
||||
flash_erase_page ((uintptr_t)p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -1192,10 +1338,11 @@ modify_binary (uint8_t op, uint8_t p1, uint8_t p2, int len)
|
||||
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
static void
|
||||
cmd_update_binary (void)
|
||||
cmd_update_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||
modify_binary (MBD_OPRATION_UPDATE, P1 (apdu), P2 (apdu), len);
|
||||
DEBUG_INFO ("UPDATE BINARY done.\r\n");
|
||||
@@ -1204,18 +1351,20 @@ cmd_update_binary (void)
|
||||
|
||||
|
||||
static void
|
||||
cmd_write_binary (void)
|
||||
cmd_write_binary (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||
modify_binary (MBD_OPRATION_WRITE, P1 (apdu), P2 (apdu), len);
|
||||
DEBUG_INFO ("WRITE BINARY done.\r\n");
|
||||
}
|
||||
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
static void
|
||||
cmd_external_authenticate (void)
|
||||
cmd_external_authenticate (struct eventflag *ccid_comm)
|
||||
{
|
||||
const uint8_t *pubkey;
|
||||
const uint8_t *signature = apdu.cmd_apdu_data;
|
||||
@@ -1223,6 +1372,7 @@ cmd_external_authenticate (void)
|
||||
uint8_t keyno = P2 (apdu);
|
||||
int r;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - EXTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
if (keyno >= 4)
|
||||
@@ -1255,12 +1405,14 @@ cmd_external_authenticate (void)
|
||||
set_res_sw (0xff, 0xff);
|
||||
DEBUG_INFO ("EXTERNAL AUTHENTICATE done.\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cmd_get_challenge (void)
|
||||
cmd_get_challenge (struct eventflag *ccid_comm)
|
||||
{
|
||||
int len = apdu.expected_res_size;
|
||||
|
||||
(void)ccid_comm;
|
||||
DEBUG_INFO (" - GET CHALLENGE\r\n");
|
||||
|
||||
if (len > CHALLENGE_LEN)
|
||||
@@ -1275,6 +1427,13 @@ cmd_get_challenge (void)
|
||||
if (challenge)
|
||||
random_bytes_free (challenge);
|
||||
|
||||
#ifdef ACKBTN_SUPPORT
|
||||
if (gpg_do_get_uif (GPG_KEY_FOR_SIGNING)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_DECRYPTION)
|
||||
|| gpg_do_get_uif (GPG_KEY_FOR_AUTHENTICATION))
|
||||
eventflag_signal (ccid_comm, EV_EXEC_ACK_REQUIRED);
|
||||
#endif
|
||||
|
||||
challenge = random_bytes_get ();
|
||||
memcpy (res_APDU, challenge, len);
|
||||
res_APDU_size = len;
|
||||
@@ -1283,10 +1442,74 @@ cmd_get_challenge (void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
|
||||
static void
|
||||
cmd_activate_file (struct eventflag *ccid_comm)
|
||||
{
|
||||
(void)ccid_comm;
|
||||
if (file_selection != FILE_CARD_TERMINATED)
|
||||
{
|
||||
GPG_NO_RECORD ();
|
||||
return;
|
||||
}
|
||||
|
||||
flash_activate ();
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_terminate_df (struct eventflag *ccid_comm)
|
||||
{
|
||||
const uint8_t *ks_pw3;
|
||||
uint8_t p1 = P1 (apdu);
|
||||
uint8_t p2 = P2 (apdu);
|
||||
|
||||
(void)ccid_comm;
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
{
|
||||
GPG_NO_RECORD ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p1 != 0 || p2 != 0)
|
||||
{
|
||||
GPG_BAD_P1_P2();
|
||||
return;
|
||||
}
|
||||
|
||||
if (apdu.cmd_apdu_data_len != 0)
|
||||
{
|
||||
GPG_WRONG_LENGTH();
|
||||
return;
|
||||
}
|
||||
|
||||
ks_pw3 = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
|
||||
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED)
|
||||
&& !((ks_pw3 && gpg_pw_locked (PW_ERR_PW3))
|
||||
|| (ks_pw3 == NULL && gpg_pw_locked (PW_ERR_PW1))))
|
||||
{
|
||||
/* Only allow the case admin authorized, or, admin pass is locked. */
|
||||
GPG_SECURITY_FAILURE();
|
||||
return;
|
||||
}
|
||||
|
||||
ac_reset_admin ();
|
||||
ac_reset_pso_cds ();
|
||||
ac_reset_other ();
|
||||
gpg_do_terminate ();
|
||||
flash_terminate ();
|
||||
file_selection = FILE_CARD_TERMINATED;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct command
|
||||
{
|
||||
uint8_t command;
|
||||
void (*cmd_handler) (void);
|
||||
void (*cmd_handler) (struct eventflag *ccid_comm);
|
||||
};
|
||||
|
||||
const struct command cmds[] = {
|
||||
@@ -1294,13 +1517,18 @@ const struct command cmds[] = {
|
||||
{ INS_CHANGE_REFERENCE_DATA, cmd_change_password },
|
||||
{ INS_PSO, cmd_pso },
|
||||
{ INS_RESET_RETRY_COUNTER, cmd_reset_user_password },
|
||||
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
|
||||
{ INS_ACTIVATE_FILE, cmd_activate_file },
|
||||
#endif
|
||||
{ INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
{ INS_EXTERNAL_AUTHENTICATE, /* Not in OpenPGP card protocol */
|
||||
cmd_external_authenticate },
|
||||
#endif
|
||||
{ INS_GET_CHALLENGE, cmd_get_challenge }, /* Not in OpenPGP card protocol */
|
||||
{ INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
|
||||
{ INS_SELECT_FILE, cmd_select_file },
|
||||
{ INS_READ_BINARY, cmd_read_binary },
|
||||
{ INS_READ_BINARY, cmd_read_binary }, /* Not in OpenPGP card protocol */
|
||||
{ INS_GET_DATA, cmd_get_data },
|
||||
{ INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
@@ -1308,11 +1536,14 @@ const struct command cmds[] = {
|
||||
#endif
|
||||
{ INS_PUT_DATA, cmd_put_data },
|
||||
{ INS_PUT_DATA_ODD, cmd_put_data },
|
||||
#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
|
||||
{ INS_TERMINATE_DF, cmd_terminate_df},
|
||||
#endif
|
||||
};
|
||||
#define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
|
||||
|
||||
static void
|
||||
process_command_apdu (void)
|
||||
process_command_apdu (struct eventflag *ccid_comm)
|
||||
{
|
||||
int i;
|
||||
uint8_t cmd = INS (apdu);
|
||||
@@ -1322,7 +1553,24 @@ process_command_apdu (void)
|
||||
break;
|
||||
|
||||
if (i < NUM_CMDS)
|
||||
cmds[i].cmd_handler ();
|
||||
{
|
||||
if (file_selection == FILE_CARD_TERMINATED
|
||||
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
|
||||
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE)
|
||||
GPG_APPLICATION_TERMINATED ();
|
||||
else if (file_selection != FILE_DF_OPENPGP
|
||||
&& cmd != INS_SELECT_FILE && cmd != INS_ACTIVATE_FILE
|
||||
&& cmd != INS_GET_CHALLENGE && cmd != INS_EXTERNAL_AUTHENTICATE
|
||||
&& cmd != INS_WRITE_BINARY && cmd != INS_UPDATE_BINARY
|
||||
&& cmd != INS_READ_BINARY)
|
||||
GPG_NO_RECORD ();
|
||||
else
|
||||
{
|
||||
chopstx_setcancelstate (1);
|
||||
cmds[i].cmd_handler (ccid_comm);
|
||||
chopstx_setcancelstate (0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
@@ -1331,23 +1579,10 @@ process_command_apdu (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void * card_thread (chopstx_t thd, struct eventflag *ccid_comm);
|
||||
|
||||
void * __attribute__ ((naked))
|
||||
void *
|
||||
openpgp_card_thread (void *arg)
|
||||
{
|
||||
chopstx_t thd;
|
||||
|
||||
asm ("mov %0, sp" : "=r" (thd));
|
||||
return card_thread (thd, (struct eventflag *)arg);
|
||||
}
|
||||
|
||||
chopstx_t openpgp_card_thd;
|
||||
|
||||
static void * __attribute__ ((noinline))
|
||||
card_thread (chopstx_t thd, struct eventflag *ccid_comm)
|
||||
{
|
||||
openpgp_card_thd = thd;
|
||||
struct eventflag *ccid_comm = (struct eventflag *)arg;
|
||||
|
||||
openpgp_comm = ccid_comm + 1;
|
||||
|
||||
@@ -1355,10 +1590,10 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m = eventflag_wait (openpgp_comm);
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
int len, pw_len, newpw_len;
|
||||
#endif
|
||||
eventmask_t m = eventflag_wait (openpgp_comm);
|
||||
|
||||
DEBUG_INFO ("GPG!: ");
|
||||
|
||||
@@ -1387,7 +1622,7 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
|
||||
else if (m == EV_MODIFY_CMD_AVAILABLE)
|
||||
{
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
|
||||
uint8_t bConfirmPIN = apdu.cmd_apdu_data[0];
|
||||
uint8_t *p = apdu.cmd_apdu_data;
|
||||
|
||||
if (INS (apdu) != INS_CHANGE_REFERENCE_DATA
|
||||
@@ -1446,7 +1681,7 @@ card_thread (chopstx_t thd, struct eventflag *ccid_comm)
|
||||
break;
|
||||
|
||||
led_blink (LED_START_COMMAND);
|
||||
process_command_apdu ();
|
||||
process_command_apdu (ccid_comm);
|
||||
led_blink (LED_FINISH_COMMAND);
|
||||
done:
|
||||
eventflag_signal (ccid_comm, EV_EXEC_FINISHED);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "config.h"
|
||||
#include "board.h"
|
||||
#include "gnuk.h"
|
||||
#include "stm32f103.h"
|
||||
#include "mcu/stm32f103.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_CIR 1
|
||||
@@ -40,21 +40,20 @@ cir_ext_disable (void)
|
||||
int rcvd = (EXTI->PR & EXTI_PR) != 0;
|
||||
|
||||
EXTI->IMR &= ~EXTI_IMR;
|
||||
EXTI->PR = EXTI_PR;
|
||||
EXTI->PR |= EXTI_PR;
|
||||
return rcvd;
|
||||
}
|
||||
|
||||
static void
|
||||
cir_ext_enable (void)
|
||||
{
|
||||
EXTI->PR = EXTI_PR;
|
||||
EXTI->PR |= EXTI_PR;
|
||||
EXTI->IMR |= EXTI_IMR;
|
||||
}
|
||||
|
||||
|
||||
static chopstx_t pin_thread;
|
||||
static uint32_t wait_usec;
|
||||
static uint8_t notification;
|
||||
static chopstx_mutex_t cir_input_mtx;
|
||||
static chopstx_cond_t cir_input_cnd;
|
||||
static int input_avail;
|
||||
|
||||
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||
uint8_t pin_input_len;
|
||||
@@ -500,9 +499,18 @@ hex (int x)
|
||||
return (x - 10) + 'a';
|
||||
}
|
||||
|
||||
static int
|
||||
check_input (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
return input_avail;
|
||||
}
|
||||
|
||||
static int
|
||||
cir_getchar (uint32_t timeout)
|
||||
{
|
||||
chopstx_poll_cond_t poll_desc;
|
||||
struct chx_poll_head *pd_array[1] = { (struct chx_poll_head *)&poll_desc };
|
||||
uint16_t cir_addr;
|
||||
#if defined(DEBUG_CIR)
|
||||
uint16_t *p;
|
||||
@@ -514,10 +522,15 @@ cir_getchar (uint32_t timeout)
|
||||
|
||||
cir_ll_init ();
|
||||
|
||||
notification = 0;
|
||||
wait_usec = timeout;
|
||||
chopstx_usec_wait_var (&wait_usec);
|
||||
if (notification == 0)
|
||||
poll_desc.type = CHOPSTX_POLL_COND;
|
||||
poll_desc.ready = 0;
|
||||
poll_desc.cond = &cir_input_cnd;
|
||||
poll_desc.mutex = &cir_input_mtx;
|
||||
poll_desc.check = check_input;
|
||||
poll_desc.arg = NULL;
|
||||
|
||||
input_avail = 0;
|
||||
if (chopstx_poll (&timeout, 1, pd_array) == 0)
|
||||
return -1;
|
||||
|
||||
/* Sleep 200ms to avoid detecting chatter inputs. */
|
||||
@@ -631,13 +644,10 @@ cir_getchar (uint32_t timeout)
|
||||
int
|
||||
pinpad_getline (int msg_code, uint32_t timeout)
|
||||
{
|
||||
extern chopstx_t openpgp_card_thd;
|
||||
|
||||
(void)msg_code;
|
||||
|
||||
DEBUG_INFO (">>>\r\n");
|
||||
|
||||
pin_thread = openpgp_card_thd;
|
||||
pin_input_len = 0;
|
||||
while (1)
|
||||
{
|
||||
@@ -663,7 +673,6 @@ pinpad_getline (int msg_code, uint32_t timeout)
|
||||
}
|
||||
|
||||
cir_ext_disable ();
|
||||
pin_thread = NULL;
|
||||
|
||||
return pin_input_len;
|
||||
}
|
||||
@@ -932,13 +941,12 @@ cir_timer_interrupt (void)
|
||||
{
|
||||
/*
|
||||
* Notify the thread, when it's waiting the input.
|
||||
* If else, throw away the input.
|
||||
* If else, the input is thrown away.
|
||||
*/
|
||||
if (pin_thread)
|
||||
{
|
||||
notification = 1;
|
||||
chopstx_wakeup_usec_wait (pin_thread);
|
||||
}
|
||||
chopstx_mutex_lock (&cir_input_mtx);
|
||||
input_avail = 1;
|
||||
chopstx_cond_signal (&cir_input_cnd);
|
||||
chopstx_mutex_unlock (&cir_input_mtx);
|
||||
}
|
||||
|
||||
#if defined(DEBUG_CIR)
|
||||
@@ -956,9 +964,14 @@ cir_timer_interrupt (void)
|
||||
}
|
||||
|
||||
|
||||
extern uint8_t __process6_stack_base__, __process6_stack_size__;
|
||||
const uint32_t __stackaddr_tim = (uint32_t)&__process6_stack_base__;
|
||||
const size_t __stacksize_tim = (size_t)&__process6_stack_size__;
|
||||
#define STACK_PROCESS_6
|
||||
#define STACK_PROCESS_7
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_TIM ((uintptr_t)process6_base)
|
||||
#define STACK_SIZE_TIM (sizeof process6_base)
|
||||
#define STACK_ADDR_EXT ((uintptr_t)process7_base)
|
||||
#define STACK_SIZE_EXT (sizeof process7_base)
|
||||
|
||||
#define PRIO_TIM 4
|
||||
|
||||
static void *
|
||||
@@ -973,14 +986,13 @@ tim_main (void *arg)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
cir_timer_interrupt ();
|
||||
chopstx_intr_done (&interrupt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern uint8_t __process7_stack_base__, __process7_stack_size__;
|
||||
const uint32_t __stackaddr_ext = (uint32_t)&__process7_stack_base__;
|
||||
const size_t __stacksize_ext = (size_t)&__process7_stack_size__;
|
||||
|
||||
#define PRIO_EXT 4
|
||||
|
||||
static void *
|
||||
@@ -995,6 +1007,7 @@ ext_main (void *arg)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
cir_ext_interrupt ();
|
||||
chopstx_intr_done (&interrupt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -1004,6 +1017,9 @@ ext_main (void *arg)
|
||||
void
|
||||
cir_init (void)
|
||||
{
|
||||
chopstx_mutex_init (&cir_input_mtx);
|
||||
chopstx_cond_init (&cir_input_cnd);
|
||||
|
||||
/*
|
||||
* We use XOR function for three signals: TIMx_CH1, TIMx_CH2, and TIMx_CH3.
|
||||
*
|
||||
@@ -1019,8 +1035,8 @@ cir_init (void)
|
||||
|
||||
/* EXTIx <= Py */
|
||||
AFIO->EXTICR[AFIO_EXTICR_INDEX] = AFIO_EXTICR1_EXTIx_Py;
|
||||
EXTI->IMR = 0;
|
||||
EXTI->FTSR = EXTI_FTSR_TR;
|
||||
EXTI->IMR &= ~EXTI_IMR;
|
||||
EXTI->FTSR |= EXTI_FTSR_TR;
|
||||
|
||||
/* TIM */
|
||||
#ifdef ENABLE_RCC_APB1
|
||||
@@ -1044,8 +1060,8 @@ cir_init (void)
|
||||
TIMx->PSC = 72 - 1; /* 1 MHz */
|
||||
TIMx->ARR = 18000; /* 18 ms */
|
||||
/* Generate UEV to upload PSC and ARR */
|
||||
TIMx->EGR = TIM_EGR_UG;
|
||||
TIMx->EGR = TIM_EGR_UG;
|
||||
|
||||
chopstx_create (PRIO_TIM, __stackaddr_tim, __stacksize_tim, tim_main, NULL);
|
||||
chopstx_create (PRIO_EXT, __stackaddr_ext, __stacksize_ext, ext_main, NULL);
|
||||
chopstx_create (PRIO_TIM, STACK_ADDR_TIM, STACK_SIZE_TIM, tim_main, NULL);
|
||||
chopstx_create (PRIO_EXT, STACK_ADDR_EXT, STACK_SIZE_EXT, ext_main, NULL);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha256.h"
|
||||
|
||||
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* sha512.c -- Compute SHA-512 hash (for little endian architecture).
|
||||
*
|
||||
* This module is written by gniibe, following the API of sha256.c.
|
||||
* This module is written by gniibe, following the API of sha256.c.
|
||||
*
|
||||
* Copyright (C) 2014 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha512.h"
|
||||
|
||||
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
|
||||
|
||||
65
src/stack-def.h
Normal file
65
src/stack-def.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#define SIZE_1 4096
|
||||
#define SIZE_2 4096
|
||||
#define SIZE_3 (5 * 4096)
|
||||
#else
|
||||
#define SIZE_0 0x0160 /* Main */
|
||||
#define SIZE_1 0x01a0 /* CCID */
|
||||
#define SIZE_2 0x0180 /* RNG */
|
||||
#if MEMORY_SIZE >= 32
|
||||
#define SIZE_3 0x4640 /* openpgp-card */
|
||||
#elif MEMORY_SIZE >= 24
|
||||
#define SIZE_3 0x2640 /* openpgp-card */
|
||||
#else
|
||||
#define SIZE_3 0x1640 /* openpgp-card */
|
||||
#endif
|
||||
#define SIZE_4 0x0000 /* --- */
|
||||
#define SIZE_5 0x0200 /* msc */
|
||||
#define SIZE_6 0x00c0 /* timer (cir) */
|
||||
#define SIZE_7 0x00c0 /* ext (cir) */
|
||||
#endif
|
||||
|
||||
#if defined(STACK_MAIN) && !defined(GNU_LINUX_EMULATION)
|
||||
/* Idle+Exception handlers */
|
||||
char __main_stack_end__[0] __attribute__ ((section(".main_stack")));
|
||||
char main_base[0x0080] __attribute__ ((section(".main_stack")));
|
||||
|
||||
/* Main program */
|
||||
char __process0_stack_end__[0] __attribute__ ((section(".process_stack.0")));
|
||||
char process0_base[SIZE_0] __attribute__ ((section(".process_stack.0")));
|
||||
#endif
|
||||
|
||||
/* First thread program */
|
||||
#if defined(STACK_PROCESS_1)
|
||||
char process1_base[SIZE_1] __attribute__ ((section(".process_stack.1")));
|
||||
#endif
|
||||
|
||||
/* Second thread program */
|
||||
#if defined(STACK_PROCESS_2)
|
||||
char process2_base[SIZE_2] __attribute__ ((section(".process_stack.2")));
|
||||
#endif
|
||||
|
||||
/* Third thread program */
|
||||
#if defined(STACK_PROCESS_3)
|
||||
char process3_base[SIZE_3] __attribute__ ((section(".process_stack.3")));
|
||||
#endif
|
||||
|
||||
/* Fourth thread program */
|
||||
#if defined(STACK_PROCESS_4)
|
||||
char process4_base[SIZE_4] __attribute__ ((section(".process_stack.4")));
|
||||
#endif
|
||||
|
||||
/* Fifth thread program */
|
||||
#if defined(STACK_PROCESS_5)
|
||||
char process5_base[SIZE_5] __attribute__ ((section(".process_stack.5")));
|
||||
#endif
|
||||
|
||||
/* Sixth thread program */
|
||||
#if defined(STACK_PROCESS_6)
|
||||
char process6_base[SIZE_6] __attribute__ ((section(".process_stack.6")));
|
||||
#endif
|
||||
|
||||
/* Seventh thread program */
|
||||
#if defined(STACK_PROCESS_7)
|
||||
char process7_base[SIZE_7] __attribute__ ((section(".process_stack.7")));
|
||||
#endif
|
||||
@@ -1,4 +1,6 @@
|
||||
#define GPG_APPLICATION_TERMINATED() set_res_sw (0x62, 0x85)
|
||||
#define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
|
||||
#define GPG_WRONG_LENGTH() set_res_sw (0x67, 0x00)
|
||||
#define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82)
|
||||
#define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83)
|
||||
#define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85)
|
||||
39
src/stdaln-sys.ld.in
Normal file
39
src/stdaln-sys.ld.in
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* ST32F103 memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = @ORIGIN_REAL@, len = 4k
|
||||
ram : org = 0x20000000, len = @MEMORY_SIZE@k
|
||||
}
|
||||
|
||||
__ram_start__ = ORIGIN(ram);
|
||||
__ram_size__ = LENGTH(ram);
|
||||
__ram_end__ = __ram_start__ + __ram_size__;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.sys : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
_sys = .;
|
||||
KEEP(*(.vectors))
|
||||
. = ALIGN(16);
|
||||
KEEP(*(.sys.version))
|
||||
KEEP(*(.sys.board_id))
|
||||
KEEP(*(.sys.board_name))
|
||||
build/sys-*.o(.text)
|
||||
build/sys-*.o(.text.*)
|
||||
build/sys-*.o(.rodata)
|
||||
build/sys-*.o(.rodata.*)
|
||||
. = ALIGN(1024);
|
||||
} > flash0
|
||||
|
||||
.aesft : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
*(.sys.0)
|
||||
*(.sys.1)
|
||||
*(.sys.2)
|
||||
} > flash0
|
||||
}
|
||||
13
src/stdlib.h
13
src/stdlib.h
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* stdlib.h replacement to replace malloc functions
|
||||
*/
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
|
||||
#define malloc(size) gnuk_malloc (size)
|
||||
#define free(p) gnuk_free (p)
|
||||
|
||||
void *gnuk_malloc (size_t);
|
||||
void gnuk_free (void *);
|
||||
700
src/stm32f103.h
700
src/stm32f103.h
@@ -1,700 +0,0 @@
|
||||
#define PERIPH_BASE 0x40000000
|
||||
#define APB1PERIPH_BASE PERIPH_BASE
|
||||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||||
|
||||
struct RCC {
|
||||
volatile uint32_t CR;
|
||||
volatile uint32_t CFGR;
|
||||
volatile uint32_t CIR;
|
||||
volatile uint32_t APB2RSTR;
|
||||
volatile uint32_t APB1RSTR;
|
||||
volatile uint32_t AHBENR;
|
||||
volatile uint32_t APB2ENR;
|
||||
volatile uint32_t APB1ENR;
|
||||
volatile uint32_t BDCR;
|
||||
volatile uint32_t CSR;
|
||||
};
|
||||
|
||||
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
|
||||
static struct RCC *const RCC = ((struct RCC *const)RCC_BASE);
|
||||
|
||||
#define RCC_AHBENR_DMA1EN 0x00000001
|
||||
#define RCC_AHBENR_CRCEN 0x00000040
|
||||
|
||||
#define RCC_APB2ENR_ADC1EN 0x00000200
|
||||
#define RCC_APB2ENR_ADC2EN 0x00000400
|
||||
#define RCC_APB2ENR_TIM1EN 0x00000800
|
||||
#define RCC_APB1ENR_TIM2EN 0x00000001
|
||||
#define RCC_APB1ENR_TIM3EN 0x00000002
|
||||
#define RCC_APB1ENR_TIM4EN 0x00000004
|
||||
|
||||
#define RCC_APB2RSTR_ADC1RST 0x00000200
|
||||
#define RCC_APB2RSTR_ADC2RST 0x00000400
|
||||
#define RCC_APB2RSTR_TIM1RST 0x00000800
|
||||
#define RCC_APB1RSTR_TIM2RST 0x00000001
|
||||
#define RCC_APB1RSTR_TIM3RST 0x00000002
|
||||
#define RCC_APB1RSTR_TIM4RST 0x00000004
|
||||
|
||||
#define CRC_CR_RESET 0x00000001
|
||||
|
||||
struct CRC {
|
||||
volatile uint32_t DR;
|
||||
volatile uint8_t IDR;
|
||||
uint8_t RESERVED0;
|
||||
uint16_t RESERVED1;
|
||||
volatile uint32_t CR;
|
||||
};
|
||||
|
||||
#define CRC_BASE (AHBPERIPH_BASE + 0x3000)
|
||||
static struct CRC *const CRC = ((struct CRC *const)CRC_BASE);
|
||||
|
||||
|
||||
struct ADC {
|
||||
volatile uint32_t SR;
|
||||
volatile uint32_t CR1;
|
||||
volatile uint32_t CR2;
|
||||
volatile uint32_t SMPR1;
|
||||
volatile uint32_t SMPR2;
|
||||
volatile uint32_t JOFR1;
|
||||
volatile uint32_t JOFR2;
|
||||
volatile uint32_t JOFR3;
|
||||
volatile uint32_t JOFR4;
|
||||
volatile uint32_t HTR;
|
||||
volatile uint32_t LTR;
|
||||
volatile uint32_t SQR1;
|
||||
volatile uint32_t SQR2;
|
||||
volatile uint32_t SQR3;
|
||||
volatile uint32_t JSQR;
|
||||
volatile uint32_t JDR1;
|
||||
volatile uint32_t JDR2;
|
||||
volatile uint32_t JDR3;
|
||||
volatile uint32_t JDR4;
|
||||
volatile uint32_t DR;
|
||||
};
|
||||
|
||||
#define ADC1_BASE (APB2PERIPH_BASE + 0x2400)
|
||||
#define ADC2_BASE (APB2PERIPH_BASE + 0x2800)
|
||||
|
||||
static struct ADC *const ADC1 = (struct ADC *const)ADC1_BASE;
|
||||
static struct ADC *const ADC2 = (struct ADC *const)ADC2_BASE;
|
||||
|
||||
#define ADC_CR1_DUALMOD_0 0x00010000
|
||||
#define ADC_CR1_DUALMOD_1 0x00020000
|
||||
#define ADC_CR1_DUALMOD_2 0x00040000
|
||||
#define ADC_CR1_DUALMOD_3 0x00080000
|
||||
|
||||
#define ADC_CR1_SCAN 0x00000100
|
||||
|
||||
#define ADC_CR2_ADON 0x00000001
|
||||
#define ADC_CR2_CONT 0x00000002
|
||||
#define ADC_CR2_CAL 0x00000004
|
||||
#define ADC_CR2_RSTCAL 0x00000008
|
||||
#define ADC_CR2_DMA 0x00000100
|
||||
#define ADC_CR2_ALIGN 0x00000800
|
||||
#define ADC_CR2_EXTSEL 0x000E0000
|
||||
#define ADC_CR2_EXTSEL_0 0x00020000
|
||||
#define ADC_CR2_EXTSEL_1 0x00040000
|
||||
#define ADC_CR2_EXTSEL_2 0x00080000
|
||||
#define ADC_CR2_EXTTRIG 0x00100000
|
||||
#define ADC_CR2_SWSTART 0x00400000
|
||||
#define ADC_CR2_TSVREFE 0x00800000
|
||||
|
||||
struct DMA_Channel {
|
||||
volatile uint32_t CCR;
|
||||
volatile uint32_t CNDTR;
|
||||
volatile uint32_t CPAR;
|
||||
volatile uint32_t CMAR;
|
||||
};
|
||||
|
||||
struct DMA {
|
||||
volatile uint32_t ISR;
|
||||
volatile uint32_t IFCR;
|
||||
};
|
||||
|
||||
#define STM32_DMA_CR_MINC DMA_CCR1_MINC
|
||||
#define STM32_DMA_CR_MSIZE_WORD DMA_CCR1_MSIZE_1
|
||||
#define STM32_DMA_CR_PSIZE_WORD DMA_CCR1_PSIZE_1
|
||||
#define STM32_DMA_CR_TCIE DMA_CCR1_TCIE
|
||||
#define STM32_DMA_CR_TEIE DMA_CCR1_TEIE
|
||||
#define STM32_DMA_CR_HTIE DMA_CCR1_HTIE
|
||||
#define STM32_DMA_ISR_TEIF DMA_ISR_TEIF1
|
||||
#define STM32_DMA_ISR_HTIF DMA_ISR_HTIF1
|
||||
#define STM32_DMA_ISR_TCIF DMA_ISR_TCIF1
|
||||
|
||||
#define STM32_DMA_ISR_MASK 0x0F
|
||||
#define STM32_DMA_CCR_RESET_VALUE 0x00000000
|
||||
#define STM32_DMA_CR_PL_MASK DMA_CCR1_PL
|
||||
#define STM32_DMA_CR_PL(n) ((n) << 12)
|
||||
|
||||
#define DMA_CCR1_EN 0x00000001
|
||||
#define DMA_CCR1_TCIE 0x00000002
|
||||
#define DMA_CCR1_HTIE 0x00000004
|
||||
#define DMA_CCR1_TEIE 0x00000008
|
||||
#define DMA_CCR1_DIR 0x00000010
|
||||
#define DMA_CCR1_CIRC 0x00000020
|
||||
#define DMA_CCR1_PINC 0x00000040
|
||||
#define DMA_CCR1_MINC 0x00000080
|
||||
#define DMA_CCR1_PSIZE 0x00000300
|
||||
#define DMA_CCR1_PSIZE_0 0x00000100
|
||||
#define DMA_CCR1_PSIZE_1 0x00000200
|
||||
#define DMA_CCR1_MSIZE 0x00000C00
|
||||
#define DMA_CCR1_MSIZE_0 0x00000400
|
||||
#define DMA_CCR1_MSIZE_1 0x00000800
|
||||
#define DMA_CCR1_PL 0x00003000
|
||||
#define DMA_CCR1_PL_0 0x00001000
|
||||
#define DMA_CCR1_PL_1 0x00002000
|
||||
#define DMA_CCR1_MEM2MEM 0x00004000
|
||||
|
||||
#define DMA_ISR_GIF1 0x00000001
|
||||
#define DMA_ISR_TCIF1 0x00000002
|
||||
#define DMA_ISR_HTIF1 0x00000004
|
||||
#define DMA_ISR_TEIF1 0x00000008
|
||||
#define DMA_ISR_GIF2 0x00000010
|
||||
#define DMA_ISR_TCIF2 0x00000020
|
||||
#define DMA_ISR_HTIF2 0x00000040
|
||||
#define DMA_ISR_TEIF2 0x00000080
|
||||
#define DMA_ISR_GIF3 0x00000100
|
||||
#define DMA_ISR_TCIF3 0x00000200
|
||||
#define DMA_ISR_HTIF3 0x00000400
|
||||
#define DMA_ISR_TEIF3 0x00000800
|
||||
#define DMA_ISR_GIF4 0x00001000
|
||||
#define DMA_ISR_TCIF4 0x00002000
|
||||
#define DMA_ISR_HTIF4 0x00004000
|
||||
#define DMA_ISR_TEIF4 0x00008000
|
||||
#define DMA_ISR_GIF5 0x00010000
|
||||
#define DMA_ISR_TCIF5 0x00020000
|
||||
#define DMA_ISR_HTIF5 0x00040000
|
||||
#define DMA_ISR_TEIF5 0x00080000
|
||||
#define DMA_ISR_GIF6 0x00100000
|
||||
#define DMA_ISR_TCIF6 0x00200000
|
||||
#define DMA_ISR_HTIF6 0x00400000
|
||||
#define DMA_ISR_TEIF6 0x00800000
|
||||
#define DMA_ISR_GIF7 0x01000000
|
||||
#define DMA_ISR_TCIF7 0x02000000
|
||||
#define DMA_ISR_HTIF7 0x04000000
|
||||
#define DMA_ISR_TEIF7 0x08000000
|
||||
|
||||
#define DMA1_BASE (AHBPERIPH_BASE + 0x0000)
|
||||
static struct DMA *const DMA1 = (struct DMA *const)DMA1_BASE;
|
||||
|
||||
#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008)
|
||||
static struct DMA_Channel *const DMA1_Channel1 =
|
||||
(struct DMA_Channel *const)DMA1_Channel1_BASE;
|
||||
|
||||
/* System Control Block */
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
uint32_t RESERVED0[5];
|
||||
volatile uint32_t CPACR;
|
||||
};
|
||||
|
||||
#define SCS_BASE 0xE000E000
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = (struct SCB *const)SCB_BASE;
|
||||
|
||||
/* Timer */
|
||||
struct TIM
|
||||
{
|
||||
volatile uint16_t CR1; uint16_t RESERVED0;
|
||||
volatile uint16_t CR2; uint16_t RESERVED1;
|
||||
volatile uint16_t SMCR; uint16_t RESERVED2;
|
||||
volatile uint16_t DIER; uint16_t RESERVED3;
|
||||
volatile uint16_t SR; uint16_t RESERVED4;
|
||||
volatile uint16_t EGR; uint16_t RESERVED5;
|
||||
volatile uint16_t CCMR1; uint16_t RESERVED6;
|
||||
volatile uint16_t CCMR2; uint16_t RESERVED7;
|
||||
volatile uint16_t CCER; uint16_t RESERVED8;
|
||||
volatile uint16_t CNT; uint16_t RESERVED9;
|
||||
volatile uint16_t PSC; uint16_t RESERVED10;
|
||||
volatile uint16_t ARR; uint16_t RESERVED11;
|
||||
volatile uint16_t RCR; uint16_t RESERVED12;
|
||||
volatile uint16_t CCR1; uint16_t RESERVED13;
|
||||
volatile uint16_t CCR2; uint16_t RESERVED14;
|
||||
volatile uint16_t CCR3; uint16_t RESERVED15;
|
||||
volatile uint16_t CCR4; uint16_t RESERVED16;
|
||||
volatile uint16_t BDTR; uint16_t RESERVED17;
|
||||
volatile uint16_t DCR; uint16_t RESERVED18;
|
||||
volatile uint16_t DMAR; uint16_t RESERVED19;
|
||||
};
|
||||
|
||||
#define TIM2_BASE 0x40000000
|
||||
#define TIM3_BASE 0x40000400
|
||||
#define TIM4_BASE 0x40000800
|
||||
static struct TIM *const TIM2 = (struct TIM *const)TIM2_BASE;
|
||||
static struct TIM *const TIM3 = (struct TIM *const)TIM3_BASE;
|
||||
static struct TIM *const TIM4 = (struct TIM *const)TIM4_BASE;
|
||||
|
||||
#define TIM_CR1_CEN 0x0001
|
||||
#define TIM_CR1_UDIS 0x0002
|
||||
#define TIM_CR1_URS 0x0004
|
||||
#define TIM_CR1_OPM 0x0008
|
||||
#define TIM_CR1_DIR 0x0010
|
||||
#define TIM_CR1_CMS 0x0060
|
||||
#define TIM_CR1_CMS_0 0x0020
|
||||
#define TIM_CR1_CMS_1 0x0040
|
||||
#define TIM_CR1_ARPE 0x0080
|
||||
#define TIM_CR1_CKD 0x0300
|
||||
#define TIM_CR1_CKD_0 0x0100
|
||||
#define TIM_CR1_CKD_1 0x0200
|
||||
|
||||
#define TIM_CR2_CCPC 0x0001
|
||||
#define TIM_CR2_CCUS 0x0004
|
||||
#define TIM_CR2_CCDS 0x0008
|
||||
#define TIM_CR2_MMS 0x0070
|
||||
#define TIM_CR2_MMS_0 0x0010
|
||||
#define TIM_CR2_MMS_1 0x0020
|
||||
#define TIM_CR2_MMS_2 0x0040
|
||||
#define TIM_CR2_TI1S 0x0080
|
||||
#define TIM_CR2_OIS1 0x0100
|
||||
#define TIM_CR2_OIS1N 0x0200
|
||||
#define TIM_CR2_OIS2 0x0400
|
||||
#define TIM_CR2_OIS2N 0x0800
|
||||
#define TIM_CR2_OIS3 0x1000
|
||||
#define TIM_CR2_OIS3N 0x2000
|
||||
#define TIM_CR2_OIS4 0x4000
|
||||
|
||||
#define TIM_SMCR_SMS 0x0007
|
||||
#define TIM_SMCR_SMS_0 0x0001
|
||||
#define TIM_SMCR_SMS_1 0x0002
|
||||
#define TIM_SMCR_SMS_2 0x0004
|
||||
#define TIM_SMCR_TS 0x0070
|
||||
#define TIM_SMCR_TS_0 0x0010
|
||||
#define TIM_SMCR_TS_1 0x0020
|
||||
#define TIM_SMCR_TS_2 0x0040
|
||||
#define TIM_SMCR_MSM 0x0080
|
||||
|
||||
#define TIM_SMCR_ETF 0x0F00
|
||||
#define TIM_SMCR_ETF_0 0x0100
|
||||
#define TIM_SMCR_ETF_1 0x0200
|
||||
#define TIM_SMCR_ETF_2 0x0400
|
||||
#define TIM_SMCR_ETF_3 0x0800
|
||||
|
||||
#define TIM_SMCR_ETPS 0x3000
|
||||
#define TIM_SMCR_ETPS_0 0x1000
|
||||
#define TIM_SMCR_ETPS_1 0x2000
|
||||
|
||||
#define TIM_SMCR_ECE 0x4000
|
||||
#define TIM_SMCR_ETP 0x8000
|
||||
|
||||
#define TIM_DIER_UIE 0x0001
|
||||
#define TIM_DIER_CC1IE 0x0002
|
||||
#define TIM_DIER_CC2IE 0x0004
|
||||
#define TIM_DIER_CC3IE 0x0008
|
||||
#define TIM_DIER_CC4IE 0x0010
|
||||
#define TIM_DIER_COMIE 0x0020
|
||||
#define TIM_DIER_TIE 0x0040
|
||||
#define TIM_DIER_BIE 0x0080
|
||||
#define TIM_DIER_UDE 0x0100
|
||||
#define TIM_DIER_CC1DE 0x0200
|
||||
#define TIM_DIER_CC2DE 0x0400
|
||||
#define TIM_DIER_CC3DE 0x0800
|
||||
#define TIM_DIER_CC4DE 0x1000
|
||||
#define TIM_DIER_COMDE 0x2000
|
||||
#define TIM_DIER_TDE 0x4000
|
||||
|
||||
#define TIM_SR_UIF 0x0001
|
||||
#define TIM_SR_CC1IF 0x0002
|
||||
#define TIM_SR_CC2IF 0x0004
|
||||
#define TIM_SR_CC3IF 0x0008
|
||||
#define TIM_SR_CC4IF 0x0010
|
||||
#define TIM_SR_COMIF 0x0020
|
||||
#define TIM_SR_TIF 0x0040
|
||||
#define TIM_SR_BIF 0x0080
|
||||
#define TIM_SR_CC1OF 0x0200
|
||||
#define TIM_SR_CC2OF 0x0400
|
||||
#define TIM_SR_CC3OF 0x0800
|
||||
#define TIM_SR_CC4OF 0x1000
|
||||
|
||||
#define TIM_EGR_UG 0x01
|
||||
#define TIM_EGR_CC1G 0x02
|
||||
#define TIM_EGR_CC2G 0x04
|
||||
#define TIM_EGR_CC3G 0x08
|
||||
#define TIM_EGR_CC4G 0x10
|
||||
#define TIM_EGR_COMG 0x20
|
||||
#define TIM_EGR_TG 0x40
|
||||
#define TIM_EGR_BG 0x80
|
||||
|
||||
#define TIM_CCMR1_CC1S 0x0003
|
||||
#define TIM_CCMR1_CC1S_0 0x0001
|
||||
#define TIM_CCMR1_CC1S_1 0x0002
|
||||
|
||||
#define TIM_CCMR1_OC1FE 0x0004
|
||||
#define TIM_CCMR1_OC1PE 0x0008
|
||||
|
||||
#define TIM_CCMR1_OC1M 0x0070
|
||||
#define TIM_CCMR1_OC1M_0 0x0010
|
||||
#define TIM_CCMR1_OC1M_1 0x0020
|
||||
#define TIM_CCMR1_OC1M_2 0x0040
|
||||
|
||||
#define TIM_CCMR1_OC1CE 0x0080
|
||||
|
||||
#define TIM_CCMR1_CC2S 0x0300
|
||||
#define TIM_CCMR1_CC2S_0 0x0100
|
||||
#define TIM_CCMR1_CC2S_1 0x0200
|
||||
|
||||
#define TIM_CCMR1_OC2FE 0x0400
|
||||
#define TIM_CCMR1_OC2PE 0x0800
|
||||
|
||||
#define TIM_CCMR1_OC2M 0x7000
|
||||
#define TIM_CCMR1_OC2M_0 0x1000
|
||||
#define TIM_CCMR1_OC2M_1 0x2000
|
||||
#define TIM_CCMR1_OC2M_2 0x4000
|
||||
|
||||
#define TIM_CCMR1_OC2CE 0x8000
|
||||
|
||||
|
||||
#define TIM_CCMR1_IC1PSC 0x000C
|
||||
#define TIM_CCMR1_IC1PSC_0 0x0004
|
||||
#define TIM_CCMR1_IC1PSC_1 0x0008
|
||||
|
||||
#define TIM_CCMR1_IC1F 0x00F0
|
||||
#define TIM_CCMR1_IC1F_0 0x0010
|
||||
#define TIM_CCMR1_IC1F_1 0x0020
|
||||
#define TIM_CCMR1_IC1F_2 0x0040
|
||||
#define TIM_CCMR1_IC1F_3 0x0080
|
||||
|
||||
#define TIM_CCMR1_IC2PSC 0x0C00
|
||||
#define TIM_CCMR1_IC2PSC_0 0x0400
|
||||
#define TIM_CCMR1_IC2PSC_1 0x0800
|
||||
|
||||
#define TIM_CCMR1_IC2F 0xF000
|
||||
#define TIM_CCMR1_IC2F_0 0x1000
|
||||
#define TIM_CCMR1_IC2F_1 0x2000
|
||||
#define TIM_CCMR1_IC2F_2 0x4000
|
||||
#define TIM_CCMR1_IC2F_3 0x8000
|
||||
|
||||
#define TIM_CCMR2_CC3S 0x0003
|
||||
#define TIM_CCMR2_CC3S_0 0x0001
|
||||
#define TIM_CCMR2_CC3S_1 0x0002
|
||||
|
||||
#define TIM_CCMR2_OC3FE 0x0004
|
||||
#define TIM_CCMR2_OC3PE 0x0008
|
||||
|
||||
#define TIM_CCMR2_OC3M 0x0070
|
||||
#define TIM_CCMR2_OC3M_0 0x0010
|
||||
#define TIM_CCMR2_OC3M_1 0x0020
|
||||
#define TIM_CCMR2_OC3M_2 0x0040
|
||||
|
||||
#define TIM_CCMR2_OC3CE 0x0080
|
||||
|
||||
#define TIM_CCMR2_CC4S 0x0300
|
||||
#define TIM_CCMR2_CC4S_0 0x0100
|
||||
#define TIM_CCMR2_CC4S_1 0x0200
|
||||
|
||||
#define TIM_CCMR2_OC4FE 0x0400
|
||||
#define TIM_CCMR2_OC4PE 0x0800
|
||||
|
||||
#define TIM_CCMR2_OC4M 0x7000
|
||||
#define TIM_CCMR2_OC4M_0 0x1000
|
||||
#define TIM_CCMR2_OC4M_1 0x2000
|
||||
#define TIM_CCMR2_OC4M_2 0x4000
|
||||
|
||||
#define TIM_CCMR2_OC4CE 0x8000
|
||||
|
||||
|
||||
#define TIM_CCMR2_IC3PSC 0x000C
|
||||
#define TIM_CCMR2_IC3PSC_0 0x0004
|
||||
#define TIM_CCMR2_IC3PSC_1 0x0008
|
||||
|
||||
#define TIM_CCMR2_IC3F 0x00F0
|
||||
#define TIM_CCMR2_IC3F_0 0x0010
|
||||
#define TIM_CCMR2_IC3F_1 0x0020
|
||||
#define TIM_CCMR2_IC3F_2 0x0040
|
||||
#define TIM_CCMR2_IC3F_3 0x0080
|
||||
|
||||
#define TIM_CCMR2_IC4PSC 0x0C00
|
||||
#define TIM_CCMR2_IC4PSC_0 0x0400
|
||||
#define TIM_CCMR2_IC4PSC_1 0x0800
|
||||
|
||||
#define TIM_CCMR2_IC4F 0xF000
|
||||
#define TIM_CCMR2_IC4F_0 0x1000
|
||||
#define TIM_CCMR2_IC4F_1 0x2000
|
||||
#define TIM_CCMR2_IC4F_2 0x4000
|
||||
#define TIM_CCMR2_IC4F_3 0x8000
|
||||
|
||||
#define TIM_CCER_CC1E 0x0001
|
||||
#define TIM_CCER_CC1P 0x0002
|
||||
#define TIM_CCER_CC1NE 0x0004
|
||||
#define TIM_CCER_CC1NP 0x0008
|
||||
#define TIM_CCER_CC2E 0x0010
|
||||
#define TIM_CCER_CC2P 0x0020
|
||||
#define TIM_CCER_CC2NE 0x0040
|
||||
#define TIM_CCER_CC2NP 0x0080
|
||||
#define TIM_CCER_CC3E 0x0100
|
||||
#define TIM_CCER_CC3P 0x0200
|
||||
#define TIM_CCER_CC3NE 0x0400
|
||||
#define TIM_CCER_CC3NP 0x0800
|
||||
#define TIM_CCER_CC4E 0x1000
|
||||
#define TIM_CCER_CC4P 0x2000
|
||||
|
||||
#define TIM_CNT_CNT 0xFFFF
|
||||
|
||||
#define TIM_PSC_PSC 0xFFFF
|
||||
|
||||
#define TIM_ARR_ARR 0xFFFF
|
||||
|
||||
#define TIM_RCR_REP 0xFF
|
||||
|
||||
#define TIM_CCR1_CCR1 0xFFFF
|
||||
#define TIM_CCR2_CCR2 0xFFFF
|
||||
#define TIM_CCR3_CCR3 0xFFFF
|
||||
#define TIM_CCR4_CCR4 0xFFFF
|
||||
|
||||
#define TIM_BDTR_DTG 0x00FF
|
||||
#define TIM_BDTR_DTG_0 0x0001
|
||||
#define TIM_BDTR_DTG_1 0x0002
|
||||
#define TIM_BDTR_DTG_2 0x0004
|
||||
#define TIM_BDTR_DTG_3 0x0008
|
||||
#define TIM_BDTR_DTG_4 0x0010
|
||||
#define TIM_BDTR_DTG_5 0x0020
|
||||
#define TIM_BDTR_DTG_6 0x0040
|
||||
#define TIM_BDTR_DTG_7 0x0080
|
||||
|
||||
#define TIM_BDTR_LOCK 0x0300
|
||||
#define TIM_BDTR_LOCK_0 0x0100
|
||||
#define TIM_BDTR_LOCK_1 0x0200
|
||||
|
||||
#define TIM_BDTR_OSSI 0x0400
|
||||
#define TIM_BDTR_OSSR 0x0800
|
||||
#define TIM_BDTR_BKE 0x1000
|
||||
#define TIM_BDTR_BKP 0x2000
|
||||
#define TIM_BDTR_AOE 0x4000
|
||||
#define TIM_BDTR_MOE 0x8000
|
||||
|
||||
#define TIM_DCR_DBA 0x001F
|
||||
#define TIM_DCR_DBA_0 0x0001
|
||||
#define TIM_DCR_DBA_1 0x0002
|
||||
#define TIM_DCR_DBA_2 0x0004
|
||||
#define TIM_DCR_DBA_3 0x0008
|
||||
#define TIM_DCR_DBA_4 0x0010
|
||||
|
||||
#define TIM_DCR_DBL 0x1F00
|
||||
#define TIM_DCR_DBL_0 0x0100
|
||||
#define TIM_DCR_DBL_1 0x0200
|
||||
#define TIM_DCR_DBL_2 0x0400
|
||||
#define TIM_DCR_DBL_3 0x0800
|
||||
#define TIM_DCR_DBL_4 0x1000
|
||||
|
||||
#define TIM_DMAR_DMAB 0xFFFF
|
||||
|
||||
struct EXTI
|
||||
{
|
||||
volatile uint32_t IMR;
|
||||
volatile uint32_t EMR;
|
||||
volatile uint32_t RTSR;
|
||||
volatile uint32_t FTSR;
|
||||
volatile uint32_t SWIER;
|
||||
volatile uint32_t PR;
|
||||
};
|
||||
|
||||
#define EXTI_BASE 0x40010400
|
||||
static struct EXTI *const EXTI = (struct EXTI *const)EXTI_BASE;
|
||||
|
||||
#define EXTI_IMR_MR0 0x00000001
|
||||
#define EXTI_IMR_MR1 0x00000002
|
||||
#define EXTI_IMR_MR2 0x00000004
|
||||
#define EXTI_IMR_MR3 0x00000008
|
||||
#define EXTI_IMR_MR4 0x00000010
|
||||
#define EXTI_IMR_MR5 0x00000020
|
||||
#define EXTI_IMR_MR6 0x00000040
|
||||
#define EXTI_IMR_MR7 0x00000080
|
||||
#define EXTI_IMR_MR8 0x00000100
|
||||
#define EXTI_IMR_MR9 0x00000200
|
||||
#define EXTI_IMR_MR10 0x00000400
|
||||
#define EXTI_IMR_MR11 0x00000800
|
||||
#define EXTI_IMR_MR12 0x00001000
|
||||
#define EXTI_IMR_MR13 0x00002000
|
||||
#define EXTI_IMR_MR14 0x00004000
|
||||
#define EXTI_IMR_MR15 0x00008000
|
||||
#define EXTI_IMR_MR16 0x00010000
|
||||
#define EXTI_IMR_MR17 0x00020000
|
||||
#define EXTI_IMR_MR18 0x00040000
|
||||
#define EXTI_IMR_MR19 0x00080000
|
||||
|
||||
#define EXTI_EMR_MR0 0x00000001
|
||||
#define EXTI_EMR_MR1 0x00000002
|
||||
#define EXTI_EMR_MR2 0x00000004
|
||||
#define EXTI_EMR_MR3 0x00000008
|
||||
#define EXTI_EMR_MR4 0x00000010
|
||||
#define EXTI_EMR_MR5 0x00000020
|
||||
#define EXTI_EMR_MR6 0x00000040
|
||||
#define EXTI_EMR_MR7 0x00000080
|
||||
#define EXTI_EMR_MR8 0x00000100
|
||||
#define EXTI_EMR_MR9 0x00000200
|
||||
#define EXTI_EMR_MR10 0x00000400
|
||||
#define EXTI_EMR_MR11 0x00000800
|
||||
#define EXTI_EMR_MR12 0x00001000
|
||||
#define EXTI_EMR_MR13 0x00002000
|
||||
#define EXTI_EMR_MR14 0x00004000
|
||||
#define EXTI_EMR_MR15 0x00008000
|
||||
#define EXTI_EMR_MR16 0x00010000
|
||||
#define EXTI_EMR_MR17 0x00020000
|
||||
#define EXTI_EMR_MR18 0x00040000
|
||||
#define EXTI_EMR_MR19 0x00080000
|
||||
|
||||
#define EXTI_RTSR_TR0 0x00000001
|
||||
#define EXTI_RTSR_TR1 0x00000002
|
||||
#define EXTI_RTSR_TR2 0x00000004
|
||||
#define EXTI_RTSR_TR3 0x00000008
|
||||
#define EXTI_RTSR_TR4 0x00000010
|
||||
#define EXTI_RTSR_TR5 0x00000020
|
||||
#define EXTI_RTSR_TR6 0x00000040
|
||||
#define EXTI_RTSR_TR7 0x00000080
|
||||
#define EXTI_RTSR_TR8 0x00000100
|
||||
#define EXTI_RTSR_TR9 0x00000200
|
||||
#define EXTI_RTSR_TR10 0x00000400
|
||||
#define EXTI_RTSR_TR11 0x00000800
|
||||
#define EXTI_RTSR_TR12 0x00001000
|
||||
#define EXTI_RTSR_TR13 0x00002000
|
||||
#define EXTI_RTSR_TR14 0x00004000
|
||||
#define EXTI_RTSR_TR15 0x00008000
|
||||
#define EXTI_RTSR_TR16 0x00010000
|
||||
#define EXTI_RTSR_TR17 0x00020000
|
||||
#define EXTI_RTSR_TR18 0x00040000
|
||||
#define EXTI_RTSR_TR19 0x00080000
|
||||
|
||||
#define EXTI_FTSR_TR0 0x00000001
|
||||
#define EXTI_FTSR_TR1 0x00000002
|
||||
#define EXTI_FTSR_TR2 0x00000004
|
||||
#define EXTI_FTSR_TR3 0x00000008
|
||||
#define EXTI_FTSR_TR4 0x00000010
|
||||
#define EXTI_FTSR_TR5 0x00000020
|
||||
#define EXTI_FTSR_TR6 0x00000040
|
||||
#define EXTI_FTSR_TR7 0x00000080
|
||||
#define EXTI_FTSR_TR8 0x00000100
|
||||
#define EXTI_FTSR_TR9 0x00000200
|
||||
#define EXTI_FTSR_TR10 0x00000400
|
||||
#define EXTI_FTSR_TR11 0x00000800
|
||||
#define EXTI_FTSR_TR12 0x00001000
|
||||
#define EXTI_FTSR_TR13 0x00002000
|
||||
#define EXTI_FTSR_TR14 0x00004000
|
||||
#define EXTI_FTSR_TR15 0x00008000
|
||||
#define EXTI_FTSR_TR16 0x00010000
|
||||
#define EXTI_FTSR_TR17 0x00020000
|
||||
#define EXTI_FTSR_TR18 0x00040000
|
||||
#define EXTI_FTSR_TR19 0x00080000
|
||||
|
||||
#define EXTI_SWIER_SWIER0 0x00000001
|
||||
#define EXTI_SWIER_SWIER1 0x00000002
|
||||
#define EXTI_SWIER_SWIER2 0x00000004
|
||||
#define EXTI_SWIER_SWIER3 0x00000008
|
||||
#define EXTI_SWIER_SWIER4 0x00000010
|
||||
#define EXTI_SWIER_SWIER5 0x00000020
|
||||
#define EXTI_SWIER_SWIER6 0x00000040
|
||||
#define EXTI_SWIER_SWIER7 0x00000080
|
||||
#define EXTI_SWIER_SWIER8 0x00000100
|
||||
#define EXTI_SWIER_SWIER9 0x00000200
|
||||
#define EXTI_SWIER_SWIER10 0x00000400
|
||||
#define EXTI_SWIER_SWIER11 0x00000800
|
||||
#define EXTI_SWIER_SWIER12 0x00001000
|
||||
#define EXTI_SWIER_SWIER13 0x00002000
|
||||
#define EXTI_SWIER_SWIER14 0x00004000
|
||||
#define EXTI_SWIER_SWIER15 0x00008000
|
||||
#define EXTI_SWIER_SWIER16 0x00010000
|
||||
#define EXTI_SWIER_SWIER17 0x00020000
|
||||
#define EXTI_SWIER_SWIER18 0x00040000
|
||||
#define EXTI_SWIER_SWIER19 0x00080000
|
||||
|
||||
#define EXTI_PR_PR0 0x00000001
|
||||
#define EXTI_PR_PR1 0x00000002
|
||||
#define EXTI_PR_PR2 0x00000004
|
||||
#define EXTI_PR_PR3 0x00000008
|
||||
#define EXTI_PR_PR4 0x00000010
|
||||
#define EXTI_PR_PR5 0x00000020
|
||||
#define EXTI_PR_PR6 0x00000040
|
||||
#define EXTI_PR_PR7 0x00000080
|
||||
#define EXTI_PR_PR8 0x00000100
|
||||
#define EXTI_PR_PR9 0x00000200
|
||||
#define EXTI_PR_PR10 0x00000400
|
||||
#define EXTI_PR_PR11 0x00000800
|
||||
#define EXTI_PR_PR12 0x00001000
|
||||
#define EXTI_PR_PR13 0x00002000
|
||||
#define EXTI_PR_PR14 0x00004000
|
||||
#define EXTI_PR_PR15 0x00008000
|
||||
#define EXTI_PR_PR16 0x00010000
|
||||
#define EXTI_PR_PR17 0x00020000
|
||||
#define EXTI_PR_PR18 0x00040000
|
||||
#define EXTI_PR_PR19 0x00080000
|
||||
|
||||
#define EXTI0_IRQ 6
|
||||
#define EXTI1_IRQ 7
|
||||
#define EXTI2_IRQ 8
|
||||
#define EXTI9_5_IRQ 23
|
||||
#define TIM2_IRQ 28
|
||||
#define TIM3_IRQ 29
|
||||
#define TIM4_IRQ 30
|
||||
|
||||
struct AFIO
|
||||
{
|
||||
volatile uint32_t EVCR;
|
||||
volatile uint32_t MAPR;
|
||||
volatile uint32_t EXTICR[4];
|
||||
uint32_t RESERVED0;
|
||||
volatile uint32_t MAPR2;
|
||||
};
|
||||
|
||||
#define AFIO_BASE 0x40010000
|
||||
static struct AFIO *const AFIO = (struct AFIO *const)AFIO_BASE;
|
||||
|
||||
#define AFIO_EXTICR1_EXTI0_PA 0x0000
|
||||
#define AFIO_EXTICR1_EXTI0_PB 0x0001
|
||||
#define AFIO_EXTICR1_EXTI0_PC 0x0002
|
||||
#define AFIO_EXTICR1_EXTI0_PD 0x0003
|
||||
|
||||
#define AFIO_EXTICR1_EXTI1_PA 0x0000
|
||||
#define AFIO_EXTICR1_EXTI1_PB 0x0010
|
||||
#define AFIO_EXTICR1_EXTI1_PC 0x0020
|
||||
#define AFIO_EXTICR1_EXTI1_PD 0x0030
|
||||
|
||||
#define AFIO_EXTICR1_EXTI2_PA 0x0000
|
||||
#define AFIO_EXTICR1_EXTI2_PB 0x0100
|
||||
#define AFIO_EXTICR1_EXTI2_PC 0x0200
|
||||
#define AFIO_EXTICR1_EXTI2_PD 0x0300
|
||||
|
||||
#define AFIO_EXTICR1_EXTI3_PA 0x0000
|
||||
#define AFIO_EXTICR1_EXTI3_PB 0x1000
|
||||
#define AFIO_EXTICR1_EXTI3_PC 0x2000
|
||||
#define AFIO_EXTICR1_EXTI3_PD 0x3000
|
||||
|
||||
#define AFIO_EXTICR2_EXTI4_PA 0x0000
|
||||
#define AFIO_EXTICR2_EXTI4_PB 0x0001
|
||||
#define AFIO_EXTICR2_EXTI4_PC 0x0002
|
||||
#define AFIO_EXTICR2_EXTI4_PD 0x0003
|
||||
|
||||
#define AFIO_EXTICR2_EXTI5_PA 0x0000
|
||||
#define AFIO_EXTICR2_EXTI5_PB 0x0010
|
||||
#define AFIO_EXTICR2_EXTI5_PC 0x0020
|
||||
#define AFIO_EXTICR2_EXTI5_PD 0x0030
|
||||
|
||||
#define AFIO_EXTICR2_EXTI6_PA 0x0000
|
||||
#define AFIO_EXTICR2_EXTI6_PB 0x0100
|
||||
#define AFIO_EXTICR2_EXTI6_PC 0x0200
|
||||
#define AFIO_EXTICR2_EXTI6_PD 0x0300
|
||||
|
||||
#define AFIO_EXTICR2_EXTI7_PA 0x0000
|
||||
#define AFIO_EXTICR2_EXTI7_PB 0x1000
|
||||
#define AFIO_EXTICR2_EXTI7_PC 0x2000
|
||||
#define AFIO_EXTICR2_EXTI7_PD 0x3000
|
||||
|
||||
#define AFIO_MAPR_TIM3_REMAP_PARTIALREMAP 0x00000800
|
||||
#define AFIO_MAPR_SWJ_CFG_DISABLE 0x04000000
|
||||
434
src/sys.c
434
src/sys.c
@@ -1,434 +0,0 @@
|
||||
/*
|
||||
* sys.c - system routines for the initial page for STM32F103.
|
||||
*
|
||||
* Copyright (C) 2013, 2014, 2015 Flying Stone Technology
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* Copying and distribution of this file, with or without modification,
|
||||
* are permitted in any medium without royalty provided the copyright
|
||||
* notice and this notice are preserved. This file is offered as-is,
|
||||
* without any warranty.
|
||||
*
|
||||
* When the flash ROM is protected, we cannot modify the initial page.
|
||||
* We put some system routines (which is useful for any program) here.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "board.h"
|
||||
|
||||
#include "clk_gpio_init.c"
|
||||
|
||||
#define CORTEX_PRIORITY_BITS 4
|
||||
#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS))
|
||||
#define USB_LP_CAN1_RX0_IRQn 20
|
||||
#define STM32_USB_IRQ_PRIORITY 11
|
||||
|
||||
struct NVIC {
|
||||
uint32_t ISER[8];
|
||||
uint32_t unused1[24];
|
||||
uint32_t ICER[8];
|
||||
uint32_t unused2[24];
|
||||
uint32_t ISPR[8];
|
||||
uint32_t unused3[24];
|
||||
uint32_t ICPR[8];
|
||||
uint32_t unused4[24];
|
||||
uint32_t IABR[8];
|
||||
uint32_t unused5[56];
|
||||
uint32_t IPR[60];
|
||||
};
|
||||
|
||||
static struct NVIC *const NVICBase = ((struct NVIC *const)0xE000E100);
|
||||
#define NVIC_ISER(n) (NVICBase->ISER[n >> 5])
|
||||
#define NVIC_ICPR(n) (NVICBase->ICPR[n >> 5])
|
||||
#define NVIC_IPR(n) (NVICBase->IPR[n >> 2])
|
||||
|
||||
static void
|
||||
nvic_enable_vector (uint32_t n, uint32_t prio)
|
||||
{
|
||||
unsigned int sh = (n & 3) << 3;
|
||||
|
||||
NVIC_IPR (n) = (NVIC_IPR(n) & ~(0xFF << sh)) | (prio << sh);
|
||||
NVIC_ICPR (n) = 1 << (n & 0x1F);
|
||||
NVIC_ISER (n) = 1 << (n & 0x1F);
|
||||
}
|
||||
|
||||
static void
|
||||
usb_cable_config (int enable)
|
||||
{
|
||||
#if defined(GPIO_USB_SET_TO_ENABLE)
|
||||
if (enable)
|
||||
GPIO_USB->BSRR = (1 << GPIO_USB_SET_TO_ENABLE);
|
||||
else
|
||||
GPIO_USB->BRR = (1 << GPIO_USB_SET_TO_ENABLE);
|
||||
#elif defined(GPIO_USB_CLEAR_TO_ENABLE)
|
||||
if (enable)
|
||||
GPIO_USB->BRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
|
||||
else
|
||||
GPIO_USB->BSRR = (1 << GPIO_USB_CLEAR_TO_ENABLE);
|
||||
#else
|
||||
(void)enable;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
set_led (int on)
|
||||
{
|
||||
#if defined(GPIO_LED_CLEAR_TO_EMIT)
|
||||
if (on)
|
||||
GPIO_LED->BRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
|
||||
else
|
||||
GPIO_LED->BSRR = (1 << GPIO_LED_CLEAR_TO_EMIT);
|
||||
#else
|
||||
if (on)
|
||||
GPIO_LED->BSRR = (1 << GPIO_LED_SET_TO_EMIT);
|
||||
else
|
||||
GPIO_LED->BRR = (1 << GPIO_LED_SET_TO_EMIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void wait (int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
asm volatile ("" : : "r" (i) : "memory");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usb_lld_sys_shutdown (void)
|
||||
{
|
||||
RCC->APB1ENR &= ~RCC_APB1ENR_USBEN;
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
||||
usb_cable_config (0);
|
||||
}
|
||||
|
||||
static void
|
||||
usb_lld_sys_init (void)
|
||||
{
|
||||
if ((RCC->APB1ENR & RCC_APB1ENR_USBEN)
|
||||
&& (RCC->APB1RSTR & RCC_APB1RSTR_USBRST) == 0)
|
||||
/* Make sure the device is disconnected, even after core reset. */
|
||||
{
|
||||
usb_lld_sys_shutdown ();
|
||||
/* Disconnect requires SE0 (>= 2.5uS). */
|
||||
wait (300);
|
||||
}
|
||||
|
||||
usb_cable_config (1);
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
|
||||
nvic_enable_vector (USB_LP_CAN1_RX0_IRQn,
|
||||
CORTEX_PRIORITY_MASK (STM32_USB_IRQ_PRIORITY));
|
||||
/*
|
||||
* Note that we also have other IRQ(s):
|
||||
* USB_HP_CAN1_TX_IRQn (for double-buffered or isochronous)
|
||||
* USBWakeUp_IRQn (suspend/resume)
|
||||
*/
|
||||
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
|
||||
RCC->APB1RSTR = 0;
|
||||
}
|
||||
|
||||
#define FLASH_KEY1 0x45670123UL
|
||||
#define FLASH_KEY2 0xCDEF89ABUL
|
||||
|
||||
enum flash_status
|
||||
{
|
||||
FLASH_BUSY = 1,
|
||||
FLASH_ERROR_PG,
|
||||
FLASH_ERROR_WRP,
|
||||
FLASH_COMPLETE,
|
||||
FLASH_TIMEOUT
|
||||
};
|
||||
|
||||
static void __attribute__ ((used))
|
||||
flash_unlock (void)
|
||||
{
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
|
||||
|
||||
#define intr_disable() asm volatile ("cpsid i" : : : "memory")
|
||||
#define intr_enable() asm volatile ("cpsie i" : : : "memory")
|
||||
|
||||
#define FLASH_SR_BSY 0x01
|
||||
#define FLASH_SR_PGERR 0x04
|
||||
#define FLASH_SR_WRPRTERR 0x10
|
||||
#define FLASH_SR_EOP 0x20
|
||||
|
||||
#define FLASH_CR_PG 0x0001
|
||||
#define FLASH_CR_PER 0x0002
|
||||
#define FLASH_CR_MER 0x0004
|
||||
#define FLASH_CR_OPTPG 0x0010
|
||||
#define FLASH_CR_OPTER 0x0020
|
||||
#define FLASH_CR_STRT 0x0040
|
||||
#define FLASH_CR_LOCK 0x0080
|
||||
#define FLASH_CR_OPTWRE 0x0200
|
||||
#define FLASH_CR_ERRIE 0x0400
|
||||
#define FLASH_CR_EOPIE 0x1000
|
||||
|
||||
static int
|
||||
flash_wait_for_last_operation (uint32_t timeout)
|
||||
{
|
||||
int status;
|
||||
|
||||
do
|
||||
{
|
||||
status = FLASH->SR;
|
||||
if (--timeout == 0)
|
||||
break;
|
||||
}
|
||||
while ((status & FLASH_SR_BSY) != 0);
|
||||
|
||||
return status & (FLASH_SR_BSY|FLASH_SR_PGERR|FLASH_SR_WRPRTERR);
|
||||
}
|
||||
|
||||
#define FLASH_PROGRAM_TIMEOUT 0x00010000
|
||||
#define FLASH_ERASE_TIMEOUT 0x01000000
|
||||
|
||||
static int
|
||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
||||
|
||||
intr_disable ();
|
||||
if (status == 0)
|
||||
{
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
*(volatile uint16_t *)addr = data;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
intr_enable ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
flash_erase_page (uint32_t addr)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
||||
|
||||
intr_disable ();
|
||||
if (status == 0)
|
||||
{
|
||||
FLASH->CR |= FLASH_CR_PER;
|
||||
FLASH->AR = addr;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
||||
FLASH->CR &= ~FLASH_CR_PER;
|
||||
}
|
||||
intr_enable ();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
flash_check_blank (const uint8_t *p_start, size_t size)
|
||||
{
|
||||
const uint8_t *p;
|
||||
|
||||
for (p = p_start; p < p_start + size; p++)
|
||||
if (*p != 0xff)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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 CHIP_ID_REG ((uint32_t *)0xe0042000)
|
||||
#define FLASH_SIZE_REG ((uint16_t *)0x1ffff7e0)
|
||||
|
||||
static int
|
||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int status;
|
||||
uint32_t flash_end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
|
||||
if (dst_addr < FLASH_START || dst_addr + len > flash_end)
|
||||
return 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
uint16_t hw = *src++;
|
||||
|
||||
hw |= (*src++ << 8);
|
||||
status = flash_program_halfword (dst_addr, hw);
|
||||
if (status != 0)
|
||||
return 0; /* error return */
|
||||
|
||||
dst_addr += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define OPTION_BYTES_ADDR 0x1ffff800
|
||||
|
||||
static int
|
||||
flash_protect (void)
|
||||
{
|
||||
int status;
|
||||
uint32_t option_bytes_value;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
||||
|
||||
intr_disable ();
|
||||
if (status == 0)
|
||||
{
|
||||
FLASH->OPTKEYR = FLASH_KEY1;
|
||||
FLASH->OPTKEYR = FLASH_KEY2;
|
||||
|
||||
FLASH->CR |= FLASH_CR_OPTER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
status = flash_wait_for_last_operation (FLASH_ERASE_TIMEOUT);
|
||||
FLASH->CR &= ~FLASH_CR_OPTER;
|
||||
}
|
||||
intr_enable ();
|
||||
|
||||
if (status != 0)
|
||||
return 0;
|
||||
|
||||
option_bytes_value = *(uint32_t *)OPTION_BYTES_ADDR;
|
||||
return (option_bytes_value & 0xff) == 0xff ? 1 : 0;
|
||||
}
|
||||
|
||||
static void __attribute__((naked))
|
||||
flash_erase_all_and_exec (void (*entry)(void))
|
||||
{
|
||||
uint32_t addr = FLASH_START;
|
||||
uint32_t end = FLASH_START_ADDR + (*FLASH_SIZE_REG)*1024;
|
||||
uint32_t page_size = 1024;
|
||||
int r;
|
||||
|
||||
if (((*CHIP_ID_REG) & 0xfff) == 0x0414)
|
||||
page_size = 2048;
|
||||
|
||||
while (addr < end)
|
||||
{
|
||||
r = flash_erase_page (addr);
|
||||
if (r != 0)
|
||||
break;
|
||||
|
||||
addr += page_size;
|
||||
}
|
||||
|
||||
if (addr >= end)
|
||||
(*entry) ();
|
||||
|
||||
for (;;);
|
||||
}
|
||||
|
||||
struct SCB
|
||||
{
|
||||
volatile uint32_t CPUID;
|
||||
volatile uint32_t ICSR;
|
||||
volatile uint32_t VTOR;
|
||||
volatile uint32_t AIRCR;
|
||||
volatile uint32_t SCR;
|
||||
volatile uint32_t CCR;
|
||||
volatile uint8_t SHP[12];
|
||||
volatile uint32_t SHCSR;
|
||||
volatile uint32_t CFSR;
|
||||
volatile uint32_t HFSR;
|
||||
volatile uint32_t DFSR;
|
||||
volatile uint32_t MMFAR;
|
||||
volatile uint32_t BFAR;
|
||||
volatile uint32_t AFSR;
|
||||
volatile uint32_t PFR[2];
|
||||
volatile uint32_t DFR;
|
||||
volatile uint32_t ADR;
|
||||
volatile uint32_t MMFR[4];
|
||||
volatile uint32_t ISAR[5];
|
||||
};
|
||||
|
||||
#define SCS_BASE (0xE000E000)
|
||||
#define SCB_BASE (SCS_BASE + 0x0D00)
|
||||
static struct SCB *const SCB = ((struct SCB *const) SCB_BASE);
|
||||
|
||||
#define SYSRESETREQ 0x04
|
||||
static void
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
SCB->AIRCR = (0x05FA0000 | (SCB->AIRCR & 0x70) | SYSRESETREQ);
|
||||
asm volatile ("dsb");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
static void __attribute__ ((naked))
|
||||
reset (void)
|
||||
{
|
||||
extern const unsigned long *FT0, *FT1, *FT2;
|
||||
|
||||
/*
|
||||
* This code may not be at the start of flash ROM, because of DFU.
|
||||
* So, we take the address from PC.
|
||||
*/
|
||||
asm volatile ("cpsid i\n\t" /* Mask all interrupts. */
|
||||
"ldr r0, 1f\n\t" /* r0 = SCR */
|
||||
"mov r1, pc\n\t" /* r1 = (PC + 0x1000) & ~0x0fff */
|
||||
"mov r2, #0x1000\n\t"
|
||||
"add r1, r1, r2\n\t"
|
||||
"sub r2, r2, #1\n\t"
|
||||
"bic r1, r1, r2\n\t"
|
||||
"str r1, [r0, #8]\n\t" /* Set SCR->VCR */
|
||||
"ldr r0, [r1], #4\n\t"
|
||||
"msr MSP, r0\n\t" /* Main (exception handler) stack. */
|
||||
"ldr r0, [r1]\n\t" /* Reset handler. */
|
||||
"bx r0\n\t"
|
||||
".align 2\n"
|
||||
"1: .word 0xe000ed00"
|
||||
: /* no output */ : /* no input */ : "memory");
|
||||
|
||||
/* Never reach here. */
|
||||
/* Artificial entry to refer FT0, FT1, and FT2. */
|
||||
asm volatile (""
|
||||
: : "r" (FT0), "r" (FT1), "r" (FT2));
|
||||
}
|
||||
|
||||
typedef void (*handler)(void);
|
||||
extern uint8_t __ram_end__;
|
||||
|
||||
handler vector[] __attribute__ ((section(".vectors"))) = {
|
||||
(handler)&__ram_end__,
|
||||
reset,
|
||||
(handler)set_led,
|
||||
flash_unlock,
|
||||
(handler)flash_program_halfword,
|
||||
(handler)flash_erase_page,
|
||||
(handler)flash_check_blank,
|
||||
(handler)flash_write,
|
||||
(handler)flash_protect,
|
||||
(handler)flash_erase_all_and_exec,
|
||||
usb_lld_sys_init,
|
||||
usb_lld_sys_shutdown,
|
||||
nvic_system_reset,
|
||||
clock_init,
|
||||
gpio_init,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const uint8_t sys_version[8] __attribute__((section(".sys.version"))) = {
|
||||
3*2+2, /* bLength */
|
||||
0x03, /* bDescriptorType = USB_STRING_DESCRIPTOR_TYPE */
|
||||
/* sys version: "2.1" */
|
||||
'2', 0, '.', 0, '1', 0,
|
||||
};
|
||||
|
||||
const uint32_t __attribute__((section(".sys.board_id")))
|
||||
sys_board_id = BOARD_ID;
|
||||
|
||||
const uint8_t __attribute__((section(".sys.board_name")))
|
||||
sys_board_name[] = BOARD_NAME;
|
||||
129
src/sys.h
129
src/sys.h
@@ -1,129 +0,0 @@
|
||||
#define BOARD_ID_CQ_STARM 0xc5480875
|
||||
#define BOARD_ID_FST_01_00 0x613870a9
|
||||
#define BOARD_ID_FST_01 0x696886af
|
||||
#define BOARD_ID_MAPLE_MINI 0x7a445272
|
||||
#define BOARD_ID_OLIMEX_STM32_H103 0xf92bb594
|
||||
#define BOARD_ID_STBEE_MINI 0x1f341961
|
||||
#define BOARD_ID_STBEE 0x945c37e8
|
||||
#define BOARD_ID_STM32_PRIMER2 0x21e5798d
|
||||
#define BOARD_ID_STM8S_DISCOVERY 0x2f0976bb
|
||||
#define BOARD_ID_ST_DONGLE 0x2cd4e471
|
||||
#define BOARD_ID_ST_NUCLEO_F103 0x9b87c16d
|
||||
|
||||
extern const uint8_t sys_version[8];
|
||||
extern const uint32_t sys_board_id;
|
||||
extern const uint8_t sys_board_name[];
|
||||
|
||||
typedef void (*handler)(void);
|
||||
extern handler vector[16];
|
||||
|
||||
static inline const uint8_t *
|
||||
unique_device_id (void)
|
||||
{
|
||||
/* STM32F103 has 96-bit unique device identifier */
|
||||
const uint8_t *addr = (const uint8_t *)0x1ffff7e8;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_led (int on)
|
||||
{
|
||||
void (*func) (int) = (void (*)(int))vector[2];
|
||||
|
||||
return (*func) (on);
|
||||
}
|
||||
|
||||
static inline void
|
||||
flash_unlock (void)
|
||||
{
|
||||
(*vector[3]) ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_program_halfword (uint32_t addr, uint16_t data)
|
||||
{
|
||||
int (*func) (uint32_t, uint16_t) = (int (*)(uint32_t, uint16_t))vector[4];
|
||||
|
||||
return (*func) (addr, data);
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_erase_page (uint32_t addr)
|
||||
{
|
||||
int (*func) (uint32_t) = (int (*)(uint32_t))vector[5];
|
||||
|
||||
return (*func) (addr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_check_blank (const uint8_t *p_start, size_t size)
|
||||
{
|
||||
int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[6];
|
||||
|
||||
return (*func) (p_start, size);
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_write (uint32_t dst_addr, const uint8_t *src, size_t len)
|
||||
{
|
||||
int (*func) (uint32_t, const uint8_t *, size_t)
|
||||
= (int (*)(uint32_t, const uint8_t *, size_t))vector[7];
|
||||
|
||||
return (*func) (dst_addr, src, len);
|
||||
}
|
||||
|
||||
static inline int
|
||||
flash_protect (void)
|
||||
{
|
||||
int (*func) (void) = (int (*)(void))vector[8];
|
||||
|
||||
return (*func) ();
|
||||
}
|
||||
|
||||
static inline void __attribute__((noreturn))
|
||||
flash_erase_all_and_exec (void (*entry)(void))
|
||||
{
|
||||
void (*func) (void (*)(void)) = (void (*)(void (*)(void)))vector[9];
|
||||
|
||||
(*func) (entry);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
static inline void
|
||||
usb_lld_sys_init (void)
|
||||
{
|
||||
(*vector[10]) ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
usb_lld_sys_shutdown (void)
|
||||
{
|
||||
(*vector[11]) ();
|
||||
}
|
||||
|
||||
static inline void
|
||||
nvic_system_reset (void)
|
||||
{
|
||||
(*vector[12]) ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Users can override INLINE by 'attribute((used))' to have an
|
||||
* implementation defined.
|
||||
*/
|
||||
#if !defined(INLINE)
|
||||
#define INLINE __inline__
|
||||
#endif
|
||||
|
||||
static INLINE void
|
||||
clock_init (void)
|
||||
{
|
||||
(*vector[13]) ();
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
gpio_init (void)
|
||||
{
|
||||
(*vector[14]) ();
|
||||
}
|
||||
2023
src/usb-ccid.c
Normal file
2023
src/usb-ccid.c
Normal file
File diff suppressed because it is too large
Load Diff
1455
src/usb-icc.c
1455
src/usb-icc.c
File diff suppressed because it is too large
Load Diff
@@ -31,9 +31,11 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb-msc.h"
|
||||
|
||||
extern uint8_t __process5_stack_base__, __process5_stack_size__;
|
||||
const uint32_t __stackaddr_msc = (uint32_t)&__process5_stack_base__;
|
||||
const size_t __stacksize_msc = (size_t)&__process5_stack_size__;
|
||||
#define STACK_PROCESS_5
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_MSC ((uintptr_t)process5_base)
|
||||
#define STACK_SIZE_MSC (sizeof process5_base)
|
||||
|
||||
#define PRIO_MSC 3
|
||||
|
||||
static chopstx_mutex_t a_pinpad_mutex;
|
||||
@@ -86,13 +88,12 @@ static void usb_start_transmit (const uint8_t *p, size_t n)
|
||||
|
||||
/* "Data Transmitted" callback */
|
||||
void
|
||||
EP6_IN_Callback (void)
|
||||
EP6_IN_Callback (uint16_t len)
|
||||
{
|
||||
size_t n;
|
||||
size_t n = len;
|
||||
|
||||
chopstx_mutex_lock (msc_mutex);
|
||||
|
||||
n = (size_t)usb_lld_tx_data_len (ENDP6);
|
||||
ep6_in.txbuf += n;
|
||||
ep6_in.txcnt += n;
|
||||
ep6_in.txsize -= n;
|
||||
@@ -132,14 +133,13 @@ static void usb_start_receive (uint8_t *p, size_t n)
|
||||
|
||||
/* "Data Received" call back */
|
||||
void
|
||||
EP6_OUT_Callback (void)
|
||||
EP6_OUT_Callback (uint16_t len)
|
||||
{
|
||||
size_t n;
|
||||
size_t n = len;
|
||||
int err = 0;
|
||||
|
||||
chopstx_mutex_lock (msc_mutex);
|
||||
|
||||
n = (size_t)usb_lld_rx_data_len (ENDP6);
|
||||
if (n > ep6_out.rxsize)
|
||||
{ /* buffer overflow */
|
||||
err = 1;
|
||||
@@ -319,7 +319,7 @@ msc_handle_command (void)
|
||||
/* Error occured, ignore the request and go into error state */
|
||||
msc_state = MSC_ERROR;
|
||||
usb_lld_stall_rx (ENDP6);
|
||||
goto done;
|
||||
goto done;
|
||||
}
|
||||
|
||||
n = ep6_out.rxcnt;
|
||||
@@ -570,5 +570,5 @@ msc_main (void *arg)
|
||||
void
|
||||
msc_init (void)
|
||||
{
|
||||
chopstx_create (PRIO_MSC, __stackaddr_msc, __stacksize_msc, msc_main, NULL);
|
||||
chopstx_create (PRIO_MSC, STACK_ADDR_MSC, STACK_SIZE_MSC, msc_main, NULL);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
#define SCSI_WRITE10 0x2A
|
||||
#define SCSI_VERIFY10 0x2F
|
||||
#define SCSI_READ_FORMAT_CAPACITIES 0x23
|
||||
|
||||
#define SCSI_SYNCHRONIZE_CACHE 0x35
|
||||
#define SCSI_REPORT_LUN 0xA0
|
||||
|
||||
#define MSC_IDLE 0
|
||||
#define MSC_DATA_OUT 1
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#ifndef __USB_CONF_H
|
||||
#define __USB_CONF_H
|
||||
|
||||
#define ICC_NUM_INTERFACES 1
|
||||
#define ICC_INTERFACE 0
|
||||
#define CCID_NUM_INTERFACES 1
|
||||
#define CCID_INTERFACE 0
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_NUM_INTERFACES 1
|
||||
#define HID_INTERFACE 1
|
||||
@@ -13,18 +13,18 @@
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#define VCOM_INTERFACE_0 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES)
|
||||
#define VCOM_INTERFACE_1 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + 1)
|
||||
#define VCOM_INTERFACE_0 (CCID_NUM_INTERFACES + HID_NUM_INTERFACES)
|
||||
#define VCOM_INTERFACE_1 (CCID_NUM_INTERFACES + HID_NUM_INTERFACES + 1)
|
||||
#else
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#define MSC_INTERFACE (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + VCOM_NUM_INTERFACES)
|
||||
#define MSC_INTERFACE (CCID_NUM_INTERFACES + HID_NUM_INTERFACES + VCOM_NUM_INTERFACES)
|
||||
#else
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
#define NUM_INTERFACES (CCID_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
|
||||
|
||||
#if defined(USB_SELF_POWERED)
|
||||
|
||||
430
src/usb_ctrl.c
430
src/usb_ctrl.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* usb_ctrl.c - USB control pipe device specific code for Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -37,7 +38,7 @@
|
||||
#include "usb_lld.h"
|
||||
#include "usb_conf.h"
|
||||
#include "gnuk.h"
|
||||
#include "stm32f103.h"
|
||||
#include "neug.h"
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#include "usb-cdc.h"
|
||||
@@ -57,48 +58,28 @@ static struct line_coding line_coding = {
|
||||
0x08 /* bits: 8 */
|
||||
};
|
||||
|
||||
#define CDC_CTRL_DTR 0x0001
|
||||
|
||||
static int
|
||||
vcom_port_data_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
|
||||
vcom_port_data_setup (struct usb_dev *dev)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
struct device_req *arg = &dev->dev_req;
|
||||
|
||||
if (USB_SETUP_GET (arg->type))
|
||||
{
|
||||
if (req_no == USB_CDC_REQ_GET_LINE_CODING)
|
||||
return usb_lld_reply_request (&line_coding, sizeof(line_coding), detail);
|
||||
if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
|
||||
return usb_lld_ctrl_send (dev, &line_coding, sizeof (line_coding));
|
||||
}
|
||||
else /* USB_SETUP_SET (req) */
|
||||
{
|
||||
if (req_no == USB_CDC_REQ_SET_LINE_CODING)
|
||||
{
|
||||
usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
{
|
||||
uint8_t connected_saved = stdout.connected;
|
||||
|
||||
if (detail->value != 0)
|
||||
{
|
||||
if (stdout.connected == 0)
|
||||
/* It's Open call */
|
||||
stdout.connected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stdout.connected)
|
||||
/* Close call */
|
||||
stdout.connected = 0;
|
||||
}
|
||||
|
||||
chopstx_mutex_lock (&stdout.m_dev);
|
||||
if (stdout.connected != connected_saved)
|
||||
chopstx_cond_signal (&stdout.cond_dev);
|
||||
chopstx_mutex_unlock (&stdout.m_dev);
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
if (arg->request == USB_CDC_REQ_SET_LINE_CODING
|
||||
&& arg->len == sizeof (line_coding))
|
||||
return usb_lld_ctrl_recv (dev, &line_coding, sizeof (line_coding));
|
||||
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -106,7 +87,7 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
|
||||
#include "usb-msc.h"
|
||||
#endif
|
||||
|
||||
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
|
||||
#define USB_HID_REQ_GET_REPORT 1
|
||||
#define USB_HID_REQ_GET_IDLE 2
|
||||
@@ -127,15 +108,25 @@ static uint16_t hid_report;
|
||||
#endif
|
||||
|
||||
static void
|
||||
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
gnuk_setup_endpoints_for_interface (struct usb_dev *dev,
|
||||
uint16_t interface, int stop)
|
||||
{
|
||||
if (interface == ICC_INTERFACE)
|
||||
#if !defined(GNU_LINUX_EMULATION)
|
||||
(void)dev;
|
||||
#endif
|
||||
|
||||
if (interface == CCID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP1, 1, 1);
|
||||
usb_lld_setup_endp (dev, ENDP2, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, ENDP1_RXADDR,
|
||||
ENDP1_TXADDR, GNUK_MAX_PACKET_SIZE);
|
||||
usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -148,7 +139,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == HID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP7, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
|
||||
#endif
|
||||
else
|
||||
usb_lld_stall_tx (ENDP7);
|
||||
}
|
||||
@@ -157,7 +152,11 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == VCOM_INTERFACE_0)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP4, 0, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
|
||||
#endif
|
||||
else
|
||||
usb_lld_stall_tx (ENDP4);
|
||||
}
|
||||
@@ -165,9 +164,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP3, 0, 1);
|
||||
usb_lld_setup_endp (dev, ENDP5, 1, 0);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, 0, ENDP3_TXADDR, 0);
|
||||
usb_lld_setup_endpoint (ENDP5, EP_BULK, 0, ENDP5_RXADDR, 0,
|
||||
VIRTUAL_COM_PORT_DATA_SIZE);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -180,8 +184,12 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
else if (interface == MSC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP6, 1, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
|
||||
ENDP6_RXADDR, ENDP6_TXADDR, 64);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
usb_lld_stall_tx (ENDP6);
|
||||
@@ -192,26 +200,19 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
|
||||
void
|
||||
usb_cb_device_reset (void)
|
||||
usb_device_reset (struct usb_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set DEVICE as not configured */
|
||||
usb_lld_set_configuration (0);
|
||||
|
||||
/* Current Feature initialization */
|
||||
usb_lld_set_feature (USB_INITIAL_FEATURE);
|
||||
|
||||
usb_lld_reset ();
|
||||
usb_lld_reset (dev, USB_INITIAL_FEATURE);
|
||||
|
||||
/* Initialize Endpoint 0 */
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
usb_lld_setup_endp (dev, ENDP0, 1, 1);
|
||||
#else
|
||||
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR,
|
||||
GNUK_MAX_PACKET_SIZE);
|
||||
64);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 0);
|
||||
|
||||
bDeviceState = ATTACHED;
|
||||
bDeviceState = USB_DEVICE_STATE_DEFAULT;
|
||||
}
|
||||
|
||||
#define USB_CCID_REQ_ABORT 0x01
|
||||
@@ -225,289 +226,306 @@ static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
|
||||
static const uint8_t lun_table[] = { 0, 0, 0, 0, };
|
||||
#endif
|
||||
|
||||
static const uint8_t *const mem_info[] = { &_regnual_start, __heap_end__, };
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
static const uint8_t *const mem_info[] = { _regnual_start, __heap_end__, };
|
||||
#endif
|
||||
|
||||
#define USB_FSIJ_GNUK_MEMINFO 0
|
||||
#define USB_FSIJ_GNUK_DOWNLOAD 1
|
||||
#define USB_FSIJ_GNUK_EXEC 2
|
||||
#define USB_FSIJ_GNUK_CARD_CHANGE 3
|
||||
|
||||
static uint32_t rbit (uint32_t v)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
asm ("rbit %0, %1" : "=r" (r) : "r" (v));
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
/* After calling this function, CRC module remain enabled. */
|
||||
static int download_check_crc32 (const uint32_t *end_p)
|
||||
static int
|
||||
download_check_crc32 (struct usb_dev *dev, const uint32_t *end_p)
|
||||
{
|
||||
uint32_t crc32 = *end_p;
|
||||
const uint32_t *p;
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_CRCEN;
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
crc32_rv_reset ();
|
||||
|
||||
for (p = (const uint32_t *)&_regnual_start; p < end_p; p++)
|
||||
CRC->DR = rbit (*p);
|
||||
crc32_rv_step (rbit (*p));
|
||||
|
||||
if ((rbit (CRC->DR) ^ crc32) == 0xffffffff)
|
||||
return USB_SUCCESS;
|
||||
if ((rbit (crc32_rv_get ()) ^ crc32) == 0xffffffff)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail)
|
||||
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_FSIJ_GNUK_MEMINFO)
|
||||
return usb_lld_reply_request (mem_info, sizeof (mem_info), detail);
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (arg->request == USB_FSIJ_GNUK_MEMINFO)
|
||||
return usb_lld_ctrl_send (dev, mem_info, sizeof (mem_info));
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else /* SETUP_SET */
|
||||
{
|
||||
uint8_t *addr = (uint8_t *)(0x20000000 + detail->value * 0x100 + detail->index);
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
uint8_t *addr = sram_address ((arg->value * 0x100) + arg->index);
|
||||
#endif
|
||||
|
||||
if (req_no == USB_FSIJ_GNUK_DOWNLOAD)
|
||||
if (arg->request == USB_FSIJ_GNUK_DOWNLOAD)
|
||||
{
|
||||
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
|
||||
return USB_UNSUPPORT;
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return -1;
|
||||
|
||||
if (addr < &_regnual_start || addr + detail->len > __heap_end__)
|
||||
return USB_UNSUPPORT;
|
||||
if (addr < _regnual_start || addr + arg->len > __heap_end__)
|
||||
return -1;
|
||||
|
||||
if (detail->index + detail->len < 256)
|
||||
memset (addr + detail->index + detail->len, 0, 256 - (detail->index + detail->len));
|
||||
if (arg->index + arg->len < 256)
|
||||
memset (addr + arg->index + arg->len, 0,
|
||||
256 - (arg->index + arg->len));
|
||||
|
||||
usb_lld_set_data_to_recv (addr, detail->len);
|
||||
return USB_SUCCESS;
|
||||
return usb_lld_ctrl_recv (dev, addr, arg->len);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else if (req_no == USB_FSIJ_GNUK_EXEC && detail->len == 0)
|
||||
else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0)
|
||||
{
|
||||
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
|
||||
return USB_UNSUPPORT;
|
||||
#ifdef FLASH_UPGRADE_SUPPORT
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return -1;
|
||||
|
||||
if (((uint32_t)addr & 0x03))
|
||||
return USB_UNSUPPORT;
|
||||
if (((uintptr_t)addr & 0x03))
|
||||
return -1;
|
||||
|
||||
return download_check_crc32 ((uint32_t *)addr);
|
||||
return download_check_crc32 (dev, (uint32_t *)addr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
else if (req_no == USB_FSIJ_GNUK_CARD_CHANGE && detail->len == 0)
|
||||
else if (arg->request == USB_FSIJ_GNUK_CARD_CHANGE && arg->len == 0)
|
||||
{
|
||||
if (detail->value != 0 && detail->value != 1 && detail->value != 2)
|
||||
return USB_UNSUPPORT;
|
||||
if (arg->value != 0 && arg->value != 1 && arg->value != 2)
|
||||
return -1;
|
||||
|
||||
ccid_card_change_signal (detail->value);
|
||||
return USB_SUCCESS;
|
||||
ccid_card_change_signal (arg->value);
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (detail->index == ICC_INTERFACE)
|
||||
if (arg->index == CCID_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
if (USB_SETUP_GET (arg->type))
|
||||
{
|
||||
if (req_no == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
||||
return usb_lld_reply_request (freq_table, sizeof (freq_table),
|
||||
detail);
|
||||
else if (req_no == USB_CCID_REQ_GET_DATA_RATES)
|
||||
return usb_lld_reply_request (data_rate_table,
|
||||
sizeof (data_rate_table), detail);
|
||||
if (arg->request == USB_CCID_REQ_GET_CLOCK_FREQUENCIES)
|
||||
return usb_lld_ctrl_send (dev, freq_table, sizeof (freq_table));
|
||||
else if (arg->request == USB_CCID_REQ_GET_DATA_RATES)
|
||||
return usb_lld_ctrl_send (dev, data_rate_table,
|
||||
sizeof (data_rate_table));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (req_no == USB_CCID_REQ_ABORT)
|
||||
if (arg->request == USB_CCID_REQ_ABORT)
|
||||
/* wValue: bSeq, bSlot */
|
||||
/* Abortion is not supported in Gnuk */
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (index == HID_INTERFACE)
|
||||
else if (arg->index == HID_INTERFACE)
|
||||
{
|
||||
switch (req_no)
|
||||
switch (arg->request)
|
||||
{
|
||||
case USB_HID_REQ_GET_IDLE:
|
||||
return usb_lld_reply_request (&hid_idle_rate, 1, detail);
|
||||
return usb_lld_ctrl_send (dev, &hid_idle_rate, 1);
|
||||
case USB_HID_REQ_SET_IDLE:
|
||||
usb_lld_set_data_to_recv (&hid_idle_rate, 1, detail);
|
||||
return USB_SUCCESS;
|
||||
return usb_lld_ctrl_recv (dev, &hid_idle_rate, 1);
|
||||
|
||||
case USB_HID_REQ_GET_REPORT:
|
||||
/* Request of LED status and key press */
|
||||
return usb_lld_reply_request (&hid_report, 2, detail);
|
||||
return usb_lld_ctrl_send (dev, &hid_report, 2);
|
||||
|
||||
case USB_HID_REQ_SET_REPORT:
|
||||
/* Received LED set request */
|
||||
if (detail->len == 1)
|
||||
usb_lld_set_data_to_recv (&hid_report, detail->len);
|
||||
return USB_SUCCESS;
|
||||
if (arg->len == 1)
|
||||
return usb_lld_ctrl_recv (dev, &hid_report, arg->len);
|
||||
else
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
|
||||
case USB_HID_REQ_GET_PROTOCOL:
|
||||
case USB_HID_REQ_SET_PROTOCOL:
|
||||
/* This driver doesn't support boot protocol. */
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
|
||||
default:
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (index == VCOM_INTERFACE_0)
|
||||
return vcom_port_data_setup (req, req_no, detail);
|
||||
else if (arg->index == VCOM_INTERFACE_0)
|
||||
return vcom_port_data_setup (dev);
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (index == MSC_INTERFACE)
|
||||
else if (arg->index == MSC_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
if (USB_SETUP_GET (arg->type))
|
||||
{
|
||||
if (req_no == MSC_GET_MAX_LUN_COMMAND)
|
||||
return usb_lld_reply_request (lun_table, sizeof (lun_table),
|
||||
detail);
|
||||
if (arg->request == MSC_GET_MAX_LUN_COMMAND)
|
||||
return usb_lld_ctrl_send (dev, lun_table, sizeof (lun_table));
|
||||
}
|
||||
else
|
||||
if (req_no == MSC_MASS_STORAGE_RESET_COMMAND)
|
||||
/* Should call resetting MSC thread, something like msc_reset() */
|
||||
return USB_SUCCESS;
|
||||
if (arg->request == MSC_MASS_STORAGE_RESET_COMMAND)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value)
|
||||
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))
|
||||
{
|
||||
if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC)
|
||||
if (USB_SETUP_SET (arg->type) && arg->request == USB_FSIJ_GNUK_EXEC)
|
||||
{
|
||||
if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED)
|
||||
if (ccid_get_ccid_state () != CCID_STATE_EXITED)
|
||||
return;
|
||||
|
||||
(void)value; (void)index;
|
||||
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
usb_lld_prepare_shutdown (); /* No further USB communication */
|
||||
*icc_state_p = ICC_STATE_EXEC_REQUESTED;
|
||||
led_blink (LED_GNUK_EXEC); /* Notify the main. */
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#if defined(HID_CARD_CHANGE_SUPPORT) || defined (ENABLE_VIRTUAL_COM_PORT)
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == HID_INTERFACE && req_no == USB_HID_REQ_SET_REPORT)
|
||||
# if defined(ENABLE_VIRTUAL_COM_PORT)
|
||||
if (arg->index == VCOM_INTERFACE_0 && USB_SETUP_SET (arg->type)
|
||||
&& arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
{
|
||||
uint8_t connected_saved = stdout.connected;
|
||||
|
||||
if ((arg->value & CDC_CTRL_DTR) != 0)
|
||||
{
|
||||
if (stdout.connected == 0)
|
||||
/* It's Open call */
|
||||
stdout.connected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stdout.connected)
|
||||
/* Close call */
|
||||
stdout.connected = 0;
|
||||
}
|
||||
|
||||
chopstx_mutex_lock (&stdout.m_dev);
|
||||
if (stdout.connected != connected_saved)
|
||||
chopstx_cond_signal (&stdout.cond_dev);
|
||||
chopstx_mutex_unlock (&stdout.m_dev);
|
||||
}
|
||||
# endif
|
||||
# if defined(HID_CARD_CHANGE_SUPPORT)
|
||||
if (arg->index == HID_INTERFACE && arg->request == USB_HID_REQ_SET_REPORT)
|
||||
{
|
||||
if ((hid_report ^ hid_report_saved) & HID_LED_STATUS_CARDCHANGE)
|
||||
ccid_card_change_signal (CARD_CHANGE_TOGGLE);
|
||||
|
||||
hid_report_saved = hid_report;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int usb_cb_handle_event (uint8_t event_type, uint16_t value)
|
||||
int
|
||||
usb_set_configuration (struct usb_dev *dev)
|
||||
{
|
||||
int i;
|
||||
uint8_t current_conf;
|
||||
|
||||
switch (event_type)
|
||||
current_conf = usb_lld_current_configuration (dev);
|
||||
if (current_conf == 0)
|
||||
{
|
||||
case USB_EVENT_ADDRESS:
|
||||
bDeviceState = ADDRESSED;
|
||||
return USB_SUCCESS;
|
||||
case USB_EVENT_CONFIG:
|
||||
current_conf = usb_lld_current_configuration ();
|
||||
if (current_conf == 0)
|
||||
{
|
||||
if (value != 1)
|
||||
return USB_UNSUPPORT;
|
||||
if (dev->dev_req.value != 1)
|
||||
return -1;
|
||||
|
||||
usb_lld_set_configuration (value);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 0);
|
||||
ccid_card_change_signal (CCID_CARD_INIT);
|
||||
bDeviceState = CONFIGURED;
|
||||
}
|
||||
else if (current_conf != value)
|
||||
{
|
||||
if (value != 0)
|
||||
return USB_UNSUPPORT;
|
||||
usb_lld_set_configuration (dev, 1);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 0);
|
||||
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
|
||||
}
|
||||
else if (current_conf != dev->dev_req.value)
|
||||
{
|
||||
if (dev->dev_req.value != 0)
|
||||
return -1;
|
||||
|
||||
usb_lld_set_configuration (0);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 1);
|
||||
bDeviceState = ADDRESSED;
|
||||
}
|
||||
/* Do nothing when current_conf == value */
|
||||
return USB_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
usb_lld_set_configuration (dev, 0);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 1);
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
}
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
/* Do nothing when current_conf == value */
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
|
||||
int usb_cb_interface (uint8_t cmd, struct control_info *detail)
|
||||
|
||||
int
|
||||
usb_set_interface (struct usb_dev *dev)
|
||||
{
|
||||
const uint8_t zero = 0;
|
||||
uint16_t interface = detail->index;
|
||||
uint16_t alt = detail->value;
|
||||
uint16_t interface = dev->dev_req.index;
|
||||
uint16_t alt = dev->dev_req.value;
|
||||
|
||||
if (interface >= NUM_INTERFACES)
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
|
||||
switch (cmd)
|
||||
if (alt != 0)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
case USB_SET_INTERFACE:
|
||||
if (alt != 0)
|
||||
return USB_UNSUPPORT;
|
||||
else
|
||||
{
|
||||
gnuk_setup_endpoints_for_interface (interface, 0);
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
case USB_GET_INTERFACE:
|
||||
return usb_lld_reply_request (&zero, 1, detail);
|
||||
|
||||
case USB_QUERY_INTERFACE:
|
||||
default:
|
||||
return USB_SUCCESS;
|
||||
gnuk_setup_endpoints_for_interface (dev, interface, 0);
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define INTR_REQ_USB 20
|
||||
|
||||
void *
|
||||
usb_intr (void *arg)
|
||||
int
|
||||
usb_get_interface (struct usb_dev *dev)
|
||||
{
|
||||
chopstx_intr_t interrupt;
|
||||
const uint8_t zero = 0;
|
||||
uint16_t interface = dev->dev_req.index;
|
||||
|
||||
(void)arg;
|
||||
usb_lld_init (USB_INITIAL_FEATURE);
|
||||
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
|
||||
usb_interrupt_handler ();
|
||||
if (interface >= NUM_INTERFACES)
|
||||
return -1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
|
||||
/* Process interrupt. */
|
||||
usb_interrupt_handler ();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return usb_lld_ctrl_send (dev, &zero, 1);
|
||||
}
|
||||
|
||||
int
|
||||
usb_get_status_interface (struct usb_dev *dev)
|
||||
{
|
||||
const uint16_t status_info = 0;
|
||||
uint16_t interface = dev->dev_req.index;
|
||||
|
||||
if (interface >= NUM_INTERFACES)
|
||||
return -1;
|
||||
|
||||
return usb_lld_ctrl_send (dev, &status_info, 2);
|
||||
}
|
||||
|
||||
107
src/usb_desc.c
107
src/usb_desc.c
@@ -53,28 +53,33 @@ static const uint8_t hid_report_desc[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define USB_ICC_INTERFACE_CLASS 0x0B
|
||||
#define USB_ICC_INTERFACE_SUBCLASS 0x00
|
||||
#define USB_ICC_INTERFACE_BULK_PROTOCOL 0x00
|
||||
#define USB_ICC_DATA_SIZE 64
|
||||
#define USB_CCID_INTERFACE_CLASS 0x0B
|
||||
#define USB_CCID_INTERFACE_SUBCLASS 0x00
|
||||
#define USB_CCID_INTERFACE_BULK_PROTOCOL 0x00
|
||||
#define USB_CCID_DATA_SIZE 64
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
static const uint8_t device_desc[] = {
|
||||
#if !defined(GNU_LINUX_EMULATION)
|
||||
static const
|
||||
#endif
|
||||
uint8_t device_desc[] = {
|
||||
18, /* bLength */
|
||||
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||
0x10, 0x01, /* bcdUSB = 1.1 */
|
||||
DEVICE_DESCRIPTOR, /* bDescriptorType */
|
||||
0x00, 0x02, /* bcdUSB = 2.0 */
|
||||
0x00, /* bDeviceClass: 0 means deferred to interface */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
0x40, /* bMaxPacketSize0 */
|
||||
#include "usb-vid-pid-ver.c.inc"
|
||||
0x00, 0x00, /* idVendor (will be replaced) */
|
||||
0x00, 0x00, /* idProduct (will be replaced) */
|
||||
0x00, 0x00, /* bcdDevice (will be replaced) */
|
||||
1, /* Index of string descriptor describing manufacturer */
|
||||
2, /* Index of string descriptor describing product */
|
||||
3, /* Index of string descriptor describing the device's serial number */
|
||||
0x01 /* bNumConfigurations */
|
||||
};
|
||||
|
||||
#define ICC_TOTAL_LENGTH (9+9+54+7+7+7)
|
||||
#define CCID_TOTAL_LENGTH (9+9+54+7+7+7)
|
||||
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_TOTAL_LENGTH (9+9+7)
|
||||
@@ -94,16 +99,16 @@ static const uint8_t device_desc[] = {
|
||||
#define MSC_TOTAL_LENGTH 0
|
||||
#endif
|
||||
|
||||
#define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH \
|
||||
#define W_TOTAL_LENGTH (CCID_TOTAL_LENGTH + HID_TOTAL_LENGTH \
|
||||
+ VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
|
||||
|
||||
|
||||
/* Configuation Descriptor */
|
||||
static const uint8_t config_desc[] = {
|
||||
9, /* bLength: Configuation Descriptor size */
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
|
||||
W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */
|
||||
NUM_INTERFACES, /* bNumInterfaces: */
|
||||
CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
|
||||
W_TOTAL_LENGTH, 0x00, /* wTotalLength:no of returned bytes */
|
||||
NUM_INTERFACES, /* bNumInterfaces: */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
USB_INITIAL_FEATURE, /* bmAttributes*/
|
||||
@@ -111,13 +116,13 @@ static const uint8_t config_desc[] = {
|
||||
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
ICC_INTERFACE, /* bInterfaceNumber: Index of this interface */
|
||||
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
|
||||
CCID_INTERFACE, /* bInterfaceNumber: Index of this interface */
|
||||
0, /* Alternate setting for this interface */
|
||||
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
|
||||
USB_ICC_INTERFACE_CLASS,
|
||||
USB_ICC_INTERFACE_SUBCLASS,
|
||||
USB_ICC_INTERFACE_BULK_PROTOCOL,
|
||||
USB_CCID_INTERFACE_CLASS,
|
||||
USB_CCID_INTERFACE_SUBCLASS,
|
||||
USB_CCID_INTERFACE_BULK_PROTOCOL,
|
||||
0, /* string index for interface */
|
||||
|
||||
/* ICC Descriptor */
|
||||
@@ -167,21 +172,21 @@ static const uint8_t config_desc[] = {
|
||||
1, /* bMaxCCIDBusySlots: 1 */
|
||||
/*Endpoint IN1 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x81, /* bEndpointAddress: (IN1) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
USB_CCID_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
0x00, /* bInterval */
|
||||
/*Endpoint OUT1 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x01, /* bEndpointAddress: (OUT1) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
USB_CCID_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
0x00, /* bInterval */
|
||||
/*Endpoint IN2 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x82, /* bEndpointAddress: (IN2) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
0x04, 0x00, /* wMaxPacketSize: 4 */
|
||||
@@ -190,7 +195,7 @@ static const uint8_t config_desc[] = {
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
|
||||
HID_INTERFACE, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoint used */
|
||||
@@ -209,7 +214,7 @@ static const uint8_t config_desc[] = {
|
||||
|
||||
/*Endpoint IN7 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x87, /* bEndpointAddress: (IN7) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
0x02, 0x00, /* wMaxPacketSize: 2 */
|
||||
@@ -219,7 +224,7 @@ static const uint8_t config_desc[] = {
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
|
||||
VCOM_INTERFACE_0, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
@@ -251,7 +256,7 @@ static const uint8_t config_desc[] = {
|
||||
VCOM_INTERFACE_1, /* bSlaveInterface0: Data Class Interface */
|
||||
/*Endpoint 4 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x84, /* bEndpointAddress: (IN4) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
VIRTUAL_COM_PORT_INT_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
@@ -259,7 +264,7 @@ static const uint8_t config_desc[] = {
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
9, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
INTERFACE_DESCRIPTOR, /* bDescriptorType: */
|
||||
VCOM_INTERFACE_1, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
@@ -269,14 +274,14 @@ static const uint8_t config_desc[] = {
|
||||
0x00, /* iInterface: */
|
||||
/*Endpoint 5 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x05, /* bEndpointAddress: (OUT5) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
/*Endpoint 3 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x83, /* bEndpointAddress: (IN3) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
VIRTUAL_COM_PORT_DATA_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
@@ -285,7 +290,7 @@ static const uint8_t config_desc[] = {
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
/* Interface Descriptor.*/
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
INTERFACE_DESCRIPTOR, /* bDescriptorType: Interface */
|
||||
MSC_INTERFACE, /* bInterfaceNumber. */
|
||||
0x00, /* bAlternateSetting. */
|
||||
0x02, /* bNumEndpoints. */
|
||||
@@ -298,14 +303,14 @@ static const uint8_t config_desc[] = {
|
||||
0x00, /* iInterface. */
|
||||
/* Endpoint Descriptor.*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x86, /* bEndpointAddress: (IN6) */
|
||||
0x02, /* bmAttributes (Bulk). */
|
||||
0x40, 0x00, /* wMaxPacketSize. */
|
||||
0x00, /* bInterval (ignored for bulk). */
|
||||
/* Endpoint Descriptor.*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
|
||||
0x06, /* bEndpointAddress: (OUT6) */
|
||||
0x02, /* bmAttributes (Bulk). */
|
||||
0x40, 0x00, /* wMaxPacketSize. */
|
||||
@@ -317,7 +322,7 @@ static const uint8_t config_desc[] = {
|
||||
/* USB String Descriptors */
|
||||
static const uint8_t gnuk_string_lang_id[] = {
|
||||
4, /* bLength */
|
||||
USB_STRING_DESCRIPTOR_TYPE,
|
||||
STRING_DESCRIPTOR,
|
||||
0x09, 0x04 /* LangID = 0x0409: US-English */
|
||||
};
|
||||
|
||||
@@ -345,21 +350,25 @@ static const struct desc string_descriptors[] = {
|
||||
#define USB_DT_REPORT 0x22
|
||||
|
||||
int
|
||||
usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
||||
struct control_info *detail)
|
||||
usb_get_descriptor (struct usb_dev *dev)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (desc_type == DEVICE_DESCRIPTOR)
|
||||
return usb_lld_reply_request (device_desc, sizeof (device_desc), detail);
|
||||
return usb_lld_ctrl_send (dev, device_desc, sizeof (device_desc));
|
||||
else if (desc_type == CONFIG_DESCRIPTOR)
|
||||
return usb_lld_reply_request (config_desc, sizeof (config_desc), detail);
|
||||
return usb_lld_ctrl_send (dev, config_desc, sizeof (config_desc));
|
||||
else if (desc_type == STRING_DESCRIPTOR)
|
||||
{
|
||||
if (desc_index < NUM_STRING_DESC)
|
||||
return usb_lld_reply_request (string_descriptors[desc_index].desc,
|
||||
string_descriptors[desc_index].size,
|
||||
detail);
|
||||
return usb_lld_ctrl_send (dev, string_descriptors[desc_index].desc,
|
||||
string_descriptors[desc_index].size);
|
||||
#ifdef USE_SYS3
|
||||
else if (desc_index == NUM_STRING_DESC)
|
||||
{
|
||||
uint8_t usbbuf[64];
|
||||
@@ -375,25 +384,25 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
||||
usbbuf[i*2+3] = 0;
|
||||
}
|
||||
usbbuf[0] = len = i*2 + 2;
|
||||
usbbuf[1] = USB_STRING_DESCRIPTOR_TYPE;
|
||||
return usb_lld_reply_request (usbbuf, len, detail);
|
||||
usbbuf[1] = STRING_DESCRIPTOR;
|
||||
return usb_lld_ctrl_send (dev, usbbuf, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (rcp == INTERFACE_RECIPIENT)
|
||||
{
|
||||
if (detail->index == 1)
|
||||
if (arg->index == HID_INTERFACE)
|
||||
{
|
||||
if (desc_type == USB_DT_HID)
|
||||
return usb_lld_reply_request (config_desc+ICC_TOTAL_LENGTH+9, 9,
|
||||
detail);
|
||||
return usb_lld_ctrl_send (dev, config_desc+CCID_TOTAL_LENGTH+9, 9);
|
||||
else if (desc_type == USB_DT_REPORT)
|
||||
return usb_lld_reply_request (hid_report_desc, HID_REPORT_DESC_SIZE,
|
||||
detail);
|
||||
return usb_lld_ctrl_send (dev, hid_report_desc,
|
||||
HID_REPORT_DESC_SIZE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
122
src/usb_lld.h
122
src/usb_lld.h
@@ -1,122 +0,0 @@
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
||||
|
||||
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
|
||||
|
||||
/* endpoints enumeration */
|
||||
#define ENDP0 ((uint8_t)0)
|
||||
#define ENDP1 ((uint8_t)1)
|
||||
#define ENDP2 ((uint8_t)2)
|
||||
#define ENDP3 ((uint8_t)3)
|
||||
#define ENDP4 ((uint8_t)4)
|
||||
#define ENDP5 ((uint8_t)5)
|
||||
#define ENDP6 ((uint8_t)6)
|
||||
#define ENDP7 ((uint8_t)7)
|
||||
|
||||
/* EP_TYPE[1:0] EndPoint TYPE */
|
||||
#define EP_BULK (0x0000) /* EndPoint BULK */
|
||||
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
|
||||
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
|
||||
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
|
||||
|
||||
enum RECIPIENT_TYPE
|
||||
{
|
||||
DEVICE_RECIPIENT, /* Recipient device */
|
||||
INTERFACE_RECIPIENT, /* Recipient interface */
|
||||
ENDPOINT_RECIPIENT, /* Recipient endpoint */
|
||||
OTHER_RECIPIENT
|
||||
};
|
||||
|
||||
enum DESCRIPTOR_TYPE
|
||||
{
|
||||
DEVICE_DESCRIPTOR = 1,
|
||||
CONFIG_DESCRIPTOR,
|
||||
STRING_DESCRIPTOR,
|
||||
INTERFACE_DESCRIPTOR,
|
||||
ENDPOINT_DESCRIPTOR
|
||||
};
|
||||
|
||||
#define REQUEST_DIR 0x80 /* Mask to get request dir */
|
||||
#define REQUEST_TYPE 0x60 /* Mask to get request type */
|
||||
#define STANDARD_REQUEST 0x00 /* Standard request */
|
||||
#define CLASS_REQUEST 0x20 /* Class request */
|
||||
#define VENDOR_REQUEST 0x40 /* Vendor request */
|
||||
#define RECIPIENT 0x1F /* Mask to get recipient */
|
||||
|
||||
#define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0)
|
||||
#define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0)
|
||||
|
||||
enum
|
||||
{
|
||||
USB_UNSUPPORT = 0,
|
||||
USB_SUCCESS = 1,
|
||||
};
|
||||
|
||||
struct control_info {
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
void usb_cb_device_reset (void);
|
||||
int usb_cb_setup (uint8_t req, uint8_t req_no, struct control_info *detail);
|
||||
int usb_cb_interface (uint8_t cmd, struct control_info *detail);
|
||||
int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
|
||||
struct control_info *detail);
|
||||
int usb_cb_handle_event (uint8_t event_type, uint16_t value);
|
||||
void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value);
|
||||
|
||||
enum {
|
||||
USB_EVENT_ADDRESS,
|
||||
USB_EVENT_CONFIG,
|
||||
USB_EVENT_SUSPEND,
|
||||
USB_EVENT_WAKEUP,
|
||||
USB_EVENT_STALL,
|
||||
};
|
||||
|
||||
enum {
|
||||
USB_SET_INTERFACE,
|
||||
USB_GET_INTERFACE,
|
||||
USB_QUERY_INTERFACE,
|
||||
};
|
||||
|
||||
enum DEVICE_STATE
|
||||
{
|
||||
UNCONNECTED,
|
||||
ATTACHED,
|
||||
POWERED,
|
||||
SUSPENDED,
|
||||
ADDRESSED,
|
||||
CONFIGURED
|
||||
};
|
||||
|
||||
void usb_lld_init (uint8_t feature);
|
||||
void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
|
||||
void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
|
||||
void usb_lld_stall_tx (int ep_num);
|
||||
void usb_lld_stall_rx (int ep_num);
|
||||
int usb_lld_tx_data_len (int ep_num);
|
||||
void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len);
|
||||
void usb_lld_tx_enable (int ep_num, size_t len);
|
||||
void usb_lld_write (uint8_t ep_num, const void *buf, size_t len);
|
||||
int usb_lld_reply_request (const void *buf, size_t buflen,
|
||||
struct control_info *ctrl);
|
||||
void usb_lld_rx_enable (int ep_num);
|
||||
int usb_lld_rx_data_len (int ep_num);
|
||||
void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len);
|
||||
void usb_lld_reset (void);
|
||||
void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind,
|
||||
int ep_rx_addr, int ep_tx_addr,
|
||||
int ep_rx_memory_size);
|
||||
void usb_lld_set_configuration (uint8_t config);
|
||||
uint8_t usb_lld_current_configuration (void);
|
||||
void usb_lld_set_feature (uint8_t feature);
|
||||
void usb_lld_set_data_to_recv (const void *p, size_t len);
|
||||
|
||||
void usb_lld_prepare_shutdown (void);
|
||||
void usb_lld_shutdown (void);
|
||||
|
||||
void usb_interrupt_handler (void);
|
||||
1168
src/usb_stm32f103.c
1168
src/usb_stm32f103.c
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,11 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object historical bytes
|
||||
When requesting historical bytes: 5f52
|
||||
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
|
||||
Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -4,7 +4,7 @@ Feature: setup pass phrase
|
||||
A token should support pass phrase: PW1, PW3 and reset code
|
||||
|
||||
Scenario: setup PW1 (admin-full mode)
|
||||
Given cmd_change_reference_data with 1 and "123456user pass phrase"
|
||||
Given cmd_change_reference_data with 1 and "another user pass phraseuser pass phrase"
|
||||
Then it should get success
|
||||
|
||||
Scenario: verify PW1 (1)
|
||||
|
||||
@@ -4,11 +4,11 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object historical bytes
|
||||
When requesting historical bytes: 5f52
|
||||
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
|
||||
Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -4,11 +4,11 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object historical bytes
|
||||
When requesting historical bytes: 5f52
|
||||
Then you should get: \x00\x31\x84\x73\x80\x01\x80\x00\x90\x00
|
||||
Then data should match: \x00\x31\x84\x73\x80\x01\x80[\x00\x05]\x90\x00
|
||||
|
||||
Scenario: data object extended capabilities
|
||||
When requesting extended capabilities: c0
|
||||
Then data should match: [\x70\x74]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
Then data should match: [\x70\x74\x75]\x00\x00\x20[\x00\x08]\x00\x00\xff\x01\x00
|
||||
|
||||
Scenario: data object algorithm attributes 1
|
||||
When requesting algorithm attributes 1: c1
|
||||
@@ -24,4 +24,4 @@ Feature: command GET DATA
|
||||
|
||||
Scenario: data object AID
|
||||
When requesting AID: 4f
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00......\x00\x00
|
||||
Then data should match: \xd2\x76\x00\x01\x24\x01\x02\x00[\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff][\x00-\xff]\x00\x00
|
||||
|
||||
@@ -11,19 +11,19 @@ from array import array
|
||||
|
||||
@Before
|
||||
def ini(sc):
|
||||
if not ftc.token:
|
||||
ftc.token = gnuk.get_gnuk_device()
|
||||
ftc.token.cmd_select_openpgp()
|
||||
if not glc.token:
|
||||
glc.token = gnuk.get_gnuk_device()
|
||||
glc.token.cmd_select_openpgp()
|
||||
|
||||
@Given("cmd_verify with (.*) and \"(.*)\"")
|
||||
def cmd_verify(who_str,pass_str):
|
||||
who = int(who_str)
|
||||
scc.result = ftc.token.cmd_verify(who, pass_str)
|
||||
scc.result = glc.token.cmd_verify(who, pass_str)
|
||||
|
||||
@Given("cmd_change_reference_data with (.*) and \"(.*)\"")
|
||||
def cmd_change_reference_data(who_str,pass_str):
|
||||
who = int(who_str)
|
||||
scc.result = ftc.token.cmd_change_reference_data(who, pass_str)
|
||||
scc.result = glc.token.cmd_change_reference_data(who, pass_str)
|
||||
|
||||
@Given("cmd_put_data with (.*) and (\".*\")")
|
||||
def cmd_put_data(tag_str,content_str_repr):
|
||||
@@ -31,12 +31,12 @@ def cmd_put_data(tag_str,content_str_repr):
|
||||
tag = int(tag_str, 16)
|
||||
tagh = tag >> 8
|
||||
tagl = tag & 0xff
|
||||
scc.result = ftc.token.cmd_put_data(tagh, tagl, content_str)
|
||||
scc.result = glc.token.cmd_put_data(tagh, tagl, content_str)
|
||||
|
||||
@Given("cmd_reset_retry_counter with (.*) and \"(.*)\"")
|
||||
def cmd_reset_retry_counter(how_str, data):
|
||||
how = int(how_str)
|
||||
scc.result = ftc.token.cmd_reset_retry_counter(how, data)
|
||||
scc.result = glc.token.cmd_reset_retry_counter(how, 0x81, data)
|
||||
|
||||
@Given("a RSA key pair (.*)")
|
||||
def set_rsa_key(keyno_str):
|
||||
@@ -46,7 +46,7 @@ def set_rsa_key(keyno_str):
|
||||
def import_key(openpgp_keyno_str):
|
||||
openpgp_keyno = int(openpgp_keyno_str)
|
||||
t = rsa_keys.build_privkey_template(openpgp_keyno, scc.keyno)
|
||||
scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
scc.result = glc.token.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
|
||||
@Given("a fingerprint of OPENPGP.(.*) key")
|
||||
def get_key_fpr(openpgp_keyno_str):
|
||||
@@ -63,7 +63,7 @@ def cmd_put_data_with_result(tag_str):
|
||||
tag = int(tag_str, 16)
|
||||
tagh = tag >> 8
|
||||
tagl = tag & 0xff
|
||||
scc.result = ftc.token.cmd_put_data(tagh, tagl, scc.result)
|
||||
scc.result = glc.token.cmd_put_data(tagh, tagl, scc.result)
|
||||
|
||||
@Given("a message (\".*\")")
|
||||
def set_msg(content_str_repr):
|
||||
@@ -73,7 +73,7 @@ def set_msg(content_str_repr):
|
||||
@Given("a public key from token for OPENPGP.(.*)")
|
||||
def get_public_key(openpgp_keyno_str):
|
||||
openpgp_keyno = int(openpgp_keyno_str)
|
||||
scc.pubkey_info = ftc.token.cmd_get_public_key(openpgp_keyno)
|
||||
scc.pubkey_info = glc.token.cmd_get_public_key(openpgp_keyno)
|
||||
|
||||
@Given("verify signature")
|
||||
def verify_signature():
|
||||
@@ -81,11 +81,11 @@ def verify_signature():
|
||||
|
||||
@Given("let a token compute digital signature")
|
||||
def compute_signature():
|
||||
scc.sig = int(hexlify(ftc.token.cmd_pso(0x9e, 0x9a, scc.digestinfo)),16)
|
||||
scc.sig = int(hexlify(glc.token.cmd_pso(0x9e, 0x9a, scc.digestinfo)),16)
|
||||
|
||||
@Given("let a token authenticate")
|
||||
def internal_authenticate():
|
||||
scc.sig = int(hexlify(ftc.token.cmd_internal_authenticate(scc.digestinfo)),16)
|
||||
scc.sig = int(hexlify(glc.token.cmd_internal_authenticate(scc.digestinfo)),16)
|
||||
|
||||
@Given("compute digital signature on host with RSA key pair (.*)")
|
||||
def compute_signature_on_host(keyno_str):
|
||||
@@ -107,29 +107,29 @@ def encrypt_on_host_public_key():
|
||||
|
||||
@Given("let a token decrypt encrypted data")
|
||||
def decrypt():
|
||||
scc.result = ftc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext).tostring()
|
||||
scc.result = glc.token.cmd_pso_longdata(0x80, 0x86, scc.ciphertext).tostring()
|
||||
|
||||
@Given("USB version string of the token")
|
||||
def usb_version_string():
|
||||
scc.result = ftc.token.get_string(3)
|
||||
scc.result = glc.token.get_string(3)
|
||||
|
||||
@When("requesting (.+): ([0-9a-fA-F]+)")
|
||||
def get_data(name, tag_str):
|
||||
tag = int(tag_str, 16)
|
||||
tagh = tag >> 8
|
||||
tagl = tag & 0xff
|
||||
scc.result = ftc.token.cmd_get_data(tagh, tagl)
|
||||
scc.result = glc.token.cmd_get_data(tagh, tagl)
|
||||
|
||||
@When("removing a key OPENPGP.(.*)")
|
||||
def remove_key(openpgp_keyno_str):
|
||||
openpgp_keyno = int(openpgp_keyno_str)
|
||||
t = rsa_keys.build_privkey_template_for_remove(openpgp_keyno)
|
||||
scc.result = ftc.token.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
scc.result = glc.token.cmd_put_data_odd(0x3f, 0xff, t)
|
||||
|
||||
@When("generating a key of OPENPGP.(.*)")
|
||||
def generate_key(openpgp_keyno_str):
|
||||
openpgp_keyno = int(openpgp_keyno_str)
|
||||
pubkey_info = ftc.token.cmd_genkey(openpgp_keyno)
|
||||
pubkey_info = glc.token.cmd_genkey(openpgp_keyno)
|
||||
scc.data = rsa_keys.calc_fpr(pubkey_info[0].tostring(), pubkey_info[1].tostring())
|
||||
|
||||
@When("put the first data to (.*)")
|
||||
@@ -137,14 +137,14 @@ def cmd_put_data_first_with_result(tag_str):
|
||||
tag = int(tag_str, 16)
|
||||
tagh = tag >> 8
|
||||
tagl = tag & 0xff
|
||||
scc.result = ftc.token.cmd_put_data(tagh, tagl, scc.data[0])
|
||||
scc.result = glc.token.cmd_put_data(tagh, tagl, scc.data[0])
|
||||
|
||||
@When("put the second data to (.*)")
|
||||
def cmd_put_data_second_with_result(tag_str):
|
||||
tag = int(tag_str, 16)
|
||||
tagh = tag >> 8
|
||||
tagl = tag & 0xff
|
||||
result = ftc.token.cmd_put_data(tagh, tagl, scc.data[1])
|
||||
result = glc.token.cmd_put_data(tagh, tagl, scc.data[1])
|
||||
scc.result = (scc.result and result)
|
||||
|
||||
@Then("you should get: (.*)")
|
||||
|
||||
@@ -60,7 +60,7 @@ def build_privkey_template(openpgp_keyno, keyno):
|
||||
|
||||
suffix = b'\x5f\x48' + b'\x82\x01\x04'
|
||||
|
||||
t = b'\x4d' + b'\x82\01\16' + exthdr + suffix + e_bytes + p_bytes + q_bytes
|
||||
t = b'\x4d' + b'\x82\x01\x16' + exthdr + suffix + e_bytes + p_bytes + q_bytes
|
||||
return t
|
||||
|
||||
def build_privkey_template_for_remove(openpgp_keyno):
|
||||
@@ -70,11 +70,11 @@ def build_privkey_template_for_remove(openpgp_keyno):
|
||||
keyspec = b'\xb8'
|
||||
else:
|
||||
keyspec = b'\xa4'
|
||||
return b'\x4d\02' + keyspec + b'\0x00'
|
||||
return b'\x4d\x02' + keyspec + b'\x00'
|
||||
|
||||
def compute_digestinfo(msg):
|
||||
digest = sha256(msg).digest()
|
||||
prefix = b'\x30\31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
prefix = b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20'
|
||||
return prefix + digest
|
||||
|
||||
# egcd and modinv are from wikibooks
|
||||
|
||||
13
tests/README
Normal file
13
tests/README
Normal file
@@ -0,0 +1,13 @@
|
||||
Here is a test suite for OpenPGP card.
|
||||
|
||||
For now, only TPDU card reader is supported for OpenPGP card.
|
||||
Gnuk Token is supported as well.
|
||||
|
||||
|
||||
You need to install:
|
||||
|
||||
$ sudo apt install python3-pytest python3-usb python3-cffi
|
||||
|
||||
Please run test by typing:
|
||||
|
||||
$ py.test-3 -x
|
||||
12
tests/card_const.py
Normal file
12
tests/card_const.py
Normal file
@@ -0,0 +1,12 @@
|
||||
FACTORY_PASSPHRASE_PW1=b"123456"
|
||||
FACTORY_PASSPHRASE_PW3=b"12345678"
|
||||
KEY_ATTRIBUTES_RSA4K=b"\x01\x10\x00\x00\x20\x00"
|
||||
KEY_ATTRIBUTES_RSA2K=b"\x01\x08\x00\x00\x20\x00"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P256R1=b"\x12\x2a\x86\x48\xce\x3d\x03\x01\x07"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P384R1=b"\x12\x2b\x81\x04\x00\x22"
|
||||
KEY_ATTRIBUTES_ECDH_ANSIX9P521R1=b"\x12\x2b\x81\x04\x00\x23"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP256R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x07"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP384R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0b"
|
||||
KEY_ATTRIBUTES_ECDH_BRAINPOOLP512R1=b"\x12\x2b\x24\x03\x03\x02\x08\x01\x01\x0d"
|
||||
KEY_ATTRIBUTES_X25519=b"\x12\x2b\x06\x01\x04\x01\x97\x55\x01\x05\x01"
|
||||
KEY_ATTRIBUTES_ED25519=b"\x16\x2b\x06\x01\x04\x01\xda\x47\x0f\x01"
|
||||
340
tests/card_reader.py
Normal file
340
tests/card_reader.py
Normal file
@@ -0,0 +1,340 @@
|
||||
"""
|
||||
card_reader.py - a library for smartcard reader
|
||||
|
||||
Copyright (C) 2016, 2017, 2019 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import usb.core
|
||||
from struct import pack
|
||||
from usb.util import find_descriptor, claim_interface, get_string, \
|
||||
endpoint_type, endpoint_direction, \
|
||||
ENDPOINT_TYPE_BULK, ENDPOINT_OUT, ENDPOINT_IN
|
||||
from binascii import hexlify
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
|
||||
def ccid_compose(msg_type, seq, slot=0, rsv=0, param=0, data=b""):
|
||||
return pack('<BiBBBH', msg_type, len(data), slot, seq, rsv, param) + data
|
||||
|
||||
IFSC=254
|
||||
|
||||
def compute_edc(pcb, info):
|
||||
edc = pcb
|
||||
edc ^= len(info)
|
||||
for i in range(len(info)):
|
||||
edc ^= info[i]
|
||||
return edc
|
||||
|
||||
def compose_i_block(ns, info, more):
|
||||
pcb = 0x00
|
||||
if ns:
|
||||
pcb |= 0x40
|
||||
if more:
|
||||
pcb |= 0x20
|
||||
edc = compute_edc(pcb, info)
|
||||
return bytes([0, pcb, len(info)]) + info + bytes([edc])
|
||||
|
||||
def compose_r_block(nr, edc_error=0):
|
||||
pcb = 0x80
|
||||
if nr:
|
||||
pcb |= 0x10
|
||||
if edc_error:
|
||||
pcb |= 0x01
|
||||
return bytes([0, pcb, 0, pcb])
|
||||
|
||||
def is_r_block_no_error_or_other(blk):
|
||||
return (((blk[1] & 0xC0) == 0x80 and (blk[1] & 0x2f) == 0x00)) or \
|
||||
((blk[1] & 0xC0) != 0x80)
|
||||
|
||||
def is_s_block_time_ext(blk):
|
||||
return (blk[1] == 0xC3)
|
||||
|
||||
def is_i_block_last(blk):
|
||||
return ((blk[1] & 0x80) == 0 and (blk[1] & 0x20) == 0)
|
||||
|
||||
def is_i_block_more(blk):
|
||||
return ((blk[1] & 0x80) == 0 and (blk[1] & 0x20) == 0x20)
|
||||
|
||||
def is_edc_error(blk):
|
||||
# to be implemented
|
||||
return 0
|
||||
|
||||
def i_block_content(blk):
|
||||
return blk[3:-1]
|
||||
|
||||
class CardReader(object):
|
||||
def __init__(self, dev):
|
||||
"""
|
||||
__init__(dev) -> None
|
||||
Initialize the DEV of CCID.
|
||||
device: usb.core.Device object.
|
||||
"""
|
||||
|
||||
cfg = dev.get_active_configuration()
|
||||
intf = find_descriptor(cfg, bInterfaceClass=CCID_CLASS,
|
||||
bInterfaceSubClass=CCID_SUBCLASS,
|
||||
bInterfaceProtocol=CCID_PROTOCOL_0)
|
||||
if intf is None:
|
||||
raise ValueError("Not a CCID device")
|
||||
|
||||
claim_interface(dev, intf)
|
||||
|
||||
for ep in intf:
|
||||
if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \
|
||||
endpoint_direction(ep.bEndpointAddress) == ENDPOINT_OUT:
|
||||
self.__bulkout = ep.bEndpointAddress
|
||||
if endpoint_type(ep.bmAttributes) == ENDPOINT_TYPE_BULK and \
|
||||
endpoint_direction(ep.bEndpointAddress) == ENDPOINT_IN:
|
||||
self.__bulkin = ep.bEndpointAddress
|
||||
|
||||
assert len(intf.extra_descriptors) == 54
|
||||
assert intf.extra_descriptors[1] == 33
|
||||
|
||||
if (intf.extra_descriptors[42] & 0x02):
|
||||
# Short APDU level exchange
|
||||
self.__use_APDU = True
|
||||
elif (intf.extra_descriptors[42] & 0x04):
|
||||
# Short and extended APDU level exchange
|
||||
self.__use_APDU = True
|
||||
elif (intf.extra_descriptors[42] & 0x01):
|
||||
# TPDU level exchange
|
||||
self.__use_APDU = False
|
||||
else:
|
||||
raise ValueError("Unknown exchange level")
|
||||
|
||||
# Check other bits???
|
||||
# intf.extra_descriptors[40]
|
||||
# intf.extra_descriptors[41]
|
||||
|
||||
self.__dev = dev
|
||||
self.__timeout = 100000
|
||||
self.__seq = 0
|
||||
|
||||
if self.ccid_get_status() & 0x03 not in (0, 1):
|
||||
raise ValueError("Card absent")
|
||||
|
||||
def get_string(self, num):
|
||||
return get_string(self.__dev, num)
|
||||
|
||||
def increment_seq(self):
|
||||
self.__seq = (self.__seq + 1) & 0xff
|
||||
|
||||
def reset_device(self):
|
||||
try:
|
||||
self.__dev.reset()
|
||||
except:
|
||||
pass
|
||||
|
||||
def is_tpdu_reader(self):
|
||||
return not self.__use_APDU
|
||||
|
||||
def ccid_get_result(self):
|
||||
msg = self.__dev.read(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print(msg)
|
||||
raise ValueError("ccid_get_result")
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data.tobytes())
|
||||
|
||||
def ccid_get_status(self):
|
||||
msg = ccid_compose(0x65, self.__seq)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data = self.ccid_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def ccid_power_on(self):
|
||||
msg = ccid_compose(0x62, self.__seq, rsv=2) # Vcc=3.3V
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data = self.ccid_get_result()
|
||||
# XXX: check status, chain
|
||||
self.atr = data
|
||||
#
|
||||
if self.__use_APDU == False:
|
||||
# TPDU reader configuration
|
||||
self.ns = 0
|
||||
self.nr = 0
|
||||
# For Gemalto's SmartCard Reader(s)
|
||||
if self.__dev.idVendor == 0x08E6:
|
||||
# Set PPS
|
||||
pps = b"\xFF\x11\x18\xF6"
|
||||
status, chain, ret_pps = self.ccid_send_data_block(pps)
|
||||
# Set parameters
|
||||
param = b"\x18\x10\xFF\x75\x00\xFE\x00"
|
||||
# ^--- This shoud be adapted by ATR string, see update_param_by_atr
|
||||
msg = ccid_compose(0x61, self.__seq, rsv=0x1, data=param)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, ret_param = self.ccid_get_result()
|
||||
# Send an S-block of changing IFSD=254
|
||||
sblk = b"\x00\xC1\x01\xFE\x3E"
|
||||
status, chain, ret_sblk = self.ccid_send_data_block(sblk)
|
||||
return self.atr
|
||||
|
||||
def ccid_power_off(self):
|
||||
msg = ccid_compose(0x63, self.__seq)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data = self.ccid_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def ccid_send_data_block(self, data):
|
||||
msg = ccid_compose(0x6f, self.__seq, data=data)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
return self.ccid_get_result()
|
||||
|
||||
def ccid_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.ccid_send_data_block(data)
|
||||
if chain == 0:
|
||||
while status == 0x80:
|
||||
status, chain, data_rcv = self.ccid_get_result()
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = ccid_compose(0x6f, self.__seq, param=0x10)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
status, chain, data_rcv = self.ccid_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError("ccid_send_cmd chain")
|
||||
return d
|
||||
else:
|
||||
raise ValueError("ccid_send_cmd")
|
||||
|
||||
def send_tpdu(self, info=None, more=0, response_time_ext=0,
|
||||
edc_error=0, no_error=0):
|
||||
rsv = 0
|
||||
if info:
|
||||
data = compose_i_block(self.ns, info, more)
|
||||
elif response_time_ext:
|
||||
# compose S-block response
|
||||
pcb = 0xe3
|
||||
bwi_byte = bytes([response_time_ext])
|
||||
edc = compute_edc(pcb, bwi_byte)
|
||||
data = bytes([0, pcb, 1]) + bwi_byte + bytes([edc])
|
||||
rsv = response_time_ext
|
||||
elif edc_error:
|
||||
data = compose_r_block(self.nr, edc_error=1)
|
||||
elif no_error:
|
||||
data = compose_r_block(self.nr)
|
||||
msg = ccid_compose(0x6f, self.__seq, rsv=rsv, data=data)
|
||||
self.__dev.write(self.__bulkout, msg, self.__timeout)
|
||||
self.increment_seq()
|
||||
|
||||
def recv_tpdu(self):
|
||||
status, chain, data = self.ccid_get_result()
|
||||
return data
|
||||
|
||||
def send_cmd(self, cmd):
|
||||
# Simple APDU case
|
||||
if self.__use_APDU:
|
||||
return self.ccid_send_cmd(cmd)
|
||||
# TPDU case
|
||||
while len(cmd) > 254:
|
||||
blk = cmd[0:254]
|
||||
cmd = cmd[254:]
|
||||
while True:
|
||||
self.send_tpdu(info=blk,more=1)
|
||||
rblk = self.recv_tpdu()
|
||||
if is_r_block_no_error_or_other(rblk):
|
||||
break
|
||||
self.ns = self.ns ^ 1
|
||||
while True:
|
||||
self.send_tpdu(info=cmd)
|
||||
blk = self.recv_tpdu()
|
||||
if is_r_block_no_error_or_other(blk):
|
||||
break
|
||||
self.ns = self.ns ^ 1
|
||||
res = b""
|
||||
while True:
|
||||
if is_s_block_time_ext(blk):
|
||||
self.send_tpdu(response_time_ext=blk[3])
|
||||
elif is_i_block_last(blk):
|
||||
self.nr = self.nr ^ 1
|
||||
if is_edc_error(blk):
|
||||
self.send_tpdu(edc_error=1)
|
||||
else:
|
||||
res += i_block_content(blk)
|
||||
break
|
||||
elif is_i_block_more(blk):
|
||||
self.nr = self.nr ^ 1
|
||||
if is_edc_error(blk):
|
||||
self.send_tpdu(edc_error=1)
|
||||
else:
|
||||
res += i_block_content(blk)
|
||||
self.send_tpdu(no_error=1)
|
||||
blk = self.recv_tpdu()
|
||||
return res
|
||||
|
||||
|
||||
class find_class(object):
|
||||
def __init__(self, usb_class):
|
||||
self.__class = usb_class
|
||||
def __call__(self, device):
|
||||
if device.bDeviceClass == self.__class:
|
||||
return True
|
||||
for cfg in device:
|
||||
intf = find_descriptor(cfg, bInterfaceClass=self.__class)
|
||||
if intf is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_ccid_device():
|
||||
ccid = None
|
||||
dev_list = usb.core.find(find_all=True, custom_match=find_class(CCID_CLASS))
|
||||
for dev in dev_list:
|
||||
try:
|
||||
ccid = CardReader(dev)
|
||||
print("CCID device: Bus %03d Device %03d" % (dev.bus, dev.address))
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if not ccid:
|
||||
raise ValueError("No CCID device present")
|
||||
status = ccid.ccid_get_status()
|
||||
if status == 0:
|
||||
# It's ON already
|
||||
atr = ccid.ccid_power_on()
|
||||
elif status == 1:
|
||||
atr = ccid.ccid_power_on()
|
||||
else:
|
||||
raise ValueError("Unknown CCID status", status)
|
||||
return ccid
|
||||
58
tests/card_test_ansix9p256r1.py
Normal file
58
tests/card_test_ansix9p256r1.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
card_test_ansix9p256r1.py - test ansix9p256r1 support
|
||||
|
||||
Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
|
||||
Gnuk is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from func_pso_auth import assert_ec_pso
|
||||
from card_const import *
|
||||
|
||||
class Test_Card_AnsiX9P256R1(object):
|
||||
def test_ECDH_reference_vectors(self, card):
|
||||
assert card.verify(3, FACTORY_PASSPHRASE_PW3)
|
||||
assert card.verify(2, FACTORY_PASSPHRASE_PW1)
|
||||
# https://tools.ietf.org/html/rfc5903#section-8.1
|
||||
assert_ec_pso(
|
||||
card=card,
|
||||
key_index=1,
|
||||
key_attributes=KEY_ATTRIBUTES_ECDH_ANSIX9P256R1,
|
||||
key_attribute_caption='ECDH ansix9p256r1',
|
||||
private_key=(
|
||||
b'\xC8\x8F\x01\xF5\x10\xD9\xAC\x3F\x70\xA2\x92\xDA\xA2\x31\x6D\xE5'
|
||||
b'\x44\xE9\xAA\xB8\xAF\xE8\x40\x49\xC6\x2A\x9C\x57\x86\x2D\x14\x33'
|
||||
),
|
||||
expected_public_key=(
|
||||
b'\x04'
|
||||
b'\xDA\xD0\xB6\x53\x94\x22\x1C\xF9\xB0\x51\xE1\xFE\xCA\x57\x87\xD0'
|
||||
b'\x98\xDF\xE6\x37\xFC\x90\xB9\xEF\x94\x5D\x0C\x37\x72\x58\x11\x80'
|
||||
b'\x52\x71\xA0\x46\x1C\xDB\x82\x52\xD6\x1F\x1C\x45\x6F\xA3\xE5\x9A'
|
||||
b'\xB1\xF4\x5B\x33\xAC\xCF\x5F\x58\x38\x9E\x05\x77\xB8\x99\x0B\xB3'
|
||||
),
|
||||
pso_input=(
|
||||
b'\xa6\x46\x7f\x49\x43\x86\x41'
|
||||
b'\x04'
|
||||
b'\xD1\x2D\xFB\x52\x89\xC8\xD4\xF8\x12\x08\xB7\x02\x70\x39\x8C\x34'
|
||||
b'\x22\x96\x97\x0A\x0B\xCC\xB7\x4C\x73\x6F\xC7\x55\x44\x94\xBF\x63'
|
||||
b'\x56\xFB\xF3\xCA\x36\x6C\xC2\x3E\x81\x57\x85\x4C\x13\xC5\x8D\x6A'
|
||||
b'\xAC\x23\xF0\x46\xAD\xA3\x0F\x83\x53\xE7\x4F\x33\x03\x98\x72\xAB'
|
||||
),
|
||||
expected_pso_output=(
|
||||
b'\xD6\x84\x0F\x6B\x42\xF6\xED\xAF\xD1\x31\x16\xE0\xE1\x25\x65\x20'
|
||||
b'\x2F\xEF\x8E\x9E\xCE\x7D\xCE\x03\x81\x24\x64\xD0\x4B\x94\x42\xDE'
|
||||
),
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user