DO management

This commit is contained in:
NIIBE Yutaka
2010-08-26 19:50:06 +09:00
parent 8ee8d3eb27
commit 4e397a033c
12 changed files with 1345 additions and 1042 deletions

View File

@@ -1,4 +1,3 @@
set arm force-mode thumb
set arm fallback-mode thumb
target remote localhost:3333
monitor reset halt

View File

@@ -78,7 +78,7 @@ CSRC = $(PORTSRC) \
$(STMUSBSRC) \
$(USBCDCSRC) \
$(RSASRC) \
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb-icc.c gpg.c
main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb-icc.c gpg.c ac.c gpg-do.c
# List ASM source files here
ASMSRC = $(PORTASM) \

69
src/ac.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* ac.c -- Check access condition
*/
#include "ch.h"
#include "gnuk.h"
static uint8_t auth_status = AC_NONE_AUTHORIZED;
int
ac_check_status (uint8_t ac_flag)
{
if (ac_flag == AC_ALWAYS)
return 1;
else if (ac_flag == AC_NEVER)
return 0;
else
return (ac_flag & auth_status)? 1 : 0;
}
/*
* XXX: should be implemented
*
* string --S2K(SHA1,SALT,ITERATE)--> key
* load params from flash with key (key,enc_params --decrypt--> params)
* check magic in params
*/
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
auth_status |= AC_PSO_CDS_AUTHORIZED;
return 0;
}
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;
}
int
verify_pso_admin (uint8_t *pw, int pw_len)
{
#if 0
compute_hash;
if (cmp_hash (pw3_hash, hash) == 0)
good;
else
return -1;
#endif
auth_status |= AC_ADMIN_AUTHORIZED;
return 0;
}

View File

@@ -1,12 +1,14 @@
extern Thread *blinker_thread;
extern void put_byte (uint8_t b);
extern void put_short (uint16_t x);
extern void put_string (const char *s);
extern void _write (const char *, int);
extern size_t strlen(const char *s);
extern void *memcpy(void *dest, const void *src, size_t n);
extern void *memset(void *s, int c, size_t n);
/*
* Interface between ICC<-->GPG
@@ -18,9 +20,32 @@ extern Thread *gpg_thread;
#define EV_EXEC_FINISHED (eventmask_t)2 /* GPG Execution finished */
#define MAX_CMD_APDU_SIZE (256) /* XXX: Check OpenPGPcard protocol */
/* maximum cmd apdu data is key import 22+4+128+128 (head, e, p, q)*/
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */
#define MAX_RES_APDU_SIZE (256+2) /* Data + status */
extern uint8_t cmd_APDU[MAX_CMD_APDU_SIZE];
extern uint8_t res_APDU[MAX_RES_APDU_SIZE];
extern int cmd_APDU_size;
extern int res_APDU_size;
#define AC_NONE_AUTHORIZED 0x00
#define AC_PSO_CDS_AUTHORIZED 0x01 /* PW1 with 0x81 verified */
#define AC_PSO_OTHER_AUTHORIZED 0x02 /* PW1 with 0x82 verified */
#define AC_ADMIN_AUTHORIZED 0x04 /* PW3 verified */
#define AC_NEVER 0x80
#define AC_ALWAYS 0xFF
extern int ac_check_status (uint8_t ac_flag);
extern int verify_pso_cds (uint8_t *pw, int pw_len);
extern int verify_pso_other (uint8_t *pw, int pw_len);
extern int verify_pso_admin (uint8_t *pw, int pw_len);
extern void write_res_apdu (const uint8_t *p, int len,
uint8_t sw1, uint8_t sw2);
#define DEBUG 1
extern int gpg_do_table_init (void);
extern void gpg_do_get_data (uint16_t tag);
extern void gpg_do_put_data (uint16_t tag, uint8_t *data, int len);

View File

@@ -1,172 +1,79 @@
const char const select_file_TOP_result[] __attribute__ ((aligned (1))) =
{ 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44,
0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };
#include "ch.h"
#include "gnuk.h"
const char const get_data_64_result[] __attribute__ ((aligned (1))) =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const char const select_file_TOP_result[] __attribute__ ((aligned (1))) = {
0x00, 0x00, /* unused */
0x0b, 0x10, /* number of bytes in this directory */
0x3f, 0x00, /* field of selected file: MF, 3f00 */
0x38, /* it's DF */
0xff, /* unused */
0xff, 0x44, 0x44, /* access conditions */
0x01, /* status of the selected file (OK, unblocked) */
0x05, /* number of bytes of data follow */
0x03, /* Features: unused */
0x01, /* number of subdirectories (OpenPGP) */
0x01, /* number of elementary files (SerialNo) */
0x00, /* number of secret codes */
0x00, /* Unused */
0x00, 0x00 /* PIN status: OK, PIN blocked?: No */
};
const char const get_data_5e_result[] __attribute__ ((aligned (1))) =
{ /* Login Data */
'g', 'n', 'i', 'i', 'b', 'e'
};
const char const do_5e[] __attribute__ ((aligned (1))) = {
6,
'g', 'n', 'i', 'i', 'b', 'e'
};
/***** do_6e is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/
const char const do_6e_head[] __attribute__ ((aligned (1))) =
{
0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */
};
const char const do_c4[] __attribute__ ((aligned (1))) = {
7,
1, 127, 127, 127, 3, 0, 3
};
const char const do_47[] __attribute__ ((aligned (1))) = /* Card Capabilities */
{
0x47, 3,
0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/
/* XXX: See ISO 7816-4 for first byte and second byte */
};
const char const do_c7[] __attribute__ ((aligned (1))) = {
20,
/* sign */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
};
const char const do_4f[] __attribute__ ((aligned (1))) = /* AID */
{
0x4f, 16,
0xD2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x01, 0x01, /* Version 1.1 */
0xF5, 0x17, /* Manufacturer (FSIJ) */
0x00, 0x00, 0x00, 0x02, /* Serial */
0x00, 0x00
};
const char const do_ca[] __attribute__ ((aligned (1))) = {
20,
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
};
const char const do_c0[] __attribute__ ((aligned (1))) =
{ /* Extended capability */
0xc0, 1,
0x00
};
const char const do_ce[] __attribute__ ((aligned (1))) = {
4,
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
};
const char const do_c1[] __attribute__ ((aligned (1))) =
{ /* Algorithm Attributes Signature ??? */
0xc1, 1,
0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */
};
const char const do_5b[] __attribute__ ((aligned (1))) = {
12,
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
};
const char const do_c2[] __attribute__ ((aligned (1))) =
{ /* Algorithm Attributes Decryption ??? */
0xc2, 1,
0x00
};
const char const do_5f2d[] __attribute__ ((aligned (1))) = {
2,
'j', 'a'
};
const char const do_c3[] __attribute__ ((aligned (1))) =
{ /* Algorithm Attributes Authentication ??? */
0xc3, 1,
0x00
};
const char const do_c4[] __attribute__ ((aligned (1))) =
{ /* CHV status bytes */
0xc4, 7,
0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01
};
const char const do_c5[] __attribute__ ((aligned (1))) =
{
0xc5, 60,
/* sign */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* enc */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* auth */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_c6[] __attribute__ ((aligned (1))) = /* CA Fingerprints */
{
0xc6, 60,
/* c6 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
/* c7 */
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
0xe5, 0x02, 0xbf, 0xcd,
/* c8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
const char const do_cd[] __attribute__ ((aligned (1))) =
{ /* Generation time */
0xcd, 12,
0x00, 0x00, 0x00, 0x00,
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
0x00, 0x00, 0x00, 0x00,
};
/*************************/
/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/
const char const do_65_head[] __attribute__ ((aligned (1))) =
{
0x65, 2*1+3*2+12+2+1
};
const char const do_5b[] __attribute__ ((aligned (1))) =
{
0x5b, 12,
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
};
const char const do_5f2d[] __attribute__ ((aligned (1))) =
{
0x5f, 0x2d, 2,
'j', 'a'
};
const char const do_5f35[] __attribute__ ((aligned (1))) =
{
0x5f, 0x35, 1,
'1'
};
/****************************/
/* do_7a is compound object of { do_93 } */
const char const do_7a_head[] __attribute__ ((aligned (1))) =
{
0x7a, 2+3
};
const char const do_5f35[] __attribute__ ((aligned (1))) = {
1,
'1'
};
/* Digital Signature Counter (3-bytes) */
const char const do_93[] __attribute__ ((aligned (1))) =
{
0x93, 3,
0, 0, 0
};
/****************************/
const char const do_93[] __attribute__ ((aligned (1))) = {
3,
0, 0, 0
};
const char const do_5f50[] __attribute__ ((aligned (1))) =
{
0x5f, 0x50, 20,
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
};
/* Historycal bytes */
const char const do_5f52[] __attribute__ ((aligned (1))) =
{
0x5f, 0x52, 10,
0x00,
0x31, 0xc0, /* full DF name, partial DF name supported */
0x73,
0xc0, 0x01, 0x00, /* full DF name, partial DF name supported */
/* 1-byte */
/* no command chaining, no ext lc_le */
0x00, 0x90, 0x00 /* Status info */
};
const char const do_5f50[] __attribute__ ((aligned (1))) = {
20,
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
'.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/'
};
const char const get_data_rb_result[] __attribute__ ((aligned (1))) = {
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04

File diff suppressed because it is too large Load Diff

729
src/gpg-do.c Normal file
View File

@@ -0,0 +1,729 @@
/*
* gpg-do.c -- OpenPGP card Data Objects (DO) handling
*
* 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 "ch.h"
#include "gnuk.h"
/*
* Compile time vars:
* AID, Historical Bytes (template), Extended Capabilities,
* and Algorithm Attributes
*/
/* AID */
static const uint8_t const aid[] __attribute__ ((aligned (1))) = {
16,
0xd2, 0x76, 0x00, 0x01, 0x24, 0x01,
0x02, 0x00, /* Version 2.0 */
0xf5, 0x17, /* Manufacturer (FSIJ) */
0x00, 0x00, 0x00, 0x01, /* Serial */
0x00, 0x00
};
/* Historical Bytes (template) */
static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = {
10,
0x00,
0x31, 0x80, /* Full DF name */
0x73,
0x80, 0x01, 0x40, /* Full DF name */
/* 1-byte */
/* No command chaining */
/* Extended Lc and Le */
0x00, 0x90, 0x00 /* Status info (no life cycle management) */
};
/* Extended Capabilities */
static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1))) = {
10,
0x30, /*
* No SM, No get challenge,
* Key import supported,
* PW status byte can be put,
* No private_use_DO,
* No algo change allowed
*/
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 0x00, /* Max get challenge */
0x00, 0x00, /* max. length of cardholder certificate */
(MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff), /* Max. length of command data */
(MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff), /* Max. length of response data */
};
/* Algorithm Attributes */
static const uint8_t const algorithm_attr[] __attribute__ ((aligned (1))) = {
6,
0x01, /* RSA */
0x08, 0x00, /* Length modulus (in bit): 2048 */
0x00, 0x20, /* Length exponent (in bit): 32 */
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
};
#define SIZE_PW_STATUS_BYTES 7
#if 0
{
1, /* PW1 valid for several PSO:CDS commands */
127, 127, 127, /* max length of PW1, RC, and PW3 */
3, 0, 3 /* Error counter of PW1, RC, and PW3 */
};
#endif
#define SIZE_DIGITAL_SIGNATURE_COUNTER 3
#if 0
{
0, 0, 0 /* 3-byte binary */
};
#endif
#define SIZE_FINGER_PRINT 20
#define SIZE_KEYGEN_TIME 4 /* RFC4880 */
/* Runtime vars: PSO */
struct key_store {
uint8_t p[128];
uint8_t q[128];
};
static struct key_store key_sig, key_dec, key_aut;
#define HASH_SIZE 20
static uint8_t pw3_hash[HASH_SIZE];
enum do_type {
DO_FIXED,
DO_VAR,
DO_CN_READ,
DO_PROC_READ,
DO_PROC_WRITE,
DO_HASH,
DO_KEYPTR
};
struct do_table_entry {
uint16_t tag;
enum do_type do_type;
uint8_t ac_read;
uint8_t ac_write;
const void *obj;
};
static uint8_t *res_p;
static int with_tag;
static void copy_do_1 (uint16_t tag, const uint8_t *do_data);
static struct do_table_entry *get_do_entry (uint16_t tag);
#define GNUK_DO_KEYPTR_SIG 0xff01
#define GNUK_DO_KEYPTR_DEC 0xff02
#define GNUK_DO_KEYPTR_AUT 0xff03
#define GNUK_DO_HASH_PW3 0xff04
#define GPG_DO_AID 0x004f
#define GPG_DO_NAME 0x005b
#define GPG_DO_LOGIN_DATA 0x005e
#define GPG_DO_CH_DATA 0x0065
#define GPG_DO_APP_DATA 0x006e
/* XXX: 0x0073 ??? */
#define GPG_DO_SS_TEMP 0x007a
#define GPG_DO_DS_COUNT 0x0093
#define GPG_DO_EXTCAP 0x00c0
#define GPG_DO_ALG_SIG 0x00c1
#define GPG_DO_ALG_DEC 0x00c2
#define GPG_DO_ALG_AUT 0x00c3
#define GPG_DO_PW_STATUS 0x00c4
#define GPG_DO_FP_ALL 0x00c5
#define GPG_DO_CAFP_ALL 0x00c6
#define GPG_DO_FP_SIG 0x00c7
#define GPG_DO_FP_DEC 0x00c8
#define GPG_DO_FP_AUT 0x00c9
#define GPG_DO_CAFP_1 0x00ca
#define GPG_DO_CAFP_2 0x00cb
#define GPG_DO_CAFP_3 0x00cc
#define GPG_DO_KGTIME_ALL 0x00cd
#define GPG_DO_KGTIME_SIG 0x00ce
#define GPG_DO_KGTIME_DEC 0x00cf
#define GPG_DO_KGTIME_AUT 0x00d0
#define GPG_DO_RESETTING_CODE 0x00d3
#define GPG_DO_KEY_IMPORT 0x3fff
#define GPG_DO_LANGUAGE 0x5f2d
#define GPG_DO_SEX 0x5f35
#define GPG_DO_URL 0x5f50
#define GPG_DO_HIST_BYTES 0x5f52
#define GPG_DO_CH_CERTIFICATE 0x7f21
static void
copy_tag (uint16_t tag)
{
if (tag < 0x0100)
*res_p++ = (tag & 0xff);
else
{
*res_p++ = (tag >> 8);
*res_p++ = (tag & 0xff);
}
}
static void
do_hist_bytes (uint16_t tag)
{
/* XXX: For now, no life cycle management, just return template as is. */
/* XXX: Supporing TERMINATE DF / ACTIVATE FILE, we need to fix here */
copy_do_1 (tag, historical_bytes);
}
#define SIZE_FP 20
#define SIZE_KGTIME 4
static void
do_fp_all (uint16_t tag)
{
struct do_table_entry *do_p;
const uint8_t *do_data;
if (with_tag)
{
copy_tag (tag);
*res_p++ = SIZE_FP*3;
}
do_p = get_do_entry (GPG_DO_FP_SIG);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
do_p = get_do_entry (GPG_DO_FP_DEC);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
do_p = get_do_entry (GPG_DO_FP_AUT);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
}
static void
do_cafp_all (uint16_t tag)
{
struct do_table_entry *do_p;
const uint8_t *do_data;
if (with_tag)
{
copy_tag (tag);
*res_p++ = SIZE_FP*3;
}
do_p = get_do_entry (GPG_DO_CAFP_1);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
do_p = get_do_entry (GPG_DO_CAFP_2);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
do_p = get_do_entry (GPG_DO_CAFP_3);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_FP);
else
memset (res_p, 0, SIZE_FP);
res_p += SIZE_FP;
}
static void
do_kgtime_all (uint16_t tag)
{
struct do_table_entry *do_p;
const uint8_t *do_data;
if (with_tag)
{
copy_tag (tag);
*res_p++ = SIZE_KGTIME*3;
}
do_p = get_do_entry (GPG_DO_KGTIME_SIG);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_KGTIME);
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
do_p = get_do_entry (GPG_DO_KGTIME_DEC);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_KGTIME);
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
do_p = get_do_entry (GPG_DO_KGTIME_AUT);
do_data = (const uint8_t *)do_p->obj;
if (do_data)
memcpy (res_p, &do_data[1], SIZE_KGTIME);
else
memset (res_p, 0, SIZE_KGTIME);
res_p += SIZE_KGTIME;
}
static void
put_hex (uint8_t nibble)
{
uint8_t c;
if (nibble < 0x0a)
c = '0' + nibble;
else
c = 'a' + nibble - 0x0a;
_write (&c, 1);
}
static void
o_put_byte (uint8_t b)
{
_write (" ", 1);
put_hex (b >> 4);
put_hex (b &0x0f);
}
/*
* 4d, xx, xx: Extended Header List
* b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT)
* 7f48, xx: cardholder private key template
* 91 xx
* 92 xx
* 93 xx
* 5f48, xx: cardholder privatge key
*/
static void
proc_key_import (uint16_t tag, uint8_t *data, int len)
{
int i;
for (i = 0; i < len; i++)
{
o_put_byte (data[i]);
if ((i & 0x0f) == 0x0f)
_write ("\r\n", 2);
}
_write ("\r\n", 2);
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
}
static const uint16_t const cn_ch_data[] = {
3,
GPG_DO_NAME,
GPG_DO_LANGUAGE,
GPG_DO_SEX,
};
static const uint16_t const cn_app_data[] = {
10,
GPG_DO_AID,
GPG_DO_HIST_BYTES,
/* XXX Discretionary data objects 0x0073 ??? */
GPG_DO_EXTCAP,
GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT,
GPG_DO_PW_STATUS,
GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL
};
static const uint16_t const cn_ss_temp[] = { 1, GPG_DO_DS_COUNT };
static struct do_table_entry
gpg_do_table[] = {
/* Pseudo DO (private): not user accessible */
{ GNUK_DO_KEYPTR_SIG, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
{ 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 */
{ 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 },
/* Fixed data */
{ GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid },
{ GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities },
{ GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
{ GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
{ GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr },
/* 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 },
{ GPG_DO_FP_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_CAFP_1, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_CAFP_2, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_CAFP_3, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_KGTIME_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_KGTIME_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_KGTIME_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
/* Variables: Variable size */
{ GPG_DO_LOGIN_DATA, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ GPG_DO_URL, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL },
{ 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 },
/* Compound data: Write access only*/
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
proc_key_import },
};
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
extern const uint8_t const do_5e[];
extern const uint8_t const do_c4[];
extern const uint8_t const do_c7[];
extern const uint8_t const do_ca[];
extern const uint8_t const do_ce[];
extern const uint8_t const do_5b[];
extern const uint8_t const do_5f2d[];
extern const uint8_t const do_5f35[];
extern const uint8_t const do_93[];
extern const uint8_t const do_5f50[];
/*
* Initialize GPG_DO_TABLE reading from Flash ROM
*/
int
gpg_do_table_init (void)
{
struct do_table_entry *do_p;
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->obj = do_c4;
#if 0
do_p = get_do_entry (GPG_DO_FP_SIG);
do_p->obj = do_c7;
do_p = get_do_entry (GPG_DO_CAFP_1);
do_p->obj = do_ca;
do_p = get_do_entry (GPG_DO_KGTIME_SIG);
do_p->obj = do_ce;
#endif
do_p = get_do_entry (GPG_DO_NAME);
do_p->obj = do_5b;
do_p = get_do_entry (GPG_DO_LANGUAGE);
do_p->obj = do_5f2d;
do_p = get_do_entry (GPG_DO_SEX);
do_p->obj = do_5f35;
do_p = get_do_entry (GPG_DO_DS_COUNT);
do_p->obj = do_93;
do_p = get_do_entry (GPG_DO_URL);
do_p->obj = do_5f50;
return 0;
}
static struct do_table_entry *
get_do_entry (uint16_t tag)
{
int i;
for (i = 0; i < NUM_DO_ENTRIES; i++)
if (gpg_do_table[i].tag == tag)
return &gpg_do_table[i];
return NULL;
}
static void
copy_do_1 (uint16_t tag, const uint8_t *do_data)
{
int len;
if (with_tag)
{
copy_tag (tag);
if (do_data[0] < 127)
len = do_data[0] + 1;
else if (do_data[1] == 0x81)
len = do_data[1] + 2;
else /* 0x82 */
len = ((do_data[1] << 8) | do_data[2]) + 3;
}
else
{
if (do_data[0] < 127)
{
len = do_data[0];
do_data++;
}
else if (do_data[1] == 0x81)
{
len = do_data[1];
do_data += 2;
}
else /* 0x82 */
{
len = ((do_data[1] << 8) | do_data[2]);
do_data += 3;
}
}
memcpy (res_p, do_data, len);
res_p += len;
}
static int
copy_do (struct do_table_entry *do_p)
{
if (do_p == NULL)
return 0;
if (ac_check_status (do_p->ac_read) == 0)
return -1;
switch (do_p->do_type)
{
case DO_FIXED:
case DO_VAR:
{
const uint8_t *do_data = (const uint8_t *)do_p->obj;
if (do_data == NULL)
return 0;
else
copy_do_1 (do_p->tag, do_data);
break;
}
case DO_CN_READ:
{
int i;
const uint16_t *cn_data = (const uint16_t *)do_p->obj;
int num_components = cn_data[0];
uint8_t *len_p;
copy_tag (do_p->tag);
*res_p++ = 0x81;
len_p = res_p;
*res_p++ = 0; /* for now */
with_tag = 1;
for (i = 0; i < num_components; i++)
{
uint16_t tag0;
struct do_table_entry *do0_p;
tag0 = cn_data[i+1];
do0_p = get_do_entry (tag0);
if (copy_do (do0_p) < 0)
return -1;
}
*len_p = (res_p - len_p);
break;
}
case DO_PROC_READ:
{
void (*do_func)(uint16_t) = (void (*)(uint16_t))do_p->obj;
do_func (do_p->tag);
break;
}
case DO_PROC_WRITE:
case DO_HASH:
case DO_KEYPTR:
return -1;
}
return 1;
}
/*
* Process GET_DATA request on Data Object specified by TAG
* Call write_res_adpu to fill data returned
*/
void
gpg_do_get_data (uint16_t tag)
{
struct do_table_entry *do_p = get_do_entry (tag);
res_p = res_APDU;
with_tag = 0;
#ifdef DEBUG
put_string (" ");
put_short (tag);
#endif
if (do_p)
{
if (copy_do (do_p) < 0)
/* Overwrite partially written result */
write_res_apdu (NULL, 0, 0x69, 0x82);
else
{
*res_p++ = 0x90;
*res_p++ = 0x00;
res_APDU_size = res_p - res_APDU;
}
}
else
/* No record */
write_res_apdu (NULL, 0, 0x6a, 0x88);
}
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)
return NULL;
*last_p++ = (tag >> 8);
*last_p++ = (tag & 0xff);
if (len < 128)
*last_p++ = len;
else if (len < 256)
{
*last_p++ = 0x81;
*last_p++ = len;
}
else
{
*last_p++ = 0x82;
*last_p++ = (len >> 8);
*last_p++ = (len & 0xff);
}
memcpy (last_p, data, len);
last_p += len;
return p + 2;
}
void
gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
{
struct do_table_entry *do_p = get_do_entry (tag);
#ifdef DEBUG
put_string (" ");
put_short (tag);
#endif
if (do_p)
{
if (ac_check_status (do_p->ac_write) == 0)
{
write_res_apdu (NULL, 0, 0x69, 0x82);
return;
}
switch (do_p->do_type)
{
case DO_FIXED:
case DO_CN_READ:
case DO_PROC_READ:
case DO_HASH:
case DO_KEYPTR:
write_res_apdu (NULL, 0, 0x69, 0x82);
break;
case DO_VAR:
{
#if 0
const uint8_t *do_data = (const uint8_t *)do_p->obj;
flash_do_release (do_data);
#endif
if (tag == GPG_DO_PW_STATUS)
{
/* XXX: only the first byte can be changed */
}
else
{
if (len == 0)
/* make DO empty */
do_p->obj = NULL;
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 */
}
}
/*
*
*/
if (tag == GPG_DO_RESETTING_CODE)
{
/* XXX: Changing Resetting code,
* we need to reset RC counter in GPG_DO_PW_STATUS */
}
break;
}
case DO_PROC_WRITE:
{
void (*proc_func)(uint16_t, uint8_t *, int)
= (void (*)(uint16_t, uint8_t *, int))do_p->obj;
proc_func (tag, data, len);
break;
}
}
}
else
/* No record */
write_res_apdu (NULL, 0, 0x6a, 0x88);
}

363
src/gpg.c
View File

@@ -46,6 +46,16 @@ put_byte (uint8_t b)
_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)
{
@@ -53,10 +63,11 @@ put_string (const char *s)
}
#define RSA_SIGNATURE_LENGTH 128 /* 256 byte == 2048-bit */
#define RSA_SIGNATURE_LENGTH 128 /* 256 *//* 256 byte == 2048-bit */
extern unsigned char *rsa_sign (unsigned char *);
#define INS_PUT_DATA 0xDA
#define INS_PUT_DATA_ODD 0xDB /* For key import */
#define INS_VERIFY 0x20
#define INS_GET_DATA 0xCA
#define INS_GET_RESPONSE 0xC0
@@ -66,50 +77,12 @@ extern unsigned char *rsa_sign (unsigned char *);
#define INS_PSO 0x2A
extern const char const select_file_TOP_result[20];
extern const char const get_data_64_result[7];
extern const char const get_data_5e_result[6];
extern const char const do_6e_head[3];
extern const char const do_47[2+3];
extern const char const do_4f[2+16];
extern const char const do_c0[2+1];
extern const char const do_c1[2+1];
extern const char const do_c2[2+1];
extern const char const do_c3[2+1];
extern const char const do_c4[2+7];
extern const char const do_c5[2+60];
extern const char const do_c6[2+60];
extern const char const do_cd[2+12];
extern const char const do_65_head[2];
extern const char const do_5b[2+12];
extern const char const do_5f2d[3+2];
extern const char const do_5f35[3+1];
extern const char const do_7a_head[2];
extern const char const do_93[2+3];
extern const char const do_5f50[3+20];
extern const char const do_5f52[3+10];
extern const char const get_data_rb_result[6];
extern const char const get_data_sigkey_result[7+128];
extern const char const get_data_enckey_result[7+128];
/*
* 73
* 101
* 102
* 103
* 104
*
* 65 - 5b, 5f2d, 5f35
* 6e - 47, 4f, c0, c1, c2, c3, c4, c5, c6, cd
* 7a - 93
*
*
* 65 L-65 [5b L-5b .... ] [5f2d 2 'j' 'a'] [5f35 1 '1']
* 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ...
* 7a L-7a [93 L-93 ... ]
*/
static void
void
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
{
res_APDU_size = 2 + len;
@@ -119,25 +92,62 @@ write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
res_APDU[len+1] = sw2;
}
static int
#define FILE_NONE -1
#define FILE_DF_OPENPGP 0
#define FILE_MF 1
#define FILE_EF_DIR 2
#define FILE_EF_SERIAL 3
static int file_selection = FILE_NONE;
static void
process_command_apdu (void)
{
/*
INS_VERIFY
uint16_t tag;
uint8_t *data;
int len;
00 20 00 81 06 - ???
CHV1
00 20 00 82 06 - ???
CHV2
00 20 00 83 08 - ???
CHV3
*/
if (cmd_APDU[1] == INS_VERIFY)
{
uint8_t p2 = cmd_APDU[3];
int r;
if (cmd_APDU[1] == INS_PUT_DATA)
put_string (" - VERIFY\r\n");
len = cmd_APDU[4];
if (p2 == 0x81)
r = verify_pso_cds (&cmd_APDU[5], len);
else if (p2 == 0x82)
r = verify_pso_other (&cmd_APDU[5], len);
else
r = verify_pso_admin (&cmd_APDU[5], len);
if (r < 0)
write_res_apdu (NULL, 0, 0x69, 0x82);
else
write_res_apdu (NULL, 0, 0x90, 0x00);
return;
}
if (cmd_APDU[1] == INS_PUT_DATA || cmd_APDU[1] == INS_PUT_DATA_ODD)
{
put_string (" - PUT DATA\r\n");
write_res_apdu (NULL, 0, 0x90, 0x00); /* 0x6a, 0x88: No record */
return 0;
if (file_selection != FILE_DF_OPENPGP)
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
len = cmd_APDU_size - 5;
data = &cmd_APDU[5];
if (len >= 256)
/* extended Lc */
{
data += 2;
len -= 2;
}
gpg_do_put_data (tag, data, len);
return;
}
if (cmd_APDU[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
@@ -183,218 +193,82 @@ INS_VERIFY
}
}
else if (cmd_APDU[1] == INS_READ_BINARY)
{ /* it must be for DF 0x2f02 */
{
put_string (" - Read binary\r\n");
if (cmd_APDU[3] >= 6)
if (file_selection == FILE_EF_SERIAL)
{
write_res_apdu (NULL, 0, 0x6b, 0x00); /* BAD_P0_P1 */
if (cmd_APDU[3] >= 6)
write_res_apdu (NULL, 0, 0x6b, 0x00); /* BAD_P0_P1 */
else
/* Tag 5a, serial number */
write_res_apdu (get_data_rb_result,
sizeof (get_data_rb_result), 0x90, 0x00);
}
else
{ /* Tag 5a, serial number */
write_res_apdu (get_data_rb_result,
sizeof (get_data_rb_result), 0x90, 0x00);
}
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
}
else if (cmd_APDU[1] == INS_SELECT_FILE)
{
if (cmd_APDU[2] == 4) /* Selection by DF name */
{
put_string (" - select DF by name\r\n");
/*
* XXX: Should return contents.
* P2 == 0, LC=6, name = D2 76 00 01 24 01
*/
if (1)
{
write_res_apdu (NULL, 0, 0x90, 0x00);
}
file_selection = FILE_DF_OPENPGP;
/* XXX: Should return contents??? */
write_res_apdu (NULL, 0, 0x90, 0x00);
}
else if (cmd_APDU[4] == 2
&& cmd_APDU[5] == 0x2f
&& cmd_APDU[6] == 02)
&& cmd_APDU[6] == 0x02)
{
put_string (" - select 0x2f02 EF\r\n");
/*
* MF.EF-GDO -- Serial number of the card and name of the owner
*/
write_res_apdu (NULL, 0, 0x90, 0x00);
file_selection = FILE_EF_SERIAL;
}
else if (cmd_APDU[4] == 2
&& cmd_APDU[5] == 0x3f
&& cmd_APDU[6] == 0x00)
{
put_string (" - select ROOT MF\r\n");
if (cmd_APDU[3] == 0x0c)
{
write_res_apdu (NULL, 0, 0x90, 0x00);
}
else
{
write_res_apdu (select_file_TOP_result,
sizeof (select_file_TOP_result), 0x90, 0x00);
}
file_selection = FILE_MF;
}
else
if (cmd_APDU[4] == 2
&& cmd_APDU[5] == 0x3f
&& cmd_APDU[6] == 0)
{
put_string (" - select ROOT MF\r\n");
if (cmd_APDU[3] == 0x0c)
{
write_res_apdu (NULL, 0, 0x90, 0x00);
}
else
{
write_res_apdu (select_file_TOP_result,
sizeof (select_file_TOP_result), 0x90, 0x00);
}
}
else
{
put_string (" - select ?? \r\n");
{
put_string (" - select ?? \r\n");
write_res_apdu (NULL, 0, 0x6a, 0x82); /* File missing */
}
write_res_apdu (NULL, 0, 0x6a, 0x82); /* File missing */
file_selection = FILE_NONE;
}
}
else if (cmd_APDU[1] == INS_GET_DATA)
{
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
put_string (" - Get Data\r\n");
switch (((cmd_APDU[2]<<8) | cmd_APDU[3]))
{
case 0x4f: /* AID */
{
put_string (" AID\r\n");
write_res_apdu (&do_4f[2],
sizeof (do_4f) - 2, 0x90, 0x00);
break;
}
case 0x5e: /* Login data */
{
put_string (" Login data\r\n");
write_res_apdu (get_data_5e_result,
sizeof (get_data_5e_result), 0x90, 0x00);
break;
}
case 0x64:
{
put_string (" 64\r\n");
write_res_apdu (get_data_64_result,
sizeof (get_data_64_result), 0x90, 0x00);
break;
}
case 0xc0:
{
put_string (" c0\r\n");
write_res_apdu (&do_c0[2],
sizeof (do_c0) - 2, 0x90, 0x00);
break;
}
case 0xc1:
{
put_string (" c1\r\n");
write_res_apdu (&do_c1[2],
sizeof (do_c1) - 2, 0x90, 0x00);
break;
}
case 0xc2:
{
put_string (" c2\r\n");
write_res_apdu (&do_c2[2],
sizeof (do_c2) - 2, 0x90, 0x00);
break;
}
case 0xc3:
{
put_string (" c3\r\n");
write_res_apdu (&do_c3[2],
sizeof (do_c3) - 2, 0x90, 0x00);
break;
}
case 0xc4:
{
put_string (" c4\r\n");
write_res_apdu (&do_c4[2],
sizeof (do_c4) - 2, 0x90, 0x00);
break;
}
case 0x5b: /* Name */
{
put_string (" 5b\r\n");
write_res_apdu (&do_5b[2],
sizeof (do_5b) - 2, 0x90, 0x00);
break;
}
case 0x93: /* Digital Signature Counter (3-bytes) */
{
put_string (" 93\r\n");
write_res_apdu (&do_93[2],
sizeof (do_93) - 2, 0x90, 0x00);
break;
}
case 0xc5: /* Fingerprints */
{
put_string (" c5\r\n");
write_res_apdu (&do_c5[2],
sizeof (do_c5) - 2, 0x90, 0x00);
break;
}
case 0x5f2d: /* Language preference */
{
put_string (" 5f2d\r\n");
write_res_apdu (&do_5f2d[3],
sizeof (do_5f2d) - 3, 0x90, 0x00);
break;
}
case 0x5f35: /* Sex */
{
put_string (" 5f35\r\n");
write_res_apdu (&do_5f35[3],
sizeof (do_5f35) - 3, 0x90, 0x00);
break;
}
case 0x5f50: /* URL */
{
put_string (" 5f50\r\n");
write_res_apdu (&do_5f50[3],
sizeof (do_5f50) - 3, 0x90, 0x00);
break;
}
case 0x5f52: /* Historycal bytes */
{
put_string (" 5f52\r\n");
write_res_apdu (&do_5f52[3],
sizeof (do_5f52) - 3, 0x90, 0x00);
break;
}
case 0x65: /* Card Holder Related Data (Tag) */
{
put_string (" 65\r\n");
write_res_apdu (do_65_head,
do_65_head[1] + 2, 0x90, 0x00);
break;
}
case 0x6e: /* Application Related Data (Tag) */
{
put_string (" 6e\r\n");
write_res_apdu (do_6e_head,
do_6e_head[2] + 3, 0x90, 0x00);
break;
}
case 0x7a: /* Security Support Template (Tag) */
{
put_string (" 7a\r\n");
write_res_apdu (do_7a_head,
do_7a_head[1] + 2, 0x90, 0x00);
break;
}
case 0xc6: /* List of CA fingerprints */
{
put_string (" c6\r\n");
write_res_apdu (&do_c6[2],
sizeof (do_c6) - 2, 0x90, 0x00);
break;
}
case 0xcd: /* List of generation dates/times public-key pairs */
{
put_string (" cd\r\n");
write_res_apdu (&do_cd[2],
sizeof (do_cd) - 2, 0x90, 0x00);
break;
}
default:
put_string (" ?");
put_byte (((cmd_APDU[2]<<8) | cmd_APDU[3]));
write_res_apdu (NULL, 0, 0x90, 0x00);
break;
}
if (file_selection != FILE_DF_OPENPGP)
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
gpg_do_get_data (tag);
}
else if (cmd_APDU[1] == INS_PSO)
{
@@ -402,11 +276,14 @@ INS_VERIFY
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
{
if (cmd_APDU_size != 5 + 35 && cmd_APDU_size != 5 + 35 + 1)
put_string (" wrong length\r\n");
if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
{
put_string (" wrong length: ");
put_short (cmd_APDU_size);
}
else
{
unsigned char * r = rsa_sign (&cmd_APDU[5]);
unsigned char * r = rsa_sign (&cmd_APDU[7]);
write_res_apdu (r, RSA_SIGNATURE_LENGTH, 0x90, 0x00);
}
@@ -414,17 +291,19 @@ INS_VERIFY
}
else
{
put_string (" - ???\r\n");
put_string (" - ??");
put_byte (cmd_APDU[2]);
put_string (" - ??");
put_byte (cmd_APDU[3]);
write_res_apdu (NULL, 0, 0x90, 0x00);
}
}
else
{
put_string (" - ???\r\n");
write_res_apdu (NULL, 0, 0x90, 0x00);
put_string (" - ??");
put_byte (cmd_APDU[1]);
write_res_apdu (NULL, 0, 0x6D, 0x00); /* INS not supported. */
}
return 0;
}
Thread *gpg_thread;

View File

@@ -28,6 +28,8 @@
#include "hal.h"
#include "usb_lld.h"
#include "gnuk.h"
#include "usb_lib.h"
#include "usb_istr.h"
#include "usb_desc.h"
@@ -73,11 +75,11 @@ stdout_init (void)
stdout.str = NULL;
}
int
void
_write (const char *s, int size)
{
if (size == 0)
return 0;
return;
chMtxLock (&stdout.m);
while (stdout.str)
@@ -87,7 +89,6 @@ _write (const char *s, int size)
chCondSignal (&stdout.start_cnd);
chCondWait (&stdout.finish_cnd);
chMtxUnlock ();
return 0;
}
extern uint32_t count_in;
@@ -180,6 +181,8 @@ int main(int argc, char **argv)
(void)argc;
(void)argv;
gpg_do_table_init ();
usb_lld_init ();
USB_Init();

View File

@@ -69,6 +69,9 @@ rsa_sign (unsigned char *raw_message)
{
rsa_context ctx;
mpi P1, Q1, H;
int len;
len = (cmd_APDU[5]<<8) | cmd_APDU[6]; /* cmd_APDU_size - 6 */
mpi_init( &P1, &Q1, &H, NULL );
rsa_init( &ctx, RSA_PKCS_V15, 0, NULL, NULL );
@@ -104,10 +107,11 @@ rsa_sign (unsigned char *raw_message)
}
#if 0
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_SHA256, 0, raw_message, output);
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output);
put_string ("done.\r\n");
return output;
#else
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, 35, raw_message, output );
rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output );
put_string ("done.\r\n");
return output;
#endif

View File

@@ -130,12 +130,16 @@ EP5_OUT_Callback (void)
icc_data_size = len - ICC_MSG_HEADER_SIZE;
icc_seq = icc_header->seq;
if (icc_data_size < 0 || icc_data_size != icc_header->data_len)
if (icc_data_size < 0)
/* just ignore short invalid packet, enable Rx again */
SetEPRxValid (ENDP5);
else
/* Notify icc_thread */
chEvtSignalI (icc_thread, EV_RX_DATA_READY);
/*
* what if (icc_data_size != icc_header->data_len)???
*/
}
enum icc_state

View File

@@ -67,7 +67,7 @@ static const uint8_t gnukConfigDescriptor[] = {
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
0x40, 0x08, 0x04, 0x00, /* dwFeatures: Short and extended ADPU level */
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 261+10 XXX */
0x40, 0x00, 0, 0, /* dwMaxCCIDMessageLength: 64 */
0xff, /* bClassGetResponse: */
0xff, /* bClassEnvelope: */
0, 0, /* wLCDLayout: FIXED VALUE */
@@ -108,7 +108,7 @@ static const uint8_t gnukConfigDescriptor[] = {
5, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x03, /* bmCapabilities: D0+D1 */
0x02, /* bDataInterface: 2 */
/*ACM Functional Descriptor*/
4, /* bFunctionLength */