card holder certificate support
This commit is contained in:
19
ChangeLog
19
ChangeLog
@@ -1,7 +1,22 @@
|
|||||||
2011-01-27 NIIBE Yutaka <gniibe@fsij.org>
|
2011-01-27 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* src/openpgp-do.c (gpg_do_table): Exclude GPG_DO_CH_CERTIFICATE
|
* src/usb-icc.c (res_APDU_pointer): New.
|
||||||
for now.
|
(icc_handle_data, USBthread): Handle res_APDU_pointer.
|
||||||
|
|
||||||
|
* src/openpgp.h (GPG_COMMAND_NOT_ALLOWED): New.
|
||||||
|
|
||||||
|
* src/openpgp.c (INS_UPDATE_BINARY, FILE_EF_CH_CERTIFICATE)
|
||||||
|
(FILE_EF_RANDOM, cmd_update_binary): New.
|
||||||
|
(process_command_apdu): Initialize res_APDU_pointer.
|
||||||
|
|
||||||
|
* src/openpgp-do.c (gpg_do_get_data): Handle GPG_DO_CH_CERTIFICATE.
|
||||||
|
|
||||||
|
* src/gnuk.ld.in (.gnuk_ch_certificate): New.
|
||||||
|
|
||||||
|
* src/flash.c (flash_check_blank, flash_erase_binary)
|
||||||
|
(flash_write_binary): New.
|
||||||
|
|
||||||
|
* src/openpgp-do.c (gpg_do_table): Exclude GPG_DO_CH_CERTIFICATE.
|
||||||
|
|
||||||
* src/openpgp.c (cmd_reset_user_password): Add PINPAD_SUPPORT.
|
* src/openpgp.c (cmd_reset_user_password): Add PINPAD_SUPPORT.
|
||||||
|
|
||||||
|
|||||||
2
NEWS
2
NEWS
@@ -4,6 +4,8 @@ Gnuk NEWS - User visible changes
|
|||||||
|
|
||||||
Released 2011-01-XX, by NIIBE Yutaka
|
Released 2011-01-XX, by NIIBE Yutaka
|
||||||
|
|
||||||
|
** Card Holder Certificate is supported.
|
||||||
|
|
||||||
** Better interoperability to OpenSC.
|
** Better interoperability to OpenSC.
|
||||||
Gnuk is not yet supported by OpenSC, but it could be. With the
|
Gnuk is not yet supported by OpenSC, but it could be. With the
|
||||||
changes in Gnuk, it could be relatively easily possible to support
|
changes in Gnuk, it could be relatively easily possible to support
|
||||||
|
|||||||
78
src/flash.c
78
src/flash.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
|
* flash.c -- Data Objects (DO) and GPG Key handling on Flash ROM
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
* We assume single DO size is less than 256.
|
* We assume single DO size is less than 256.
|
||||||
*
|
*
|
||||||
* NOTE: When we will support "Card holder certificate" (which size is
|
* NOTE: When we will support "Card holder certificate" (which size is
|
||||||
* larger than 256), it will not be put into data pool, but will
|
* larger than 256), it is not put into data pool, but is
|
||||||
* be implemented by its own flash page.
|
* implemented by its own flash page(s).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -167,7 +167,7 @@ static const uint8_t *keystore_pool;
|
|||||||
static uint8_t *last_p;
|
static uint8_t *last_p;
|
||||||
static const uint8_t *keystore;
|
static const uint8_t *keystore;
|
||||||
|
|
||||||
/* The first halfward is generation for the data page (little endian) */
|
/* The first halfword is generation for the data page (little endian) */
|
||||||
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
const uint8_t const flash_data[4] __attribute__ ((section (".gnuk_data"))) = {
|
||||||
0x01, 0x00, 0xff, 0xff
|
0x01, 0x00, 0xff, 0xff
|
||||||
};
|
};
|
||||||
@@ -300,7 +300,7 @@ flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len)
|
|||||||
flash_warning ("DO WRITE ERROR");
|
flash_warning ("DO WRITE ERROR");
|
||||||
addr += 2;
|
addr += 2;
|
||||||
|
|
||||||
for (i = 0; i < len/2; i ++)
|
for (i = 0; i < len/2; i++)
|
||||||
{
|
{
|
||||||
hw = data[i*2] | (data[i*2+1]<<8);
|
hw = data[i*2] | (data[i*2+1]<<8);
|
||||||
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||||
@@ -581,3 +581,71 @@ flash_cnt123_clear (const uint8_t **addr_p)
|
|||||||
flash_program_halfword ((uint32_t)p, 0);
|
flash_program_halfword ((uint32_t)p, 0);
|
||||||
*addr_p = NULL;
|
*addr_p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
flash_check_blank (const uint8_t *page, int size)
|
||||||
|
{
|
||||||
|
const uint8_t *p;
|
||||||
|
|
||||||
|
for (p = page; p < page + size; p++)
|
||||||
|
if (*p != 0xff)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define FLASH_CH_CERTIFICATE_SIZE 2048
|
||||||
|
int
|
||||||
|
flash_erase_binary (uint8_t file_id)
|
||||||
|
{
|
||||||
|
const uint8_t *p = &ch_certificate_start;
|
||||||
|
|
||||||
|
if (file_id == FILEID_CH_CERTIFICATE)
|
||||||
|
{
|
||||||
|
if (flash_check_blank (p, FLASH_CH_CERTIFICATE_SIZE) == 0)
|
||||||
|
{
|
||||||
|
flash_erase_page ((uint32_t)p);
|
||||||
|
#if FLASH_CH_CERTIFICATE_SIZE > FLASH_PAGE_SIZE
|
||||||
|
flash_erase_page ((uint32_t)p + FLASH_PAGE_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
flash_write_binary (uint8_t file_id, const uint8_t *data,
|
||||||
|
uint16_t len, uint16_t offset)
|
||||||
|
{
|
||||||
|
if (file_id == FILEID_CH_CERTIFICATE)
|
||||||
|
{
|
||||||
|
if (offset + len > FLASH_CH_CERTIFICATE_SIZE || (offset&1) || (len&1))
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const uint8_t *p = &ch_certificate_start;
|
||||||
|
uint16_t hw;
|
||||||
|
uint32_t addr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr = (uint32_t)p + offset;
|
||||||
|
for (i = 0; i < len/2; i++)
|
||||||
|
{
|
||||||
|
hw = data[i*2] | (data[i*2+1]<<8);
|
||||||
|
if (flash_program_halfword (addr, hw) != FLASH_COMPLETE)
|
||||||
|
flash_warning ("DO WRITE ERROR");
|
||||||
|
addr += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ extern void *memmove(void *dest, const void *src, size_t n);
|
|||||||
extern int icc_data_size;
|
extern int icc_data_size;
|
||||||
#define cmd_APDU_size icc_data_size
|
#define cmd_APDU_size icc_data_size
|
||||||
extern int res_APDU_size;
|
extern int res_APDU_size;
|
||||||
|
extern uint8_t *res_APDU_pointer;
|
||||||
|
|
||||||
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
|
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
|
||||||
#define USB_LL_BUF_SIZE 64
|
#define USB_LL_BUF_SIZE 64
|
||||||
@@ -115,6 +116,14 @@ extern void flash_clear_halfword (uint32_t addr);
|
|||||||
extern void flash_increment_counter (uint8_t counter_tag_nr);
|
extern void flash_increment_counter (uint8_t counter_tag_nr);
|
||||||
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
extern void flash_reset_counter (uint8_t counter_tag_nr);
|
||||||
|
|
||||||
|
#define FILEID_CH_CERTIFICATE 0
|
||||||
|
#define FILEID_RANDOM 1
|
||||||
|
extern int flash_erase_binary (uint8_t file_id);
|
||||||
|
extern int flash_write_binary (uint8_t file_id, const uint8_t *data, uint16_t len, uint16_t offset);
|
||||||
|
|
||||||
|
/* Linker set this symbol */
|
||||||
|
extern uint8_t ch_certificate_start;
|
||||||
|
|
||||||
#define KEY_MAGIC_LEN 8
|
#define KEY_MAGIC_LEN 8
|
||||||
#define KEY_CONTENT_LEN 256 /* p and q */
|
#define KEY_CONTENT_LEN 256 /* p and q */
|
||||||
#define GNUK_MAGIC "Gnuk KEY"
|
#define GNUK_MAGIC "Gnuk KEY"
|
||||||
|
|||||||
@@ -121,6 +121,14 @@ SECTIONS
|
|||||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||||
} > flash =0xffffffff
|
} > flash =0xffffffff
|
||||||
|
|
||||||
|
.gnuk_ch_certificate :
|
||||||
|
{
|
||||||
|
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||||
|
ch_certificate_start = .;
|
||||||
|
. += 1920;
|
||||||
|
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||||
|
} > flash =0xffffffff
|
||||||
|
|
||||||
.gnuk_flash :
|
.gnuk_flash :
|
||||||
{
|
{
|
||||||
_data_pool = .;
|
_data_pool = .;
|
||||||
|
|||||||
@@ -929,8 +929,8 @@ gpg_do_table[] = {
|
|||||||
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
{ GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED,
|
||||||
proc_key_import },
|
proc_key_import },
|
||||||
#if 0
|
#if 0
|
||||||
/* Card holder certificate: Not supported yet */
|
/* Card holder certificate */
|
||||||
{ GPG_DO_CH_CERTIFICATE, DO_PROC_READWRITE, AC_NEVER, AC_NEVER, NULL },
|
{ GPG_DO_CH_CERTIFICATE, DO_PROC_READ, AC_ALWAYS, AC_NEVER, NULL },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1200,27 +1200,40 @@ copy_do (const struct do_table_entry *do_p, int with_tag)
|
|||||||
void
|
void
|
||||||
gpg_do_get_data (uint16_t tag, int with_tag)
|
gpg_do_get_data (uint16_t tag, int with_tag)
|
||||||
{
|
{
|
||||||
const struct do_table_entry *do_p = get_do_entry (tag);
|
if (tag == GPG_DO_CH_CERTIFICATE)
|
||||||
|
|
||||||
res_p = res_APDU;
|
|
||||||
|
|
||||||
DEBUG_INFO (" ");
|
|
||||||
DEBUG_SHORT (tag);
|
|
||||||
|
|
||||||
if (do_p)
|
|
||||||
{
|
{
|
||||||
if (copy_do (do_p, with_tag) < 0)
|
res_APDU_pointer = &ch_certificate_start;
|
||||||
/* Overwriting partially written result */
|
res_APDU_size = (res_APDU_pointer[2] << 8) | res_APDU_pointer[3];
|
||||||
GPG_SECURITY_FAILURE ();
|
if (res_APDU_size == 0xffff)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
*res_p++ = 0x90;
|
res_APDU_pointer = NULL;
|
||||||
*res_p++ = 0x00;
|
GPG_NO_RECORD ();
|
||||||
res_APDU_size = res_p - res_APDU;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GPG_NO_RECORD ();
|
{
|
||||||
|
const struct do_table_entry *do_p = get_do_entry (tag);
|
||||||
|
|
||||||
|
res_p = res_APDU;
|
||||||
|
|
||||||
|
DEBUG_INFO (" ");
|
||||||
|
DEBUG_SHORT (tag);
|
||||||
|
|
||||||
|
if (do_p)
|
||||||
|
{
|
||||||
|
if (copy_do (do_p, with_tag) < 0)
|
||||||
|
/* Overwriting partially written result */
|
||||||
|
GPG_SECURITY_FAILURE ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*res_p++ = 0x90;
|
||||||
|
*res_p++ = 0x00;
|
||||||
|
res_APDU_size = res_p - res_APDU;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GPG_NO_RECORD ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#define INS_SELECT_FILE 0xa4
|
#define INS_SELECT_FILE 0xa4
|
||||||
#define INS_READ_BINARY 0xb0
|
#define INS_READ_BINARY 0xb0
|
||||||
#define INS_GET_DATA 0xca
|
#define INS_GET_DATA 0xca
|
||||||
|
#define INS_UPDATE_BINARY 0xd6
|
||||||
#define INS_PUT_DATA 0xda
|
#define INS_PUT_DATA 0xda
|
||||||
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
||||||
|
|
||||||
@@ -75,6 +76,8 @@ write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
|||||||
#define FILE_MF 2
|
#define FILE_MF 2
|
||||||
#define FILE_EF_DIR 3
|
#define FILE_EF_DIR 3
|
||||||
#define FILE_EF_SERIAL 4
|
#define FILE_EF_SERIAL 4
|
||||||
|
#define FILE_EF_CH_CERTIFICATE 5
|
||||||
|
#define FILE_EF_RANDOM 6
|
||||||
|
|
||||||
static uint8_t file_selection;
|
static uint8_t file_selection;
|
||||||
|
|
||||||
@@ -632,7 +635,7 @@ cmd_read_binary (void)
|
|||||||
static void
|
static void
|
||||||
cmd_select_file (void)
|
cmd_select_file (void)
|
||||||
{
|
{
|
||||||
if (cmd_APDU[2] == 4) /* Selection by DF name */
|
if (cmd_APDU[2] == 4) /* Selection by DF name: it must be OpenPGP card */
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select DF by name\r\n");
|
DEBUG_INFO (" - select DF by name\r\n");
|
||||||
|
|
||||||
@@ -654,8 +657,7 @@ cmd_select_file (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[4] == 2
|
else if (cmd_APDU[4] == 2
|
||||||
&& cmd_APDU[5] == 0x2f
|
&& cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02)
|
||||||
&& cmd_APDU[6] == 0x02)
|
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
||||||
/*
|
/*
|
||||||
@@ -665,8 +667,7 @@ cmd_select_file (void)
|
|||||||
file_selection = FILE_EF_SERIAL;
|
file_selection = FILE_EF_SERIAL;
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[4] == 2
|
else if (cmd_APDU[4] == 2
|
||||||
&& cmd_APDU[5] == 0x3f
|
&& cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00)
|
||||||
&& cmd_APDU[6] == 0x00)
|
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select ROOT MF\r\n");
|
DEBUG_INFO (" - select ROOT MF\r\n");
|
||||||
if (cmd_APDU[3] == 0x0c)
|
if (cmd_APDU[3] == 0x0c)
|
||||||
@@ -682,6 +683,7 @@ cmd_select_file (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
file_selection = FILE_MF;
|
file_selection = FILE_MF;
|
||||||
|
ac_fini (); /* Reset authentication */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -838,6 +840,77 @@ cmd_internal_authenticate (void)
|
|||||||
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_update_binary (void)
|
||||||
|
{
|
||||||
|
int len = cmd_APDU[4];
|
||||||
|
int data_start = 5;
|
||||||
|
uint16_t offset;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||||
|
data_start = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||||
|
|
||||||
|
if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("security error.");
|
||||||
|
GPG_SECURITY_FAILURE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmd_APDU[2] & 0x80))
|
||||||
|
if ((cmd_APDU[2] & 0x7f) <= 0x01)
|
||||||
|
{
|
||||||
|
file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
|
||||||
|
r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GPG_NO_FILE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (file_selection != FILE_EF_CH_CERTIFICATE
|
||||||
|
&& file_selection != FILE_EF_RANDOM)
|
||||||
|
{
|
||||||
|
GPG_COMMAND_NOT_ALLOWED ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_SHORT (len);
|
||||||
|
DEBUG_SHORT (offset);
|
||||||
|
|
||||||
|
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
|
||||||
|
&cmd_APDU[data_start], len, offset);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
|
GPG_MEMORY_FAILURE ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_INFO ("UPDATE BINARY done.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct command
|
struct command
|
||||||
{
|
{
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
@@ -854,6 +927,7 @@ const struct command cmds[] = {
|
|||||||
{ INS_SELECT_FILE, cmd_select_file },
|
{ INS_SELECT_FILE, cmd_select_file },
|
||||||
{ INS_READ_BINARY, cmd_read_binary },
|
{ INS_READ_BINARY, cmd_read_binary },
|
||||||
{ INS_GET_DATA, cmd_get_data },
|
{ INS_GET_DATA, cmd_get_data },
|
||||||
|
{ INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */
|
||||||
{ INS_PUT_DATA, cmd_put_data },
|
{ INS_PUT_DATA, cmd_put_data },
|
||||||
{ INS_PUT_DATA_ODD, cmd_put_data },
|
{ INS_PUT_DATA_ODD, cmd_put_data },
|
||||||
};
|
};
|
||||||
@@ -869,6 +943,8 @@ process_command_apdu (void)
|
|||||||
if (cmds[i].command == cmd)
|
if (cmds[i].command == cmd)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
res_APDU_pointer = NULL; /* default */
|
||||||
|
|
||||||
if (i < NUM_CMDS)
|
if (i < NUM_CMDS)
|
||||||
cmds[i].cmd_handler ();
|
cmds[i].cmd_handler ();
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
|
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
|
||||||
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
|
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
|
||||||
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
|
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
|
||||||
|
#define GPG_COMMAND_NOT_ALLOWED() write_res_apdu (NULL, 0, 0x69, 0x86)
|
||||||
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
|
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
|
||||||
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
|
#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_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
|
||||||
|
|||||||
@@ -385,6 +385,7 @@ icc_power_off (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int res_APDU_size;
|
int res_APDU_size;
|
||||||
|
uint8_t *res_APDU_pointer;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icc_send_data_block (int len, uint8_t status, uint8_t chain)
|
icc_send_data_block (int len, uint8_t status, uint8_t chain)
|
||||||
@@ -608,8 +609,16 @@ icc_handle_data (void)
|
|||||||
{
|
{
|
||||||
if (icc_header->param == 0x10)
|
if (icc_header->param == 0x10)
|
||||||
{
|
{
|
||||||
memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE,
|
if (res_APDU_pointer != NULL)
|
||||||
res_APDU_size);
|
{
|
||||||
|
memcpy (res_APDU, res_APDU_pointer,
|
||||||
|
ICC_RESPONSE_MSG_DATA_SIZE);
|
||||||
|
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE,
|
||||||
|
res_APDU_size);
|
||||||
|
|
||||||
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
||||||
{
|
{
|
||||||
icc_send_data_block (res_APDU_size, 0, 0x02);
|
icc_send_data_block (res_APDU_size, 0, 0x02);
|
||||||
@@ -689,6 +698,9 @@ USBthread (void *arg)
|
|||||||
{
|
{
|
||||||
if (icc_state == ICC_STATE_EXECUTE)
|
if (icc_state == ICC_STATE_EXECUTE)
|
||||||
{
|
{
|
||||||
|
if (res_APDU_pointer != NULL)
|
||||||
|
memcpy (res_APDU, res_APDU_pointer, ICC_RESPONSE_MSG_DATA_SIZE);
|
||||||
|
|
||||||
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
||||||
{
|
{
|
||||||
icc_send_data_block (res_APDU_size, 0, 0);
|
icc_send_data_block (res_APDU_size, 0, 0);
|
||||||
@@ -698,6 +710,7 @@ USBthread (void *arg)
|
|||||||
{
|
{
|
||||||
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01);
|
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x01);
|
||||||
res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE;
|
res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
|
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
icc_state = ICC_STATE_SEND;
|
icc_state = ICC_STATE_SEND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user