fix key page release

This commit is contained in:
NIIBE Yutaka
2014-12-13 21:57:38 +09:00
parent 3cca2798b0
commit d6e70ab0f4
7 changed files with 90 additions and 65 deletions

View File

@@ -1,3 +1,10 @@
2014-12-13 Niibe Yutaka <gniibe@fsij.org>
* src/flash.c (flash_key_getpage, flash_key_release_page): New.
* src/openpgp-do.c (gpg_do_delete_prvkey): New arg.
(rw_algorithm_attr): Call gpg_do_delete_prvkey with CLEAN_PAGE_FULL.
2014-12-12 Niibe Yutaka <gniibe@fsij.org> 2014-12-12 Niibe Yutaka <gniibe@fsij.org>
* src/Makefile.in (build/bignum.o): Specific OPT for this target. * src/Makefile.in (build/bignum.o): Specific OPT for this target.

79
README
View File

@@ -1,14 +1,14 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 1.1.3 Version 1.1.4
2014-04-16 2014-12-1x
Niibe Yutaka Niibe Yutaka
Free Software Initiative of Japan Free Software Initiative of Japan
Warning Warning
======= =======
This is another experimental release of Gnuk, version 1.1.3, which has This is another experimental release of Gnuk, version 1.1.4, which has
incompatible changes to Gnuk 1.0.x. Specifically, it now supports incompatible changes to Gnuk 1.0.x. Specifically, it now supports
overriding key import, but importing keys (or generating keys) results overriding key import, but importing keys (or generating keys) results
password reset. Please update your documentation for Gnuk Token, so password reset. Please update your documentation for Gnuk Token, so
@@ -17,7 +17,8 @@ has supports of ECDSA (with NIST P256 and secp256k1) and EdDSA with
EdDSA, but this feature is pretty much experimental, and it requires EdDSA, but this feature is pretty much experimental, and it requires
development version of GnuPG with newest version of libgcrypt. You development version of GnuPG with newest version of libgcrypt. You
will not able to keep using EdDSA keys, as the key format is subject will not able to keep using EdDSA keys, as the key format is subject
to change. to change. It also support RSA-4096 experimentally, but users should
know that it takes more than 8 second to sign/decrypt.
What's Gnuk? What's Gnuk?
@@ -57,8 +58,9 @@ A0: Good points of Gnuk are:
"for Free Software"; Gnuk supports GnuPG. "for Free Software"; Gnuk supports GnuPG.
Q1: What kind of key algorithm is supported? Q1: What kind of key algorithm is supported?
A1: Gnuk version 1.0 only supports 2048-bit RSA. A1: Gnuk version 1.0 only supports RSA 2048.
Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA. Development version of Gnuk (1.1.x) supports 256-bit ECDSA and EdDSA,
as well as RSA 4096-bit. But it takes long time to sign with RSA 4096.
Q2: How long does it take for digital signing? Q2: How long does it take for digital signing?
A2: It takes a second and a half or so. A2: It takes a second and a half or so.
@@ -87,13 +89,7 @@ A6: You need a target board plus a JTAG/SWD debugger. If you just
Q7: How much does it cost? Q7: How much does it cost?
A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so. A7: Olimex STM32-H103 plus ARM-USB-TINY-H cost 70 Euro or so.
Q8: How much does it cost for DIY version?
A8: STM8S Discovery Kit costs 750 JPY (< $10 USD) only. You can build
your own JTAG debugger using FTDI2232 module (1450 JPY), see:
http://www.fsij.org/gnuk/jtag_dongle_ftdi2232
Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up? Q9: I got an error like "gpg: selecting openpgp failed: ec=6.108", what's up?
A9: GnuPG's SCDaemon has problems for handling insertion/removal of A9: GnuPG's SCDaemon has problems for handling insertion/removal of
card/reader. When your newly inserted token is not found by card/reader. When your newly inserted token is not found by
GnuPG, try killing scdaemon and let it to be invoked again. I do: GnuPG, try killing scdaemon and let it to be invoked again. I do:
@@ -110,7 +106,7 @@ Aa: You need to deactivate seahorse-agent and gnome-keyring, but use
$ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false $ gconftool-2 --type bool --set /apps/gnome-keyring/daemon-components/ssh false
Qb: With GNOME 3, I can't use Gnuk Token at all. Why? Qb: With GNOME 3.0, I can't use Gnuk Token at all. Why?
Ab: That's because gnome-keyring-daemon interferes GnuPG. Type: Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
$ gnome-session-properties $ gnome-session-properties
@@ -122,6 +118,16 @@ Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM Ac: ST-Link/V2 is cheap one. We have a tool/stlinkv2.py as flash ROM
writer program. writer program.
Qd: With GNOME 3.x (x >= 8?), I can't use Gnuk Token at all. Why?
Ad: Please set the configration variable OnlyShowIn as none. Like:
OnlyShowIn=
In the files of /etc/xdg/autostart/gnome-keyring-gpg.desktop and
/etc/xdg/autostart/gnome-keyring-ssh.desktop
Release notes Release notes
============= =============
@@ -130,10 +136,9 @@ This is third experimental release in version 1.1 series of Gnuk.
While it is daily use by its developer, some newly introduced features While it is daily use by its developer, some newly introduced features
(including ECDSA/EdDSA, key generation and firmware upgrade) should be (including ECDSA/EdDSA, key generation and firmware upgrade) should be
considered experimental. ECDSA/EdDSA is really experimental. The considered experimental. ECDSA/EdDSA is really experimental.
feature even requires manual edit of Makefile after 'configure'. Further, EdDSA is much experimental. You won't be able to keep using
More, EdDSA is much experimental. You won't be able to keep using the EdDSA key, as the key format of GnuPG is subject to change.
the EdDSA key, as it is subject to change.
Tested features are: Tested features are:
@@ -181,11 +186,12 @@ DfuSe is for experiment only, because it is impossible for DfuSe to
disable read from flash. For real use, please consider killing DfuSe disable read from flash. For real use, please consider killing DfuSe
and enabling read protection using JTAG debugger. and enabling read protection using JTAG debugger.
For PIN-pad support, I connect a consumer IR receive module to FST-01, and use controller for TV. PIN verification For PIN-pad support, I connect a consumer IR receive module to FST-01,
is supported by this configuration. Yes, it is not secure at all, and use controller for TV. PIN verification is supported by this
since it is very easy to monitor IR output of the controllers. It is configuration. Yes, it is not secure at all, since it is very easy to
just an experiment. Note that hardware needed for this experiment is monitor IR output of the controllers. It is just an experiment. Note
only a consumer IR receive module which is as cheap as 50 JPY. that hardware needed for this experiment is only a consumer IR receive
module which is as cheap as 50 JPY.
Note that you need pinpad support for GnuPG to use PIN-pad enabled Note that you need pinpad support for GnuPG to use PIN-pad enabled
Gnuk. The pinpad support for GnuPG is only available in version 2. Gnuk. The pinpad support for GnuPG is only available in version 2.
@@ -223,7 +229,7 @@ External source code
Gnuk is distributed with external source code. Gnuk is distributed with external source code.
* chopstx/ -- Chopstx 0.03 (+ STBee support) * chopstx/ -- Chopstx 0.04
We use Chopstx as the kernel for Gnuk. We use Chopstx as the kernel for Gnuk.
@@ -380,30 +386,7 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
Flying Stone Tiny 01 Flying Stone Tiny 01
-------------------- --------------------
If you are using Flying Stone Tiny 01, you need a SWD writer. I am If you are using Flying Stone Tiny 01, you need a SWD writer.
using revision 946 of Simon Qian's Versaloon.
svn checkout -r 946 http://vsprog.googlecode.com/svn/trunk/
For OpenOCD, we need unofficial patch.
See the article of Versaloon Forum:
http://www.versaloon.com/bbs/viewtopic.php?p=16179
Type following to invoke OpenOCD:
$ openocd -f interface/vsllink.cfg -c "transport select swd" -c "swd_mode 2" -f target/stm32f1x.cfg
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
OpenOCD 0.6.1 now supports ST-Link/V2. We can use it: OpenOCD 0.6.1 now supports ST-Link/V2. We can use it:
@@ -568,7 +551,7 @@ You can get it by:
$ git clone git://gitorious.org/gnuk/gnuk.git $ git clone git://gitorious.org/gnuk/gnuk.git
It's also available at: www.gniibe.org It's also available at: www.gniibe.org
You can browse at: http://www.gniibe.org/gitweb?p=gnuk.git;a=summary You can browse at: http://git.gniibe.org/gitweb?p=gnuk/gnuk.git;a=summary
I put Chopstx as a submodule of Git. Please do this: I put Chopstx as a submodule of Git. Please do this:

View File

@@ -1,7 +1,8 @@
/* /*
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
* *
* Copyright (C) 2010, 2011, 2012, 2013 Free Software Initiative of Japan * Copyright (C) 2010, 2011, 2012, 2013, 2014
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org> * Author: NIIBE Yutaka <gniibe@fsij.org>
* *
* This file is a part of Gnuk, a GnuPG USB Token implementation. * This file is a part of Gnuk, a GnuPG USB Token implementation.

View File

@@ -21,6 +21,12 @@
* *
*/ */
/*
* Note: we don't take advantage of the specific feature of this curve,
* but use same method of computation as NIST P-256 curve. That's due
* to some software patent(s).
*/
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "bn.h" #include "bn.h"

View File

@@ -318,16 +318,20 @@ flash_do_release (const uint8_t *do_data)
} }
static uint8_t *
flash_key_getpage (enum kind_of_key kk)
{
/* There is a page for each KK. */
return &_keystore_pool + (FLASH_PAGE_SIZE * kk);
}
uint8_t * uint8_t *
flash_key_alloc (enum kind_of_key kk) flash_key_alloc (enum kind_of_key kk)
{ {
uint8_t *k0, *k; uint8_t *k, *k0 = flash_key_getpage (kk);
int i; int i;
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE); int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
/* There is a page for each KK. */
k0 = &_keystore_pool + (FLASH_PAGE_SIZE * kk);
/* Seek free space in the page. */ /* Seek free space in the page. */
for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += key_size) for (k = k0; k < k0 + FLASH_PAGE_SIZE; k += key_size)
{ {
@@ -412,6 +416,12 @@ flash_key_release (uint8_t *key_addr, int key_size)
flash_key_fill_zero_as_released (key_addr, key_size); flash_key_fill_zero_as_released (key_addr, key_size);
} }
void
flash_key_release_page (enum kind_of_key kk)
{
flash_erase_page ((uint32_t)flash_key_getpage (kk));
}
void void
flash_clear_halfword (uint32_t addr) flash_clear_halfword (uint32_t addr)

View File

@@ -137,6 +137,7 @@ void flash_do_release (const uint8_t *);
const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len); const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
uint8_t *flash_key_alloc (enum kind_of_key); uint8_t *flash_key_alloc (enum kind_of_key);
void flash_key_release (uint8_t *, int); void flash_key_release (uint8_t *, int);
void flash_key_release_page (enum kind_of_key);
int flash_key_write (uint8_t *key_addr, int flash_key_write (uint8_t *key_addr,
const uint8_t *key_data, int key_data_len, const uint8_t *key_data, int key_data_len,
const uint8_t *pubkey, int pubkey_len); const uint8_t *pubkey, int pubkey_len);

View File

@@ -36,6 +36,11 @@
#include "polarssl/aes.h" #include "polarssl/aes.h"
#include "sha512.h" #include "sha512.h"
/* Forward declaration */
#define CLEAN_PAGE_FULL 1
#define CLEAN_SINGLE 0
static void gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full);
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */ #define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
static const uint8_t *pw_err_counter_p[3]; static const uint8_t *pw_err_counter_p[3];
@@ -458,8 +463,15 @@ copy_tag (uint16_t tag)
static int static int
do_hist_bytes (uint16_t tag, int with_tag) do_hist_bytes (uint16_t tag, int with_tag)
{ {
/* XXX: For now, no life cycle management, just return template as is. */ /*
/* XXX: Supporing TERMINATE DF / ACTIVATE FILE, we need to fix here */ * Currently, we support no life cycle management.
* In case of Gnuk, user could flash the MCU, instead.
* Thus, just return the template as is.
*
* In future (when Gnuk will be onn the real smartcard),
* we can support life cycle management by implementing
* TERMINATE DF / ACTIVATE FILE and fix code around here.
*/
copy_do_1 (tag, historical_bytes, with_tag); copy_do_1 (tag, historical_bytes, with_tag);
return 1; return 1;
} }
@@ -717,17 +729,15 @@ rw_algorithm_attr (uint16_t tag, int with_tag,
return 0; /* Error */ return 0; /* Error */
else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL) else if (algo == ALGO_RSA2K && *algo_attr_pp != NULL)
{ {
// xxx: make sure there is no key registered gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
flash_enum_clear (algo_attr_pp); flash_enum_clear (algo_attr_pp);
if (*algo_attr_pp != NULL) if (*algo_attr_pp != NULL)
return 0; return 0;
} }
else if (*algo_attr_pp == NULL || (*algo_attr_pp)[1] != algo) else if (*algo_attr_pp == NULL || (*algo_attr_pp)[1] != algo)
{ {
int nr = kk_to_nr (kk); gpg_do_delete_prvkey (kk, CLEAN_PAGE_FULL);
*algo_attr_pp = flash_enum_write (kk_to_nr (kk), algo);
// xxx: make sure there is no key registered
*algo_attr_pp = flash_enum_write (nr, algo);
if (*algo_attr_pp == NULL) if (*algo_attr_pp == NULL)
return 0; return 0;
} }
@@ -947,7 +957,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
static int8_t num_prv_keys; static int8_t num_prv_keys;
static void static void
gpg_do_delete_prvkey (enum kind_of_key kk) gpg_do_delete_prvkey (enum kind_of_key kk, int clean_page_full)
{ {
uint8_t nr = get_do_ptr_nr_for_kk (kk); uint8_t nr = get_do_ptr_nr_for_kk (kk);
const uint8_t *do_data = do_ptr[nr]; const uint8_t *do_data = do_ptr[nr];
@@ -956,13 +966,20 @@ gpg_do_delete_prvkey (enum kind_of_key kk)
int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE); int key_size = gpg_get_algo_attr_key_size (kk, GPG_KEY_STORAGE);
if (do_data == NULL) if (do_data == NULL)
return; {
if (clean_page_full)
flash_key_release_page (kk);
return;
}
do_ptr[nr] = NULL; do_ptr[nr] = NULL;
flash_do_release (do_data); flash_do_release (do_data);
key_addr = (uint8_t *)kd[kk].pubkey - prvkey_len; key_addr = (uint8_t *)kd[kk].pubkey - prvkey_len;
kd[kk].pubkey = NULL; kd[kk].pubkey = NULL;
flash_key_release (key_addr, key_size); if (clean_page_full)
flash_key_release_page (kk);
else
flash_key_release (key_addr, key_size);
if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING) if (admin_authorized == BY_ADMIN && kk == GPG_KEY_FOR_SIGNING)
{ /* Recover admin keystring DO. */ { /* Recover admin keystring DO. */
@@ -1014,7 +1031,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
DEBUG_SHORT (prvkey_len); DEBUG_SHORT (prvkey_len);
/* Delete it first, if any. */ /* Delete it first, if any. */
gpg_do_delete_prvkey (kk); gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data)); pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
if (pd == NULL) if (pd == NULL)
@@ -1314,7 +1331,7 @@ proc_key_import (const uint8_t *data, int len)
|| attr == ALGO_ED25519)) || attr == ALGO_ED25519))
|| (len <= 22 && attr == ALGO_RSA2K) || (len <= 24 && attr == ALGO_RSA4K)) || (len <= 22 && attr == ALGO_RSA2K) || (len <= 24 && attr == ALGO_RSA4K))
{ /* Deletion of the key */ { /* Deletion of the key */
gpg_do_delete_prvkey (kk); gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
return 1; return 1;
} }