Release 0.1.

This commit is contained in:
NIIBE Yutaka 2010-09-09 17:50:34 +09:00
parent 975157c9d8
commit 338b4eac03
11 changed files with 248 additions and 103 deletions

View File

@ -6,7 +6,9 @@ Kaz Kojima:
boards/STM32_PRIMER2/mcuconf.h boards/STM32_PRIMER2/mcuconf.h
boards/STM32_PRIMER2/hw_config.c boards/STM32_PRIMER2/hw_config.c
NIIBE Yutaka: wrote NIIBE Yutaka:
Founder of the project
Wrote
src/ac.c src/ac.c
src/main.c src/main.c
src/usb_lld.h src/usb_lld.h

View File

@ -1,3 +1,30 @@
2010-09-10 NIIBE Yutaka <gniibe@fsij.org>
* src/usb_desc.c (gnukStringSerial): Change the value so that
libccid doesn't get confused.
* src/openpgp.c (gpg_change_keystring): Support key for decryption
as well.
(cmd_read_binary): Use openpgpcard_aid.
(cmd_pso): call ac_reset_pso_other.
* src/openpgp-do.c (openpgpcard_aid): Renamed from aid, and exported.
(do_ds_count_initial_value): New const variable.
(num_prv_keys): New variable.
(gpg_do_write_prvkey): Remove contents of keystring only if
++num_prv_keys == NUM_ALL_PRV_KEYS.
(gpg_do_chks_prvkey): Call flash_do_release.
(gpg_do_table_init): Initialize with do_ds_count_initial_value.
Initialize num_prv_keys.
(gpg_do_write_simple): Support removing DO.
(gpg_do_increment_digital_signature_counter): Call flash_do_release.
* src/gnuk.h (NUM_ALL_PRV_KEYS): New definition.
(OPENPGP_CARD_INITIAL_PW1): New definition.
(enum kind_of_key): Rename.
* src/ac.c (ac_reset_pso_cds): New function.
2010-09-09 Kaz Kojima <kkojima@rr.iij4u.or.jp> 2010-09-09 Kaz Kojima <kkojima@rr.iij4u.or.jp>
* boards/STM32_PRIMER2/{board.c,board.h,board.mk,hw_config.c,mcuconf.h}: * boards/STM32_PRIMER2/{board.c,board.h,board.mk,hw_config.c,mcuconf.h}:
@ -48,6 +75,8 @@
(mpi_write_string, mpi_read_file, mpi_read_file): #if-out to avoid (mpi_write_string, mpi_read_file, mpi_read_file): #if-out to avoid
stdio of libc. stdio of libc.
2010-09-07 NIIBE Yutaka <gniibe@fsij.org>
* gnuk.svg: New file. * gnuk.svg: New file.
2010-09-06 NIIBE Yutaka <gniibe@fsij.org> 2010-09-06 NIIBE Yutaka <gniibe@fsij.org>

12
NEWS
View File

@ -2,18 +2,22 @@ Gnuk NEWS - User visible changes
* Major changes in Gnuk 0.1 * Major changes in Gnuk 0.1
Released 2010-09-XX, by NIIBE Yutaka Released 2010-09-10, by NIIBE Yutaka
** Enabled force_chv1 (in the pw_status_bytes), so that the decipher works.
** Support both of key for digital signing and key for decryption.
** Decipher is supported.
** New board support "STM32 Primer2" is added by Kaz Kojima. ** New board support "STM32 Primer2" is added by Kaz Kojima.
** Now, LED behavior is meaningful. "ON" during execution. ** LED behavior is meaningful now. "ON" during execution.
** Fixed bcdCCID revision number. ** Fixed bcdCCID revision number.
** Logo. ** Logo.
** Decipher is supported.
* Major changes in Gnuk 0.0 * Major changes in Gnuk 0.0

43
README
View File

@ -1,22 +1,31 @@
Gnuk - software for GPG USB Token Gnuk - software for GPG USB Token
Version 0.0 Version 0.1
2010-09-06 2010-09-10
Niibe Yutaka Niibe Yutaka
Free Software Initiative of Japan Free Software Initiative of Japan
What's Gnuk What's Gnuk?
=========== ============
Gnuk is software implementation of a USB token for GNU privacy guard. Gnuk is software implementation of a USB token for GNU privacy guard.
Gnuk supports OpenPGP card protocol version 2, and it runs on STM32 Gnuk supports OpenPGP card protocol version 2, and it runs on STM32
processor. processor.
Please look at the graphics of "gnuk.svg" for the software name.
I wish that Gnuk will be a developer's soother who uses GnuPG. I have
been nervous of storing secret key(s) on usual secondary storage.
While I want to work at different places, but it is not the choice for
me to bring a card reader all the time. With Gnuk, this issue will be
solved by a USB token which is small enough.
Release notes Release notes
============= =============
This is initial release of Gnuk, and it is experimental. This is second release of Gnuk. While it works somehow, it is still
experimental.
Tested features are: Tested features are:
@ -26,17 +35,19 @@ Tested features are:
* Password handling (PW1, RC, PW3) * Password handling (PW1, RC, PW3)
* Key import for signature only. * Key import for both of key for digital signing and key for
decryption.
* PSO: Digital Signature * PSO: Digital Signature
It is known not-working:
* Multiple key import
* PSO: Decipher * PSO: Decipher
It is known not-working well:
* Key import multiple times
* Changing value of password status bytes (0x00C4).
Targets Targets
======= =======
@ -195,6 +206,16 @@ Inside GDB, we can connect OpenOCD by:
(gdb) target remote localhost:3333 (gdb) target remote localhost:3333
You can see output of PCSCD:
# /etc/init.d/pcscd stop
# LIBCCID_ifdLogLevel=7 /usr/sbin/pcscd --debug --foreground
You can observe the traffic of USB using "usbmon". See the file:
linux/Documentation/usb/usbmon.txt
Development history Development history
=================== ===================

View File

@ -22,6 +22,18 @@ ac_check_status (uint8_t ac_flag)
return (ac_flag & auth_status)? 1 : 0; return (ac_flag & auth_status)? 1 : 0;
} }
void
ac_reset_pso_cds (void)
{
auth_status &= ~AC_PSO_CDS_AUTHORIZED;
}
void
ac_reset_pso_other (void)
{
auth_status &= ~AC_PSO_OTHER_AUTHORIZED;
}
int int
verify_pso_cds (const uint8_t *pw, int pw_len) verify_pso_cds (const uint8_t *pw, int pw_len)
{ {
@ -40,7 +52,7 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
keystring[0] = pw_len; keystring[0] = pw_len;
sha1 (pw, pw_len, keystring+1); sha1 (pw, pw_len, keystring+1);
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES); memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0) if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, 1, keystring+1)) < 0)
{ {
pwsb[PW_STATUS_PW1]--; pwsb[PW_STATUS_PW1]--;
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES); gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
@ -56,12 +68,6 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
return 1; return 1;
} }
void
ac_reset_pso_cds (void)
{
auth_status &= ~AC_PSO_CDS_AUTHORIZED;
}
int int
verify_pso_other (const uint8_t *pw, int pw_len) verify_pso_other (const uint8_t *pw, int pw_len)
{ {
@ -79,7 +85,7 @@ verify_pso_other (const uint8_t *pw, int pw_len)
keystring[0] = pw_len; keystring[0] = pw_len;
sha1 (pw, pw_len, keystring+1); sha1 (pw, pw_len, keystring+1);
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES); memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPT, 1, keystring+1)) < 0) if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, 1, keystring+1)) < 0)
{ {
pwsb[PW_STATUS_PW1]--; pwsb[PW_STATUS_PW1]--;
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES); gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);

View File

@ -2,9 +2,6 @@
#define ENABLE_VIRTUAL_COM_PORT 1 #define ENABLE_VIRTUAL_COM_PORT 1
#endif #endif
/* Packet size of USB Bulk transfer for full speed */
#define GNUK_MAX_PACKET_SIZE 64
#if 0 #if 0
/* FSIJ */ /* FSIJ */
#define MANUFACTURER_IN_AID 0xf5, 0x17 #define MANUFACTURER_IN_AID 0xf5, 0x17

View File

@ -58,7 +58,7 @@ extern int verify_admin (const uint8_t *pw, int pw_len);
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known); extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known);
extern void ac_reset_pso_cds (void); extern void ac_reset_pso_cds (void);
extern void ac_reset_pso_other (void);
extern void write_res_apdu (const uint8_t *p, int len, extern void write_res_apdu (const uint8_t *p, int len,
@ -72,8 +72,8 @@ extern void gpg_do_public_key (uint8_t kk_byte);
enum kind_of_key { enum kind_of_key {
GPG_KEY_FOR_SIGNATURE, GPG_KEY_FOR_SIGNING,
GPG_KEY_FOR_DECRYPT, GPG_KEY_FOR_DECRYPTION,
GPG_KEY_FOR_AUTHENTICATION, GPG_KEY_FOR_AUTHENTICATION,
}; };
@ -199,3 +199,9 @@ extern uint32_t hardclock (void);
extern void gpg_do_reset_pw_counter (uint8_t which); extern void gpg_do_reset_pw_counter (uint8_t which);
extern void set_led (int); extern void set_led (int);
#define NUM_ALL_PRV_KEYS 2 /* SIG and DEC *//* we don't support AUT yet */
#define OPENPGP_CARD_INITIAL_PW1 "123456"
const uint8_t openpgpcard_aid[17] __attribute__ ((aligned (1)));

View File

@ -39,7 +39,7 @@
*/ */
/* AID */ /* AID */
static const uint8_t aid[] __attribute__ ((aligned (1))) = { const uint8_t openpgpcard_aid[17] __attribute__ ((aligned (1))) = {
16, 16,
0xd2, 0x76, 0x00, 0x01, 0x24, 0x01, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x02, 0x00, /* Version 2.0 */ 0x02, 0x00, /* Version 2.0 */
@ -87,10 +87,14 @@ static const uint8_t algorithm_attr[] __attribute__ ((aligned (1))) = {
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */ 0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
}; };
static const uint8_t do_pw_status_bytes_template[] = static const uint8_t do_ds_count_initial_value[] __attribute__ ((aligned (1))) = {
{ 3,
0, 0, 0
};
static const uint8_t do_pw_status_bytes_template[] __attribute__ ((aligned (1))) = {
7, 7,
1, /* PW1 valid for several PSO:CDS commands */ 0, /* PW1 is valid for single PSO:CDS command */
127, 127, 127, /* max length of PW1, RC, and PW3 */ 127, 127, 127, /* max length of PW1, RC, and PW3 */
3, 0, 3 /* Error counter of PW1, RC, and PW3 */ 3, 0, 3 /* Error counter of PW1, RC, and PW3 */
}; };
@ -483,9 +487,9 @@ get_do_ptr_nr_for_kk (enum kind_of_key kk)
{ {
switch (kk) switch (kk)
{ {
case GPG_KEY_FOR_SIGNATURE: case GPG_KEY_FOR_SIGNING:
return NR_DO_PRVKEY_SIG; return NR_DO_PRVKEY_SIG;
case GPG_KEY_FOR_DECRYPT: case GPG_KEY_FOR_DECRYPTION:
return NR_DO_PRVKEY_DEC; return NR_DO_PRVKEY_DEC;
case GPG_KEY_FOR_AUTHENTICATION: case GPG_KEY_FOR_AUTHENTICATION:
return NR_DO_PRVKEY_AUT; return NR_DO_PRVKEY_AUT;
@ -521,7 +525,7 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n"); DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n");
return -1; return -1;
} }
/* XXX: more sanity check */ /* more sanity check??? */
return 1; return 1;
} }
@ -538,6 +542,8 @@ calc_check32 (const uint8_t *p, int len)
return check; return check;
} }
static int8_t num_prv_keys;
int int
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
const uint8_t *keystring) const uint8_t *keystring)
@ -549,8 +555,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
struct prvkey_data *pd; struct prvkey_data *pd;
uint8_t *key_addr; uint8_t *key_addr;
const uint8_t *dek; const uint8_t *dek;
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1); const uint8_t *do_data = do_ptr[nr];
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC); const uint8_t *ks_pw1;
const uint8_t *ks_rc;
#if 0 #if 0
assert (key_len == KEY_CONTENT_LEN); assert (key_len == KEY_CONTENT_LEN);
@ -587,19 +594,42 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
kd.random = get_random (); kd.random = get_random ();
memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN); memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
DEBUG_INFO ("enc..."); if (do_data) /* We have old prvkey */
{
/* Write new prvkey resetting PW1 and RC */
/* Note: if you have other prvkey(s), it becomes bogus */
memcpy (pd, do_data+1, sizeof (struct prvkey_data));
decrypt (keystring_md_pw3, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
dek = pd->dek_encrypted_3;
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
flash_do_release (do_data);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
flash_key_release (pd->key_addr);
flash_do_release (do_data);
ks_pw1 = NULL;
ks_rc = NULL;
}
else
{
dek = random_bytes_get (); /* 16-byte random bytes */
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
}
dek = random_bytes_get (); /* 16-byte random bytes */
encrypt (dek, (uint8_t *)&kd, sizeof (struct key_data)); encrypt (dek, (uint8_t *)&kd, sizeof (struct key_data));
DEBUG_INFO ("done\r\n");
r = flash_key_write (key_addr, kd.data, modulus); r = flash_key_write (key_addr, kd.data, modulus);
modulus_free (modulus); modulus_free (modulus);
if (r < 0) if (r < 0)
{ {
random_bytes_free (dek); if (do_data == NULL)
random_bytes_free (dek);
free (pd); free (pd);
return r; return r;
} }
@ -609,49 +639,49 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
ac_reset_pso_cds (); ac_reset_pso_cds ();
if (ks_pw1) if (ks_pw1)
{ encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
uint8_t ks_pw1_len = ks_pw1[0];
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
/* Only its length */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
}
else else
{ {
uint8_t ks123_pw1[KEYSTRING_SIZE_PW1]; uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
ks123_pw1[0] = 6; ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1);
sha1 ((uint8_t *)"123456", 6, ks123_pw1+1); sha1 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1, 6, ks123_pw1+1);
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE); encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
/* Only but its length */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks123_pw1, 1);
} }
if (ks_rc) if (ks_rc)
{ encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
uint8_t ks_rc_len = ks_rc[0];
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
/* Only its length */
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
}
else else
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE); memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE); encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr] = p; do_ptr[nr] = p;
random_bytes_free (dek); if (do_data == NULL)
random_bytes_free (dek);
free (pd); free (pd);
if (p == NULL) if (p == NULL)
return -1; return -1;
if (do_data == NULL
&& ++num_prv_keys == NUM_ALL_PRV_KEYS) /* All keys are registered. */
{
/* Remove contents of keystrings from DO, but length */
if (ks_pw1)
{
uint8_t ks_pw1_len = ks_pw1[0];
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
}
if (ks_rc)
{
uint8_t ks_rc_len = ks_rc[0];
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
}
}
return 0; return 0;
} }
@ -685,6 +715,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data)); p = flash_do_write (nr, (const uint8_t *)pd, sizeof (struct prvkey_data));
do_ptr[nr] = p; do_ptr[nr] = p;
flash_do_release (do_data);
free (pd); free (pd);
if (p == NULL) if (p == NULL)
return -1; return -1;
@ -710,9 +741,9 @@ proc_key_import (const uint8_t *data, int len)
DEBUG_BINARY (data, len); DEBUG_BINARY (data, len);
if (data[4] == 0xb6) if (data[4] == 0xb6)
kk = GPG_KEY_FOR_SIGNATURE; kk = GPG_KEY_FOR_SIGNING;
else if (data[4] == 0xb8) else if (data[4] == 0xb8)
kk = GPG_KEY_FOR_DECRYPT; kk = GPG_KEY_FOR_DECRYPTION;
else /* 0xa4 */ else /* 0xa4 */
kk = GPG_KEY_FOR_AUTHENTICATION; kk = GPG_KEY_FOR_AUTHENTICATION;
@ -721,15 +752,23 @@ proc_key_import (const uint8_t *data, int len)
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];
/* Delete the key */
if (do_data) if (do_data)
{ {
uint8_t *key_addr = *(uint8_t **)&do_data[1]; uint8_t *key_addr = *(uint8_t **)&do_data[1];
flash_do_release (do_data);
flash_key_release (key_addr); flash_key_release (key_addr);
flash_do_release (do_data);
}
do_ptr[nr] = NULL;
if (--num_prv_keys == 0)
{
/* Delete PW1 and RC if any */
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, NULL, 0);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, NULL, 0);
} }
do_ptr[nr] = NULL;
GPG_SUCCESS (); GPG_SUCCESS ();
return; return;
} }
@ -801,11 +840,11 @@ gpg_do_table[] = {
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED, { GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_pw_status }, rw_pw_status },
/* Fixed data */ /* Fixed data */
{ GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid }, { GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, openpgpcard_aid },
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
{ GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr }, { GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
{ GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr }, { GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, NULL }, { GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
/* Compound data: Read access only */ /* Compound data: Read access only */
{ GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data }, { GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data },
{ GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data }, { GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data },
@ -829,6 +868,7 @@ gpg_do_table_init (void)
const uint8_t *p, *p_start; const uint8_t *p, *p_start;
int len; int len;
do_ptr[NR_DO_DS_COUNT] = do_ds_count_initial_value;
do_ptr[NR_DO_PW_STATUS] = do_pw_status_bytes_template; do_ptr[NR_DO_PW_STATUS] = do_pw_status_bytes_template;
p_start = flash_do_pool (); p_start = flash_do_pool ();
@ -863,6 +903,13 @@ gpg_do_table_init (void)
flash_set_do_pool_last (p); flash_set_do_pool_last (p);
num_prv_keys = 0;
if (do_ptr[NR_DO_PRVKEY_SIG] != NULL)
num_prv_keys++;
if (do_ptr[NR_DO_PRVKEY_DEC] != NULL)
num_prv_keys++;
if (do_ptr[NR_DO_PRVKEY_AUT] != NULL)
num_prv_keys++;
return 0; return 0;
} }
@ -1171,11 +1218,19 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
if (*do_data_p) if (*do_data_p)
flash_do_release (*do_data_p); flash_do_release (*do_data_p);
*do_data_p = flash_do_write (nr, data, size); if (data != NULL)
if (*do_data_p) {
GPG_SUCCESS (); *do_data_p = flash_do_write (nr, data, size);
if (*do_data_p)
GPG_SUCCESS ();
else
GPG_MEMORY_FAILURE();
}
else else
GPG_MEMORY_FAILURE(); {
*do_data_p = NULL;
GPG_SUCCESS ();
}
} }
void void
@ -1196,6 +1251,7 @@ gpg_do_increment_digital_signature_counter (void)
count_data[1] = (count >> 8) & 0xff; count_data[1] = (count >> 8) & 0xff;
count_data[2] = count & 0xff; count_data[2] = count & 0xff;
flash_do_release (do_data);
do_ptr[NR_DO_DS_COUNT] = flash_do_write (NR_DO_DS_COUNT, count_data, do_ptr[NR_DO_DS_COUNT] = flash_do_write (NR_DO_DS_COUNT, count_data,
SIZE_DIGITAL_SIGNATURE_COUNTER); SIZE_DIGITAL_SIGNATURE_COUNTER);
} }

View File

@ -60,11 +60,6 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
0x00, 0x00 /* PIN status: OK, PIN blocked?: No */ 0x00, 0x00 /* PIN status: OK, PIN blocked?: No */
}; };
static const uint8_t
read_binary_result[] __attribute__ ((aligned (1))) = {
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
};
void void
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2) write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
{ {
@ -129,17 +124,37 @@ int
gpg_change_keystring (int who_old, const uint8_t *old_ks, gpg_change_keystring (int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks) int who_new, const uint8_t *new_ks)
{ {
int r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, who_old, old_ks); int r;
int prv_keys_exist = 0;
if (r <= 0) r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks);
if (r < 0)
return r; return r;
r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNATURE, who_old, old_ks, if (r > 0)
prv_keys_exist++;
r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks,
who_new, new_ks); who_new, new_ks);
if (r < 0) if (r < 0)
return -2; return -2;
return r; r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks);
if (r < 0)
return r;
if (r > 0)
prv_keys_exist++;
r = gpg_do_chks_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks,
who_new, new_ks);
if (r < 0)
return -2;
if (prv_keys_exist)
return 1;
else
return 0;
} }
static void static void
@ -171,21 +186,16 @@ cmd_change_password (void)
if (pk == NULL) if (pk == NULL)
{ {
if (len < 6) if (len < (int)strlen (OPENPGP_CARD_INITIAL_PW1))
{ {
DEBUG_INFO ("permission denied.\r\n"); DEBUG_INFO ("permission denied.\r\n");
GPG_SECURITY_FAILURE (); GPG_SECURITY_FAILURE ();
return; return;
} }
/* pk==NULL implies we have no prvkey */ pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
pw_len = 6;
newpw = pw + pw_len; newpw = pw + pw_len;
newpw_len = len - pw_len; newpw_len = len - pw_len;
sha1 (newpw, newpw_len, new_ks);
new_ks0[0] = newpw_len;
goto no_prvkey;
} }
else else
{ {
@ -235,18 +245,17 @@ cmd_change_password (void)
} }
else if (r == 0 && who == 1) /* no prvkey */ else if (r == 0 && who == 1) /* no prvkey */
{ {
no_prvkey:
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1); gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
ac_reset_pso_cds (); ac_reset_pso_cds ();
gpg_do_reset_pw_counter (PW_STATUS_PW1); gpg_do_reset_pw_counter (PW_STATUS_PW1);
DEBUG_INFO ("Changed DO_KEYSTRING_PW1\r\n"); DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
} }
else if (r > 0 && who == 1) else if (r > 0 && who == 1)
{ {
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1); gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
ac_reset_pso_cds (); ac_reset_pso_cds ();
gpg_do_reset_pw_counter (PW_STATUS_PW1); gpg_do_reset_pw_counter (PW_STATUS_PW1);
DEBUG_INFO ("Removed content of DO_KEYSTRING_PW1\r\n"); DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
} }
else /* r >= 0 && who == 3 */ else /* r >= 0 && who == 3 */
{ {
@ -435,9 +444,15 @@ cmd_read_binary (void)
if (cmd_APDU[3] >= 6) if (cmd_APDU[3] >= 6)
GPG_BAD_P0_P1 (); GPG_BAD_P0_P1 ();
else else
/* Tag 5a, serial number */ {
write_res_apdu (read_binary_result, int len = openpgpcard_aid[0];
sizeof (read_binary_result), 0x90, 0x00);
res_APDU[0] = 0x5a;
memcpy (res_APDU+1, openpgpcard_aid, len);
res_APDU[len+1] = 0x90;
res_APDU[len+2] = 0x00;
res_APDU_size = len + 3;
}
} }
else else
GPG_NO_RECORD(); GPG_NO_RECORD();
@ -545,7 +560,10 @@ cmd_pso (void)
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len); r = rsa_sign (&cmd_APDU[data_start], res_APDU, len);
if (r < 0) if (r < 0)
GPG_ERROR (); {
ac_reset_pso_cds ();
GPG_ERROR ();
}
else else
{ /* Success */ { /* Success */
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS); const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
@ -572,6 +590,8 @@ cmd_pso (void)
DEBUG_SHORT (len); DEBUG_SHORT (len);
ac_reset_pso_other ();
/* Skip padding 0x00 */ /* Skip padding 0x00 */
data_start++; data_start++;
len--; len--;

View File

@ -193,9 +193,10 @@ static const uint8_t gnukStringProduct[] = {
}; };
static const uint8_t gnukStringSerial[] = { static const uint8_t gnukStringSerial[] = {
8, /* bLength */ 8*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'2', 0, '.', 0, '0', 0 '2', 0, '0', 0, '1', 0, '0', 0,
'0', 0, '9', 0, '1', 0, '0', 0
}; };
const ONE_DESCRIPTOR Device_Descriptor = { const ONE_DESCRIPTOR Device_Descriptor = {

View File

@ -21,6 +21,9 @@
* *
*/ */
/* Packet size of USB Bulk transfer for full speed */
#define GNUK_MAX_PACKET_SIZE 64
#include "config.h" #include "config.h"
#include "usb_lib.h" #include "usb_lib.h"
#include "usb_conf.h" #include "usb_conf.h"