Now, v2 works.

This commit is contained in:
NIIBE Yutaka 2010-08-30 20:02:22 +09:00
parent 55e9678ab8
commit 40455cd4a5
13 changed files with 574 additions and 209 deletions

110
README
View File

@ -1,34 +1,110 @@
Gnuk - A USB Token software implementation
Version 0.0 2010-09-01
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.
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).
Since this is the initial release, some garbages still remain.
Target
======
We use Olimex STM32-H103 board.
I think that it runs on Olimex STM32-P103 too. We are porting to
STM32 Primer 2.
Souce code
==========
Initially, it is copy of ChibiOS_2.0.2/demos/ARMCM3-STM32F103-GCC/*.
Gnuk source code is under src/ directory.
External source
===============
* ChibiOS_2.0.2
License
=======
It is distributed under GNU General Public Licence version 3 or later
(GPLv3+).
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.
* PolarSSS 0.14.0
* polarssl-0.14.0/ -- PolarSSL 0.14.0
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)
I took Libraries/STM32_USB-FS-Device_Driver and a part of
Project/Virtual_COM_Port in STM32_USB-FS-Device_Lib distribution.
Project/ in STM32_USB-FS-Device_Lib distribution.
See http://www.st.com for detail.
HOWTO RUN
=================
How to compile
==============
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
You need GNU Toolchain and newlib for 'arm-none-eabi' target.
$ arm-none-eabi-gdb --annotate=3 gnuk.elf
See http://github.com/esden/summon-arm-toolchain/ for preparation of
GNU Toolchain for 'arm-none-eabi' target.
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
$ cd gnuk-VERSION/src
$ make
Then, we will have "gnuk.elf".
How to run
==========
If you are using Olimex JTAG-Tiny, type following to invoke OpenOCD:
$ openocd -f interface/olimex-jtag-tiny.cfg -f board/olimex_stm32_h103.cfg
Then, with another terminal, type following to write "gnuk.elf" to Flash ROM:
$ telnet localhost 4444
> reset halt
> flash write_image erase gnuk.elf
> reset
> exit
$
How to debug
============
We can use GDB.
$ arm-none-eabi-gdb gnuk.elf
--

View File

@ -92,9 +92,8 @@
/*
* Uncomment this macro to store the AES tables in ROM.
*
#define POLARSSL_AES_ROM_TABLES
*/
#define POLARSSL_AES_ROM_TABLES
/*
* Module: library/aes.c

View File

@ -66,7 +66,7 @@ include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/port.mk
include $(CHIBIOS)/os/kernel/kernel.mk
include stmusb.mk
include vcomport.mk
include rsa.mk
include crypt.mk
include ../boards/OLIMEX_STM32_H103/board.mk
# C sources that can be compiled in ARM or THUMB mode depending on the global
@ -80,15 +80,16 @@ CSRC = $(PORTSRC) \
$(CHIBIOS)/os/various/syscalls.c \
$(STMUSBSRC) \
$(VCOMSRC) \
$(RSASRC) \
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c \
$(CRYPTSRC) \
main.c debug.c usb_lld.c \
hw_config.c usb_desc.c usb_prop.c \
usb-icc.c gpg.c ac.c openpgp-do.c flash.c
# List ASM source files here
ASMSRC = $(PORTASM) \
$(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F10x/vectors.s gpg-data.s
INCDIR = $(RSAINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
INCDIR = $(CRYPTINCDIR) $(STMUSBINCDIR) $(VCOMDIR) \
$(PORTINC) $(KERNINC) $(TESTINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
$(CHIBIOS)/os/various

View File

@ -5,6 +5,9 @@
#include "ch.h"
#include "gnuk.h"
#include "polarssl/config.h"
#include "polarssl/sha1.h"
static uint8_t auth_status = AC_NONE_AUTHORIZED;
int
@ -26,16 +29,21 @@ ac_check_status (uint8_t ac_flag)
* check magic in params
*/
uint8_t keystring_pw1[KEYSTRING_LEN] = {
0x62, 0x10, 0x27, 0x44, 0x34, 0x05, 0x2f, 0x20,
0xfc, 0xb8, 0x3e, 0x1d, 0x0f, 0x49, 0x22, 0x04,
0xfc, 0xb1, 0x18, 0x84
};
int
verify_pso_cds (uint8_t *pw, int pw_len)
{
#if 0
compute_hash;
if (cmp_hash (pw1_hash, hash) == 0)
good;
else
return -1;
#endif
int r;
sha1 (pw, pw_len, keystring_pw1);
if ((r = gpg_load_key (GPG_KEY_FOR_SIGNATURE)) < 0)
return r;
auth_status |= AC_PSO_CDS_AUTHORIZED;
return 0;
}
@ -43,13 +51,6 @@ verify_pso_cds (uint8_t *pw, int pw_len)
int
verify_pso_other (uint8_t *pw, int pw_len)
{
#if 0
compute_hash;
if (cmp_hash (pw1_hash, hash) == 0)
good;
else
return -1;
#endif
auth_status |= AC_PSO_OTHER_AUTHORIZED;
return 0;
}

6
src/crypt.mk Normal file
View File

@ -0,0 +1,6 @@
CRYPTDIR = ../polarssl-0.14.0
CRYPTSRCDIR = $(CRYPTDIR)/library
CRYPTINCDIR = $(CRYPTDIR)/include
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
$(CRYPTSRCDIR)/aes.c \
rsa-sign.c

73
src/debug.c Normal file
View File

@ -0,0 +1,73 @@
/*
* debug.c -- Debuging with virtual COM port
*
* 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"
static void
put_hex (uint8_t nibble)
{
uint8_t c;
if (nibble < 0x0a)
c = '0' + nibble;
else
c = 'a' + nibble - 0x0a;
_write (&c, 1);
}
void
put_byte (uint8_t b)
{
put_hex (b >> 4);
put_hex (b &0x0f);
_write ("\r\n", 2);
}
void
put_byte_with_no_nl (uint8_t b)
{
_write (" ", 1);
put_hex (b >> 4);
put_hex (b &0x0f);
}
void
put_short (uint16_t x)
{
put_hex (x >> 12);
put_hex ((x >> 8)&0x0f);
put_hex ((x >> 4)&0x0f);
put_hex (x & 0x0f);
_write ("\r\n", 2);
}
void
put_string (const char *s)
{
_write (s, strlen (s));
}

View File

@ -21,14 +21,22 @@
*
*/
/*
* Writing to Flash ROM is NOT YET IMPLEMENTED, just API only
*/
#include "ch.h"
#include "gnuk.h"
static uint8_t do_pool[256];
static uint8_t *last_p = do_pool;
/*
* TLV (Tag, Length, and Value)
*/
uint8_t *
flash_do_write (uint16_t tag, uint8_t *data, int len)
{
static uint8_t do_pool[1024];
static uint8_t *last_p = do_pool;
uint8_t *p = last_p;
if (last_p - do_pool + len + 2 + 3 > 1024)
@ -54,3 +62,35 @@ flash_do_write (uint16_t tag, uint8_t *data, int len)
return p + 2;
}
static uint8_t k1[KEY_CONTENT_LEN];
#if 0
static uint8_t k2[KEY_CONTENT_LEN];
static uint8_t k3[KEY_CONTENT_LEN];
#endif
uint8_t *
flash_key_alloc (enum kind_of_key kk)
{
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
}
}
int
flash_key_write (uint8_t *key_addr, uint8_t *key_data)
{
memcpy (key_addr, key_data, KEY_CONTENT_LEN);
return 0;
}

15
src/gen-gpg-data Normal file
View File

@ -0,0 +1,15 @@
#! /bin/sh
arm-none-eabi-gcc -S -mcpu=cortex-m3 -O0 -ggdb -fomit-frame-pointer \
-falign-functions=16 -ffunction-sections \
-Wall -Wextra -Wstrict-prototypes -Wa,-alms=gpg-data.lst \
-DCORTEX_USE_BASEPRI=TRUE -DTHUMB_PRESENT -mno-thumb-interwork \
-DTHUMB_NO_INTERWORKING -mthumb -DTHUMB \
-I . -I../STM32_USB-FS-Device_Driver/inc -I../USBCDC \
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx \
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/STM32F10x \
-I../ChibiOS_2.0.2/os/ports/GCC/ARMCMx/cmsis \
-I../ChibiOS_2.0.2/os/kernel/include -I../ChibiOS_2.0.2/test \
-I../ChibiOS_2.0.2/os/hal/include \
-I../ChibiOS_2.0.2/os/hal/platforms/STM32 -I../boards/OLIMEX_STM32_H103 \
-I../ChibiOS_2.0.2/os/various gpg-data.c

View File

@ -1,6 +1,7 @@
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_string (const char *s);
@ -50,3 +51,34 @@ extern void gpg_do_get_data (uint16_t tag);
extern void gpg_do_put_data (uint16_t tag, uint8_t *data, int len);
extern uint8_t * flash_do_write (uint16_t tag, uint8_t *data, int len);
enum kind_of_key {
GPG_KEY_FOR_SIGNATURE,
GPG_KEY_FOR_DECRYPT,
GPG_KEY_FOR_AUTHENTICATION,
};
extern uint8_t *flash_key_alloc (enum kind_of_key);
#define KEY_MAGIC_LEN 8
#define KEY_CONTENT_LEN 256
#define GNUK_MAGIC "Gnuk KEY"
#define KEYSTORE_LEN (KEY_MAGIC_LEN+4+4+KEY_CONTENT_LEN)
struct key_data {
uint8_t *key_addr;
/* encrypted data content */
char magic[KEY_MAGIC_LEN];
uint32_t random;
uint32_t check;
uint8_t data[KEY_CONTENT_LEN];
};
extern int flash_key_write (uint8_t *key_addr, uint8_t *key_data);
#define KEYSTRING_LEN 20 /* Use 16-byte for AES encryption */
extern uint8_t keystring_pw1[KEYSTRING_LEN];
extern int gpg_load_key (enum kind_of_key kk);
extern struct key_data kd;

View File

@ -25,45 +25,7 @@
#include "hal.h"
#include "gnuk.h"
static void
put_hex (uint8_t nibble)
{
uint8_t c;
if (nibble < 0x0a)
c = '0' + nibble;
else
c = 'a' + nibble - 0x0a;
_write (&c, 1);
}
void
put_byte (uint8_t b)
{
put_hex (b >> 4);
put_hex (b &0x0f);
_write ("\r\n", 2);
}
void
put_short (uint16_t x)
{
put_hex (x >> 12);
put_hex ((x >> 8)&0x0f);
put_hex ((x >> 4)&0x0f);
put_hex (x & 0x0f);
_write ("\r\n", 2);
}
void
put_string (const char *s)
{
_write (s, strlen (s));
}
#define RSA_SIGNATURE_LENGTH 128 /* 256 *//* 256 byte == 2048-bit */
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
extern unsigned char *rsa_sign (unsigned char *);
#define INS_PUT_DATA 0xDA
@ -277,6 +239,7 @@ process_command_apdu (void)
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
{
if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
/* Extended Lc: 3-byte */
{
put_string (" wrong length: ");
put_short (cmd_APDU_size);

View File

@ -26,6 +26,9 @@
#include "ch.h"
#include "gnuk.h"
#include "polarssl/config.h"
#include "polarssl/aes.h"
/*
* Compile time vars:
* AID, Historical Bytes (template), Extended Capabilities,
@ -120,6 +123,7 @@ enum do_type {
DO_CN_READ,
DO_PROC_READ,
DO_PROC_WRITE,
DO_PROC_READWRITE,
DO_HASH,
DO_KEYPTR
};
@ -142,6 +146,8 @@ static struct do_table_entry *get_do_entry (uint16_t tag);
#define GNUK_DO_KEYPTR_DEC 0xff02
#define GNUK_DO_KEYPTR_AUT 0xff03
#define GNUK_DO_HASH_PW3 0xff04
#define GNUK_DO_HASH_RC 0xff05
#define GNUK_DO_PW_STATUS 0xff06
#define GPG_DO_AID 0x004f
#define GPG_DO_NAME 0x005b
@ -311,24 +317,225 @@ do_kgtime_all (uint16_t tag)
}
static void
put_hex (uint8_t nibble)
rw_pw_status (uint16_t tag, uint8_t *data, int len, int is_write)
{
uint8_t c;
struct do_table_entry *do_p;
if (nibble < 0x0a)
c = '0' + nibble;
if (is_write)
{
const uint8_t *do_data;
do_p = get_do_entry (GNUK_DO_PW_STATUS);
if (do_p)
{
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (data, &do_data[2], SIZE_PW_STATUS_BYTES - 1);
do_p->obj = flash_do_write (tag, data, len);
if (do_p->obj)
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
else
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
}
else
/* No record */
write_res_apdu (NULL, 0, 0x6a, 0x88);
}
else
c = 'a' + nibble - 0x0a;
{
const uint8_t *do_data;
_write (&c, 1);
if (with_tag)
{
copy_tag (tag);
*res_p++ = SIZE_PW_STATUS_BYTES;
}
do_p = get_do_entry (GNUK_DO_PW_STATUS);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
{
memcpy (res_p, &do_data[1], SIZE_PW_STATUS_BYTES);
res_p += SIZE_PW_STATUS_BYTES;
}
else
/* No record */
write_res_apdu (NULL, 0, 0x6a, 0x88);
}
}
static void
o_put_byte (uint8_t b)
proc_resetting_code (uint16_t tag, uint8_t *data, int len)
{
_write (" ", 1);
put_hex (b >> 4);
put_hex (b &0x0f);
/* Not implementad yet */
/*
* calculate hash, write it to GNUK_DO_HASH_RC.
*/
/* Then, we need to reset RC counter in GNUK_DO_PW_STATUS */
}
static uint8_t iv[16];
static aes_context aes;
static int iv_offset;
static void
encrypt (uint8_t *key_str, uint8_t *data)
{
aes_setkey_enc (&aes, key_str, 128);
memset (iv, 0, 16);
iv_offset = 0;
aes_crypt_cfb128 (&aes, AES_ENCRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
{
int i, len = KEYSTORE_LEN;
put_string ("ENC\r\n");
for (i = 0; i < len; i++)
{
put_byte_with_no_nl (data[i]);
if ((i & 0x0f) == 0x0f)
_write ("\r\n", 2);
}
_write ("\r\n", 2);
}
}
struct key_data kd;
static void
decrypt (uint8_t *key_str, uint8_t *data)
{
aes_setkey_enc (&aes, key_str, 128);
memset (iv, 0, 16);
iv_offset = 0;
aes_crypt_cfb128 (&aes, AES_DECRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
{
int i, len = KEYSTORE_LEN;
put_string ("DEC\r\n");
for (i = 0; i < len; i++)
{
put_byte_with_no_nl (data[i]);
if ((i & 0x0f) == 0x0f)
_write ("\r\n", 2);
}
_write ("\r\n", 2);
}
}
int
gpg_load_key (enum kind_of_key kk)
{
struct do_table_entry *do_p;
switch (kk)
{
case GPG_KEY_FOR_SIGNATURE:
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
break;
case GPG_KEY_FOR_DECRYPT:
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
break;
case GPG_KEY_FOR_AUTHENTICATION:
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
break;
}
if (do_p == NULL)
return -1;
kd.key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
memcpy (((uint8_t *)&kd)+4, ((uint8_t *)do_p->obj)+5, KEY_MAGIC_LEN+4+4);
memcpy (kd.data, kd.key_addr, KEY_CONTENT_LEN);
decrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
return -1;
/* XXX: more sanity check */
return 0;
}
uint32_t
get_random (void)
{
return 0x80808080; /* XXX: for now */
}
static uint32_t
calc_check (uint8_t *data, int len)
{
uint32_t check = 0;
int i;
for (i = 0; i < len; i++)
check += data[i];
return check;
}
static int
gpg_write_do_keyptr (enum kind_of_key kk, uint8_t *key_data, int key_len)
{
uint8_t *p;
int len;
int r;
uint32_t key_addr;
struct do_table_entry *do_p;
#if 0
assert (key_len == KEY_CONTENT_LEN+4);
/* key_data should starts with 00 01 00 01 (E) */
#endif
put_short (key_len);
key_data += 4;
kd.key_addr = flash_key_alloc (kk);
if (kd.key_addr == NULL)
return -1;
memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
kd.check = calc_check (key_data, KEY_CONTENT_LEN);
kd.random = get_random ();
memcpy (kd.data, key_data, KEY_CONTENT_LEN);
put_string ("enc...");
encrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
put_string ("done\r\n");
if ((r = flash_key_write (kd.key_addr, kd.data)) < 0)
return r;
switch (kk)
{
case GPG_KEY_FOR_SIGNATURE:
p = flash_do_write (GNUK_DO_KEYPTR_SIG, &kd,
sizeof (kd) - KEY_CONTENT_LEN);
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
do_p->obj = p;
break;
case GPG_KEY_FOR_DECRYPT:
p = flash_do_write (GNUK_DO_KEYPTR_DEC, &kd,
sizeof (kd) - KEY_CONTENT_LEN);
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
do_p->obj = p;
break;
case GPG_KEY_FOR_AUTHENTICATION:
p = flash_do_write (GNUK_DO_KEYPTR_AUT, &kd,
sizeof (kd) - KEY_CONTENT_LEN);
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
do_p->obj = p;
break;
}
if (p == NULL)
return -1;
return 0;
}
/*
@ -338,22 +545,34 @@ o_put_byte (uint8_t b)
* 91 xx
* 92 xx
* 93 xx
* 5f48, xx: cardholder privatge key
* 5f48, xx: cardholder private key
*/
static void
proc_key_import (uint16_t tag, uint8_t *data, int len)
{
int i;
int i, r;
enum kind_of_key kk;
for (i = 0; i < len; i++)
{
o_put_byte (data[i]);
put_byte_with_no_nl (data[i]);
if ((i & 0x0f) == 0x0f)
_write ("\r\n", 2);
}
_write ("\r\n", 2);
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
if (data[4] == 0xa4)
kk = GPG_KEY_FOR_AUTHENTICATION;
else if (data[4] == 0xb8)
kk = GPG_KEY_FOR_DECRYPT;
else /* 0xb6 */
kk = GPG_KEY_FOR_SIGNATURE;
r = gpg_write_do_keyptr (kk, &data[22], len - 22);
if (r < 0)
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
else
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
}
static const uint16_t const cn_ch_data[] = {
@ -383,11 +602,16 @@ gpg_do_table[] = {
{ GNUK_DO_KEYPTR_DEC, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
{ GNUK_DO_KEYPTR_AUT, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
{ GNUK_DO_HASH_PW3, DO_HASH, AC_NEVER, AC_NEVER, NULL },
/* Pseudo DO: calculated */
{ GNUK_DO_HASH_RC, DO_HASH, AC_NEVER, AC_NEVER, NULL },
{ GNUK_DO_PW_STATUS, DO_VAR, AC_NEVER, AC_NEVER, NULL },
/* Pseudo DO READ: calculated */
{ GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
{ GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all },
{ GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all },
{ GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all },
/* Pseudo DO READ/WRITE: calculated */
{ GPG_DO_PW_STATUS, DO_PROC_READWRITE, AC_ALWAYS, AC_ADMIN_AUTHORIZED,
rw_pw_status },
/* Fixed data */
{ GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid },
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
@ -397,7 +621,6 @@ gpg_do_table[] = {
/* Variable(s): Fixed size, not changeable by user */
{ GPG_DO_DS_COUNT, DO_VAR, AC_ALWAYS, AC_NEVER, NULL },
/* Variables: Fixed size */
{ GPG_DO_PW_STATUS, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
@ -414,12 +637,13 @@ gpg_do_table[] = {
{ GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
/* Variable(s): Variable size, write only by user */
{ GPG_DO_RESETTING_CODE, DO_VAR, AC_NEVER, AC_ADMIN_AUTHORIZED, NULL },
/* Compound data: Read access only */
{ GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data },
{ GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data },
{ GPG_DO_SS_TEMP, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ss_temp },
/* Simple data: write access only */
{ GPG_DO_RESETTING_CODE, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
proc_resetting_code },
/* Compound data: Write access only*/
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
proc_key_import },
@ -448,7 +672,7 @@ gpg_do_table_init (void)
do_p = get_do_entry (GPG_DO_LOGIN_DATA);
do_p->obj = do_5e;
do_p = get_do_entry (GPG_DO_PW_STATUS);
do_p = get_do_entry (GNUK_DO_PW_STATUS);
do_p->obj = do_c4;
#if 0
do_p = get_do_entry (GPG_DO_FP_SIG);
@ -578,6 +802,14 @@ copy_do (struct do_table_entry *do_p)
do_func (do_p->tag);
break;
}
case DO_PROC_READWRITE:
{
void (*rw_func)(uint16_t, uint8_t *, int, int)
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
rw_func (do_p->tag, NULL, 0, 0);
break;
}
case DO_PROC_WRITE:
case DO_HASH:
case DO_KEYPTR:
@ -655,33 +887,25 @@ gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
flash_do_release (do_data);
#endif
if (tag == GPG_DO_PW_STATUS)
{
/* XXX: only the first byte can be changed */
}
if (len == 0)
/* make DO empty */
do_p->obj = NULL;
else
{
if (len == 0)
/* make DO empty */
do_p->obj = NULL;
do_p->obj = flash_do_write (tag, data, len);
if (do_p->obj)
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
else
{
do_p->obj = flash_do_write (tag, data, len);
if (do_p->obj)
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
else
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
}
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
}
break;
}
case DO_PROC_READWRITE:
{
void (*rw_func)(uint16_t, uint8_t *, int, int)
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
/*
*
*/
if (tag == GPG_DO_RESETTING_CODE)
{
/* XXX: Changing Resetting code,
* we need to reset RC counter in GPG_DO_PW_STATUS */
}
rw_func (tag, data, len, 1);
break;
}
case DO_PROC_WRITE:

View File

@ -1,118 +1,57 @@
#include "ch.h"
#include "gnuk.h"
#include <polarssl/config.h>
#include <polarssl/rsa.h>
#include "polarssl/config.h"
#include "polarssl/rsa.h"
static unsigned char output[256];
/* big endian */
static const unsigned char p[64] = {
0xe3,0xec,0x42,0x6c,0x23,0x37,0x1f,0x96,
0x55,0x2f,0x1d,0x2a,0x37,0xd2,0x66,0x43,
0x3c,0xb1,0xa5,0x24,0x47,0x8e,0x29,0x86,
0xee,0xec,0xa9,0x86,0x1e,0x05,0xfb,0xfa,
0x00,0x0e,0x69,0xbc,0x60,0x47,0x1c,0x00,
0x96,0xdc,0x30,0x00,0x05,0xfb,0xe0,0x00,
0xae,0x05,0x38,0x38,0xf9,0x7e,0xa6,0xae,
0xf6,0x90,0x68,0x48,0xf5,0x23,0x7f,0x3d,
};
static const unsigned char q[64] = {
0xf2,0x8c,0xa0,0x24,0x38,0x7c,0x6e,0x66,
0x9c,0x39,0xe9,0x4d,0x2b,0xe3,0x94,0xd1,
0x93,0x3f,0x17,0xcb,0x3f,0x4e,0x8d,0xa4,
0xdd,0x1f,0xee,0x00,0x7d,0x8c,0x5e,0xbb,
0xc7,0x80,0x1a,0xf5,0x79,0x80,0x63,0x5a,
0xc7,0xa2,0xb7,0x92,0x75,0x26,0xda,0xd4,
0xc9,0x9f,0x83,0x58,0x81,0x0a,0x53,0xa3,
0xe4,0x0b,0xd1,0xde,0xe2,0x33,0xf2,0x9b,
};
/* dq = 1/e mod (p - 1) */
static const unsigned char dp[64] = {
0x44,0x60,0x63,0x88,0xe7,0x83,0xa9,0x01,
0x43,0xaa,0xef,0xb7,0xf3,0xa9,0x36,0x2e,
0xa3,0xad,0xb3,0x9a,0x4f,0xb1,0x31,0x7a,
0x1e,0x81,0x77,0x56,0x19,0xf9,0xb7,0x9f,
0x47,0x97,0x0b,0x57,0x8d,0x16,0xa8,0x2a,
0xf1,0x17,0x3b,0x7b,0x36,0x50,0x5a,0xe2,
0x39,0x52,0xad,0x8c,0x42,0x25,0x21,0xc2,
0x49,0x8c,0x07,0x0d,0x24,0x25,0xb3,0x0d,
};
/* dq = 1/e mod (q - 1) */
static const unsigned char dq[64] = {
0x6c,0xbe,0xbd,0xe1,0xdf,0x6d,0x72,0x76,
0x10,0xdf,0x2a,0x09,0x8e,0x7e,0xe7,0xaf,
0x1a,0xcc,0x73,0xd7,0x8d,0x57,0xa3,0xcb,
0xe1,0xd4,0x39,0xfa,0x00,0x50,0x19,0xfd,
0x28,0xd1,0xf7,0xc4,0x4d,0x28,0x51,0xe3,
0x56,0x94,0x4e,0xa7,0x9c,0x5c,0xc2,0x4a,
0x1a,0xe7,0xa8,0x94,0xda,0xae,0x0d,0x97,
0xf2,0x5b,0x96,0x49,0xce,0xb3,0x29,0xb7,
};
/* q_inv = 1/q mod p */
static const unsigned char q_inv[64] = {
0x19,0x77,0x6a,0xc8,0xd7,0x2b,0x9f,0x82,
0x2d,0xbd,0x05,0x89,0xd8,0x0f,0x1e,0xb6,
0x19,0x82,0x58,0x2f,0x7f,0xfd,0xee,0x50,
0x00,0x75,0x85,0x69,0x64,0x37,0x32,0xa0,
0x62,0x55,0x5b,0x13,0x71,0x9e,0x4e,0x1f,
0x93,0x4c,0xa2,0x77,0x6c,0x70,0x07,0xa6,
0xfb,0xd5,0x4e,0x94,0xab,0xbd,0xa0,0x0e,
0x0d,0x42,0x07,0x9d,0xbb,0x5d,0xbc,0x75,
};
static rsa_context ctx;
unsigned char *
rsa_sign (unsigned char *raw_message)
{
rsa_context ctx;
mpi P1, Q1, H;
int len;
int r;
len = (cmd_APDU[5]<<8) | cmd_APDU[6]; /* cmd_APDU_size - 6 */
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
put_byte (len);
/* cmd_APDU_size - 6 */
mpi_init( &P1, &Q1, &H, NULL );
rsa_init( &ctx, RSA_PKCS_V15, 0 );
#if 0
ctx.len = 2048 / 8;
#else
ctx.len = 1024 / 8;
mpi_read_string( &ctx.E, 16, "10001" );
mpi_read_binary (&ctx.P, p, ctx.len / 2);
mpi_read_binary (&ctx.Q, q, ctx.len / 2);
mpi_mul_mpi( &ctx.N, &ctx.P, &ctx.Q );
mpi_sub_int( &P1, &ctx.P, 1 );
mpi_sub_int( &Q1, &ctx.Q, 1 );
mpi_mul_mpi( &H, &P1, &Q1 );
mpi_inv_mod( &ctx.D , &ctx.E, &H );
mpi_read_binary (&ctx.DP, dp, ctx.len / 2);
mpi_read_binary (&ctx.DQ, dq, ctx.len / 2);
mpi_read_binary (&ctx.QP, q_inv, ctx.len / 2);
#endif
mpi_read_string ( &ctx.E, 16, "10001" );
mpi_read_binary ( &ctx.P, &kd.data[0], ctx.len / 2 );
mpi_read_binary ( &ctx.Q, &kd.data[128], ctx.len / 2 );
mpi_mul_mpi ( &ctx.N, &ctx.P, &ctx.Q );
mpi_sub_int ( &P1, &ctx.P, 1 );
mpi_sub_int ( &Q1, &ctx.Q, 1 );
mpi_mul_mpi ( &H, &P1, &Q1 );
mpi_inv_mod ( &ctx.D , &ctx.E, &H );
mpi_mod_mpi ( &ctx.DP, &ctx.D, &P1);
mpi_mod_mpi ( &ctx.DQ, &ctx.D, &Q1);
mpi_inv_mod ( &ctx.QP, &ctx.Q, &ctx.P);
mpi_free (&P1, &Q1, &H, NULL);
put_string ("RSA...");
{
int r;
if ((r = rsa_check_privkey( &ctx )) == 0)
if ((r = rsa_check_privkey ( &ctx )) == 0)
put_string ("ok...");
else
{
put_string ("failed.\r\n");
put_byte (r);
rsa_free (&ctx);
return output;
}
}
#if 0
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output);
r = rsa_pkcs1_sign ( &ctx, RSA_PRIVATE, SIG_RSA_RAW,
len, raw_message, output );
put_short (r);
put_string ("done.\r\n");
rsa_free (&ctx);
return output;
#else
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output );
put_string ("done.\r\n");
return output;
#endif
}

View File

@ -1,4 +0,0 @@
RSADIR = ../polarssl-0.14.0
RSASRCDIR = $(RSADIR)/library
RSAINCDIR = $(RSADIR)/include
RSASRC = $(RSASRCDIR)/bignum.c $(RSASRCDIR)/rsa.c rsa-sign.c