New API between gpg and ccid layer
This commit is contained in:
22
ChangeLog
22
ChangeLog
@@ -1,3 +1,25 @@
|
|||||||
|
2012-01-18 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
Clean up API between application layer and CCID layer.
|
||||||
|
* tool/gnuk_put_binary.py, gnuk_put_binary_libusb.py: Don't append
|
||||||
|
0x9000 at the data, any more.
|
||||||
|
* src/usb-icc.c (icc_data_size, icc_buffer, icc_seq): Make them
|
||||||
|
internal.
|
||||||
|
(res_APDU_size, res_APDU_pointer): Removed.
|
||||||
|
(icc_handle_data, USBthread): Follow new API of struct apdu.
|
||||||
|
* src/call-rsa.c (rsa_sign, rsa_decrypt): Likewise.
|
||||||
|
* src/openpgp.c (CLS, INS, P1, P2): New.
|
||||||
|
(set_res_apdu, cmd_verify, cmd_change_password)
|
||||||
|
(cmd_reset_user_password, cmd_put_data, cmd_pgp_gakp)
|
||||||
|
(cmd_read_binary, cmd_select_file, cmd_pso)
|
||||||
|
(cmd_internal_authenticate, cmd_update_binary, cmd_write_binary)
|
||||||
|
(process_command_apdu, GPGthread): Follow new API of struct apdu.
|
||||||
|
* src/openpgp-do.c (gpg_do_get_data, gpg_do_public_key): Follow
|
||||||
|
new API of struct apdu.
|
||||||
|
* src/gnuk.h (struct apdu, apdu): New.
|
||||||
|
(cmd_APDU, icc_data_size, cmd_APDU_size, icc_buffer): Removed.
|
||||||
|
(res_APDU, res_APDU_size): Use members of struct apdu.
|
||||||
|
|
||||||
2012-01-16 Niibe Yutaka <gniibe@fsij.org>
|
2012-01-16 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
Adopt new USB API.
|
Adopt new USB API.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
|
#include "openpgp.h"
|
||||||
#include "polarssl/config.h"
|
#include "polarssl/config.h"
|
||||||
#include "polarssl/rsa.h"
|
#include "polarssl/rsa.h"
|
||||||
|
|
||||||
@@ -84,10 +85,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
|
res_APDU_size = RSA_SIGNATURE_LENGTH;
|
||||||
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
|
|
||||||
res_APDU_size = RSA_SIGNATURE_LENGTH + 2;
|
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
|
GPG_SUCCESS ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,10 +177,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res_APDU[output_len] = 0x90;
|
res_APDU_size = output_len;
|
||||||
res_APDU[output_len+1] = 0x00;
|
|
||||||
res_APDU_size = output_len + 2;
|
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
|
GPG_SUCCESS ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/gnuk.h
49
src/gnuk.h
@@ -1,3 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* We declare some of libc functions here, because we will
|
||||||
|
* remove dependency on libc in future, possibly.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
extern void *memset (void *s, int c, size_t n);
|
||||||
|
extern int memcmp (const void *s1, const void *s2, size_t n);
|
||||||
|
extern void *memmove(void *dest, const void *src, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debug functions
|
||||||
|
*/
|
||||||
extern Thread *stdout_thread;
|
extern Thread *stdout_thread;
|
||||||
#define EV_TX_READY ((eventmask_t)1)
|
#define EV_TX_READY ((eventmask_t)1)
|
||||||
|
|
||||||
@@ -11,16 +25,26 @@ extern void put_binary (const char *s, int len);
|
|||||||
|
|
||||||
extern void _write (const char *, int);
|
extern void _write (const char *, int);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We declare some of libc functions here, because we will
|
* Application layer <-> CCID layer data structure
|
||||||
* remove dependency on libc in future.
|
|
||||||
*/
|
*/
|
||||||
extern size_t strlen (const char *s);
|
struct apdu {
|
||||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
uint8_t seq;
|
||||||
extern void *memcpy (void *dest, const void *src, size_t n);
|
|
||||||
extern void *memset (void *s, int c, size_t n);
|
/* command APDU */
|
||||||
extern int memcmp (const void *s1, const void *s2, size_t n);
|
uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
|
||||||
extern void *memmove(void *dest, const void *src, size_t n);
|
uint8_t *cmd_apdu_data;
|
||||||
|
uint16_t cmd_apdu_data_len; /* Nc, calculated by Lc field */
|
||||||
|
uint32_t expected_res_size; /* Ne, calculated by Le field */
|
||||||
|
|
||||||
|
/* response APDU */
|
||||||
|
uint16_t sw;
|
||||||
|
uint8_t *res_apdu_data;
|
||||||
|
uint16_t res_apdu_data_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct apdu apdu;
|
||||||
|
|
||||||
#define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */
|
#define EV_EXEC_FINISHED ((eventmask_t)2) /* GPG Execution finished */
|
||||||
|
|
||||||
@@ -38,12 +62,8 @@ extern void *memmove(void *dest, const void *src, size_t n);
|
|||||||
|
|
||||||
#define ICC_MSG_HEADER_SIZE 10
|
#define ICC_MSG_HEADER_SIZE 10
|
||||||
|
|
||||||
#define cmd_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
|
#define res_APDU apdu.res_apdu_data
|
||||||
#define res_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
|
#define res_APDU_size apdu.res_apdu_data_len
|
||||||
extern int icc_data_size;
|
|
||||||
#define cmd_APDU_size icc_data_size
|
|
||||||
extern int res_APDU_size;
|
|
||||||
extern const 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
|
||||||
@@ -54,7 +74,6 @@ extern const uint8_t *res_APDU_pointer;
|
|||||||
*/
|
*/
|
||||||
#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \
|
#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \
|
||||||
/ USB_LL_BUF_SIZE * USB_LL_BUF_SIZE)
|
/ USB_LL_BUF_SIZE * USB_LL_BUF_SIZE)
|
||||||
extern uint8_t icc_buffer[USB_BUF_SIZE];
|
|
||||||
|
|
||||||
enum icc_state
|
enum icc_state
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1250,16 +1250,13 @@ gpg_do_get_data (uint16_t tag, int with_tag)
|
|||||||
#if defined(CERTDO_SUPPORT)
|
#if defined(CERTDO_SUPPORT)
|
||||||
if (tag == GPG_DO_CH_CERTIFICATE)
|
if (tag == GPG_DO_CH_CERTIFICATE)
|
||||||
{
|
{
|
||||||
res_APDU_pointer = &ch_certificate_start;
|
apdu.res_apdu_data = &ch_certificate_start;
|
||||||
res_APDU_size = ((res_APDU_pointer[2] << 8) | res_APDU_pointer[3]);
|
apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]);
|
||||||
if (res_APDU_size == 0xffff)
|
if (apdu.res_apdu_data_len == 0xffff)
|
||||||
{
|
|
||||||
res_APDU_pointer = NULL;
|
|
||||||
GPG_NO_RECORD ();
|
GPG_NO_RECORD ();
|
||||||
}
|
|
||||||
else
|
else
|
||||||
/* Add length of (tag+len) and status word (0x9000) at the end */
|
/* Add length of (tag+len) */
|
||||||
res_APDU_size += 4 + 2;
|
apdu.res_apdu_data_len += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -1278,9 +1275,8 @@ gpg_do_get_data (uint16_t tag, int with_tag)
|
|||||||
GPG_SECURITY_FAILURE ();
|
GPG_SECURITY_FAILURE ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*res_p++ = 0x90;
|
|
||||||
*res_p++ = 0x00;
|
|
||||||
res_APDU_size = res_p - res_APDU;
|
res_APDU_size = res_p - res_APDU;
|
||||||
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1414,8 +1410,8 @@ gpg_do_public_key (uint8_t kk_byte)
|
|||||||
*res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01;
|
*res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01;
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
*res_p++ = 0x90; *res_p++ = 0x00;
|
|
||||||
res_APDU_size = res_p - res_APDU;
|
res_APDU_size = res_p - res_APDU;
|
||||||
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_INFO ("done.\r\n");
|
DEBUG_INFO ("done.\r\n");
|
||||||
|
|||||||
224
src/openpgp.c
224
src/openpgp.c
@@ -29,6 +29,11 @@
|
|||||||
#include "polarssl/config.h"
|
#include "polarssl/config.h"
|
||||||
#include "polarssl/sha1.h"
|
#include "polarssl/sha1.h"
|
||||||
|
|
||||||
|
#define CLS(a) a.cmd_apdu_head[0]
|
||||||
|
#define INS(a) a.cmd_apdu_head[1]
|
||||||
|
#define P1(a) a.cmd_apdu_head[2]
|
||||||
|
#define P2(a) a.cmd_apdu_head[3]
|
||||||
|
|
||||||
#define INS_VERIFY 0x20
|
#define INS_VERIFY 0x20
|
||||||
#define INS_CHANGE_REFERENCE_DATA 0x24
|
#define INS_CHANGE_REFERENCE_DATA 0x24
|
||||||
#define INS_PSO 0x2a
|
#define INS_PSO 0x2a
|
||||||
@@ -64,9 +69,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
|
|||||||
void
|
void
|
||||||
set_res_apdu (uint8_t sw1, uint8_t sw2)
|
set_res_apdu (uint8_t sw1, uint8_t sw2)
|
||||||
{
|
{
|
||||||
res_APDU_size = 2;
|
apdu.sw = (sw1 << 8) | sw2;
|
||||||
res_APDU[0] = sw1;
|
|
||||||
res_APDU[1] = sw2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FILE_NONE 0
|
#define FILE_NONE 0
|
||||||
@@ -117,22 +120,15 @@ static void
|
|||||||
cmd_verify (void)
|
cmd_verify (void)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
uint8_t p2 = cmd_APDU[3];
|
uint8_t p2 = P2 (apdu);
|
||||||
int r;
|
int r;
|
||||||
int data_start = 5;
|
|
||||||
const uint8_t *pw;
|
const uint8_t *pw;
|
||||||
|
|
||||||
DEBUG_INFO (" - VERIFY\r\n");
|
DEBUG_INFO (" - VERIFY\r\n");
|
||||||
DEBUG_BYTE (p2);
|
DEBUG_BYTE (p2);
|
||||||
|
|
||||||
len = cmd_APDU[4];
|
len = apdu.cmd_apdu_data_len;
|
||||||
if (len == 0) /* extended length */
|
pw = apdu.cmd_apdu_data;
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
data_start = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw = &cmd_APDU[data_start];
|
|
||||||
|
|
||||||
if (p2 == 0x81)
|
if (p2 == 0x81)
|
||||||
r = verify_pso_cds (pw, len);
|
r = verify_pso_cds (pw, len);
|
||||||
@@ -213,8 +209,8 @@ cmd_change_password (void)
|
|||||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||||
uint8_t *new_ks = &new_ks0[1];
|
uint8_t *new_ks = &new_ks0[1];
|
||||||
uint8_t p1 = cmd_APDU[2]; /* 0: change (old+new), 1: exchange (new) */
|
uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */
|
||||||
uint8_t p2 = cmd_APDU[3];
|
uint8_t p2 = P2 (apdu);
|
||||||
int len;
|
int len;
|
||||||
const uint8_t *pw;
|
const uint8_t *pw;
|
||||||
const uint8_t *newpw;
|
const uint8_t *newpw;
|
||||||
@@ -225,13 +221,8 @@ cmd_change_password (void)
|
|||||||
DEBUG_INFO ("Change PW\r\n");
|
DEBUG_INFO ("Change PW\r\n");
|
||||||
DEBUG_BYTE (who);
|
DEBUG_BYTE (who);
|
||||||
|
|
||||||
len = cmd_APDU[4];
|
len = apdu.cmd_apdu_data_len;
|
||||||
pw = &cmd_APDU[5];
|
pw = apdu.cmd_apdu_data;
|
||||||
if (len == 0) /* extended length */
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
pw += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p1 != 0)
|
if (p1 != 0)
|
||||||
{
|
{
|
||||||
@@ -329,7 +320,7 @@ cmd_change_password (void)
|
|||||||
static void
|
static void
|
||||||
cmd_reset_user_password (void)
|
cmd_reset_user_password (void)
|
||||||
{
|
{
|
||||||
uint8_t p1 = cmd_APDU[2];
|
uint8_t p1 = P1 (apdu);
|
||||||
int len;
|
int len;
|
||||||
const uint8_t *pw;
|
const uint8_t *pw;
|
||||||
const uint8_t *newpw;
|
const uint8_t *newpw;
|
||||||
@@ -341,13 +332,8 @@ cmd_reset_user_password (void)
|
|||||||
DEBUG_INFO ("Reset PW1\r\n");
|
DEBUG_INFO ("Reset PW1\r\n");
|
||||||
DEBUG_BYTE (p1);
|
DEBUG_BYTE (p1);
|
||||||
|
|
||||||
len = cmd_APDU[4];
|
len = apdu.cmd_apdu_data_len;
|
||||||
pw = &cmd_APDU[5];
|
pw = apdu.cmd_apdu_data;
|
||||||
if (len == 0) /* extended length */
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
pw += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p1 == 0x00) /* by User with Reseting Code */
|
if (p1 == 0x00) /* by User with Reseting Code */
|
||||||
{
|
{
|
||||||
@@ -469,17 +455,9 @@ cmd_put_data (void)
|
|||||||
if (file_selection != FILE_DF_OPENPGP)
|
if (file_selection != FILE_DF_OPENPGP)
|
||||||
GPG_NO_RECORD();
|
GPG_NO_RECORD();
|
||||||
|
|
||||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||||
data = &cmd_APDU[5];
|
len = apdu.cmd_apdu_data_len;
|
||||||
|
data = apdu.cmd_apdu_data;
|
||||||
len = cmd_APDU_size - 5;
|
|
||||||
if (len >= 256)
|
|
||||||
/* extended Lc */
|
|
||||||
{
|
|
||||||
data += 2;
|
|
||||||
len -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpg_do_put_data (tag, data, len);
|
gpg_do_put_data (tag, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,16 +465,11 @@ static void
|
|||||||
cmd_pgp_gakp (void)
|
cmd_pgp_gakp (void)
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
||||||
DEBUG_BYTE (cmd_APDU[2]);
|
DEBUG_BYTE (P1 (apdu));
|
||||||
|
|
||||||
if (cmd_APDU[2] == 0x81)
|
if (P1 (apdu) == 0x81)
|
||||||
/* Get public key */
|
/* Get public key */
|
||||||
{
|
gpg_do_public_key (apdu.cmd_apdu_data[0]);
|
||||||
if (cmd_APDU[4] == 0)
|
|
||||||
gpg_do_public_key (cmd_APDU[7]);
|
|
||||||
else
|
|
||||||
gpg_do_public_key (cmd_APDU[5]);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{ /* Generate key pair */
|
{ /* Generate key pair */
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
@@ -514,7 +487,7 @@ cmd_read_binary (void)
|
|||||||
|
|
||||||
if (file_selection == FILE_EF_SERIAL)
|
if (file_selection == FILE_EF_SERIAL)
|
||||||
{
|
{
|
||||||
if (cmd_APDU[3] >= 6)
|
if (P2 (apdu) >= 6)
|
||||||
GPG_BAD_P0_P1 ();
|
GPG_BAD_P0_P1 ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -529,19 +502,23 @@ 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 (P1 (apdu) == 4) /* Selection by DF name */
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select DF by name\r\n");
|
DEBUG_INFO (" - select DF by name\r\n");
|
||||||
|
|
||||||
/* name = D2 76 00 01 24 01 */
|
/* name = D2 76 00 01 24 01 */
|
||||||
if (cmd_APDU[4] != 6 || memcmp (openpgpcard_aid, &cmd_APDU[5], 6) != 0)
|
if (apdu.cmd_apdu_data_len != 6
|
||||||
|
|| memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
|
||||||
{
|
{
|
||||||
|
DEBUG_WORD (apdu.cmd_apdu_data_len);
|
||||||
|
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
||||||
|
|
||||||
GPG_NO_FILE ();
|
GPG_NO_FILE ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_selection = FILE_DF_OPENPGP;
|
file_selection = FILE_DF_OPENPGP;
|
||||||
if ((cmd_APDU[3] & 0x0c) == 0x0c) /* No FCI */
|
if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -553,8 +530,8 @@ cmd_select_file (void)
|
|||||||
res_APDU_size += 2;
|
res_APDU_size += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[4] == 2
|
else if (apdu.cmd_apdu_data_len == 2
|
||||||
&& cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02)
|
&& apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02)
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
||||||
/*
|
/*
|
||||||
@@ -563,11 +540,11 @@ cmd_select_file (void)
|
|||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
file_selection = FILE_EF_SERIAL;
|
file_selection = FILE_EF_SERIAL;
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[4] == 2
|
else if (apdu.cmd_apdu_data_len == 2
|
||||||
&& cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00)
|
&& apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - select ROOT MF\r\n");
|
DEBUG_INFO (" - select ROOT MF\r\n");
|
||||||
if (cmd_APDU[3] == 0x0c)
|
if (P2 (apdu) == 0x0c)
|
||||||
{
|
{
|
||||||
GPG_SUCCESS ();
|
GPG_SUCCESS ();
|
||||||
}
|
}
|
||||||
@@ -575,12 +552,11 @@ cmd_select_file (void)
|
|||||||
{
|
{
|
||||||
int len = sizeof (select_file_TOP_result);
|
int len = sizeof (select_file_TOP_result);
|
||||||
|
|
||||||
res_APDU_size = 2 + len;
|
res_APDU_size = len;
|
||||||
memcpy (res_APDU, select_file_TOP_result, len);
|
memcpy (res_APDU, select_file_TOP_result, len);
|
||||||
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
||||||
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
||||||
res_APDU[len] = 0x90;
|
GPG_SUCCESS ();
|
||||||
res_APDU[len+1] = 0x00;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file_selection = FILE_MF;
|
file_selection = FILE_MF;
|
||||||
@@ -598,7 +574,7 @@ cmd_select_file (void)
|
|||||||
static void
|
static void
|
||||||
cmd_get_data (void)
|
cmd_get_data (void)
|
||||||
{
|
{
|
||||||
uint16_t tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||||
|
|
||||||
DEBUG_INFO (" - Get Data\r\n");
|
DEBUG_INFO (" - Get Data\r\n");
|
||||||
|
|
||||||
@@ -611,21 +587,14 @@ cmd_get_data (void)
|
|||||||
static void
|
static void
|
||||||
cmd_pso (void)
|
cmd_pso (void)
|
||||||
{
|
{
|
||||||
int len = cmd_APDU[4];
|
int len = apdu.cmd_apdu_data_len;
|
||||||
int data_start = 5;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
data_start = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO (" - PSO: ");
|
DEBUG_INFO (" - PSO: ");
|
||||||
DEBUG_WORD ((uint32_t)&r);
|
DEBUG_WORD ((uint32_t)&r);
|
||||||
DEBUG_BINARY (cmd_APDU, cmd_APDU_size);
|
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
||||||
|
|
||||||
if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
|
if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a)
|
||||||
{
|
{
|
||||||
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
|
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
|
||||||
{
|
{
|
||||||
@@ -634,24 +603,24 @@ cmd_pso (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_APDU_size != 7 + 34 + 2 /* MD5 */
|
/* Check size of digestInfo */
|
||||||
/* Header (with Extended Lc)=7, size of digestInfo, and Le=2-byte */
|
if (len != 34 /* MD5 */
|
||||||
&& cmd_APDU_size != 7 + 35 + 2 /* SHA1 / RIPEMD-160 */
|
&& len != 35 /* SHA1 / RIPEMD-160 */
|
||||||
&& cmd_APDU_size != 7 + 47 + 2 /* SHA224 */
|
&& len != 47 /* SHA224 */
|
||||||
&& cmd_APDU_size != 7 + 51 + 2 /* SHA256 */
|
&& len != 51 /* SHA256 */
|
||||||
&& cmd_APDU_size != 7 + 67 + 2 /* SHA384 */
|
&& len != 67 /* SHA384 */
|
||||||
&& cmd_APDU_size != 7 + 83 + 2) /* SHA512 */
|
&& len != 83) /* SHA512 */
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" wrong length: ");
|
DEBUG_INFO (" wrong length: ");
|
||||||
DEBUG_SHORT (cmd_APDU_size);
|
DEBUG_SHORT (len);
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
|
DEBUG_SHORT (len);
|
||||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
|
||||||
|
|
||||||
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
|
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||||
&kd[GPG_KEY_FOR_SIGNING]);
|
&kd[GPG_KEY_FOR_SIGNING]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
@@ -663,7 +632,7 @@ cmd_pso (void)
|
|||||||
gpg_increment_digital_signature_counter ();
|
gpg_increment_digital_signature_counter ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
|
else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
|
||||||
{
|
{
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||||
@@ -676,9 +645,8 @@ cmd_pso (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Skip padding 0x00 */
|
/* Skip padding 0x00 */
|
||||||
data_start++;
|
|
||||||
len--;
|
len--;
|
||||||
r = rsa_decrypt (&cmd_APDU[data_start], res_APDU, len,
|
r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
|
||||||
&kd[GPG_KEY_FOR_DECRYPTION]);
|
&kd[GPG_KEY_FOR_DECRYPTION]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
@@ -686,9 +654,9 @@ cmd_pso (void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - ??");
|
DEBUG_INFO (" - ??");
|
||||||
DEBUG_BYTE (cmd_APDU[2]);
|
DEBUG_BYTE (P1 (apdu));
|
||||||
DEBUG_INFO (" - ??");
|
DEBUG_INFO (" - ??");
|
||||||
DEBUG_BYTE (cmd_APDU[3]);
|
DEBUG_BYTE (P2 (apdu));
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,19 +666,12 @@ cmd_pso (void)
|
|||||||
static void
|
static void
|
||||||
cmd_internal_authenticate (void)
|
cmd_internal_authenticate (void)
|
||||||
{
|
{
|
||||||
int len = cmd_APDU[4];
|
int len = apdu.cmd_apdu_data_len;
|
||||||
int data_start = 5;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
data_start = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
|
||||||
|
|
||||||
if (cmd_APDU[2] == 0x00 && cmd_APDU[3] == 0x00)
|
if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
|
||||||
{
|
{
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
|
|
||||||
@@ -721,7 +682,7 @@ cmd_internal_authenticate (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
|
r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
|
||||||
&kd[GPG_KEY_FOR_AUTHENTICATION]);
|
&kd[GPG_KEY_FOR_AUTHENTICATION]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
@@ -729,9 +690,9 @@ cmd_internal_authenticate (void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_INFO (" - ??");
|
DEBUG_INFO (" - ??");
|
||||||
DEBUG_BYTE (cmd_APDU[2]);
|
DEBUG_BYTE (P1 (apdu));
|
||||||
DEBUG_INFO (" - ??");
|
DEBUG_INFO (" - ??");
|
||||||
DEBUG_BYTE (cmd_APDU[3]);
|
DEBUG_BYTE (P2 (apdu));
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,17 +703,10 @@ cmd_internal_authenticate (void)
|
|||||||
static void
|
static void
|
||||||
cmd_update_binary (void)
|
cmd_update_binary (void)
|
||||||
{
|
{
|
||||||
int len = cmd_APDU[4];
|
int len = apdu.cmd_apdu_data_len;
|
||||||
int data_start = 5;
|
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
data_start = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
DEBUG_INFO (" - UPDATE BINARY\r\n");
|
||||||
|
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
@@ -762,10 +716,10 @@ cmd_update_binary (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmd_APDU[2] & 0x80))
|
if ((P1 (apdu) & 0x80))
|
||||||
if ((cmd_APDU[2] & 0x7f) <= FILEID_RANDOM)
|
if ((P1 (apdu) & 0x7f) <= FILEID_RANDOM)
|
||||||
{
|
{
|
||||||
file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
|
file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f);
|
||||||
r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE);
|
r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
@@ -790,14 +744,14 @@ cmd_update_binary (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
|
offset = (P1 (apdu) << 8) | P2 (apdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
DEBUG_SHORT (offset);
|
DEBUG_SHORT (offset);
|
||||||
|
|
||||||
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
|
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
|
||||||
&cmd_APDU[data_start], len, offset);
|
apdu.cmd_apdu_data, len, offset);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("memory error.\r\n");
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
@@ -813,17 +767,10 @@ cmd_update_binary (void)
|
|||||||
static void
|
static void
|
||||||
cmd_write_binary (void)
|
cmd_write_binary (void)
|
||||||
{
|
{
|
||||||
int len = cmd_APDU[4];
|
int len = apdu.cmd_apdu_data_len;
|
||||||
int data_start = 5;
|
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
|
||||||
data_start = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||||
|
|
||||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||||
@@ -833,10 +780,10 @@ cmd_write_binary (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmd_APDU[2] & 0x80))
|
if ((P1 (apdu) & 0x80))
|
||||||
if ((cmd_APDU[2] & 0x7f) <= FILEID_SERIAL_NO)
|
if ((P1 (apdu) & 0x7f) <= FILEID_SERIAL_NO)
|
||||||
{
|
{
|
||||||
file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
|
file_selection = FILE_EF_CH_CERTIFICATE + (P1 (apdu) & 0x7f);
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -854,14 +801,14 @@ cmd_write_binary (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
|
offset = (P1 (apdu) << 8) | P2 (apdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_SHORT (len);
|
DEBUG_SHORT (len);
|
||||||
DEBUG_SHORT (offset);
|
DEBUG_SHORT (offset);
|
||||||
|
|
||||||
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
|
r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
|
||||||
&cmd_APDU[data_start], len, offset);
|
apdu.cmd_apdu_data, len, offset);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("memory error.\r\n");
|
DEBUG_INFO ("memory error.\r\n");
|
||||||
@@ -901,7 +848,7 @@ static void
|
|||||||
process_command_apdu (void)
|
process_command_apdu (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint8_t cmd = cmd_APDU[1];
|
uint8_t cmd = INS (apdu);
|
||||||
|
|
||||||
for (i = 0; i < NUM_CMDS; i++)
|
for (i = 0; i < NUM_CMDS; i++)
|
||||||
if (cmds[i].command == cmd)
|
if (cmds[i].command == cmd)
|
||||||
@@ -935,12 +882,10 @@ GPGthread (void *arg)
|
|||||||
|
|
||||||
DEBUG_INFO ("GPG!: ");
|
DEBUG_INFO ("GPG!: ");
|
||||||
|
|
||||||
res_APDU_pointer = NULL;
|
|
||||||
|
|
||||||
if (m == EV_VERIFY_CMD_AVAILABLE)
|
if (m == EV_VERIFY_CMD_AVAILABLE)
|
||||||
{
|
{
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
if (cmd_APDU[1] != INS_VERIFY)
|
if (INS (apdu) != INS_VERIFY)
|
||||||
{
|
{
|
||||||
GPG_CONDITION_NOT_SATISFIED ();
|
GPG_CONDITION_NOT_SATISFIED ();
|
||||||
goto done;
|
goto done;
|
||||||
@@ -952,9 +897,8 @@ GPGthread (void *arg)
|
|||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
|
memcpy (apdu.cmd_apdu_data, pin_input_buffer, pw_len);
|
||||||
cmd_APDU[4] = pw_len;
|
apdu.cmd_apdu_data_len = pw_len;
|
||||||
icc_data_size = 5 + pw_len;
|
|
||||||
#else
|
#else
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
goto done;
|
goto done;
|
||||||
@@ -963,12 +907,12 @@ GPGthread (void *arg)
|
|||||||
else if (m == EV_MODIFY_CMD_AVAILABLE)
|
else if (m == EV_MODIFY_CMD_AVAILABLE)
|
||||||
{
|
{
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
uint8_t bConfirmPIN = cmd_APDU[4];
|
uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
|
||||||
uint8_t *p = &cmd_APDU[5];
|
uint8_t *p = apdu.cmd_apdu_data;
|
||||||
|
|
||||||
if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA
|
if (INS (apdu) != INS_CHANGE_REFERENCE_DATA
|
||||||
&& cmd_APDU[1] != INS_RESET_RETRY_COUNTER
|
&& INS (apdu) != INS_RESET_RETRY_COUNTER
|
||||||
&& cmd_APDU[1] != INS_PUT_DATA)
|
&& INS (apdu) != INS_PUT_DATA)
|
||||||
{
|
{
|
||||||
GPG_CONDITION_NOT_SATISFIED ();
|
GPG_CONDITION_NOT_SATISFIED ();
|
||||||
goto done;
|
goto done;
|
||||||
@@ -1012,8 +956,7 @@ GPGthread (void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = cmd_APDU[4] = pw_len + newpw_len;
|
apdu.cmd_apdu_data_len = pw_len + newpw_len;
|
||||||
icc_data_size = 5 + len;
|
|
||||||
#else
|
#else
|
||||||
GPG_ERROR ();
|
GPG_ERROR ();
|
||||||
goto done;
|
goto done;
|
||||||
@@ -1022,13 +965,10 @@ GPGthread (void *arg)
|
|||||||
else if (m == EV_NOP)
|
else if (m == EV_NOP)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (icc_data_size != 0)
|
|
||||||
{
|
|
||||||
process_command_apdu ();
|
process_command_apdu ();
|
||||||
done:
|
done:
|
||||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gpg_fini ();
|
gpg_fini ();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
244
src/usb-icc.c
244
src/usb-icc.c
@@ -31,6 +31,8 @@
|
|||||||
#include "usb_istr.h"
|
#include "usb_istr.h"
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
|
|
||||||
|
struct apdu apdu;
|
||||||
|
|
||||||
#define ICC_SET_PARAMS 0x61 /* non-ICCD command */
|
#define ICC_SET_PARAMS 0x61 /* non-ICCD command */
|
||||||
#define ICC_POWER_ON 0x62
|
#define ICC_POWER_ON 0x62
|
||||||
#define ICC_POWER_OFF 0x63
|
#define ICC_POWER_OFF 0x63
|
||||||
@@ -74,7 +76,7 @@ struct icc_header {
|
|||||||
uint16_t param;
|
uint16_t param;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
int icc_data_size;
|
static int icc_data_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB-ICC communication could be considered "half duplex".
|
* USB-ICC communication could be considered "half duplex".
|
||||||
@@ -94,8 +96,8 @@ int icc_data_size;
|
|||||||
* The buffer will be filled by multiple RX transactions (Bulk-OUT)
|
* The buffer will be filled by multiple RX transactions (Bulk-OUT)
|
||||||
* or will be used for multiple TX transactions (Bulk-IN)
|
* or will be used for multiple TX transactions (Bulk-IN)
|
||||||
*/
|
*/
|
||||||
uint8_t icc_buffer[USB_BUF_SIZE];
|
static uint8_t icc_buffer[USB_BUF_SIZE];
|
||||||
uint8_t icc_seq;
|
static uint8_t icc_seq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to ICC_BUFFER
|
* Pointer to ICC_BUFFER
|
||||||
@@ -391,9 +393,6 @@ icc_power_off (void)
|
|||||||
return ICC_STATE_START;
|
return ICC_STATE_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res_APDU_size;
|
|
||||||
const 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)
|
||||||
{
|
{
|
||||||
@@ -501,6 +500,87 @@ icc_handle_data (void)
|
|||||||
{
|
{
|
||||||
if (icc_header->param == 0)
|
if (icc_header->param == 0)
|
||||||
{ /* Give this message to GPG thread */
|
{ /* Give this message to GPG thread */
|
||||||
|
run_gpg_thread:
|
||||||
|
apdu.seq = icc_seq;
|
||||||
|
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE];
|
||||||
|
|
||||||
|
apdu.sw = 0x9000;
|
||||||
|
apdu.res_apdu_data_len = 0;
|
||||||
|
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
|
||||||
|
|
||||||
|
if (icc_data_size < 4)
|
||||||
|
{
|
||||||
|
icc_error (ICC_MSG_HEADER_SIZE + icc_data_size);
|
||||||
|
next_state = ICC_STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (icc_data_size == 4)
|
||||||
|
{ /* No Lc and No Le */
|
||||||
|
apdu.cmd_apdu_data = NULL;
|
||||||
|
apdu.cmd_apdu_data_len = 0;
|
||||||
|
apdu.expected_res_size = 0;
|
||||||
|
apdu.cmd_apdu_head[4] = 0;
|
||||||
|
}
|
||||||
|
else if (icc_data_size == 5)
|
||||||
|
{ /* No Lc but Le */
|
||||||
|
apdu.cmd_apdu_data = NULL;
|
||||||
|
apdu.cmd_apdu_data_len = 0;
|
||||||
|
apdu.expected_res_size = apdu.cmd_apdu_head[4];
|
||||||
|
if (apdu.expected_res_size == 0)
|
||||||
|
apdu.expected_res_size = 256;
|
||||||
|
apdu.cmd_apdu_head[4] = 0;
|
||||||
|
}
|
||||||
|
else if (apdu.cmd_apdu_head[4] == 0)
|
||||||
|
{ /* extended Lc or extended Le */
|
||||||
|
apdu.cmd_apdu_data = apdu.cmd_apdu_head + 7;
|
||||||
|
apdu.cmd_apdu_data_len
|
||||||
|
= (apdu.cmd_apdu_head[5] << 8) + apdu.cmd_apdu_head[6];
|
||||||
|
if (icc_data_size == 7)
|
||||||
|
{ /* No Lc but extended Le */
|
||||||
|
apdu.expected_res_size = apdu.cmd_apdu_data_len;
|
||||||
|
apdu.cmd_apdu_data_len = 0;
|
||||||
|
}
|
||||||
|
else if (icc_data_size == apdu.cmd_apdu_data_len + 7)
|
||||||
|
apdu.expected_res_size = 0;
|
||||||
|
else if (icc_data_size == apdu.cmd_apdu_data_len + 7 + 2)
|
||||||
|
{
|
||||||
|
apdu.expected_res_size
|
||||||
|
= (icc_buffer[ICC_MSG_HEADER_SIZE + 7
|
||||||
|
+ apdu.cmd_apdu_data_len] << 8)
|
||||||
|
| icc_buffer[ICC_MSG_HEADER_SIZE + 7
|
||||||
|
+ apdu.cmd_apdu_data_len + 1];
|
||||||
|
if (apdu.expected_res_size == 0)
|
||||||
|
apdu.expected_res_size = 65536;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
icc_error (ICC_MSG_HEADER_SIZE + 5);
|
||||||
|
next_state = ICC_STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* short Lc */
|
||||||
|
{
|
||||||
|
apdu.cmd_apdu_data = apdu.cmd_apdu_head + 5;
|
||||||
|
apdu.cmd_apdu_data_len = apdu.cmd_apdu_head[4];
|
||||||
|
if (icc_data_size == apdu.cmd_apdu_data_len + 5)
|
||||||
|
apdu.expected_res_size = 0;
|
||||||
|
else if (icc_data_size == apdu.cmd_apdu_data_len + 5 + 1)
|
||||||
|
{
|
||||||
|
apdu.expected_res_size
|
||||||
|
= icc_buffer[ICC_MSG_HEADER_SIZE + 5
|
||||||
|
+ apdu.cmd_apdu_data_len];
|
||||||
|
if (apdu.expected_res_size == 0)
|
||||||
|
apdu.expected_res_size = 256;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
icc_error (ICC_MSG_HEADER_SIZE + 5);
|
||||||
|
next_state = ICC_STATE_WAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
|
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
|
||||||
next_state = ICC_STATE_EXECUTE;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
@@ -523,19 +603,28 @@ icc_handle_data (void)
|
|||||||
{
|
{
|
||||||
if (icc_buffer[10] == 0x00) /* PIN verification */
|
if (icc_buffer[10] == 0x00) /* PIN verification */
|
||||||
{
|
{
|
||||||
cmd_APDU[0] = icc_buffer[25];
|
icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[25];
|
||||||
cmd_APDU[1] = icc_buffer[26];
|
icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[26];
|
||||||
cmd_APDU[2] = icc_buffer[27];
|
icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[27];
|
||||||
cmd_APDU[3] = icc_buffer[28];
|
icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[28];
|
||||||
icc_data_size = 4;
|
/**/
|
||||||
cmd_APDU[4] = 0; /* bConfirmPIN */
|
icc_buffer[ICC_MSG_HEADER_SIZE+5] = 0; /* bConfirmPIN */
|
||||||
cmd_APDU[5] = icc_buffer[17]; /* bEntryValidationCondition */
|
icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[17]; /* bEntryValidationCondition */
|
||||||
cmd_APDU[6] = icc_buffer[18]; /* bNumberMessage */
|
icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[18]; /* bNumberMessage */
|
||||||
cmd_APDU[7] = icc_buffer[19]; /* wLangId L */
|
icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[19]; /* wLangId L */
|
||||||
cmd_APDU[8] = icc_buffer[20]; /* wLangId H */
|
icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[20]; /* wLangId H */
|
||||||
cmd_APDU[9] = icc_buffer[21]; /* bMsgIndex, bMsgIndex1 */
|
icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[21]; /* bMsgIndex */
|
||||||
cmd_APDU[10] = 0; /* bMsgIndex2 */
|
|
||||||
cmd_APDU[11] = 0; /* bMsgIndex3 */
|
apdu.seq = icc_seq;
|
||||||
|
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0];
|
||||||
|
apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5];
|
||||||
|
apdu.cmd_apdu_data_len = 6;
|
||||||
|
apdu.expected_res_size = 0;
|
||||||
|
|
||||||
|
apdu.sw = 0x9000;
|
||||||
|
apdu.res_apdu_data_len = 0;
|
||||||
|
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
|
||||||
|
|
||||||
chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE);
|
chEvtSignal (gpg_thread, EV_VERIFY_CMD_AVAILABLE);
|
||||||
next_state = ICC_STATE_EXECUTE;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
@@ -547,22 +636,32 @@ icc_handle_data (void)
|
|||||||
num_msgs = 1;
|
num_msgs = 1;
|
||||||
else if (num_msgs == 0xff)
|
else if (num_msgs == 0xff)
|
||||||
num_msgs = 3;
|
num_msgs = 3;
|
||||||
cmd_APDU[0] = icc_buffer[27 + num_msgs];
|
icc_buffer[ICC_MSG_HEADER_SIZE+0] = icc_buffer[27 + num_msgs];
|
||||||
cmd_APDU[1] = icc_buffer[28 + num_msgs];
|
icc_buffer[ICC_MSG_HEADER_SIZE+1] = icc_buffer[28 + num_msgs];
|
||||||
cmd_APDU[2] = icc_buffer[29 + num_msgs];
|
icc_buffer[ICC_MSG_HEADER_SIZE+2] = icc_buffer[29 + num_msgs];
|
||||||
cmd_APDU[3] = icc_buffer[30 + num_msgs];
|
icc_buffer[ICC_MSG_HEADER_SIZE+3] = icc_buffer[30 + num_msgs];
|
||||||
icc_data_size = 4;
|
/**/
|
||||||
cmd_APDU[4] = icc_buffer[19]; /* bConfirmPIN */
|
icc_buffer[ICC_MSG_HEADER_SIZE+5] = icc_buffer[19]; /* bConfirmPIN */
|
||||||
cmd_APDU[5] = icc_buffer[20]; /* bEntryValidationCondition */
|
icc_buffer[ICC_MSG_HEADER_SIZE+6] = icc_buffer[20]; /* bEntryValidationCondition */
|
||||||
cmd_APDU[6] = icc_buffer[21]; /* bNumberMessage */
|
icc_buffer[ICC_MSG_HEADER_SIZE+7] = icc_buffer[21]; /* bNumberMessage */
|
||||||
cmd_APDU[7] = icc_buffer[22]; /* wLangId L */
|
icc_buffer[ICC_MSG_HEADER_SIZE+8] = icc_buffer[22]; /* wLangId L */
|
||||||
cmd_APDU[8] = icc_buffer[23]; /* wLangId H */
|
icc_buffer[ICC_MSG_HEADER_SIZE+9] = icc_buffer[23]; /* wLangId H */
|
||||||
cmd_APDU[9] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */
|
icc_buffer[ICC_MSG_HEADER_SIZE+10] = icc_buffer[24]; /* bMsgIndex, bMsgIndex1 */
|
||||||
cmd_APDU[10] = cmd_APDU[11] = 0;
|
|
||||||
if (num_msgs >= 2)
|
if (num_msgs >= 2)
|
||||||
cmd_APDU[10] = icc_buffer[25]; /* bMsgIndex2 */
|
icc_buffer[ICC_MSG_HEADER_SIZE+11] = icc_buffer[25]; /* bMsgIndex2 */
|
||||||
if (num_msgs == 3)
|
if (num_msgs == 3)
|
||||||
cmd_APDU[11] = icc_buffer[26]; /* bMsgIndex3 */
|
icc_buffer[ICC_MSG_HEADER_SIZE+12] = icc_buffer[26]; /* bMsgIndex3 */
|
||||||
|
|
||||||
|
apdu.seq = icc_seq;
|
||||||
|
apdu.cmd_apdu_head = &icc_buffer[ICC_MSG_HEADER_SIZE+0];
|
||||||
|
apdu.cmd_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE+5];
|
||||||
|
apdu.cmd_apdu_data_len = 5 + num_msgs;
|
||||||
|
apdu.expected_res_size = 0;
|
||||||
|
|
||||||
|
apdu.sw = 0x9000;
|
||||||
|
apdu.res_apdu_data_len = 0;
|
||||||
|
apdu.res_apdu_data = &icc_buffer[ICC_MSG_HEADER_SIZE];
|
||||||
|
|
||||||
chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE);
|
chEvtSignal (gpg_thread, EV_MODIFY_CMD_AVAILABLE);
|
||||||
next_state = ICC_STATE_EXECUTE;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
@@ -594,8 +693,7 @@ icc_handle_data (void)
|
|||||||
icc_next_p -= ICC_MSG_HEADER_SIZE;
|
icc_next_p -= ICC_MSG_HEADER_SIZE;
|
||||||
icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE;
|
icc_data_size = icc_next_p - icc_buffer - ICC_MSG_HEADER_SIZE;
|
||||||
icc_chain_p = NULL;
|
icc_chain_p = NULL;
|
||||||
next_state = ICC_STATE_EXECUTE;
|
goto run_gpg_thread;
|
||||||
chEvtSignal (gpg_thread, EV_CMD_AVAILABLE);
|
|
||||||
}
|
}
|
||||||
else /* icc_header->param == 3 is not supported. */
|
else /* icc_header->param == 3 is not supported. */
|
||||||
{
|
{
|
||||||
@@ -633,25 +731,59 @@ icc_handle_data (void)
|
|||||||
{
|
{
|
||||||
if (icc_header->param == 0x10)
|
if (icc_header->param == 0x10)
|
||||||
{
|
{
|
||||||
if (res_APDU_pointer != NULL)
|
int len = apdu.res_apdu_data_len;
|
||||||
|
|
||||||
|
if (apdu.res_apdu_data == NULL)
|
||||||
|
{ /* send last byte of 0x9000 */
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE] = 0x00;
|
||||||
|
len = 1;
|
||||||
|
}
|
||||||
|
else if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE])
|
||||||
{
|
{
|
||||||
memcpy (res_APDU, res_APDU_pointer,
|
if (apdu.res_apdu_data_len >= ICC_RESPONSE_MSG_DATA_SIZE)
|
||||||
ICC_RESPONSE_MSG_DATA_SIZE);
|
{
|
||||||
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
|
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
|
||||||
|
apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE);
|
||||||
|
apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
|
}
|
||||||
|
else if (apdu.res_apdu_data_len
|
||||||
|
<= ICC_RESPONSE_MSG_DATA_SIZE - 2)
|
||||||
|
{
|
||||||
|
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
|
||||||
|
apdu.res_apdu_data, apdu.res_apdu_data_len);
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len]
|
||||||
|
= 0x90;
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1]
|
||||||
|
= 0x00;
|
||||||
|
apdu.res_apdu_data = NULL;
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
else if (apdu.res_apdu_data_len
|
||||||
|
== ICC_RESPONSE_MSG_DATA_SIZE - 1)
|
||||||
|
{
|
||||||
|
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
|
||||||
|
apdu.res_apdu_data, apdu.res_apdu_data_len);
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len]
|
||||||
|
= 0x90;
|
||||||
|
apdu.res_apdu_data = NULL;
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memmove (res_APDU, res_APDU+ICC_RESPONSE_MSG_DATA_SIZE,
|
memmove (&icc_buffer[ICC_MSG_HEADER_SIZE],
|
||||||
res_APDU_size);
|
&icc_buffer[ICC_MSG_HEADER_SIZE]
|
||||||
|
+ICC_RESPONSE_MSG_DATA_SIZE,
|
||||||
|
apdu.res_apdu_data_len);
|
||||||
|
|
||||||
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
if (len <= ICC_RESPONSE_MSG_DATA_SIZE)
|
||||||
{
|
{
|
||||||
icc_send_data_block (res_APDU_size, 0, 0x02);
|
icc_send_data_block (len, 0, 0x02);
|
||||||
next_state = ICC_STATE_WAIT;
|
next_state = ICC_STATE_WAIT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03);
|
icc_send_data_block (ICC_RESPONSE_MSG_DATA_SIZE, 0, 0x03);
|
||||||
res_APDU_size -= ICC_RESPONSE_MSG_DATA_SIZE;
|
apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -721,26 +853,36 @@ USBthread (void *arg)
|
|||||||
else if (m == EV_EXEC_FINISHED)
|
else if (m == EV_EXEC_FINISHED)
|
||||||
if (icc_state == ICC_STATE_EXECUTE)
|
if (icc_state == ICC_STATE_EXECUTE)
|
||||||
{
|
{
|
||||||
if (res_APDU_pointer != NULL)
|
if (apdu.res_apdu_data != &icc_buffer[ICC_MSG_HEADER_SIZE])
|
||||||
{
|
{
|
||||||
memcpy (res_APDU, res_APDU_pointer, ICC_RESPONSE_MSG_DATA_SIZE);
|
/* Assume that
|
||||||
res_APDU_pointer += ICC_RESPONSE_MSG_DATA_SIZE;
|
* apdu.res_apdu_data_len > ICC_RESPONSE_MSG_DATA_SIZE
|
||||||
|
*/
|
||||||
|
memcpy (&icc_buffer[ICC_MSG_HEADER_SIZE],
|
||||||
|
apdu.res_apdu_data, ICC_RESPONSE_MSG_DATA_SIZE);
|
||||||
|
apdu.res_apdu_data += ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len] = (apdu.sw >> 8);
|
||||||
|
icc_buffer[ICC_MSG_HEADER_SIZE+apdu.res_apdu_data_len+1] = (apdu.sw & 0xff);
|
||||||
|
apdu.res_apdu_data_len += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res_APDU_size <= ICC_RESPONSE_MSG_DATA_SIZE)
|
if (apdu.res_apdu_data_len <= ICC_RESPONSE_MSG_DATA_SIZE)
|
||||||
{
|
{
|
||||||
icc_send_data_block (res_APDU_size, 0, 0);
|
icc_send_data_block (apdu.res_apdu_data_len, 0, 0);
|
||||||
icc_state = ICC_STATE_WAIT;
|
icc_state = ICC_STATE_WAIT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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;
|
apdu.res_apdu_data_len -= ICC_RESPONSE_MSG_DATA_SIZE;
|
||||||
icc_state = ICC_STATE_SEND;
|
icc_state = ICC_STATE_SEND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* XXX: error */
|
{ /* error */
|
||||||
DEBUG_INFO ("ERR07\r\n");
|
DEBUG_INFO ("ERR07\r\n");
|
||||||
}
|
}
|
||||||
else if (m == EV_TX_FINISHED)
|
else if (m == EV_TX_FINISHED)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class GnukToken(object):
|
|||||||
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
|
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
|
||||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||||
raise ValueError, "cmd_verify"
|
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||||
|
|
||||||
def cmd_write_binary(self, fileid, data, is_update):
|
def cmd_write_binary(self, fileid, data, is_update):
|
||||||
count = 0
|
count = 0
|
||||||
@@ -66,22 +66,22 @@ class GnukToken(object):
|
|||||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||||
if is_update:
|
if is_update:
|
||||||
raise ValueError, "cmd_update_binary"
|
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||||
else:
|
else:
|
||||||
raise ValueError, "cmd_write_binary"
|
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def cmd_select_openpgp(self):
|
def cmd_select_openpgp(self):
|
||||||
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
|
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
|
||||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||||
raise ValueError, "cmd_select_openpgp"
|
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||||
|
|
||||||
def cmd_get_data(self, tagh, tagl):
|
def cmd_get_data(self, tagh, tagl):
|
||||||
apdu = [0x00, 0xca, tagh, tagl]
|
apdu = [0x00, 0xca, tagh, tagl]
|
||||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||||
raise ValueError, "cmd_get_data"
|
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def compare(data_original, data_in_device):
|
def compare(data_original, data_in_device):
|
||||||
@@ -165,6 +165,5 @@ if __name__ == '__main__':
|
|||||||
data = f.read()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
print "%s: %d" % (filename, len(data))
|
print "%s: %d" % (filename, len(data))
|
||||||
data += "\x90\x00"
|
|
||||||
print "Updating card holder certificate"
|
print "Updating card holder certificate"
|
||||||
main(fileid, is_update, data, passwd)
|
main(fileid, is_update, data, passwd)
|
||||||
|
|||||||
@@ -289,6 +289,5 @@ if __name__ == '__main__':
|
|||||||
data = f.read()
|
data = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
print "%s: %d" % (filename, len(data))
|
print "%s: %d" % (filename, len(data))
|
||||||
data += "\x90\x00"
|
|
||||||
print "Updating card holder certificate"
|
print "Updating card holder certificate"
|
||||||
main(fileid, is_update, data)
|
main(fileid, is_update, data)
|
||||||
|
|||||||
Reference in New Issue
Block a user