Compare commits
19 Commits
release/1.
...
release/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2471616f74 | ||
|
|
3926f42647 | ||
|
|
ce070f85ff | ||
|
|
bd02cbfdb0 | ||
|
|
16149ff960 | ||
|
|
c4a5681f35 | ||
|
|
3d5a776ab1 | ||
|
|
9f4671eaf6 | ||
|
|
5af5d18310 | ||
|
|
3765c9233b | ||
|
|
0bd0af1fe1 | ||
|
|
92189e2d12 | ||
|
|
6dcd5aa00c | ||
|
|
09d3068222 | ||
|
|
0f11d320e6 | ||
|
|
365308f374 | ||
|
|
0e510b32c1 | ||
|
|
a9244d9b13 | ||
|
|
c268e59813 |
71
ChangeLog
71
ChangeLog
@@ -1,3 +1,74 @@
|
||||
2015-06-03 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.5.
|
||||
|
||||
* test/ecc_nistp256_keys.py: New.
|
||||
|
||||
* tool/upgrade_by_passwd.py: Remove -p option and add -f option.
|
||||
|
||||
* tool/gnuk_token.py (gnuk_token.download): Add verbose flag.
|
||||
(regnual.download): Ditto.
|
||||
|
||||
* tool/gnuk_upgrade.py: Use gnuk_token module.
|
||||
|
||||
2015-06-02 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Support OpenPGPcard spec v3.0.
|
||||
|
||||
2015-04-20 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* chopstx: Upgrade to 0.05.
|
||||
|
||||
2015-04-19 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/gnuk.h (CCID_CARD_INIT): New.
|
||||
* src/usb_desc.c (gnukConfigDescriptor): Update dwDefaultClock,
|
||||
dwMaximumClock, dwFeatures, and bClassEnvelope.
|
||||
* src/usb_ctrl.c (freq_table): Change the value to 4000MHz.
|
||||
(usb_cb_handle_event): Call ccid_card_change_signal after configure.
|
||||
* src/usb-icc.c (ccid_thread): Change EV_CARD_CHANGE handling.
|
||||
|
||||
2015-04-18 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/main.c (main): Call chopstx_main_init.
|
||||
* src/Makefile.in (DEFS): Remove CHX_PRIO_MAIN.
|
||||
|
||||
2015-04-17 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/configure: Fix shell syntax.
|
||||
|
||||
2015-03-31 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_conf.h (ICC_NUM_INTERFACES, HID_NUM_INTERFACES)
|
||||
(HID_NUM_INTERFACES, VCOM_NUM_INTERFACES, MSC_NUM_INTERFACES)
|
||||
(NUM_INTERFACES): Define here (moved from usb_desc.c).
|
||||
(ICC_INTERFACE, HID_INTERFACE, VCOM_INTERFACE_0, VCOM_INTERFACE_1)
|
||||
(MSC_INTERFACE): New.
|
||||
* src/usb_ctrl.c (gnuk_setup_endpoints_for_interface)
|
||||
(usb_cb_setup, usb_cb_ctrl_write_finish): Use *_INTERFACE.
|
||||
* src/usb_desc.c (gnukConfigDescriptor): Likewise.
|
||||
|
||||
2015-03-06 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/ecc-edwards.c (eddsa_sign_25519): Return 0.
|
||||
|
||||
2015-02-25 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_internal_authenticate): Fix storing to
|
||||
res_APDU_size.
|
||||
|
||||
2015-02-10 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Fix counter update for EdDSA. Thanks
|
||||
to Jonathan Schleifer.
|
||||
|
||||
* src/call-rsa.c (rsa_sign): Don't set res_APDU_len.
|
||||
(rsa_decrypt): Likewise, but get OUTPUT_LEN_P as an argument.
|
||||
|
||||
2015-02-09 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_pso): Fix EdDSA. Use GPG_KEY_FOR_SIGNING.
|
||||
|
||||
2014-12-15 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* VERSION: 1.1.4.
|
||||
|
||||
21
NEWS
21
NEWS
@@ -1,5 +1,26 @@
|
||||
Gnuk NEWS - User visible changes
|
||||
|
||||
* Major changes in Gnuk 1.1.5
|
||||
|
||||
Released 2015-06-03, by NIIBE Yutaka
|
||||
|
||||
** upgrade_by_passwd.py is not so noisy any more.
|
||||
Since it's getting stable, no debug output any more.
|
||||
|
||||
** Maple mini support.
|
||||
Although it's random number generation is not tested, Maple mini
|
||||
support is added.
|
||||
|
||||
** Windows interoperability fix.
|
||||
1.1.x (0 to 4) didn't work with Windows because of INTERRUPT transfer.
|
||||
It's fixed and it works now.
|
||||
|
||||
** OpenPGPcard specification v3.0 compatibility.
|
||||
OpenPGPcard specification v3.0 now include NIST curves (and other
|
||||
curves) and ECDSA and ECDH operations are defined. Gnuk follows
|
||||
this specification.
|
||||
|
||||
|
||||
* Major changes in Gnuk 1.1.4
|
||||
|
||||
Released 2014-12-15, by NIIBE Yutaka
|
||||
|
||||
21
README
21
README
@@ -1,14 +1,14 @@
|
||||
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
|
||||
|
||||
Version 1.1.4
|
||||
2014-12-15
|
||||
Version 1.1.5
|
||||
2015-06-03
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
Warning
|
||||
=======
|
||||
|
||||
This is another experimental release of Gnuk, version 1.1.4, which has
|
||||
This is another experimental release of Gnuk, version 1.1.5, which has
|
||||
incompatible changes to Gnuk 1.0.x. Specifically, it now supports
|
||||
overriding key import, but importing keys (or generating keys) results
|
||||
password reset. Please update your documentation for Gnuk Token, so
|
||||
@@ -25,7 +25,7 @@ What's Gnuk?
|
||||
============
|
||||
|
||||
Gnuk is an implementation of USB cryptographic token for GNU Privacy
|
||||
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
|
||||
Guard. Gnuk supports OpenPGP card protocol version 3, and it runs on
|
||||
STM32F103 processor.
|
||||
|
||||
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
|
||||
@@ -544,11 +544,11 @@ See doc/note/firmware-update.
|
||||
Git Repositories
|
||||
================
|
||||
|
||||
Please use: http://gitorious.org/gnuk
|
||||
Please use: https://anonscm.debian.org/cgit/gnuk/gnuk/
|
||||
|
||||
You can get it by:
|
||||
|
||||
$ git clone git://gitorious.org/gnuk/gnuk.git
|
||||
$ git clone git://anonscm.debian.org/gnuk/gnuk/gnuk.git
|
||||
|
||||
It's also available at: www.gniibe.org
|
||||
You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
|
||||
@@ -570,6 +570,14 @@ Information on the Web
|
||||
|
||||
Please visit: http://www.fsij.org/gnuk/
|
||||
|
||||
Please see the FST-01 support pages:
|
||||
|
||||
http://www.gniibe.org/category/fst-01.html
|
||||
|
||||
Please consider to join Gnuk-users mailing list:
|
||||
|
||||
https://lists.alioth.debian.org/mailman/listinfo/gnuk-users
|
||||
|
||||
|
||||
Your Contributions
|
||||
==================
|
||||
@@ -580,5 +588,6 @@ to FSIJ (if possible).
|
||||
|
||||
Foot note
|
||||
==========
|
||||
|
||||
* NUK(R) is a registered trademark owend by MAPA GmbH, Germany.
|
||||
--
|
||||
|
||||
3
THANKS
3
THANKS
@@ -8,6 +8,7 @@ encouraging the development, testing the implementation, suggesting
|
||||
improvements, or fixing bugs. Here is a list of those people.
|
||||
|
||||
Achim Pietig achim@pietig.com
|
||||
Aidan Thornton
|
||||
Andre Zepezauer andre.zepezauer@student.uni-halle.de
|
||||
Hironobu SUZUKI hironobu@h2np.net
|
||||
Jan Suhr jan@suhr.info
|
||||
@@ -17,7 +18,9 @@ Luis Felipe R. Murillo luisfelipe@ucla.edu
|
||||
MATSUU Takuto matsuu@gentoo.org
|
||||
NAGAMI Takeshi nagami-takeshi@aist.go.jp
|
||||
Nguyễn Hồng Quân quannguyen@mbm.vn
|
||||
NOKUBI Takatsugu knok@daionet.gr.jp
|
||||
Paul Bakker polarssl_maintainer@polarssl.org
|
||||
Shane Coughlan scoughlan@openinventionnetwork.com
|
||||
Vasily Evseenko
|
||||
Werner Koch wk@gnupg.org
|
||||
Yuji Imai ug@xcast.jp
|
||||
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: 23893d9b73...fc26cf0889
@@ -1,8 +1,8 @@
|
||||
==========================
|
||||
GnuPG settings for GNOME 3
|
||||
==========================
|
||||
===========================================
|
||||
GnuPG settings for GNOME 3.1x and GNOME 3.0
|
||||
===========================================
|
||||
|
||||
In the article `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
|
||||
In the section `GnuPG settings`_, I wrote how I disable GNOME-keyrings for SSH.
|
||||
|
||||
It was for GNOME 2. The old days was good, we just disabled GNOME-keyrings
|
||||
interference to SSH and customizing our desktop was easy for GNU and UNIX users.
|
||||
@@ -10,29 +10,33 @@ interference to SSH and customizing our desktop was easy for GNU and UNIX users.
|
||||
.. _GnuPG settings: gpg-settings
|
||||
|
||||
|
||||
GNOME keyrings in GNOME 3
|
||||
=========================
|
||||
GNOME keyrings in GNOME 3.1x
|
||||
============================
|
||||
|
||||
It seems that it is more integrated into the desktop.
|
||||
It is difficult to kill it. It would be possible to kill it simply,
|
||||
but then, I can't use, say, wi-fi access (which needs to access "secrets")
|
||||
any more.
|
||||
In the files /etc/xdg/autostart/gnome-keyring-ssh.desktop
|
||||
and /etc/xdg/autostart/gnome-keyring-gpg.desktop,
|
||||
we have a line something like: ::
|
||||
|
||||
We can't use GNOME configuration tool to disable interference by
|
||||
GNOME keyrings any more. It seems that desktop should not have
|
||||
customization these days.
|
||||
OnlyShowIn=GNOME;Unity;MATE;
|
||||
|
||||
Please edit this line to: ::
|
||||
|
||||
OnlyShowIn=
|
||||
|
||||
Then, no desktop environment invokes gnome-keyring for ssh and gpg. I think that it is The Right Thing.
|
||||
|
||||
|
||||
GNOME-SESSION-PROPERTIES
|
||||
========================
|
||||
GNOME keyrings in GNOME 3.0 by GNOME-SESSION-PROPERTIES
|
||||
=======================================================
|
||||
|
||||
After struggling some hours, I figured out it is GNOME-SESSION-PROPERTIES
|
||||
to disable the interference. Invoking::
|
||||
We can't use GNOME configuration tool (like GNOME 2) to disable interference by
|
||||
GNOME keyrings in GNOME 3.0.
|
||||
|
||||
It is GNOME-SESSION-PROPERTIES to disable the interference. Invoking::
|
||||
|
||||
$ gnome-session-properties
|
||||
|
||||
and at the tab of "Startup Programs", I removed radio check buttons
|
||||
for "GPG Password Agent" and "SSH Key Agent".
|
||||
|
||||
|
||||
Now, I use gpg-agent for GnuPG Agent and SSH agent with Gnuk Token.
|
||||
Then, I can use proper gpg-agent for GnuPG Agent Service and SSH Agent Service with Gnuk Token in GNOME 3.0.
|
||||
|
||||
@@ -5,174 +5,14 @@ Key import from PC to Gnuk Token (no removal)
|
||||
This document describes how I put my **keys on PC** to the Token
|
||||
without removing keys from PC.
|
||||
|
||||
The difference is just not-to-save changes after key imports.
|
||||
The difference is only the last step.
|
||||
I don't save changes on PC after keytocard.
|
||||
|
||||
After personalization, I put my keys into the Token.
|
||||
For the steps before the last step, please see `keytocard with removing keys on PC`_.
|
||||
|
||||
Here is the log.
|
||||
.. _keytocard removing keys: gnuk-keytocard
|
||||
|
||||
I invoke GnuPG with my key (4ca7babe) and with ``--homedir`` option
|
||||
to specify the directory which contains my secret keys. ::
|
||||
|
||||
$ gpg --homedir=/home/gniibe/tmp/gnuk-testing-dir --edit-key 4ca7babe
|
||||
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
|
||||
Secret key is available.
|
||||
|
||||
pub 2048R/4CA7BABE created: 2010-10-15 expires: never usage: SC
|
||||
trust: ultimate validity: ultimate
|
||||
sub 2048R/084239CF created: 2010-10-15 expires: never usage: E
|
||||
sub 2048R/5BB065DC created: 2010-10-22 expires: never usage: A
|
||||
[ultimate] (1). NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
|
||||
Then, GnuPG enters its own command interaction mode. The prompt is ``gpg>``.
|
||||
To enable ``keytocard`` command, I type ``toggle`` command. ::
|
||||
|
||||
gpg> toggle
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
Firstly, I import my primary key into Gnuk Token.
|
||||
I type ``keytocard`` command, answer ``y`` to confirm keyimport,
|
||||
and type ``1`` to say it's signature key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Really move the primary key? (y/N) y
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(1) Signature key
|
||||
(3) Authentication key
|
||||
Your selection? 1
|
||||
|
||||
Then, GnuPG asks two passwords. One is the passphrase of **keys on PC**
|
||||
and another is the password of **Gnuk Token**. Note that the password of
|
||||
the token and the password of the keys on PC are different things,
|
||||
although they can be same.
|
||||
|
||||
Here, I assume that Gnuk Token's admin password of factory setting (12345678).
|
||||
|
||||
I enter these passwords. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 4CA7BABE, created 2010-10-15
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
gpg: 3 Admin PIN attempts remaining before card is permanently locked
|
||||
|
||||
Please enter the Admin PIN
|
||||
Enter Admin PIN: 12345678
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The primary key is now on the Token and GnuPG says its card-no (F517 00000001),
|
||||
where F517 is the vendor ID of FSIJ.
|
||||
|
||||
Secondly, I import my subkey of encryption. I select key number '1'. ::
|
||||
|
||||
gpg> key 1
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/084239CF created: 2010-10-15 expires: never
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
You can see that the subkey is marked by '*'.
|
||||
I type ``keytocard`` command to import this subkey to Gnuk Token.
|
||||
I select ``2`` as it's encryption key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(2) Encryption key
|
||||
Your selection? 2
|
||||
|
||||
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 084239CF, created 2010-10-15
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The sub key is now on the Token and GnuPG says its card-no for it.
|
||||
|
||||
I type ``key 1`` to deselect key number '1'. ::
|
||||
|
||||
gpg> key 1
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
Thirdly, I select sub key of authentication which has key number '2'. ::
|
||||
|
||||
gpg> key 2
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
You can see that the subkey number '2' is marked by '*'.
|
||||
I type ``keytocard`` command to import this subkey to Gnuk Token.
|
||||
I select ``3`` as it's authentication key. ::
|
||||
|
||||
gpg> keytocard
|
||||
Signature key ....: [none]
|
||||
Encryption key....: [none]
|
||||
Authentication key: [none]
|
||||
|
||||
Please select where to store the key:
|
||||
(3) Authentication key
|
||||
Your selection? 3
|
||||
|
||||
Then, GnuPG asks the passphrase of **keys on PC** again. I enter. ::
|
||||
|
||||
You need a passphrase to unlock the secret key for
|
||||
user: "NIIBE Yutaka <gniibe@fsij.org>"
|
||||
2048-bit RSA key, ID 5BB065DC, created 2010-10-22
|
||||
<PASSWORD-KEY-4CA7BABE>
|
||||
gpg: writing new key
|
||||
|
||||
sec 2048R/4CA7BABE created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb 2048R/084239CF created: 2010-10-15 expires: never
|
||||
card-no: F517 00000001
|
||||
ssb* 2048R/5BB065DC created: 2010-10-22 expires: never
|
||||
card-no: F517 00000001
|
||||
(1) NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
The sub key is now on the Token and GnuPG says its card-no for it.
|
||||
Here is the session log of the last step.
|
||||
|
||||
Lastly, I quit GnuPG. Note that I **don't** save changes. ::
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ See `another document`_ to import keys to the Token from copied directory.
|
||||
|
||||
After personalization, I put my keys into the Token.
|
||||
|
||||
Here is the log.
|
||||
Here is the session log.
|
||||
|
||||
I invoke GnuPG with my key (4ca7babe). ::
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ For GnuPG 2.0.x, gpg-agent is always used, so there is no need to specify the ``
|
||||
Let gpg-agent manage SSH key
|
||||
============================
|
||||
|
||||
I deactivate seahose-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
|
||||
I deactivate seahorse-agent. Also, for GNOME 2, I deactivate gnome-keyring managing SSH key. ::
|
||||
|
||||
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ I have three keys in my token.
|
||||
With the script below, I extract public key of the keygrip
|
||||
5D6C89682D07CCFC034AF508420BF2276D8018ED into the file: 5D6C8968.bin::
|
||||
|
||||
$ ./get_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
||||
$ ./get_raw_public_key.py 5D6C89682D07CCFC034AF508420BF2276D8018ED
|
||||
|
||||
Here is the script, get_public_key.py::
|
||||
Here is the script, get_raw_public_key.py::
|
||||
|
||||
#! /usr/bin/python
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ OBJCOPY = $(CROSS)objcopy
|
||||
MCU = cortex-m3
|
||||
CWARN = -Wall -Wextra -Wstrict-prototypes
|
||||
# DEFS: Add
|
||||
DEFS = -DCHX_PRIO_MAIN=5 @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
DEFS = @KEYGEN_SUPPORT@ @HAVE_SYS_H@
|
||||
OPT = -O3 -Os -g
|
||||
LIBS =
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU_size = pubkey_len;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
@@ -120,14 +119,13 @@ modulus_calc (const uint8_t *p, int len)
|
||||
|
||||
int
|
||||
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
struct key_data *kd)
|
||||
struct key_data *kd, unsigned int *output_len_p)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int ret;
|
||||
unsigned int output_len;
|
||||
|
||||
DEBUG_INFO ("RSA decrypt:");
|
||||
DEBUG_WORD ((uint32_t)&output_len);
|
||||
DEBUG_WORD ((uint32_t)&ret);
|
||||
|
||||
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
||||
mpi_init (&P1); mpi_init (&Q1); mpi_init (&H);
|
||||
@@ -154,7 +152,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
{
|
||||
DEBUG_INFO ("RSA decrypt ...");
|
||||
ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
|
||||
RSA_PRIVATE, &output_len, input,
|
||||
RSA_PRIVATE, output_len_p, input,
|
||||
output, MAX_RES_APDU_DATA_SIZE);
|
||||
}
|
||||
|
||||
@@ -167,7 +165,6 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU_size = output_len;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
|
||||
11
src/configure
vendored
11
src/configure
vendored
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
|
||||
#
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
# Free Software Initiative of Japan
|
||||
#
|
||||
# This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -66,13 +66,13 @@ for option; do
|
||||
--disable-keygen)
|
||||
keygen=no ;;
|
||||
--enable-sys1-compat)
|
||||
sys1_compat = yes ;;
|
||||
sys1_compat=yes ;;
|
||||
--disable-sys1-compat)
|
||||
sys1_compat = no ;;
|
||||
sys1_compat=no ;;
|
||||
--enable-hid-card-change)
|
||||
hid_card_change = yes ;;
|
||||
hid_card_change=yes ;;
|
||||
--disable-hid-card-change)
|
||||
hid_card_change = no ;;
|
||||
hid_card_change=no ;;
|
||||
--with-dfu)
|
||||
with_dfu=yes ;;
|
||||
--without-dfu)
|
||||
@@ -100,6 +100,7 @@ Configuration:
|
||||
OLIMEX_STM32_H103
|
||||
STBEE
|
||||
STBEE_MINI
|
||||
MAPLE_MINI
|
||||
FST_01_00 (unreleased version with 8MHz XTAL)
|
||||
--enable-debug debug with virtual COM port [no]
|
||||
--enable-pinpad=cir
|
||||
|
||||
@@ -660,7 +660,7 @@ mod_reduce_M (bn256 *R, const bn512 *A)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
int
|
||||
eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
|
||||
const bn256 *a, const uint8_t *seed, const bn256 *pk)
|
||||
{
|
||||
@@ -704,6 +704,8 @@ eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
|
||||
bn256_add (s, s, M);
|
||||
else
|
||||
bn256_add (tmp, s, M);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -62,6 +62,8 @@ enum icc_state {
|
||||
ICC_STATE_EXEC_REQUESTED, /* Exec requested */
|
||||
};
|
||||
|
||||
#define CCID_CARD_INIT CARD_CHANGE_INSERT
|
||||
|
||||
extern enum icc_state *icc_state_p;
|
||||
|
||||
extern volatile uint8_t auth_status;
|
||||
@@ -256,7 +258,8 @@ void put_binary (const char *s, int len);
|
||||
|
||||
int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
|
||||
uint8_t *modulus_calc (const uint8_t *, int);
|
||||
int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *);
|
||||
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);
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* main.c - main routine of Gnuk
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2015
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -290,6 +291,7 @@ const size_t __stacksize_usb = (size_t)&__process4_stack_size__;
|
||||
|
||||
#define PRIO_CCID 3
|
||||
#define PRIO_USB 4
|
||||
#define PRIO_MAIN 5
|
||||
|
||||
extern void *usb_intr (void *arg);
|
||||
|
||||
@@ -343,6 +345,8 @@ main (int argc, char *argv[])
|
||||
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
|
||||
usb_intr, NULL);
|
||||
|
||||
chopstx_main_init (PRIO_MAIN);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bDeviceState != UNCONNECTED)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014
|
||||
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
|
||||
* Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
@@ -812,6 +812,8 @@ cmd_get_data (void)
|
||||
#define EDDSA_HASH_LEN_MAX 256
|
||||
#define EDDSA_SIGNATURE_LENGTH 64
|
||||
|
||||
#define ECC_CIPHER_DO_HEADER_SIZE 7
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
@@ -819,6 +821,7 @@ cmd_pso (void)
|
||||
int r = -1;
|
||||
int attr;
|
||||
int pubkey_len;
|
||||
unsigned int result_len = 0;
|
||||
|
||||
DEBUG_INFO (" - PSO: ");
|
||||
DEBUG_WORD ((uint32_t)&r);
|
||||
@@ -855,13 +858,9 @@ cmd_pso (void)
|
||||
|
||||
DEBUG_BINARY (kd[GPG_KEY_FOR_SIGNING].data, pubkey_len);
|
||||
|
||||
result_len = pubkey_len;
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_SIGNING], pubkey_len);
|
||||
if (r < 0)
|
||||
ac_reset_pso_cds ();
|
||||
else
|
||||
/* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
@@ -873,19 +872,13 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
else /* ALGO_SECP256K1 */
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_SIGNING].data);
|
||||
if (r < 0)
|
||||
ac_reset_pso_cds ();
|
||||
else
|
||||
{ /* Success */
|
||||
gpg_increment_digital_signature_counter ();
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
}
|
||||
}
|
||||
else if (attr == ALGO_ED25519)
|
||||
{
|
||||
@@ -898,13 +891,27 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = EDDSA_SIGNATURE_LENGTH;
|
||||
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);
|
||||
kd[GPG_KEY_FOR_SIGNING].data,
|
||||
kd[GPG_KEY_FOR_SIGNING].data+32,
|
||||
kd[GPG_KEY_FOR_SIGNING].pubkey);
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("unknown algo.");
|
||||
GPG_FUNCTION_NOT_SUPPORTED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
res_APDU_size = result_len;
|
||||
gpg_increment_digital_signature_counter ();
|
||||
}
|
||||
else /* Failure */
|
||||
ac_reset_pso_cds ();
|
||||
}
|
||||
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
|
||||
{
|
||||
@@ -931,27 +938,41 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_DECRYPTION]);
|
||||
&kd[GPG_KEY_FOR_DECRYPTION], &result_len);
|
||||
}
|
||||
else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
|
||||
{
|
||||
int header_size = -1;
|
||||
|
||||
if (len == 65)
|
||||
header_size = 0;
|
||||
else if (len == 65 + ECC_CIPHER_DO_HEADER_SIZE)
|
||||
header_size = ECC_CIPHER_DO_HEADER_SIZE;
|
||||
|
||||
/* Format is in big endian MPI: 04 || x || y */
|
||||
if (len != 65 || apdu.cmd_apdu_data[0] != 4)
|
||||
if (header_size < 0 || apdu.cmd_apdu_data[header_size] != 4)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = 65;
|
||||
if (attr == ALGO_NISTP256R1)
|
||||
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
r = ecdh_decrypt_p256r1 (apdu.cmd_apdu_data + header_size, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
else
|
||||
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
r = ecdh_decrypt_p256k1 (apdu.cmd_apdu_data + header_size, res_APDU,
|
||||
kd[GPG_KEY_FOR_DECRYPTION].data);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("unknown algo.");
|
||||
GPG_FUNCTION_NOT_SUPPORTED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == 0)
|
||||
res_APDU_size = 65;
|
||||
}
|
||||
res_APDU_size = result_len;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
@@ -976,6 +997,7 @@ cmd_internal_authenticate (void)
|
||||
GPG_KEY_PUBLIC);
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r = -1;
|
||||
unsigned int result_len = 0;
|
||||
|
||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||
|
||||
@@ -1006,6 +1028,7 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
result_len = pubkey_len;
|
||||
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||
&kd[GPG_KEY_FOR_AUTHENTICATION], pubkey_len);
|
||||
}
|
||||
@@ -1018,7 +1041,7 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
}
|
||||
@@ -1031,7 +1054,7 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = ECDSA_SIGNATURE_LENGTH;
|
||||
result_len = ECDSA_SIGNATURE_LENGTH;
|
||||
r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU,
|
||||
kd[GPG_KEY_FOR_AUTHENTICATION].data);
|
||||
}
|
||||
@@ -1046,7 +1069,7 @@ cmd_internal_authenticate (void)
|
||||
return;
|
||||
}
|
||||
|
||||
res_APDU_size = EDDSA_SIGNATURE_LENGTH;
|
||||
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,
|
||||
@@ -1054,7 +1077,9 @@ cmd_internal_authenticate (void)
|
||||
memcpy (res_APDU, output, EDDSA_SIGNATURE_LENGTH);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
if (r == 0)
|
||||
res_APDU_size = result_len;
|
||||
else
|
||||
GPG_ERROR ();
|
||||
|
||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||
|
||||
@@ -139,6 +139,7 @@ static uint8_t icc_buffer[USB_BUF_SIZE];
|
||||
#define ICC_SLOT_STATUS 0x65 /* non-ICCD command */
|
||||
#define ICC_SECURE 0x69 /* non-ICCD command */
|
||||
#define ICC_GET_PARAMS 0x6C /* non-ICCD command */
|
||||
#define ICC_RESET_PARAMS 0x6D /* non-ICCD command */
|
||||
#define ICC_XFR_BLOCK 0x6F
|
||||
#define ICC_DATA_BLOCK_RET 0x80
|
||||
#define ICC_SLOT_STATUS_RET 0x81 /* non-ICCD result */
|
||||
@@ -253,7 +254,7 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo,
|
||||
{
|
||||
icc_state_p = &c->icc_state;
|
||||
|
||||
c->icc_state = ICC_STATE_START;
|
||||
c->icc_state = ICC_STATE_NOCARD;
|
||||
c->state = APDU_STATE_WAIT_COMMAND;
|
||||
/*
|
||||
* Note: a is not yet initialized yet, we can't use c->a->cmd_apdu_data here.
|
||||
@@ -1178,7 +1179,8 @@ icc_handle_data (struct ccid *c)
|
||||
}
|
||||
}
|
||||
else if (c->icc_header.msg_type == ICC_SET_PARAMS
|
||||
|| c->icc_header.msg_type == ICC_GET_PARAMS)
|
||||
|| c->icc_header.msg_type == ICC_GET_PARAMS
|
||||
|| c->icc_header.msg_type == ICC_RESET_PARAMS)
|
||||
icc_send_params (c);
|
||||
else if (c->icc_header.msg_type == ICC_SECURE)
|
||||
{
|
||||
@@ -1297,6 +1299,8 @@ icc_handle_timeout (struct ccid *c)
|
||||
return next_state;
|
||||
}
|
||||
|
||||
static struct ccid ccid;
|
||||
|
||||
/*
|
||||
* Another Tx done callback
|
||||
*/
|
||||
@@ -1308,8 +1312,6 @@ EP2_IN_Callback (void)
|
||||
|
||||
#define USB_ICC_TIMEOUT (1950*1000)
|
||||
|
||||
static struct ccid ccid;
|
||||
|
||||
#define GPG_THREAD_TERMINATED 0xffff
|
||||
|
||||
static void *ccid_thread (chopstx_t) __attribute__ ((noinline));
|
||||
@@ -1336,6 +1338,8 @@ ccid_card_change_signal (int how)
|
||||
}
|
||||
|
||||
|
||||
#define NOTIFY_SLOT_CHANGE 0x50
|
||||
|
||||
static void * __attribute__ ((noinline))
|
||||
ccid_thread (chopstx_t thd)
|
||||
{
|
||||
@@ -1343,7 +1347,9 @@ ccid_thread (chopstx_t thd)
|
||||
struct ep_out *epo = &endpoint_out;
|
||||
struct ccid *c = &ccid;
|
||||
struct apdu *a = &apdu;
|
||||
int card_change_requested = 0;
|
||||
uint8_t int_msg[2];
|
||||
|
||||
int_msg[0] = NOTIFY_SLOT_CHANGE;
|
||||
|
||||
epi_init (epi, ENDP1, notify_tx, c);
|
||||
epo_init (epo, ENDP1, notify_icc, c);
|
||||
@@ -1359,19 +1365,13 @@ ccid_thread (chopstx_t thd)
|
||||
|
||||
if (m == EV_CARD_CHANGE)
|
||||
{
|
||||
if (card_change_requested)
|
||||
{
|
||||
uint8_t notify_slot_change[2] = { 0x50, 0x02 };
|
||||
|
||||
led_blink (LED_TWOSHOTS);
|
||||
|
||||
if (c->icc_state == ICC_STATE_NOCARD)
|
||||
{ /* Inserted! */
|
||||
c->icc_state = ICC_STATE_START;
|
||||
notify_slot_change[1] |= 1;
|
||||
int_msg[1] = 0x03;
|
||||
}
|
||||
else
|
||||
{
|
||||
{ /* Removed! */
|
||||
if (c->application)
|
||||
{
|
||||
eventflag_signal (&c->openpgp_comm, EV_EXIT);
|
||||
@@ -1380,13 +1380,11 @@ ccid_thread (chopstx_t thd)
|
||||
}
|
||||
|
||||
c->icc_state = ICC_STATE_NOCARD;
|
||||
int_msg[1] = 0x02;
|
||||
}
|
||||
|
||||
card_change_requested = 0;
|
||||
usb_lld_write (ENDP2, notify_slot_change, 2);
|
||||
}
|
||||
else
|
||||
card_change_requested = 1;
|
||||
usb_lld_write (ENDP2, int_msg, sizeof int_msg);
|
||||
led_blink (LED_TWOSHOTS);
|
||||
}
|
||||
else if (m == EV_RX_DATA_READY)
|
||||
c->icc_state = icc_handle_data (c);
|
||||
@@ -1444,10 +1442,7 @@ ccid_thread (chopstx_t thd)
|
||||
icc_prepare_receive (c);
|
||||
}
|
||||
else /* Timeout */
|
||||
{
|
||||
c->icc_state = icc_handle_timeout (c);
|
||||
card_change_requested = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->application)
|
||||
|
||||
@@ -4,6 +4,29 @@
|
||||
#define __USB_CONF_H
|
||||
|
||||
#define NUM_STRING_DESC 7
|
||||
#define ICC_NUM_INTERFACES 1
|
||||
#define ICC_INTERFACE 0
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_NUM_INTERFACES 1
|
||||
#define HID_INTERFACE 1
|
||||
#else
|
||||
#define HID_NUM_INTERFACES 0
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#define VCOM_INTERFACE_0 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES)
|
||||
#define VCOM_INTERFACE_1 (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + 1)
|
||||
#else
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#define MSC_INTERFACE (ICC_NUM_INTERFACES + HID_NUM_INTERFACES + VCOM_NUM_INTERFACES)
|
||||
#else
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
|
||||
|
||||
#if defined(USB_SELF_POWERED)
|
||||
#define USB_INITIAL_FEATURE 0xC0 /* bmAttributes: self powered */
|
||||
|
||||
@@ -103,22 +103,12 @@ vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
|
||||
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#else
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#include "usb-msc.h"
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#else
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#define NUM_INTERFACES (2+VCOM_NUM_INTERFACES+MSC_NUM_INTERFACES)
|
||||
#define MSC_INTERFACE_NO (2+VCOM_NUM_INTERFACES)
|
||||
|
||||
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
|
||||
#define USB_HID_REQ_GET_REPORT 1
|
||||
@@ -142,7 +132,7 @@ static uint16_t hid_report;
|
||||
static void
|
||||
gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
{
|
||||
if (interface == 0)
|
||||
if (interface == ICC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
@@ -158,7 +148,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (interface == 1)
|
||||
else if (interface == HID_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP7, EP_INTERRUPT, 0, 0, ENDP7_TXADDR, 0);
|
||||
@@ -167,14 +157,14 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (interface == 2)
|
||||
else if (interface == VCOM_INTERFACE_0)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP4, EP_INTERRUPT, 0, 0, ENDP4_TXADDR, 0);
|
||||
else
|
||||
usb_lld_stall_tx (ENDP4);
|
||||
}
|
||||
else if (interface == 3)
|
||||
else if (interface == VCOM_INTERFACE_1)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
@@ -190,7 +180,7 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
|
||||
}
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (interface == MSC_INTERFACE_NO)
|
||||
else if (interface == MSC_INTERFACE)
|
||||
{
|
||||
if (!stop)
|
||||
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
|
||||
@@ -231,8 +221,7 @@ usb_cb_device_reset (void)
|
||||
#define USB_CCID_REQ_GET_CLOCK_FREQUENCIES 0x02
|
||||
#define USB_CCID_REQ_GET_DATA_RATES 0x03
|
||||
|
||||
static const uint8_t freq_table[] = { 0xf3, 0x0d, 0, 0, }; /* dwDefaultClock */
|
||||
|
||||
static const uint8_t freq_table[] = { 0xa0, 0x0f, 0, 0, }; /* dwDefaultClock */
|
||||
static const uint8_t data_rate_table[] = { 0x80, 0x25, 0, 0, }; /* dwDataRate */
|
||||
|
||||
#if defined(PINPAD_DND_SUPPORT)
|
||||
@@ -328,7 +317,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == 0)
|
||||
if (index == ICC_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
{
|
||||
@@ -353,7 +342,7 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
}
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (index == 1)
|
||||
else if (index == HID_INTERFACE)
|
||||
{
|
||||
switch (req_no)
|
||||
{
|
||||
@@ -386,11 +375,11 @@ usb_cb_setup (uint8_t req, uint8_t req_no,
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
else if (index == 2)
|
||||
else if (index == VCOM_INTERFACE_0)
|
||||
return vcom_port_data_setup (req, req_no, value);
|
||||
#endif
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
else if (index == MSC_INTERFACE_NO)
|
||||
else if (index == MSC_INTERFACE)
|
||||
{
|
||||
if (USB_SETUP_GET (req))
|
||||
{
|
||||
@@ -433,7 +422,7 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
{
|
||||
if (index == 1 && req_no == USB_HID_REQ_SET_REPORT)
|
||||
if (index == HID_INTERFACE && req_no == USB_HID_REQ_SET_REPORT)
|
||||
{
|
||||
if ((hid_report ^ hid_report_saved) & HID_LED_STATUS_CARDCHANGE)
|
||||
ccid_card_change_signal (CARD_CHANGE_TOGGLE);
|
||||
@@ -465,6 +454,7 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
|
||||
usb_lld_set_configuration (value);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (i, 0);
|
||||
ccid_card_change_signal (CCID_CARD_INIT);
|
||||
bDeviceState = CONFIGURED;
|
||||
}
|
||||
else if (current_conf != value)
|
||||
|
||||
@@ -75,37 +75,27 @@ static const uint8_t gnukDeviceDescriptor[] = {
|
||||
};
|
||||
|
||||
#define ICC_TOTAL_LENGTH (9+9+54+7+7+7)
|
||||
#define ICC_NUM_INTERFACES 1
|
||||
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
#define HID_TOTAL_LENGTH (9+9+7)
|
||||
#define HID_NUM_INTERFACES 1
|
||||
#else
|
||||
#define HID_TOTAL_LENGTH 0
|
||||
#define HID_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
#define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
|
||||
#define VCOM_NUM_INTERFACES 2
|
||||
#else
|
||||
#define VCOM_TOTAL_LENGTH 0
|
||||
#define VCOM_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#ifdef PINPAD_DND_SUPPORT
|
||||
#define MSC_TOTAL_LENGTH (9+7+7)
|
||||
#define MSC_NUM_INTERFACES 1
|
||||
#else
|
||||
#define MSC_TOTAL_LENGTH 0
|
||||
#define MSC_NUM_INTERFACES 0
|
||||
#endif
|
||||
|
||||
#define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH \
|
||||
+ VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
|
||||
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
|
||||
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
|
||||
|
||||
|
||||
|
||||
/* Configuation Descriptor */
|
||||
@@ -122,7 +112,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0, /* bInterfaceNumber: Index of this interface */
|
||||
ICC_INTERFACE, /* bInterfaceNumber: Index of this interface */
|
||||
0, /* Alternate setting for this interface */
|
||||
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
|
||||
USB_ICC_INTERFACE_CLASS,
|
||||
@@ -135,42 +125,36 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
0x21, /* bDescriptorType: USBDESCR_ICC */
|
||||
0x10, 0x01, /* bcdCCID: revision 1.1 (of CCID) */
|
||||
0, /* bMaxSlotIndex: */
|
||||
1, /* bVoltageSupport: FIXED VALUE */
|
||||
1, /* bVoltageSupport: 5V-only */
|
||||
0x02, 0, 0, 0, /* dwProtocols: T=1 */
|
||||
0xf3, 0x0d, 0, 0, /* dwDefaultClock: 3571 (non-ICCD): 3580 (ICCD) */
|
||||
0xf3, 0x0d, 0, 0, /* dwMaximumClock: 3571 (non-ICCD): 3580 (ICCD) */
|
||||
1, /* bNumClockSupported: FIXED VALUE */
|
||||
0x80, 0x25, 0, 0, /* dwDataRate: 9600: FIXED VALUE */
|
||||
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600: FIXED VALUE */
|
||||
1, /* bNumDataRateSupported: FIXED VALUE */
|
||||
0xa0, 0x0f, 0, 0, /* dwDefaultClock: 4000 */
|
||||
0xa0, 0x0f, 0, 0, /* dwMaximumClock: 4000 */
|
||||
0, /* bNumClockSupported: 0x00 */
|
||||
0x80, 0x25, 0, 0, /* dwDataRate: 9600 */
|
||||
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600 */
|
||||
0, /* bNumDataRateSupported: 0x00 */
|
||||
0xfe, 0, 0, 0, /* dwMaxIFSD: 254 */
|
||||
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
|
||||
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
|
||||
/*
|
||||
* According to Specification for USB ICCD (revision 1.0),
|
||||
* dwFeatures should be 0x00040840.
|
||||
*
|
||||
* It is different now for better interaction to GPG's in-stock
|
||||
* ccid-driver.
|
||||
*/
|
||||
0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
|
||||
0, 0, 0, 0, /* dwSynchProtocols: 0 */
|
||||
0, 0, 0, 0, /* dwMechanical: 0 */
|
||||
0x7a, 0x04, 0x02, 0x00, /* dwFeatures:
|
||||
* Short and extended APDU level: 0x40000 ----
|
||||
* Short APDU level : 0x20000 *
|
||||
* (what? means ICCD?) : 0x00800 *
|
||||
* Automatic IFSD : 0x00400
|
||||
* (ICCD?) : 0x00800 ----
|
||||
* Automatic IFSD : 0x00400 *
|
||||
* NAD value other than 0x00 : 0x00200
|
||||
* Can set ICC in clock stop : 0x00100
|
||||
* Automatic PPS CUR : 0x00080
|
||||
* Automatic PPS PROP : 0x00040 *
|
||||
* Auto baud rate change : 0x00020
|
||||
* Auto clock change : 0x00010
|
||||
* Auto voltage selection : 0x00008
|
||||
* Auto baud rate change : 0x00020 *
|
||||
* Auto clock change : 0x00010 *
|
||||
* Auto voltage selection : 0x00008 *
|
||||
* Auto activaction of ICC : 0x00004
|
||||
* Automatic conf. based on ATR : 0x00002 g
|
||||
* Automatic conf. based on ATR : 0x00002 *
|
||||
*/
|
||||
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
|
||||
0xff, /* bClassGetResponse: */
|
||||
0xff, /* bClassEnvelope: */
|
||||
0, 0, /* wLCDLayout: FIXED VALUE */
|
||||
0xff, /* bClassGetResponse: 0xff */
|
||||
0x00, /* bClassEnvelope: 0 */
|
||||
0, 0, /* wLCDLayout: 0 */
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
|
||||
1, /* bPinSupport: with PIN pad (verify) */
|
||||
@@ -200,14 +184,14 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
0x82, /* bEndpointAddress: (IN2) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
4, 0x00, /* wMaxPacketSize: */
|
||||
0x04, 0x00, /* wMaxPacketSize: 4 */
|
||||
0xFF, /* bInterval (255ms) */
|
||||
|
||||
#ifdef HID_CARD_CHANGE_SUPPORT
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
HID_INTERFACE, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoint used */
|
||||
0x03, /* bInterfaceClass: HID */
|
||||
@@ -236,7 +220,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
0x02, /* bInterfaceNumber: Number of Interface */
|
||||
VCOM_INTERFACE_0, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
@@ -247,14 +231,13 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
5, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
0x10, 0x01, /* bcdCDC: spec release number */
|
||||
/*Call Managment Functional Descriptor*/
|
||||
5, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x03, /* bmCapabilities: D0+D1 */
|
||||
0x02, /* bDataInterface: 2 */
|
||||
VCOM_INTERFACE_1, /* bDataInterface */
|
||||
/*ACM Functional Descriptor*/
|
||||
4, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
@@ -264,8 +247,8 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
5, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x01, /* bMasterInterface: Communication class interface */
|
||||
0x02, /* bSlaveInterface0: Data Class Interface */
|
||||
VCOM_INTERFACE_0, /* bMasterInterface: Communication class interface */
|
||||
VCOM_INTERFACE_1, /* bSlaveInterface0: Data Class Interface */
|
||||
/*Endpoint 4 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
|
||||
@@ -277,7 +260,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/*Data class interface descriptor*/
|
||||
9, /* bLength: Endpoint Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
|
||||
0x03, /* bInterfaceNumber: Number of Interface */
|
||||
VCOM_INTERFACE_1, /* bInterfaceNumber: Index of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
@@ -303,11 +286,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
/* Interface Descriptor.*/
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
|
||||
#ifdef ENABLE_VIRTUAL_COM_PORT
|
||||
0x04, /* bInterfaceNumber. */
|
||||
#else
|
||||
0x02, /* bInterfaceNumber. */
|
||||
#endif
|
||||
MSC_INTERFACE, /* bInterfaceNumber. */
|
||||
0x00, /* bAlternateSetting. */
|
||||
0x02, /* bNumEndpoints. */
|
||||
0x08, /* bInterfaceClass (Mass Stprage). */
|
||||
|
||||
31
test/ecc_nistp256_keys.py
Normal file
31
test/ecc_nistp256_keys.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Data taken from:
|
||||
# A. Jivsov, Sample Keys and Messages:
|
||||
# https://sites.google.com/site/brainhub/pgpecckeys
|
||||
|
||||
# uid ec_dsa_dh_256 <openpgp@brainhub.org>
|
||||
# sign key:
|
||||
# nistp256/BAA59D9C 2010-09-17
|
||||
# keygrip: 8E06A180EFFE4C65B812150CAF19BF30C0689A4C
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[0] = (0x0bc7a7baebd5f08c74c77b71ee44e7bb0b5a18317b996da5393e33acc52932c6,
|
||||
0xd2f60f4d1efe35a0b9fb8d3787ed4bee97ca012d07b8f5835be7093545d532e6,
|
||||
0xd8f28c530c99821faa5ee2ff4dd8d1df01995d4e98fb45f8768cb65abd4adaa9)
|
||||
|
||||
# decryption key:
|
||||
# sub nistp256/4089AB73 2010-09-17 nistp256
|
||||
# keygrip: E4403F3FD7A443FAC29FEF288FA0D20AC212851E
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[1] = (0x7f70c0a8184cdcaea5db20ba8fed17e47bdefb744d575ec449130af37edade65,
|
||||
0x8ae7ee35d20e8897911c9f564be33d9a94bc1e5c927b1aa07ff750d2d11c2971,
|
||||
0xa05cd14749bea3f3d14c92dc438e45e351efe860360c431705b7d42410581843)
|
||||
|
||||
# auth key from: uid ec_dsa_dh_256_no_pass <openpgp@brainhub.org>
|
||||
#
|
||||
# q=(x, y) and d
|
||||
key[2] = (0x81fbbc20eea9e8d1c3ceabb0a8185925b113d1ac42cd5c78403bd83da19235c6,
|
||||
0x5ed6db13d91db34507d0129bf88981878d29adbf8fcd1720afdb767bb3fcaaff,
|
||||
0xa355916f8665eb99c1af48d9560b5c6889e5287bc75aa693aaae9bdb15e8b3fd)
|
||||
|
||||
# This file is here to extend the test suite for ECC.
|
||||
@@ -123,15 +123,16 @@ class gnuk_token(object):
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
def download(self, start, data, verbose=False):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x20000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
print("start %08x" % addr)
|
||||
print("end %08x" % addr_end)
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d : %d" % (addr, i, 256)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, 256))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
@@ -141,7 +142,8 @@ class gnuk_token(object):
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, residue))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:],
|
||||
@@ -157,7 +159,7 @@ class gnuk_token(object):
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
print msg
|
||||
print(msg)
|
||||
raise ValueError("icc_get_result")
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
@@ -491,15 +493,16 @@ class regnual(object):
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
def download(self, start, data, verbose=False):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x08000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
print("start %08x" % addr)
|
||||
print("end %08x" % addr_end)
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d: %d : %d" % (addr, i, j, 256)
|
||||
if verbose:
|
||||
print("# %08x: %d: %d : %d" % (addr, i, j, 256))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
@@ -510,7 +513,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
print("failure")
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
@@ -521,13 +524,14 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
print("failure")
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
if verbose:
|
||||
print("# %08x: %d : %d" % (addr, i, residue))
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:],
|
||||
@@ -538,7 +542,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
print("failure")
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
@@ -549,7 +553,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
print("failure")
|
||||
|
||||
def protect(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 4,
|
||||
@@ -561,7 +565,7 @@ class regnual(object):
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "protection failure"
|
||||
print("protection failure")
|
||||
|
||||
def finish(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
|
||||
@@ -611,9 +615,9 @@ def get_gnuk_device():
|
||||
for (dev, config, intf) in gnuk_devices():
|
||||
try:
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
print "Device: ", dev.filename
|
||||
print "Configuration: ", config.value
|
||||
print "Interface: ", intf.interfaceNumber
|
||||
print("Device: %s" % dev.filename)
|
||||
print("Configuration: %d" % config.value)
|
||||
print("Interface: %d" % intf.interfaceNumber)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"""
|
||||
gnuk_upgrade.py - a tool to upgrade firmware of Gnuk Token
|
||||
|
||||
Copyright (C) 2012 Free Software Initiative of Japan
|
||||
Copyright (C) 2012, 2015 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -31,354 +31,7 @@ import sys, time, os, binascii, string
|
||||
|
||||
import usb
|
||||
|
||||
# USB class, subclass, protocol
|
||||
CCID_CLASS = 0x0B
|
||||
CCID_SUBCLASS = 0x00
|
||||
CCID_PROTOCOL_0 = 0x00
|
||||
|
||||
def icc_compose(msg_type, data_len, slot, seq, param, data):
|
||||
return pack('<BiBBBH', msg_type, data_len, slot, seq, 0, param) + data
|
||||
|
||||
def iso7816_compose(ins, p1, p2, data, cls=0x00):
|
||||
data_len = len(data)
|
||||
if data_len == 0:
|
||||
return pack('>BBBB', cls, ins, p1, p2)
|
||||
else:
|
||||
return pack('>BBBBB', cls, ins, p1, p2, data_len) + data
|
||||
|
||||
class regnual(object):
|
||||
def __init__(self, dev):
|
||||
conf = dev.configurations[0]
|
||||
intf_alt = conf.interfaces[0]
|
||||
intf = intf_alt[0]
|
||||
if intf.interfaceClass != 0xff:
|
||||
raise ValueError, "Wrong interface class"
|
||||
self.__devhandle = dev.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(conf)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(intf)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
value = 0, index = 0, buffer = 8,
|
||||
timeout = 10000)
|
||||
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x08000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d: %d : %d" % (addr, i, j, 256)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
timeout = 10000)
|
||||
crc32code = crc32(data[j*256:j*256+256])
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.010)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = 0, index = 0,
|
||||
buffer = data[j*256:],
|
||||
timeout = 10000)
|
||||
crc32code = crc32(data[j*256:].ljust(256,chr(255)))
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if (crc32code ^ r_value) != 0xffffffff:
|
||||
print "failure"
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 3,
|
||||
value = i, index = 0,
|
||||
buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.010)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "failure"
|
||||
|
||||
def protect(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 4,
|
||||
value = 0, index = 0, buffer = None,
|
||||
timeout = 10000)
|
||||
time.sleep(0.100)
|
||||
res = self.__devhandle.controlMsg(requestType = 0xc0, request = 2,
|
||||
value = 0, index = 0, buffer = 4,
|
||||
timeout = 10000)
|
||||
r_value = ((res[3]*256 + res[2])*256 + res[1])*256 + res[0]
|
||||
if r_value == 0:
|
||||
print "protection failure"
|
||||
|
||||
def finish(self):
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 5,
|
||||
value = 0, index = 0, buffer = None,
|
||||
timeout = 10000)
|
||||
|
||||
def reset_device(self):
|
||||
try:
|
||||
self.__devhandle.reset()
|
||||
except:
|
||||
pass
|
||||
|
||||
# This class only supports Gnuk (for now)
|
||||
class gnuk_token(object):
|
||||
def __init__(self, device, configuration, interface):
|
||||
"""
|
||||
__init__(device, configuration, interface) -> None
|
||||
Initialize the device.
|
||||
device: usb.Device object.
|
||||
configuration: configuration number.
|
||||
interface: usb.Interface object representing the interface and altenate setting.
|
||||
"""
|
||||
if interface.interfaceClass != CCID_CLASS:
|
||||
raise ValueError, "Wrong interface class"
|
||||
if interface.interfaceSubClass != CCID_SUBCLASS:
|
||||
raise ValueError, "Wrong interface sub class"
|
||||
self.__devhandle = device.open()
|
||||
try:
|
||||
self.__devhandle.setConfiguration(configuration)
|
||||
except:
|
||||
pass
|
||||
self.__devhandle.claimInterface(interface)
|
||||
self.__devhandle.setAltInterface(0)
|
||||
|
||||
self.__intf = interface.interfaceNumber
|
||||
self.__alt = interface.alternateSetting
|
||||
self.__conf = configuration
|
||||
|
||||
self.__bulkout = 1
|
||||
self.__bulkin = 0x81
|
||||
|
||||
self.__timeout = 10000
|
||||
self.__seq = 0
|
||||
|
||||
def reset_device(self):
|
||||
try:
|
||||
self.__devhandle.reset()
|
||||
except:
|
||||
pass
|
||||
|
||||
def stop_gnuk(self):
|
||||
self.__devhandle.releaseInterface()
|
||||
self.__devhandle.setConfiguration(0)
|
||||
return
|
||||
|
||||
def mem_info(self):
|
||||
mem = self.__devhandle.controlMsg(requestType = 0xc0, request = 0,
|
||||
value = 0, index = 0, buffer = 8,
|
||||
timeout = 10)
|
||||
start = ((mem[3]*256 + mem[2])*256 + mem[1])*256 + mem[0]
|
||||
end = ((mem[7]*256 + mem[6])*256 + mem[5])*256 + mem[4]
|
||||
return (start, end)
|
||||
|
||||
def download(self, start, data):
|
||||
addr = start
|
||||
addr_end = (start + len(data)) & 0xffffff00
|
||||
i = (addr - 0x20000000) / 0x100
|
||||
j = 0
|
||||
print "start %08x" % addr
|
||||
print "end %08x" % addr_end
|
||||
while addr < addr_end:
|
||||
print "# %08x: %d : %d" % (addr, i, 256)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:j*256+256],
|
||||
timeout = 10)
|
||||
i = i+1
|
||||
j = j+1
|
||||
addr = addr + 256
|
||||
residue = len(data) % 256
|
||||
if residue != 0:
|
||||
print "# %08x: %d : %d" % (addr, i, residue)
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 1,
|
||||
value = i, index = 0,
|
||||
buffer = data[j*256:],
|
||||
timeout = 10)
|
||||
|
||||
def execute(self, last_addr):
|
||||
i = (last_addr - 0x20000000) / 0x100
|
||||
o = (last_addr - 0x20000000) % 0x100
|
||||
self.__devhandle.controlMsg(requestType = 0x40, request = 2,
|
||||
value = i, index = o, buffer = None,
|
||||
timeout = 10)
|
||||
|
||||
def icc_get_result(self):
|
||||
msg = self.__devhandle.bulkRead(self.__bulkin, 1024, self.__timeout)
|
||||
if len(msg) < 10:
|
||||
raise ValueError, "icc_get_result"
|
||||
msg_type = msg[0]
|
||||
data_len = msg[1] + (msg[2]<<8) + (msg[3]<<16) + (msg[4]<<24)
|
||||
slot = msg[5]
|
||||
seq = msg[6]
|
||||
status = msg[7]
|
||||
error = msg[8]
|
||||
chain = msg[9]
|
||||
data = msg[10:]
|
||||
# XXX: check msg_type, data_len, slot, seq, error
|
||||
return (status, chain, data)
|
||||
|
||||
def icc_get_status(self):
|
||||
msg = icc_compose(0x65, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_power_on(self):
|
||||
msg = icc_compose(0x62, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check status, chain
|
||||
return data # ATR
|
||||
|
||||
def icc_power_off(self):
|
||||
msg = icc_compose(0x63, 0, 0, self.__seq, 0, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data = self.icc_get_result()
|
||||
# XXX: check chain, data
|
||||
return status
|
||||
|
||||
def icc_send_data_block(self, data):
|
||||
msg = icc_compose(0x6f, len(data), 0, self.__seq, 0, data)
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
return self.icc_get_result()
|
||||
|
||||
def icc_send_cmd(self, data):
|
||||
status, chain, data_rcv = self.icc_send_data_block(data)
|
||||
if chain == 0:
|
||||
return data_rcv
|
||||
elif chain == 1:
|
||||
d = data_rcv
|
||||
while True:
|
||||
msg = icc_compose(0x6f, 0, 0, self.__seq, 0x10, "")
|
||||
self.__devhandle.bulkWrite(self.__bulkout, msg, self.__timeout)
|
||||
self.__seq += 1
|
||||
status, chain, data_rcv = self.icc_get_result()
|
||||
# XXX: check status
|
||||
d += data_rcv
|
||||
if chain == 2:
|
||||
break
|
||||
elif chain == 3:
|
||||
continue
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd chain"
|
||||
return d
|
||||
else:
|
||||
raise ValueError, "icc_send_cmd"
|
||||
|
||||
def cmd_get_response(self, expected_len):
|
||||
cmd_data = iso7816_compose(0xc0, 0x00, 0x00, '') + pack('>B', expected_len)
|
||||
response = self.icc_send_cmd(cmd_data)
|
||||
return response[:-2]
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
cmd_data = iso7816_compose(0x20, 0x00, 0x80+who, passwd)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, sw
|
||||
|
||||
def cmd_select_openpgp(self):
|
||||
cmd_data = iso7816_compose(0xa4, 0x04, 0x0c, "\xD2\x76\x00\x01\x24\x01")
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def cmd_external_authenticate(self, signed):
|
||||
cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[0:128], cls=0x10)
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
cmd_data = iso7816_compose(0x82, 0x00, 0x00, signed[128:])
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if not (sw[0] == 0x90 and sw[1] == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
|
||||
def cmd_get_challenge(self):
|
||||
cmd_data = iso7816_compose(0x84, 0x00, 0x00, '')
|
||||
sw = self.icc_send_cmd(cmd_data)
|
||||
if len(sw) != 2:
|
||||
raise ValueError, sw
|
||||
if sw[0] != 0x61:
|
||||
raise ValueError, ("%02x%02x" % (sw[0], sw[1]))
|
||||
return self.cmd_get_response(sw[1])
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
i = 0
|
||||
for d in data_original:
|
||||
if ord(d) != data_in_device[i]:
|
||||
raise ValueError, "verify failed at %08x" % i
|
||||
i += 1
|
||||
|
||||
def ccid_devices():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
for config in dev.configurations:
|
||||
for intf in config.interfaces:
|
||||
for alt in intf:
|
||||
if alt.interfaceClass == CCID_CLASS and \
|
||||
alt.interfaceSubClass == CCID_SUBCLASS and \
|
||||
alt.interfaceProtocol == CCID_PROTOCOL_0:
|
||||
yield dev, config, alt
|
||||
|
||||
USB_VENDOR_FSIJ=0x234b
|
||||
USB_PRODUCT_GNUK=0x0000
|
||||
|
||||
def gnuk_devices():
|
||||
busses = usb.busses()
|
||||
for bus in busses:
|
||||
devices = bus.devices
|
||||
for dev in devices:
|
||||
if dev.idVendor != USB_VENDOR_FSIJ:
|
||||
continue
|
||||
if dev.idProduct != USB_PRODUCT_GNUK:
|
||||
continue
|
||||
yield dev
|
||||
from gnuk_token import *
|
||||
|
||||
def to_string(t):
|
||||
result = ""
|
||||
@@ -420,24 +73,17 @@ def gpg_sign(keygrip, hash):
|
||||
pos = signed.index("D ") + 2
|
||||
signed = signed[pos:-4] # \nOK\n
|
||||
if len(signed) != 256:
|
||||
raise ValueError, binascii.hexlify(signed)
|
||||
raise ValueError(binascii.hexlify(signed))
|
||||
return signed
|
||||
|
||||
def UNSIGNED(n):
|
||||
return n & 0xffffffff
|
||||
|
||||
def crc32(bytestr):
|
||||
crc = binascii.crc32(bytestr)
|
||||
return UNSIGNED(crc)
|
||||
|
||||
def main(keygrip, data_regnual, data_upgrade):
|
||||
def main(keyno,keygrip, data_regnual, data_upgrade):
|
||||
l = len(data_regnual)
|
||||
if (l & 0x03) != 0:
|
||||
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
|
||||
crc32code = crc32(data_regnual)
|
||||
print "CRC32: %04x\n" % crc32code
|
||||
data_regnual += pack('<I', crc32code)
|
||||
for (dev, config, intf) in ccid_devices():
|
||||
for (dev, config, intf) in gnuk_devices():
|
||||
try:
|
||||
icc = gnuk_token(dev, config, intf)
|
||||
print "Device: ", dev.filename
|
||||
@@ -447,13 +93,13 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
except:
|
||||
icc = None
|
||||
if icc.icc_get_status() == 2:
|
||||
raise ValueError, "No ICC present"
|
||||
raise ValueError("No ICC present")
|
||||
elif icc.icc_get_status() == 1:
|
||||
icc.icc_power_on()
|
||||
icc.cmd_select_openpgp()
|
||||
challenge = icc.cmd_get_challenge()
|
||||
signed = gpg_sign(keygrip, binascii.hexlify(to_string(challenge)))
|
||||
icc.cmd_external_authenticate(signed)
|
||||
icc.cmd_external_authenticate(keyno, signed)
|
||||
icc.stop_gnuk()
|
||||
mem_info = icc.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
@@ -471,7 +117,7 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
time.sleep(3)
|
||||
# Then, send upgrade program...
|
||||
reg = None
|
||||
for dev in gnuk_devices():
|
||||
for dev in gnuk_devices_by_vidpid():
|
||||
try:
|
||||
reg = regnual(dev)
|
||||
print "Device: ", dev.filename
|
||||
@@ -489,6 +135,7 @@ def main(keygrip, data_regnual, data_upgrade):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
keyno = 0
|
||||
keygrip = None
|
||||
if sys.argv[1] == '-k':
|
||||
sys.argv.pop(1)
|
||||
@@ -504,4 +151,4 @@ if __name__ == '__main__':
|
||||
data_upgrade = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_upgrade, len(data_upgrade))
|
||||
main(keygrip, data_regnual, data_upgrade[4096:])
|
||||
main(keyno, keygrip, data_regnual, data_upgrade[4096:])
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
upgrade_by_passwd.py - a tool to install another firmware for Gnuk Token
|
||||
which is just shipped from factory
|
||||
|
||||
Copyright (C) 2012, 2013 Free Software Initiative of Japan
|
||||
Copyright (C) 2012, 2013, 2015 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -37,7 +37,7 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
if (l & 0x03) != 0:
|
||||
data_regnual = data_regnual.ljust(l + 4 - (l & 0x03), chr(0))
|
||||
crc32code = crc32(data_regnual)
|
||||
print "CRC32: %04x\n" % crc32code
|
||||
print("CRC32: %04x\n" % crc32code)
|
||||
data_regnual += pack('<I', crc32code)
|
||||
|
||||
rsa_key = rsa.read_key_from_file('rsa_example.key')
|
||||
@@ -55,11 +55,11 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
gnuk.cmd_external_authenticate(keyno, signed_bytes)
|
||||
gnuk.stop_gnuk()
|
||||
mem_info = gnuk.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
print("%08x:%08x" % mem_info)
|
||||
|
||||
print "Downloading flash upgrade program..."
|
||||
print("Downloading flash upgrade program...")
|
||||
gnuk.download(mem_info[0], data_regnual)
|
||||
print "Run flash upgrade program..."
|
||||
print("Run flash upgrade program...")
|
||||
gnuk.execute(mem_info[0] + len(data_regnual) - 4)
|
||||
#
|
||||
time.sleep(3)
|
||||
@@ -67,51 +67,56 @@ def main(keyno, passwd, data_regnual, data_upgrade):
|
||||
del gnuk
|
||||
gnuk = None
|
||||
#
|
||||
print "Wait 3 seconds..."
|
||||
print("Wait 3 seconds...")
|
||||
time.sleep(3)
|
||||
# Then, send upgrade program...
|
||||
reg = None
|
||||
for dev in gnuk_devices_by_vidpid():
|
||||
try:
|
||||
reg = regnual(dev)
|
||||
print "Device: ", dev.filename
|
||||
print("Device: %s" % dev.filename)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
mem_info = reg.mem_info()
|
||||
print "%08x:%08x" % mem_info
|
||||
print "Downloading the program"
|
||||
print("%08x:%08x" % mem_info)
|
||||
print("Downloading the program")
|
||||
reg.download(mem_info[0], data_upgrade)
|
||||
reg.protect()
|
||||
reg.finish()
|
||||
reg.reset_device()
|
||||
return 0
|
||||
|
||||
from getpass import getpass
|
||||
|
||||
if __name__ == '__main__':
|
||||
if os.getcwd() != os.path.dirname(os.path.abspath(__file__)):
|
||||
print "Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__))
|
||||
print("Please change working directory to: %s" % os.path.dirname(os.path.abspath(__file__)))
|
||||
exit(1)
|
||||
|
||||
passwd = DEFAULT_PW3
|
||||
keyno = 0
|
||||
passwd = None
|
||||
while len(sys.argv) > 3:
|
||||
option = sys.argv[1]
|
||||
sys.argv.pop(1)
|
||||
if option == '-p':
|
||||
from getpass import getpass
|
||||
passwd = getpass("Admin password: ")
|
||||
elif option == '-k':
|
||||
if option == '-f': # F for Factory setting
|
||||
passwd = DEFAULT_PW3
|
||||
elif option == '-k': # K for Key number
|
||||
keyno = int(sys.argv[1])
|
||||
sys.argv.pop(1)
|
||||
else:
|
||||
raise ValueError("unknown option", option)
|
||||
if not passwd:
|
||||
passwd = getpass("Admin password: ")
|
||||
filename_regnual = sys.argv[1]
|
||||
filename_upgrade = sys.argv[2]
|
||||
f = open(filename_regnual)
|
||||
data_regnual = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_regnual, len(data_regnual))
|
||||
print("%s: %d" % (filename_regnual, len(data_regnual)))
|
||||
f = open(filename_upgrade)
|
||||
data_upgrade = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename_upgrade, len(data_upgrade))
|
||||
print("%s: %d" % (filename_upgrade, len(data_upgrade)))
|
||||
# First 4096-byte in data_upgrade is SYS, so, skip it.
|
||||
main(keyno, passwd, data_regnual, data_upgrade[4096:])
|
||||
|
||||
Reference in New Issue
Block a user