Compare commits

...

6 Commits

Author SHA1 Message Date
NIIBE Yutaka
c98f1fe8c6 fix usb config 2012-02-02 14:17:51 +09:00
NIIBE Yutaka
14673b825b version 0.17 2012-02-02 14:09:38 +09:00
NIIBE Yutaka
6550dd5353 space removal 2012-02-02 13:15:23 +09:00
NIIBE Yutaka
3d732a7c2d command chaining change 2012-02-02 12:18:47 +09:00
NIIBE Yutaka
aff9080b35 add alignment for gnuk.ld.in, add ChangeLog entries. 2012-01-21 00:33:17 +09:00
NIIBE Yutaka
21debc0567 no ext lc and le but short APDU only 2012-01-20 18:18:23 +09:00
18 changed files with 1256 additions and 652 deletions

View File

@@ -1,3 +1,83 @@
2012-02-02 Niibe Yutaka <gniibe@fsij.org>
* Version 0.17.
* src/usb_desc.c (gnukStringSerial): Updated.
(gnukConfigDescriptor): Short APDU only.
* tool/gnuk_put_binary.py (cmd_get_response): New.
(cmd_select_openpgp, cmd_get_data): Call cmd_get_response.
2012-01-30 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (struct ccid): Add chained_cls_ins_p1_p2.
(end_cmd_apdu_head, icc_cmd_apdu_data, icc_handle_data): Add checking
CMD APDU head for command chaining.
2012-01-20 Niibe Yutaka <gniibe@fsij.org>
Short APDU only CCID driver.
* STM32_USB-FS-Device_Driver/src/usb_core.c (DataStageOut)
(DataStageIn): Use usb_lld_to_pmabuf and usb_lld_from_pmabuf.
* src/configure (CERTDO_SUPPORT): Comment fix.
* src/gnuk.h (struct adpu): expected_res_size has type uint16_t.
(MAX_CMD_APDU_DATA_SIZE, MAX_RES_APDU_DATA_SIZE): New.
(MAX_CMD_APDU_SIZE, MAX_RES_APDU_SIZE, USB_BUF_SIZE): Remove.
(icc_state_p): New.
(set_res_sw): Rename from set_res_apdu.
* src/call-rsa.c (rsa_decrypt): Use MAX_RES_APDU_DATA_SIZE.
* src/openpgp.c (set_res_sw): Rename from set_res_apdu.
* src/openpgp.h: Use set_res_sw.
* src/main.c: Handle icc_state_p.
* src/openpgp-do.c (historical_bytes): command chaining but short
APDU only.
(extended_capabilities): Change for short APDU only.
* src/usb-icc.c (USB_BUF_SIZE): Define here (was in gnuk.h).
(struct ep_in, epi_init, struct ep_out, epo_init, endpoint_out)
(endpoint_in, icc_state_p, struct ccid, APDU_STATE_WAIT_COMMAND)
(APDU_STATE_COMMAND_CHAINING, APDU_STATE_COMMAND_RECEIVED)
(APDU_STATE_RESULT, APDU_STATE_RESULT_GET_RESPONSE, ccid_reset)
(ccid_init, CMD_APDU_HEAD_SIZE, apdu_init, notify_tx, no_buf)
(set_sw1sw2, get_sw1sw2, notify_icc, end_icc_rx, end_abdata)
(end_cmd_apdu_head, end_nomore_data, end_cmd_apdu_data)
(nomore_data, INS_GET_RESPONSE, icc_cmd_apdu_data, icc_abdata)
(icc_send_data_block_0x9000, icc_send_data_block_gr, ccid): New.
(icc_data_size, icc_seq, icc_next_p, icc_chain_p, icc_tx_size)
(icc_thread, icc_state, gpg_thread, ICC_RESPONSE_MSG_DATA_SIZE):
Remove.
(EP1_IN_Callback): Rewrite using epi.
(EP2_OUT_Callback): Rewrite using epo.
(icc_prepare_receive): Rewrite using epo and struct ccid.
(ATR): Change ofr short APDU only.
(icc_error, icc_power_on, icc_send_status, icc_power_off)
(icc_send_data_block, icc_send_params, icc_handle_data)
(icc_handle_timeout, USBthread): Rewrite using struct ccid.
* src/usb_desc.c (gnukConfigDescriptor): dwFeatures: Short APDU
level, dwMaxCCIDMessageLength: 271.
* src/usb_lld.c (usb_lld_to_pmabuf, usb_lld_from_pmabuf): New.
* src/usb_lld.h (usb_lld_txcpy, void usb_lld_write) Use
usb_lld_to_pmabuf.
(usb_lld_rxcpy): Use usb_lld_from_pmabuf.
* src/stmusb.mk (usb_mem.c): Remove.
* gnuk_put_binary.py (cmd_select_openpgp): No response APDU data.
(cmd_verify, cmd_write_binary): Send short APDU.
(__main__): Remove RANDOM_NUMBER_BITS support.
Bug fix for CERTDO_SUPPORT.
* src/gnuk.ld.in: Add missing alignment for _data_pool (when no
CERTDO_SUPPORT).
2012-01-19 Niibe Yutaka <gniibe@fsij.org>
* src/usb-icc.c (icc_handle_data): Handle the case when it only

11
NEWS
View File

@@ -2,14 +2,19 @@ Gnuk NEWS - User visible changes
* Major changes in Gnuk 0.17
Released 2012-01-XX, by NIIBE Yutaka
Released 2012-02-02, by NIIBE Yutaka
** ISO 7816 SELECT command behavior is strict now
** USB CCID/ICCD protocol implementation change
Gnuk now only supports short APDU level exchange, not support.
extended APDU level exchange. Thus, Gnuk could be compatible to older
host side software implementation.
** ISO 7816 SELECT command behavior is somewhat strict now
Old implementations do not check DF name for SELECT command.
This causes some trouble when Gnuk Token is identified as if it were
different card/token. Now, DF name of OpenPGP card is checked.
** USB CCID/ICCD low level bug is fixed
** USB CCID/ICCD low-level bug is fixed
When the size of command APDU data is just 49, the lower level packet
size is 64. This is maximum size of BULK-OUT transfer packet, and
caused trouble in the past implementations. Example is setting url

23
README
View File

@@ -1,7 +1,7 @@
Gnuk - software for GnuPG USB Token
Version 0.16
2011-12-14
Version 0.17
2012-02-02
Niibe Yutaka
Free Software Initiative of Japan
@@ -104,12 +104,15 @@ Ab: That's because gnome-keyring-daemon interferes GnuPG. Type:
and at the tab of "Startup Programs", disable check buttons for
"GPG Password Agent" and "SSH Key Agent".
Qc: Do you know a good SWD debugger to connect FST-01 or something?
Ac: Perhaps, you can use a part of STM32F4 Discovery Kit as SWD
debugger. It seems that there is a free software tool for that.
Release notes
=============
This is seventeenth release of Gnuk. While it works well for specific
This is eighteenth release of Gnuk. While it works well for specific
usages and it is considered stable, it is still somewhat experimental.
Tested features are:
@@ -127,18 +130,13 @@ Tested features are:
* Changing value of password status bytes (0x00C4): forcesig
* Verify with pin pad
* Modify with pin pad
* Card holder certificate
It is known not-working well:
* For some version of kernel and libccid, --enable-debug can't
work well. Please disable DEBUG option if it doesn't work well.
* Card holder certificate
It is implemented in Gnuk side. But its large size matters
(> 1KB). Some versions of GnuPG cannot handle a data object
of large size with PC/SC backend. Specifically,
handle_transmit function in pcsc-wrapper.c uses the buffer
of size 1024-byte.
work well. Please make sure to disable DEBUG option if it
doesn't work well.
Not supported feature(s):
@@ -241,8 +239,7 @@ Gnuk is distributed with external source code.
Host Requirements
=================
For GNU/Linux, libccid version >= 1.3.11 is required.
libccid version == 1.3.9 is known not working well by the issue [r4235].
For GNU/Linux, libccid version >= 1.3.11 is recommended.
I think that it should not be requirment but the kernel version of my use is:
Linux version 2.6.32-5-686 (Debian 2.6.32-18) (ben@decadent.org.uk) (gcc version 4.3.5 (Debian 4.3.5-2) ) #1 SMP Sat Jul 24 02:27:10 UTC 2010

View File

@@ -15,6 +15,9 @@
/* Includes ------------------------------------------------------------------*/
#include "usb_lib.h"
extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, uint32_t n);
extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, uint32_t n);
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ValBit(VAR,Place) (VAR & (1 << Place))
@@ -460,7 +463,7 @@ void DataStageOut(void)
#ifdef STM32F10X_CL
OTGD_FS_PCD_EP_Read(ENDP0, Buffer, Length);
#else
PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length);
usb_lld_from_pmabuf (Buffer, GetEPRxAddr(ENDP0), Length);
#endif /* STM32F10X_CL */
}
@@ -544,7 +547,7 @@ void DataStageIn(void)
#ifdef STM32F10X_CL
OTGD_FS_PCD_EP_Write (ENDP0, DataBuffer, Length);
#else
UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
usb_lld_to_pmabuf (DataBuffer, GetEPTxAddr(ENDP0), Length);
#endif /* STM32F10X_CL */
SetEPTxCount(ENDP0, Length);

View File

@@ -167,7 +167,7 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
#endif
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
input, output, MAX_RES_APDU_SIZE - 2);
input, output, MAX_RES_APDU_DATA_SIZE);
rsa_free (&rsa_ctx);
if (r < 0)
{

2
src/configure vendored
View File

@@ -173,7 +173,7 @@ fi
# --enable-certdo option
if test "$certdo" = "yes"; then
CERTDO_DEFINE="#define CERTDO_SUPPORT 1"
echo "CERT.3 Data Object is supported (Note: it is not supported by GnuPG)"
echo "CERT.3 Data Object is supported"
else
CERTDO_DEFINE="#undef CERTDO_SUPPORT"
echo "CERT.3 Data Object is not supported"

View File

@@ -36,7 +36,7 @@ struct apdu {
uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
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 */
uint16_t expected_res_size; /* Ne, calculated by Le field */
/* response APDU */
uint16_t sw;
@@ -55,10 +55,10 @@ extern struct apdu apdu;
#define EV_VERIFY_CMD_AVAILABLE ((eventmask_t)8)
#define EV_MODIFY_CMD_AVAILABLE ((eventmask_t)16)
/* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */
/* maximum res apdu data is public key 5+9+256+2 (gpg_do_public_key) */
#define MAX_RES_APDU_SIZE ((5+9+256)+2) /* Data + status */
/* Maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
#define MAX_CMD_APDU_DATA_SIZE (22+4+128+128) /* without header */
/* Maximum res apdu data is public key 5+9+256 (gpg_do_public_key) */
#define MAX_RES_APDU_DATA_SIZE (5+9+256) /* without trailer */
#define ICC_MSG_HEADER_SIZE 10
@@ -68,13 +68,6 @@ extern struct apdu apdu;
/* USB buffer size of LL (Low-level): size of single Bulk transaction */
#define USB_LL_BUF_SIZE 64
/*
* USB buffer size of USB-ICC driver
* (Changing this, dwMaxCCIDMessageLength too !!)
*/
#define USB_BUF_SIZE ((10 + 10 + MAX_CMD_APDU_SIZE + USB_LL_BUF_SIZE - 1) \
/ USB_LL_BUF_SIZE * USB_LL_BUF_SIZE)
enum icc_state
{
ICC_STATE_START, /* Initial */
@@ -85,7 +78,7 @@ enum icc_state
ICC_STATE_SEND, /* APDU Sent Partially */
};
extern volatile enum icc_state icc_state;
extern enum icc_state *icc_state_p;
extern volatile uint8_t auth_status;
#define AC_NONE_AUTHORIZED 0x00
@@ -116,7 +109,7 @@ extern void ac_reset_admin (void);
extern void ac_fini (void);
extern void set_res_apdu (uint8_t sw1, uint8_t sw2);
extern void set_res_sw (uint8_t sw1, uint8_t sw2);
extern uint16_t data_objects_number_of_bytes;
extern void gpg_data_scan (const uint8_t *p);

View File

@@ -128,6 +128,7 @@ SECTIONS
.gnuk_flash :
{
. = ALIGN (@FLASH_PAGE_SIZE@);
_data_pool = .;
KEEP(*(.gnuk_data))
. = ALIGN(@FLASH_PAGE_SIZE@);

View File

@@ -287,6 +287,13 @@ static void display_fatal_code (void)
static void display_status_code (void)
{
enum icc_state icc_state;
if (icc_state_p == NULL)
icc_state = ICC_STATE_START;
else
icc_state = *icc_state_p;
if (icc_state == ICC_STATE_START)
{
set_led (1);

View File

@@ -77,12 +77,11 @@ uint16_t data_objects_number_of_bytes;
static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
10,
0x00,
0x31, 0x80, /* Full DF name */
0x31, 0x84, /* Full DF name, GET DATA, MF */
0x73,
0x80, 0x01, 0x40, /* Full DF name */
0x80, 0x01, 0x80, /* Full DF name */
/* 1-byte */
/* No command chaining */
/* Extended Lc and Le */
/* Command chaining, No extended Lc and Le */
0x00, 0x90, 0x00 /* Status info (no life cycle management) */
};
@@ -90,27 +89,24 @@ static const uint8_t historical_bytes[] __attribute__ ((aligned (1))) = {
static const uint8_t extended_capabilities[] __attribute__ ((aligned (1))) = {
10,
0x30, /*
* No SM, No get challenge,
* 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 get challenge (0: Get challenge not supported) */
#ifdef CERTDO_SUPPORT
0x07, 0xfe, /* max. length of cardholder certificate (2KB - 2)*/
0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
#else
0x00, 0x00,
#endif
/* Max. length of command data */
(MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff),
/* Max. length of response data */
#ifdef CERTDO_SUPPORT
0x08, 0x00, /* the case of cardholder ceritificate */
#else
(MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff),
#endif
/* Max. length of command APDU data */
0x00, 0xff,
/* Max. length of response APDU data */
0x01, 0x00,
};
/* Algorithm Attributes */

View File

@@ -67,7 +67,7 @@ select_file_TOP_result[] __attribute__ ((aligned (1))) = {
};
void
set_res_apdu (uint8_t sw1, uint8_t sw2)
set_res_sw (uint8_t sw1, uint8_t sw2)
{
apdu.sw = (sw1 << 8) | sw2;
}
@@ -510,7 +510,7 @@ cmd_select_file (void)
if (apdu.cmd_apdu_data_len != 6
|| memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
{
DEBUG_WORD (apdu.cmd_apdu_data_len);
DEBUG_SHORT (apdu.cmd_apdu_data_len);
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
GPG_NO_FILE ();
@@ -528,6 +528,7 @@ cmd_select_file (void)
res_APDU[1] = 0x12;
res_APDU[2] = 0x84; /* overwrite: DF name */
res_APDU_size += 2;
GPG_SUCCESS ();
}
}
else if (apdu.cmd_apdu_data_len == 2

View File

@@ -1,12 +1,12 @@
#define GPG_MEMORY_FAILURE() set_res_apdu (0x65, 0x81)
#define GPG_SECURITY_FAILURE() set_res_apdu (0x69, 0x82)
#define GPG_SECURITY_AUTH_BLOCKED() set_res_apdu (0x69, 0x83)
#define GPG_CONDITION_NOT_SATISFIED() set_res_apdu (0x69, 0x85)
#define GPG_COMMAND_NOT_ALLOWED() set_res_apdu (0x69, 0x86)
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_apdu (0x6a, 0x81)
#define GPG_NO_FILE() set_res_apdu (0x6a, 0x82)
#define GPG_NO_RECORD() set_res_apdu (0x6a, 0x88)
#define GPG_BAD_P0_P1() set_res_apdu (0x6b, 0x00)
#define GPG_NO_INS() set_res_apdu (0x6d, 0x00)
#define GPG_ERROR() set_res_apdu (0x6f, 0x00)
#define GPG_SUCCESS() set_res_apdu (0x90, 0x00)
#define GPG_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
#define GPG_SECURITY_FAILURE() set_res_sw (0x69, 0x82)
#define GPG_SECURITY_AUTH_BLOCKED() set_res_sw (0x69, 0x83)
#define GPG_CONDITION_NOT_SATISFIED() set_res_sw (0x69, 0x85)
#define GPG_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86)
#define GPG_FUNCTION_NOT_SUPPORTED() set_res_sw (0x6a, 0x81)
#define GPG_NO_FILE() set_res_sw (0x6a, 0x82)
#define GPG_NO_RECORD() set_res_sw (0x6a, 0x88)
#define GPG_BAD_P0_P1() set_res_sw (0x6b, 0x00)
#define GPG_NO_INS() set_res_sw (0x6d, 0x00)
#define GPG_ERROR() set_res_sw (0x6f, 0x00)
#define GPG_SUCCESS() set_res_sw (0x90, 0x00)

View File

@@ -3,5 +3,5 @@ STMUSBSRCDIR = $(STMUSBDIR)/src
STMUSBINCDIR = $(STMUSBDIR)/inc
STMUSBSRC= \
$(STMUSBSRCDIR)/usb_init.c $(STMUSBSRCDIR)/usb_int.c \
$(STMUSBSRCDIR)/usb_mem.c $(STMUSBSRCDIR)/usb_core.c \
$(STMUSBSRCDIR)/usb_core.c \
$(STMUSBSRCDIR)/usb_regs.c

File diff suppressed because it is too large Load Diff

View File

@@ -101,8 +101,8 @@ static const uint8_t gnukConfigDescriptor[] = {
* It is different now for better interaction to GPG's in-stock
* ccid-driver.
*/
0x42, 0x08, 0x04, 0x00, /* dwFeatures (not ICCD):
* Short and extended APDU level: 0x40000 *
0x42, 0x08, 0x02, 0x00, /* dwFeatures (not ICCD):
* Short APDU level : 0x20000 *
* (what? means ICCD?) : 0x00800 *
* Automatic IFSD : 0x00400
* NAD value other than 0x00 : 0x00200
@@ -115,7 +115,7 @@ static const uint8_t gnukConfigDescriptor[] = {
* Auto activaction of ICC : 0x00004
* Automatic conf. based on ATR : 0x00002 g
*/
0x40, 0x01, 0, 0, /* dwMaxCCIDMessageLength */
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
0xff, /* bClassGetResponse: */
0xff, /* bClassEnvelope: */
0, 0, /* wLCDLayout: FIXED VALUE */
@@ -275,7 +275,7 @@ static const uint8_t gnukStringProduct[] = {
const uint8_t gnukStringSerial[] = {
13*2+2, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0', 0, '.', 0, '1', 0, '6', 0, /* Version number of Gnuk */
'0', 0, '.', 0, '1', 0, '7', 0, /* Version number of Gnuk */
'-', 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

View File

@@ -27,3 +27,76 @@ void usb_lld_init (void) {
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB1RSTR = 0;
}
void usb_lld_to_pmabuf (const void *src, uint16_t wPMABufAddr, size_t n)
{
const uint8_t *s = (const uint8_t *)src;
uint16_t *p;
uint16_t w;
if (n == 0)
return;
if ((wPMABufAddr & 1))
{
p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2);
w = *p;
w = (w & 0xff) | (*s++) << 8;
*p = w;
p += 2;
n--;
}
else
p = (uint16_t *)(PMAAddr + wPMABufAddr * 2);
while (n >= 2)
{
w = *s++;
w |= (*s++) << 8;
*p = w;
p += 2;
n -= 2;
}
if (n > 0)
{
w = *s;
*p = w;
}
}
void usb_lld_from_pmabuf (void *dst, uint16_t wPMABufAddr, size_t n)
{
uint8_t *d = (uint8_t *)dst;
uint16_t *p;
uint16_t w;
if (n == 0)
return;
if ((wPMABufAddr & 1))
{
p = (uint16_t *)(PMAAddr + (wPMABufAddr - 1) * 2);
w = *p;
*d++ = (w >> 8);
p += 2;
n--;
}
else
p = (uint16_t *)(PMAAddr + wPMABufAddr * 2);
while (n >= 2)
{
w = *p;
*d++ = (w & 0xff);
*d++ = (w >> 8);
p += 2;
n -= 2;
}
if (n > 0)
{
w = *p;
*d = (w & 0xff);
}
}

View File

@@ -1,6 +1,9 @@
#define STM32_USB_IRQ_PRIORITY 11
void usb_lld_init (void);
extern void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n);
extern void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n);
extern inline void usb_lld_stall_tx (int ep_num)
{
SetEPTxStatus (ep_num, EP_TX_STALL);
@@ -16,10 +19,10 @@ extern inline int usb_lld_tx_data_len (int ep_num)
return GetEPTxCount (ep_num);
}
extern inline void usb_lld_txcpy (const uint8_t *src,
extern inline void usb_lld_txcpy (const void *src,
int ep_num, int offset, size_t len)
{
UserToPMABufferCopy ((uint8_t *)src, GetEPTxAddr (ep_num) + offset, len);
usb_lld_to_pmabuf (src, GetEPTxAddr (ep_num) + offset, len);
}
extern inline void usb_lld_tx_enable (int ep_num, size_t len)
@@ -28,9 +31,9 @@ extern inline void usb_lld_tx_enable (int ep_num, size_t len)
SetEPTxValid (ep_num);
}
extern inline void usb_lld_write (uint8_t ep_num, void *buf, size_t len)
extern inline void usb_lld_write (uint8_t ep_num, const void *buf, size_t len)
{
UserToPMABufferCopy (buf, GetEPTxAddr (ep_num), len);
usb_lld_to_pmabuf (buf, GetEPTxAddr (ep_num), len);
SetEPTxCount (ep_num, len);
SetEPTxValid (ep_num);
}
@@ -48,5 +51,5 @@ extern inline int usb_lld_rx_data_len (int ep_num)
extern inline void usb_lld_rxcpy (uint8_t *dst,
int ep_num, int offset, size_t len)
{
PMAToUserBufferCopy (dst, GetEPRxAddr (ep_num) + offset, len);
usb_lld_from_pmabuf (dst, GetEPRxAddr (ep_num) + offset, len);
}

View File

@@ -43,8 +43,15 @@ class GnukToken(object):
cardservice = cardrequest.waitforcard()
self.connection = cardservice.connection
def cmd_get_response(self, expected_len):
apdu = [0x00, 0xc0, 0x00, 0x00, expected_len ]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
def cmd_verify(self, who, passwd):
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
apdu = [0x00, 0x20, 0x00, 0x80+who, len(passwd)] + s2l(passwd)
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
@@ -59,10 +66,20 @@ class GnukToken(object):
while count*256 < data_len:
if count == 0:
d = data[:256]
apdu = [0x00, ins, 0x80+fileid, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d)
if len(d) <= 255:
apdu = [0x00, ins, 0x80+fileid, 0x00, len(d) ] + s2l(d)
else:
apdu0 = [0x10, ins, 0x80+fileid, 0x00, 255 ] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
else:
d = data[256*count:256*(count+1)]
apdu = [0x00, ins, count, 0x00, 0, len(d)>>8, len(d)&0xff] + s2l(d)
if len(d) <= 255:
apdu = [0x00, ins, count, 0x00, len(d) ] + s2l(d)
else:
apdu0 = [0x10, ins, count, 0x00, 255 ] + s2l(d[:255])
response, sw1, sw2 = self.connection.transmit(apdu0)
apdu = [0x00, ins, 0x80+fileid, 0x00, 1 ] + s2l(d[255:])
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if is_update:
@@ -72,15 +89,19 @@ class GnukToken(object):
count += 1
def cmd_select_openpgp(self):
apdu = [0x00, 0xa4, 0x04, 0x00, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
apdu = [0x00, 0xa4, 0x04, 0x0c, 6, 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01 ]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
def cmd_get_data(self, tagh, tagl):
apdu = [0x00, 0xca, tagh, tagl]
response, sw1, sw2 = self.connection.transmit(apdu)
if not (sw1 == 0x90 and sw2 == 0x00):
if sw1 == 0x61:
response = self.cmd_get_response(sw2)
elif not (sw1 == 0x90 and sw2 == 0x00):
raise ValueError, ("%02x%02x" % (sw1, sw2))
return response
@@ -146,18 +167,6 @@ if __name__ == '__main__':
exit(1)
print "Writing serial number"
data = binascii.unhexlify(serial_data_hex)
elif sys.argv[1] == '-r':
fileid = 1 # Random number bits
if len(sys.argv) == 3:
filename = sys.argv[2]
f = open(filename)
else:
filename = stdin
f = sys.stdin
data = f.read()
f.close()
print "%s: %d" % (filename, len(data))
print "Updating random bits"
else:
fileid = 0 # Card holder certificate
filename = sys.argv[1]