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

138
README
View File

@@ -1,33 +1,49 @@
Gnuk - A USB Token software implementation
Gnuk - software for GPG USB Token
Version 0.0 2010-09-01
Version 0.0 2010-09-05
Niibe Yutaka
What's Gnuk
===========
Gnuk is a USB token software implementation to use with GNU privacy
guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
Olimex STM32-H103 board.
Gnuk is software implementation of a USB token for GNU privacy guard.
Gnuk supports OpenPGP card protocol version 2, and it runs on STM32
processor.
Release notes
=============
Initially, the development was started with a copy of the files in
ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*, Makefile, linker script,
and header files (chconf.h, halconf.h, and mcuconf.h).
This is initial release of Gnuk, and it is experimental yet.
It is not yet daily use.
Since this is the initial release, some garbages still remain.
Supported and tested features are:
* Personalization of the card
* Changing Login name, URL, Name, Sex, Language, etc.
* Password handling (PW1, RC, PW3)
* Single key import
* PSO: Digital Signature
Target
======
It is known not-working:
* Multiple key import
* PSO: Decipher
Targets
=======
We use Olimex STM32-H103 board.
I think that it runs on Olimex STM32-P103 too. We are porting to
STM32 Primer 2.
I think that it runs on Olimex STM32-P103, STBee, or STBee mini too.
Besides, we are porting it to STM32 Primer 2.
Souce code
@@ -49,35 +65,46 @@ External source code
Gnuk is distributed with external source code.
* ChibiOS_2.0.2/ -- ChibiOS/RT 2.0.2
Taken from http://chibios.sourceforge.net/
Note that CRLF is converted to LF in this repository.
We use ChibiOS/RT as the kernel for Gnuk.
Taken from http://chibios.sourceforge.net/
Note that CRLF is converted to LF in this repository.
We use ChibiOS/RT as the kernel for Gnuk.
* polarssl-0.14.0/ -- PolarSSL 0.14.0
Taken from http://polarssl.org/
We use PolarSSL for RSA computation.
Taken from http://polarssl.org/
We use PolarSSL for RSA computation.
* STM32_USB-FS-Device_Driver/ -- a part of USB-FS-Device_Lib
* Virtual_COM_Port/ -- a part of USB-FS-Device_Lib
STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
is a STM32F10x library for USB functionality.
STM32F10x USB Full Speed Device Library (USB-FS-Device_Lib)
is a STM32F10x library for USB functionality.
I took Libraries/STM32_USB-FS-Device_Driver and a part of
Project/ in STM32_USB-FS-Device_Lib distribution.
See http://www.st.com for detail.
I took Libraries/STM32_USB-FS-Device_Driver and a part of
Project/ in STM32_USB-FS-Device_Lib distribution.
See http://www.st.com for detail.
How to compile
==============
You need GNU Toolchain and newlib for 'arm-none-eabi' target.
You need GNU toolchain and newlib for 'arm-none-eabi' target.
See http://github.com/esden/summon-arm-toolchain/ for preparation of
GNU Toolchain for 'arm-none-eabi' target.
$ cd gnuk-VERSION/src
Edit the Makefile. Comment out the line:
----------------
ENABLE_DEBUG=1
----------------
if you don't want to debug Gnuk.
Type:
$ make
Then, we will have "gnuk.elf".
@@ -99,6 +126,54 @@ Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
> exit
$
If you compiled with ENABLE_DEBUG=1, Gnuk has two interfaces
(one is CCID/ICCD device and another is virtual COM port). Open
virtual COM port by:
$ cu -l /dev/ttyACM0
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
+++ /etc/libccid_Info.plist 2010-09-05 09:09:49.000000000 +0900
@@ -104,6 +104,7 @@
<key>ifdVendorID</key>
<array>
+ <string>0x234B</string>
<string>0x08E6</string>
<string>0x08E6</string>
<string>0x08E6</string>
@@ -237,6 +238,7 @@
<key>ifdProductID</key>
<array>
+ <string>0x0000</string>
<string>0x2202</string>
<string>0x3437</string>
<string>0x3438</string>
@@ -370,6 +372,7 @@
<key>ifdFriendlyName</key>
<array>
+ <string>FSIJ USB Token</string>
<string>Gemplus Gem e-Seal Pro</string>
<string>Gemplus GemPC Twin</string>
<string>Gemplus GemPC Key</string>
------------------
Then, try following to see Gnuk runs:
$ gpg --card-status
For more, see doc/HOWTO_GNUK.
How to debug
============
@@ -107,4 +182,19 @@ We can use GDB.
$ arm-none-eabi-gdb gnuk.elf
Inside GDB, we can connect OpenOCD by:
(gdb) target remote localhost:3333
Development history
===================
Initially, the development was started with a copy of the files in
ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*, Makefile, linker script,
and header files (chconf.h, halconf.h, and mcuconf.h).
Since this is the initial release, some garbages may still remain.
--

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

@@ -111,10 +111,22 @@ SECTIONS
. = ALIGN(4);
_bss_end = .;
} > 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 */