RSA in a single step.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 5 Oct 2017 08:06:50 +0000 (17:06 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 5 Oct 2017 08:06:50 +0000 (17:06 +0900)
ChangeLog
src/call-rsa.c
src/gnuk.h
src/openpgp-do.c
src/openpgp.c

index 8e9ce09..049706d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
index 88fff99..57b7c9e 100644 (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
index 1b9b340..77189a4 100644 (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);
index 2405791..7c34bf4 100644 (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;
        }
-    }
-
-  {
-    const uint8_t *prv;
-    const uint8_t *rnd;
-    uint8_t d[64];
-    uint8_t p_q[512];
-    uint8_t pubkey[512];
-
-    if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
-      {
-       if (rsa_genkey_finish (prvkey_len, pubkey, p_q) < 0)
-         {
-           GPG_MEMORY_FAILURE ();
-           return;
-         }
 
-       prv = p_q;
-      }
-    else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
-      {
-       uint8_t d1[32];
-       const uint8_t *p;
-       int i, r;
+      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);
+      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 */
+      /* 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];
+      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);
+      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;
-      }
+      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 (r >= 0)
+    {
+      const uint8_t *keystring_admin;
 
-       if (admin_authorized == BY_ADMIN)
-         keystring_admin = keystring_md_pw3;
-       else
-         keystring_admin = NULL;
+      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);
-      }
+      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)
     {
index 9ffd76b..f0d8d7b 100644 (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]);
     }
 }