RSA in a single step.

This commit is contained in:
NIIBE Yutaka
2017-10-05 17:06:50 +09:00
parent 183cec8a04
commit 43980d1c81
5 changed files with 97 additions and 119 deletions

View File

@@ -1,5 +1,10 @@
2017-10-05 NIIBE Yutaka <gniibe@fsij.org>
* 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.

View File

@@ -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

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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]);
}
}