From 9feeeb308bc53951d7489d016bc3361de975aa84 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 20 Feb 2014 12:02:44 +0900 Subject: [PATCH] Add RSA_SIG (disable to use p256k1) --- ChangeLog | 10 ++++ src/Makefile.in | 6 ++- src/openpgp-do.c | 117 +++++++++++++++++++++++++++++++++++++++-------- src/openpgp.c | 37 ++++++++++++--- 4 files changed, 144 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4ce69f8..1954db1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2014-02-20 Niibe Yutaka + * src/Makefile.in (CSRC): Add files of p256k1. + + * src/openpgp.c (cmd_pso): Support p256k1 for signature. + + * src/openpgp-do.c (algorithm_attr_p256k1): New. + (gpg_do_write_prvkey): Support p256k1 for signature. + (proc_key_import, gpg_do_table, gpg_do_public_key): Likewise. + + * src/Makefile.in (DEFS): Add -DRSA_SIG. + * src/openpgp-do.c (gpg_do_write_prvkey): Use _p256r1. * src/openpgp.c (cmd_internal_authenticate): Likewise. diff --git a/src/Makefile.in b/src/Makefile.in index dcea9c5..46169bb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -12,7 +12,9 @@ CSRC = main.c usb_stm32f103.c adc_stm32f103.c \ usb_desc.c usb_ctrl.c \ call-rsa.c \ usb-icc.c openpgp.c ac.c openpgp-do.c flash.c \ - bn.c modp256r1.c jpc_p256r1.c mod.c ec_p256r1.c call-ec_p256r1.c \ + bn.c mod.c \ + modp256r1.c jpc_p256r1.c ec_p256r1.c call-ec_p256r1.c \ + modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \ random.c neug.c sha256.c sys.c INCDIR = @@ -52,7 +54,7 @@ OBJCOPY = $(CROSS)objcopy MCU = cortex-m3 CWARN = -Wall -Wextra -Wstrict-prototypes # DEFS: Add -DEFS = -DCHX_PRIO_MAIN=5 -DRSA_AUTH @KEYGEN_SUPPORT@ @HAVE_SYS_H@ +DEFS = -DCHX_PRIO_MAIN=5 -DRSA_AUTH -DRSA_SIG @KEYGEN_SUPPORT@ @HAVE_SYS_H@ OPT = -O3 -Os -g LIBS = diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 22d8f44..5b5a010 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -1,7 +1,7 @@ /* * openpgp-do.c -- OpenPGP card Data Objects (DO) handling * - * Copyright (C) 2010, 2011, 2012, 2013 + * Copyright (C) 2010, 2011, 2012, 2013, 2014 * Free Software Initiative of Japan * Author: NIIBE Yutaka * @@ -148,6 +148,12 @@ static const uint8_t algorithm_attr_p256r1[] __attribute__ ((aligned (1))) = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 /* OID of NIST curve P-256 */ }; +static const uint8_t algorithm_attr_p256k1[] __attribute__ ((aligned (1))) = { + 6, + 0x13, /* ECDSA */ + 0x2b, 0x81, 0x04, 0x00, 0x0a /* OID of curve secp256k1 */ +}; + /* * Representation of PW1_LIFETIME: * 0: PW1_LIEFTIME_P == NULL : PW1 is valid for single PSO:CDS command @@ -805,10 +811,21 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, /* Delete it first, if any. */ gpg_do_delete_prvkey (kk); -#ifdef RSA_AUTH +#if defined(RSA_AUTH) && defined(RSA_SIG) if (key_len != KEY_CONTENT_LEN) return -1; -#else /* ECDSA for authentication */ +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if (kk != GPG_KEY_FOR_SIGNING && key_len != KEY_CONTENT_LEN) + return -1; + if (kk == GPG_KEY_FOR_SIGNING) + { + pubkey_len = key_len * 2; + if (key_len != 32) + return -1; + } +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if (kk != GPG_KEY_FOR_AUTHENTICATION && key_len != KEY_CONTENT_LEN) return -1; if (kk == GPG_KEY_FOR_AUTHENTICATION) @@ -817,6 +834,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (key_len != 32) return -1; } +#else +#error "not supported." #endif pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data)); @@ -825,13 +844,22 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, if (pubkey == NULL) { -#ifdef RSA_AUTH +#if defined(RSA_AUTH) && defined(RSA_SIG) pubkey_allocated_here = modulus_calc (key_data, key_len); -#else /* ECDSA for authentication */ +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if (kk == GPG_KEY_FOR_SIGNING) + pubkey_allocated_here = ecdsa_compute_public_p256k1 (key_data); + else + pubkey_allocated_here = modulus_calc (key_data, key_len); +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if (kk == GPG_KEY_FOR_AUTHENTICATION) pubkey_allocated_here = ecdsa_compute_public_p256r1 (key_data); else pubkey_allocated_here = modulus_calc (key_data, key_len); +#else +#error "not supported." #endif if (pubkey_allocated_here == NULL) { @@ -858,9 +886,19 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, DEBUG_INFO ("key_addr: "); DEBUG_WORD ((uint32_t)key_addr); -#ifdef RSA_AUTH +#if defined(RSA_AUTH) && defined(RSA_SIG) memcpy (kdi.data, key_data, KEY_CONTENT_LEN); -#else /* ECDSA for authentication */ +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if (kk == GPG_KEY_FOR_SIGNING) + { + memcpy (kdi.data, key_data, key_len); + memset ((uint8_t *)kdi.data + key_len, 0, KEY_CONTENT_LEN - key_len); + } + else + memcpy (kdi.data, key_data, KEY_CONTENT_LEN); +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if (kk == GPG_KEY_FOR_AUTHENTICATION) { memcpy (kdi.data, key_data, key_len); @@ -868,6 +906,8 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len, } else memcpy (kdi.data, key_data, KEY_CONTENT_LEN); +#else +#error "not supported." #endif compute_key_data_checksum (&kdi, 0); @@ -1076,20 +1116,38 @@ proc_key_import (const uint8_t *data, int len) ac_reset_other (); } -#ifdef RSA_AUTH +#if defined(RSA_AUTH) && defined(RSA_SIG) if (len <= 22) -#else /* ECDSA for authentication */ +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if ((kk != GPG_KEY_FOR_SIGNING && len <= 22) + || (kk == GPG_KEY_FOR_SIGNING && len <= 12)) +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if ((kk != GPG_KEY_FOR_AUTHENTICATION && len <= 22) || (kk == GPG_KEY_FOR_AUTHENTICATION && len <= 12)) +#else +#error "not supported." #endif { /* Deletion of the key */ gpg_do_delete_prvkey (kk); return 1; } -#ifdef RSA_AUTH +#if defined(RSA_AUTH) && defined(RSA_SIG) r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL); -#else /* ECDSA for authentication */ +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if (kk != GPG_KEY_FOR_SIGNING) + { /* RSA */ + /* It should starts with 00 01 00 01 (E) */ + /* Skip E, 4-byte */ + r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL); + } + else + r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL); +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if (kk != GPG_KEY_FOR_AUTHENTICATION) { /* RSA */ /* It should starts with 00 01 00 01 (E) */ @@ -1098,6 +1156,8 @@ proc_key_import (const uint8_t *data, int len) } else r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL); +#else +#error "not supported." #endif if (r < 0) @@ -1161,7 +1221,11 @@ gpg_do_table[] = { rw_pw_status }, /* Fixed data */ { GPG_DO_EXTCAP, DO_FIXED, AC_ALWAYS, AC_NEVER, extended_capabilities }, +#ifdef RSA_SIG { GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa }, +#else + { GPG_DO_ALG_SIG, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_p256k1 }, +#endif { GPG_DO_ALG_DEC, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa }, #ifdef RSA_AUTH { GPG_DO_ALG_AUT, DO_FIXED, AC_ALWAYS, AC_NEVER, algorithm_attr_rsa }, @@ -1610,16 +1674,34 @@ gpg_do_public_key (uint8_t kk_byte) /* TAG */ *res_p++ = 0x7f; *res_p++ = 0x49; -#ifndef RSA_AUTH /* ECDSA for authentication */ +#if defined(RSA_AUTH) && defined(RSA_SIG) + if (0) +#elif defined(RSA_AUTH) && !defined(RSA_SIG) + /* ECDSA with p256k1 for signature */ + if (kk_byte == 0xb6) +#elif !defined(RSA_AUTH) && defined(RSA_SIG) + /* ECDSA with p256r1 for authentication */ if (kk_byte == 0xa4) +#else +#error "not supported." +#endif { /* ECDSA */ + const uint8_t *algorithm_attr; + int aa_len; + + if (kk_byte == 0xb6) + algorithm_attr = algorithm_attr_p256k1; + else + algorithm_attr = algorithm_attr_p256r1; + aa_len = algorithm_attr[0] - 1; + /* LEN */ - *res_p++ = 2 + 8 + 2 + 1 + 64; + *res_p++ = 2 + aa_len + 2 + 1 + 64; { - /*TAG*/ /* LEN = 8 */ - *res_p++ = 0x06; *res_p++ = 0x08; - memcpy (res_p, algorithm_attr_p256r1+2, 8); - res_p += 8; + /*TAG*/ /* LEN = AA_LEN */ + *res_p++ = 0x06; *res_p++ = aa_len; + memcpy (res_p, algorithm_attr+2, aa_len); + res_p += aa_len; /*TAG*/ /* LEN = 1+64 */ *res_p++ = 0x86; *res_p++ = 0x41; @@ -1630,7 +1712,6 @@ gpg_do_public_key (uint8_t kk_byte) } } else -#endif { /* RSA */ /* LEN = 9+256 */ *res_p++ = 0x82; *res_p++ = 0x01; *res_p++ = 0x09; diff --git a/src/openpgp.c b/src/openpgp.c index 834470b..db6c8fe 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -1,7 +1,7 @@ /* * openpgp.c -- OpenPGP card protocol support * - * Copyright (C) 2010, 2011, 2012, 2013 + * Copyright (C) 2010, 2011, 2012, 2013, 2014 * Free Software Initiative of Japan * Author: NIIBE Yutaka * @@ -805,6 +805,9 @@ cmd_get_data (void) gpg_do_get_data (tag, 0); } +#define ECDSA_HASH_LEN 32 +#define ECDSA_SIGNATURE_LENGTH 64 + static void cmd_pso (void) { @@ -824,6 +827,7 @@ cmd_pso (void) return; } +#ifdef RSA_SIG /* Check size of digestInfo */ if (len != 34 /* MD5 */ && len != 35 /* SHA1 / RIPEMD-160 */ @@ -852,6 +856,30 @@ cmd_pso (void) /* Success */ gpg_increment_digital_signature_counter (); } +#else + /* ECDSA with p256k1 for signature */ + if (len != ECDSA_HASH_LEN) + { + DEBUG_INFO (" wrong length: "); + GPG_CONDITION_NOT_SATISFIED (); + } + else + { + DEBUG_SHORT (len); + + res_APDU_size = ECDSA_SIGNATURE_LENGTH; + r = ecdsa_sign_p256k1 (apdu.cmd_apdu_data, res_APDU, + kd[GPG_KEY_FOR_SIGNING].data); + if (r < 0) + { + ac_reset_pso_cds (); + GPG_ERROR (); + } + else + /* Success */ + gpg_increment_digital_signature_counter (); + } +#endif } else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86) { @@ -935,9 +963,6 @@ cmd_internal_authenticate (void) DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n"); } #else -#define ECDSA_P256_HASH_LEN 32 -#define ECDSA_SIGNATURE_LENGTH 64 - static void cmd_internal_authenticate (void) { @@ -957,7 +982,7 @@ cmd_internal_authenticate (void) return; } - if (len != ECDSA_P256_HASH_LEN) + if (len != ECDSA_HASH_LEN) { DEBUG_INFO ("wrong hash length."); GPG_CONDITION_NOT_SATISFIED (); @@ -966,7 +991,7 @@ cmd_internal_authenticate (void) res_APDU_size = ECDSA_SIGNATURE_LENGTH; r = ecdsa_sign_p256r1 (apdu.cmd_apdu_data, res_APDU, - kd[GPG_KEY_FOR_AUTHENTICATION]->data); + kd[GPG_KEY_FOR_AUTHENTICATION].data); if (r < 0) GPG_ERROR (); }