works now again

This commit is contained in:
NIIBE Yutaka
2010-09-06 01:55:29 +09:00
parent 043946aad0
commit 6b752f7489
13 changed files with 215 additions and 141 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -115,6 +115,11 @@ SECTIONS
PROVIDE(end = .);
_end = .;
.gnuk_random : ALIGN (1024)
{
*(.gnuk_random)
} > flash
.gnuk_flash : ALIGN (1024)
{
_do_pool = .;

View File

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

View File

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

View File

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

View File

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

View File

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