Compare commits

...

19 Commits

Author SHA1 Message Date
NIIBE Yutaka
2471616f74 version 1.1.5 2015-06-03 17:22:56 +09:00
NIIBE Yutaka
3926f42647 add test/ecc_nistp256_keys.py 2015-06-03 16:27:41 +09:00
NIIBE Yutaka
ce070f85ff Improve tool/ 2015-06-03 16:27:15 +09:00
NIIBE Yutaka
bd02cbfdb0 OpenPGPcard spec v3.0 change 2015-06-02 20:46:30 +09:00
NIIBE Yutaka
16149ff960 show MAPLE_MINI in help message 2015-06-02 20:44:38 +09:00
NIIBE Yutaka
c4a5681f35 upgrade Chopstx 0.05 2015-06-02 20:44:09 +09:00
NIIBE Yutaka
3d5a776ab1 works on Windows 2015-04-19 09:55:51 +09:00
NIIBE Yutaka
9f4671eaf6 ccid_card_change_signal change 2015-04-18 14:34:53 +09:00
NIIBE Yutaka
5af5d18310 Use chopstx_main_init. 2015-04-18 14:13:00 +09:00
NIIBE Yutaka
3765c9233b shell syntax fix 2015-04-18 12:30:21 +09:00
NIIBE Yutaka
0bd0af1fe1 USB clean up 2015-03-31 14:05:52 +09:00
NIIBE Yutaka
92189e2d12 Update README and THANKS 2015-03-12 14:52:41 +09:00
NIIBE Yutaka
6dcd5aa00c doc fix 2015-03-06 16:14:12 +09:00
NIIBE Yutaka
09d3068222 fix EdDSA auth 2015-03-06 16:13:57 +09:00
NIIBE Yutaka
0f11d320e6 bug fix of OPENPGP.3 singing 2015-02-25 10:03:41 +09:00
NIIBE Yutaka
365308f374 Fix the doc. Thanks to Micah 2015-02-18 10:19:10 +09:00
NIIBE Yutaka
0e510b32c1 Fix EdDSA signature counter 2015-02-10 09:58:45 +09:00
NIIBE Yutaka
a9244d9b13 Fix the bug of EdDSA signing 2015-02-09 16:28:26 +09:00
NIIBE Yutaka
c268e59813 fix doc: Thanks to Micah 2015-01-19 11:08:13 +09:00
26 changed files with 401 additions and 747 deletions

View File

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

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

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

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

View File

@@ -1 +1 @@
release/1.1.4
release/1.1.5

Submodule chopstx updated: 23893d9b73...fc26cf0889

View File

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

View File

@@ -5,174 +5,14 @@ Key import from PC to Gnuk Token (no removal)
This document describes how I put my **keys on PC** to the Token
without removing keys from PC.
The difference is just not-to-save changes after key imports.
The difference is only the last step.
I don't save changes on PC after keytocard.
After personalization, I put my keys into the Token.
For the steps before the last step, please see `keytocard with removing keys on PC`_.
Here is the log.
.. _keytocard 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. ::

View File

@@ -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). ::

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@@ -1,7 +1,8 @@
/*
* main.c - main routine of Gnuk
*
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan
* Copyright (C) 2010, 2011, 2012, 2013, 2015
* 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)

View File

@@ -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);
if (r == 0)
res_APDU_size = 65;
}
else
{
DEBUG_INFO ("unknown algo.");
GPG_FUNCTION_NOT_SUPPORTED ();
return;
}
if (r == 0)
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");

View File

@@ -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,34 +1365,26 @@ ccid_thread (chopstx_t thd)
if (m == EV_CARD_CHANGE)
{
if (card_change_requested)
{
uint8_t notify_slot_change[2] = { 0x50, 0x02 };
led_blink (LED_TWOSHOTS);
if (c->icc_state == ICC_STATE_NOCARD)
{ /* Inserted! */
c->icc_state = ICC_STATE_START;
notify_slot_change[1] |= 1;
}
else
{
if (c->application)
{
eventflag_signal (&c->openpgp_comm, EV_EXIT);
chopstx_join (c->application, NULL);
c->application = 0;
}
c->icc_state = ICC_STATE_NOCARD;
}
card_change_requested = 0;
usb_lld_write (ENDP2, notify_slot_change, 2);
if (c->icc_state == ICC_STATE_NOCARD)
{ /* Inserted! */
c->icc_state = ICC_STATE_START;
int_msg[1] = 0x03;
}
else
card_change_requested = 1;
{ /* Removed! */
if (c->application)
{
eventflag_signal (&c->openpgp_comm, EV_EXIT);
chopstx_join (c->application, NULL);
c->application = 0;
}
c->icc_state = ICC_STATE_NOCARD;
int_msg[1] = 0x02;
}
usb_lld_write (ENDP2, int_msg, sizeof int_msg);
led_blink (LED_TWOSHOTS);
}
else if (m == EV_RX_DATA_READY)
c->icc_state = icc_handle_data (c);
@@ -1444,10 +1442,7 @@ ccid_thread (chopstx_t thd)
icc_prepare_receive (c);
}
else /* Timeout */
{
c->icc_state = icc_handle_timeout (c);
card_change_requested = 0;
}
c->icc_state = icc_handle_timeout (c);
}
if (c->application)

View File

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

View File

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

View File

@@ -75,37 +75,27 @@ static const uint8_t gnukDeviceDescriptor[] = {
};
#define ICC_TOTAL_LENGTH (9+9+54+7+7+7)
#define ICC_NUM_INTERFACES 1
#ifdef HID_CARD_CHANGE_SUPPORT
#define HID_TOTAL_LENGTH (9+9+7)
#define HID_NUM_INTERFACES 1
#else
#define HID_TOTAL_LENGTH 0
#define HID_NUM_INTERFACES 0
#endif
#ifdef ENABLE_VIRTUAL_COM_PORT
#define VCOM_TOTAL_LENGTH (9+5+5+4+5+7+9+7+7)
#define VCOM_NUM_INTERFACES 2
#else
#define VCOM_TOTAL_LENGTH 0
#define VCOM_NUM_INTERFACES 0
#endif
#ifdef PINPAD_DND_SUPPORT
#define MSC_TOTAL_LENGTH (9+7+7)
#define MSC_NUM_INTERFACES 1
#else
#define MSC_TOTAL_LENGTH 0
#define MSC_NUM_INTERFACES 0
#endif
#define W_TOTAL_LENGTH (ICC_TOTAL_LENGTH + HID_TOTAL_LENGTH \
+ VCOM_TOTAL_LENGTH + MSC_TOTAL_LENGTH)
#define NUM_INTERFACES (ICC_NUM_INTERFACES + HID_NUM_INTERFACES \
+ VCOM_NUM_INTERFACES + MSC_NUM_INTERFACES)
/* Configuation Descriptor */
@@ -122,7 +112,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0, /* bInterfaceNumber: Index of this interface */
ICC_INTERFACE, /* bInterfaceNumber: Index of this interface */
0, /* Alternate setting for this interface */
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
USB_ICC_INTERFACE_CLASS,
@@ -135,42 +125,36 @@ static const uint8_t gnukConfigDescriptor[] = {
0x21, /* bDescriptorType: USBDESCR_ICC */
0x10, 0x01, /* bcdCCID: revision 1.1 (of CCID) */
0, /* bMaxSlotIndex: */
1, /* bVoltageSupport: FIXED VALUE */
1, /* bVoltageSupport: 5V-only */
0x02, 0, 0, 0, /* dwProtocols: T=1 */
0xf3, 0x0d, 0, 0, /* dwDefaultClock: 3571 (non-ICCD): 3580 (ICCD) */
0xf3, 0x0d, 0, 0, /* dwMaximumClock: 3571 (non-ICCD): 3580 (ICCD) */
1, /* bNumClockSupported: FIXED VALUE */
0x80, 0x25, 0, 0, /* dwDataRate: 9600: FIXED VALUE */
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600: FIXED VALUE */
1, /* bNumDataRateSupported: FIXED VALUE */
0xa0, 0x0f, 0, 0, /* dwDefaultClock: 4000 */
0xa0, 0x0f, 0, 0, /* dwMaximumClock: 4000 */
0, /* bNumClockSupported: 0x00 */
0x80, 0x25, 0, 0, /* dwDataRate: 9600 */
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600 */
0, /* bNumDataRateSupported: 0x00 */
0xfe, 0, 0, 0, /* dwMaxIFSD: 254 */
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
/*
* According to Specification for USB ICCD (revision 1.0),
* dwFeatures should be 0x00040840.
*
* It is different now for better interaction to GPG's in-stock
* ccid-driver.
*/
0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
* Short APDU level : 0x20000 *
* (what? means ICCD?) : 0x00800 *
* Automatic IFSD : 0x00400
0, 0, 0, 0, /* dwSynchProtocols: 0 */
0, 0, 0, 0, /* dwMechanical: 0 */
0x7a, 0x04, 0x02, 0x00, /* dwFeatures:
* Short and extended APDU level: 0x40000 ----
* Short APDU level : 0x20000 *
* (ICCD?) : 0x00800 ----
* Automatic IFSD : 0x00400 *
* NAD value other than 0x00 : 0x00200
* Can set ICC in clock stop : 0x00100
* Automatic PPS CUR : 0x00080
* Automatic PPS PROP : 0x00040 *
* Auto baud rate change : 0x00020
* Auto clock change : 0x00010
* Auto voltage selection : 0x00008
* Auto baud rate change : 0x00020 *
* Auto clock change : 0x00010 *
* Auto voltage selection : 0x00008 *
* Auto activaction of ICC : 0x00004
* Automatic conf. based on ATR : 0x00002 g
* Automatic conf. based on ATR : 0x00002 *
*/
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
0xff, /* bClassGetResponse: */
0xff, /* bClassEnvelope: */
0, 0, /* wLCDLayout: FIXED VALUE */
0xff, /* bClassGetResponse: 0xff */
0x00, /* bClassEnvelope: 0 */
0, 0, /* wLCDLayout: 0 */
#if defined(PINPAD_SUPPORT)
#if defined(PINPAD_CIR_SUPPORT) || defined(PINPAD_DND_SUPPORT)
1, /* bPinSupport: with PIN pad (verify) */
@@ -200,14 +184,14 @@ static const uint8_t gnukConfigDescriptor[] = {
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x82, /* bEndpointAddress: (IN2) */
0x03, /* bmAttributes: Interrupt */
4, 0x00, /* wMaxPacketSize: */
0x04, 0x00, /* wMaxPacketSize: 4 */
0xFF, /* bInterval (255ms) */
#ifdef HID_CARD_CHANGE_SUPPORT
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0x01, /* bInterfaceNumber: Number of Interface */
HID_INTERFACE, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
0x03, /* bInterfaceClass: HID */
@@ -236,7 +220,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* Interface Descriptor */
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
0x02, /* bInterfaceNumber: Number of Interface */
VCOM_INTERFACE_0, /* bInterfaceNumber: Index of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
@@ -247,14 +231,13 @@ static const uint8_t gnukConfigDescriptor[] = {
5, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
0x10, 0x01, /* bcdCDC: spec release number */
/*Call Managment Functional Descriptor*/
5, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x03, /* bmCapabilities: D0+D1 */
0x02, /* bDataInterface: 2 */
VCOM_INTERFACE_1, /* bDataInterface */
/*ACM Functional Descriptor*/
4, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
@@ -264,8 +247,8 @@ static const uint8_t gnukConfigDescriptor[] = {
5, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x01, /* bMasterInterface: Communication class interface */
0x02, /* bSlaveInterface0: Data Class Interface */
VCOM_INTERFACE_0, /* bMasterInterface: Communication class interface */
VCOM_INTERFACE_1, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 4 Descriptor*/
7, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
@@ -277,7 +260,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/*Data class interface descriptor*/
9, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x03, /* bInterfaceNumber: Number of Interface */
VCOM_INTERFACE_1, /* bInterfaceNumber: Index of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
@@ -303,11 +286,7 @@ static const uint8_t gnukConfigDescriptor[] = {
/* Interface Descriptor.*/
9, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
#ifdef ENABLE_VIRTUAL_COM_PORT
0x04, /* bInterfaceNumber. */
#else
0x02, /* bInterfaceNumber. */
#endif
MSC_INTERFACE, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x02, /* bNumEndpoints. */
0x08, /* bInterfaceClass (Mass Stprage). */

31
test/ecc_nistp256_keys.py Normal file
View 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.

View File

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

View File

@@ -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:])

View File

@@ -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:])