diff --git a/src/.gdbinit b/src/.gdbinit index 3415b26..3e08392 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -1,4 +1,3 @@ set arm force-mode thumb set arm fallback-mode thumb target remote localhost:3333 -monitor reset halt diff --git a/src/Makefile b/src/Makefile index 37d2a6a..d40ec2e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -78,7 +78,7 @@ CSRC = $(PORTSRC) \ $(STMUSBSRC) \ $(USBCDCSRC) \ $(RSASRC) \ - main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb-icc.c gpg.c + main.c hw_config.c usb_lld.c usb_desc.c usb_prop.c usb-icc.c gpg.c ac.c gpg-do.c # List ASM source files here ASMSRC = $(PORTASM) \ diff --git a/src/ac.c b/src/ac.c new file mode 100644 index 0000000..c48b9d1 --- /dev/null +++ b/src/ac.c @@ -0,0 +1,69 @@ +/* + * ac.c -- Check access condition + */ + +#include "ch.h" +#include "gnuk.h" + +static uint8_t auth_status = AC_NONE_AUTHORIZED; + +int +ac_check_status (uint8_t ac_flag) +{ + if (ac_flag == AC_ALWAYS) + return 1; + else if (ac_flag == AC_NEVER) + return 0; + else + 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 (uint8_t *pw, int pw_len) +{ +#if 0 + compute_hash; + if (cmp_hash (pw1_hash, hash) == 0) + good; + else + return -1; +#endif + auth_status |= AC_PSO_CDS_AUTHORIZED; + return 0; +} + +int +verify_pso_other (uint8_t *pw, int pw_len) +{ +#if 0 + compute_hash; + if (cmp_hash (pw1_hash, hash) == 0) + good; + else + return -1; +#endif + 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 + auth_status |= AC_ADMIN_AUTHORIZED; + return 0; +} diff --git a/src/gnuk.h b/src/gnuk.h index e1e9efe..2acbbff 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -1,12 +1,14 @@ extern Thread *blinker_thread; extern void put_byte (uint8_t b); +extern void put_short (uint16_t x); extern void put_string (const char *s); 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); /* * Interface between ICC<-->GPG @@ -18,9 +20,32 @@ extern Thread *gpg_thread; #define EV_EXEC_FINISHED (eventmask_t)2 /* GPG Execution finished */ -#define MAX_CMD_APDU_SIZE (256) /* XXX: Check OpenPGPcard protocol */ +/* maximum cmd apdu data is key import 22+4+128+128 (head, e, p, q)*/ +#define MAX_CMD_APDU_SIZE (7+282) /* header + data */ + #define MAX_RES_APDU_SIZE (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; extern int res_APDU_size; + +#define AC_NONE_AUTHORIZED 0x00 +#define AC_PSO_CDS_AUTHORIZED 0x01 /* PW1 with 0x81 verified */ +#define AC_PSO_OTHER_AUTHORIZED 0x02 /* PW1 with 0x82 verified */ +#define AC_ADMIN_AUTHORIZED 0x04 /* PW3 verified */ +#define AC_NEVER 0x80 +#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 void write_res_apdu (const uint8_t *p, int len, + uint8_t sw1, uint8_t sw2); +#define DEBUG 1 + +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); diff --git a/src/gpg-data.c b/src/gpg-data.c index e1f2d2d..2538b85 100644 --- a/src/gpg-data.c +++ b/src/gpg-data.c @@ -1,172 +1,79 @@ -const char const select_file_TOP_result[] __attribute__ ((aligned (1))) = - { 0x00, 0x00, 0x0b, 0x10, 0x3f, 0x00, 0x38, 0xff, 0xff, 0x44, - 0x44, 0x01, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }; +#include "ch.h" +#include "gnuk.h" -const char const get_data_64_result[] __attribute__ ((aligned (1))) = - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; +const char const select_file_TOP_result[] __attribute__ ((aligned (1))) = { + 0x00, 0x00, /* unused */ + 0x0b, 0x10, /* number of bytes in this directory */ + 0x3f, 0x00, /* field of selected file: MF, 3f00 */ + 0x38, /* it's DF */ + 0xff, /* unused */ + 0xff, 0x44, 0x44, /* access conditions */ + 0x01, /* status of the selected file (OK, unblocked) */ + 0x05, /* number of bytes of data follow */ + 0x03, /* Features: unused */ + 0x01, /* number of subdirectories (OpenPGP) */ + 0x01, /* number of elementary files (SerialNo) */ + 0x00, /* number of secret codes */ + 0x00, /* Unused */ + 0x00, 0x00 /* PIN status: OK, PIN blocked?: No */ +}; -const char const get_data_5e_result[] __attribute__ ((aligned (1))) = - { /* Login Data */ - 'g', 'n', 'i', 'i', 'b', 'e' - }; +const char const do_5e[] __attribute__ ((aligned (1))) = { + 6, + 'g', 'n', 'i', 'i', 'b', 'e' +}; -/***** do_6e is compound object of { do_47, do_4f, do_c0,..,c6,cd }*/ -const char const do_6e_head[] __attribute__ ((aligned (1))) = - { - 0x6e, 0x81, 2*10+3+16+1+1+1+1+7+60+60+12 /* (> 128) */ - }; +const char const do_c4[] __attribute__ ((aligned (1))) = { + 7, + 1, 127, 127, 127, 3, 0, 3 +}; -const char const do_47[] __attribute__ ((aligned (1))) = /* Card Capabilities */ - { - 0x47, 3, - 0x00 /*???*/, 0x00 /*???*/, 0x00 /*???*/ - /* XXX: See ISO 7816-4 for first byte and second byte */ - }; +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_4f[] __attribute__ ((aligned (1))) = /* AID */ - { - 0x4f, 16, - 0xD2, 0x76, 0x00, 0x01, 0x24, 0x01, - 0x01, 0x01, /* Version 1.1 */ - 0xF5, 0x17, /* Manufacturer (FSIJ) */ - 0x00, 0x00, 0x00, 0x02, /* Serial */ - 0x00, 0x00 - }; +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_c0[] __attribute__ ((aligned (1))) = - { /* Extended capability */ - 0xc0, 1, - 0x00 - }; +const char const do_ce[] __attribute__ ((aligned (1))) = { + 4, + 0x49, 0x8a, 0x50, 0x7a, /* 0xce */ +}; -const char const do_c1[] __attribute__ ((aligned (1))) = - { /* Algorithm Attributes Signature ??? */ - 0xc1, 1, - 0x01, /* RSA */ /*??? should have length modulus, length exponent ??? */ - }; +const char const do_5b[] __attribute__ ((aligned (1))) = { + 12, + 'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a' +}; -const char const do_c2[] __attribute__ ((aligned (1))) = - { /* Algorithm Attributes Decryption ??? */ - 0xc2, 1, - 0x00 - }; +const char const do_5f2d[] __attribute__ ((aligned (1))) = { + 2, + 'j', 'a' +}; -const char const do_c3[] __attribute__ ((aligned (1))) = - { /* Algorithm Attributes Authentication ??? */ - 0xc3, 1, - 0x00 - }; - -const char const do_c4[] __attribute__ ((aligned (1))) = - { /* CHV status bytes */ - 0xc4, 7, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01 - }; - -const char const do_c5[] __attribute__ ((aligned (1))) = - { - 0xc5, 60, - /* sign */ - 0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d, - 0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc, - 0xe5, 0x02, 0xbf, 0xcd, - /* enc */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* auth */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }; - -const char const do_c6[] __attribute__ ((aligned (1))) = /* CA Fingerprints */ - { - 0xc6, 60, - /* c6 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* c7 */ - 0x5b, 0x85, 0x67, 0x3c, 0x08, 0x4f, 0x80, 0x0d, - 0x54, 0xac, 0x95, 0x1c, 0x35, 0x15, 0x97, 0xcc, - 0xe5, 0x02, 0xbf, 0xcd, - /* c8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }; - -const char const do_cd[] __attribute__ ((aligned (1))) = - { /* Generation time */ - 0xcd, 12, - 0x00, 0x00, 0x00, 0x00, - 0x49, 0x8a, 0x50, 0x7a, /* 0xce */ - 0x00, 0x00, 0x00, 0x00, - }; -/*************************/ - -/***** do_65 is compound object of { do_5b, do_5f2d, do_5f35 }*/ -const char const do_65_head[] __attribute__ ((aligned (1))) = - { - 0x65, 2*1+3*2+12+2+1 - }; - -const char const do_5b[] __attribute__ ((aligned (1))) = - { - 0x5b, 12, - 'N', 'I', 'I', 'B', 'E', ' ', 'Y', 'u', 't', 'a', 'k', 'a' - }; - -const char const do_5f2d[] __attribute__ ((aligned (1))) = - { - 0x5f, 0x2d, 2, - 'j', 'a' - }; - -const char const do_5f35[] __attribute__ ((aligned (1))) = - { - 0x5f, 0x35, 1, - '1' - }; -/****************************/ - -/* do_7a is compound object of { do_93 } */ -const char const do_7a_head[] __attribute__ ((aligned (1))) = - { - 0x7a, 2+3 - }; +const char const do_5f35[] __attribute__ ((aligned (1))) = { + 1, + '1' +}; /* Digital Signature Counter (3-bytes) */ -const char const do_93[] __attribute__ ((aligned (1))) = - { - 0x93, 3, - 0, 0, 0 - }; -/****************************/ +const char const do_93[] __attribute__ ((aligned (1))) = { + 3, + 0, 0, 0 +}; - -const char const do_5f50[] __attribute__ ((aligned (1))) = - { - 0x5f, 0x50, 20, - 'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w', - '.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/' - }; - -/* Historycal bytes */ -const char const do_5f52[] __attribute__ ((aligned (1))) = - { - 0x5f, 0x52, 10, - 0x00, - 0x31, 0xc0, /* full DF name, partial DF name supported */ - 0x73, - 0xc0, 0x01, 0x00, /* full DF name, partial DF name supported */ - /* 1-byte */ - /* no command chaining, no ext lc_le */ - 0x00, 0x90, 0x00 /* Status info */ - }; +const char const do_5f50[] __attribute__ ((aligned (1))) = { + 20, + 'h', 't', 't', 'p', ':', '/', '/', 'w', 'w', 'w', + '.', 'f', 's', 'i', 'j', '.', 'o', 'r', 'g', '/' +}; const char const get_data_rb_result[] __attribute__ ((aligned (1))) = { 0x5a, 0x4, 0x01, 0x02, 0x03, 0x04 diff --git a/src/gpg-data.s b/src/gpg-data.s index 331f3d6..6f68e16 100644 --- a/src/gpg-data.s +++ b/src/gpg-data.s @@ -38,112 +38,40 @@ select_file_TOP_result: .byte 1 .byte 5 .byte 3 - .byte 0 - .byte 2 + .byte 1 + .byte 1 .byte 0 .byte 0 .byte 0 .byte 0 - .global get_data_64_result - .type get_data_64_result, %object - .size get_data_64_result, 7 -get_data_64_result: - .space 7 - .global get_data_5e_result - .type get_data_5e_result, %object - .size get_data_5e_result, 6 -get_data_5e_result: + .global do_5e + .type do_5e, %object + .size do_5e, 7 +do_5e: + .byte 6 .byte 103 .byte 110 .byte 105 .byte 105 .byte 98 .byte 101 - .global do_6e_head - .type do_6e_head, %object - .size do_6e_head, 3 -do_6e_head: - .byte 110 - .byte -127 - .byte -74 - .global do_47 - .type do_47, %object - .size do_47, 5 -do_47: - .byte 71 - .byte 3 - .byte 0 - .byte 0 - .byte 0 - .global do_4f - .type do_4f, %object - .size do_4f, 18 -do_4f: - .byte 79 - .byte 16 - .byte -46 - .byte 118 - .byte 0 - .byte 1 - .byte 36 - .byte 1 - .byte 1 - .byte 1 - .byte -11 - .byte 23 - .byte 0 - .byte 0 - .byte 0 - .byte 2 - .byte 0 - .byte 0 - .global do_c0 - .type do_c0, %object - .size do_c0, 3 -do_c0: - .byte -64 - .byte 1 - .byte 0 - .global do_c1 - .type do_c1, %object - .size do_c1, 3 -do_c1: - .byte -63 - .byte 1 - .byte 1 - .global do_c2 - .type do_c2, %object - .size do_c2, 3 -do_c2: - .byte -62 - .byte 1 - .byte 0 - .global do_c3 - .type do_c3, %object - .size do_c3, 3 -do_c3: - .byte -61 - .byte 1 - .byte 0 .global do_c4 .type do_c4, %object - .size do_c4, 9 + .size do_c4, 8 do_c4: - .byte -60 .byte 7 .byte 1 + .byte 127 + .byte 127 + .byte 127 + .byte 3 .byte 0 - .byte 0 - .byte 0 - .byte 1 - .byte 1 - .byte 1 - .global do_c5 - .type do_c5, %object - .size do_c5, 62 -do_c5: - .byte -59 - .byte 60 + .byte 3 + .global do_c7 + .type do_c7, %object + .size do_c7, 21 +do_c7: + .byte 20 .byte 91 .byte -123 .byte 103 @@ -164,72 +92,11 @@ do_c5: .byte 2 .byte -65 .byte -51 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .global do_c6 - .type do_c6, %object - .size do_c6, 62 -do_c6: - .byte -58 - .byte 60 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 + .global do_ca + .type do_ca, %object + .size do_ca, 21 +do_ca: + .byte 20 .byte 91 .byte -123 .byte 103 @@ -250,55 +117,19 @@ do_c6: .byte 2 .byte -65 .byte -51 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .global do_cd - .type do_cd, %object - .size do_cd, 14 -do_cd: - .byte -51 - .byte 12 - .byte 0 - .byte 0 - .byte 0 - .byte 0 + .global do_ce + .type do_ce, %object + .size do_ce, 5 +do_ce: + .byte 4 .byte 73 .byte -118 .byte 80 .byte 122 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .global do_65_head - .type do_65_head, %object - .size do_65_head, 2 -do_65_head: - .byte 101 - .byte 23 .global do_5b .type do_5b, %object - .size do_5b, 14 + .size do_5b, 13 do_5b: - .byte 91 .byte 12 .byte 78 .byte 73 @@ -314,42 +145,29 @@ do_5b: .byte 97 .global do_5f2d .type do_5f2d, %object - .size do_5f2d, 5 + .size do_5f2d, 3 do_5f2d: - .byte 95 - .byte 45 .byte 2 .byte 106 .byte 97 .global do_5f35 .type do_5f35, %object - .size do_5f35, 4 + .size do_5f35, 2 do_5f35: - .byte 95 - .byte 53 .byte 1 .byte 49 - .global do_7a_head - .type do_7a_head, %object - .size do_7a_head, 2 -do_7a_head: - .byte 122 - .byte 5 .global do_93 .type do_93, %object - .size do_93, 5 + .size do_93, 4 do_93: - .byte -109 .byte 3 .byte 0 .byte 0 .byte 0 .global do_5f50 .type do_5f50, %object - .size do_5f50, 23 + .size do_5f50, 21 do_5f50: - .byte 95 - .byte 80 .byte 20 .byte 104 .byte 116 @@ -371,23 +189,6 @@ do_5f50: .byte 114 .byte 103 .byte 47 - .global do_5f52 - .type do_5f52, %object - .size do_5f52, 13 -do_5f52: - .byte 95 - .byte 82 - .byte 10 - .byte 0 - .byte 49 - .byte -64 - .byte 115 - .byte -64 - .byte 1 - .byte 0 - .byte 0 - .byte -112 - .byte 0 .global get_data_rb_result .type get_data_rb_result, %object .size get_data_rb_result, 6 @@ -690,398 +491,296 @@ get_data_enckey_result: .Letext0: .file 1 "gpg-data.c" .section .debug_info - .4byte 0x34b + .4byte 0x264 .2byte 0x2 .4byte .Ldebug_abbrev0 .byte 0x4 .uleb128 0x1 - .4byte .LASF25 + .4byte .LASF24 .byte 0x1 + .4byte .LASF25 .4byte .LASF26 - .4byte .LASF27 .4byte .Ltext0 .4byte .Letext0 .4byte .Ldebug_line0 .uleb128 0x2 - .4byte 0x38 - .4byte 0x35 + .byte 0x4 + .byte 0x5 + .ascii "int\000" .uleb128 0x3 - .4byte 0x35 - .byte 0x13 - .byte 0x0 + .byte 0x4 + .byte 0x7 + .4byte .LASF0 + .uleb128 0x3 + .byte 0x1 + .byte 0x6 + .4byte .LASF1 + .uleb128 0x3 + .byte 0x1 + .byte 0x8 + .4byte .LASF2 + .uleb128 0x3 + .byte 0x2 + .byte 0x5 + .4byte .LASF3 + .uleb128 0x3 + .byte 0x2 + .byte 0x7 + .4byte .LASF4 + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .4byte .LASF5 + .uleb128 0x3 + .byte 0x4 + .byte 0x7 + .4byte .LASF6 + .uleb128 0x3 + .byte 0x8 + .byte 0x5 + .4byte .LASF7 + .uleb128 0x3 + .byte 0x8 + .byte 0x7 + .4byte .LASF8 .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 .LASF28 - .uleb128 0x6 - .4byte .LASF0 + .4byte .LASF9 + .uleb128 0x7 + .4byte .LASF10 .byte 0x1 - .byte 0x1 - .4byte 0x51 + .byte 0x4 + .4byte 0x97 .byte 0x1 .byte 0x5 .byte 0x3 .4byte select_file_TOP_result - .uleb128 0x7 - .4byte 0x25 - .uleb128 0x2 - .4byte 0x38 - .4byte 0x66 - .uleb128 0x3 - .4byte 0x35 + .uleb128 0x8 + .4byte 0x6e + .uleb128 0x5 + .4byte 0x7e + .4byte 0xac + .uleb128 0x6 + .4byte 0x6b .byte 0x6 .byte 0x0 - .uleb128 0x6 - .4byte .LASF1 - .byte 0x1 - .byte 0x5 - .4byte 0x78 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte get_data_64_result .uleb128 0x7 - .4byte 0x56 - .uleb128 0x2 - .4byte 0x38 - .4byte 0x8d - .uleb128 0x3 - .4byte 0x35 - .byte 0x5 - .byte 0x0 - .uleb128 0x6 - .4byte .LASF2 - .byte 0x1 - .byte 0xa - .4byte 0x9f - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte get_data_5e_result - .uleb128 0x7 - .4byte 0x7d - .uleb128 0x2 - .4byte 0x38 - .4byte 0xb4 - .uleb128 0x3 - .4byte 0x35 - .byte 0x2 - .byte 0x0 - .uleb128 0x6 - .4byte .LASF3 - .byte 0x1 - .byte 0x10 - .4byte 0xc6 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_6e_head - .uleb128 0x7 - .4byte 0xa4 - .uleb128 0x2 - .4byte 0x38 - .4byte 0xdb - .uleb128 0x3 - .4byte 0x35 - .byte 0x4 - .byte 0x0 - .uleb128 0x6 - .4byte .LASF4 + .4byte .LASF11 .byte 0x1 .byte 0x15 - .4byte 0xed + .4byte 0xbe .byte 0x1 .byte 0x5 .byte 0x3 - .4byte do_47 - .uleb128 0x7 - .4byte 0xcb - .uleb128 0x2 - .4byte 0x38 - .4byte 0x102 - .uleb128 0x3 - .4byte 0x35 - .byte 0x11 + .4byte do_5e + .uleb128 0x8 + .4byte 0x9c + .uleb128 0x5 + .4byte 0x7e + .4byte 0xd3 + .uleb128 0x6 + .4byte 0x6b + .byte 0x7 .byte 0x0 - .uleb128 0x6 - .4byte .LASF5 - .byte 0x1 - .byte 0x1c - .4byte 0x114 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_4f .uleb128 0x7 - .4byte 0xf2 - .uleb128 0x6 - .4byte .LASF6 + .4byte .LASF12 .byte 0x1 - .byte 0x26 - .4byte 0x12b - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c0 - .uleb128 0x7 - .4byte 0xa4 - .uleb128 0x6 - .4byte .LASF7 - .byte 0x1 - .byte 0x2c - .4byte 0x142 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c1 - .uleb128 0x7 - .4byte 0xa4 - .uleb128 0x6 - .4byte .LASF8 - .byte 0x1 - .byte 0x32 - .4byte 0x159 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c2 - .uleb128 0x7 - .4byte 0xa4 - .uleb128 0x6 - .4byte .LASF9 - .byte 0x1 - .byte 0x38 - .4byte 0x170 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c3 - .uleb128 0x7 - .4byte 0xa4 - .uleb128 0x2 - .4byte 0x38 - .4byte 0x185 - .uleb128 0x3 - .4byte 0x35 - .byte 0x8 - .byte 0x0 - .uleb128 0x6 - .4byte .LASF10 - .byte 0x1 - .byte 0x3e - .4byte 0x197 + .byte 0x1a + .4byte 0xe5 .byte 0x1 .byte 0x5 .byte 0x3 .4byte do_c4 - .uleb128 0x7 - .4byte 0x175 - .uleb128 0x2 - .4byte 0x38 - .4byte 0x1ac - .uleb128 0x3 - .4byte 0x35 - .byte 0x3d + .uleb128 0x8 + .4byte 0xc3 + .uleb128 0x5 + .4byte 0x7e + .4byte 0xfa + .uleb128 0x6 + .4byte 0x6b + .byte 0x14 .byte 0x0 - .uleb128 0x6 - .4byte .LASF11 - .byte 0x1 - .byte 0x44 - .4byte 0x1be - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c5 .uleb128 0x7 - .4byte 0x19c - .uleb128 0x6 - .4byte .LASF12 - .byte 0x1 - .byte 0x55 - .4byte 0x1d5 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_c6 - .uleb128 0x7 - .4byte 0x19c - .uleb128 0x2 - .4byte 0x38 - .4byte 0x1ea - .uleb128 0x3 - .4byte 0x35 - .byte 0xd - .byte 0x0 - .uleb128 0x6 .4byte .LASF13 .byte 0x1 - .byte 0x66 - .4byte 0x1fc + .byte 0x1f + .4byte 0x10c .byte 0x1 .byte 0x5 .byte 0x3 - .4byte do_cd + .4byte do_c7 + .uleb128 0x8 + .4byte 0xea .uleb128 0x7 - .4byte 0x1da - .uleb128 0x2 - .4byte 0x38 - .4byte 0x211 - .uleb128 0x3 - .4byte 0x35 - .byte 0x1 - .byte 0x0 - .uleb128 0x6 .4byte .LASF14 .byte 0x1 - .byte 0x70 - .4byte 0x223 + .byte 0x27 + .4byte 0x123 .byte 0x1 .byte 0x5 .byte 0x3 - .4byte do_65_head - .uleb128 0x7 - .4byte 0x201 + .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 0x75 - .4byte 0x23a + .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 0x7 - .4byte 0x1da + .uleb128 0x8 + .4byte 0x14f + .uleb128 0x5 + .4byte 0x7e + .4byte 0x186 .uleb128 0x6 - .4byte .LASF16 + .4byte 0x6b + .byte 0x2 + .byte 0x0 + .uleb128 0x7 + .4byte .LASF17 .byte 0x1 - .byte 0x7b - .4byte 0x251 + .byte 0x38 + .4byte 0x198 .byte 0x1 .byte 0x5 .byte 0x3 .4byte do_5f2d - .uleb128 0x7 - .4byte 0xcb - .uleb128 0x2 - .4byte 0x38 - .4byte 0x266 - .uleb128 0x3 - .4byte 0x35 - .byte 0x3 - .byte 0x0 + .uleb128 0x8 + .4byte 0x176 + .uleb128 0x5 + .4byte 0x7e + .4byte 0x1ad .uleb128 0x6 - .4byte .LASF17 + .4byte 0x6b .byte 0x1 - .byte 0x81 - .4byte 0x278 + .byte 0x0 + .uleb128 0x7 + .4byte .LASF18 + .byte 0x1 + .byte 0x3d + .4byte 0x1bf .byte 0x1 .byte 0x5 .byte 0x3 .4byte do_5f35 - .uleb128 0x7 - .4byte 0x256 + .uleb128 0x8 + .4byte 0x19d + .uleb128 0x5 + .4byte 0x7e + .4byte 0x1d4 .uleb128 0x6 - .4byte .LASF18 - .byte 0x1 - .byte 0x89 - .4byte 0x28f - .byte 0x1 - .byte 0x5 + .4byte 0x6b .byte 0x3 - .4byte do_7a_head + .byte 0x0 .uleb128 0x7 - .4byte 0x201 - .uleb128 0x6 .4byte .LASF19 .byte 0x1 - .byte 0x8f - .4byte 0x2a6 + .byte 0x43 + .4byte 0x1e6 .byte 0x1 .byte 0x5 .byte 0x3 .4byte do_93 + .uleb128 0x8 + .4byte 0x1c4 .uleb128 0x7 - .4byte 0xcb - .uleb128 0x2 - .4byte 0x38 - .4byte 0x2bb - .uleb128 0x3 - .4byte 0x35 - .byte 0x16 - .byte 0x0 - .uleb128 0x6 .4byte .LASF20 .byte 0x1 - .byte 0x97 - .4byte 0x2cd + .byte 0x48 + .4byte 0x1fd .byte 0x1 .byte 0x5 .byte 0x3 .4byte do_5f50 - .uleb128 0x7 - .4byte 0x2ab - .uleb128 0x2 - .4byte 0x38 - .4byte 0x2e2 - .uleb128 0x3 - .4byte 0x35 - .byte 0xc - .byte 0x0 + .uleb128 0x8 + .4byte 0xea + .uleb128 0x5 + .4byte 0x7e + .4byte 0x212 .uleb128 0x6 + .4byte 0x6b + .byte 0x5 + .byte 0x0 + .uleb128 0x7 .4byte .LASF21 .byte 0x1 - .byte 0x9f - .4byte 0x2f4 - .byte 0x1 - .byte 0x5 - .byte 0x3 - .4byte do_5f52 - .uleb128 0x7 - .4byte 0x2d2 - .uleb128 0x6 - .4byte .LASF22 - .byte 0x1 - .byte 0xab - .4byte 0x30b + .byte 0x4e + .4byte 0x224 .byte 0x1 .byte 0x5 .byte 0x3 .4byte get_data_rb_result - .uleb128 0x7 - .4byte 0x7d - .uleb128 0x2 - .4byte 0x38 - .4byte 0x320 - .uleb128 0x3 - .4byte 0x35 + .uleb128 0x8 + .4byte 0x202 + .uleb128 0x5 + .4byte 0x7e + .4byte 0x239 + .uleb128 0x6 + .4byte 0x6b .byte 0x8b .byte 0x0 - .uleb128 0x6 - .4byte .LASF23 + .uleb128 0x7 + .4byte .LASF22 .byte 0x1 - .byte 0xaf - .4byte 0x332 + .byte 0x52 + .4byte 0x24b .byte 0x1 .byte 0x5 .byte 0x3 .4byte get_data_sigkey_result + .uleb128 0x8 + .4byte 0x229 .uleb128 0x7 - .4byte 0x310 - .uleb128 0x6 - .4byte .LASF24 + .4byte .LASF23 .byte 0x1 - .byte 0xc8 - .4byte 0x349 + .byte 0x6b + .4byte 0x262 .byte 0x1 .byte 0x5 .byte 0x3 .4byte get_data_enckey_result - .uleb128 0x7 - .4byte 0x310 + .uleb128 0x8 + .4byte 0x229 .byte 0x0 .section .debug_abbrev .uleb128 0x1 @@ -1104,21 +803,25 @@ get_data_enckey_result: .byte 0x0 .byte 0x0 .uleb128 0x2 - .uleb128 0x1 - .byte 0x1 - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x1 - .uleb128 0x13 + .uleb128 0x24 + .byte 0x0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 .byte 0x0 .byte 0x0 .uleb128 0x3 - .uleb128 0x21 + .uleb128 0x24 .byte 0x0 - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x2f .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe .byte 0x0 .byte 0x0 .uleb128 0x4 @@ -1131,17 +834,24 @@ get_data_enckey_result: .byte 0x0 .byte 0x0 .uleb128 0x5 - .uleb128 0x24 - .byte 0x0 - .uleb128 0xb - .uleb128 0xb - .uleb128 0x3e - .uleb128 0xb - .uleb128 0x3 - .uleb128 0xe + .uleb128 0x1 + .byte 0x1 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1 + .uleb128 0x13 .byte 0x0 .byte 0x0 .uleb128 0x6 + .uleb128 0x21 + .byte 0x0 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2f + .uleb128 0xb + .byte 0x0 + .byte 0x0 + .uleb128 0x7 .uleb128 0x34 .byte 0x0 .uleb128 0x3 @@ -1158,7 +868,7 @@ get_data_enckey_result: .uleb128 0xa .byte 0x0 .byte 0x0 - .uleb128 0x7 + .uleb128 0x8 .uleb128 0x26 .byte 0x0 .uleb128 0x49 @@ -1167,118 +877,92 @@ get_data_enckey_result: .byte 0x0 .byte 0x0 .section .debug_pubnames,"",%progbits - .4byte 0x179 + .4byte 0xe0 .2byte 0x2 .4byte .Ldebug_info0 - .4byte 0x34f - .4byte 0x3f + .4byte 0x268 + .4byte 0x85 .ascii "select_file_TOP_result\000" - .4byte 0x66 - .ascii "get_data_64_result\000" - .4byte 0x8d - .ascii "get_data_5e_result\000" - .4byte 0xb4 - .ascii "do_6e_head\000" - .4byte 0xdb - .ascii "do_47\000" - .4byte 0x102 - .ascii "do_4f\000" - .4byte 0x119 - .ascii "do_c0\000" - .4byte 0x130 - .ascii "do_c1\000" - .4byte 0x147 - .ascii "do_c2\000" - .4byte 0x15e - .ascii "do_c3\000" - .4byte 0x185 + .4byte 0xac + .ascii "do_5e\000" + .4byte 0xd3 .ascii "do_c4\000" - .4byte 0x1ac - .ascii "do_c5\000" - .4byte 0x1c3 - .ascii "do_c6\000" - .4byte 0x1ea - .ascii "do_cd\000" - .4byte 0x211 - .ascii "do_65_head\000" - .4byte 0x228 + .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 0x23f + .4byte 0x186 .ascii "do_5f2d\000" - .4byte 0x266 + .4byte 0x1ad .ascii "do_5f35\000" - .4byte 0x27d - .ascii "do_7a_head\000" - .4byte 0x294 + .4byte 0x1d4 .ascii "do_93\000" - .4byte 0x2bb + .4byte 0x1eb .ascii "do_5f50\000" - .4byte 0x2e2 - .ascii "do_5f52\000" - .4byte 0x2f9 + .4byte 0x212 .ascii "get_data_rb_result\000" - .4byte 0x320 + .4byte 0x239 .ascii "get_data_sigkey_result\000" - .4byte 0x337 + .4byte 0x250 .ascii "get_data_enckey_result\000" .4byte 0x0 .section .debug_str,"MS",%progbits,1 -.LASF22: - .ascii "get_data_rb_result\000" +.LASF7: + .ascii "long long int\000" .LASF4: - .ascii "do_47\000" -.LASF1: - .ascii "get_data_64_result\000" -.LASF16: - .ascii "do_5f2d\000" -.LASF9: - .ascii "do_c3\000" -.LASF10: - .ascii "do_c4\000" -.LASF14: - .ascii "do_65_head\000" -.LASF24: - .ascii "get_data_enckey_result\000" -.LASF20: - .ascii "do_5f50\000" -.LASF2: - .ascii "get_data_5e_result\000" + .ascii "short unsigned int\000" .LASF0: - .ascii "select_file_TOP_result\000" -.LASF25: - .ascii "GNU C 4.4.2\000" + .ascii "unsigned int\000" +.LASF2: + .ascii "unsigned char\000" .LASF17: - .ascii "do_5f35\000" -.LASF28: - .ascii "char\000" + .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" -.LASF21: - .ascii "do_5f52\000" -.LASF6: - .ascii "do_c0\000" -.LASF7: - .ascii "do_c1\000" -.LASF8: - .ascii "do_c2\000" -.LASF3: - .ascii "do_6e_head\000" -.LASF26: - .ascii "gpg-data.c\000" -.LASF11: - .ascii "do_c5\000" -.LASF12: - .ascii "do_c6\000" -.LASF23: - .ascii "get_data_sigkey_result\000" -.LASF13: - .ascii "do_cd\000" -.LASF27: - .ascii "gnuk/src\000" -.LASF5: - .ascii "do_4f\000" +.LASF14: + .ascii "do_ca\000" +.LASF24: + .ascii "GNU C 4.4.2\000" .LASF15: - .ascii "do_5b\000" + .ascii "do_ce\000" .LASF18: - .ascii "do_7a_head\000" + .ascii "do_5f35\000" +.LASF9: + .ascii "char\000" +.LASF21: + .ascii "get_data_rb_result\000" +.LASF5: + .ascii "long int\000" +.LASF20: + .ascii "do_5f50\000" +.LASF12: + .ascii "do_c4\000" +.LASF10: + .ascii "select_file_TOP_result\000" +.LASF13: + .ascii "do_c7\000" +.LASF1: + .ascii "signed char\000" +.LASF22: + .ascii "get_data_sigkey_result\000" +.LASF26: + .ascii "/var/tmp/stm32/gnuk/src\000" +.LASF3: + .ascii "short int\000" +.LASF16: + .ascii "do_5b\000" +.LASF11: + .ascii "do_5e\000" +.LASF25: + .ascii "gpg-data.c\000" .ident "GCC: (GNU) 4.4.2" diff --git a/src/gpg-do.c b/src/gpg-do.c new file mode 100644 index 0000000..16e661c --- /dev/null +++ b/src/gpg-do.c @@ -0,0 +1,729 @@ +/* + * gpg-do.c -- OpenPGP card Data Objects (DO) handling + * + * Copyright (C) 2010 Free Software Initiative of Japan + * Author: NIIBE Yutaka + * + * 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 . + * + */ + +#include "ch.h" +#include "gnuk.h" + +/* + * Compile time vars: + * AID, Historical Bytes (template), Extended Capabilities, + * and Algorithm Attributes + */ + +/* AID */ +static const uint8_t const aid[] __attribute__ ((aligned (1))) = { + 16, + 0xd2, 0x76, 0x00, 0x01, 0x24, 0x01, + 0x02, 0x00, /* Version 2.0 */ + 0xf5, 0x17, /* Manufacturer (FSIJ) */ + 0x00, 0x00, 0x00, 0x01, /* Serial */ + 0x00, 0x00 +}; + +/* Historical Bytes (template) */ +static const uint8_t const historical_bytes[] __attribute__ ((aligned (1))) = { + 10, + 0x00, + 0x31, 0x80, /* Full DF name */ + 0x73, + 0x80, 0x01, 0x40, /* Full DF name */ + /* 1-byte */ + /* No command chaining */ + /* Extended Lc and Le */ + 0x00, 0x90, 0x00 /* Status info (no life cycle management) */ +}; + +/* Extended Capabilities */ +static const uint8_t const extended_capabilities[] __attribute__ ((aligned (1))) = { + 10, + 0x30, /* + * No SM, No get challenge, + * Key import supported, + * PW status byte can be put, + * No private_use_DO, + * No algo change allowed + */ + 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ + 0x00, 0x00, /* Max get challenge */ + 0x00, 0x00, /* max. length of cardholder certificate */ + (MAX_CMD_APDU_SIZE>>8), (MAX_CMD_APDU_SIZE&0xff), /* Max. length of command data */ + (MAX_RES_APDU_SIZE>>8), (MAX_RES_APDU_SIZE&0xff), /* Max. length of response data */ +}; + +/* Algorithm Attributes */ +static const uint8_t const algorithm_attr[] __attribute__ ((aligned (1))) = { + 6, + 0x01, /* RSA */ + 0x08, 0x00, /* Length modulus (in bit): 2048 */ + 0x00, 0x20, /* Length exponent (in bit): 32 */ + 0x00 /* 0: p&q , 3: CRT with N (not yet supported) */ +}; + + + +#define SIZE_PW_STATUS_BYTES 7 +#if 0 +{ + 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 + +#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, + DO_CN_READ, + DO_PROC_READ, + DO_PROC_WRITE, + DO_HASH, + DO_KEYPTR +}; + +struct do_table_entry { + uint16_t tag; + enum do_type do_type; + uint8_t ac_read; + uint8_t ac_write; + const void *obj; +}; + +static uint8_t *res_p; +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 GPG_DO_AID 0x004f +#define GPG_DO_NAME 0x005b +#define GPG_DO_LOGIN_DATA 0x005e +#define GPG_DO_CH_DATA 0x0065 +#define GPG_DO_APP_DATA 0x006e +/* XXX: 0x0073 ??? */ +#define GPG_DO_SS_TEMP 0x007a +#define GPG_DO_DS_COUNT 0x0093 +#define GPG_DO_EXTCAP 0x00c0 +#define GPG_DO_ALG_SIG 0x00c1 +#define GPG_DO_ALG_DEC 0x00c2 +#define GPG_DO_ALG_AUT 0x00c3 +#define GPG_DO_PW_STATUS 0x00c4 +#define GPG_DO_FP_ALL 0x00c5 +#define GPG_DO_CAFP_ALL 0x00c6 +#define GPG_DO_FP_SIG 0x00c7 +#define GPG_DO_FP_DEC 0x00c8 +#define GPG_DO_FP_AUT 0x00c9 +#define GPG_DO_CAFP_1 0x00ca +#define GPG_DO_CAFP_2 0x00cb +#define GPG_DO_CAFP_3 0x00cc +#define GPG_DO_KGTIME_ALL 0x00cd +#define GPG_DO_KGTIME_SIG 0x00ce +#define GPG_DO_KGTIME_DEC 0x00cf +#define GPG_DO_KGTIME_AUT 0x00d0 +#define GPG_DO_RESETTING_CODE 0x00d3 +#define GPG_DO_KEY_IMPORT 0x3fff +#define GPG_DO_LANGUAGE 0x5f2d +#define GPG_DO_SEX 0x5f35 +#define GPG_DO_URL 0x5f50 +#define GPG_DO_HIST_BYTES 0x5f52 +#define GPG_DO_CH_CERTIFICATE 0x7f21 + +static void +copy_tag (uint16_t tag) +{ + if (tag < 0x0100) + *res_p++ = (tag & 0xff); + else + { + *res_p++ = (tag >> 8); + *res_p++ = (tag & 0xff); + } +} + +static void +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); +} + +#define SIZE_FP 20 +#define SIZE_KGTIME 4 + +static void +do_fp_all (uint16_t tag) +{ + struct do_table_entry *do_p; + const uint8_t *do_data; + + if (with_tag) + { + copy_tag (tag); + *res_p++ = SIZE_FP*3; + } + + do_p = get_do_entry (GPG_DO_FP_SIG); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; + + do_p = get_do_entry (GPG_DO_FP_DEC); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; + + do_p = get_do_entry (GPG_DO_FP_AUT); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; +} + +static void +do_cafp_all (uint16_t tag) +{ + struct do_table_entry *do_p; + const uint8_t *do_data; + + if (with_tag) + { + copy_tag (tag); + *res_p++ = SIZE_FP*3; + } + + do_p = get_do_entry (GPG_DO_CAFP_1); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; + + do_p = get_do_entry (GPG_DO_CAFP_2); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; + + do_p = get_do_entry (GPG_DO_CAFP_3); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_FP); + else + memset (res_p, 0, SIZE_FP); + res_p += SIZE_FP; +} + +static void +do_kgtime_all (uint16_t tag) +{ + struct do_table_entry *do_p; + const uint8_t *do_data; + + if (with_tag) + { + copy_tag (tag); + *res_p++ = SIZE_KGTIME*3; + } + + do_p = get_do_entry (GPG_DO_KGTIME_SIG); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_KGTIME); + else + memset (res_p, 0, SIZE_KGTIME); + res_p += SIZE_KGTIME; + + do_p = get_do_entry (GPG_DO_KGTIME_DEC); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_KGTIME); + else + memset (res_p, 0, SIZE_KGTIME); + res_p += SIZE_KGTIME; + + do_p = get_do_entry (GPG_DO_KGTIME_AUT); + do_data = (const uint8_t *)do_p->obj; + if (do_data) + memcpy (res_p, &do_data[1], SIZE_KGTIME); + else + memset (res_p, 0, SIZE_KGTIME); + res_p += SIZE_KGTIME; +} + +static void +put_hex (uint8_t nibble) +{ + uint8_t c; + + if (nibble < 0x0a) + c = '0' + nibble; + else + c = 'a' + nibble - 0x0a; + + _write (&c, 1); +} + +static void +o_put_byte (uint8_t b) +{ + _write (" ", 1); + put_hex (b >> 4); + put_hex (b &0x0f); +} + +/* + * 4d, xx, xx: Extended Header List + * b6 00 (SIG) / b8 00 (DEC) / a4 00 (AUT) + * 7f48, xx: cardholder private key template + * 91 xx + * 92 xx + * 93 xx + * 5f48, xx: cardholder privatge key + */ +static void +proc_key_import (uint16_t tag, uint8_t *data, int len) +{ + int i; + + for (i = 0; i < len; i++) + { + o_put_byte (data[i]); + if ((i & 0x0f) == 0x0f) + _write ("\r\n", 2); + } + _write ("\r\n", 2); + + write_res_apdu (NULL, 0, 0x65, 0x81); /* memory failure */ +} + +static const uint16_t const cn_ch_data[] = { + 3, + GPG_DO_NAME, + GPG_DO_LANGUAGE, + GPG_DO_SEX, +}; + +static const uint16_t const cn_app_data[] = { + 10, + GPG_DO_AID, + GPG_DO_HIST_BYTES, + /* XXX Discretionary data objects 0x0073 ??? */ + GPG_DO_EXTCAP, + GPG_DO_ALG_SIG, GPG_DO_ALG_DEC, GPG_DO_ALG_AUT, + GPG_DO_PW_STATUS, + GPG_DO_FP_ALL, GPG_DO_CAFP_ALL, GPG_DO_KGTIME_ALL +}; + +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 }, + /* Pseudo DO: calculated */ + { GPG_DO_HIST_BYTES, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_hist_bytes }, + { GPG_DO_FP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_fp_all }, + { GPG_DO_CAFP_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_cafp_all }, + { GPG_DO_KGTIME_ALL, DO_PROC_READ, AC_ALWAYS, AC_NEVER, do_kgtime_all }, + /* Fixed data */ + { GPG_DO_AID, DO_FIXED, AC_ALWAYS, AC_NEVER, aid }, + { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, + { GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr }, + { GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr }, + { GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr }, + /* Variable(s): Fixed size, not changeable by user */ + { GPG_DO_DS_COUNT, DO_VAR, AC_ALWAYS, AC_NEVER, NULL }, + /* Variables: Fixed size */ + { GPG_DO_PW_STATUS, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_SEX, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_FP_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_FP_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_FP_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_CAFP_1, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_CAFP_2, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_CAFP_3, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_KGTIME_SIG, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_KGTIME_DEC, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_KGTIME_AUT, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + /* Variables: Variable size */ + { GPG_DO_LOGIN_DATA, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_URL, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_NAME, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_LANGUAGE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + { GPG_DO_CH_CERTIFICATE, DO_VAR, AC_ALWAYS, AC_ADMIN_AUTHORIZED, NULL }, + /* Variable(s): Variable size, write only by user */ + { GPG_DO_RESETTING_CODE, DO_VAR, AC_NEVER, AC_ADMIN_AUTHORIZED, NULL }, + /* Compound data: Read access only */ + { GPG_DO_CH_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ch_data }, + { GPG_DO_APP_DATA, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_app_data }, + { GPG_DO_SS_TEMP, DO_CN_READ, AC_ALWAYS, AC_NEVER, cn_ss_temp }, + /* Compound data: Write access only*/ + { GPG_DO_KEY_IMPORT, DO_PROC_WRITE, AC_NEVER, AC_ADMIN_AUTHORIZED, + proc_key_import }, +}; + +#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[]; + +/* + * Initialize GPG_DO_TABLE reading from Flash ROM + */ +int +gpg_do_table_init (void) +{ + struct do_table_entry *do_p; + + do_p = get_do_entry (GPG_DO_LOGIN_DATA); + do_p->obj = do_5e; + do_p = get_do_entry (GPG_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 = 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; + + return 0; +} + +static struct do_table_entry * +get_do_entry (uint16_t tag) +{ + int i; + + for (i = 0; i < NUM_DO_ENTRIES; i++) + if (gpg_do_table[i].tag == tag) + return &gpg_do_table[i]; + + return NULL; +} + +static void +copy_do_1 (uint16_t tag, const uint8_t *do_data) +{ + int len; + + if (with_tag) + { + copy_tag (tag); + + if (do_data[0] < 127) + len = do_data[0] + 1; + else if (do_data[1] == 0x81) + len = do_data[1] + 2; + else /* 0x82 */ + len = ((do_data[1] << 8) | do_data[2]) + 3; + } + else + { + if (do_data[0] < 127) + { + len = do_data[0]; + do_data++; + } + else if (do_data[1] == 0x81) + { + len = do_data[1]; + do_data += 2; + } + else /* 0x82 */ + { + len = ((do_data[1] << 8) | do_data[2]); + do_data += 3; + } + } + + memcpy (res_p, do_data, len); + res_p += len; +} + +static int +copy_do (struct do_table_entry *do_p) +{ + if (do_p == NULL) + return 0; + + if (ac_check_status (do_p->ac_read) == 0) + return -1; + + switch (do_p->do_type) + { + case DO_FIXED: + case DO_VAR: + { + const uint8_t *do_data = (const uint8_t *)do_p->obj; + if (do_data == NULL) + return 0; + else + copy_do_1 (do_p->tag, do_data); + break; + } + case DO_CN_READ: + { + int i; + const uint16_t *cn_data = (const uint16_t *)do_p->obj; + int num_components = cn_data[0]; + uint8_t *len_p; + + copy_tag (do_p->tag); + *res_p++ = 0x81; + len_p = res_p; + *res_p++ = 0; /* for now */ + with_tag = 1; + + for (i = 0; i < num_components; i++) + { + uint16_t tag0; + struct do_table_entry *do0_p; + + tag0 = cn_data[i+1]; + do0_p = get_do_entry (tag0); + if (copy_do (do0_p) < 0) + return -1; + } + + *len_p = (res_p - len_p); + break; + } + case DO_PROC_READ: + { + void (*do_func)(uint16_t) = (void (*)(uint16_t))do_p->obj; + + do_func (do_p->tag); + break; + } + case DO_PROC_WRITE: + case DO_HASH: + case DO_KEYPTR: + return -1; + } + + return 1; +} + +/* + * Process GET_DATA request on Data Object specified by TAG + * Call write_res_adpu to fill data returned + */ +void +gpg_do_get_data (uint16_t tag) +{ + struct do_table_entry *do_p = get_do_entry (tag); + + res_p = res_APDU; + with_tag = 0; + +#ifdef DEBUG + put_string (" "); + put_short (tag); +#endif + + if (do_p) + { + if (copy_do (do_p) < 0) + /* Overwrite partially written result */ + write_res_apdu (NULL, 0, 0x69, 0x82); + else + { + *res_p++ = 0x90; + *res_p++ = 0x00; + res_APDU_size = res_p - res_APDU; + } + } + else + /* No record */ + write_res_apdu (NULL, 0, 0x6a, 0x88); +} + +uint8_t * +flash_do_write (uint16_t tag, uint8_t *data, int len) +{ + static uint8_t do_pool[1024]; + static uint8_t *last_p = do_pool; + uint8_t *p = last_p; + + if (last_p - do_pool + len + 2 + 3 > 1024) + return NULL; + + *last_p++ = (tag >> 8); + *last_p++ = (tag & 0xff); + if (len < 128) + *last_p++ = len; + else if (len < 256) + { + *last_p++ = 0x81; + *last_p++ = len; + } + else + { + *last_p++ = 0x82; + *last_p++ = (len >> 8); + *last_p++ = (len & 0xff); + } + memcpy (last_p, data, len); + last_p += len; + + return p + 2; +} + +void +gpg_do_put_data (uint16_t tag, uint8_t *data, int len) +{ + struct do_table_entry *do_p = get_do_entry (tag); + +#ifdef DEBUG + put_string (" "); + put_short (tag); +#endif + + if (do_p) + { + if (ac_check_status (do_p->ac_write) == 0) + { + write_res_apdu (NULL, 0, 0x69, 0x82); + return; + } + + switch (do_p->do_type) + { + case DO_FIXED: + case DO_CN_READ: + case DO_PROC_READ: + case DO_HASH: + case DO_KEYPTR: + write_res_apdu (NULL, 0, 0x69, 0x82); + break; + case DO_VAR: + { +#if 0 + const uint8_t *do_data = (const uint8_t *)do_p->obj; + + flash_do_release (do_data); +#endif + if (tag == GPG_DO_PW_STATUS) + { + /* XXX: only the first byte can be changed */ + } + else + { + if (len == 0) + /* make DO empty */ + do_p->obj = NULL; + else + { + 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 */ + } + } + + /* + * + */ + if (tag == GPG_DO_RESETTING_CODE) + { + /* XXX: Changing Resetting code, + * we need to reset RC counter in GPG_DO_PW_STATUS */ + } + break; + } + case DO_PROC_WRITE: + { + void (*proc_func)(uint16_t, uint8_t *, int) + = (void (*)(uint16_t, uint8_t *, int))do_p->obj; + + proc_func (tag, data, len); + break; + } + } + } + else + /* No record */ + write_res_apdu (NULL, 0, 0x6a, 0x88); +} diff --git a/src/gpg.c b/src/gpg.c index 34e48c9..ffe25b0 100644 --- a/src/gpg.c +++ b/src/gpg.c @@ -46,6 +46,16 @@ put_byte (uint8_t b) _write ("\r\n", 2); } +void +put_short (uint16_t x) +{ + put_hex (x >> 12); + put_hex ((x >> 8)&0x0f); + put_hex ((x >> 4)&0x0f); + put_hex (x & 0x0f); + _write ("\r\n", 2); +} + void put_string (const char *s) { @@ -53,10 +63,11 @@ put_string (const char *s) } -#define RSA_SIGNATURE_LENGTH 128 /* 256 byte == 2048-bit */ +#define RSA_SIGNATURE_LENGTH 128 /* 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 @@ -66,50 +77,12 @@ extern unsigned char *rsa_sign (unsigned char *); #define INS_PSO 0x2A extern const char const select_file_TOP_result[20]; -extern const char const get_data_64_result[7]; -extern const char const get_data_5e_result[6]; -extern const char const do_6e_head[3]; -extern const char const do_47[2+3]; -extern const char const do_4f[2+16]; -extern const char const do_c0[2+1]; -extern const char const do_c1[2+1]; -extern const char const do_c2[2+1]; -extern const char const do_c3[2+1]; -extern const char const do_c4[2+7]; -extern const char const do_c5[2+60]; -extern const char const do_c6[2+60]; -extern const char const do_cd[2+12]; -extern const char const do_65_head[2]; -extern const char const do_5b[2+12]; -extern const char const do_5f2d[3+2]; -extern const char const do_5f35[3+1]; -extern const char const do_7a_head[2]; -extern const char const do_93[2+3]; -extern const char const do_5f50[3+20]; -extern const char const do_5f52[3+10]; 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]; -/* - * 73 - * 101 - * 102 - * 103 - * 104 - * - * 65 - 5b, 5f2d, 5f35 - * 6e - 47, 4f, c0, c1, c2, c3, c4, c5, c6, cd - * 7a - 93 - * - * - * 65 L-65 [5b L-5b .... ] [5f2d 2 'j' 'a'] [5f35 1 '1'] - * 6e L-6e [47 3 x x x ] [4f L-4f ...] [c0 L-c0 ...] ... - * 7a L-7a [93 L-93 ... ] - */ - -static void +void write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2) { res_APDU_size = 2 + len; @@ -119,25 +92,62 @@ write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2) res_APDU[len+1] = sw2; } -static int +#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) { - /* -INS_VERIFY + uint16_t tag; + uint8_t *data; + int len; - 00 20 00 81 06 - ??? - CHV1 - 00 20 00 82 06 - ??? - CHV2 - 00 20 00 83 08 - ??? - CHV3 - */ + if (cmd_APDU[1] == INS_VERIFY) + { + uint8_t p2 = cmd_APDU[3]; + int r; - if (cmd_APDU[1] == INS_PUT_DATA) + 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"); - write_res_apdu (NULL, 0, 0x90, 0x00); /* 0x6a, 0x88: No record */ - return 0; + + 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) @@ -183,218 +193,82 @@ INS_VERIFY } } else if (cmd_APDU[1] == INS_READ_BINARY) - { /* it must be for DF 0x2f02 */ + { put_string (" - Read binary\r\n"); - if (cmd_APDU[3] >= 6) + if (file_selection == FILE_EF_SERIAL) { - write_res_apdu (NULL, 0, 0x6b, 0x00); /* BAD_P0_P1 */ + 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 - { /* Tag 5a, serial number */ - write_res_apdu (get_data_rb_result, - sizeof (get_data_rb_result), 0x90, 0x00); - } + 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"); + /* - * XXX: Should return contents. + * P2 == 0, LC=6, name = D2 76 00 01 24 01 */ - if (1) - { - write_res_apdu (NULL, 0, 0x90, 0x00); - } + 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] == 02) + && 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 - if (cmd_APDU[4] == 2 - && cmd_APDU[5] == 0x3f - && cmd_APDU[6] == 0) - { - 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); - } - } - else - { - put_string (" - select ?? \r\n"); + { + put_string (" - select ?? \r\n"); - write_res_apdu (NULL, 0, 0x6a, 0x82); /* File missing */ - } + 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"); - switch (((cmd_APDU[2]<<8) | cmd_APDU[3])) - { - case 0x4f: /* AID */ - { - put_string (" AID\r\n"); - write_res_apdu (&do_4f[2], - sizeof (do_4f) - 2, 0x90, 0x00); - break; - } - case 0x5e: /* Login data */ - { - put_string (" Login data\r\n"); - write_res_apdu (get_data_5e_result, - sizeof (get_data_5e_result), 0x90, 0x00); - break; - } - case 0x64: - { - put_string (" 64\r\n"); - write_res_apdu (get_data_64_result, - sizeof (get_data_64_result), 0x90, 0x00); - break; - } - case 0xc0: - { - put_string (" c0\r\n"); - write_res_apdu (&do_c0[2], - sizeof (do_c0) - 2, 0x90, 0x00); - break; - } - case 0xc1: - { - put_string (" c1\r\n"); - write_res_apdu (&do_c1[2], - sizeof (do_c1) - 2, 0x90, 0x00); - break; - } - case 0xc2: - { - put_string (" c2\r\n"); - write_res_apdu (&do_c2[2], - sizeof (do_c2) - 2, 0x90, 0x00); - break; - } - case 0xc3: - { - put_string (" c3\r\n"); - write_res_apdu (&do_c3[2], - sizeof (do_c3) - 2, 0x90, 0x00); - break; - } - case 0xc4: - { - put_string (" c4\r\n"); - write_res_apdu (&do_c4[2], - sizeof (do_c4) - 2, 0x90, 0x00); - break; - } - case 0x5b: /* Name */ - { - put_string (" 5b\r\n"); - write_res_apdu (&do_5b[2], - sizeof (do_5b) - 2, 0x90, 0x00); - break; - } - case 0x93: /* Digital Signature Counter (3-bytes) */ - { - put_string (" 93\r\n"); - write_res_apdu (&do_93[2], - sizeof (do_93) - 2, 0x90, 0x00); - break; - } - case 0xc5: /* Fingerprints */ - { - put_string (" c5\r\n"); - write_res_apdu (&do_c5[2], - sizeof (do_c5) - 2, 0x90, 0x00); - break; - } - case 0x5f2d: /* Language preference */ - { - put_string (" 5f2d\r\n"); - write_res_apdu (&do_5f2d[3], - sizeof (do_5f2d) - 3, 0x90, 0x00); - break; - } - case 0x5f35: /* Sex */ - { - put_string (" 5f35\r\n"); - write_res_apdu (&do_5f35[3], - sizeof (do_5f35) - 3, 0x90, 0x00); - break; - } - case 0x5f50: /* URL */ - { - put_string (" 5f50\r\n"); - write_res_apdu (&do_5f50[3], - sizeof (do_5f50) - 3, 0x90, 0x00); - break; - } - case 0x5f52: /* Historycal bytes */ - { - put_string (" 5f52\r\n"); - write_res_apdu (&do_5f52[3], - sizeof (do_5f52) - 3, 0x90, 0x00); - break; - } - case 0x65: /* Card Holder Related Data (Tag) */ - { - put_string (" 65\r\n"); - write_res_apdu (do_65_head, - do_65_head[1] + 2, 0x90, 0x00); - break; - } - case 0x6e: /* Application Related Data (Tag) */ - { - put_string (" 6e\r\n"); - write_res_apdu (do_6e_head, - do_6e_head[2] + 3, 0x90, 0x00); - break; - } - case 0x7a: /* Security Support Template (Tag) */ - { - put_string (" 7a\r\n"); - write_res_apdu (do_7a_head, - do_7a_head[1] + 2, 0x90, 0x00); - break; - } - case 0xc6: /* List of CA fingerprints */ - { - put_string (" c6\r\n"); - write_res_apdu (&do_c6[2], - sizeof (do_c6) - 2, 0x90, 0x00); - break; - } - case 0xcd: /* List of generation dates/times public-key pairs */ - { - put_string (" cd\r\n"); - write_res_apdu (&do_cd[2], - sizeof (do_cd) - 2, 0x90, 0x00); - break; - } - default: - put_string (" ?"); - put_byte (((cmd_APDU[2]<<8) | cmd_APDU[3])); - write_res_apdu (NULL, 0, 0x90, 0x00); - break; - } + 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) { @@ -402,11 +276,14 @@ INS_VERIFY if (cmd_APDU[2] == 0x9E && cmd_APDU[3] == 0x9A) { - if (cmd_APDU_size != 5 + 35 && cmd_APDU_size != 5 + 35 + 1) - put_string (" wrong length\r\n"); + if (cmd_APDU_size != 8 + 35 && cmd_APDU_size != 8 + 35 + 1) + { + put_string (" wrong length: "); + put_short (cmd_APDU_size); + } else { - unsigned char * r = rsa_sign (&cmd_APDU[5]); + unsigned char * r = rsa_sign (&cmd_APDU[7]); write_res_apdu (r, RSA_SIGNATURE_LENGTH, 0x90, 0x00); } @@ -414,17 +291,19 @@ INS_VERIFY } else { - put_string (" - ???\r\n"); + put_string (" - ??"); + put_byte (cmd_APDU[2]); + put_string (" - ??"); + put_byte (cmd_APDU[3]); write_res_apdu (NULL, 0, 0x90, 0x00); } } else { - put_string (" - ???\r\n"); - write_res_apdu (NULL, 0, 0x90, 0x00); + put_string (" - ??"); + put_byte (cmd_APDU[1]); + write_res_apdu (NULL, 0, 0x6D, 0x00); /* INS not supported. */ } - - return 0; } Thread *gpg_thread; diff --git a/src/main.c b/src/main.c index c10d5cd..0e823de 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,8 @@ #include "hal.h" #include "usb_lld.h" +#include "gnuk.h" + #include "usb_lib.h" #include "usb_istr.h" #include "usb_desc.h" @@ -73,11 +75,11 @@ stdout_init (void) stdout.str = NULL; } -int +void _write (const char *s, int size) { if (size == 0) - return 0; + return; chMtxLock (&stdout.m); while (stdout.str) @@ -87,7 +89,6 @@ _write (const char *s, int size) chCondSignal (&stdout.start_cnd); chCondWait (&stdout.finish_cnd); chMtxUnlock (); - return 0; } extern uint32_t count_in; @@ -180,6 +181,8 @@ int main(int argc, char **argv) (void)argc; (void)argv; + gpg_do_table_init (); + usb_lld_init (); USB_Init(); diff --git a/src/rsa_sign.c b/src/rsa_sign.c index 0817dcb..8e548f7 100644 --- a/src/rsa_sign.c +++ b/src/rsa_sign.c @@ -69,6 +69,9 @@ rsa_sign (unsigned char *raw_message) { rsa_context ctx; mpi P1, Q1, H; + int len; + + len = (cmd_APDU[5]<<8) | cmd_APDU[6]; /* cmd_APDU_size - 6 */ mpi_init( &P1, &Q1, &H, NULL ); rsa_init( &ctx, RSA_PKCS_V15, 0, NULL, NULL ); @@ -104,10 +107,11 @@ rsa_sign (unsigned char *raw_message) } #if 0 - rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_SHA256, 0, raw_message, output); + rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output); + put_string ("done.\r\n"); + return output; #else - rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, 35, raw_message, output ); - + rsa_pkcs1_sign( &ctx, RSA_PRIVATE, SIG_RSA_RAW, len, raw_message, output ); put_string ("done.\r\n"); return output; #endif diff --git a/src/usb-icc.c b/src/usb-icc.c index 825c1e3..ae4e16a 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -130,12 +130,16 @@ EP5_OUT_Callback (void) icc_data_size = len - ICC_MSG_HEADER_SIZE; icc_seq = icc_header->seq; - if (icc_data_size < 0 || icc_data_size != icc_header->data_len) + if (icc_data_size < 0) /* just ignore short invalid packet, enable Rx again */ SetEPRxValid (ENDP5); else /* Notify icc_thread */ chEvtSignalI (icc_thread, EV_RX_DATA_READY); + + /* + * what if (icc_data_size != icc_header->data_len)??? + */ } enum icc_state diff --git a/src/usb_desc.c b/src/usb_desc.c index bf175e8..467aa31 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -67,7 +67,7 @@ static const uint8_t gnukConfigDescriptor[] = { 0, 0, 0, 0, /* dwSynchProtocols: FIXED VALUE */ 0, 0, 0, 0, /* dwMechanical: FIXED VALUE */ 0x40, 0x08, 0x04, 0x00, /* dwFeatures: Short and extended ADPU level */ - 0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 261+10 XXX */ + 0x40, 0x00, 0, 0, /* dwMaxCCIDMessageLength: 64 */ 0xff, /* bClassGetResponse: */ 0xff, /* bClassEnvelope: */ 0, 0, /* wLCDLayout: FIXED VALUE */ @@ -108,7 +108,7 @@ static const uint8_t gnukConfigDescriptor[] = { 5, /* bFunctionLength */ 0x24, /* bDescriptorType: CS_INTERFACE */ 0x01, /* bDescriptorSubtype: Call Management Func Desc */ - 0x00, /* bmCapabilities: D0+D1 */ + 0x03, /* bmCapabilities: D0+D1 */ 0x02, /* bDataInterface: 2 */ /*ACM Functional Descriptor*/ 4, /* bFunctionLength */