works now again
This commit is contained in:
21
README
21
README
@@ -1,7 +1,9 @@
|
||||
Gnuk - software for GPG USB Token
|
||||
|
||||
Version 0.0 2010-09-05
|
||||
Niibe Yutaka
|
||||
Version 0.0
|
||||
2010-09-06
|
||||
Niibe Yutaka
|
||||
Free Software Initiative of Japan
|
||||
|
||||
What's Gnuk
|
||||
===========
|
||||
@@ -14,8 +16,7 @@ processor.
|
||||
Release notes
|
||||
=============
|
||||
|
||||
This is initial release of Gnuk, and it is experimental yet.
|
||||
It is not yet daily use.
|
||||
This is initial release of Gnuk, and it is experimental.
|
||||
|
||||
Supported and tested features are:
|
||||
|
||||
@@ -25,7 +26,7 @@ Supported and tested features are:
|
||||
|
||||
* Password handling (PW1, RC, PW3)
|
||||
|
||||
* Single key import
|
||||
* Single key import for signature.
|
||||
|
||||
* PSO: Digital Signature
|
||||
|
||||
@@ -107,6 +108,13 @@ Type:
|
||||
|
||||
$ 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".
|
||||
|
||||
|
||||
@@ -134,7 +142,6 @@ virtual COM port by:
|
||||
|
||||
and you will see debug output of Gnuk.
|
||||
|
||||
|
||||
For libccid, we need following change:
|
||||
|
||||
--- /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
|
||||
|
||||
|
||||
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
|
||||
|
||||
* dwMaxCCIDMessageLength: 64
|
||||
|
||||
|
||||
OpenPGP card protocol implementation
|
||||
====================================
|
||||
|
||||
* No clear password(s)
|
||||
|
||||
PW1
|
||||
|
||||
* Support of Resetting code
|
||||
I try to follow "no clear password(s)" policy.
|
||||
After key import, keystrings are also removed.
|
||||
But because of this, we only support single key for this version.
|
||||
|
||||
|
||||
KEY
|
||||
=======
|
||||
How a private key is stored
|
||||
===========================
|
||||
|
||||
KEYPTR
|
||||
----> [ P ][ Q ][ N ]
|
||||
|
||||
17
src/Makefile
17
src/Makefile
@@ -89,7 +89,8 @@ CSRC = $(PORTSRC) \
|
||||
$(CRYPTSRC) \
|
||||
main.c usb_lld.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),)
|
||||
CSRC += debug.c
|
||||
@@ -203,3 +204,17 @@ ifeq ($(USE_FWLIB),yes)
|
||||
endif
|
||||
|
||||
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 */
|
||||
return 0;
|
||||
|
||||
DEBUG_INFO ("verify_pso_cds\r\n");
|
||||
DEBUG_BYTE (pw_len);
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
else if (pwsb[PW_STATUS_PW1] != 3)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
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);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
else if (pwsb[PW_STATUS_PW1] != 3)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
else if (pwsb[PW_STATUS_PW3] != 3)
|
||||
{ /* OK, the user is now authenticated */
|
||||
pwsb[PW_STATUS_PW3] = 3;
|
||||
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
|
||||
{
|
||||
hw |= data[0]<<8;
|
||||
hw |= (data[0]<<8);
|
||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||
return NULL;
|
||||
addr += 2;
|
||||
|
||||
@@ -185,10 +185,10 @@ extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
#define SIZE_PW_STATUS_BYTES 7
|
||||
|
||||
extern uint8_t *get_data_encryption_key (void); /* 16-byte random bytes */
|
||||
extern void dek_free (uint8_t *);
|
||||
/* 32-byte random bytes */
|
||||
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);
|
||||
|
||||
|
||||
@@ -115,6 +115,11 @@ SECTIONS
|
||||
PROVIDE(end = .);
|
||||
_end = .;
|
||||
|
||||
.gnuk_random : ALIGN (1024)
|
||||
{
|
||||
*(.gnuk_random)
|
||||
} > flash
|
||||
|
||||
.gnuk_flash : ALIGN (1024)
|
||||
{
|
||||
_do_pool = .;
|
||||
|
||||
17
src/main.c
17
src/main.c
@@ -173,7 +173,6 @@ main (int argc, char **argv)
|
||||
{
|
||||
eventmask_t m;
|
||||
int count = 0;
|
||||
uint8_t once = 0;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -200,8 +199,6 @@ main (int argc, char **argv)
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
#if 0
|
||||
if (palReadPad(IOPORT1, GPIOA_BUTTON))
|
||||
palSetPad (IOPORT3, GPIOC_LED);
|
||||
@@ -211,23 +208,15 @@ main (int argc, char **argv)
|
||||
if (m == EV_LED)
|
||||
palClearPad (IOPORT3, GPIOC_LED);
|
||||
|
||||
if (once == 0 && bDeviceState == CONFIGURED)
|
||||
{
|
||||
random_init ();
|
||||
once = 1;
|
||||
r = get_random ();
|
||||
DEBUG_WORD (r);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
if (bDeviceState == CONFIGURED && (count % 100) == 0)
|
||||
{
|
||||
r = get_random ();
|
||||
|
||||
DEBUG_WORD (r);
|
||||
DEBUG_WORD (count / 100);
|
||||
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
||||
"Testing USB driver.\n\n"
|
||||
"Hello world\r\n\r\n", 47+21+15);
|
||||
}
|
||||
#endif
|
||||
|
||||
m = chEvtWaitOneTimeout (ALL_EVENTS, 100);
|
||||
if (m == EV_LED)
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
/* AID */
|
||||
static const uint8_t const aid[] __attribute__ ((aligned (1))) = {
|
||||
static const uint8_t aid[] __attribute__ ((aligned (1))) = {
|
||||
16,
|
||||
0xd2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||
0x02, 0x00, /* Version 2.0 */
|
||||
@@ -48,7 +48,7 @@ static const uint8_t const aid[] __attribute__ ((aligned (1))) = {
|
||||
};
|
||||
|
||||
/* Historical Bytes (template) */
|
||||
static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = {
|
||||
static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
|
||||
10,
|
||||
0x00,
|
||||
0x31, 0x80, /* Full DF name */
|
||||
@@ -61,7 +61,7 @@ static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = {
|
||||
};
|
||||
|
||||
/* Extended Capabilities */
|
||||
static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1))) = {
|
||||
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
|
||||
10,
|
||||
0x30, /*
|
||||
* No SM, No get challenge,
|
||||
@@ -78,7 +78,7 @@ static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1)))
|
||||
};
|
||||
|
||||
/* Algorithm Attributes */
|
||||
static const uint8_t const algorithm_attr[] __attribute__ ((aligned (1))) = {
|
||||
static const uint8_t algorithm_attr[] __attribute__ ((aligned (1))) = {
|
||||
6,
|
||||
0x01, /* RSA */
|
||||
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) */
|
||||
};
|
||||
|
||||
static const uint8_t const do_pw_status_bytes_template[] =
|
||||
static const uint8_t do_pw_status_bytes_template[] =
|
||||
{
|
||||
7,
|
||||
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;
|
||||
struct prvkey_data *pd;
|
||||
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_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...");
|
||||
|
||||
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));
|
||||
|
||||
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)
|
||||
{
|
||||
dek_free (dek);
|
||||
random_bytes_free (dek);
|
||||
free (pd);
|
||||
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 ();
|
||||
if (ks_pw1)
|
||||
{
|
||||
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, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, &ks_pw1_len, 1);
|
||||
}
|
||||
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)
|
||||
{
|
||||
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, 1);
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_RC, &ks_rc_len, 1);
|
||||
}
|
||||
else
|
||||
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));
|
||||
do_ptr[nr] = p;
|
||||
|
||||
dek_free (dek);
|
||||
random_bytes_free (dek);
|
||||
free (pd);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
@@ -1086,9 +1090,10 @@ void
|
||||
gpg_do_public_key (uint8_t kk_byte)
|
||||
{
|
||||
const uint8_t *do_data;
|
||||
uint8_t *key_addr;
|
||||
const uint8_t *key_addr;
|
||||
|
||||
DEBUG_INFO ("Public key\r\n");
|
||||
DEBUG_BYTE (kk_byte);
|
||||
|
||||
if (kk_byte == 0xb6)
|
||||
do_data = do_ptr[NR_DO_PRVKEY_SIG];
|
||||
@@ -1104,7 +1109,7 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
return;
|
||||
}
|
||||
|
||||
key_addr = *(uint8_t **)&do_data[1];
|
||||
key_addr = *(const uint8_t **)&do_data[1];
|
||||
|
||||
res_p = res_APDU;
|
||||
|
||||
@@ -1200,12 +1205,18 @@ gpg_do_reset_pw_counter (uint8_t which)
|
||||
if (do_data)
|
||||
{
|
||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
||||
if (pwsb[which] == 3)
|
||||
return;
|
||||
|
||||
pwsb[which] = 3;
|
||||
flash_do_release (do_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (pwsb, PW_STATUS_BYTES_TEMPLATE, SIZE_PW_STATUS_BYTES);
|
||||
if (pwsb[which] == 3)
|
||||
return;
|
||||
|
||||
pwsb[which] = 3;
|
||||
}
|
||||
|
||||
|
||||
105
src/openpgp.c
105
src/openpgp.c
@@ -42,7 +42,7 @@
|
||||
#define INS_PUT_DATA 0xda
|
||||
#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))) = {
|
||||
0x00, 0x00, /* unused */
|
||||
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 */
|
||||
};
|
||||
|
||||
static const uint8_t const
|
||||
static const uint8_t
|
||||
read_binary_result[] __attribute__ ((aligned (1))) = {
|
||||
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
||||
};
|
||||
@@ -89,17 +89,24 @@ cmd_verify (void)
|
||||
int len;
|
||||
uint8_t p2 = cmd_APDU[3];
|
||||
int r;
|
||||
int data_start = 5;
|
||||
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
DEBUG_BYTE (p2);
|
||||
|
||||
len = cmd_APDU[4];
|
||||
if (len == 0) /* extended length */
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
data_start = 7;
|
||||
}
|
||||
|
||||
if (p2 == 0x81)
|
||||
r = verify_pso_cds (&cmd_APDU[5], len);
|
||||
r = verify_pso_cds (&cmd_APDU[data_start], len);
|
||||
else if (p2 == 0x82)
|
||||
r = verify_pso_other (&cmd_APDU[5], len);
|
||||
r = verify_pso_other (&cmd_APDU[data_start], len);
|
||||
else
|
||||
r = verify_admin (&cmd_APDU[5], len);
|
||||
r = verify_admin (&cmd_APDU[data_start], len);
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
@@ -152,6 +159,12 @@ cmd_change_password (void)
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
DEBUG_BYTE (who);
|
||||
|
||||
if (len == 0) /* extended length */
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
pw += 2;
|
||||
}
|
||||
|
||||
if (who == 1) /* PW1 */
|
||||
{
|
||||
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
@@ -169,6 +182,9 @@ cmd_change_password (void)
|
||||
pw_len = 6;
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
goto no_prvkey;
|
||||
}
|
||||
else
|
||||
@@ -244,22 +260,28 @@ static void
|
||||
cmd_reset_user_password (void)
|
||||
{
|
||||
uint8_t p1 = cmd_APDU[2];
|
||||
int len = cmd_APDU[3];
|
||||
const uint8_t *pw = &cmd_APDU[4];
|
||||
int len = cmd_APDU[4];
|
||||
const uint8_t *pw = &cmd_APDU[5];
|
||||
const uint8_t *newpw;
|
||||
int pw_len, newpw_len;
|
||||
int r;
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
|
||||
DEBUG_INFO ("Reset PW1\r\n");
|
||||
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 */
|
||||
{
|
||||
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);
|
||||
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
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
@@ -318,46 +340,43 @@ cmd_reset_user_password (void)
|
||||
}
|
||||
else /* by Admin (p1 == 0x02) */
|
||||
{
|
||||
const uint8_t *old_ks = keystring_md_pw3;
|
||||
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
{
|
||||
DEBUG_INFO ("permission denied.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
newpw_len = len;
|
||||
newpw = pw;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (3, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
DEBUG_INFO ("done (no privkey).\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
}
|
||||
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 = pw;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (3, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
GPG_MEMORY_FAILURE ();
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
DEBUG_INFO ("security error.\r\n");
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
DEBUG_INFO ("done (no privkey).\r\n");
|
||||
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
ac_reset_pso_cds ();
|
||||
gpg_do_reset_pw_counter (PW_STATUS_PW1);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,7 +414,7 @@ cmd_pgp_gakp (void)
|
||||
|
||||
if (cmd_APDU[2] == 0x81)
|
||||
/* Get public key */
|
||||
gpg_do_public_key (cmd_APDU[5]);
|
||||
gpg_do_public_key (cmd_APDU[7]);
|
||||
else
|
||||
{ /* Generate key pair */
|
||||
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 "ch.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
/*
|
||||
* XXX: I have tried havege_rand, but it requires too much memory...
|
||||
*/
|
||||
extern void *_binary_random_bits_start;
|
||||
|
||||
/*
|
||||
* Multiply-with-carry method by George Marsaglia
|
||||
*/
|
||||
static uint32_t m_w;
|
||||
static uint32_t m_z;
|
||||
const uint8_t *
|
||||
random_bytes_get (void)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
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
|
||||
get_random (void)
|
||||
{
|
||||
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
|
||||
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
|
||||
|
||||
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;
|
||||
const uint32_t *p = (const uint32_t *)random_bytes_get ();
|
||||
return *p;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,9 @@ icc_send_status (void)
|
||||
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP1);
|
||||
}
|
||||
#ifdef DEBUG_MORE
|
||||
DEBUG_INFO ("St\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
USB_SIL_Write (EP1_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP1);
|
||||
#ifdef DEBUG_MORE
|
||||
DEBUG_INFO ("DATA\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user