works now again
This commit is contained in:
19
README
19
README
@@ -1,7 +1,9 @@
|
|||||||
Gnuk - software for GPG USB Token
|
Gnuk - software for GPG USB Token
|
||||||
|
|
||||||
Version 0.0 2010-09-05
|
Version 0.0
|
||||||
|
2010-09-06
|
||||||
Niibe Yutaka
|
Niibe Yutaka
|
||||||
|
Free Software Initiative of Japan
|
||||||
|
|
||||||
What's Gnuk
|
What's Gnuk
|
||||||
===========
|
===========
|
||||||
@@ -14,8 +16,7 @@ processor.
|
|||||||
Release notes
|
Release notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is initial release of Gnuk, and it is experimental yet.
|
This is initial release of Gnuk, and it is experimental.
|
||||||
It is not yet daily use.
|
|
||||||
|
|
||||||
Supported and tested features are:
|
Supported and tested features are:
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ Supported and tested features are:
|
|||||||
|
|
||||||
* Password handling (PW1, RC, PW3)
|
* Password handling (PW1, RC, PW3)
|
||||||
|
|
||||||
* Single key import
|
* Single key import for signature.
|
||||||
|
|
||||||
* PSO: Digital Signature
|
* PSO: Digital Signature
|
||||||
|
|
||||||
@@ -107,6 +108,13 @@ Type:
|
|||||||
|
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
|
In the make process, it takes time for the command of
|
||||||
|
|
||||||
|
dd if=/dev/random bs=1 of=random_bits count=1024
|
||||||
|
|
||||||
|
Don't just wait, but do some other work on your PC.
|
||||||
|
/dev/random needs entropy to finish.
|
||||||
|
|
||||||
Then, we will have "gnuk.elf".
|
Then, we will have "gnuk.elf".
|
||||||
|
|
||||||
|
|
||||||
@@ -134,7 +142,6 @@ virtual COM port by:
|
|||||||
|
|
||||||
and you will see debug output of Gnuk.
|
and you will see debug output of Gnuk.
|
||||||
|
|
||||||
|
|
||||||
For libccid, we need following change:
|
For libccid, we need following change:
|
||||||
|
|
||||||
--- /etc/libccid_Info.plist.dpkg-dist 2009-07-29 06:50:20.000000000 +0900
|
--- /etc/libccid_Info.plist.dpkg-dist 2009-07-29 06:50:20.000000000 +0900
|
||||||
@@ -171,7 +178,7 @@ Then, try following to see Gnuk runs:
|
|||||||
$ gpg --card-status
|
$ gpg --card-status
|
||||||
|
|
||||||
|
|
||||||
For more, see doc/HOWTO_GNUK.
|
For more, see doc/HOWTO-GNUK.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
30
doc/HACKING
Normal file
30
doc/HACKING
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
* Random Number Generator
|
||||||
|
|
||||||
|
RNG is needed for Data Encryption Key to encrypt private key (P and Q).
|
||||||
|
It is important to collect enough entropy. Perhaps, it would
|
||||||
|
be possible to get entropy from USB traffic (of other devices).
|
||||||
|
|
||||||
|
|
||||||
|
* RSA
|
||||||
|
|
||||||
|
It would be good not to use malloc.
|
||||||
|
|
||||||
|
|
||||||
|
* Manufacture ID
|
||||||
|
|
||||||
|
Get it from FSFE.
|
||||||
|
|
||||||
|
|
||||||
|
* Serial number
|
||||||
|
|
||||||
|
Currently, aid[] in openpgp-do.c has serial number 00000001.
|
||||||
|
It would be good to generate (random) number at compile time.
|
||||||
|
|
||||||
|
|
||||||
|
* Flash ROM recover from shutdown
|
||||||
|
|
||||||
|
|
||||||
|
* Flash ROM garbage collection
|
||||||
|
|
||||||
|
|
||||||
|
* Flash ROM protection
|
||||||
13
doc/NOTES
13
doc/NOTES
@@ -2,21 +2,20 @@ USB communication
|
|||||||
=================
|
=================
|
||||||
|
|
||||||
* No command chaining, but extended APDU and extended Lc and Le
|
* No command chaining, but extended APDU and extended Lc and Le
|
||||||
|
|
||||||
* dwMaxCCIDMessageLength: 64
|
* dwMaxCCIDMessageLength: 64
|
||||||
|
|
||||||
|
|
||||||
OpenPGP card protocol implementation
|
OpenPGP card protocol implementation
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
* No clear password(s)
|
I try to follow "no clear password(s)" policy.
|
||||||
|
After key import, keystrings are also removed.
|
||||||
PW1
|
But because of this, we only support single key for this version.
|
||||||
|
|
||||||
* Support of Resetting code
|
|
||||||
|
|
||||||
|
|
||||||
KEY
|
How a private key is stored
|
||||||
=======
|
===========================
|
||||||
|
|
||||||
KEYPTR
|
KEYPTR
|
||||||
----> [ P ][ Q ][ N ]
|
----> [ P ][ Q ][ N ]
|
||||||
|
|||||||
17
src/Makefile
17
src/Makefile
@@ -89,7 +89,8 @@ CSRC = $(PORTSRC) \
|
|||||||
$(CRYPTSRC) \
|
$(CRYPTSRC) \
|
||||||
main.c usb_lld.c \
|
main.c usb_lld.c \
|
||||||
hw_config.c usb_desc.c usb_prop.c \
|
hw_config.c usb_desc.c usb_prop.c \
|
||||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c random.c
|
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c \
|
||||||
|
random.c
|
||||||
|
|
||||||
ifneq ($(ENABLE_DEBUG),)
|
ifneq ($(ENABLE_DEBUG),)
|
||||||
CSRC += debug.c
|
CSRC += debug.c
|
||||||
@@ -203,3 +204,17 @@ ifeq ($(USE_FWLIB),yes)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
|
include $(CHIBIOS)/os/ports/GCC/ARM/rules.mk
|
||||||
|
|
||||||
|
OBJS += random-data.o
|
||||||
|
OUTFILES += random_bits
|
||||||
|
|
||||||
|
random_bits:
|
||||||
|
dd if=/dev/random bs=1 of=random_bits count=1024
|
||||||
|
|
||||||
|
random-data.o: random_bits
|
||||||
|
$(CP) -I binary $< -O elf32-littlearm -B arm \
|
||||||
|
--rename-section \
|
||||||
|
.data=.gnuk_random,alloc,load,readonly,data,contents \
|
||||||
|
$@
|
||||||
|
|
||||||
|
$(PROJECT).elf: random-data.o
|
||||||
|
|||||||
9
src/ac.c
9
src/ac.c
@@ -34,6 +34,9 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
DEBUG_INFO ("verify_pso_cds\r\n");
|
||||||
|
DEBUG_BYTE (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);
|
||||||
@@ -43,7 +46,7 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
|
|||||||
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);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else
|
else if (pwsb[PW_STATUS_PW1] != 3)
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1] = 3;
|
pwsb[PW_STATUS_PW1] = 3;
|
||||||
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);
|
||||||
@@ -80,7 +83,7 @@ verify_pso_other (const uint8_t *pw, int pw_len)
|
|||||||
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);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else
|
else if (pwsb[PW_STATUS_PW1] != 3)
|
||||||
{
|
{
|
||||||
pwsb[PW_STATUS_PW1] = 3;
|
pwsb[PW_STATUS_PW1] = 3;
|
||||||
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);
|
||||||
@@ -162,7 +165,7 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
|||||||
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);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else if (pwsb[PW_STATUS_PW3] != 3)
|
||||||
{ /* OK, the user is now authenticated */
|
{ /* OK, the user is now authenticated */
|
||||||
pwsb[PW_STATUS_PW3] = 3;
|
pwsb[PW_STATUS_PW3] = 3;
|
||||||
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);
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ flash_do_write (uint8_t nr, const uint8_t *data, int len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hw |= data[0]<<8;
|
hw |= (data[0]<<8);
|
||||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||||
return NULL;
|
return NULL;
|
||||||
addr += 2;
|
addr += 2;
|
||||||
|
|||||||
@@ -185,10 +185,10 @@ extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
|||||||
|
|
||||||
#define SIZE_PW_STATUS_BYTES 7
|
#define SIZE_PW_STATUS_BYTES 7
|
||||||
|
|
||||||
extern uint8_t *get_data_encryption_key (void); /* 16-byte random bytes */
|
/* 32-byte random bytes */
|
||||||
extern void dek_free (uint8_t *);
|
|
||||||
extern uint32_t get_random (void);
|
extern uint32_t get_random (void);
|
||||||
extern void random_init (void);
|
extern const uint8_t *random_bytes_get (void);
|
||||||
|
extern void random_bytes_free (const uint8_t *);
|
||||||
|
|
||||||
extern uint32_t hardclock (void);
|
extern uint32_t hardclock (void);
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ SECTIONS
|
|||||||
PROVIDE(end = .);
|
PROVIDE(end = .);
|
||||||
_end = .;
|
_end = .;
|
||||||
|
|
||||||
|
.gnuk_random : ALIGN (1024)
|
||||||
|
{
|
||||||
|
*(.gnuk_random)
|
||||||
|
} > flash
|
||||||
|
|
||||||
.gnuk_flash : ALIGN (1024)
|
.gnuk_flash : ALIGN (1024)
|
||||||
{
|
{
|
||||||
_do_pool = .;
|
_do_pool = .;
|
||||||
|
|||||||
17
src/main.c
17
src/main.c
@@ -173,7 +173,6 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
eventmask_t m;
|
eventmask_t m;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
uint8_t once = 0;
|
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
@@ -200,8 +199,6 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
uint32_t r;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (palReadPad(IOPORT1, GPIOA_BUTTON))
|
if (palReadPad(IOPORT1, GPIOA_BUTTON))
|
||||||
palSetPad (IOPORT3, GPIOC_LED);
|
palSetPad (IOPORT3, GPIOC_LED);
|
||||||
@@ -211,23 +208,15 @@ main (int argc, char **argv)
|
|||||||
if (m == EV_LED)
|
if (m == EV_LED)
|
||||||
palClearPad (IOPORT3, GPIOC_LED);
|
palClearPad (IOPORT3, GPIOC_LED);
|
||||||
|
|
||||||
if (once == 0 && bDeviceState == CONFIGURED)
|
#ifdef DEBUG_MORE
|
||||||
{
|
|
||||||
random_init ();
|
|
||||||
once = 1;
|
|
||||||
r = get_random ();
|
|
||||||
DEBUG_WORD (r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bDeviceState == CONFIGURED && (count % 100) == 0)
|
if (bDeviceState == CONFIGURED && (count % 100) == 0)
|
||||||
{
|
{
|
||||||
r = get_random ();
|
DEBUG_WORD (count / 100);
|
||||||
|
|
||||||
DEBUG_WORD (r);
|
|
||||||
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
||||||
"Testing USB driver.\n\n"
|
"Testing USB driver.\n\n"
|
||||||
"Hello world\r\n\r\n", 47+21+15);
|
"Hello world\r\n\r\n", 47+21+15);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m = chEvtWaitOneTimeout (ALL_EVENTS, 100);
|
m = chEvtWaitOneTimeout (ALL_EVENTS, 100);
|
||||||
if (m == EV_LED)
|
if (m == EV_LED)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* AID */
|
/* AID */
|
||||||
static const uint8_t const aid[] __attribute__ ((aligned (1))) = {
|
static const uint8_t aid[] __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 */
|
||||||
@@ -48,7 +48,7 @@ static const uint8_t const aid[] __attribute__ ((aligned (1))) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Historical Bytes (template) */
|
/* Historical Bytes (template) */
|
||||||
static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = {
|
static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
|
||||||
10,
|
10,
|
||||||
0x00,
|
0x00,
|
||||||
0x31, 0x80, /* Full DF name */
|
0x31, 0x80, /* Full DF name */
|
||||||
@@ -61,7 +61,7 @@ static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Extended Capabilities */
|
/* Extended Capabilities */
|
||||||
static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1))) = {
|
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
|
||||||
10,
|
10,
|
||||||
0x30, /*
|
0x30, /*
|
||||||
* No SM, No get challenge,
|
* No SM, No get challenge,
|
||||||
@@ -78,7 +78,7 @@ static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1)))
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Algorithm Attributes */
|
/* Algorithm Attributes */
|
||||||
static const uint8_t const algorithm_attr[] __attribute__ ((aligned (1))) = {
|
static const uint8_t algorithm_attr[] __attribute__ ((aligned (1))) = {
|
||||||
6,
|
6,
|
||||||
0x01, /* RSA */
|
0x01, /* RSA */
|
||||||
0x08, 0x00, /* Length modulus (in bit): 2048 */
|
0x08, 0x00, /* Length modulus (in bit): 2048 */
|
||||||
@@ -86,7 +86,7 @@ static const uint8_t const 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 const do_pw_status_bytes_template[] =
|
static const uint8_t do_pw_status_bytes_template[] =
|
||||||
{
|
{
|
||||||
7,
|
7,
|
||||||
1, /* PW1 valid for several PSO:CDS commands */
|
1, /* PW1 valid for several PSO:CDS commands */
|
||||||
@@ -543,7 +543,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
const uint8_t *modulus;
|
const uint8_t *modulus;
|
||||||
struct prvkey_data *pd;
|
struct prvkey_data *pd;
|
||||||
uint8_t *key_addr;
|
uint8_t *key_addr;
|
||||||
uint8_t *dek;
|
const uint8_t *dek;
|
||||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||||
|
|
||||||
@@ -584,7 +584,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
|
|
||||||
DEBUG_INFO ("enc...");
|
DEBUG_INFO ("enc...");
|
||||||
|
|
||||||
dek = get_data_encryption_key (); /* 16-byte random bytes */
|
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");
|
DEBUG_INFO ("done\r\n");
|
||||||
@@ -594,7 +594,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
dek_free (dek);
|
random_bytes_free (dek);
|
||||||
free (pd);
|
free (pd);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -605,10 +605,12 @@ 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)
|
||||||
{
|
{
|
||||||
|
uint8_t ks_pw1_len = ks_pw1[0];
|
||||||
|
|
||||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
/* Only its length */
|
/* Only its length */
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks_pw1, 1);
|
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -624,10 +626,12 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
|
|
||||||
if (ks_rc)
|
if (ks_rc)
|
||||||
{
|
{
|
||||||
|
uint8_t ks_rc_len = ks_rc[0];
|
||||||
|
|
||||||
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
|
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
|
encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
|
||||||
/* Only its length */
|
/* Only its length */
|
||||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, ks_rc, 1);
|
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);
|
||||||
@@ -638,7 +642,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
|||||||
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;
|
||||||
|
|
||||||
dek_free (dek);
|
random_bytes_free (dek);
|
||||||
free (pd);
|
free (pd);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1086,9 +1090,10 @@ void
|
|||||||
gpg_do_public_key (uint8_t kk_byte)
|
gpg_do_public_key (uint8_t kk_byte)
|
||||||
{
|
{
|
||||||
const uint8_t *do_data;
|
const uint8_t *do_data;
|
||||||
uint8_t *key_addr;
|
const uint8_t *key_addr;
|
||||||
|
|
||||||
DEBUG_INFO ("Public key\r\n");
|
DEBUG_INFO ("Public key\r\n");
|
||||||
|
DEBUG_BYTE (kk_byte);
|
||||||
|
|
||||||
if (kk_byte == 0xb6)
|
if (kk_byte == 0xb6)
|
||||||
do_data = do_ptr[NR_DO_PRVKEY_SIG];
|
do_data = do_ptr[NR_DO_PRVKEY_SIG];
|
||||||
@@ -1104,7 +1109,7 @@ gpg_do_public_key (uint8_t kk_byte)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_addr = *(uint8_t **)&do_data[1];
|
key_addr = *(const uint8_t **)&do_data[1];
|
||||||
|
|
||||||
res_p = res_APDU;
|
res_p = res_APDU;
|
||||||
|
|
||||||
@@ -1200,12 +1205,18 @@ gpg_do_reset_pw_counter (uint8_t which)
|
|||||||
if (do_data)
|
if (do_data)
|
||||||
{
|
{
|
||||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
||||||
|
if (pwsb[which] == 3)
|
||||||
|
return;
|
||||||
|
|
||||||
pwsb[which] = 3;
|
pwsb[which] = 3;
|
||||||
flash_do_release (do_data);
|
flash_do_release (do_data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy (pwsb, PW_STATUS_BYTES_TEMPLATE, SIZE_PW_STATUS_BYTES);
|
memcpy (pwsb, PW_STATUS_BYTES_TEMPLATE, SIZE_PW_STATUS_BYTES);
|
||||||
|
if (pwsb[which] == 3)
|
||||||
|
return;
|
||||||
|
|
||||||
pwsb[which] = 3;
|
pwsb[which] = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
#define INS_PUT_DATA 0xda
|
#define INS_PUT_DATA 0xda
|
||||||
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
||||||
|
|
||||||
static const uint8_t const
|
static const uint8_t
|
||||||
select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
||||||
0x00, 0x00, /* unused */
|
0x00, 0x00, /* unused */
|
||||||
0x0b, 0x10, /* number of bytes in this directory */
|
0x0b, 0x10, /* number of bytes in this directory */
|
||||||
@@ -60,7 +60,7 @@ 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 const
|
static const uint8_t
|
||||||
read_binary_result[] __attribute__ ((aligned (1))) = {
|
read_binary_result[] __attribute__ ((aligned (1))) = {
|
||||||
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
||||||
};
|
};
|
||||||
@@ -89,17 +89,24 @@ cmd_verify (void)
|
|||||||
int len;
|
int len;
|
||||||
uint8_t p2 = cmd_APDU[3];
|
uint8_t p2 = cmd_APDU[3];
|
||||||
int r;
|
int r;
|
||||||
|
int data_start = 5;
|
||||||
|
|
||||||
DEBUG_INFO (" - VERIFY\r\n");
|
DEBUG_INFO (" - VERIFY\r\n");
|
||||||
DEBUG_BYTE (p2);
|
DEBUG_BYTE (p2);
|
||||||
|
|
||||||
len = cmd_APDU[4];
|
len = cmd_APDU[4];
|
||||||
|
if (len == 0) /* extended length */
|
||||||
|
{
|
||||||
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
|
data_start = 7;
|
||||||
|
}
|
||||||
|
|
||||||
if (p2 == 0x81)
|
if (p2 == 0x81)
|
||||||
r = verify_pso_cds (&cmd_APDU[5], len);
|
r = verify_pso_cds (&cmd_APDU[data_start], len);
|
||||||
else if (p2 == 0x82)
|
else if (p2 == 0x82)
|
||||||
r = verify_pso_other (&cmd_APDU[5], len);
|
r = verify_pso_other (&cmd_APDU[data_start], len);
|
||||||
else
|
else
|
||||||
r = verify_admin (&cmd_APDU[5], len);
|
r = verify_admin (&cmd_APDU[data_start], len);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
@@ -152,6 +159,12 @@ cmd_change_password (void)
|
|||||||
DEBUG_INFO ("Change PW\r\n");
|
DEBUG_INFO ("Change PW\r\n");
|
||||||
DEBUG_BYTE (who);
|
DEBUG_BYTE (who);
|
||||||
|
|
||||||
|
if (len == 0) /* extended length */
|
||||||
|
{
|
||||||
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
|
pw += 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (who == 1) /* PW1 */
|
if (who == 1) /* PW1 */
|
||||||
{
|
{
|
||||||
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||||
@@ -169,6 +182,9 @@ cmd_change_password (void)
|
|||||||
pw_len = 6;
|
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;
|
goto no_prvkey;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -244,22 +260,28 @@ static void
|
|||||||
cmd_reset_user_password (void)
|
cmd_reset_user_password (void)
|
||||||
{
|
{
|
||||||
uint8_t p1 = cmd_APDU[2];
|
uint8_t p1 = cmd_APDU[2];
|
||||||
int len = cmd_APDU[3];
|
int len = cmd_APDU[4];
|
||||||
const uint8_t *pw = &cmd_APDU[4];
|
const uint8_t *pw = &cmd_APDU[5];
|
||||||
const uint8_t *newpw;
|
const uint8_t *newpw;
|
||||||
int pw_len, newpw_len;
|
int pw_len, newpw_len;
|
||||||
int r;
|
int r;
|
||||||
|
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||||
|
uint8_t *new_ks = &new_ks0[1];
|
||||||
|
|
||||||
DEBUG_INFO ("Reset PW1\r\n");
|
DEBUG_INFO ("Reset PW1\r\n");
|
||||||
DEBUG_BYTE (p1);
|
DEBUG_BYTE (p1);
|
||||||
|
|
||||||
|
if (len == 0) /* extended length */
|
||||||
|
{
|
||||||
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
|
pw += 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (p1 == 0x00) /* by User with Reseting Code */
|
if (p1 == 0x00) /* by User with Reseting Code */
|
||||||
{
|
{
|
||||||
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);
|
||||||
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
|
||||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
|
||||||
uint8_t *new_ks = &new_ks0[1];
|
|
||||||
|
|
||||||
if (pw_status_bytes == NULL
|
if (pw_status_bytes == NULL
|
||||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||||
@@ -318,16 +340,14 @@ cmd_reset_user_password (void)
|
|||||||
}
|
}
|
||||||
else /* by Admin (p1 == 0x02) */
|
else /* by Admin (p1 == 0x02) */
|
||||||
{
|
{
|
||||||
|
const uint8_t *old_ks = keystring_md_pw3;
|
||||||
|
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("permission denied.\r\n");
|
DEBUG_INFO ("permission denied.\r\n");
|
||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
const uint8_t *old_ks = keystring_md_pw3;
|
|
||||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
|
||||||
uint8_t *new_ks = &new_ks0[1];
|
|
||||||
|
|
||||||
newpw_len = len;
|
newpw_len = len;
|
||||||
newpw = pw;
|
newpw = pw;
|
||||||
@@ -360,7 +380,6 @@ cmd_reset_user_password (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_put_data (void)
|
cmd_put_data (void)
|
||||||
@@ -395,7 +414,7 @@ cmd_pgp_gakp (void)
|
|||||||
|
|
||||||
if (cmd_APDU[2] == 0x81)
|
if (cmd_APDU[2] == 0x81)
|
||||||
/* Get public key */
|
/* Get public key */
|
||||||
gpg_do_public_key (cmd_APDU[5]);
|
gpg_do_public_key (cmd_APDU[7]);
|
||||||
else
|
else
|
||||||
{ /* Generate key pair */
|
{ /* Generate key pair */
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
|
|||||||
90
src/random.c
90
src/random.c
@@ -1,59 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* random.c -- get random bytes
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
*
|
||||||
|
* Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
|
|
||||||
/*
|
extern void *_binary_random_bits_start;
|
||||||
* XXX: I have tried havege_rand, but it requires too much memory...
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
const uint8_t *
|
||||||
* Multiply-with-carry method by George Marsaglia
|
random_bytes_get (void)
|
||||||
*/
|
{
|
||||||
static uint32_t m_w;
|
uint32_t addr;
|
||||||
static uint32_t m_z;
|
|
||||||
|
addr = (uint32_t)&_binary_random_bits_start + ((hardclock () << 5) & 0x3e0);
|
||||||
|
|
||||||
|
return (const uint8_t *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
random_bytes_free (const uint8_t *p)
|
||||||
|
{
|
||||||
|
(void)p;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
get_random (void)
|
get_random (void)
|
||||||
{
|
{
|
||||||
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
|
const uint32_t *p = (const uint32_t *)random_bytes_get ();
|
||||||
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
|
return *p;
|
||||||
|
|
||||||
return (m_z << 16) + m_w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
random_init (void)
|
|
||||||
{
|
|
||||||
static uint8_t s = 0;
|
|
||||||
|
|
||||||
again:
|
|
||||||
if ((s & 1))
|
|
||||||
m_w = (m_w << 8) ^ hardclock ();
|
|
||||||
else
|
|
||||||
m_z = (m_z << 8) ^ hardclock ();
|
|
||||||
|
|
||||||
s++;
|
|
||||||
if (m_w == 0 || m_z == 0)
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t dek[16];
|
|
||||||
uint8_t *get_data_encryption_key (void)
|
|
||||||
{
|
|
||||||
uint32_t r;
|
|
||||||
r = get_random ();
|
|
||||||
memcpy (dek, &r, 4);
|
|
||||||
r = get_random ();
|
|
||||||
memcpy (dek+4, &r, 4);
|
|
||||||
r = get_random ();
|
|
||||||
memcpy (dek+8, &r, 4);
|
|
||||||
r = get_random ();
|
|
||||||
memcpy (dek+12, &r, 4);
|
|
||||||
return dek;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dek_free (uint8_t *dek)
|
|
||||||
{
|
|
||||||
(void)dek;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,9 @@ icc_send_status (void)
|
|||||||
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
||||||
SetEPTxValid (ENDP1);
|
SetEPTxValid (ENDP1);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_MORE
|
||||||
DEBUG_INFO ("St\r\n");
|
DEBUG_INFO ("St\r\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
enum icc_state
|
enum icc_state
|
||||||
@@ -267,7 +269,9 @@ icc_send_data_block (uint8_t status, uint8_t error, uint8_t chain,
|
|||||||
icc_tx_size = ICC_MSG_DATA_OFFSET + len;
|
icc_tx_size = ICC_MSG_DATA_OFFSET + len;
|
||||||
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
||||||
SetEPTxValid (ENDP1);
|
SetEPTxValid (ENDP1);
|
||||||
|
#ifdef DEBUG_MORE
|
||||||
DEBUG_INFO ("DATA\r\n");
|
DEBUG_INFO ("DATA\r\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user