Compare commits
22 Commits
extended-a
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c98f1fe8c6 | ||
|
|
14673b825b | ||
|
|
6550dd5353 | ||
|
|
3d732a7c2d | ||
|
|
aff9080b35 | ||
|
|
21debc0567 | ||
|
|
f92ee76db5 | ||
|
|
87e4fd50c1 | ||
|
|
cbb2c6aab5 | ||
|
|
00541d7627 | ||
|
|
27277e56ee | ||
|
|
4ee4417fb5 | ||
|
|
11351c8cae | ||
|
|
6abac73354 | ||
|
|
41537cc827 | ||
|
|
a4e0e67340 | ||
|
|
58f8470446 | ||
|
|
885e1c4ecb | ||
|
|
2c111d0b20 | ||
|
|
35a62354ae | ||
|
|
18f3e72c32 | ||
|
|
121df70044 |
160
ChangeLog
160
ChangeLog
@@ -1,5 +1,165 @@
|
||||
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
|
||||
sends 0x90 and 0x00 correctly.
|
||||
|
||||
* src/openpgp-do.c (gpg_do_get_data): Fix res_apdu_data_len.
|
||||
|
||||
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>
|
||||
|
||||
Adopt new USB API.
|
||||
* src/usb_msc.c (usb_start_transmit): Use usb_lld_write.
|
||||
(EP6_IN_Callback): Use usb_lld_tx_data_len and usb_lld_write.
|
||||
(usb_start_receive): Use usb_lld_rx_enable.
|
||||
(EP7_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy
|
||||
and usb_lld_rx_enable
|
||||
(msc_handle_command): Use usb_lld_stall_rx and usb_lld_stall_tx.
|
||||
|
||||
* src/usb_lld.h (usb_lld_stall_tx, usb_lld_stall_rx)
|
||||
(usb_lld_tx_data_len): New.
|
||||
|
||||
* src/main.c (STDOUTthread): Use usb_lld_write.
|
||||
|
||||
* src/usb-icc.c (EP1_IN_Callback, icc_error, icc_power_on)
|
||||
(icc_send_status, icc_send_data_block, icc_send_params): Use
|
||||
usb_lld_write (was: USB_SIL_Write).
|
||||
(EP2_OUT_Callback): Use usb_lld_rx_data_len, usb_lld_rxcpy,
|
||||
and usb_lld_rx_enable (was: USB_SIL_Read and SetEPRxValid).
|
||||
(icc_prepare_receive): Use usb_lld_rx_enable.
|
||||
|
||||
* src/stmusb.mk (STMUSBSRC): Dont' include usb_sil.c.
|
||||
|
||||
* src/usb_lld.h (usb_lld_txcpy, usb_lld_tx_enable)
|
||||
(usb_lld_write, usb_lld_rx_enable, usb_lld_rx_data_len)
|
||||
(usb_lld_rxcpy): New.
|
||||
|
||||
* src/usb_prop.c (SetEPRxCount_allocated_size): Fix the
|
||||
implementation. (ST's SetEPRxCount is actually meant to
|
||||
setup allocated size, which is confusing).
|
||||
(gnuk_device_init): Don't call USB_SIL_Init.
|
||||
|
||||
2012-01-10 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (GPGthread): Allow INS_RESET_RETRY_COUNTER and
|
||||
INS_PUT_DATA for pinentry targets.
|
||||
|
||||
2012-01-05 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp.c (cmd_select_file): Check DF name.
|
||||
|
||||
* tool/pinpadtest.py: Rename from pinpad-test.py.
|
||||
|
||||
2011-12-28 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_prop.c (SetEPRxCount_allocated_size): New.
|
||||
(gnuk_device_reset): Use SetEPRxCount_allocated_size.
|
||||
* src/usb_msc.c (usb_start_receive): Don't set RxCount register
|
||||
here.
|
||||
* STM32_USB-FS-Device_Driver/src/usb_core.c (Standard_ClearFeature)
|
||||
(Post0_Process): Don't need to set RxCount register.
|
||||
|
||||
* src/usb_prop.c (msc_lun_info) [PINPAD_DND_SUPPORT]: ifdef-out.
|
||||
|
||||
* src/usb-icc.c (EP2_OUT_Callback): Fix apdu size == 49 bug,
|
||||
|
||||
22
NEWS
22
NEWS
@@ -2,15 +2,25 @@ 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
|
||||
|
||||
** USB CCID/ICCD low level bug is fixed
|
||||
** 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
|
||||
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
|
||||
(0x5f50) as: http://www.gniibe.org/adpu-string-size-is-just-49
|
||||
This is because the past implementations expect ZLP (zero size
|
||||
packet). Now, it has been fixed. You can use any size.
|
||||
This is because the past implementations expect ZLP (zero length
|
||||
packet). Now, it has been fixed. You can use any size of string.
|
||||
|
||||
** CERT.3 Data Object (0x7f21) is now optional
|
||||
As there's no valid use case for this data object and it does not
|
||||
@@ -22,8 +32,8 @@ configure time.
|
||||
Now, user can cancel pin input by unmounting device before finishing
|
||||
DnD.
|
||||
|
||||
** New tool: pinpad-test.py
|
||||
The tool pinpad-test.py is PC/SC test tool for pinentry of pinpad with
|
||||
** New tool: pinpadtest.py
|
||||
The tool pinpadtest.py is PC/SC test tool for pinentry of pinpad with
|
||||
OpenPGP card v2.
|
||||
|
||||
|
||||
|
||||
23
README
23
README
@@ -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
|
||||
|
||||
@@ -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))
|
||||
@@ -308,7 +311,6 @@ RESULT Standard_ClearFeature(void)
|
||||
if (Related_Endpoint == ENDP0)
|
||||
{
|
||||
/* After clear the STALL, enable the default endpoint receiver */
|
||||
SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize);
|
||||
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
|
||||
}
|
||||
else
|
||||
@@ -461,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 */
|
||||
}
|
||||
|
||||
@@ -545,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);
|
||||
@@ -1019,8 +1021,6 @@ uint8_t Post0_Process(void)
|
||||
USB_OTG_EP *ep;
|
||||
#endif /* STM32F10X_CL */
|
||||
|
||||
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
|
||||
|
||||
if (pInformation->ControlState == STALLED)
|
||||
{
|
||||
vSetEPRxStatus(EP_RX_STALL);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "openpgp.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
@@ -84,10 +85,9 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
|
||||
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
|
||||
res_APDU_size = RSA_SIGNATURE_LENGTH + 2;
|
||||
res_APDU_size = RSA_SIGNATURE_LENGTH;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
@@ -177,10 +177,9 @@ rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
||||
}
|
||||
else
|
||||
{
|
||||
res_APDU[output_len] = 0x90;
|
||||
res_APDU[output_len+1] = 0x00;
|
||||
res_APDU_size = output_len + 2;
|
||||
res_APDU_size = output_len;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
GPG_SUCCESS ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
2
src/configure
vendored
2
src/configure
vendored
@@ -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"
|
||||
|
||||
68
src/gnuk.h
68
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;
|
||||
#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);
|
||||
|
||||
|
||||
/*
|
||||
* We declare some of libc functions here, because we will
|
||||
* remove dependency on libc in future.
|
||||
* Application layer <-> CCID layer data structure
|
||||
*/
|
||||
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);
|
||||
struct apdu {
|
||||
uint8_t seq;
|
||||
|
||||
/* command 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 */
|
||||
uint16_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 */
|
||||
|
||||
@@ -31,31 +55,19 @@ extern void *memmove(void *dest, const void *src, size_t n);
|
||||
#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
|
||||
|
||||
#define cmd_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
|
||||
#define res_APDU (&icc_buffer[ICC_MSG_HEADER_SIZE])
|
||||
extern int icc_data_size;
|
||||
#define cmd_APDU_size icc_data_size
|
||||
extern int res_APDU_size;
|
||||
extern const uint8_t *res_APDU_pointer;
|
||||
#define res_APDU apdu.res_apdu_data
|
||||
#define res_APDU_size apdu.res_apdu_data_len
|
||||
|
||||
/* 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)
|
||||
extern uint8_t icc_buffer[USB_BUF_SIZE];
|
||||
|
||||
enum icc_state
|
||||
{
|
||||
ICC_STATE_START, /* Initial */
|
||||
@@ -66,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
|
||||
@@ -97,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);
|
||||
|
||||
@@ -128,6 +128,7 @@ SECTIONS
|
||||
|
||||
.gnuk_flash :
|
||||
{
|
||||
. = ALIGN (@FLASH_PAGE_SIZE@);
|
||||
_data_pool = .;
|
||||
KEEP(*(.gnuk_data))
|
||||
. = ALIGN(@FLASH_PAGE_SIZE@);
|
||||
|
||||
10
src/main.c
10
src/main.c
@@ -132,8 +132,7 @@ STDOUTthread (void *arg)
|
||||
|
||||
chEvtClear (EV_TX_READY);
|
||||
|
||||
USB_SIL_Write (EP3_IN, buffer_in, count_in);
|
||||
SetEPTxValid (ENDP3);
|
||||
usb_lld_write (ENDP3, buffer_in, count_in);
|
||||
|
||||
chEvtWaitOne (EV_TX_READY);
|
||||
}
|
||||
@@ -288,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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -417,10 +413,12 @@ do_kgtime_all (uint16_t tag, int with_tag)
|
||||
}
|
||||
|
||||
const uint8_t openpgpcard_aid[] = {
|
||||
0xd2, 0x76, 0x00, 0x01, 0x24, 0x01,
|
||||
0x02, 0x00, /* Version 2.0 */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
|
||||
0xd2, 0x76, /* D: National, 276: DEU ISO 3166-1 */
|
||||
0x00, 0x01, 0x24, /* Registered Application Provider Identifier */
|
||||
0x01, /* Application: OpenPGPcard */
|
||||
0x02, 0x00, /* Version 2.0 */
|
||||
/* v. id */ /* serial number */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* To be overwritten */
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1248,16 +1246,16 @@ gpg_do_get_data (uint16_t tag, int with_tag)
|
||||
#if defined(CERTDO_SUPPORT)
|
||||
if (tag == GPG_DO_CH_CERTIFICATE)
|
||||
{
|
||||
res_APDU_pointer = &ch_certificate_start;
|
||||
res_APDU_size = ((res_APDU_pointer[2] << 8) | res_APDU_pointer[3]);
|
||||
if (res_APDU_size == 0xffff)
|
||||
apdu.res_apdu_data = &ch_certificate_start;
|
||||
apdu.res_apdu_data_len = ((apdu.res_apdu_data[2] << 8) | apdu.res_apdu_data[3]);
|
||||
if (apdu.res_apdu_data_len == 0xffff)
|
||||
{
|
||||
res_APDU_pointer = NULL;
|
||||
apdu.res_apdu_data_len = 0;
|
||||
GPG_NO_RECORD ();
|
||||
}
|
||||
else
|
||||
/* Add length of (tag+len) and status word (0x9000) at the end */
|
||||
res_APDU_size += 4 + 2;
|
||||
/* Add length of (tag+len) */
|
||||
apdu.res_apdu_data_len += 4;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1276,9 +1274,8 @@ gpg_do_get_data (uint16_t tag, int with_tag)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else
|
||||
{
|
||||
*res_p++ = 0x90;
|
||||
*res_p++ = 0x00;
|
||||
res_APDU_size = res_p - res_APDU;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1412,8 +1409,8 @@ gpg_do_public_key (uint8_t kk_byte)
|
||||
*res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01;
|
||||
|
||||
/* Success */
|
||||
*res_p++ = 0x90; *res_p++ = 0x00;
|
||||
res_APDU_size = res_p - res_APDU;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
|
||||
238
src/openpgp.c
238
src/openpgp.c
@@ -29,6 +29,11 @@
|
||||
#include "polarssl/config.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_CHANGE_REFERENCE_DATA 0x24
|
||||
#define INS_PSO 0x2a
|
||||
@@ -62,11 +67,9 @@ 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)
|
||||
{
|
||||
res_APDU_size = 2;
|
||||
res_APDU[0] = sw1;
|
||||
res_APDU[1] = sw2;
|
||||
apdu.sw = (sw1 << 8) | sw2;
|
||||
}
|
||||
|
||||
#define FILE_NONE 0
|
||||
@@ -117,22 +120,15 @@ static void
|
||||
cmd_verify (void)
|
||||
{
|
||||
int len;
|
||||
uint8_t p2 = cmd_APDU[3];
|
||||
uint8_t p2 = P2 (apdu);
|
||||
int r;
|
||||
int data_start = 5;
|
||||
const uint8_t *pw;
|
||||
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
DEBUG_BYTE (p2);
|
||||
|
||||
len = cmd_APDU[4];
|
||||
if (len == 0) /* extended length */
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
data_start = 7;
|
||||
}
|
||||
|
||||
pw = &cmd_APDU[data_start];
|
||||
len = apdu.cmd_apdu_data_len;
|
||||
pw = apdu.cmd_apdu_data;
|
||||
|
||||
if (p2 == 0x81)
|
||||
r = verify_pso_cds (pw, len);
|
||||
@@ -213,8 +209,8 @@ cmd_change_password (void)
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
uint8_t p1 = cmd_APDU[2]; /* 0: change (old+new), 1: exchange (new) */
|
||||
uint8_t p2 = cmd_APDU[3];
|
||||
uint8_t p1 = P1 (apdu); /* 0: change (old+new), 1: exchange (new) */
|
||||
uint8_t p2 = P2 (apdu);
|
||||
int len;
|
||||
const uint8_t *pw;
|
||||
const uint8_t *newpw;
|
||||
@@ -225,13 +221,8 @@ cmd_change_password (void)
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
DEBUG_BYTE (who);
|
||||
|
||||
len = cmd_APDU[4];
|
||||
pw = &cmd_APDU[5];
|
||||
if (len == 0) /* extended length */
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
pw += 2;
|
||||
}
|
||||
len = apdu.cmd_apdu_data_len;
|
||||
pw = apdu.cmd_apdu_data;
|
||||
|
||||
if (p1 != 0)
|
||||
{
|
||||
@@ -329,7 +320,7 @@ cmd_change_password (void)
|
||||
static void
|
||||
cmd_reset_user_password (void)
|
||||
{
|
||||
uint8_t p1 = cmd_APDU[2];
|
||||
uint8_t p1 = P1 (apdu);
|
||||
int len;
|
||||
const uint8_t *pw;
|
||||
const uint8_t *newpw;
|
||||
@@ -341,13 +332,8 @@ cmd_reset_user_password (void)
|
||||
DEBUG_INFO ("Reset PW1\r\n");
|
||||
DEBUG_BYTE (p1);
|
||||
|
||||
len = cmd_APDU[4];
|
||||
pw = &cmd_APDU[5];
|
||||
if (len == 0) /* extended length */
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
pw += 2;
|
||||
}
|
||||
len = apdu.cmd_apdu_data_len;
|
||||
pw = apdu.cmd_apdu_data;
|
||||
|
||||
if (p1 == 0x00) /* by User with Reseting Code */
|
||||
{
|
||||
@@ -469,17 +455,9 @@ cmd_put_data (void)
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
GPG_NO_RECORD();
|
||||
|
||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||
data = &cmd_APDU[5];
|
||||
|
||||
len = cmd_APDU_size - 5;
|
||||
if (len >= 256)
|
||||
/* extended Lc */
|
||||
{
|
||||
data += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
tag = ((P1 (apdu)<<8) | P2 (apdu));
|
||||
len = apdu.cmd_apdu_data_len;
|
||||
data = apdu.cmd_apdu_data;
|
||||
gpg_do_put_data (tag, data, len);
|
||||
}
|
||||
|
||||
@@ -487,16 +465,11 @@ static void
|
||||
cmd_pgp_gakp (void)
|
||||
{
|
||||
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 */
|
||||
{
|
||||
if (cmd_APDU[4] == 0)
|
||||
gpg_do_public_key (cmd_APDU[7]);
|
||||
else
|
||||
gpg_do_public_key (cmd_APDU[5]);
|
||||
}
|
||||
gpg_do_public_key (apdu.cmd_apdu_data[0]);
|
||||
else
|
||||
{ /* Generate key pair */
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
@@ -514,7 +487,7 @@ cmd_read_binary (void)
|
||||
|
||||
if (file_selection == FILE_EF_SERIAL)
|
||||
{
|
||||
if (cmd_APDU[3] >= 6)
|
||||
if (P2 (apdu) >= 6)
|
||||
GPG_BAD_P0_P1 ();
|
||||
else
|
||||
{
|
||||
@@ -529,16 +502,23 @@ cmd_read_binary (void)
|
||||
static void
|
||||
cmd_select_file (void)
|
||||
{
|
||||
if (cmd_APDU[2] == 4) /* Selection by DF name: it must be OpenPGP card */
|
||||
if (P1 (apdu) == 4) /* Selection by DF name */
|
||||
{
|
||||
DEBUG_INFO (" - select DF by name\r\n");
|
||||
|
||||
/*
|
||||
* P2 == 0, LC=6, name = D2 76 00 01 24 01
|
||||
*/
|
||||
/* name = D2 76 00 01 24 01 */
|
||||
if (apdu.cmd_apdu_data_len != 6
|
||||
|| memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
|
||||
{
|
||||
DEBUG_SHORT (apdu.cmd_apdu_data_len);
|
||||
DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
||||
|
||||
GPG_NO_FILE ();
|
||||
return;
|
||||
}
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
if (cmd_APDU[3] == 0x0c) /* No FCI */
|
||||
if ((P2 (apdu) & 0x0c) == 0x0c) /* No FCI */
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
{
|
||||
@@ -548,10 +528,11 @@ cmd_select_file (void)
|
||||
res_APDU[1] = 0x12;
|
||||
res_APDU[2] = 0x84; /* overwrite: DF name */
|
||||
res_APDU_size += 2;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02)
|
||||
else if (apdu.cmd_apdu_data_len == 2
|
||||
&& apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02)
|
||||
{
|
||||
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
||||
/*
|
||||
@@ -560,11 +541,11 @@ cmd_select_file (void)
|
||||
GPG_SUCCESS ();
|
||||
file_selection = FILE_EF_SERIAL;
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00)
|
||||
else if (apdu.cmd_apdu_data_len == 2
|
||||
&& apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
|
||||
{
|
||||
DEBUG_INFO (" - select ROOT MF\r\n");
|
||||
if (cmd_APDU[3] == 0x0c)
|
||||
if (P2 (apdu) == 0x0c)
|
||||
{
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
@@ -572,12 +553,11 @@ cmd_select_file (void)
|
||||
{
|
||||
int len = sizeof (select_file_TOP_result);
|
||||
|
||||
res_APDU_size = 2 + len;
|
||||
res_APDU_size = len;
|
||||
memcpy (res_APDU, select_file_TOP_result, len);
|
||||
res_APDU[2] = (data_objects_number_of_bytes & 0xff);
|
||||
res_APDU[3] = (data_objects_number_of_bytes >> 8);
|
||||
res_APDU[len] = 0x90;
|
||||
res_APDU[len+1] = 0x00;
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
file_selection = FILE_MF;
|
||||
@@ -595,7 +575,7 @@ cmd_select_file (void)
|
||||
static 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");
|
||||
|
||||
@@ -608,21 +588,14 @@ cmd_get_data (void)
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
int len = cmd_APDU[4];
|
||||
int data_start = 5;
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
data_start = 7;
|
||||
}
|
||||
|
||||
DEBUG_INFO (" - PSO: ");
|
||||
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))
|
||||
{
|
||||
@@ -631,24 +604,24 @@ cmd_pso (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_APDU_size != 7 + 34 + 2 /* MD5 */
|
||||
/* Header (with Extended Lc)=7, size of digestInfo, and Le=2-byte */
|
||||
&& cmd_APDU_size != 7 + 35 + 2 /* SHA1 / RIPEMD-160 */
|
||||
&& cmd_APDU_size != 7 + 47 + 2 /* SHA224 */
|
||||
&& cmd_APDU_size != 7 + 51 + 2 /* SHA256 */
|
||||
&& cmd_APDU_size != 7 + 67 + 2 /* SHA384 */
|
||||
&& cmd_APDU_size != 7 + 83 + 2) /* SHA512 */
|
||||
/* Check size of digestInfo */
|
||||
if (len != 34 /* MD5 */
|
||||
&& len != 35 /* SHA1 / RIPEMD-160 */
|
||||
&& len != 47 /* SHA224 */
|
||||
&& len != 51 /* SHA256 */
|
||||
&& len != 67 /* SHA384 */
|
||||
&& len != 83) /* SHA512 */
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
DEBUG_SHORT (cmd_APDU_size);
|
||||
DEBUG_SHORT (len);
|
||||
GPG_ERROR ();
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SHORT (len); /* Should be cmd_APDU_size - 8 [- 1] */
|
||||
DEBUG_SHORT (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]);
|
||||
if (r < 0)
|
||||
{
|
||||
@@ -660,7 +633,7 @@ cmd_pso (void)
|
||||
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_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
|
||||
@@ -673,9 +646,8 @@ cmd_pso (void)
|
||||
}
|
||||
|
||||
/* Skip padding 0x00 */
|
||||
data_start++;
|
||||
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]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
@@ -683,9 +655,9 @@ cmd_pso (void)
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[2]);
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[3]);
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
@@ -695,19 +667,12 @@ cmd_pso (void)
|
||||
static void
|
||||
cmd_internal_authenticate (void)
|
||||
{
|
||||
int len = cmd_APDU[4];
|
||||
int data_start = 5;
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
int r;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
data_start = 7;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -718,7 +683,7 @@ cmd_internal_authenticate (void)
|
||||
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]);
|
||||
if (r < 0)
|
||||
GPG_ERROR ();
|
||||
@@ -726,9 +691,9 @@ cmd_internal_authenticate (void)
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[2]);
|
||||
DEBUG_BYTE (P1 (apdu));
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[3]);
|
||||
DEBUG_BYTE (P2 (apdu));
|
||||
GPG_ERROR ();
|
||||
}
|
||||
|
||||
@@ -739,17 +704,10 @@ cmd_internal_authenticate (void)
|
||||
static void
|
||||
cmd_update_binary (void)
|
||||
{
|
||||
int len = cmd_APDU[4];
|
||||
int data_start = 5;
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
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 (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
@@ -759,10 +717,10 @@ cmd_update_binary (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd_APDU[2] & 0x80))
|
||||
if ((cmd_APDU[2] & 0x7f) <= FILEID_RANDOM)
|
||||
if ((P1 (apdu) & 0x80))
|
||||
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);
|
||||
if (r < 0)
|
||||
{
|
||||
@@ -787,14 +745,14 @@ cmd_update_binary (void)
|
||||
return;
|
||||
}
|
||||
|
||||
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
|
||||
offset = (P1 (apdu) << 8) | P2 (apdu);
|
||||
}
|
||||
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_SHORT (offset);
|
||||
|
||||
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)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
@@ -810,17 +768,10 @@ cmd_update_binary (void)
|
||||
static void
|
||||
cmd_write_binary (void)
|
||||
{
|
||||
int len = cmd_APDU[4];
|
||||
int data_start = 5;
|
||||
int len = apdu.cmd_apdu_data_len;
|
||||
uint16_t offset;
|
||||
int r;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
data_start = 7;
|
||||
}
|
||||
|
||||
DEBUG_INFO (" - WRITE BINARY\r\n");
|
||||
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
@@ -830,10 +781,10 @@ cmd_write_binary (void)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd_APDU[2] & 0x80))
|
||||
if ((cmd_APDU[2] & 0x7f) <= FILEID_SERIAL_NO)
|
||||
if ((P1 (apdu) & 0x80))
|
||||
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;
|
||||
}
|
||||
else
|
||||
@@ -851,14 +802,14 @@ cmd_write_binary (void)
|
||||
return;
|
||||
}
|
||||
|
||||
offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
|
||||
offset = (P1 (apdu) << 8) | P2 (apdu);
|
||||
}
|
||||
|
||||
DEBUG_SHORT (len);
|
||||
DEBUG_SHORT (offset);
|
||||
|
||||
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)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
@@ -898,7 +849,7 @@ static void
|
||||
process_command_apdu (void)
|
||||
{
|
||||
int i;
|
||||
uint8_t cmd = cmd_APDU[1];
|
||||
uint8_t cmd = INS (apdu);
|
||||
|
||||
for (i = 0; i < NUM_CMDS; i++)
|
||||
if (cmds[i].command == cmd)
|
||||
@@ -932,12 +883,10 @@ GPGthread (void *arg)
|
||||
|
||||
DEBUG_INFO ("GPG!: ");
|
||||
|
||||
res_APDU_pointer = NULL;
|
||||
|
||||
if (m == EV_VERIFY_CMD_AVAILABLE)
|
||||
{
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
if (cmd_APDU[1] != INS_VERIFY)
|
||||
if (INS (apdu) != INS_VERIFY)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
goto done;
|
||||
@@ -949,9 +898,8 @@ GPGthread (void *arg)
|
||||
GPG_ERROR ();
|
||||
goto done;
|
||||
}
|
||||
memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
|
||||
cmd_APDU[4] = pw_len;
|
||||
icc_data_size = 5 + pw_len;
|
||||
memcpy (apdu.cmd_apdu_data, pin_input_buffer, pw_len);
|
||||
apdu.cmd_apdu_data_len = pw_len;
|
||||
#else
|
||||
GPG_ERROR ();
|
||||
goto done;
|
||||
@@ -960,10 +908,12 @@ GPGthread (void *arg)
|
||||
else if (m == EV_MODIFY_CMD_AVAILABLE)
|
||||
{
|
||||
#if defined(PINPAD_SUPPORT)
|
||||
uint8_t bConfirmPIN = cmd_APDU[4];
|
||||
uint8_t *p = &cmd_APDU[5];
|
||||
uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
|
||||
uint8_t *p = apdu.cmd_apdu_data;
|
||||
|
||||
if (cmd_APDU[1] != INS_CHANGE_REFERENCE_DATA)
|
||||
if (INS (apdu) != INS_CHANGE_REFERENCE_DATA
|
||||
&& INS (apdu) != INS_RESET_RETRY_COUNTER
|
||||
&& INS (apdu) != INS_PUT_DATA)
|
||||
{
|
||||
GPG_CONDITION_NOT_SATISFIED ();
|
||||
goto done;
|
||||
@@ -1007,8 +957,7 @@ GPGthread (void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
len = cmd_APDU[4] = pw_len + newpw_len;
|
||||
icc_data_size = 5 + len;
|
||||
apdu.cmd_apdu_data_len = pw_len + newpw_len;
|
||||
#else
|
||||
GPG_ERROR ();
|
||||
goto done;
|
||||
@@ -1017,12 +966,9 @@ GPGthread (void *arg)
|
||||
else if (m == EV_NOP)
|
||||
continue;
|
||||
|
||||
if (icc_data_size != 0)
|
||||
{
|
||||
process_command_apdu ();
|
||||
done:
|
||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||
}
|
||||
process_command_apdu ();
|
||||
done:
|
||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||
}
|
||||
|
||||
gpg_fini ();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
STMUSBDIR = ../STM32_USB-FS-Device_Driver
|
||||
STMUSBSRCDIR = $(STMUSBDIR)/src
|
||||
STMUSBINCDIR = $(STMUSBDIR)/inc
|
||||
STMUSBSRC= $(STMUSBSRCDIR)/usb_sil.c \
|
||||
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
|
||||
|
||||
1427
src/usb-icc.c
1427
src/usb-icc.c
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "usb_lib.h"
|
||||
#include "usb_lld.h"
|
||||
|
||||
extern void USB_Istr (void);
|
||||
@@ -26,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,55 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_stall_rx (int ep_num)
|
||||
{
|
||||
SetEPRxStatus (ep_num, EP_RX_STALL);
|
||||
}
|
||||
|
||||
extern inline int usb_lld_tx_data_len (int ep_num)
|
||||
{
|
||||
return GetEPTxCount (ep_num);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_txcpy (const void *src,
|
||||
int ep_num, int offset, size_t len)
|
||||
{
|
||||
usb_lld_to_pmabuf (src, GetEPTxAddr (ep_num) + offset, len);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_tx_enable (int ep_num, size_t len)
|
||||
{
|
||||
SetEPTxCount (ep_num, len);
|
||||
SetEPTxValid (ep_num);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_write (uint8_t ep_num, const void *buf, size_t len)
|
||||
{
|
||||
usb_lld_to_pmabuf (buf, GetEPTxAddr (ep_num), len);
|
||||
SetEPTxCount (ep_num, len);
|
||||
SetEPTxValid (ep_num);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_rx_enable (int ep_num)
|
||||
{
|
||||
SetEPRxValid (ep_num);
|
||||
}
|
||||
|
||||
extern inline int usb_lld_rx_data_len (int ep_num)
|
||||
{
|
||||
return GetEPRxCount (ep_num);
|
||||
}
|
||||
|
||||
extern inline void usb_lld_rxcpy (uint8_t *dst,
|
||||
int ep_num, int offset, size_t len)
|
||||
{
|
||||
usb_lld_from_pmabuf (dst, GetEPRxAddr (ep_num) + offset, len);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* usb_msc.c -- USB Mass Storage Class protocol handling
|
||||
*
|
||||
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||
* Copyright (C) 2011, 2012 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "usb_lld.h"
|
||||
#include "usb_msc.h"
|
||||
|
||||
struct usb_endp_in {
|
||||
@@ -50,11 +51,6 @@ static Thread *the_thread;
|
||||
static uint8_t msc_state;
|
||||
|
||||
|
||||
static void usb_stall_transmit (void)
|
||||
{
|
||||
SetEPTxStatus (ENDP6, EP_TX_STALL);
|
||||
}
|
||||
|
||||
static void usb_start_transmit (const uint8_t *p, size_t n)
|
||||
{
|
||||
size_t pkt_len = n > ENDP_MAX_SIZE ? ENDP_MAX_SIZE : n;
|
||||
@@ -63,14 +59,13 @@ static void usb_start_transmit (const uint8_t *p, size_t n)
|
||||
ep6_in.txsize = n;
|
||||
ep6_in.txcnt = 0;
|
||||
|
||||
USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, pkt_len);
|
||||
SetEPTxValid (ENDP6);
|
||||
usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, pkt_len);
|
||||
}
|
||||
|
||||
/* "Data Transmitted" callback */
|
||||
void EP6_IN_Callback (void)
|
||||
{
|
||||
size_t n = (size_t)GetEPTxCount (ENDP6);
|
||||
size_t n = (size_t)usb_lld_tx_data_len (ENDP6);
|
||||
|
||||
ep6_in.txbuf += n;
|
||||
ep6_in.txcnt += n;
|
||||
@@ -82,8 +77,7 @@ void EP6_IN_Callback (void)
|
||||
n = ENDP_MAX_SIZE;
|
||||
else
|
||||
n = ep6_in.txsize;
|
||||
USB_SIL_Write (EP6_IN, (uint8_t *)ep6_in.txbuf, n);
|
||||
SetEPTxValid (ENDP6);
|
||||
usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, n);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -108,43 +102,34 @@ void EP6_IN_Callback (void)
|
||||
}
|
||||
|
||||
|
||||
static void usb_stall_receive (void)
|
||||
{
|
||||
SetEPRxStatus (ENDP7, EP_RX_STALL);
|
||||
}
|
||||
|
||||
static void usb_start_receive (uint8_t *p, size_t n)
|
||||
{
|
||||
ep7_out.rxbuf = p;
|
||||
ep7_out.rxsize = n;
|
||||
ep7_out.rxcnt = 0;
|
||||
if (n < ENDP_MAX_SIZE)
|
||||
SetEPRxCount (ENDP7, n);
|
||||
else
|
||||
SetEPRxCount (ENDP7, ENDP_MAX_SIZE);
|
||||
SetEPRxValid (ENDP7);
|
||||
usb_lld_rx_enable (ENDP7);
|
||||
}
|
||||
|
||||
/* "Data Received" call back */
|
||||
void EP7_OUT_Callback (void)
|
||||
{
|
||||
size_t n = (size_t)GetEPRxCount (ENDP7);
|
||||
size_t n = (size_t)usb_lld_rx_data_len (ENDP7);
|
||||
int err = 0;
|
||||
|
||||
if (n > ep7_out.rxsize)
|
||||
{ /* buffer overflow */
|
||||
err = 1;
|
||||
SetEPRxCount (ENDP7, ep7_out.rxsize);
|
||||
n = ep7_out.rxsize;
|
||||
}
|
||||
|
||||
n = USB_SIL_Read (EP7_OUT, ep7_out.rxbuf);
|
||||
usb_lld_rxcpy (ep7_out.rxbuf, ENDP7, 0, n);
|
||||
ep7_out.rxbuf += n;
|
||||
ep7_out.rxcnt += n;
|
||||
ep7_out.rxsize -= n;
|
||||
|
||||
if (n == ENDP_MAX_SIZE && ep7_out.rxsize != 0)
|
||||
{ /* More data to be received */
|
||||
SetEPRxValid (ENDP7);
|
||||
usb_lld_rx_enable (ENDP7);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -333,7 +318,7 @@ void msc_handle_command (void)
|
||||
if (msg != RDY_TIMEOUT)
|
||||
{
|
||||
chSysLock ();
|
||||
usb_stall_receive ();
|
||||
usb_lld_stall_rx (ENDP7);
|
||||
chSysUnlock ();
|
||||
}
|
||||
return;
|
||||
@@ -345,7 +330,7 @@ void msc_handle_command (void)
|
||||
{
|
||||
msc_state = MSC_ERROR;
|
||||
chSysLock ();
|
||||
usb_stall_receive ();
|
||||
usb_lld_stall_rx (ENDP7);
|
||||
chSysUnlock ();
|
||||
return;
|
||||
}
|
||||
@@ -448,8 +433,8 @@ void msc_handle_command (void)
|
||||
{
|
||||
msc_state = MSC_ERROR;
|
||||
chSysLock ();
|
||||
usb_stall_transmit ();
|
||||
usb_stall_receive ();
|
||||
usb_lld_stall_tx (ENDP6);
|
||||
usb_lld_stall_rx (ENDP7);
|
||||
chSysUnlock ();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,20 @@
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
SetEPRxCount_allocated_size (uint8_t bEpNum, uint16_t wCount)
|
||||
{ /* Assume wCount is even */
|
||||
uint32_t *pdwReg = _pEPRxCount (bEpNum);
|
||||
uint16_t value;
|
||||
|
||||
if (wCount <= 62)
|
||||
value = (wCount & 0x3e) << 9;
|
||||
else
|
||||
value = 0x8000 | (((wCount >> 5) - 1) << 10);
|
||||
|
||||
*pdwReg = (uint32_t)value;
|
||||
}
|
||||
|
||||
static void
|
||||
gnuk_device_init (void)
|
||||
{
|
||||
@@ -50,7 +64,9 @@ gnuk_device_init (void)
|
||||
PowerOn ();
|
||||
|
||||
/* Perform basic device initialization operations */
|
||||
USB_SIL_Init ();
|
||||
_SetISTR (0);
|
||||
wInterrupt_Mask = IMR_MSK;
|
||||
_SetCNTR (wInterrupt_Mask);
|
||||
|
||||
bDeviceState = UNCONNECTED;
|
||||
}
|
||||
@@ -75,7 +91,7 @@ gnuk_device_reset (void)
|
||||
SetEPRxAddr (ENDP0, ENDP0_RXADDR);
|
||||
SetEPTxAddr (ENDP0, ENDP0_TXADDR);
|
||||
Clear_Status_Out (ENDP0);
|
||||
SetEPRxCount (ENDP0, GNUK_MAX_PACKET_SIZE);
|
||||
SetEPRxCount_allocated_size (ENDP0, GNUK_MAX_PACKET_SIZE);
|
||||
SetEPRxValid (ENDP0);
|
||||
|
||||
/* Initialize Endpoint 1 */
|
||||
@@ -87,7 +103,7 @@ gnuk_device_reset (void)
|
||||
/* Initialize Endpoint 2 */
|
||||
SetEPType (ENDP2, EP_BULK);
|
||||
SetEPRxAddr (ENDP2, ENDP2_RXADDR);
|
||||
SetEPRxCount (ENDP2, GNUK_MAX_PACKET_SIZE);
|
||||
SetEPRxCount_allocated_size (ENDP2, GNUK_MAX_PACKET_SIZE);
|
||||
SetEPRxStatus (ENDP2, EP_RX_VALID);
|
||||
SetEPTxStatus (ENDP2, EP_TX_DIS);
|
||||
|
||||
@@ -107,7 +123,7 @@ gnuk_device_reset (void)
|
||||
/* Initialize Endpoint 5 */
|
||||
SetEPType (ENDP5, EP_BULK);
|
||||
SetEPRxAddr (ENDP5, ENDP5_RXADDR);
|
||||
SetEPRxCount (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE);
|
||||
SetEPRxCount_allocated_size (ENDP5, VIRTUAL_COM_PORT_DATA_SIZE);
|
||||
SetEPRxStatus (ENDP5, EP_RX_VALID);
|
||||
SetEPTxStatus (ENDP5, EP_TX_DIS);
|
||||
#endif
|
||||
@@ -122,6 +138,7 @@ gnuk_device_reset (void)
|
||||
/* Initialize Endpoint 7 */
|
||||
SetEPType (ENDP7, EP_BULK);
|
||||
SetEPRxAddr (ENDP7, ENDP7_RXADDR);
|
||||
SetEPRxCount_allocated_size (ENDP7, 64);
|
||||
SetEPRxStatus (ENDP7, EP_RX_STALL);
|
||||
SetEPTxStatus (ENDP7, EP_TX_DIS);
|
||||
#endif
|
||||
|
||||
@@ -43,11 +43,18 @@ class GnukToken(object):
|
||||
cardservice = cardrequest.waitforcard()
|
||||
self.connection = cardservice.connection
|
||||
|
||||
def cmd_verify(self, who, passwd):
|
||||
apdu = [0x00, 0x20, 0x00, 0x80+who, 0, 0, len(passwd)] + s2l(passwd)
|
||||
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, "cmd_verify"
|
||||
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||
return response
|
||||
|
||||
def cmd_verify(self, who, 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))
|
||||
|
||||
def cmd_write_binary(self, fileid, data, is_update):
|
||||
count = 0
|
||||
@@ -59,29 +66,43 @@ 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:
|
||||
raise ValueError, "cmd_update_binary"
|
||||
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||
else:
|
||||
raise ValueError, "cmd_write_binary"
|
||||
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||
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):
|
||||
raise ValueError, "cmd_select_openpgp"
|
||||
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):
|
||||
raise ValueError, "cmd_get_data"
|
||||
if sw1 == 0x61:
|
||||
response = self.cmd_get_response(sw2)
|
||||
elif not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("%02x%02x" % (sw1, sw2))
|
||||
return response
|
||||
|
||||
def compare(data_original, data_in_device):
|
||||
@@ -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]
|
||||
@@ -165,6 +174,5 @@ if __name__ == '__main__':
|
||||
data = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename, len(data))
|
||||
data += "\x90\x00"
|
||||
print "Updating card holder certificate"
|
||||
main(fileid, is_update, data, passwd)
|
||||
|
||||
@@ -289,6 +289,5 @@ if __name__ == '__main__':
|
||||
data = f.read()
|
||||
f.close()
|
||||
print "%s: %d" % (filename, len(data))
|
||||
data += "\x90\x00"
|
||||
print "Updating card holder certificate"
|
||||
main(fileid, is_update, data)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
"""
|
||||
pinpad-test.py - a tool to test pinpad support by card reader.
|
||||
pinpadtest.py - a tool to test variable length pin entry with pinpad
|
||||
|
||||
Copyright (C) 2011 Free Software Initiative of Japan
|
||||
Copyright (C) 2011, 2012 Free Software Initiative of Japan
|
||||
Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
@@ -30,14 +30,20 @@ from smartcard.CardType import AnyCardType
|
||||
from smartcard.CardRequest import CardRequest
|
||||
from smartcard.util import toHexString
|
||||
|
||||
from getpass import getpass
|
||||
|
||||
CM_IOCTL_GET_FEATURE_REQUEST = (0x42000000 + 3400)
|
||||
FEATURE_VERIFY_PIN_DIRECT = 0x06
|
||||
FEATURE_MODIFY_PIN_DIRECT = 0x07
|
||||
|
||||
BY_ADMIN = 3
|
||||
BY_USER = 1
|
||||
PIN_MIN_DEFAULT = 6 # min of OpenPGP card
|
||||
PIN_MAX_DEFAULT = 15 # max of VASCO DIGIPASS 920
|
||||
|
||||
def s2l(s):
|
||||
return [ ord(c) for c in s ]
|
||||
|
||||
def confirm_pin_setting(single_step):
|
||||
if single_step:
|
||||
return 0x01 # bConfirmPIN: new PIN twice
|
||||
@@ -45,14 +51,15 @@ def confirm_pin_setting(single_step):
|
||||
return 0x03 # bConfirmPIN: old PIN and new PIN twice
|
||||
|
||||
class Card(object):
|
||||
def __init__(self, add_a_byte, pinmax):
|
||||
def __init__(self, add_a_byte, pinmin, pinmax):
|
||||
cardtype = AnyCardType()
|
||||
cardrequest = CardRequest(timeout=1, cardType=cardtype)
|
||||
cardrequest = CardRequest(timeout=10, cardType=cardtype)
|
||||
cardservice = cardrequest.waitforcard()
|
||||
self.connection = cardservice.connection
|
||||
self.verify_ioctl = -1
|
||||
self.modify_ioctl = -1
|
||||
self.another_byte = add_a_byte
|
||||
self.pinmin = pinmin
|
||||
self.pinmax = pinmax
|
||||
|
||||
def get_features(self):
|
||||
@@ -97,7 +104,7 @@ class Card(object):
|
||||
0x00, # bmPINBlockString
|
||||
0x00, # bmPINLengthFormat
|
||||
self.pinmax, # wPINMaxExtraDigit Low (PINmax)
|
||||
1, # wPINMaxExtraDigit High (PINmin)
|
||||
self.pinmin, # wPINMaxExtraDigit High (PINmin)
|
||||
0x02, # bEntryValidationCondition
|
||||
0x01, # bNumberMessage
|
||||
0x00, # wLangId Low
|
||||
@@ -107,7 +114,8 @@ class Card(object):
|
||||
0x00, # bTeoPrologue[1]
|
||||
0x00 # bTeoPrologue[2]
|
||||
]
|
||||
pin_verify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte()
|
||||
apdu += self.possibly_add_dummy_byte()
|
||||
pin_verify += [ len(apdu), 0, 0, 0 ] + apdu
|
||||
data = self.connection.control(self.verify_ioctl,pin_verify)
|
||||
sw1 = data[0]
|
||||
sw2 = data[1]
|
||||
@@ -125,7 +133,7 @@ class Card(object):
|
||||
0x00, # bInsertionOffsetOld
|
||||
0x00, # bInsertionOffsetNew
|
||||
self.pinmax, # wPINMaxExtraDigit Low (PINmax)
|
||||
1, # wPINMaxExtraDigit High (PINmin)
|
||||
self.pinmin, # wPINMaxExtraDigit High (PINmin)
|
||||
confirm_pin_setting(single_step),
|
||||
0x02, # bEntryValidationCondition
|
||||
0x03, # bNumberMessage
|
||||
@@ -138,20 +146,37 @@ class Card(object):
|
||||
0x00, # bTeoPrologue[1]
|
||||
0x00 # bTeoPrologue[2]
|
||||
]
|
||||
pin_modify += [ len(apdu), 0, 0, 0 ] + apdu + self.possibly_add_dummy_byte()
|
||||
apdu += self.possibly_add_dummy_byte()
|
||||
pin_modify += [ len(apdu), 0, 0, 0 ] + apdu
|
||||
data = self.connection.control(self.modify_ioctl,pin_modify)
|
||||
sw1 = data[0]
|
||||
sw2 = data[1]
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("%s %02x %02x" % (command, sw1, sw2))
|
||||
|
||||
def cmd_reset_retry_counter(self, who, data):
|
||||
if who == BY_ADMIN:
|
||||
apdu = [0x00, 0x2c, 0x02, 0x81, len(data) ] + data # BY_ADMIN
|
||||
else:
|
||||
apdu = [0x00, 0x2c, 0x00, 0x81, len(data) ] + data # BY_USER with resetcode
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_reset_retry_counter %02x %02x" % (sw1, sw2))
|
||||
|
||||
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
|
||||
def cmd_reset_retry_counter_pinpad(self, who):
|
||||
if who == BY_ADMIN:
|
||||
apdu = [0x00, 0x2c, 0x02, 0x81] # BY_ADMIN
|
||||
self.send_modify_pinpad(apdu, True, "cmd_reset_retry_counter_pinpad")
|
||||
else:
|
||||
apdu = [0x00, 0x2c, 0x00, 0x81] # BY_USER with resetcode
|
||||
self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad")
|
||||
self.send_modify_pinpad(apdu, False, "cmd_reset_retry_counter_pinpad")
|
||||
|
||||
def cmd_put_resetcode(self, data):
|
||||
apdu = [0x00, 0xda, 0x00, 0xd3, len(data) ] + data # BY_ADMIN
|
||||
response, sw1, sw2 = self.connection.transmit(apdu)
|
||||
if not (sw1 == 0x90 and sw2 == 0x00):
|
||||
raise ValueError, ("cmd_put_resetcode %02x %02x" % (sw1, sw2))
|
||||
|
||||
# Note: CCID specification doesn't permit this (only 0x20 and 0x24)
|
||||
def cmd_put_resetcode_pinpad(self):
|
||||
@@ -166,11 +191,8 @@ class Card(object):
|
||||
self.send_modify_pinpad(apdu, is_exchange,
|
||||
"cmd_change_reference_data_pinpad")
|
||||
|
||||
# "Vasco DIGIPASS 920 [CCID] 00 00"
|
||||
# "FSIJ Gnuk (0.16-34006F06) 00 00"
|
||||
|
||||
def main(who, method, add_a_byte, pinmax, change_by_two_steps):
|
||||
card = Card(add_a_byte, pinmax)
|
||||
def main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps):
|
||||
card = Card(add_a_byte, pinmin, pinmax)
|
||||
card.connection.connect()
|
||||
|
||||
print "Reader/Token:", card.connection.getReader()
|
||||
@@ -206,20 +228,38 @@ def main(who, method, add_a_byte, pinmax, change_by_two_steps):
|
||||
print "and New Admin's PIN twice"
|
||||
card.cmd_change_reference_data_pinpad(who, False)
|
||||
elif method == "unblock":
|
||||
# It's always by single step
|
||||
if who == BY_USER:
|
||||
print "Please input reset code"
|
||||
print "and New User's PIN twice"
|
||||
if change_by_two_steps:
|
||||
# It means using keyboard for new PIN
|
||||
if who == BY_USER:
|
||||
resetcode=s2l(getpass("Please input reset code from keyboard: "))
|
||||
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
|
||||
card.cmd_reset_retry_counter(who,resetcode+newpin)
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
newpin=s2l(getpass("Please input New User's PIN from keyboard: "))
|
||||
card.cmd_reset_retry_counter(who,newpin)
|
||||
else:
|
||||
if who == BY_USER:
|
||||
print "Please input reset code"
|
||||
print "and New User's PIN twice"
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
print "Please input New User's PIN twice"
|
||||
card.cmd_reset_retry_counter_pinpad(who)
|
||||
elif method == "put":
|
||||
if change_by_two_steps:
|
||||
# It means using keyboard for new PIN
|
||||
print "Please input Admin's PIN"
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
resetcode=s2l(getpass("Please input New Reset Code from keyboard: "))
|
||||
card.cmd_put_resetcode(resetcode)
|
||||
else:
|
||||
print "Please input Admin's PIN"
|
||||
print "and New User's PIN twice"
|
||||
card.cmd_reset_retry_counter_pinpad(who)
|
||||
elif method == "put":
|
||||
# It's always by two steps
|
||||
print "Please input Admin's PIN"
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
print "Please input New Reset Code twice"
|
||||
card.cmd_put_resetcode_pinpad()
|
||||
card.cmd_verify_pinpad(BY_ADMIN)
|
||||
print "Please input New Reset Code twice"
|
||||
card.cmd_put_resetcode_pinpad()
|
||||
else:
|
||||
raise ValueError, method
|
||||
card.connection.disconnect()
|
||||
@@ -236,10 +276,13 @@ def print_usage():
|
||||
print "\t--change:\tchange PIN (old PIN, new PIN twice)"
|
||||
print "\t--change2:\tchange PIN by two steps (old PIN, new PIN twice)"
|
||||
print "\t--unblock:\tunblock PIN (admin PIN/resetcode, new PIN twice)"
|
||||
print "\t--unblock2:\tunblock PIN (admin PIN:pinpad, new PIN:kbd)"
|
||||
print "\t--put:\t\tsetup resetcode (admin PIN, new PIN twice)"
|
||||
print "\t--put2::\t\tsetup resetcode (admin PIN:pinpad, new PIN:kbd)"
|
||||
print " options:"
|
||||
print "\t--admin:\tby administrator\t\t\t[False]"
|
||||
print "\t--add:\t\tadd a dummy byte at the end of APDU\t[False]"
|
||||
print "\t--pinmin:\tspecify minimum length of PIN\t\t[6]"
|
||||
print "\t--pinmax:\tspecify maximum length of PIN\t\t[15]"
|
||||
print "EXAMPLES:"
|
||||
print " $ pinpad-test # verify user's PIN "
|
||||
@@ -256,6 +299,7 @@ if __name__ == '__main__':
|
||||
who = BY_USER
|
||||
method = "verify"
|
||||
add_a_byte = False
|
||||
pinmin = PIN_MIN_DEFAULT
|
||||
pinmax = PIN_MAX_DEFAULT
|
||||
change_by_two_steps = False
|
||||
while len(sys.argv) >= 2:
|
||||
@@ -270,13 +314,22 @@ if __name__ == '__main__':
|
||||
change_by_two_steps = True
|
||||
elif option == '--unblock':
|
||||
method = "unblock"
|
||||
elif option == '--unblock2':
|
||||
method = "unblock"
|
||||
change_by_two_steps = True
|
||||
elif option == '--add':
|
||||
add_a_byte = True
|
||||
elif option == '--pinmin':
|
||||
pinmin = int(sys.argv[1])
|
||||
sys.argv.pop(1)
|
||||
elif option == '--pinmax':
|
||||
pinmax = int(sys.argv[1])
|
||||
sys.argv.pop(1)
|
||||
elif option == '--put':
|
||||
method = "put"
|
||||
elif option == '--put2':
|
||||
method = "put"
|
||||
change_by_two_steps = True
|
||||
elif option == "verify":
|
||||
method = "verify"
|
||||
elif option == '--help':
|
||||
@@ -284,8 +337,62 @@ if __name__ == '__main__':
|
||||
exit(0)
|
||||
else:
|
||||
raise ValueError, option
|
||||
main(who, method, add_a_byte, pinmax, change_by_two_steps)
|
||||
main(who, method, add_a_byte, pinmin, pinmax, change_by_two_steps)
|
||||
|
||||
# Failure
|
||||
# 67 00: Wrong length; no further indication
|
||||
# 69 82: Security status not satisfied: pin doesn't match
|
||||
# 69 85: Conditions of use not satisfied
|
||||
# 6b 00: Wrong parameters P1-P2
|
||||
# 6b 80
|
||||
# 64 02: PIN different
|
||||
|
||||
# General
|
||||
# OpenPGP card v2 doesn't support CHANGE REFERENCE DATA in exchanging
|
||||
# mode (with P1 == 01, replacing PIN).
|
||||
# FAIL: --change2 fails with 6b 00 (after input of PIN)
|
||||
# FAIL: --change2 --admin fails with 6b 00 (after input of PIN)
|
||||
|
||||
# "FSIJ Gnuk (0.16-34006F06) 00 00"
|
||||
# Works well except --change2
|
||||
# It could support --put and --unblock, but currently it's disabled.
|
||||
|
||||
# "Vasco DIGIPASS 920 [CCID] 00 00"
|
||||
# OK: --verify
|
||||
# OK: --verify --admin
|
||||
# OK: --change
|
||||
# OK: --change --admin
|
||||
# OK: --unblock
|
||||
# FAIL: --unblock --admin fails with 69 85 (after input of PIN)
|
||||
# FAIL: --put fails with 6b 80 (before input of resetcode)
|
||||
# OK: --put2
|
||||
# FAIL: --unblock2 fails with 69 85
|
||||
# FAIL: --unblock2 --admin fails with 69 85 (after input of PIN)
|
||||
|
||||
# 0c4b:0500 Reiner SCT Kartensysteme GmbH
|
||||
# "REINER SCT cyberJack RFID standard (7592671050) 00 00"
|
||||
# OK: --verify
|
||||
# OK: --verify --admin
|
||||
# OK: --change
|
||||
# OK: --change --admin
|
||||
# OK: --unblock
|
||||
# OK: --unblock --admin
|
||||
# FAIL: --put fails with 69 85
|
||||
|
||||
# Gemalto GemPC Pinpad 00 00
|
||||
# It asks users PIN with --add but it results 67 00
|
||||
# It seems that it doesn't support variable length PIN
|
||||
# Firmware version: GemTwRC2-V2.10-GL04
|
||||
|
||||
# 072f:90d2 Advanced Card Systems, Ltd
|
||||
# ACS ACR83U 01 00
|
||||
# --verify failed with 6b 80
|
||||
|
||||
# 08e6:34c2 Gemplus
|
||||
# Gemalto Ezio Shield PinPad 01 00
|
||||
# works well
|
||||
# FAIL: --unblock2 fails with 6d 00
|
||||
|
||||
# 076b:3821 OmniKey AG CardMan 3821
|
||||
# OmniKey CardMan 3821 01 00
|
||||
# Works well with --pinmax 31 --pinmin 1
|
||||
Reference in New Issue
Block a user