works again

This commit is contained in:
NIIBE Yutaka
2010-09-05 18:10:54 +09:00
parent ea96a32119
commit 38e0533156
17 changed files with 871 additions and 295 deletions

View File

@@ -1,6 +1,5 @@
# Makefile for Gnuk
#
#
ENABLE_DEBUG=1
@@ -88,10 +87,14 @@ CSRC = $(PORTSRC) \
$(STMUSBSRC) \
$(VCOMSRC) \
$(CRYPTSRC) \
main.c debug.c usb_lld.c \
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
ifneq ($(ENABLE_DEBUG),)
CSRC += debug.c
endif
# List ASM source files here
ASMSRC = $(PORTASM) \
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s

View File

@@ -26,7 +26,7 @@ int
verify_pso_cds (const uint8_t *pw, int pw_len)
{
int r;
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
uint8_t keystring[KEYSTRING_SIZE_PW1];
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
@@ -40,13 +40,13 @@ verify_pso_cds (const uint8_t *pw, int pw_len)
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0)
{
pwsb[PW_STATUS_PW1]--;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
return r;
}
else
{
pwsb[PW_STATUS_PW1] = 3;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
}
auth_status |= AC_PSO_CDS_AUTHORIZED;
@@ -63,7 +63,7 @@ int
verify_pso_other (const uint8_t *pw, int pw_len)
{
int r;
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
uint8_t keystring[KEYSTRING_SIZE_PW1];
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
@@ -77,13 +77,13 @@ verify_pso_other (const uint8_t *pw, int pw_len)
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPT, 1, keystring+1)) < 0)
{
pwsb[PW_STATUS_PW1]--;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
return r;
}
else
{
pwsb[PW_STATUS_PW1] = 3;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
}
auth_status |= AC_PSO_OTHER_AUTHORIZED;
@@ -131,14 +131,14 @@ int
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
{
const uint8_t *pw3_keystring;
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
int pw_len;
if (pw_status_bytes == NULL
|| pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
return 0;
pw3_keystring = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW3);
pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
if (pw3_keystring != NULL)
{
int count;
@@ -159,13 +159,13 @@ verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
{
failure:
pwsb[PW_STATUS_PW3]--;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
return -1;
}
else
{ /* OK, the user is now authenticated */
pwsb[PW_STATUS_PW3] = 3;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
}
}
else
@@ -196,7 +196,7 @@ gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
ks[9] = 0x60; /* 65536 iterations */
calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
}
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];

164
src/call-rsa.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
*
* 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"
#include "polarssl/config.h"
#include "polarssl/rsa.h"
static rsa_context rsa_ctx;
int
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len)
{
mpi P1, Q1, H;
int r;
mpi_init (&P1, &Q1, &H, NULL);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = 2048 / 8;
mpi_read_string (&rsa_ctx.E, 16, "10001");
mpi_read_binary (&rsa_ctx.P, &kd.data[0], rsa_ctx.len / 2);
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], rsa_ctx.len / 2);
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
mpi_mul_mpi (&H, &P1, &Q1);
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
mpi_free (&P1, &Q1, &H, NULL);
DEBUG_INFO ("RSA...");
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
DEBUG_INFO ("ok...");
else
{
DEBUG_INFO ("failed.\r\n");
DEBUG_SHORT (r);
rsa_free (&rsa_ctx);
return r;
}
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, output);
rsa_free (&rsa_ctx);
if (r < 0)
{
DEBUG_INFO ("fail:");
DEBUG_SHORT (r);
return r;
}
else
{
DEBUG_INFO ("done.\r\n");
return 0;
}
}
const uint8_t *
modulus_calc (const uint8_t *p, int len)
{
mpi P, Q, N;
uint8_t *modulus;
(void)len; /* 2048-bit assumed */
modulus = malloc (2048 / 8);
if (modulus == NULL)
return NULL;
mpi_init (&P, &Q, &N, NULL);
mpi_read_binary (&P, p, 2048 / 8 / 2);
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
mpi_mul_mpi (&N, &P, &Q);
mpi_write_binary (&N, modulus, 2048 / 8);
mpi_free (&P, &Q, &N, NULL);
return modulus;
}
void
modulus_free (const uint8_t *p)
{
free ((void *)p);
}
int
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len)
{
mpi P1, Q1, H;
int r;
int output_len;
mpi_init (&P1, &Q1, &H, NULL);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = msg_len;
mpi_read_string (&rsa_ctx.E, 16, "10001");
mpi_read_binary (&rsa_ctx.P, &kd.data[0], 2048 / 8 / 2);
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], 2048 / 8 / 2);
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
mpi_mul_mpi (&H, &P1, &Q1);
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
mpi_free (&P1, &Q1, &H, NULL);
DEBUG_INFO ("RSA...");
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
DEBUG_INFO ("ok...");
else
{
DEBUG_INFO ("failed.\r\n");
DEBUG_SHORT (r);
rsa_free (&rsa_ctx);
return r;
}
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
input, output, MAX_RES_APDU_SIZE - 2);
rsa_free (&rsa_ctx);
if (r < 0)
{
DEBUG_INFO ("fail:");
DEBUG_SHORT (r);
return r;
}
else
{
res_APDU[output_len] = 0x90;
res_APDU[output_len+1] = 0x00;
res_APDU_size = output_len + 2;
DEBUG_INFO ("done.\r\n");
return 0;
}
}

View File

@@ -18,14 +18,14 @@
#define CH_USE_CONDVARS_TIMEOUT TRUE
#define CH_USE_EVENTS TRUE /* We use this! */
#define CH_USE_EVENTS_TIMEOUT TRUE /* We use this! */
#define CH_USE_MESSAGES TRUE
#define CH_USE_MESSAGES FALSE
#define CH_USE_MESSAGES_PRIORITY FALSE
#define CH_USE_MAILBOXES FALSE
#define CH_USE_QUEUES FALSE
#define CH_USE_MEMCORE TRUE
#define CH_USE_HEAP TRUE
#define CH_USE_MALLOC_HEAP FALSE
#define CH_USE_MEMPOOLS TRUE
#define CH_USE_MEMPOOLS FALSE
#define CH_USE_DYNAMIC FALSE
/* Debug options */

View File

@@ -3,4 +3,4 @@ CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
$(CRYPTSRCDIR)/aes.c \
rsa-sign.c
call-rsa.c

View File

@@ -64,6 +64,20 @@ put_short (uint16_t x)
_write ("\r\n", 2);
}
void
put_word (uint32_t x)
{
put_hex (x >> 28);
put_hex ((x >> 24)&0x0f);
put_hex ((x >> 20)&0x0f);
put_hex ((x >> 16)&0x0f);
put_hex ((x >> 12)&0x0f);
put_hex ((x >> 8)&0x0f);
put_hex ((x >> 4)&0x0f);
put_hex (x & 0x0f);
_write ("\r\n", 2);
}
void
put_binary (const char *s, int len)
{

View File

@@ -22,90 +22,288 @@
*/
/*
* Writing to Flash ROM is NOT YET IMPLEMENTED, just API only
* Note: Garbage collection and page management with flash erase
* is *NOT YET* implemented
*/
#include "config.h"
#include "ch.h"
#include "hal.h"
#include "gnuk.h"
static uint8_t do_pool[256];
static uint8_t *last_p = do_pool;
#define FLASH_KEY1 0x45670123UL
#define FLASH_KEY2 0xCDEF89ABUL
enum flash_status
{
FLASH_BUSY = 1,
FLASH_ERROR_PG,
FLASH_ERROR_WRP,
FLASH_COMPLETE,
FLASH_TIMEOUT
};
static void
flash_unlock (void)
{
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
static int
flash_get_status (void)
{
int status;
if ((FLASH->SR & FLASH_SR_BSY) != 0)
status = FLASH_BUSY;
else if ((FLASH->SR & FLASH_SR_PGERR) != 0)
status = FLASH_ERROR_PG;
else if((FLASH->SR & FLASH_SR_WRPRTERR) != 0 )
status = FLASH_ERROR_WRP;
else
status = FLASH_COMPLETE;
return status;
}
static int
flash_wait_for_last_operation (uint32_t timeout)
{
int status;
do
if (--timeout == 0)
return FLASH_TIMEOUT;
else
status = flash_get_status ();
while (status == FLASH_BUSY);
return status;
}
#define FLASH_PROGRAM_TIMEOUT 0x10000
static int
flash_program_halfword (uint32_t addr, uint16_t data)
{
int status;
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
chSysLock ();
if (status == FLASH_COMPLETE)
{
FLASH->CR |= FLASH_CR_PG;
*(volatile uint16_t *)addr = data;
status = flash_wait_for_last_operation (FLASH_PROGRAM_TIMEOUT);
if (status != FLASH_TIMEOUT)
FLASH->CR &= ~FLASH_CR_PG;
}
chSysUnlock ();
return status;
}
/*
* TLV (Tag, Length, and Value)
* Flash memory map
*
* _text
* .text
* .ctors
* .dtors
* _etext
* .data
* ...
* _etext + (_edata - _data)
*
* 1-KiB align padding
*
* 1-KiB DO pool * 3
*
* 3-KiB Key store (512-byte (p, q and N) key-store * 6)
*/
static const uint8_t *do_pool;
static const uint8_t *keystore_pool;
static const uint8_t *last_p;
static const uint8_t *keystore;
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
0xff, 0xff, 0xff, 0xff
};
void
flash_init (void)
{
const uint8_t *p;
extern uint8_t _do_pool;
extern uint8_t _keystore_pool;
do_pool = &_do_pool;
keystore_pool = &_keystore_pool;
/* Seek empty keystore */
p = keystore_pool;
while (*p != 0xff || *(p+1) != 0xff)
p += 512;
keystore = p;
flash_unlock ();
}
const uint8_t *
flash_do_write (uint16_t tag, const uint8_t *data, int len)
flash_do_pool (void)
{
return do_pool;
}
void
flash_set_do_pool_last (const uint8_t *p)
{
last_p = p;
}
const uint8_t *
flash_do_write (uint8_t nr, const uint8_t *data, int len)
{
const uint8_t *p = last_p;
uint16_t hw;
uint32_t addr;
int state = 0;
int i;
if (last_p - do_pool + len + 2 + 3 > 1024)
if (last_p - do_pool + len + 2 + 3 > 1024*3)
return NULL;
*last_p++ = (tag >> 8);
*last_p++ = (tag & 0xff);
DEBUG_INFO ("flash DO\r\n");
addr = (uint32_t)last_p;
hw = nr | (0xff << 8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
if (len < 128)
*last_p++ = len;
{
hw = len;
state = 1;
}
else if (len < 256)
{
*last_p++ = 0x81;
*last_p++ = len;
hw = 0x81 | (len << 8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
state = 0;
}
else
{
*last_p++ = 0x82;
*last_p++ = (len >> 8);
*last_p++ = (len & 0xff);
hw = 0x82 | ((len >> 8) << 8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
hw = (len & 0xff);
state = 1;
}
memcpy (last_p, data, len);
last_p += len;
if (state == 0)
{
for (i = 0; i < len/2; i ++)
{
hw = data[i*2] | (data[i*2+1]<<8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
}
if ((len & 1))
{
hw = data[i*2] | 0xff00;
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
}
}
else
{
hw |= data[0]<<8;
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
for (i = 0; i < (len - 1)/2; i ++)
{
hw = data[i*2+1] | (data[i*2+2]<<8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
}
if (((len - 1) & 1))
{
hw = data[i*2+1] | 0xff00;
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return NULL;
addr += 2;
}
}
last_p = (const uint8_t *)addr;
DEBUG_INFO ("flash DO...done\r\n");
return p + 2;
}
void
flash_do_release (const uint8_t *data)
flash_do_release (const uint8_t *data_p)
{
(void)data;/*XXX*/
(void)data_p;
}
static uint8_t k1[KEY_CONTENT_LEN*2]; /* p, q and N */
#if 0
static uint8_t k2[KEY_CONTENT_LEN*2];
static uint8_t k3[KEY_CONTENT_LEN*2];
#endif
uint8_t *
flash_key_alloc (enum kind_of_key kk)
flash_key_alloc (void)
{
switch (kk)
{
case GPG_KEY_FOR_SIGNATURE:
return k1;
#if 0
case GPG_KEY_FOR_DECRYPT:
return k2;
case GPG_KEY_FOR_AUTHENTICATION:
return k3;
#else
default:
return k1;
#endif
}
uint8_t *k = (uint8_t *)keystore;
keystore += 512;
return k;
}
int
flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
const uint8_t *modulus)
{
memcpy (key_addr, key_data, KEY_CONTENT_LEN);
memcpy (key_addr+KEY_CONTENT_LEN, modulus, KEY_CONTENT_LEN);
uint16_t hw;
uint32_t addr;
int i;
addr = (uint32_t)key_addr;
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
{
hw = key_data[i*2] | (key_data[i*2+1]<<8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return -1;
addr += 2;
}
for (i = 0; i < KEY_CONTENT_LEN/2; i ++)
{
hw = modulus[i*2] | (modulus[i*2+1]<<8);
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
return -1;
addr += 2;
}
return 0;
}
void
flash_key_release (const uint8_t *key_addr)
{
(void)key_addr; /*XXX*/
(void)key_addr;
}

View File

@@ -3,11 +3,16 @@ extern Thread *blinker_thread;
extern void put_byte (uint8_t b);
extern void put_byte_with_no_nl (uint8_t b);
extern void put_short (uint16_t x);
extern void put_word (uint32_t x);
extern void put_string (const char *s);
extern void put_binary (const char *s, int len);
extern void _write (const char *, int);
/*
* We declare some of libc functions here, because we will
* remove dependency on libc in future.
*/
extern size_t strlen (const char *s);
extern int strncmp(const char *s1, const char *s2, size_t n);
extern void *memcpy (void *dest, const void *src, size_t n);
@@ -68,10 +73,13 @@ enum kind_of_key {
GPG_KEY_FOR_AUTHENTICATION,
};
extern void flash_init (void);
extern void flash_do_release (const uint8_t *);
extern const uint8_t *flash_do_write (uint16_t tag, const uint8_t *data, int len);
extern uint8_t *flash_key_alloc (enum kind_of_key);
extern const uint8_t *flash_do_write (uint8_t nr, const uint8_t *data, int len);
extern uint8_t *flash_key_alloc (void);
extern void flash_key_release (const uint8_t *);
extern const uint8_t *flash_do_pool (void);
extern void flash_set_do_pool_last (const uint8_t *p);
#define KEY_MAGIC_LEN 8
#define KEY_CONTENT_LEN 256 /* p and q */
@@ -118,11 +126,13 @@ extern struct key_data kd;
#ifdef DEBUG
#define DEBUG_INFO(msg) put_string (msg)
#define DEBUG_WORD(w) put_word (w)
#define DEBUG_SHORT(h) put_short (h)
#define DEBUG_BYTE(b) put_byte (b)
#define DEBUG_BINARY(s,len) put_binary ((const char *)s,len)
#else
#define DEBUG_INFO(msg)
#define DEBUG_WORD(w)
#define DEBUG_SHORT(h)
#define DEBUG_BYTE(b)
#define DEBUG_BINARY(s,len)
@@ -131,11 +141,12 @@ extern struct key_data kd;
extern int rsa_sign (const uint8_t *, uint8_t *, int);
extern const uint8_t *modulus_calc (const uint8_t *, int);
extern void modulus_free (const uint8_t *);
extern int rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len);
extern int gpg_do_write_privkey (enum kind_of_key kk, const uint8_t *key_data, int key_len);
extern int gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, const uint8_t *keystring);
extern const uint8_t *gpg_do_read_simple (uint16_t);
extern void gpg_do_write_simple (uint16_t, const uint8_t *, int);
extern const uint8_t *gpg_do_read_simple (uint8_t);
extern void gpg_do_write_simple (uint8_t, const uint8_t *, int);
extern void gpg_do_increment_digital_signature_counter (void);
#define PW_STATUS_PW1 4
@@ -144,21 +155,37 @@ extern void gpg_do_increment_digital_signature_counter (void);
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
extern void fatal (void);
extern void fatal (void) __attribute__ ((noreturn));
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
#define GNUK_DO_PRVKEY_SIG 0xff01
#define GNUK_DO_PRVKEY_DEC 0xff02
#define GNUK_DO_PRVKEY_AUT 0xff03
#define GNUK_DO_KEYSTRING_PW1 0xff04
#define GNUK_DO_KEYSTRING_RC 0xff05
#define GNUK_DO_KEYSTRING_PW3 0xff06
#define GNUK_DO_PW_STATUS 0xff07
#define NR_DO_PRVKEY_SIG 0
#define NR_DO_PRVKEY_DEC 1
#define NR_DO_PRVKEY_AUT 2
#define NR_DO_KEYSTRING_PW1 3
#define NR_DO_KEYSTRING_RC 4
#define NR_DO_KEYSTRING_PW3 5
#define NR_DO_PW_STATUS 6
#define NR_DO_DS_COUNT 7
#define NR_DO_SEX 8
#define NR_DO_FP_SIG 9
#define NR_DO_FP_DEC 10
#define NR_DO_FP_AUT 11
#define NR_DO_CAFP_1 12
#define NR_DO_CAFP_2 13
#define NR_DO_CAFP_3 14
#define NR_DO_KGTIME_SIG 15
#define NR_DO_KGTIME_DEC 16
#define NR_DO_KGTIME_AUT 17
#define NR_DO_LOGIN_DATA 18
#define NR_DO_URL 19
#define NR_DO_NAME 20
#define NR_DO_LANGUAGE 21
#define NR_DO_CH_CERTIFICATE 22
#define SIZE_PW_STATUS_BYTES 7
/* 16-byte random bytes */
extern uint8_t *get_data_encryption_key (void);
extern uint8_t *get_data_encryption_key (void); /* 16-byte random bytes */
extern void dek_free (uint8_t *);
extern uint32_t get_random (void);
extern void random_init (void);

View File

@@ -110,11 +110,23 @@ SECTIONS
*(COMMON)
. = ALIGN(4);
_bss_end = .;
} > ram
}
} > ram
PROVIDE(end = .);
_end = .;
PROVIDE(end = .);
_end = .;
.gnuk_flash : ALIGN (1024)
{
_do_pool = .;
KEEP(*(.gnuk_data))
FILL(0xffffffff);
. = ALIGN(1024);
. += 1024*2;
_keystore_pool = .;
FILL(0xffffffff);
. += 1024*3;
} > flash
}
__heap_base__ = _end;
__heap_end__ = __ram_end__ - __stacks_total_size__;

View File

@@ -173,12 +173,14 @@ main (int argc, char **argv)
{
eventmask_t m;
int count = 0;
uint8_t once = 0;
(void)argc;
(void)argv;
blinker_thread = chThdSelf ();
flash_init ();
gpg_do_table_init ();
usb_lld_init ();
@@ -198,7 +200,8 @@ main (int argc, char **argv)
while (1)
{
uint8_t once = 0;
uint32_t r;
#if 0
if (palReadPad(IOPORT1, GPIOA_BUTTON))
palSetPad (IOPORT3, GPIOC_LED);
@@ -212,14 +215,15 @@ main (int argc, char **argv)
{
random_init ();
once = 1;
r = get_random ();
DEBUG_WORD (r);
}
if (bDeviceState == CONFIGURED && (count % 100) == 0)
{
uint32_t r;
r = get_random ();
DEBUG_SHORT (r);
DEBUG_WORD (r);
_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);

View File

@@ -124,6 +124,13 @@ static int with_tag;
static void copy_do_1 (uint16_t tag, const uint8_t *do_data);
static const struct do_table_entry *get_do_entry (uint16_t tag);
#define GNUK_DO_PRVKEY_SIG 0xff01
#define GNUK_DO_PRVKEY_DEC 0xff02
#define GNUK_DO_PRVKEY_AUT 0xff03
#define GNUK_DO_KEYSTRING_PW1 0xff04
#define GNUK_DO_KEYSTRING_RC 0xff05
#define GNUK_DO_KEYSTRING_PW3 0xff06
#define GNUK_DO_PW_STATUS 0xff07
#define GPG_DO_AID 0x004f
#define GPG_DO_NAME 0x005b
#define GPG_DO_LOGIN_DATA 0x005e
@@ -159,29 +166,62 @@ static const struct do_table_entry *get_do_entry (uint16_t tag);
#define NUM_DO_OBJS 23
static const uint8_t *do_ptr[NUM_DO_OBJS];
#define NR_DO_PRVKEY_SIG 0
#define NR_DO_PRVKEY_DEC 1
#define NR_DO_PRVKEY_AUT 2
#define NR_DO_KEYSTRING_PW1 3
#define NR_DO_KEYSTRING_RC 4
#define NR_DO_KEYSTRING_PW3 5
#define NR_DO_PW_STATUS 6
#define NR_DO_DS_COUNT 7
#define NR_DO_SEX 8
#define NR_DO_FP_SIG 9
#define NR_DO_FP_DEC 10
#define NR_DO_FP_AUT 11
#define NR_DO_CAFP_1 12
#define NR_DO_CAFP_2 13
#define NR_DO_CAFP_3 14
#define NR_DO_KGTIME_SIG 15
#define NR_DO_KGTIME_DEC 16
#define NR_DO_KGTIME_AUT 17
#define NR_DO_LOGIN_DATA 18
#define NR_DO_URL 19
#define NR_DO_NAME 20
#define NR_DO_LANGUAGE 21
#define NR_DO_CH_CERTIFICATE 22
static uint8_t
do_tag_to_nr (uint16_t tag)
{
switch (tag)
{
case GNUK_DO_PRVKEY_SIG:
return NR_DO_PRVKEY_SIG;
case GNUK_DO_PRVKEY_DEC:
return NR_DO_PRVKEY_DEC;
case GNUK_DO_PRVKEY_AUT:
return NR_DO_PRVKEY_AUT;
case GNUK_DO_KEYSTRING_PW1:
return NR_DO_KEYSTRING_PW1;
case GNUK_DO_KEYSTRING_RC:
return NR_DO_KEYSTRING_RC;
case GNUK_DO_KEYSTRING_PW3:
return NR_DO_KEYSTRING_PW3;
case GNUK_DO_PW_STATUS:
return NR_DO_PW_STATUS;
case GPG_DO_DS_COUNT:
return NR_DO_DS_COUNT;
case GPG_DO_SEX:
return NR_DO_SEX;
case GPG_DO_FP_SIG:
return NR_DO_FP_SIG;
case GPG_DO_FP_DEC:
return NR_DO_FP_DEC;
case GPG_DO_FP_AUT:
return NR_DO_FP_AUT;
case GPG_DO_CAFP_1:
return NR_DO_CAFP_1;
case GPG_DO_CAFP_2:
return NR_DO_CAFP_2;
case GPG_DO_CAFP_3:
return NR_DO_CAFP_3;
case GPG_DO_KGTIME_SIG:
return NR_DO_KGTIME_SIG;
case GPG_DO_KGTIME_DEC:
return NR_DO_KGTIME_DEC;
case GPG_DO_KGTIME_AUT:
return NR_DO_KGTIME_AUT;
case GPG_DO_LOGIN_DATA:
return NR_DO_LOGIN_DATA;
case GPG_DO_URL:
return NR_DO_URL;
case GPG_DO_NAME:
return NR_DO_NAME;
case GPG_DO_LANGUAGE:
return NR_DO_LANGUAGE;
case GPG_DO_CH_CERTIFICATE:
return NR_DO_CH_CERTIFICATE;
default:
fatal ();
}
}
static void
copy_tag (uint16_t tag)
@@ -218,21 +258,21 @@ do_fp_all (uint16_t tag)
*res_p++ = SIZE_FP*3;
}
data = gpg_do_read_simple (GPG_DO_FP_SIG);
data = gpg_do_read_simple (NR_DO_FP_SIG);
if (data)
memcpy (res_p, data, SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
data = gpg_do_read_simple (GPG_DO_FP_DEC);
data = gpg_do_read_simple (NR_DO_FP_DEC);
if (data)
memcpy (res_p, data, SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
data = gpg_do_read_simple (GPG_DO_FP_AUT);
data = gpg_do_read_simple (NR_DO_FP_AUT);
if (data)
memcpy (res_p, data, SIZE_FP);
else
@@ -253,21 +293,21 @@ do_cafp_all (uint16_t tag)
*res_p++ = SIZE_FP*3;
}
data = gpg_do_read_simple (GPG_DO_CAFP_1);
data = gpg_do_read_simple (NR_DO_CAFP_1);
if (data)
memcpy (res_p, data, SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
data = gpg_do_read_simple (GPG_DO_CAFP_2);
data = gpg_do_read_simple (NR_DO_CAFP_2);
if (data)
memcpy (res_p, data, SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
data = gpg_do_read_simple (GPG_DO_CAFP_2);
data = gpg_do_read_simple (NR_DO_CAFP_2);
if (data)
memcpy (res_p, data, SIZE_FP);
else
@@ -288,21 +328,21 @@ do_kgtime_all (uint16_t tag)
*res_p++ = SIZE_KGTIME*3;
}
data = gpg_do_read_simple (GPG_DO_KGTIME_SIG);
data = gpg_do_read_simple (NR_DO_KGTIME_SIG);
if (data)
memcpy (res_p, data, SIZE_KGTIME);
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
data = gpg_do_read_simple (GPG_DO_KGTIME_DEC);
data = gpg_do_read_simple (NR_DO_KGTIME_DEC);
if (data)
memcpy (res_p, data, SIZE_KGTIME);
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
data = gpg_do_read_simple (GPG_DO_KGTIME_AUT);
data = gpg_do_read_simple (NR_DO_KGTIME_AUT);
if (data)
memcpy (res_p, data, SIZE_KGTIME);
else
@@ -331,7 +371,7 @@ rw_pw_status (uint16_t tag, const uint8_t *data, int len, int is_write)
pwsb[0] = data[0];
do_ptr[NR_DO_PW_STATUS]
= flash_do_write (tag, pwsb, SIZE_PW_STATUS_BYTES);
= flash_do_write (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
if (do_ptr[NR_DO_PW_STATUS])
GPG_SUCCESS ();
else
@@ -372,6 +412,8 @@ proc_resetting_code (const uint8_t *data, int len)
int newpw_len;
int r;
DEBUG_INFO ("Resetting Code!\r\n");
newpw_len = len;
newpw = data;
sha1 (newpw, newpw_len, new_ks);
@@ -379,18 +421,27 @@ proc_resetting_code (const uint8_t *data, int len)
r = gpg_change_keystring (3, old_ks, 2, new_ks);
if (r < -2)
{
DEBUG_INFO ("memory error.\r\n");
GPG_MEMORY_FAILURE ();
return;
}
else if (r < 0)
{
DEBUG_INFO ("security error.\r\n");
GPG_SECURITY_FAILURE ();
return;
}
else if (r == 0)
gpg_do_write_simple (GNUK_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
{
DEBUG_INFO ("done (no prvkey).\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
}
else
GPG_SUCCESS ();
{
DEBUG_INFO ("done.\r\n");
gpg_do_write_simple (NR_DO_KEYSTRING_RC, new_ks0, 1);
GPG_SUCCESS ();
}
/* Reset RC counter in GNUK_DO_PW_STATUS */
gpg_do_reset_pw_counter (PW_STATUS_RC);
@@ -422,21 +473,6 @@ decrypt (const uint8_t *key_str, uint8_t *data, int len)
DEBUG_BINARY (data, len);
}
static uint16_t
get_tag_for_kk (enum kind_of_key kk)
{
switch (kk)
{
case GPG_KEY_FOR_SIGNATURE:
return GNUK_DO_PRVKEY_SIG;
case GPG_KEY_FOR_DECRYPT:
return GNUK_DO_PRVKEY_DEC;
case GPG_KEY_FOR_AUTHENTICATION:
return GNUK_DO_PRVKEY_AUT;
}
return GNUK_DO_PRVKEY_SIG;
}
static uint8_t
get_do_ptr_nr_for_kk (enum kind_of_key kk)
{
@@ -476,7 +512,10 @@ gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
decrypt (keystring, dek, DATA_ENCRYPTION_KEY_SIZE);
decrypt (dek, (uint8_t *)&kd, sizeof (struct key_data));
if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
return -1;
{
DEBUG_INFO ("gpg_do_load_prvkey failed.\r\n");
return -1;
}
/* XXX: more sanity check */
return 1;
}
@@ -498,7 +537,6 @@ int
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
const uint8_t *keystring)
{
uint16_t tag = get_tag_for_kk (kk);
uint8_t nr = get_do_ptr_nr_for_kk (kk);
const uint8_t *p;
int r;
@@ -506,13 +544,14 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
struct prvkey_data *pd;
uint8_t *key_addr;
uint8_t *dek;
const uint8_t *ks_pw1 = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
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);
#if 0
assert (key_len == KEY_CONTENT_LEN);
#endif
DEBUG_INFO ("Key import\r\n");
DEBUG_SHORT (key_len);
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
@@ -526,7 +565,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
return -1;
}
key_addr = flash_key_alloc (kk);
DEBUG_INFO ("Getting keystore address...\r\n");
key_addr = flash_key_alloc ();
if (key_addr == NULL)
{
free (pd);
@@ -534,6 +574,9 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
return -1;
}
DEBUG_INFO ("key_addr: ");
DEBUG_WORD ((uint32_t)key_addr);
memcpy (kd.data, key_data, KEY_CONTENT_LEN);
kd.check = calc_check32 (key_data, KEY_CONTENT_LEN);
kd.random = get_random ();
@@ -565,7 +608,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
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 (GNUK_DO_KEYSTRING_PW1, ks_pw1, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks_pw1, 1);
}
else
{
@@ -576,7 +619,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
/* Only but its length */
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, ks123_pw1, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, ks123_pw1, 1);
}
if (ks_rc)
@@ -584,7 +627,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
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 (GNUK_DO_KEYSTRING_RC, ks_rc, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_RC, ks_rc, 1);
}
else
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
@@ -592,7 +635,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
p = flash_do_write (tag, (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;
dek_free (dek);
@@ -608,7 +651,6 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
int who_old, const uint8_t *old_ks,
int who_new, const uint8_t *new_ks)
{
uint16_t tag = get_tag_for_kk (kk);
uint8_t nr = get_do_ptr_nr_for_kk (kk);
const uint8_t *do_data = do_ptr[nr];
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
@@ -631,7 +673,7 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old);
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
p = flash_do_write (tag, (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;
free (pd);
@@ -770,12 +812,48 @@ gpg_do_table[] = {
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
/*
* Initialize GPG_DO_TABLE reading from Flash ROM
* Initialize DO_PTR reading from Flash ROM
*/
int
gpg_do_table_init (void)
{
const uint8_t *p, *p_start;
int len;
do_ptr[NR_DO_PW_STATUS] = do_pw_status_bytes_template;
p_start = flash_do_pool ();
/* Traverse DO pool */
p = p_start;
while (*p != 0xff)
{
uint8_t nr = *p++;
uint8_t check = *p++;
if (check == 0xff)
do_ptr[nr] = p;
if (*p < 128)
len = *p++;
else if (*p == 0x81)
{
p++;
len = *p++;
}
else /* 0x82 */
{
p++;
len = (*p << 8) + *(p+1);
p += 2;
}
p += len;
if (((uint32_t)p & 1))
p++;
}
flash_set_do_pool_last (p);
return 0;
}
@@ -972,7 +1050,9 @@ gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
*do_data_p = NULL;
else
{
*do_data_p = flash_do_write (tag, data, len);
uint8_t nr = do_tag_to_nr (tag);
*do_data_p = flash_do_write (nr, data, len);
if (*do_data_p)
GPG_SUCCESS ();
else
@@ -1008,6 +1088,8 @@ gpg_do_public_key (uint8_t kk_byte)
const uint8_t *do_data;
uint8_t *key_addr;
DEBUG_INFO ("Public key\r\n");
if (kk_byte == 0xb6)
do_data = do_ptr[NR_DO_PRVKEY_SIG];
else if (kk_byte == 0xb8)
@@ -1017,6 +1099,7 @@ gpg_do_public_key (uint8_t kk_byte)
if (do_data == NULL)
{
DEBUG_INFO ("none.\r\n");
GPG_NO_RECORD();
return;
}
@@ -1048,17 +1131,16 @@ gpg_do_public_key (uint8_t kk_byte)
res_APDU_size = res_p - res_APDU;
}
DEBUG_INFO ("done.\r\n");
return;
}
const uint8_t *
gpg_do_read_simple (uint16_t tag)
gpg_do_read_simple (uint8_t nr)
{
const struct do_table_entry *do_p;
const uint8_t *do_data;
do_p = get_do_entry (tag);
do_data = *((const uint8_t **)do_p->obj);
do_data = do_ptr[nr];
if (do_data == NULL)
return NULL;
@@ -1071,17 +1153,15 @@ gpg_do_read_simple (uint16_t tag)
}
void
gpg_do_write_simple (uint16_t tag, const uint8_t *data, int size)
gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size)
{
const struct do_table_entry *do_p;
const uint8_t **do_data_p;
do_p = get_do_entry (tag);
do_data_p = (const uint8_t **)do_p->obj;
do_data_p = (const uint8_t **)&do_ptr[nr];
if (*do_data_p)
flash_do_release (*do_data_p);
*do_data_p = flash_do_write (tag, data, size);
*do_data_p = flash_do_write (nr, data, size);
if (*do_data_p)
GPG_SUCCESS ();
else
@@ -1106,7 +1186,7 @@ gpg_do_increment_digital_signature_counter (void)
count_data[1] = (count >> 8) & 0xff;
count_data[2] = count & 0xff;
do_ptr[NR_DO_DS_COUNT] = flash_do_write (GPG_DO_DS_COUNT, count_data,
do_ptr[NR_DO_DS_COUNT] = flash_do_write (NR_DO_DS_COUNT, count_data,
SIZE_DIGITAL_SIGNATURE_COUNTER);
}
@@ -1129,5 +1209,5 @@ gpg_do_reset_pw_counter (uint8_t which)
pwsb[which] = 3;
}
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
}

View File

@@ -61,7 +61,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
};
static const uint8_t const
get_data_rb_result[] __attribute__ ((aligned (1))) = {
read_binary_result[] __attribute__ ((aligned (1))) = {
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
};
@@ -91,6 +91,7 @@ cmd_verify (void)
int r;
DEBUG_INFO (" - VERIFY\r\n");
DEBUG_BYTE (p2);
len = cmd_APDU[4];
if (p2 == 0x81)
@@ -101,11 +102,20 @@ cmd_verify (void)
r = verify_admin (&cmd_APDU[5], len);
if (r < 0)
GPG_SECURITY_FAILURE ();
{
DEBUG_INFO ("failed\r\n");
GPG_SECURITY_FAILURE ();
}
else if (r == 0)
GPG_SECURITY_AUTH_BLOCKED ();
{
DEBUG_INFO ("blocked\r\n");
GPG_SECURITY_AUTH_BLOCKED ();
}
else
GPG_SUCCESS ();
{
DEBUG_INFO ("good\r\n");
GPG_SUCCESS ();
}
}
int
@@ -139,14 +149,18 @@ cmd_change_password (void)
int who = p2 - 0x80;
int r;
DEBUG_INFO ("Change PW\r\n");
DEBUG_BYTE (who);
if (who == 1) /* PW1 */
{
const uint8_t *pk = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
if (pk == NULL)
{
if (len < 6)
{
DEBUG_INFO ("permission denied.\r\n");
GPG_SECURITY_FAILURE ();
return;
}
@@ -170,11 +184,13 @@ cmd_change_password (void)
if (pw_len < 0)
{
DEBUG_INFO ("permission denied.\r\n");
GPG_SECURITY_FAILURE ();
return;
}
else if (pw_len == 0)
{
DEBUG_INFO ("blocked.\r\n");
GPG_SECURITY_AUTH_BLOCKED ();
return;
}
@@ -192,24 +208,33 @@ cmd_change_password (void)
r = gpg_change_keystring (who, old_ks, who, new_ks);
if (r < -2)
GPG_MEMORY_FAILURE ();
{
DEBUG_INFO ("memory error.\r\n");
GPG_MEMORY_FAILURE ();
}
else if (r < 0)
GPG_SECURITY_FAILURE ();
{
DEBUG_INFO ("security error.\r\n");
GPG_SECURITY_FAILURE ();
}
else if (r == 0 && who == 1) /* no prvkey */
{
no_prvkey:
gpg_do_write_simple (GNUK_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 ();
gpg_do_reset_pw_counter (PW_STATUS_PW1);
DEBUG_INFO ("Changed DO_KEYSTRING_PW1\r\n");
}
else if (r > 0 && who == 1)
{
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, 1);
gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
ac_reset_pso_cds ();
gpg_do_reset_pw_counter (PW_STATUS_PW1);
DEBUG_INFO ("Removed content of DO_KEYSTRING_PW1\r\n");
}
else /* r >= 0 && who == 3 */
{
DEBUG_INFO ("done.\r\n");
gpg_do_reset_pw_counter (PW_STATUS_PW3);
GPG_SUCCESS ();
}
@@ -225,10 +250,13 @@ cmd_reset_user_password (void)
int pw_len, newpw_len;
int r;
DEBUG_INFO ("Reset PW1\r\n");
DEBUG_BYTE (p1);
if (p1 == 0x00) /* by User with Reseting Code */
{
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
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];
@@ -236,12 +264,14 @@ cmd_reset_user_password (void)
if (pw_status_bytes == NULL
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
{
DEBUG_INFO ("blocked.\r\n");
GPG_SECURITY_AUTH_BLOCKED ();
return;
}
if (ks_rc == NULL)
{
DEBUG_INFO ("security error.\r\n");
GPG_SECURITY_FAILURE ();
return;
}
@@ -254,27 +284,33 @@ cmd_reset_user_password (void)
new_ks0[0] = newpw_len;
r = gpg_change_keystring (2, old_ks, 1, new_ks);
if (r < -2)
GPG_MEMORY_FAILURE ();
{
DEBUG_INFO ("memory error.\r\n");
GPG_MEMORY_FAILURE ();
}
else if (r < 0)
{
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
sec_fail:
DEBUG_INFO ("failed.\r\n");
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
pwsb[PW_STATUS_RC]--;
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
GPG_SECURITY_FAILURE ();
}
else if (r == 0)
{
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
goto sec_fail;
gpg_do_write_simple (GNUK_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 ();
gpg_do_reset_pw_counter (PW_STATUS_PW1);
DEBUG_INFO ("done (no prvkey).\r\n");
}
else
{
DEBUG_INFO ("done.\r\n");
ac_reset_pso_cds ();
gpg_do_reset_pw_counter (PW_STATUS_PW1);
GPG_SUCCESS ();
@@ -283,7 +319,10 @@ cmd_reset_user_password (void)
else /* by Admin (p1 == 0x02) */
{
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
GPG_SECURITY_FAILURE ();
{
DEBUG_INFO ("permission denied.\r\n");
GPG_SECURITY_FAILURE ();
}
else
{
const uint8_t *old_ks = keystring_md_pw3;
@@ -296,17 +335,25 @@ cmd_reset_user_password (void)
new_ks0[0] = newpw_len;
r = gpg_change_keystring (3, old_ks, 1, new_ks);
if (r < -2)
GPG_MEMORY_FAILURE ();
{
DEBUG_INFO ("memory error.\r\n");
GPG_MEMORY_FAILURE ();
}
else if (r < 0)
GPG_SECURITY_FAILURE ();
{
DEBUG_INFO ("security error.\r\n");
GPG_SECURITY_FAILURE ();
}
else if (r == 0)
{
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
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 ();
@@ -344,6 +391,7 @@ static void
cmd_pgp_gakp (void)
{
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
DEBUG_BYTE (cmd_APDU[2]);
if (cmd_APDU[2] == 0x81)
/* Get public key */
@@ -354,7 +402,7 @@ cmd_pgp_gakp (void)
GPG_SECURITY_FAILURE ();
/* XXX: Not yet supported */
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
GPG_ERROR ();
}
}
@@ -369,8 +417,8 @@ cmd_read_binary (void)
GPG_BAD_P0_P1 ();
else
/* Tag 5a, serial number */
write_res_apdu ((const uint8_t *)get_data_rb_result,
sizeof (get_data_rb_result), 0x90, 0x00);
write_res_apdu (read_binary_result,
sizeof (read_binary_result), 0x90, 0x00);
}
else
GPG_NO_RECORD();
@@ -388,8 +436,6 @@ cmd_select_file (void)
*/
file_selection = FILE_DF_OPENPGP;
/* XXX: Should return contents??? */
GPG_SUCCESS ();
}
else if (cmd_APDU[4] == 2
@@ -445,12 +491,16 @@ cmd_get_data (void)
static void
cmd_pso (void)
{
int len;
int r;
DEBUG_INFO (" - PSO\r\n");
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
{
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
{
DEBUG_INFO ("security error.");
GPG_SECURITY_FAILURE ();
return;
}
@@ -463,18 +513,16 @@ cmd_pso (void)
}
else
{
int len = (cmd_APDU[5]<<8) | cmd_APDU[6];
int r;
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
DEBUG_BYTE (len); /* Should be cmd_APDU_size - 6 */
r = rsa_sign (&cmd_APDU[7], res_APDU, len);
if (r < 0)
/* XXX: fail code??? */
write_res_apdu (NULL, 0, 0x69, 0x85);
GPG_ERROR ();
else
{ /* Success */
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
@@ -486,8 +534,23 @@ cmd_pso (void)
gpg_do_increment_digital_signature_counter ();
}
}
}
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
{
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
DEBUG_INFO ("done.\r\n");
if (!ac_check_status (AC_PSO_OTHER_AUTHORIZED))
{
DEBUG_INFO ("security error.");
GPG_SECURITY_FAILURE ();
return;
}
DEBUG_BYTE (len);
r = rsa_decrypt (&cmd_APDU[7], res_APDU, len);
if (r < 0)
GPG_ERROR ();
}
else
{ /* XXX: not yet supported */
@@ -497,6 +560,8 @@ cmd_pso (void)
DEBUG_BYTE (cmd_APDU[3]);
GPG_SUCCESS ();
}
DEBUG_INFO ("PSO done.\r\n");
}
struct command

View File

@@ -5,4 +5,5 @@
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
#define GPG_ERROR() write_res_apdu (NULL, 0, 0x6f, 0x00)
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 0x00)

View File

@@ -1,84 +0,0 @@
#include "config.h"
#include "ch.h"
#include "gnuk.h"
#include "polarssl/config.h"
#include "polarssl/rsa.h"
static rsa_context rsa_ctx;
int
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len)
{
mpi P1, Q1, H;
int r;
DEBUG_BINARY (kd.data, 256);
mpi_init (&P1, &Q1, &H, NULL);
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
rsa_ctx.len = 2048 / 8;
mpi_read_string (&rsa_ctx.E, 16, "10001");
mpi_read_binary (&rsa_ctx.P, &kd.data[0], rsa_ctx.len / 2);
mpi_read_binary (&rsa_ctx.Q, &kd.data[128], rsa_ctx.len / 2);
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
mpi_sub_int (&P1, &rsa_ctx.P, 1);
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
mpi_mul_mpi (&H, &P1, &Q1);
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
mpi_free (&P1, &Q1, &H, NULL);
DEBUG_INFO ("RSA...");
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
DEBUG_INFO ("ok...");
else
{
DEBUG_INFO ("failed.\r\n");
DEBUG_SHORT (r);
rsa_free (&rsa_ctx);
return r;
}
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
msg_len, raw_message, output);
rsa_free (&rsa_ctx);
DEBUG_INFO ("done.\r\n");
if (r < 0)
{
DEBUG_SHORT (r);
return r;
}
else
return 0;
}
const uint8_t *
modulus_calc (const uint8_t *p, int len)
{
mpi P, Q, N;
uint8_t *modulus;
(void)len; /* 2048-bit assumed */
modulus = malloc (2048 / 8);
if (modulus == NULL)
return NULL;
mpi_init (&P, &Q, &N, NULL);
mpi_read_binary (&P, p, 2048 / 8 / 2);
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
mpi_mul_mpi (&N, &P, &Q);
mpi_write_binary (&N, modulus, 2048 / 8);
mpi_free (&P, &Q, &N, NULL);
return modulus;
}
void
modulus_free (const uint8_t *p)
{
free ((void *)p);
}

View File

@@ -435,7 +435,9 @@ icc_handle_timeout (void)
switch (icc_state)
{
case ICC_STATE_EXECUTE:
#if 0
icc_send_data_block (ICC_CMD_STATUS_TIMEEXT, 0, 0, NULL, 0);
#endif
break;
case ICC_STATE_RECEIVE:
case ICC_STATE_SEND:

View File

@@ -1,5 +1,5 @@
/*
*
* usb_desc.c - USB Descriptor
*/
#include "config.h"
@@ -20,8 +20,8 @@ static const uint8_t gnukDeviceDescriptor[] = {
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0xff, 0xff, /* idVendor = 0xffff */
0x01, 0x00, /* idProduct = 0x0001 */
0x4b, 0x23, /* idVendor = 0x234b (FSIJ) */
0x00, 0x00, /* idProduct = 0x0000 (FSIJ USB Token) */
0x00, 0x02, /* bcdDevice = 2.00 */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */