more changes
This commit is contained in:
36
doc/NOTES
Normal file
36
doc/NOTES
Normal file
@@ -0,0 +1,36 @@
|
||||
USB communication
|
||||
=================
|
||||
|
||||
* No command chaining, but extended APDU and extended Lc and Le
|
||||
* dwMaxCCIDMessageLength: 64
|
||||
|
||||
|
||||
OpenPGP card protocol implementation
|
||||
====================================
|
||||
|
||||
* No clear password(s)
|
||||
|
||||
PW1
|
||||
|
||||
* Support of Resetting code
|
||||
|
||||
|
||||
KEY
|
||||
=======
|
||||
|
||||
KEYPTR
|
||||
----> [ P ][ Q ][ N ]
|
||||
<---encrypted----><--- plain ---->
|
||||
|
||||
key_addr 4-byte
|
||||
additional_data_encrypted 16-byte
|
||||
dek_encrypted_by_keystring_pw1 16-byte
|
||||
dek_encrypted_by_keystring_rc 16-byte
|
||||
dek_encrypted_by_keystring_pw3 16-byte
|
||||
|
||||
... decrypted to
|
||||
|
||||
[ P ][ Q ]
|
||||
check 4-byte
|
||||
random 4-byte
|
||||
magic[] 8-byte
|
||||
3
doc/NOTES~
Normal file
3
doc/NOTES~
Normal file
@@ -0,0 +1,3 @@
|
||||
PW1
|
||||
|
||||
* Support of Resetting code
|
||||
@@ -83,7 +83,7 @@ CSRC = $(PORTSRC) \
|
||||
$(CRYPTSRC) \
|
||||
main.c debug.c usb_lld.c \
|
||||
hw_config.c usb_desc.c usb_prop.c \
|
||||
usb-icc.c gpg.c ac.c openpgp-do.c flash.c
|
||||
usb-icc.c openpgp.c ac.c openpgp-do.c flash.c hardclock.c
|
||||
|
||||
# List ASM source files here
|
||||
ASMSRC = $(PORTASM) \
|
||||
|
||||
219
src/ac.c
219
src/ac.c
@@ -21,50 +21,195 @@ ac_check_status (uint8_t ac_flag)
|
||||
return (ac_flag & auth_status)? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: should be implemented
|
||||
*
|
||||
* string --S2K(SHA1,SALT,ITERATE)--> key
|
||||
* load params from flash with key (key,enc_params --decrypt--> params)
|
||||
* check magic in params
|
||||
*/
|
||||
int
|
||||
verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
uint8_t keystring_pw1[KEYSTRING_LEN] = {
|
||||
0x62, 0x10, 0x27, 0x44, 0x34, 0x05, 0x2f, 0x20,
|
||||
0xfc, 0xb8, 0x3e, 0x1d, 0x0f, 0x49, 0x22, 0x04,
|
||||
0xfc, 0xb1, 0x18, 0x84
|
||||
};
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
reset_pso_cds (void)
|
||||
{
|
||||
auth_status &= ~AC_PSO_CDS_AUTHORIZED;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_cds (uint8_t *pw, int pw_len)
|
||||
verify_pso_other (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPT, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For keystring of PW3, we use SALT+ITER+MD format
|
||||
*/
|
||||
static sha1_context sha1_ctx;
|
||||
|
||||
static uint32_t
|
||||
decode_iterate_count (uint8_t x)
|
||||
{
|
||||
return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
|
||||
}
|
||||
|
||||
static void
|
||||
calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
||||
uint8_t md[KEYSTRING_MD_SIZE])
|
||||
{
|
||||
sha1_starts (&sha1_ctx);
|
||||
|
||||
while (count > pw_len + 8)
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
sha1_update (&sha1_ctx, pw, pw_len);
|
||||
count -= pw_len + 8;
|
||||
}
|
||||
|
||||
if (count < 8)
|
||||
sha1_update (&sha1_ctx, salt, count);
|
||||
else
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
count -= 8;
|
||||
sha1_update (&sha1_ctx, pw, count);
|
||||
}
|
||||
|
||||
sha1_finish (&sha1_ctx, md);
|
||||
memset (&sha1_ctx, 0, sizeof (sha1_ctx));
|
||||
}
|
||||
|
||||
int
|
||||
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
{
|
||||
const uint8_t *pw3_keystring;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
int pw_len;
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
pw3_keystring = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW3);
|
||||
if (pw3_keystring != NULL)
|
||||
{
|
||||
int count;
|
||||
uint8_t md[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
pw_len = pw3_keystring[0];
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
|
||||
goto failure;
|
||||
|
||||
salt = &pw3_keystring[1];
|
||||
count = decode_iterate_count (pw3_keystring[1+8]);
|
||||
calc_md (count, salt, pw, pw_len, md);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
|
||||
if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
|
||||
{
|
||||
failure:
|
||||
pwsb[PW_STATUS_PW3]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{ /* OK, the user is now authenticated */
|
||||
pwsb[PW_STATUS_PW3] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* For empty PW3, pass phrase should be "12345678" */
|
||||
{
|
||||
if ((pw_len_known >=0 && pw_len_known != 8)
|
||||
|| buf_len < 8 || strncmp ((const char *)pw, "12345678", 8) != 0)
|
||||
/* It is failure, but we don't try to lock for the case of empty PW3 */
|
||||
return -1;
|
||||
|
||||
pw_len = 8;
|
||||
}
|
||||
|
||||
return pw_len;
|
||||
}
|
||||
|
||||
void
|
||||
gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
|
||||
{
|
||||
uint8_t ks[KEYSTRING_SIZE_PW3];
|
||||
uint32_t random;
|
||||
|
||||
ks[0] = newpw_len;
|
||||
random = get_random ();
|
||||
memcpy (&ks[1], &random, sizeof (random));
|
||||
random = get_random ();
|
||||
memcpy (&ks[5], &random, sizeof (random));
|
||||
ks[9] = 0x60; /* 65536 iterations */
|
||||
|
||||
calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
int
|
||||
verify_admin (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
|
||||
sha1 (pw, pw_len, keystring_pw1);
|
||||
if ((r = gpg_load_key (GPG_KEY_FOR_SIGNATURE)) < 0)
|
||||
r = verify_admin_0 (pw, pw_len, pw_len);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_other (uint8_t *pw, int pw_len)
|
||||
{
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_admin (uint8_t *pw, int pw_len)
|
||||
{
|
||||
#if 0
|
||||
compute_hash;
|
||||
if (cmp_hash (pw3_hash, hash) == 0)
|
||||
good;
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
sha1 (pw, pw_len, keystring_md_pw3);
|
||||
auth_status |= AC_ADMIN_AUTHORIZED;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#define DEBUG 1
|
||||
/* #undef DEBUG */
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ENABLE_VIRTUAL_COM_PORT 1
|
||||
#endif
|
||||
|
||||
#define GNUK_MAX_PACKET_SIZE 64 /* USB */
|
||||
|
||||
16
src/debug.c
16
src/debug.c
@@ -35,7 +35,7 @@ put_hex (uint8_t nibble)
|
||||
else
|
||||
c = 'a' + nibble - 0x0a;
|
||||
|
||||
_write (&c, 1);
|
||||
_write ((const char *)&c, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -64,6 +64,20 @@ put_short (uint16_t x)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_binary (const char *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (s[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
|
||||
void
|
||||
put_string (const char *s)
|
||||
{
|
||||
|
||||
28
src/flash.c
28
src/flash.c
@@ -34,10 +34,10 @@ static uint8_t *last_p = do_pool;
|
||||
/*
|
||||
* TLV (Tag, Length, and Value)
|
||||
*/
|
||||
uint8_t *
|
||||
flash_do_write (uint16_t tag, uint8_t *data, int len)
|
||||
const uint8_t *
|
||||
flash_do_write (uint16_t tag, const uint8_t *data, int len)
|
||||
{
|
||||
uint8_t *p = last_p;
|
||||
const uint8_t *p = last_p;
|
||||
|
||||
if (last_p - do_pool + len + 2 + 3 > 1024)
|
||||
return NULL;
|
||||
@@ -63,10 +63,16 @@ flash_do_write (uint16_t tag, uint8_t *data, int len)
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
static uint8_t k1[KEY_CONTENT_LEN];
|
||||
void
|
||||
flash_do_release (const uint8_t *data)
|
||||
{
|
||||
(void)data;/*XXX*/
|
||||
}
|
||||
|
||||
static uint8_t k1[KEY_CONTENT_LEN*2]; /* p, q and N */
|
||||
#if 0
|
||||
static uint8_t k2[KEY_CONTENT_LEN];
|
||||
static uint8_t k3[KEY_CONTENT_LEN];
|
||||
static uint8_t k2[KEY_CONTENT_LEN*2];
|
||||
static uint8_t k3[KEY_CONTENT_LEN*2];
|
||||
#endif
|
||||
|
||||
uint8_t *
|
||||
@@ -89,8 +95,16 @@ flash_key_alloc (enum kind_of_key kk)
|
||||
}
|
||||
|
||||
int
|
||||
flash_key_write (uint8_t *key_addr, uint8_t *key_data)
|
||||
flash_key_write (uint8_t *key_addr, const uint8_t *key_data,
|
||||
const uint8_t *modulus)
|
||||
{
|
||||
memcpy (key_addr, key_data, KEY_CONTENT_LEN);
|
||||
memcpy (key_addr+KEY_CONTENT_LEN, modulus, KEY_CONTENT_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
flash_key_release (const uint8_t *key_addr)
|
||||
{
|
||||
(void)key_addr; /*XXX*/
|
||||
}
|
||||
|
||||
127
src/gnuk.h
127
src/gnuk.h
@@ -4,12 +4,17 @@ extern void put_byte (uint8_t b);
|
||||
extern void put_byte_with_no_nl (uint8_t b);
|
||||
extern void put_short (uint16_t x);
|
||||
extern void put_string (const char *s);
|
||||
extern void put_binary (const char *s, int len);
|
||||
|
||||
extern void _write (const char *, int);
|
||||
|
||||
extern size_t strlen(const char *s);
|
||||
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||
extern void *memset(void *s, int c, size_t n);
|
||||
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 void *malloc (size_t size);
|
||||
extern int memcmp (const void *s1, const void *s2, size_t n);
|
||||
extern void free (void *ptr);
|
||||
|
||||
/*
|
||||
* Interface between ICC<-->GPG
|
||||
@@ -21,10 +26,10 @@ extern Thread *gpg_thread;
|
||||
|
||||
#define EV_EXEC_FINISHED (eventmask_t)2 /* GPG Execution finished */
|
||||
|
||||
/* maximum cmd apdu data is key import 22+4+128+128 (head, e, p, q)*/
|
||||
/* maximum cmd apdu data is key import 22+4+128+128 (proc_key_import) */
|
||||
#define MAX_CMD_APDU_SIZE (7+282) /* header + data */
|
||||
|
||||
#define MAX_RES_APDU_SIZE (256+2) /* Data + status */
|
||||
/* 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 */
|
||||
extern uint8_t cmd_APDU[MAX_CMD_APDU_SIZE];
|
||||
extern uint8_t res_APDU[MAX_RES_APDU_SIZE];
|
||||
extern int cmd_APDU_size;
|
||||
@@ -38,9 +43,13 @@ extern int res_APDU_size;
|
||||
#define AC_ALWAYS 0xFF
|
||||
|
||||
extern int ac_check_status (uint8_t ac_flag);
|
||||
extern int verify_pso_cds (uint8_t *pw, int pw_len);
|
||||
extern int verify_pso_other (uint8_t *pw, int pw_len);
|
||||
extern int verify_pso_admin (uint8_t *pw, int pw_len);
|
||||
extern int verify_pso_cds (const uint8_t *pw, int pw_len);
|
||||
extern int verify_pso_other (const uint8_t *pw, int pw_len);
|
||||
extern int verify_admin (const uint8_t *pw, int pw_len);
|
||||
extern int verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known);
|
||||
|
||||
extern void reset_pso_cds (void);
|
||||
|
||||
|
||||
|
||||
extern void write_res_apdu (const uint8_t *p, int len,
|
||||
@@ -48,9 +57,10 @@ extern void write_res_apdu (const uint8_t *p, int len,
|
||||
|
||||
extern int gpg_do_table_init (void);
|
||||
extern void gpg_do_get_data (uint16_t tag);
|
||||
extern void gpg_do_put_data (uint16_t tag, uint8_t *data, int len);
|
||||
extern void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len);
|
||||
extern void gpg_do_public_key (uint8_t kk_byte);
|
||||
|
||||
|
||||
extern uint8_t * flash_do_write (uint16_t tag, uint8_t *data, int len);
|
||||
|
||||
enum kind_of_key {
|
||||
GPG_KEY_FOR_SIGNATURE,
|
||||
@@ -58,27 +68,100 @@ enum kind_of_key {
|
||||
GPG_KEY_FOR_AUTHENTICATION,
|
||||
};
|
||||
|
||||
extern void flash_do_release (const uint8_t *);
|
||||
extern const uint8_t *flash_do_write (uint16_t tag, const uint8_t *data, int len);
|
||||
extern uint8_t *flash_key_alloc (enum kind_of_key);
|
||||
extern void flash_key_release (const uint8_t *);
|
||||
|
||||
#define KEY_MAGIC_LEN 8
|
||||
#define KEY_CONTENT_LEN 256
|
||||
#define KEY_CONTENT_LEN 256 /* p and q */
|
||||
#define GNUK_MAGIC "Gnuk KEY"
|
||||
#define KEYSTORE_LEN (KEY_MAGIC_LEN+4+4+KEY_CONTENT_LEN)
|
||||
#define KEYSTORE_LEN (KEY_MAGIC_LEN+4+4+KEY_CONTENT_LEN*2)
|
||||
|
||||
/* encrypted data content */
|
||||
struct key_data {
|
||||
uint8_t *key_addr;
|
||||
/* encrypted data content */
|
||||
char magic[KEY_MAGIC_LEN];
|
||||
uint32_t random;
|
||||
uint8_t data[KEY_CONTENT_LEN]; /* p and q */
|
||||
uint32_t check;
|
||||
uint8_t data[KEY_CONTENT_LEN];
|
||||
uint32_t random;
|
||||
char magic[KEY_MAGIC_LEN];
|
||||
};
|
||||
|
||||
extern int flash_key_write (uint8_t *key_addr, uint8_t *key_data);
|
||||
#define ADDITIONAL_DATA_SIZE 16
|
||||
#define DATA_ENCRYPTION_KEY_SIZE 16
|
||||
struct prvkey_data {
|
||||
const uint8_t *key_addr;
|
||||
uint8_t crm_encrypted[ADDITIONAL_DATA_SIZE];
|
||||
uint8_t dek_encrypted_1[DATA_ENCRYPTION_KEY_SIZE];
|
||||
uint8_t dek_encrypted_2[DATA_ENCRYPTION_KEY_SIZE];
|
||||
uint8_t dek_encrypted_3[DATA_ENCRYPTION_KEY_SIZE];
|
||||
};
|
||||
|
||||
#define KEYSTRING_LEN 20 /* Use 16-byte for AES encryption */
|
||||
extern uint8_t keystring_pw1[KEYSTRING_LEN];
|
||||
extern uint32_t get_random (void);
|
||||
|
||||
extern int gpg_load_key (enum kind_of_key kk);
|
||||
extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const uint8_t *modulus);
|
||||
|
||||
#define KEYSTRING_PASSLEN_SIZE 1
|
||||
#define KEYSTRING_SALT_SIZE 8 /* optional */
|
||||
#define KEYSTRING_ITER_SIZE 1 /* optional */
|
||||
#define KEYSTRING_MD_SIZE 20
|
||||
#define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
|
||||
#define KEYSTRING_SIZE_RC (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
|
||||
#define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \
|
||||
+KEYSTRING_ITER_SIZE+KEYSTRING_MD_SIZE)
|
||||
|
||||
extern int gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring);
|
||||
extern int gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
|
||||
extern int gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks);
|
||||
|
||||
extern struct key_data kd;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_INFO(msg) put_string (msg)
|
||||
#define DEBUG_SHORT(h) put_short (h)
|
||||
#define DEBUG_BYTE(b) put_byte (b)
|
||||
#define DEBUG_BINARY(s,len) put_binary ((const char *)s,len)
|
||||
#else
|
||||
#define DEBUG_INFO(msg)
|
||||
#define DEBUG_SHORT(h)
|
||||
#define DEBUG_BYTE(b)
|
||||
#define DEBUG_BINARY(s,len)
|
||||
#endif
|
||||
|
||||
extern int rsa_sign (const uint8_t *, uint8_t *, int);
|
||||
extern const uint8_t *modulus_calc (const uint8_t *, int);
|
||||
extern void modulus_free (const uint8_t *);
|
||||
|
||||
extern int gpg_do_write_privkey (enum kind_of_key kk, const uint8_t *key_data, int key_len);
|
||||
|
||||
extern const uint8_t *gpg_do_read_simple (uint16_t);
|
||||
extern void gpg_do_write_simple (uint16_t, const uint8_t *, int);
|
||||
extern void gpg_do_increment_digital_signature_counter (void);
|
||||
|
||||
#define PW_STATUS_PW1 4
|
||||
#define PW_STATUS_RC 5
|
||||
#define PW_STATUS_PW3 6
|
||||
|
||||
|
||||
extern void gpg_set_pw3 (const uint8_t *newpw, int newpw_len);
|
||||
extern void fatal (void);
|
||||
|
||||
extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
#define GNUK_DO_PRVKEY_SIG 0xff01
|
||||
#define GNUK_DO_PRVKEY_DEC 0xff02
|
||||
#define GNUK_DO_PRVKEY_AUT 0xff03
|
||||
#define GNUK_DO_KEYSTRING_PW1 0xff04
|
||||
#define GNUK_DO_KEYSTRING_RC 0xff05
|
||||
#define GNUK_DO_KEYSTRING_PW3 0xff06
|
||||
#define GNUK_DO_PW_STATUS 0xff07
|
||||
#define SIZE_PW_STATUS_BYTES 7
|
||||
|
||||
/* 16-byte random bytes */
|
||||
extern uint8_t *get_data_encryption_key (void);
|
||||
extern void dek_free (uint8_t *);
|
||||
|
||||
extern uint32_t hardclock (void);
|
||||
|
||||
@@ -23,31 +23,6 @@ const char const do_5e[] __attribute__ ((aligned (1))) = {
|
||||
'g', 'n', 'i', 'i', 'b', 'e'
|
||||
};
|
||||
|
||||
const char const do_c4[] __attribute__ ((aligned (1))) = {
|
||||
7,
|
||||
1, 127, 127, 127, 3, 0, 3
|
||||
};
|
||||
|
||||
const char const do_c7[] __attribute__ ((aligned (1))) = {
|
||||
20,
|
||||
/* sign */
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
};
|
||||
|
||||
const char const do_ca[] __attribute__ ((aligned (1))) = {
|
||||
20,
|
||||
0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d,
|
||||
0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc,
|
||||
0xe5, 0x02, 0xbf, 0xcd,
|
||||
};
|
||||
|
||||
const char const do_ce[] __attribute__ ((aligned (1))) = {
|
||||
4,
|
||||
0x49, 0x8a, 0x50, 0x7a, /* 0xce */
|
||||
};
|
||||
|
||||
const char const do_5b[] __attribute__ ((aligned (1))) = {
|
||||
12,
|
||||
'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a'
|
||||
@@ -63,12 +38,6 @@ const char const do_5f35[] __attribute__ ((aligned (1))) = {
|
||||
'1'
|
||||
};
|
||||
|
||||
/* Digital Signature Counter (3-bytes) */
|
||||
const char const do_93[] __attribute__ ((aligned (1))) = {
|
||||
3,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
const char const do_5f50[] __attribute__ ((aligned (1))) = {
|
||||
20,
|
||||
'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w',
|
||||
@@ -78,51 +47,3 @@ const char const do_5f50[] __attribute__ ((aligned (1))) = {
|
||||
const char const get_data_rb_result[] __attribute__ ((aligned (1))) = {
|
||||
0x5a, 0x4, 0x01, 0x02, 0x03, 0x04
|
||||
};
|
||||
|
||||
const char const get_data_sigkey_result[] __attribute__ ((aligned (1))) = {
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
/* modulus */
|
||||
0xdb, 0xca, 0x58, 0x74, 0x44, 0x8e, 0x1a, 0x2c,
|
||||
0xa0, 0x91, 0xac, 0xc4, 0xe2, 0x77, 0x2b, 0x90,
|
||||
0xcf, 0x3c, 0x7e, 0x81, 0xdc, 0x8d, 0xb0, 0xe2,
|
||||
0xf1, 0xfe, 0x56, 0x7e, 0x54, 0x57, 0xf0, 0xd8,
|
||||
0xb1, 0xb1, 0xaa, 0x9d, 0x8f, 0xb0, 0x56, 0x01,
|
||||
0xaa, 0x6b, 0xa7, 0x2e, 0xce, 0x01, 0x20, 0xd2,
|
||||
0xf8, 0xf5, 0x85, 0x3a, 0xc2, 0x73, 0xf9, 0x66,
|
||||
0x30, 0x28, 0x65, 0x5e, 0x3f, 0x91, 0xaf, 0x3f,
|
||||
0xf6, 0x1c, 0x31, 0x2f, 0xa2, 0x91, 0xbb, 0x41,
|
||||
0x91, 0x41, 0x08, 0x0a, 0xc5, 0x3e, 0x39, 0xda,
|
||||
0x2f, 0x6f, 0x58, 0x51, 0xe2, 0xd2, 0xe9, 0x42,
|
||||
0x8a, 0x7b, 0x72, 0x7b, 0x15, 0xf6, 0xf6, 0x6a,
|
||||
0x12, 0x6e, 0x0c, 0x15, 0x24, 0x13, 0x16, 0x55,
|
||||
0x3a, 0xf1, 0xa7, 0x16, 0x3e, 0xe9, 0xc8, 0x3d,
|
||||
0x2c, 0x3d, 0xae, 0x51, 0x2d, 0x7f, 0xef, 0x92,
|
||||
0x25, 0x6a, 0xbb, 0x02, 0x03, 0x70, 0x45, 0x3d,
|
||||
/* public exponent */
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
const char const get_data_enckey_result[] __attribute__ ((aligned (1))) = {
|
||||
0x7f, 0x49, 0x81, 0x88,
|
||||
0x81, 0x81, 0x80,
|
||||
/* 128-byte data */
|
||||
0xB2, 0x19, 0x91, 0x42, 0x27, 0xC7, 0x97, 0xFE,
|
||||
0x92, 0x64, 0x42, 0xCA, 0xE3, 0x66, 0x4D, 0xD0,
|
||||
0x31, 0xE4, 0x10, 0x31, 0x0F, 0xC7, 0x07, 0x4A,
|
||||
0xAA, 0x6D, 0x31, 0xA2, 0x88, 0x68, 0xAF, 0x45,
|
||||
0x8E, 0x42, 0x12, 0xFF, 0xB6, 0xEF, 0x6E, 0x54,
|
||||
0x7E, 0x51, 0x8E, 0xBC, 0xE8, 0x18, 0x79, 0xA7,
|
||||
0xBC, 0xA8, 0x14, 0x8B, 0xE7, 0x91, 0x57, 0x38,
|
||||
0xCE, 0x4F, 0x6E, 0x16, 0x48, 0xCB, 0xD6, 0x0B,
|
||||
0x3A, 0x53, 0x70, 0xF3, 0xFC, 0xFA, 0xC3, 0x58,
|
||||
0x3D, 0xE7, 0x2A, 0x5E, 0xDD, 0xE1, 0x38, 0x82,
|
||||
0x57, 0x87, 0x3A, 0xDC, 0x34, 0xDE, 0xCD, 0x5D,
|
||||
0x33, 0x1C, 0xAB, 0xB0, 0x1B, 0xEE, 0x82, 0x43,
|
||||
0x7B, 0xAC, 0xF8, 0xF0, 0xB2, 0x62, 0xB2, 0x6D,
|
||||
0x09, 0xED, 0x2E, 0xD1, 0xBA, 0xB8, 0xC6, 0x96,
|
||||
0xFA, 0x3E, 0xB4, 0xE3, 0xFE, 0x68, 0xF9, 0x51,
|
||||
0x9A, 0x8C, 0x8B, 0x20, 0x93, 0xD0, 0x2E, 0x0F,
|
||||
0x82, 3, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
626
src/gpg-data.s
626
src/gpg-data.s
@@ -55,77 +55,6 @@ do_5e:
|
||||
.byte 105
|
||||
.byte 98
|
||||
.byte 101
|
||||
.global do_c4
|
||||
.type do_c4, %object
|
||||
.size do_c4, 8
|
||||
do_c4:
|
||||
.byte 7
|
||||
.byte 1
|
||||
.byte 127
|
||||
.byte 127
|
||||
.byte 127
|
||||
.byte 3
|
||||
.byte 0
|
||||
.byte 3
|
||||
.global do_c7
|
||||
.type do_c7, %object
|
||||
.size do_c7, 21
|
||||
do_c7:
|
||||
.byte 20
|
||||
.byte 91
|
||||
.byte -123
|
||||
.byte 103
|
||||
.byte 60
|
||||
.byte 8
|
||||
.byte 79
|
||||
.byte -128
|
||||
.byte 13
|
||||
.byte 84
|
||||
.byte -84
|
||||
.byte -107
|
||||
.byte 28
|
||||
.byte 53
|
||||
.byte 21
|
||||
.byte -105
|
||||
.byte -52
|
||||
.byte -27
|
||||
.byte 2
|
||||
.byte -65
|
||||
.byte -51
|
||||
.global do_ca
|
||||
.type do_ca, %object
|
||||
.size do_ca, 21
|
||||
do_ca:
|
||||
.byte 20
|
||||
.byte 91
|
||||
.byte -123
|
||||
.byte 103
|
||||
.byte 60
|
||||
.byte 8
|
||||
.byte 79
|
||||
.byte -128
|
||||
.byte 13
|
||||
.byte 84
|
||||
.byte -84
|
||||
.byte -107
|
||||
.byte 28
|
||||
.byte 53
|
||||
.byte 21
|
||||
.byte -105
|
||||
.byte -52
|
||||
.byte -27
|
||||
.byte 2
|
||||
.byte -65
|
||||
.byte -51
|
||||
.global do_ce
|
||||
.type do_ce, %object
|
||||
.size do_ce, 5
|
||||
do_ce:
|
||||
.byte 4
|
||||
.byte 73
|
||||
.byte -118
|
||||
.byte 80
|
||||
.byte 122
|
||||
.global do_5b
|
||||
.type do_5b, %object
|
||||
.size do_5b, 13
|
||||
@@ -156,14 +85,6 @@ do_5f2d:
|
||||
do_5f35:
|
||||
.byte 1
|
||||
.byte 49
|
||||
.global do_93
|
||||
.type do_93, %object
|
||||
.size do_93, 4
|
||||
do_93:
|
||||
.byte 3
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.global do_5f50
|
||||
.type do_5f50, %object
|
||||
.size do_5f50, 21
|
||||
@@ -199,307 +120,19 @@ get_data_rb_result:
|
||||
.byte 2
|
||||
.byte 3
|
||||
.byte 4
|
||||
.global get_data_sigkey_result
|
||||
.type get_data_sigkey_result, %object
|
||||
.size get_data_sigkey_result, 140
|
||||
get_data_sigkey_result:
|
||||
.byte 127
|
||||
.byte 73
|
||||
.byte -127
|
||||
.byte -120
|
||||
.byte -127
|
||||
.byte -127
|
||||
.byte -128
|
||||
.byte -37
|
||||
.byte -54
|
||||
.byte 88
|
||||
.byte 116
|
||||
.byte 68
|
||||
.byte -114
|
||||
.byte 26
|
||||
.byte 44
|
||||
.byte -96
|
||||
.byte -111
|
||||
.byte -84
|
||||
.byte -60
|
||||
.byte -30
|
||||
.byte 119
|
||||
.byte 43
|
||||
.byte -112
|
||||
.byte -49
|
||||
.byte 60
|
||||
.byte 126
|
||||
.byte -127
|
||||
.byte -36
|
||||
.byte -115
|
||||
.byte -80
|
||||
.byte -30
|
||||
.byte -15
|
||||
.byte -2
|
||||
.byte 86
|
||||
.byte 126
|
||||
.byte 84
|
||||
.byte 87
|
||||
.byte -16
|
||||
.byte -40
|
||||
.byte -79
|
||||
.byte -79
|
||||
.byte -86
|
||||
.byte -99
|
||||
.byte -113
|
||||
.byte -80
|
||||
.byte 86
|
||||
.byte 1
|
||||
.byte -86
|
||||
.byte 107
|
||||
.byte -89
|
||||
.byte 46
|
||||
.byte -50
|
||||
.byte 1
|
||||
.byte 32
|
||||
.byte -46
|
||||
.byte -8
|
||||
.byte -11
|
||||
.byte -123
|
||||
.byte 58
|
||||
.byte -62
|
||||
.byte 115
|
||||
.byte -7
|
||||
.byte 102
|
||||
.byte 48
|
||||
.byte 40
|
||||
.byte 101
|
||||
.byte 94
|
||||
.byte 63
|
||||
.byte -111
|
||||
.byte -81
|
||||
.byte 63
|
||||
.byte -10
|
||||
.byte 28
|
||||
.byte 49
|
||||
.byte 47
|
||||
.byte -94
|
||||
.byte -111
|
||||
.byte -69
|
||||
.byte 65
|
||||
.byte -111
|
||||
.byte 65
|
||||
.byte 8
|
||||
.byte 10
|
||||
.byte -59
|
||||
.byte 62
|
||||
.byte 57
|
||||
.byte -38
|
||||
.byte 47
|
||||
.byte 111
|
||||
.byte 88
|
||||
.byte 81
|
||||
.byte -30
|
||||
.byte -46
|
||||
.byte -23
|
||||
.byte 66
|
||||
.byte -118
|
||||
.byte 123
|
||||
.byte 114
|
||||
.byte 123
|
||||
.byte 21
|
||||
.byte -10
|
||||
.byte -10
|
||||
.byte 106
|
||||
.byte 18
|
||||
.byte 110
|
||||
.byte 12
|
||||
.byte 21
|
||||
.byte 36
|
||||
.byte 19
|
||||
.byte 22
|
||||
.byte 85
|
||||
.byte 58
|
||||
.byte -15
|
||||
.byte -89
|
||||
.byte 22
|
||||
.byte 62
|
||||
.byte -23
|
||||
.byte -56
|
||||
.byte 61
|
||||
.byte 44
|
||||
.byte 61
|
||||
.byte -82
|
||||
.byte 81
|
||||
.byte 45
|
||||
.byte 127
|
||||
.byte -17
|
||||
.byte -110
|
||||
.byte 37
|
||||
.byte 106
|
||||
.byte -69
|
||||
.byte 2
|
||||
.byte 3
|
||||
.byte 112
|
||||
.byte 69
|
||||
.byte 61
|
||||
.byte -126
|
||||
.byte 3
|
||||
.byte 1
|
||||
.byte 0
|
||||
.byte 1
|
||||
.global get_data_enckey_result
|
||||
.type get_data_enckey_result, %object
|
||||
.size get_data_enckey_result, 140
|
||||
get_data_enckey_result:
|
||||
.byte 127
|
||||
.byte 73
|
||||
.byte -127
|
||||
.byte -120
|
||||
.byte -127
|
||||
.byte -127
|
||||
.byte -128
|
||||
.byte -78
|
||||
.byte 25
|
||||
.byte -111
|
||||
.byte 66
|
||||
.byte 39
|
||||
.byte -57
|
||||
.byte -105
|
||||
.byte -2
|
||||
.byte -110
|
||||
.byte 100
|
||||
.byte 66
|
||||
.byte -54
|
||||
.byte -29
|
||||
.byte 102
|
||||
.byte 77
|
||||
.byte -48
|
||||
.byte 49
|
||||
.byte -28
|
||||
.byte 16
|
||||
.byte 49
|
||||
.byte 15
|
||||
.byte -57
|
||||
.byte 7
|
||||
.byte 74
|
||||
.byte -86
|
||||
.byte 109
|
||||
.byte 49
|
||||
.byte -94
|
||||
.byte -120
|
||||
.byte 104
|
||||
.byte -81
|
||||
.byte 69
|
||||
.byte -114
|
||||
.byte 66
|
||||
.byte 18
|
||||
.byte -1
|
||||
.byte -74
|
||||
.byte -17
|
||||
.byte 110
|
||||
.byte 84
|
||||
.byte 126
|
||||
.byte 81
|
||||
.byte -114
|
||||
.byte -68
|
||||
.byte -24
|
||||
.byte 24
|
||||
.byte 121
|
||||
.byte -89
|
||||
.byte -68
|
||||
.byte -88
|
||||
.byte 20
|
||||
.byte -117
|
||||
.byte -25
|
||||
.byte -111
|
||||
.byte 87
|
||||
.byte 56
|
||||
.byte -50
|
||||
.byte 79
|
||||
.byte 110
|
||||
.byte 22
|
||||
.byte 72
|
||||
.byte -53
|
||||
.byte -42
|
||||
.byte 11
|
||||
.byte 58
|
||||
.byte 83
|
||||
.byte 112
|
||||
.byte -13
|
||||
.byte -4
|
||||
.byte -6
|
||||
.byte -61
|
||||
.byte 88
|
||||
.byte 61
|
||||
.byte -25
|
||||
.byte 42
|
||||
.byte 94
|
||||
.byte -35
|
||||
.byte -31
|
||||
.byte 56
|
||||
.byte -126
|
||||
.byte 87
|
||||
.byte -121
|
||||
.byte 58
|
||||
.byte -36
|
||||
.byte 52
|
||||
.byte -34
|
||||
.byte -51
|
||||
.byte 93
|
||||
.byte 51
|
||||
.byte 28
|
||||
.byte -85
|
||||
.byte -80
|
||||
.byte 27
|
||||
.byte -18
|
||||
.byte -126
|
||||
.byte 67
|
||||
.byte 123
|
||||
.byte -84
|
||||
.byte -8
|
||||
.byte -16
|
||||
.byte -78
|
||||
.byte 98
|
||||
.byte -78
|
||||
.byte 109
|
||||
.byte 9
|
||||
.byte -19
|
||||
.byte 46
|
||||
.byte -47
|
||||
.byte -70
|
||||
.byte -72
|
||||
.byte -58
|
||||
.byte -106
|
||||
.byte -6
|
||||
.byte 62
|
||||
.byte -76
|
||||
.byte -29
|
||||
.byte -2
|
||||
.byte 104
|
||||
.byte -7
|
||||
.byte 81
|
||||
.byte -102
|
||||
.byte -116
|
||||
.byte -117
|
||||
.byte 32
|
||||
.byte -109
|
||||
.byte -48
|
||||
.byte 46
|
||||
.byte 15
|
||||
.byte -126
|
||||
.byte 3
|
||||
.byte 1
|
||||
.byte 0
|
||||
.byte 1
|
||||
.text
|
||||
.Letext0:
|
||||
.file 1 "gpg-data.c"
|
||||
.section .debug_info
|
||||
.4byte 0x264
|
||||
.4byte 0x183
|
||||
.2byte 0x2
|
||||
.4byte .Ldebug_abbrev0
|
||||
.byte 0x4
|
||||
.uleb128 0x1
|
||||
.4byte .LASF24
|
||||
.4byte .LASF17
|
||||
.byte 0x1
|
||||
.4byte .LASF25
|
||||
.4byte .LASF26
|
||||
.4byte .LASF18
|
||||
.4byte .LASF19
|
||||
.4byte .Ltext0
|
||||
.4byte .Letext0
|
||||
.4byte .Ldebug_line0
|
||||
@@ -546,17 +179,17 @@ get_data_enckey_result:
|
||||
.uleb128 0x4
|
||||
.byte 0x4
|
||||
.byte 0x7
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x7e
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x13
|
||||
.byte 0x0
|
||||
.uleb128 0x3
|
||||
.byte 0x1
|
||||
.byte 0x8
|
||||
.4byte .LASF9
|
||||
.uleb128 0x5
|
||||
.4byte 0x6e
|
||||
.4byte 0x85
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x13
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF10
|
||||
.byte 0x1
|
||||
@@ -567,9 +200,9 @@ get_data_enckey_result:
|
||||
.byte 0x3
|
||||
.4byte select_file_TOP_result
|
||||
.uleb128 0x8
|
||||
.4byte 0x6e
|
||||
.4byte 0x75
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x6e
|
||||
.4byte 0xac
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
@@ -587,11 +220,11 @@ get_data_enckey_result:
|
||||
.uleb128 0x8
|
||||
.4byte 0x9c
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x6e
|
||||
.4byte 0xd3
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x7
|
||||
.byte 0xc
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF12
|
||||
@@ -601,15 +234,15 @@ get_data_enckey_result:
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_c4
|
||||
.4byte do_5b
|
||||
.uleb128 0x8
|
||||
.4byte 0xc3
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x6e
|
||||
.4byte 0xfa
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x14
|
||||
.byte 0x2
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF13
|
||||
@@ -619,168 +252,63 @@ get_data_enckey_result:
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_c7
|
||||
.4byte do_5f2d
|
||||
.uleb128 0x8
|
||||
.4byte 0xea
|
||||
.uleb128 0x5
|
||||
.4byte 0x6e
|
||||
.4byte 0x121
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x1
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF14
|
||||
.byte 0x1
|
||||
.byte 0x27
|
||||
.4byte 0x123
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_ca
|
||||
.uleb128 0x8
|
||||
.4byte 0xea
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x138
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x4
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF15
|
||||
.byte 0x1
|
||||
.byte 0x2e
|
||||
.4byte 0x14a
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_ce
|
||||
.uleb128 0x8
|
||||
.4byte 0x128
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x15f
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0xc
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF16
|
||||
.byte 0x1
|
||||
.byte 0x33
|
||||
.4byte 0x171
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_5b
|
||||
.uleb128 0x8
|
||||
.4byte 0x14f
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x186
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x2
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF17
|
||||
.byte 0x1
|
||||
.byte 0x38
|
||||
.4byte 0x198
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_5f2d
|
||||
.uleb128 0x8
|
||||
.4byte 0x176
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x1ad
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x1
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF18
|
||||
.byte 0x1
|
||||
.byte 0x3d
|
||||
.4byte 0x1bf
|
||||
.byte 0x24
|
||||
.4byte 0x133
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_5f35
|
||||
.uleb128 0x8
|
||||
.4byte 0x19d
|
||||
.4byte 0x111
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x1d4
|
||||
.4byte 0x6e
|
||||
.4byte 0x148
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x3
|
||||
.byte 0x14
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF19
|
||||
.4byte .LASF15
|
||||
.byte 0x1
|
||||
.byte 0x43
|
||||
.4byte 0x1e6
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_93
|
||||
.uleb128 0x8
|
||||
.4byte 0x1c4
|
||||
.uleb128 0x7
|
||||
.4byte .LASF20
|
||||
.byte 0x1
|
||||
.byte 0x48
|
||||
.4byte 0x1fd
|
||||
.byte 0x29
|
||||
.4byte 0x15a
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte do_5f50
|
||||
.uleb128 0x8
|
||||
.4byte 0xea
|
||||
.4byte 0x138
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x212
|
||||
.4byte 0x6e
|
||||
.4byte 0x16f
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x5
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF21
|
||||
.4byte .LASF16
|
||||
.byte 0x1
|
||||
.byte 0x4e
|
||||
.4byte 0x224
|
||||
.byte 0x2f
|
||||
.4byte 0x181
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte get_data_rb_result
|
||||
.uleb128 0x8
|
||||
.4byte 0x202
|
||||
.uleb128 0x5
|
||||
.4byte 0x7e
|
||||
.4byte 0x239
|
||||
.uleb128 0x6
|
||||
.4byte 0x6b
|
||||
.byte 0x8b
|
||||
.byte 0x0
|
||||
.uleb128 0x7
|
||||
.4byte .LASF22
|
||||
.byte 0x1
|
||||
.byte 0x52
|
||||
.4byte 0x24b
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte get_data_sigkey_result
|
||||
.uleb128 0x8
|
||||
.4byte 0x229
|
||||
.uleb128 0x7
|
||||
.4byte .LASF23
|
||||
.byte 0x1
|
||||
.byte 0x6b
|
||||
.4byte 0x262
|
||||
.byte 0x1
|
||||
.byte 0x5
|
||||
.byte 0x3
|
||||
.4byte get_data_enckey_result
|
||||
.uleb128 0x8
|
||||
.4byte 0x229
|
||||
.4byte 0x15f
|
||||
.byte 0x0
|
||||
.section .debug_abbrev
|
||||
.uleb128 0x1
|
||||
@@ -877,92 +405,64 @@ get_data_enckey_result:
|
||||
.byte 0x0
|
||||
.byte 0x0
|
||||
.section .debug_pubnames,"",%progbits
|
||||
.4byte 0xe0
|
||||
.4byte 0x78
|
||||
.2byte 0x2
|
||||
.4byte .Ldebug_info0
|
||||
.4byte 0x268
|
||||
.4byte 0x187
|
||||
.4byte 0x85
|
||||
.ascii "select_file_TOP_result\000"
|
||||
.4byte 0xac
|
||||
.ascii "do_5e\000"
|
||||
.4byte 0xd3
|
||||
.ascii "do_c4\000"
|
||||
.4byte 0xfa
|
||||
.ascii "do_c7\000"
|
||||
.4byte 0x111
|
||||
.ascii "do_ca\000"
|
||||
.4byte 0x138
|
||||
.ascii "do_ce\000"
|
||||
.4byte 0x15f
|
||||
.ascii "do_5b\000"
|
||||
.4byte 0x186
|
||||
.4byte 0xfa
|
||||
.ascii "do_5f2d\000"
|
||||
.4byte 0x1ad
|
||||
.4byte 0x121
|
||||
.ascii "do_5f35\000"
|
||||
.4byte 0x1d4
|
||||
.ascii "do_93\000"
|
||||
.4byte 0x1eb
|
||||
.4byte 0x148
|
||||
.ascii "do_5f50\000"
|
||||
.4byte 0x212
|
||||
.4byte 0x16f
|
||||
.ascii "get_data_rb_result\000"
|
||||
.4byte 0x239
|
||||
.ascii "get_data_sigkey_result\000"
|
||||
.4byte 0x250
|
||||
.ascii "get_data_enckey_result\000"
|
||||
.4byte 0x0
|
||||
.section .debug_str,"MS",%progbits,1
|
||||
.LASF7:
|
||||
.ascii "long long int\000"
|
||||
.LASF4:
|
||||
.ascii "short unsigned int\000"
|
||||
.LASF0:
|
||||
.ascii "unsigned int\000"
|
||||
.LASF2:
|
||||
.ascii "unsigned char\000"
|
||||
.LASF17:
|
||||
.LASF13:
|
||||
.ascii "do_5f2d\000"
|
||||
.LASF23:
|
||||
.ascii "get_data_enckey_result\000"
|
||||
.LASF6:
|
||||
.ascii "long unsigned int\000"
|
||||
.LASF8:
|
||||
.ascii "long long unsigned int\000"
|
||||
.LASF19:
|
||||
.ascii "do_93\000"
|
||||
.LASF14:
|
||||
.ascii "do_ca\000"
|
||||
.LASF24:
|
||||
.LASF10:
|
||||
.ascii "select_file_TOP_result\000"
|
||||
.LASF17:
|
||||
.ascii "GNU C 4.4.2\000"
|
||||
.LASF15:
|
||||
.ascii "do_ce\000"
|
||||
.LASF18:
|
||||
.LASF2:
|
||||
.ascii "unsigned char\000"
|
||||
.LASF14:
|
||||
.ascii "do_5f35\000"
|
||||
.LASF9:
|
||||
.ascii "char\000"
|
||||
.LASF21:
|
||||
.LASF16:
|
||||
.ascii "get_data_rb_result\000"
|
||||
.LASF5:
|
||||
.ascii "long int\000"
|
||||
.LASF20:
|
||||
.LASF15:
|
||||
.ascii "do_5f50\000"
|
||||
.LASF12:
|
||||
.ascii "do_c4\000"
|
||||
.LASF10:
|
||||
.ascii "select_file_TOP_result\000"
|
||||
.LASF13:
|
||||
.ascii "do_c7\000"
|
||||
.LASF18:
|
||||
.ascii "gpg-data.c\000"
|
||||
.LASF4:
|
||||
.ascii "short unsigned int\000"
|
||||
.LASF1:
|
||||
.ascii "signed char\000"
|
||||
.LASF22:
|
||||
.ascii "get_data_sigkey_result\000"
|
||||
.LASF26:
|
||||
.LASF19:
|
||||
.ascii "/var/tmp/stm32/gnuk/src\000"
|
||||
.LASF3:
|
||||
.ascii "short int\000"
|
||||
.LASF16:
|
||||
.LASF12:
|
||||
.ascii "do_5b\000"
|
||||
.LASF11:
|
||||
.ascii "do_5e\000"
|
||||
.LASF25:
|
||||
.ascii "gpg-data.c\000"
|
||||
.ident "GCC: (GNU) 4.4.2"
|
||||
|
||||
296
src/gpg.c
296
src/gpg.c
@@ -1,296 +0,0 @@
|
||||
/*
|
||||
* gpg.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
||||
extern unsigned char *rsa_sign (unsigned char *);
|
||||
|
||||
#define INS_PUT_DATA 0xDA
|
||||
#define INS_PUT_DATA_ODD 0xDB /* For key import */
|
||||
#define INS_VERIFY 0x20
|
||||
#define INS_GET_DATA 0xCA
|
||||
#define INS_GET_RESPONSE 0xC0
|
||||
#define INS_SELECT_FILE 0xA4
|
||||
#define INS_READ_BINARY 0xB0
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_PSO 0x2A
|
||||
|
||||
extern const char const select_file_TOP_result[20];
|
||||
extern const char const get_data_rb_result[6];
|
||||
extern const char const get_data_sigkey_result[7+128];
|
||||
extern const char const get_data_enckey_result[7+128];
|
||||
|
||||
|
||||
void
|
||||
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
||||
{
|
||||
res_APDU_size = 2 + len;
|
||||
if (len)
|
||||
memcpy (res_APDU, p, len);
|
||||
res_APDU[len] = sw1;
|
||||
res_APDU[len+1] = sw2;
|
||||
}
|
||||
|
||||
#define FILE_NONE -1
|
||||
#define FILE_DF_OPENPGP 0
|
||||
#define FILE_MF 1
|
||||
#define FILE_EF_DIR 2
|
||||
#define FILE_EF_SERIAL 3
|
||||
|
||||
static int file_selection = FILE_NONE;
|
||||
|
||||
static void
|
||||
process_command_apdu (void)
|
||||
{
|
||||
uint16_t tag;
|
||||
uint8_t *data;
|
||||
int len;
|
||||
|
||||
if (cmd_APDU[1] == INS_VERIFY)
|
||||
{
|
||||
uint8_t p2 = cmd_APDU[3];
|
||||
int r;
|
||||
|
||||
put_string (" - VERIFY\r\n");
|
||||
|
||||
len = cmd_APDU[4];
|
||||
if (p2 == 0x81)
|
||||
r = verify_pso_cds (&cmd_APDU[5], len);
|
||||
else if (p2 == 0x82)
|
||||
r = verify_pso_other (&cmd_APDU[5], len);
|
||||
else
|
||||
r = verify_pso_admin (&cmd_APDU[5], len);
|
||||
|
||||
if (r < 0)
|
||||
write_res_apdu (NULL, 0, 0x69, 0x82);
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_APDU[1] == INS_PUT_DATA || cmd_APDU[1] == INS_PUT_DATA_ODD)
|
||||
{
|
||||
put_string (" - PUT DATA\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
|
||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||
len = cmd_APDU_size - 5;
|
||||
data = &cmd_APDU[5];
|
||||
if (len >= 256)
|
||||
/* extended Lc */
|
||||
{
|
||||
data += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
gpg_do_put_data (tag, data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_APDU[1] == INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR)
|
||||
{
|
||||
put_string (" - Generate Asymmetric Key Pair\r\n");
|
||||
|
||||
if (cmd_APDU[2] == 0x81)
|
||||
{
|
||||
/*
|
||||
* tag: 0x7f49 public key data
|
||||
* tag: 0x0081 RSA modulus
|
||||
* tag: 0x0082 RSA exponent
|
||||
*
|
||||
* TAG
|
||||
* [0x7f 0x49][LEN][DATA]
|
||||
* _______/ \_________________
|
||||
* / \
|
||||
* [0x81][128][DATA][0x82][3][DATA]
|
||||
* __/ \__ 0x01, 0x00, 0x01
|
||||
* / \
|
||||
* 0x81 0x80
|
||||
*/
|
||||
|
||||
if (cmd_APDU[6] == 0x00 && cmd_APDU[5] == 0xb6)
|
||||
{ /* Key for Sign */
|
||||
write_res_apdu (get_data_sigkey_result,
|
||||
sizeof (get_data_sigkey_result), 0x90, 0x00);
|
||||
}
|
||||
else if (cmd_APDU[6] == 0x00 && cmd_APDU[5] == 0xb8)
|
||||
{ /* Key for Encryption */
|
||||
write_res_apdu (get_data_enckey_result,
|
||||
sizeof (get_data_enckey_result), 0x90, 0x00);
|
||||
}
|
||||
/* cmd_APDU[5] == 0xa4 */
|
||||
else
|
||||
{
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
}
|
||||
else if (cmd_APDU[1] == INS_READ_BINARY)
|
||||
{
|
||||
put_string (" - Read binary\r\n");
|
||||
|
||||
if (file_selection == FILE_EF_SERIAL)
|
||||
{
|
||||
if (cmd_APDU[3] >= 6)
|
||||
write_res_apdu (NULL, 0, 0x6b, 0x00); /* BAD_P0_P1 */
|
||||
else
|
||||
/* Tag 5a, serial number */
|
||||
write_res_apdu (get_data_rb_result,
|
||||
sizeof (get_data_rb_result), 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
else if (cmd_APDU[1] == INS_SELECT_FILE)
|
||||
{
|
||||
if (cmd_APDU[2] == 4) /* Selection by DF name */
|
||||
{
|
||||
put_string (" - select DF by name\r\n");
|
||||
|
||||
/*
|
||||
* P2 == 0, LC=6, name = D2 76 00 01 24 01
|
||||
*/
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
|
||||
/* XXX: Should return contents??? */
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x2f
|
||||
&& cmd_APDU[6] == 0x02)
|
||||
{
|
||||
put_string (" - select 0x2f02 EF\r\n");
|
||||
/*
|
||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||
*/
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
file_selection = FILE_EF_SERIAL;
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x3f
|
||||
&& cmd_APDU[6] == 0x00)
|
||||
{
|
||||
put_string (" - select ROOT MF\r\n");
|
||||
if (cmd_APDU[3] == 0x0c)
|
||||
{
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_res_apdu (select_file_TOP_result,
|
||||
sizeof (select_file_TOP_result), 0x90, 0x00);
|
||||
}
|
||||
|
||||
file_selection = FILE_MF;
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string (" - select ?? \r\n");
|
||||
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x82); /* File missing */
|
||||
file_selection = FILE_NONE;
|
||||
}
|
||||
}
|
||||
else if (cmd_APDU[1] == INS_GET_DATA)
|
||||
{
|
||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||
|
||||
put_string (" - Get Data\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
|
||||
gpg_do_get_data (tag);
|
||||
}
|
||||
else if (cmd_APDU[1] == INS_PSO)
|
||||
{
|
||||
put_string (" - PSO\r\n");
|
||||
|
||||
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
|
||||
{
|
||||
if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
|
||||
/* Extended Lc: 3-byte */
|
||||
{
|
||||
put_string (" wrong length: ");
|
||||
put_short (cmd_APDU_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char * r = rsa_sign (&cmd_APDU[7]);
|
||||
write_res_apdu (r, RSA_SIGNATURE_LENGTH, 0x90, 0x00);
|
||||
}
|
||||
|
||||
put_string ("done.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string (" - ??");
|
||||
put_byte (cmd_APDU[2]);
|
||||
put_string (" - ??");
|
||||
put_byte (cmd_APDU[3]);
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
put_string (" - ??");
|
||||
put_byte (cmd_APDU[1]);
|
||||
write_res_apdu (NULL, 0, 0x6D, 0x00); /* INS not supported. */
|
||||
}
|
||||
}
|
||||
|
||||
Thread *gpg_thread;
|
||||
|
||||
msg_t
|
||||
GPGthread (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
gpg_thread = chThdSelf ();
|
||||
chEvtClear (ALL_EVENTS);
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
m = chEvtWaitOne (ALL_EVENTS);
|
||||
|
||||
_write ("GPG!\r\n", 6);
|
||||
|
||||
process_command_apdu ();
|
||||
|
||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
src/hardclock.c
Normal file
8
src/hardclock.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
uint32_t
|
||||
hardclock (void)
|
||||
{
|
||||
return SysTick->VAL;
|
||||
}
|
||||
98
src/main.c
98
src/main.c
@@ -53,6 +53,7 @@ Thread1 (void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static
|
||||
struct stdout {
|
||||
Mutex m;
|
||||
@@ -94,9 +95,8 @@ extern uint8_t buffer_in[VIRTUAL_COM_PORT_DATA_SIZE];
|
||||
extern uint8_t buffer_out[VIRTUAL_COM_PORT_DATA_SIZE];
|
||||
extern void USB_Init (void);
|
||||
|
||||
|
||||
static WORKING_AREA(waThread2, 128);
|
||||
static msg_t Thread2 (void *arg)
|
||||
static WORKING_AREA(waSTDOUTthread, 128);
|
||||
static msg_t STDOUTthread (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
@@ -160,6 +160,19 @@ static msg_t Thread2 (void *arg)
|
||||
goto again;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
stdout_init (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_write (const char *s, int size)
|
||||
{
|
||||
(void)s;
|
||||
(void)size;
|
||||
}
|
||||
#endif
|
||||
|
||||
static WORKING_AREA(waUSBthread, 128*2);
|
||||
extern msg_t USBthread (void *arg);
|
||||
@@ -167,6 +180,66 @@ extern msg_t USBthread (void *arg);
|
||||
static WORKING_AREA(waGPGthread, 128*16);
|
||||
extern msg_t GPGthread (void *arg);
|
||||
|
||||
/*
|
||||
* XXX: I have tried havege_rand, but it requires too much memory...
|
||||
*/
|
||||
/*
|
||||
* Multiply-with-carry method by George Marsaglia
|
||||
*/
|
||||
static uint32_t m_w;
|
||||
static uint32_t m_z;
|
||||
|
||||
static void
|
||||
random_init (void)
|
||||
{
|
||||
static uint8_t s = 0;
|
||||
|
||||
again:
|
||||
switch ((s & 1))
|
||||
{
|
||||
case 0:
|
||||
m_w = (m_w << 8) ^ hardclock ();
|
||||
break;
|
||||
case 1:
|
||||
m_z = (m_z << 8) ^ hardclock ();
|
||||
break;
|
||||
}
|
||||
|
||||
s++;
|
||||
if (m_w == 0 || m_z == 0)
|
||||
goto again;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_random (void)
|
||||
{
|
||||
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
|
||||
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
|
||||
|
||||
return (m_z << 16) + m_w;
|
||||
}
|
||||
|
||||
uint8_t dek[16];
|
||||
uint8_t *get_data_encryption_key (void)
|
||||
{
|
||||
uint32_t r;
|
||||
r = get_random ();
|
||||
memcpy (dek, &r, 4);
|
||||
r = get_random ();
|
||||
memcpy (dek+4, &r, 4);
|
||||
r = get_random ();
|
||||
memcpy (dek+8, &r, 4);
|
||||
r = get_random ();
|
||||
memcpy (dek+12, &r, 4);
|
||||
return dek;
|
||||
}
|
||||
|
||||
void dek_free (uint8_t *dek)
|
||||
{
|
||||
(void)dek;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Entry point, note, the main() function is already a thread in the system
|
||||
* on entry.
|
||||
@@ -190,10 +263,12 @@ main (int argc, char **argv)
|
||||
*/
|
||||
chThdCreateStatic (waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Creates 'stdout' thread.
|
||||
*/
|
||||
chThdCreateStatic (waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
|
||||
chThdCreateStatic (waSTDOUTthread2, sizeof(waSTDOUTthread2), NORMALPRIO, STDOUTthread2, NULL);
|
||||
#endif
|
||||
|
||||
chThdCreateStatic (waUSBthread, sizeof(waUSBthread), NORMALPRIO, USBthread, NULL);
|
||||
chThdCreateStatic (waGPGthread, sizeof(waGPGthread), NORMALPRIO, GPGthread, NULL);
|
||||
@@ -207,9 +282,15 @@ main (int argc, char **argv)
|
||||
|
||||
chThdSleepMilliseconds (100);
|
||||
|
||||
if (bDeviceState != CONFIGURED)
|
||||
random_init ();
|
||||
|
||||
if (bDeviceState == CONFIGURED && (count % 300) == 0)
|
||||
{
|
||||
_write ("0123456789"+((count / 300)%10), 1);
|
||||
uint32_t r;
|
||||
r = get_random ();
|
||||
|
||||
DEBUG_SHORT (r);
|
||||
_write ("\r\nThis is ChibiOS 2.0.2 on Olimex STM32-H103.\r\n"
|
||||
"Testing USB driver.\n\n"
|
||||
"Hello world\r\n\r\n", 47+21+15);
|
||||
@@ -219,3 +300,10 @@ main (int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fatal (void)
|
||||
{
|
||||
_write ("fatal\r\n", 7);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
675
src/openpgp-do.c
675
src/openpgp-do.c
@@ -25,9 +25,11 @@
|
||||
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
#include "openpgp.h"
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/aes.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
/*
|
||||
* Compile time vars:
|
||||
@@ -84,39 +86,19 @@ static const uint8_t const algorithm_attr[] __attribute__ ((aligned (1))) = {
|
||||
0x00 /* 0: p&q , 3: CRT with N (not yet supported) */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define SIZE_PW_STATUS_BYTES 7
|
||||
#if 0
|
||||
const uint8_t const pw_status_bytes_template[] =
|
||||
{
|
||||
1, /* PW1 valid for several PSO:CDS commands */
|
||||
127, 127, 127, /* max length of PW1, RC, and PW3 */
|
||||
3, 0, 3 /* Error counter of PW1, RC, and PW3 */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define SIZE_DIGITAL_SIGNATURE_COUNTER 3
|
||||
#if 0
|
||||
{
|
||||
0, 0, 0 /* 3-byte binary */
|
||||
};
|
||||
#endif
|
||||
/* 3-byte binary (big endian) */
|
||||
|
||||
#define SIZE_FINGER_PRINT 20
|
||||
#define SIZE_KEYGEN_TIME 4 /* RFC4880 */
|
||||
|
||||
/* Runtime vars: PSO */
|
||||
|
||||
struct key_store {
|
||||
uint8_t p[128];
|
||||
uint8_t q[128];
|
||||
};
|
||||
|
||||
static struct key_store key_sig, key_dec, key_aut;
|
||||
|
||||
#define HASH_SIZE 20
|
||||
static uint8_t pw3_hash[HASH_SIZE];
|
||||
|
||||
enum do_type {
|
||||
DO_FIXED,
|
||||
DO_VAR,
|
||||
@@ -124,8 +106,6 @@ enum do_type {
|
||||
DO_PROC_READ,
|
||||
DO_PROC_WRITE,
|
||||
DO_PROC_READWRITE,
|
||||
DO_HASH,
|
||||
DO_KEYPTR
|
||||
};
|
||||
|
||||
struct do_table_entry {
|
||||
@@ -142,13 +122,6 @@ static int with_tag;
|
||||
static void copy_do_1 (uint16_t tag, const uint8_t *do_data);
|
||||
static struct do_table_entry *get_do_entry (uint16_t tag);
|
||||
|
||||
#define GNUK_DO_KEYPTR_SIG 0xff01
|
||||
#define GNUK_DO_KEYPTR_DEC 0xff02
|
||||
#define GNUK_DO_KEYPTR_AUT 0xff03
|
||||
#define GNUK_DO_HASH_PW3 0xff04
|
||||
#define GNUK_DO_HASH_RC 0xff05
|
||||
#define GNUK_DO_PW_STATUS 0xff06
|
||||
|
||||
#define GPG_DO_AID 0x004f
|
||||
#define GPG_DO_NAME 0x005b
|
||||
#define GPG_DO_LOGIN_DATA 0x005e
|
||||
@@ -194,18 +167,19 @@ copy_tag (uint16_t tag)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
do_hist_bytes (uint16_t tag)
|
||||
{
|
||||
/* XXX: For now, no life cycle management, just return template as is. */
|
||||
/* XXX: Supporing TERMINATE DF / ACTIVATE FILE, we need to fix here */
|
||||
copy_do_1 (tag, historical_bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SIZE_FP 20
|
||||
#define SIZE_KGTIME 4
|
||||
|
||||
static void
|
||||
static int
|
||||
do_fp_all (uint16_t tag)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
@@ -240,9 +214,11 @@ do_fp_all (uint16_t tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_FP);
|
||||
res_p += SIZE_FP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
do_cafp_all (uint16_t tag)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
@@ -277,9 +253,11 @@ do_cafp_all (uint16_t tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_FP);
|
||||
res_p += SIZE_FP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
do_kgtime_all (uint16_t tag)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
@@ -314,33 +292,38 @@ do_kgtime_all (uint16_t tag)
|
||||
else
|
||||
memset (res_p, 0, SIZE_KGTIME);
|
||||
res_p += SIZE_KGTIME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rw_pw_status (uint16_t tag, uint8_t *data, int len, int is_write)
|
||||
static int
|
||||
rw_pw_status (uint16_t tag, const uint8_t *data, int len, int is_write)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
|
||||
if (is_write)
|
||||
{
|
||||
const uint8_t *do_data;
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
(void)len;
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
if (do_p)
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
{
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
memcpy (data, &do_data[2], SIZE_PW_STATUS_BYTES - 1);
|
||||
|
||||
do_p->obj = flash_do_write (tag, data, len);
|
||||
if (do_p->obj)
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
||||
flash_do_release (do_p->obj);
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
memcpy (pwsb, pw_status_bytes_template, SIZE_PW_STATUS_BYTES);
|
||||
|
||||
pwsb[0] = data[0];
|
||||
do_p->obj = flash_do_write (tag, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
if (do_p->obj)
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
GPG_MEMORY_FAILURE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -360,184 +343,308 @@ rw_pw_status (uint16_t tag, uint8_t *data, int len, int is_write)
|
||||
res_p += SIZE_PW_STATUS_BYTES;
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
proc_resetting_code (uint16_t tag, uint8_t *data, int len)
|
||||
{
|
||||
/* Not implementad yet */
|
||||
/*
|
||||
* calculate hash, write it to GNUK_DO_HASH_RC.
|
||||
*/
|
||||
/* Then, we need to reset RC counter in GNUK_DO_PW_STATUS */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t iv[16];
|
||||
|
||||
static aes_context aes;
|
||||
static uint8_t iv[16];
|
||||
static int iv_offset;
|
||||
|
||||
static void
|
||||
encrypt (uint8_t *key_str, uint8_t *data)
|
||||
proc_resetting_code (const uint8_t *data, int len)
|
||||
{
|
||||
const uint8_t *old_ks = keystring_md_pw3;
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
const uint8_t *newpw;
|
||||
int newpw_len;
|
||||
int r;
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
struct do_table_entry *do_p;
|
||||
const uint8_t *do_data;
|
||||
|
||||
newpw_len = len;
|
||||
newpw = data;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (3, old_ks, 2, new_ks);
|
||||
if (r < -2)
|
||||
{
|
||||
GPG_MEMORY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (r < 0)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (r == 0)
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_RC, new_ks0, KEYSTRING_SIZE_RC);
|
||||
else
|
||||
GPG_SUCCESS ();
|
||||
|
||||
/* Reset RC counter in GNUK_DO_PW_STATUS */
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
{
|
||||
memcpy (pwsb, &do_data[1], SIZE_PW_STATUS_BYTES);
|
||||
pwsb[PW_STATUS_RC] = 3;
|
||||
flash_do_release (do_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (pwsb, pw_status_bytes_template, SIZE_PW_STATUS_BYTES);
|
||||
pwsb[5] = 3;
|
||||
}
|
||||
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
static void
|
||||
encrypt (const uint8_t *key_str, uint8_t *data, int len)
|
||||
{
|
||||
aes_setkey_enc (&aes, key_str, 128);
|
||||
memset (iv, 0, 16);
|
||||
iv_offset = 0;
|
||||
aes_crypt_cfb128 (&aes, AES_ENCRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
|
||||
aes_crypt_cfb128 (&aes, AES_ENCRYPT, len, &iv_offset, iv, data, data);
|
||||
|
||||
{
|
||||
int i, len = KEYSTORE_LEN;
|
||||
|
||||
put_string ("ENC\r\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
DEBUG_INFO ("ENC\r\n");
|
||||
DEBUG_BINARY (data, KEYSTORE_LEN);
|
||||
}
|
||||
|
||||
struct key_data kd;
|
||||
|
||||
static void
|
||||
decrypt (uint8_t *key_str, uint8_t *data)
|
||||
decrypt (const uint8_t *key_str, uint8_t *data, int len)
|
||||
{
|
||||
aes_setkey_enc (&aes, key_str, 128);
|
||||
memset (iv, 0, 16);
|
||||
iv_offset = 0;
|
||||
aes_crypt_cfb128 (&aes, AES_DECRYPT, KEYSTORE_LEN, &iv_offset, iv, data, data);
|
||||
{
|
||||
int i, len = KEYSTORE_LEN;
|
||||
|
||||
put_string ("DEC\r\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
aes_crypt_cfb128 (&aes, AES_DECRYPT, len, &iv_offset, iv, data, data);
|
||||
DEBUG_INFO ("DEC\r\n");
|
||||
DEBUG_BINARY (data, KEYSTORE_LEN);
|
||||
}
|
||||
|
||||
int
|
||||
gpg_load_key (enum kind_of_key kk)
|
||||
static uint16_t
|
||||
get_tag_for_kk (enum kind_of_key kk)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
|
||||
switch (kk)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
|
||||
break;
|
||||
return GNUK_DO_PRVKEY_SIG;
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
|
||||
break;
|
||||
return GNUK_DO_PRVKEY_DEC;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
|
||||
break;
|
||||
return GNUK_DO_PRVKEY_AUT;
|
||||
}
|
||||
if (do_p == NULL)
|
||||
return -1;
|
||||
return GNUK_DO_PRVKEY_SIG;
|
||||
}
|
||||
|
||||
kd.key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
|
||||
memcpy (((uint8_t *)&kd)+4, ((uint8_t *)do_p->obj)+5, KEY_MAGIC_LEN+4+4);
|
||||
memcpy (kd.data, kd.key_addr, KEY_CONTENT_LEN);
|
||||
/*
|
||||
* Return 1 on success,
|
||||
* 0 if none,
|
||||
* -1 on error,
|
||||
*/
|
||||
int
|
||||
gpg_do_load_prvkey (enum kind_of_key kk, int who, const uint8_t *keystring)
|
||||
{
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
struct do_table_entry *do_p = get_do_entry (tag);
|
||||
uint8_t *key_addr;
|
||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||
|
||||
decrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
|
||||
if (do_p->obj == NULL)
|
||||
return 0;
|
||||
|
||||
key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
|
||||
memcpy (kd.data, key_addr, KEY_CONTENT_LEN);
|
||||
memcpy (((uint8_t *)&kd.check), ((uint8_t *)do_p->obj)+5, ADDITIONAL_DATA_SIZE);
|
||||
memcpy (dek, ((uint8_t *)do_p->obj)+5+16*who, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
decrypt (keystring, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt (dek, (uint8_t *)&kd, sizeof (kd));
|
||||
if (memcmp (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN) != 0)
|
||||
return -1;
|
||||
/* XXX: more sanity check */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_random (void)
|
||||
{
|
||||
return 0x80808080; /* XXX: for now */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
calc_check (uint8_t *data, int len)
|
||||
calc_check32 (const uint8_t *p, int len)
|
||||
{
|
||||
uint32_t check = 0;
|
||||
uint32_t *data = (uint32_t *)p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
for (i = 0; i < len/4; i++)
|
||||
check += data[i];
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
static int
|
||||
gpg_write_do_keyptr (enum kind_of_key kk, uint8_t *key_data, int key_len)
|
||||
int
|
||||
gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
const uint8_t *keystring)
|
||||
{
|
||||
uint8_t *p;
|
||||
int len;
|
||||
const uint8_t *p;
|
||||
int r;
|
||||
uint32_t key_addr;
|
||||
struct do_table_entry *do_p;
|
||||
const uint8_t *modulus;
|
||||
struct key_data *kd;
|
||||
struct prvkey_data *pd;
|
||||
uint8_t *key_addr;
|
||||
uint8_t *dek;
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
|
||||
|
||||
#if 0
|
||||
assert (key_len == KEY_CONTENT_LEN+4);
|
||||
/* key_data should starts with 00 01 00 01 (E) */
|
||||
assert (key_len == KEY_CONTENT_LEN);
|
||||
#endif
|
||||
|
||||
put_short (key_len);
|
||||
DEBUG_SHORT (key_len);
|
||||
|
||||
key_data += 4;
|
||||
|
||||
kd.key_addr = flash_key_alloc (kk);
|
||||
if (kd.key_addr == NULL)
|
||||
kd = (struct key_data *)malloc (sizeof (struct key_data));
|
||||
if (kd == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy (kd.magic, GNUK_MAGIC, KEY_MAGIC_LEN);
|
||||
kd.check = calc_check (key_data, KEY_CONTENT_LEN);
|
||||
kd.random = get_random ();
|
||||
memcpy (kd.data, key_data, KEY_CONTENT_LEN);
|
||||
|
||||
put_string ("enc...");
|
||||
|
||||
encrypt (keystring_pw1, ((uint8_t *)&kd) + 4);
|
||||
|
||||
put_string ("done\r\n");
|
||||
|
||||
if ((r = flash_key_write (kd.key_addr, kd.data)) < 0)
|
||||
return r;
|
||||
|
||||
switch (kk)
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
if (pd == NULL)
|
||||
{
|
||||
case GPG_KEY_FOR_SIGNATURE:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_SIG, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_SIG);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
case GPG_KEY_FOR_DECRYPT:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_DEC, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_DEC);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
case GPG_KEY_FOR_AUTHENTICATION:
|
||||
p = flash_do_write (GNUK_DO_KEYPTR_AUT, &kd,
|
||||
sizeof (kd) - KEY_CONTENT_LEN);
|
||||
do_p = get_do_entry (GNUK_DO_KEYPTR_AUT);
|
||||
do_p->obj = p;
|
||||
break;
|
||||
free (kd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
modulus = modulus_calc (key_data, key_len);
|
||||
if (modulus == NULL)
|
||||
{
|
||||
free (kd);
|
||||
free (pd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key_addr = flash_key_alloc (kk);
|
||||
if (key_addr == NULL)
|
||||
{
|
||||
free (kd);
|
||||
free (pd);
|
||||
modulus_free (modulus);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (kd->data, key_data, KEY_CONTENT_LEN);
|
||||
kd->check = calc_check32 (key_data, KEY_CONTENT_LEN);
|
||||
kd->random = get_random ();
|
||||
memcpy (kd->magic, GNUK_MAGIC, KEY_MAGIC_LEN);
|
||||
|
||||
DEBUG_INFO ("enc...");
|
||||
|
||||
dek = get_data_encryption_key (); /* 16-byte random bytes */
|
||||
encrypt (dek, (uint8_t *)kd, sizeof (kd));
|
||||
|
||||
DEBUG_INFO ("done\r\n");
|
||||
|
||||
r = flash_key_write (key_addr, kd->data, modulus);
|
||||
modulus_free (modulus);
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
dek_free (dek);
|
||||
free (pd);
|
||||
free (kd);
|
||||
return r;
|
||||
}
|
||||
|
||||
pd->key_addr = key_addr;
|
||||
memcpy (pd->crm_encrypted, (uint8_t *)&kd->check, ADDITIONAL_DATA_SIZE);
|
||||
|
||||
reset_pso_cds ();
|
||||
if (ks_pw1)
|
||||
{
|
||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, ks_pw1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
|
||||
|
||||
ks123_pw1[0] = 6;
|
||||
sha1 ((uint8_t *)"123456", 6, ks123_pw1+1);
|
||||
memcpy (pd->dek_encrypted_1, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only but its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, ks123_pw1, 1);
|
||||
}
|
||||
|
||||
if (ks_rc)
|
||||
{
|
||||
memcpy (pd->dek_encrypted_2, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (ks_rc+1, pd->dek_encrypted_2, DATA_ENCRYPTION_KEY_SIZE);
|
||||
/* Only its length */
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_RC, ks_rc, 1);
|
||||
}
|
||||
else
|
||||
memset (pd->dek_encrypted_2, 0, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
memcpy (pd->dek_encrypted_3, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (keystring, pd->dek_encrypted_3, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
p = flash_do_write (tag, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_p = get_do_entry (tag);
|
||||
do_p->obj = p;
|
||||
|
||||
dek_free (dek);
|
||||
free (kd);
|
||||
free (pd);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gpg_do_chks_prvkey (enum kind_of_key kk,
|
||||
int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks)
|
||||
{
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
struct do_table_entry *do_p = get_do_entry (tag);
|
||||
uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
|
||||
struct prvkey_data *pd;
|
||||
const uint8_t *p;
|
||||
uint8_t *dek_p;
|
||||
|
||||
if (do_p->obj == NULL)
|
||||
return 0; /* No private key */
|
||||
|
||||
pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
|
||||
if (pd == NULL)
|
||||
return -1;
|
||||
|
||||
memcpy (pd, &((uint8_t *)do_p->obj)[1], sizeof (struct prvkey_data));
|
||||
dek_p = ((uint8_t *)pd) + 4 + ADDITIONAL_DATA_SIZE + DATA_ENCRYPTION_KEY_SIZE * (who_old - 1);
|
||||
memcpy (dek, dek_p, DATA_ENCRYPTION_KEY_SIZE);
|
||||
decrypt (old_ks, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
encrypt (new_ks, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
dek_p += DATA_ENCRYPTION_KEY_SIZE * (who_new - who_old);
|
||||
memcpy (dek_p, dek, DATA_ENCRYPTION_KEY_SIZE);
|
||||
|
||||
p = flash_do_write (tag, (const uint8_t *)pd, sizeof (struct prvkey_data));
|
||||
do_p->obj = p;
|
||||
|
||||
free (pd);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 4d, xx, xx: Extended Header List
|
||||
* b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT)
|
||||
@@ -548,31 +655,45 @@ gpg_write_do_keyptr (enum kind_of_key kk, uint8_t *key_data, int key_len)
|
||||
* 5f48, xx: cardholder private key
|
||||
*/
|
||||
static void
|
||||
proc_key_import (uint16_t tag, uint8_t *data, int len)
|
||||
proc_key_import (const uint8_t *data, int len)
|
||||
{
|
||||
int i, r;
|
||||
int r;
|
||||
enum kind_of_key kk;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
put_byte_with_no_nl (data[i]);
|
||||
if ((i & 0x0f) == 0x0f)
|
||||
_write ("\r\n", 2);
|
||||
}
|
||||
_write ("\r\n", 2);
|
||||
DEBUG_BINARY (data, len);
|
||||
|
||||
if (data[4] == 0xa4)
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
if (data[4] == 0xb6)
|
||||
kk = GPG_KEY_FOR_SIGNATURE;
|
||||
else if (data[4] == 0xb8)
|
||||
kk = GPG_KEY_FOR_DECRYPT;
|
||||
else /* 0xb6 */
|
||||
kk = GPG_KEY_FOR_SIGNATURE;
|
||||
else /* 0xa4 */
|
||||
kk = GPG_KEY_FOR_AUTHENTICATION;
|
||||
|
||||
r = gpg_write_do_keyptr (kk, &data[22], len - 22);
|
||||
if (len <= 22)
|
||||
{ /* Deletion of the key */
|
||||
uint16_t tag = get_tag_for_kk (kk);
|
||||
struct do_table_entry *do_p = get_do_entry (tag);
|
||||
|
||||
if (do_p->obj)
|
||||
{
|
||||
uint8_t *key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
|
||||
|
||||
flash_do_release (do_p->obj);
|
||||
flash_key_release (key_addr);
|
||||
}
|
||||
|
||||
do_p->obj = NULL;
|
||||
GPG_SUCCESS ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* It should starts with 00 01 00 01 (E) */
|
||||
/* Skip E, 4-byte */
|
||||
r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_md_pw3);
|
||||
if (r < 0)
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
GPG_MEMORY_FAILURE();
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
static const uint16_t const cn_ch_data[] = {
|
||||
@@ -597,12 +718,13 @@ static const uint16_t const cn_ss_temp[] = { 1, GPG_DO_DS_COUNT };
|
||||
|
||||
static struct do_table_entry
|
||||
gpg_do_table[] = {
|
||||
/* Pseudo DO (private): not user accessible */
|
||||
{ GNUK_DO_KEYPTR_SIG, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYPTR_DEC, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYPTR_AUT, DO_KEYPTR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_HASH_PW3, DO_HASH, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_HASH_RC, DO_HASH, AC_NEVER, AC_NEVER, NULL },
|
||||
/* Pseudo DO (private): not directly user accessible */
|
||||
{ GNUK_DO_PRVKEY_SIG, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_PRVKEY_DEC, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_PRVKEY_AUT, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYSTRING_PW1, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYSTRING_PW3, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_KEYSTRING_RC, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
{ GNUK_DO_PW_STATUS, DO_VAR, AC_NEVER, AC_NEVER, NULL },
|
||||
/* Pseudo DO READ: calculated */
|
||||
{ GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes },
|
||||
@@ -652,14 +774,9 @@ gpg_do_table[] = {
|
||||
#define NUM_DO_ENTRIES (int)(sizeof (gpg_do_table) / sizeof (struct do_table_entry))
|
||||
|
||||
extern const uint8_t const do_5e[];
|
||||
extern const uint8_t const do_c4[];
|
||||
extern const uint8_t const do_c7[];
|
||||
extern const uint8_t const do_ca[];
|
||||
extern const uint8_t const do_ce[];
|
||||
extern const uint8_t const do_5b[];
|
||||
extern const uint8_t const do_5f2d[];
|
||||
extern const uint8_t const do_5f35[];
|
||||
extern const uint8_t const do_93[];
|
||||
extern const uint8_t const do_5f50[];
|
||||
|
||||
/*
|
||||
@@ -673,23 +790,13 @@ gpg_do_table_init (void)
|
||||
do_p = get_do_entry (GPG_DO_LOGIN_DATA);
|
||||
do_p->obj = do_5e;
|
||||
do_p = get_do_entry (GNUK_DO_PW_STATUS);
|
||||
do_p->obj = do_c4;
|
||||
#if 0
|
||||
do_p = get_do_entry (GPG_DO_FP_SIG);
|
||||
do_p->obj = do_c7;
|
||||
do_p = get_do_entry (GPG_DO_CAFP_1);
|
||||
do_p->obj = do_ca;
|
||||
do_p = get_do_entry (GPG_DO_KGTIME_SIG);
|
||||
do_p->obj = do_ce;
|
||||
#endif
|
||||
do_p->obj = pw_status_bytes_template;
|
||||
do_p = get_do_entry (GPG_DO_NAME);
|
||||
do_p->obj = do_5b;
|
||||
do_p = get_do_entry (GPG_DO_LANGUAGE);
|
||||
do_p->obj = do_5f2d;
|
||||
do_p = get_do_entry (GPG_DO_SEX);
|
||||
do_p->obj = do_5f35;
|
||||
do_p = get_do_entry (GPG_DO_DS_COUNT);
|
||||
do_p->obj = do_93;
|
||||
do_p = get_do_entry (GPG_DO_URL);
|
||||
do_p->obj = do_5f50;
|
||||
|
||||
@@ -753,7 +860,7 @@ copy_do (struct do_table_entry *do_p)
|
||||
if (do_p == NULL)
|
||||
return 0;
|
||||
|
||||
if (ac_check_status (do_p->ac_read) == 0)
|
||||
if (!ac_check_status (do_p->ac_read))
|
||||
return -1;
|
||||
|
||||
switch (do_p->do_type)
|
||||
@@ -797,22 +904,18 @@ copy_do (struct do_table_entry *do_p)
|
||||
}
|
||||
case DO_PROC_READ:
|
||||
{
|
||||
void (*do_func)(uint16_t) = (void (*)(uint16_t))do_p->obj;
|
||||
int (*do_func)(uint16_t) = (int (*)(uint16_t))do_p->obj;
|
||||
|
||||
do_func (do_p->tag);
|
||||
break;
|
||||
return do_func (do_p->tag);
|
||||
}
|
||||
case DO_PROC_READWRITE:
|
||||
{
|
||||
void (*rw_func)(uint16_t, uint8_t *, int, int)
|
||||
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
|
||||
int (*rw_func)(uint16_t, uint8_t *, int, int)
|
||||
= (int (*)(uint16_t, uint8_t *, int, int))do_p->obj;
|
||||
|
||||
rw_func (do_p->tag, NULL, 0, 0);
|
||||
break;
|
||||
return rw_func (do_p->tag, NULL, 0, 0);
|
||||
}
|
||||
case DO_PROC_WRITE:
|
||||
case DO_HASH:
|
||||
case DO_KEYPTR:
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -831,16 +934,14 @@ gpg_do_get_data (uint16_t tag)
|
||||
res_p = res_APDU;
|
||||
with_tag = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
put_string (" ");
|
||||
put_short (tag);
|
||||
#endif
|
||||
DEBUG_INFO (" ");
|
||||
DEBUG_SHORT (tag);
|
||||
|
||||
if (do_p)
|
||||
{
|
||||
if (copy_do (do_p) < 0)
|
||||
/* Overwrite partially written result */
|
||||
write_res_apdu (NULL, 0, 0x69, 0x82);
|
||||
/* Overwriting partially written result */
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else
|
||||
{
|
||||
*res_p++ = 0x90;
|
||||
@@ -849,25 +950,22 @@ gpg_do_get_data (uint16_t tag)
|
||||
}
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
GPG_NO_RECORD();
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
|
||||
gpg_do_put_data (uint16_t tag, const uint8_t *data, int len)
|
||||
{
|
||||
struct do_table_entry *do_p = get_do_entry (tag);
|
||||
|
||||
#ifdef DEBUG
|
||||
put_string (" ");
|
||||
put_short (tag);
|
||||
#endif
|
||||
DEBUG_INFO (" ");
|
||||
DEBUG_SHORT (tag);
|
||||
|
||||
if (do_p)
|
||||
{
|
||||
if (ac_check_status (do_p->ac_write) == 0)
|
||||
if (!ac_check_status (do_p->ac_write))
|
||||
{
|
||||
write_res_apdu (NULL, 0, 0x69, 0x82);
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -876,17 +974,15 @@ gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
|
||||
case DO_FIXED:
|
||||
case DO_CN_READ:
|
||||
case DO_PROC_READ:
|
||||
case DO_HASH:
|
||||
case DO_KEYPTR:
|
||||
write_res_apdu (NULL, 0, 0x69, 0x82);
|
||||
GPG_SECURITY_FAILURE ();
|
||||
break;
|
||||
case DO_VAR:
|
||||
{
|
||||
#if 0
|
||||
const uint8_t *do_data = (const uint8_t *)do_p->obj;
|
||||
|
||||
flash_do_release (do_data);
|
||||
#endif
|
||||
if (do_data)
|
||||
flash_do_release (do_data);
|
||||
|
||||
if (len == 0)
|
||||
/* make DO empty */
|
||||
do_p->obj = NULL;
|
||||
@@ -894,31 +990,134 @@ gpg_do_put_data (uint16_t tag, uint8_t *data, int len)
|
||||
{
|
||||
do_p->obj = flash_do_write (tag, data, len);
|
||||
if (do_p->obj)
|
||||
write_res_apdu (NULL, 0, 0x90, 0x00); /* success */
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */
|
||||
GPG_MEMORY_FAILURE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DO_PROC_READWRITE:
|
||||
{
|
||||
void (*rw_func)(uint16_t, uint8_t *, int, int)
|
||||
= (void (*)(uint16_t, uint8_t *, int, int))do_p->obj;
|
||||
int (*rw_func)(uint16_t, const uint8_t *, int, int)
|
||||
= (int (*)(uint16_t, const uint8_t *, int, int))do_p->obj;
|
||||
|
||||
rw_func (tag, data, len, 1);
|
||||
break;
|
||||
}
|
||||
case DO_PROC_WRITE:
|
||||
{
|
||||
void (*proc_func)(uint16_t, uint8_t *, int)
|
||||
= (void (*)(uint16_t, uint8_t *, int))do_p->obj;
|
||||
void (*proc_func)(const uint8_t *, int)
|
||||
= (void (*)(const uint8_t *, int))do_p->obj;
|
||||
|
||||
proc_func (tag, data, len);
|
||||
proc_func (data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/* No record */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88);
|
||||
GPG_NO_RECORD();
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_public_key (uint8_t kk_byte)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
uint8_t *key_addr;
|
||||
|
||||
if (kk_byte == 0xa4)
|
||||
do_p = get_do_entry (GNUK_DO_PRVKEY_AUT);
|
||||
else if (kk_byte == 0xb8)
|
||||
do_p = get_do_entry (GNUK_DO_PRVKEY_DEC);
|
||||
else /* 0xb6 */
|
||||
do_p = get_do_entry (GNUK_DO_PRVKEY_SIG);
|
||||
if (do_p->obj == NULL)
|
||||
{
|
||||
GPG_NO_RECORD();
|
||||
return;
|
||||
}
|
||||
|
||||
key_addr = *(uint8_t **)&((uint8_t *)do_p->obj)[1];
|
||||
|
||||
res_p = res_APDU;
|
||||
|
||||
/* TAG */
|
||||
*res_p++ = 0x7f; *res_p++ = 0x49;
|
||||
/* LEN = 9+256 */
|
||||
*res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x09;
|
||||
|
||||
{
|
||||
/*TAG*/ /*LEN = 256 */
|
||||
*res_p++ = 0x81; *res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x00;
|
||||
/* 256-byte binary (big endian) */
|
||||
memcpy (res_p, key_addr + KEY_CONTENT_LEN, KEY_CONTENT_LEN);
|
||||
res_p += 256;
|
||||
}
|
||||
{
|
||||
/*TAG*/ /*LEN= 3 */
|
||||
*res_p++ = 0x82; *res_p++ = 3;
|
||||
/* 3-byte E=0x10001 (big endian) */
|
||||
*res_p++ = 0x01; *res_p++ = 0x00; *res_p++ = 0x01;
|
||||
|
||||
/* Success */
|
||||
*res_p++ = 0x90; *res_p++ = 0x00;
|
||||
res_APDU_size = res_p - res_APDU;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
gpg_do_read_simple (uint16_t tag)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
const uint8_t *do_data;
|
||||
|
||||
do_p = get_do_entry (tag);
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data == NULL)
|
||||
return NULL;
|
||||
|
||||
return do_data+1;
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_write_simple (uint16_t tag, const uint8_t *data, int size)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
const uint8_t *do_data;
|
||||
|
||||
do_p = get_do_entry (tag);
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data)
|
||||
flash_do_release (do_p->obj);
|
||||
|
||||
do_p->obj = flash_do_write (tag, data, size);
|
||||
if (do_p->obj)
|
||||
GPG_SUCCESS ();
|
||||
else
|
||||
GPG_MEMORY_FAILURE();
|
||||
}
|
||||
|
||||
void
|
||||
gpg_do_increment_digital_signature_counter (void)
|
||||
{
|
||||
struct do_table_entry *do_p;
|
||||
const uint8_t *do_data;
|
||||
uint32_t count;
|
||||
uint8_t count_data[SIZE_DIGITAL_SIGNATURE_COUNTER];
|
||||
|
||||
do_p = get_do_entry (GPG_DO_DS_COUNT);
|
||||
do_data = (const uint8_t *)do_p->obj;
|
||||
if (do_data == NULL) /* No object means count 0 */
|
||||
count = 0;
|
||||
else
|
||||
count = (do_data[1]<<16) | (do_data[2]<<8) | do_data[3];
|
||||
|
||||
count++;
|
||||
count_data[0] = (count >> 16) & 0xff;
|
||||
count_data[1] = (count >> 8) & 0xff;
|
||||
count_data[2] = count & 0xff;
|
||||
|
||||
do_p->obj = flash_do_write (GPG_DO_DS_COUNT, count_data,
|
||||
SIZE_DIGITAL_SIGNATURE_COUNTER);
|
||||
}
|
||||
|
||||
536
src/openpgp.c
Normal file
536
src/openpgp.c
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* openpgp.c -- OpenPGP card protocol support
|
||||
*
|
||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||
*
|
||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||
*
|
||||
* Gnuk is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "gnuk.h"
|
||||
#include "openpgp.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
#define RSA_SIGNATURE_LENGTH 256 /* 256 byte == 2048-bit */
|
||||
|
||||
#define INS_VERIFY 0x20
|
||||
#define INS_CHANGE_REFERENCE_DATA 0x24
|
||||
#define INS_PSO 0x2a
|
||||
#define INS_RESET_RETRY_COUNTER 0x2c
|
||||
#define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR 0x47
|
||||
#define INS_SELECT_FILE 0xa4
|
||||
#define INS_READ_BINARY 0xb0
|
||||
#define INS_GET_DATA 0xca
|
||||
#define INS_PUT_DATA 0xda
|
||||
#define INS_PUT_DATA_ODD 0xdb /* For key import */
|
||||
|
||||
extern const char const select_file_TOP_result[20];
|
||||
extern const char const get_data_rb_result[6];
|
||||
|
||||
void
|
||||
write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
|
||||
{
|
||||
res_APDU_size = 2 + len;
|
||||
if (len)
|
||||
memcpy (res_APDU, p, len);
|
||||
res_APDU[len] = sw1;
|
||||
res_APDU[len+1] = sw2;
|
||||
}
|
||||
|
||||
#define FILE_NONE -1
|
||||
#define FILE_DF_OPENPGP 0
|
||||
#define FILE_MF 1
|
||||
#define FILE_EF_DIR 2
|
||||
#define FILE_EF_SERIAL 3
|
||||
|
||||
static int file_selection = FILE_NONE;
|
||||
|
||||
static void
|
||||
cmd_verify (void)
|
||||
{
|
||||
int len;
|
||||
uint8_t p2 = cmd_APDU[3];
|
||||
int r;
|
||||
|
||||
DEBUG_INFO (" - VERIFY\r\n");
|
||||
|
||||
len = cmd_APDU[4];
|
||||
if (p2 == 0x81)
|
||||
r = verify_pso_cds (&cmd_APDU[5], len);
|
||||
else if (p2 == 0x82)
|
||||
r = verify_pso_other (&cmd_APDU[5], len);
|
||||
else
|
||||
r = verify_admin (&cmd_APDU[5], len);
|
||||
|
||||
if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else if (r == 0)
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
else
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
int
|
||||
gpg_change_keystring (int who_old, const uint8_t *old_ks,
|
||||
int who_new, const uint8_t *new_ks)
|
||||
{
|
||||
int r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, who_old, old_ks);
|
||||
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNATURE, who_old, old_ks,
|
||||
who_new, new_ks);
|
||||
if (r < 0)
|
||||
return -2;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
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 p2 = cmd_APDU[3];
|
||||
int len = cmd_APDU[4];
|
||||
const uint8_t *pw = &cmd_APDU[5];
|
||||
const uint8_t *newpw;
|
||||
int pw_len, newpw_len;
|
||||
int who = p2 - 0x80;
|
||||
int r;
|
||||
|
||||
if (who == 1) /* PW1 */
|
||||
{
|
||||
const uint8_t *pk = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW1);
|
||||
|
||||
if (pk == NULL)
|
||||
{
|
||||
if (len < 6)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* pk==NULL implies we have no prvkey */
|
||||
pw_len = 6;
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
goto no_prvkey;
|
||||
}
|
||||
else
|
||||
{
|
||||
pw_len = pk[0];
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
}
|
||||
}
|
||||
else /* PW3 (0x83) */
|
||||
{
|
||||
pw_len = verify_admin_0 (pw, len, -1);
|
||||
|
||||
if (pw_len < 0)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
else if (pw_len == 0)
|
||||
{
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
gpg_set_pw3 (newpw, newpw_len);
|
||||
}
|
||||
}
|
||||
|
||||
sha1 (pw, pw_len, old_ks);
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
|
||||
r = gpg_change_keystring (who, old_ks, who, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
else if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else if (r == 0 && who == 1) /* no prvkey */
|
||||
{
|
||||
no_prvkey:
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
reset_pso_cds ();
|
||||
}
|
||||
else if (r > 0 && who == 1)
|
||||
{
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, 1);
|
||||
reset_pso_cds ();
|
||||
}
|
||||
else /* r >= 0 && who == 3 */
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_reset_user_password (void)
|
||||
{
|
||||
uint8_t p1 = cmd_APDU[2];
|
||||
int len = cmd_APDU[3];
|
||||
const uint8_t *pw = &cmd_APDU[4];
|
||||
const uint8_t *newpw;
|
||||
int pw_len, newpw_len;
|
||||
int r;
|
||||
|
||||
if (p1 == 0x00) /* by User with Reseting Code */
|
||||
{
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
const uint8_t *ks_rc = gpg_do_read_simple (GNUK_DO_KEYSTRING_RC);
|
||||
uint8_t old_ks[KEYSTRING_MD_SIZE];
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
{
|
||||
GPG_SECURITY_AUTH_BLOCKED ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ks_rc == NULL)
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
pw_len = ks_rc[0];
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
sha1 (pw, pw_len, old_ks);
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (2, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
else if (r < 0)
|
||||
{
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
sec_fail:
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
pwsb[PW_STATUS_RC]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
GPG_SECURITY_FAILURE ();
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
|
||||
goto sec_fail;
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
reset_pso_cds ();
|
||||
}
|
||||
else
|
||||
{
|
||||
reset_pso_cds ();
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
else /* by Admin (p1 == 0x02) */
|
||||
{
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else
|
||||
{
|
||||
const uint8_t *old_ks = keystring_md_pw3;
|
||||
uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
|
||||
uint8_t *new_ks = &new_ks0[1];
|
||||
|
||||
newpw_len = len;
|
||||
newpw = pw;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (3, old_ks, 1, new_ks);
|
||||
if (r < -2)
|
||||
GPG_MEMORY_FAILURE ();
|
||||
else if (r < 0)
|
||||
GPG_SECURITY_FAILURE ();
|
||||
else if (r == 0)
|
||||
{
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
|
||||
reset_pso_cds ();
|
||||
}
|
||||
else
|
||||
{
|
||||
reset_pso_cds ();
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_put_data (void)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint16_t tag;
|
||||
int len;
|
||||
|
||||
DEBUG_INFO (" - PUT DATA\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
GPG_NO_RECORD();
|
||||
|
||||
tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||
len = cmd_APDU_size - 5;
|
||||
data = &cmd_APDU[5];
|
||||
if (len >= 256)
|
||||
/* extended Lc */
|
||||
{
|
||||
data += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
gpg_do_put_data (tag, data, len);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_pgp_gakp (void)
|
||||
{
|
||||
DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
|
||||
|
||||
if (cmd_APDU[2] == 0x81)
|
||||
/* Get public key */
|
||||
gpg_do_public_key (cmd_APDU[5]);
|
||||
else
|
||||
{ /* Generate key pair */
|
||||
if (!ac_check_status (AC_ADMIN_AUTHORIZED))
|
||||
GPG_SECURITY_FAILURE ();
|
||||
|
||||
/* XXX: Not yet supported */
|
||||
write_res_apdu (NULL, 0, 0x6a, 0x88); /* No record */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_read_binary (void)
|
||||
{
|
||||
DEBUG_INFO (" - Read binary\r\n");
|
||||
|
||||
if (file_selection == FILE_EF_SERIAL)
|
||||
{
|
||||
if (cmd_APDU[3] >= 6)
|
||||
GPG_BAD_P0_P1 ();
|
||||
else
|
||||
/* Tag 5a, serial number */
|
||||
write_res_apdu ((const uint8_t *)get_data_rb_result,
|
||||
sizeof (get_data_rb_result), 0x90, 0x00);
|
||||
}
|
||||
else
|
||||
GPG_NO_RECORD();
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_select_file (void)
|
||||
{
|
||||
if (cmd_APDU[2] == 4) /* Selection by DF name */
|
||||
{
|
||||
DEBUG_INFO (" - select DF by name\r\n");
|
||||
|
||||
/*
|
||||
* P2 == 0, LC=6, name = D2 76 00 01 24 01
|
||||
*/
|
||||
|
||||
file_selection = FILE_DF_OPENPGP;
|
||||
|
||||
/* XXX: Should return contents??? */
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x2f
|
||||
&& cmd_APDU[6] == 0x02)
|
||||
{
|
||||
DEBUG_INFO (" - select 0x2f02 EF\r\n");
|
||||
/*
|
||||
* MF.EF-GDO -- Serial number of the card and name of the owner
|
||||
*/
|
||||
GPG_SUCCESS ();
|
||||
file_selection = FILE_EF_SERIAL;
|
||||
}
|
||||
else if (cmd_APDU[4] == 2
|
||||
&& cmd_APDU[5] == 0x3f
|
||||
&& cmd_APDU[6] == 0x00)
|
||||
{
|
||||
DEBUG_INFO (" - select ROOT MF\r\n");
|
||||
if (cmd_APDU[3] == 0x0c)
|
||||
{
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
else
|
||||
{
|
||||
write_res_apdu ((const uint8_t *)select_file_TOP_result,
|
||||
sizeof (select_file_TOP_result), 0x90, 0x00);
|
||||
}
|
||||
|
||||
file_selection = FILE_MF;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - select ?? \r\n");
|
||||
|
||||
file_selection = FILE_NONE;
|
||||
GPG_NO_FILE();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_get_data (void)
|
||||
{
|
||||
uint16_t tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
|
||||
|
||||
DEBUG_INFO (" - Get Data\r\n");
|
||||
|
||||
if (file_selection != FILE_DF_OPENPGP)
|
||||
GPG_NO_RECORD();
|
||||
|
||||
gpg_do_get_data (tag);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_pso (void)
|
||||
{
|
||||
DEBUG_INFO (" - PSO\r\n");
|
||||
|
||||
if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A)
|
||||
{
|
||||
if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
|
||||
{
|
||||
GPG_SECURITY_FAILURE ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1)
|
||||
/* Extended Lc: 3-byte */
|
||||
{
|
||||
DEBUG_INFO (" wrong length: ");
|
||||
DEBUG_SHORT (cmd_APDU_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
int r;
|
||||
|
||||
DEBUG_BYTE (len); /* Should be cmd_APDU_size - 6 */
|
||||
|
||||
r = rsa_sign (&cmd_APDU[7], res_APDU, len);
|
||||
if (r < 0)
|
||||
/* XXX: fail code??? */
|
||||
write_res_apdu (NULL, 0, 0x69, 0x85);
|
||||
else
|
||||
{ /* Success */
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
|
||||
res_APDU[RSA_SIGNATURE_LENGTH] = 0x90;
|
||||
res_APDU[RSA_SIGNATURE_LENGTH+1] = 0x00;
|
||||
res_APDU_size = RSA_SIGNATURE_LENGTH + 2;
|
||||
|
||||
if (pw_status_bytes[0] == 0)
|
||||
reset_pso_cds ();
|
||||
|
||||
gpg_do_increment_digital_signature_counter ();
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
}
|
||||
else
|
||||
{ /* XXX: not yet supported */
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[2]);
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd_APDU[3]);
|
||||
GPG_SUCCESS ();
|
||||
}
|
||||
}
|
||||
|
||||
struct command
|
||||
{
|
||||
uint8_t command;
|
||||
void (*cmd_handler) (void);
|
||||
};
|
||||
|
||||
struct command cmds[] = {
|
||||
{ INS_VERIFY, cmd_verify },
|
||||
{ INS_CHANGE_REFERENCE_DATA, cmd_change_password },
|
||||
{ INS_PSO, cmd_pso },
|
||||
{ INS_RESET_RETRY_COUNTER, cmd_reset_user_password },
|
||||
{ INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
|
||||
{ INS_SELECT_FILE, cmd_select_file },
|
||||
{ INS_READ_BINARY, cmd_read_binary },
|
||||
{ INS_GET_DATA, cmd_get_data },
|
||||
{ INS_PUT_DATA, cmd_put_data },
|
||||
{ INS_PUT_DATA_ODD, cmd_put_data },
|
||||
};
|
||||
#define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
|
||||
|
||||
static void
|
||||
process_command_apdu (void)
|
||||
{
|
||||
int i;
|
||||
uint8_t cmd = cmd_APDU[1];
|
||||
|
||||
for (i = 0; i < NUM_CMDS; i++)
|
||||
if (cmds[i].command == cmd)
|
||||
break;
|
||||
|
||||
if (i < NUM_CMDS)
|
||||
cmds[i].cmd_handler ();
|
||||
else
|
||||
{
|
||||
DEBUG_INFO (" - ??");
|
||||
DEBUG_BYTE (cmd);
|
||||
GPG_NO_INS ();
|
||||
}
|
||||
}
|
||||
|
||||
Thread *gpg_thread;
|
||||
|
||||
msg_t
|
||||
GPGthread (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
gpg_thread = chThdSelf ();
|
||||
chEvtClear (ALL_EVENTS);
|
||||
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
m = chEvtWaitOne (ALL_EVENTS);
|
||||
|
||||
DEBUG_INFO ("GPG!\r\n");
|
||||
|
||||
process_command_apdu ();
|
||||
|
||||
chEvtSignal (icc_thread, EV_EXEC_FINISHED);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
src/openpgp.h
Normal file
8
src/openpgp.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#define GPG_MEMORY_FAILURE() write_res_apdu (NULL, 0, 0x65, 0x81)
|
||||
#define GPG_SECURITY_FAILURE() write_res_apdu (NULL, 0, 0x69, 0x82)
|
||||
#define GPG_SECURITY_AUTH_BLOCKED() write_res_apdu (NULL, 0, 0x69, 0x83)
|
||||
#define GPG_NO_FILE() write_res_apdu (NULL, 0, 0x6a, 0x82)
|
||||
#define GPG_NO_RECORD() write_res_apdu (NULL, 0, 0x6a, 0x88)
|
||||
#define GPG_BAD_P0_P1() write_res_apdu (NULL, 0, 0x6b, 0x00)
|
||||
#define GPG_NO_INS() write_res_apdu (NULL, 0, 0x6d, 0x00)
|
||||
#define GPG_SUCCESS() write_res_apdu (NULL, 0, 0x90, 0x00)
|
||||
@@ -3,20 +3,14 @@
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/rsa.h"
|
||||
|
||||
static unsigned char output[256];
|
||||
static rsa_context ctx;
|
||||
|
||||
unsigned char *
|
||||
rsa_sign (unsigned char *raw_message)
|
||||
int
|
||||
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len)
|
||||
{
|
||||
mpi P1, Q1, H;
|
||||
int len;
|
||||
int r;
|
||||
|
||||
len = (cmd_APDU[5]<<8) | cmd_APDU[6];
|
||||
put_byte (len);
|
||||
/* cmd_APDU_size - 6 */
|
||||
|
||||
mpi_init( &P1, &Q1, &H, NULL );
|
||||
rsa_init( &ctx, RSA_PKCS_V15, 0 );
|
||||
|
||||
@@ -34,24 +28,54 @@ rsa_sign (unsigned char *raw_message)
|
||||
mpi_inv_mod ( &ctx.QP, &ctx.Q, &ctx.P);
|
||||
mpi_free (&P1, &Q1, &H, NULL);
|
||||
|
||||
put_string ("RSA...");
|
||||
{
|
||||
int r;
|
||||
if ((r = rsa_check_privkey ( &ctx )) == 0)
|
||||
put_string ("ok...");
|
||||
else
|
||||
{
|
||||
put_string ("failed.\r\n");
|
||||
put_byte (r);
|
||||
rsa_free (&ctx);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
DEBUG_INFO ("RSA...");
|
||||
|
||||
if ((r = rsa_check_privkey ( &ctx )) == 0)
|
||||
DEBUG_INFO ("ok...");
|
||||
else
|
||||
{
|
||||
DEBUG_INFO ("failed.\r\n");
|
||||
DEBUG_BYTE (r);
|
||||
rsa_free (&ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = rsa_pkcs1_sign ( &ctx, RSA_PRIVATE, SIG_RSA_RAW,
|
||||
len, raw_message, output );
|
||||
put_short (r);
|
||||
put_string ("done.\r\n");
|
||||
msg_len, raw_message, output );
|
||||
rsa_free (&ctx);
|
||||
return output;
|
||||
DEBUG_INFO ("done.\r\n");
|
||||
if (r < 0)
|
||||
{
|
||||
DEBUG_SHORT (r);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *
|
||||
modulus_calc (const uint8_t *p, int len)
|
||||
{
|
||||
mpi P, Q, N;
|
||||
uint8_t *modulus;
|
||||
|
||||
(void)len; /* 2048-bit assumed */
|
||||
modulus = malloc (2048 / 8);
|
||||
if (modulus == NULL)
|
||||
return NULL;
|
||||
|
||||
mpi_init (&P, &Q, &N, NULL);
|
||||
mpi_read_binary (&P, p, 2048 / 8 / 2);
|
||||
mpi_read_binary (&Q, p + 128, 2048 / 8 / 2);
|
||||
mpi_mul_mpi (&N, &P, &Q);
|
||||
|
||||
mpi_write_binary (&N, modulus, 2048 / 8);
|
||||
mpi_free (&P, &Q, &N, NULL);
|
||||
return modulus;
|
||||
}
|
||||
|
||||
void
|
||||
modulus_free (const uint8_t *p)
|
||||
{
|
||||
free ((void *)p);
|
||||
}
|
||||
|
||||
@@ -180,14 +180,14 @@ icc_power_on (void)
|
||||
|
||||
if (!icc_tx_ready ())
|
||||
{
|
||||
_write ("ERR0B\r\n", 7);
|
||||
DEBUG_INFO ("ERR0B\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_tx_size = ICC_MSG_DATA_OFFSET + size_atr;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
_write ("ON\r\n", 4);
|
||||
DEBUG_INFO ("ON\r\n");
|
||||
}
|
||||
|
||||
return ICC_STATE_WAIT;
|
||||
@@ -214,7 +214,7 @@ icc_send_status (void)
|
||||
|
||||
if (!icc_tx_ready ())
|
||||
{
|
||||
_write ("ERR0C\r\n", 7);
|
||||
DEBUG_INFO ("ERR0C\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -222,7 +222,7 @@ icc_send_status (void)
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
}
|
||||
_write ("St\r\n", 4);
|
||||
DEBUG_INFO ("St\r\n");
|
||||
}
|
||||
|
||||
enum icc_state
|
||||
@@ -230,7 +230,7 @@ icc_power_off (void)
|
||||
{
|
||||
|
||||
icc_send_status ();
|
||||
_write ("OFF\r\n", 5);
|
||||
DEBUG_INFO ("OFF\r\n");
|
||||
return ICC_STATE_START;
|
||||
}
|
||||
|
||||
@@ -261,14 +261,14 @@ icc_send_data_block (uint8_t status, uint8_t error, uint8_t chain,
|
||||
|
||||
if (!icc_tx_ready ())
|
||||
{ /* not ready to send */
|
||||
_write ("ERR09\r\n", 7);
|
||||
DEBUG_INFO ("ERR09\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
icc_tx_size = ICC_MSG_DATA_OFFSET + len;
|
||||
USB_SIL_Write (EP4_IN, icc_tx_data, icc_tx_size);
|
||||
SetEPTxValid (ENDP4);
|
||||
_write ("DATA\r\n", 6);
|
||||
DEBUG_INFO ("DATA\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ icc_handle_data (void)
|
||||
icc_send_status ();
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR01\r\n", 7);
|
||||
DEBUG_INFO ("ERR01\r\n");
|
||||
}
|
||||
break;
|
||||
case ICC_STATE_WAIT:
|
||||
@@ -320,13 +320,13 @@ icc_handle_data (void)
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */;
|
||||
_write ("ERR02\r\n", 7);
|
||||
DEBUG_INFO ("ERR02\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR03\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
DEBUG_INFO ("ERR03\r\n");
|
||||
DEBUG_BYTE (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
@@ -340,8 +340,8 @@ icc_handle_data (void)
|
||||
icc_send_status ();
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR04\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
DEBUG_INFO ("ERR04\r\n");
|
||||
DEBUG_BYTE (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
@@ -368,7 +368,7 @@ icc_handle_data (void)
|
||||
icc_send_data_block (0, 0, 0x10, NULL, 0);
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR08\r\n", 7);
|
||||
DEBUG_INFO ("ERR08\r\n");
|
||||
}
|
||||
}
|
||||
else /* Overrun */
|
||||
@@ -380,8 +380,8 @@ icc_handle_data (void)
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR05\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
DEBUG_INFO ("ERR05\r\n");
|
||||
DEBUG_BYTE (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
@@ -409,16 +409,16 @@ icc_handle_data (void)
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR0A\r\n", 7);
|
||||
put_byte (icc_header->param >> 8);
|
||||
put_byte (icc_header->param & 0xff);
|
||||
DEBUG_INFO ("ERR0A\r\n");
|
||||
DEBUG_BYTE (icc_header->param >> 8);
|
||||
DEBUG_BYTE (icc_header->param & 0xff);
|
||||
next_state = ICC_STATE_WAIT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR06\r\n", 7);
|
||||
put_byte (icc_header->msg_type);
|
||||
DEBUG_INFO ("ERR06\r\n");
|
||||
DEBUG_BYTE (icc_header->msg_type);
|
||||
next_state = ICC_STATE_START;
|
||||
}
|
||||
break;
|
||||
@@ -491,7 +491,7 @@ USBthread (void *arg)
|
||||
}
|
||||
else
|
||||
{ /* XXX: error */
|
||||
_write ("ERR07\r\n", 7);
|
||||
DEBUG_INFO ("ERR07\r\n");
|
||||
}
|
||||
}
|
||||
else /* Timeout */
|
||||
|
||||
@@ -66,7 +66,7 @@ static const uint8_t gnukConfigDescriptor[] = {
|
||||
0xfe, 0, 0, 0, /* dwMaxIFSD: */
|
||||
0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */
|
||||
0, 0, 0, 0, /* dwMechanical: FIXED VALUE */
|
||||
0x40, 0x08, 0x04, 0x00, /* dwFeatures: Short and extended ADPU level */
|
||||
0x40, 0x08, 0x04, 0x00, /* dwFeatures: Short and extended APDU level */
|
||||
0x40, 0x00, 0, 0, /* dwMaxCCIDMessageLength: 64 */
|
||||
0xff, /* bClassGetResponse: */
|
||||
0xff, /* bClassEnvelope: */
|
||||
|
||||
Reference in New Issue
Block a user