diff --git a/ChangeLog b/ChangeLog index 8e9ce09..049706d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2017-10-05 NIIBE Yutaka + * src/call-rsa.c (rsa_genkey): Single step. + * src/openpgp-do.c (gpg_do_keygen): Do RSA key generation in single + step, using APDU buffer. + * src/openpgp.c (cmd_pgp_gakp): Supply the APDU as a buffer. + * src/Makefile (install): New target. * src/configure (prefix. exec_prefix, libexecdir): Add. diff --git a/src/call-rsa.c b/src/call-rsa.c index 88fff99..57b7c9e 100644 --- a/src/call-rsa.c +++ b/src/call-rsa.c @@ -237,10 +237,12 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len, #define RSA_EXPONENT 0x10001 int -rsa_genkey_start (int pubkey_len) +rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q) { int ret; uint8_t index = 0; + uint8_t *p = p_q; + uint8_t *q = p_q + pubkey_len / 2; int cs; extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t), @@ -258,30 +260,13 @@ rsa_genkey_start (int pubkey_len) cs = chopstx_setcancelstate (0); /* Allow cancellation. */ MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8, RSA_EXPONENT) ); - - cleanup: - chopstx_setcancelstate (cs); - chopstx_cleanup_pop (0); - if (ret != 0) - return -1; - else - return 0; -} - -int -rsa_genkey_finish (int pubkey_len, uint8_t *pubkey, uint8_t *p_q) -{ - int ret; - uint8_t *p = p_q; - uint8_t *q = p_q + pubkey_len / 2; - MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) ); MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) ); MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) ); cleanup: - rsa_free (&rsa_ctx); - + chopstx_setcancelstate (cs); + chopstx_cleanup_pop (1); if (ret != 0) return -1; else diff --git a/src/gnuk.h b/src/gnuk.h index 1b9b340..77189a4 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -112,7 +112,7 @@ void gpg_do_terminate (void); void gpg_do_get_data (uint16_t tag, int with_tag); void gpg_do_put_data (uint16_t tag, const uint8_t *data, int len); void gpg_do_public_key (uint8_t kk_byte); -void gpg_do_keygen (uint8_t kk_byte); +void gpg_do_keygen (uint8_t *buf); const uint8_t *gpg_get_firmware_update_key (uint8_t keyno); @@ -269,8 +269,7 @@ int modulus_calc (const uint8_t *, int, uint8_t *); int rsa_decrypt (const uint8_t *, uint8_t *, int, struct key_data *, unsigned int *); int rsa_verify (const uint8_t *, int, const uint8_t *, const uint8_t *); -int rsa_genkey_start (int); -int rsa_genkey_finish (int, uint8_t *, uint8_t *); +int rsa_genkey (int, uint8_t *, uint8_t *); int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output, const uint8_t *key_data); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 2405791..7c34bf4 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -2058,121 +2058,110 @@ gpg_do_write_simple (uint8_t nr, const uint8_t *data, int size) } void -gpg_do_keygen (uint8_t kk_byte) +gpg_do_keygen (uint8_t *buf) { + uint8_t kk_byte = buf[0]; enum kind_of_key kk = kkb_to_kk (kk_byte); int attr = gpg_get_algo_attr (kk);; int prvkey_len = gpg_get_algo_attr_key_size (kk, GPG_KEY_PRIVATE); + const uint8_t *prv; + const uint8_t *rnd; int r = 0; +#define p_q buf +#define d buf +#define d1 (&buf[64]) +#define pubkey (&buf[256]) DEBUG_INFO ("Keygen\r\n"); DEBUG_BYTE (kk_byte); - /* RSA key generation is done in two steps to lower memory pressure. */ if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) { - if (rsa_genkey_start (prvkey_len) < 0) + if (rsa_genkey (prvkey_len, pubkey, p_q) < 0) { GPG_MEMORY_FAILURE (); return; } + + prv = p_q; + } + else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1) + { + const uint8_t *p; + int i, r; + + rnd = NULL; + do + { + if (rnd) + random_bytes_free (rnd); + rnd = random_bytes_get (); + if (attr == ALGO_NISTP256R1) + r = ecc_check_secret_p256r1 (rnd, d1); + else + r = ecc_check_secret_p256k1 (rnd, d1); + } + while (r == 0); + + /* Convert it to big endian */ + + if (r < 0) + p = (const uint8_t *)d1; + else + p = rnd; + for (i = 0; i < 32; i++) + d[32 - i - 1] = p[i]; + + random_bytes_free (rnd); + + prv = d; + if (attr == ALGO_SECP256K1) + r = ecc_compute_public_p256k1 (prv, pubkey); + else if (attr == ALGO_NISTP256R1) + r = ecc_compute_public_p256r1 (prv, pubkey); + } + else if (attr == ALGO_ED25519) + { + rnd = random_bytes_get (); + sha512 (rnd, 32, d); + random_bytes_free (rnd); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + prv = d; + eddsa_compute_public_25519 (d, pubkey); + } + else if (attr == ALGO_CURVE25519) + { + rnd = random_bytes_get (); + memcpy (d, rnd, 32); + random_bytes_free (rnd); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + prv = d; + ecdh_compute_public_25519 (prv, pubkey); + } + else + { + GPG_CONDITION_NOT_SATISFIED (); + return; } - { - const uint8_t *prv; - const uint8_t *rnd; - uint8_t d[64]; - uint8_t p_q[512]; - uint8_t pubkey[512]; + if (r >= 0) + { + const uint8_t *keystring_admin; - if (attr == ALGO_RSA2K || attr == ALGO_RSA4K) - { - if (rsa_genkey_finish (prvkey_len, pubkey, p_q) < 0) - { - GPG_MEMORY_FAILURE (); - return; - } + if (admin_authorized == BY_ADMIN) + keystring_admin = keystring_md_pw3; + else + keystring_admin = NULL; - prv = p_q; - } - else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1) - { - uint8_t d1[32]; - const uint8_t *p; - int i, r; + r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey); + } - rnd = NULL; - do - { - if (rnd) - random_bytes_free (rnd); - rnd = random_bytes_get (); - if (attr == ALGO_NISTP256R1) - r = ecc_check_secret_p256r1 (rnd, d1); - else - r = ecc_check_secret_p256k1 (rnd, d1); - } - while (r == 0); - - /* Convert it to big endian */ - - if (r < 0) - p = (const uint8_t *)d1; - else - p = rnd; - for (i = 0; i < 32; i++) - d[32 - i - 1] = p[i]; - - random_bytes_free (rnd); - - prv = d; - if (attr == ALGO_SECP256K1) - r = ecc_compute_public_p256k1 (prv, pubkey); - else if (attr == ALGO_NISTP256R1) - r = ecc_compute_public_p256r1 (prv, pubkey); - } - else if (attr == ALGO_ED25519) - { - rnd = random_bytes_get (); - sha512 (rnd, 32, d); - random_bytes_free (rnd); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - prv = d; - eddsa_compute_public_25519 (d, pubkey); - } - else if (attr == ALGO_CURVE25519) - { - rnd = random_bytes_get (); - memcpy (d, rnd, 32); - random_bytes_free (rnd); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - prv = d; - ecdh_compute_public_25519 (prv, pubkey); - } - else - { - GPG_CONDITION_NOT_SATISFIED (); - return; - } - - if (r >= 0) - { - const uint8_t *keystring_admin; - - if (admin_authorized == BY_ADMIN) - keystring_admin = keystring_md_pw3; - else - keystring_admin = NULL; - - r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey); - } - - /* XXX: clear private key data on stack here. */ - } + /* Clear private key data in the buffer. */ + memset (buf, 0, 256); if (r < 0) { diff --git a/src/openpgp.c b/src/openpgp.c index 9ffd76b..f0d8d7b 100644 --- a/src/openpgp.c +++ b/src/openpgp.c @@ -644,7 +644,7 @@ cmd_pgp_gakp (void) { if (!ac_check_status (AC_ADMIN_AUTHORIZED)) GPG_SECURITY_FAILURE (); - gpg_do_keygen (apdu.cmd_apdu_data[0]); + gpg_do_keygen (&apdu.cmd_apdu_data[0]); } }