Don't use malloc if not needed.
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 3 Oct 2017 07:12:41 +0000 (16:12 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 3 Oct 2017 07:12:41 +0000 (16:12 +0900)
ChangeLog
src/call-ec.c
src/call-ec_p256k1.c
src/call-ec_p256r1.c
src/call-rsa.c
src/ecc-edwards.c
src/ecc-mont.c
src/gnuk.h
src/openpgp-do.c

index 342be8e..81e418b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2017-10-03  NIIBE Yutaka  <gniibe@fsij.org>
 
+       * src/call-ec.c (ecc_compute_public): No use of malloc.
+       * src/call-rsa.c (modulus_calc, rsa_genkey): Likewise.
+       * src/ecc-edwards.c (eddsa_compute_public_25519): Likewise.
+       * src/ecc-mont.c (ecdh_compute_public_25519): Likewise.
+       * src/openpgp-do.c (gpg_do_write_prvkey, gpg_do_chks_prvkey)
+       (proc_key_import, gpg_do_keygen): Likewise.
+
        * polarssl/library/rsa.c: Don't include stdlib.h.
        * src/gnuk-malloc.h: Rename from stdlib.h.
        * polarssl/library/bignum.c: Include gnuk-malloc.h.
index 1350369..c739173 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
  *
- * Copyright (C) 2013, 2014 Free Software Initiative of Japan
+ * Copyright (C) 2013, 2014, 2017  Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -54,28 +54,21 @@ FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
   return 0;
 }
 
-uint8_t *
-FUNC(ecc_compute_public) (const uint8_t *key_data)
+int
+FUNC(ecc_compute_public) (const uint8_t *key_data, uint8_t *pubkey)
 {
-  uint8_t *p0, *p, *p1;
+  uint8_t *p, *p1;
   ac q[1];
   bn256 k[1];
   int i;
 
-  p0 = (uint8_t *)malloc (ECDSA_BYTE_SIZE * 2);
-  if (p0 == NULL)
-    return NULL;
-
   p = (uint8_t *)k;
   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
     p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
   if (FUNC(compute_kG) (q, k) < 0)
-    {
-      free (p0);
-      return NULL;
-    }
+    return -1;
 
-  p = p0;
+  p = pubkey;
   p1 = (uint8_t *)q->x;
   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
     *p++ = p1[ECDSA_BYTE_SIZE - i - 1];
@@ -83,7 +76,7 @@ FUNC(ecc_compute_public) (const uint8_t *key_data)
   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
     *p++ = p1[ECDSA_BYTE_SIZE - i - 1];
 
-  return p0;
+  return 0;
 }
 
 int
index a4908df..efc7cad 100644 (file)
@@ -2,7 +2,7 @@
  * call-ec_p256k1.c - interface between Gnuk and Elliptic curve over
  *                    GF(p256k1)
  *
- * Copyright (C) 2014 Free Software Initiative of Japan
+ * Copyright (C) 2014, 2017  Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
  */
 
 #include <stdint.h>
-#include <stdlib.h>
 #include <string.h>
 #include "bn.h"
 #include "affine.h"
index e9fa040..e851cca 100644 (file)
@@ -2,7 +2,7 @@
  * call-ec_p256r1.c - interface between Gnuk and Elliptic curve over
  *                    GF(p256r1)
  *
- * Copyright (C) 2014 Free Software Initiative of Japan
+ * Copyright (C) 2014, 2017  Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
  */
 
 #include <stdint.h>
-#include <stdlib.h>
 #include <string.h>
 #include "bn.h"
 #include "affine.h"
index 6548ef6..5a7632e 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <stdint.h>
 #include <string.h>
-#include <stdlib.h>
 #include <chopstx.h>
 
 #include "config.h"
@@ -41,7 +40,7 @@ static struct chx_cleanup clp;
 static void
 rsa_cleanup (void *arg)
 {
-  free (arg);
+  (void)arg;
   rsa_free (&rsa_ctx);
 }
 
@@ -111,30 +110,23 @@ rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
 /*
  * LEN: length in byte
  */
-uint8_t *
-modulus_calc (const uint8_t *p, int len)
+int
+modulus_calc (const uint8_t *p, int len, uint8_t *pubkey)
 {
   mpi P, Q, N;
-  uint8_t *modulus;
   int ret;
 
-  modulus = malloc (len);
-  if (modulus == NULL)
-    return NULL;
-
   mpi_init (&P);  mpi_init (&Q);  mpi_init (&N);
   MPI_CHK( mpi_read_binary (&P, p, len / 2) );
   MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
   MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
-  MPI_CHK( mpi_write_binary (&N, modulus, len) );
+  MPI_CHK( mpi_write_binary (&N, pubkey, len) );
  cleanup:
   mpi_free (&P);  mpi_free (&Q);  mpi_free (&N);
   if (ret != 0)
-    {
-      free (modulus);
-      return NULL;
-    }
-  return modulus;
+    return -1;
+
+  return 0;
 }
 
 
@@ -244,45 +236,40 @@ rsa_verify (const uint8_t *pubkey, int pubkey_len,
 
 #define RSA_EXPONENT 0x10001
 
-uint8_t *
-rsa_genkey (int pubkey_len)
+int
+rsa_genkey (int pubkey_len, uint8_t *pubkey, uint8_t *p_q)
 {
   int ret;
   uint8_t index = 0;
-  uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
-  uint8_t *p = p_q_modulus;
-  uint8_t *q = p_q_modulus + pubkey_len / 2;
-  uint8_t *modulus = p_q_modulus + pubkey_len;
+  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),
                        void *p_rng);
   extern void neug_flush (void);
 
-  if (p_q_modulus == NULL)
-    return NULL;
-
   neug_flush ();
   prng_seed (random_gen, &index);
   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
 
   clp.next = NULL;
   clp.routine = rsa_cleanup;
-  clp.arg = (void *)p_q_modulus;
+  clp.arg = NULL;
   chopstx_cleanup_push (&clp);
   cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
   MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
                        RSA_EXPONENT) );
   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, modulus, pubkey_len) );
+  MPI_CHK( mpi_write_binary (&rsa_ctx.N, pubkey, pubkey_len) );
   clp.arg = NULL;
 
  cleanup:
   chopstx_setcancelstate (cs);
   chopstx_cleanup_pop (1);
   if (ret != 0)
-      return NULL;
+    return -1;
   else
-    return p_q_modulus;
+    return 0;
 }
index 16b8ed9..903f48d 100644 (file)
@@ -2,7 +2,7 @@
  * ecc-edwards.c - Elliptic curve computation for
  *                 the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
  *
- * Copyright (C) 2014 Free Software Initiative of Japan
+ * Copyright (C) 2014, 2017  Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -23,7 +23,6 @@
  */
 
 #include <stdint.h>
-#include <stdlib.h>
 #include <string.h>
 
 #include "bn.h"
@@ -708,7 +707,7 @@ eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *out,
   return 0;
 }
 
-void
+static void
 eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
 {
   ac R[1];
@@ -730,18 +729,10 @@ eddsa_public_key_25519 (bn256 *pk, const bn256 *a)
 }
 
 
-uint8_t *
-eddsa_compute_public_25519 (const uint8_t *kd)
+void
+eddsa_compute_public_25519 (const uint8_t *kd, uint8_t *pubkey)
 {
-  uint8_t *p0;
-  const bn256 *a = (const bn256 *)kd;
-
-  p0 = (uint8_t *)malloc (sizeof (bn256));
-  if (p0 == NULL)
-    return NULL;
-
-  eddsa_public_key_25519 ((bn256 *)p0, a);
-  return p0;
+  eddsa_public_key_25519 ((bn256 *)pubkey, (const bn256 *)kd);
 }
 
 
index 062bfe8..635b09f 100644 (file)
@@ -2,7 +2,7 @@
  * ecc-mont.c - Elliptic curve computation for
  *              the Montgomery curve: y^2 = x^3 + 486662*x^2 + x.
  *
- * Copyright (C) 2014, 2015 Free Software Initiative of Japan
+ * Copyright (C) 2014, 2015, 2017  Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -24,7 +24,6 @@
 
 #include <stdint.h>
 #include <string.h>
-#include <stdlib.h>
 #include "bn.h"
 #include "mod25638.h"
 #include "mod.h"
@@ -198,22 +197,17 @@ compute_nQ (bn256 *res, const bn256 *n, const bn256 *q_x)
 }
 
 
-uint8_t *
-ecdh_compute_public_25519 (const uint8_t *key_data)
+void
+ecdh_compute_public_25519 (const uint8_t *key_data, uint8_t *pubkey)
 {
-  uint8_t *p;
   bn256 gx[1];
   bn256 k[1];
 
   memset (gx, 0, sizeof (bn256));
   gx[0].word[0] = 9;                   /* Gx = 9 */
   memcpy (k, key_data, sizeof (bn256));
-  p = (uint8_t *)malloc (sizeof (bn256));
-  if (p == NULL)
-    return NULL;
 
-  compute_nQ ((bn256 *)p, k, gx);
-  return p;
+  compute_nQ ((bn256 *)pubkey, k, gx);
 }
 
 int
index 55aed22..e64f58c 100644 (file)
@@ -265,22 +265,22 @@ void put_binary (const char *s, int len);
 #endif
 
 int rsa_sign (const uint8_t *, uint8_t *, int, struct key_data *, int);
-uint8_t *modulus_calc (const uint8_t *, int);
+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 *);
-uint8_t *rsa_genkey (int);
+int rsa_genkey (int, uint8_t *, uint8_t *);
 
 int ecdsa_sign_p256r1 (const uint8_t *hash, uint8_t *output,
                       const uint8_t *key_data);
-uint8_t *ecc_compute_public_p256r1 (const uint8_t *key_data);
+int ecc_compute_public_p256r1 (const uint8_t *key_data, uint8_t *);
 int ecc_check_secret_p256r1 (const uint8_t *d0, uint8_t *d1);
 int ecdh_decrypt_p256r1 (const uint8_t *input, uint8_t *output,
                         const uint8_t *key_data);
 
 int ecdsa_sign_p256k1 (const uint8_t *hash, uint8_t *output,
                       const uint8_t *key_data);
-uint8_t *ecc_compute_public_p256k1 (const uint8_t *key_data);
+int ecc_compute_public_p256k1 (const uint8_t *key_data, uint8_t *);
 int ecc_check_secret_p256k1 (const uint8_t *d0, uint8_t  *d1);
 int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
                         const uint8_t *key_data);
@@ -288,8 +288,8 @@ int ecdh_decrypt_p256k1 (const uint8_t *input, uint8_t *output,
 int eddsa_sign_25519 (const uint8_t *input, size_t ilen, uint32_t *output,
                      const uint8_t *sk_a, const uint8_t *seed,
                      const uint8_t *pk);
-uint8_t *eddsa_compute_public_25519 (const uint8_t *a);
-uint8_t *ecdh_compute_public_25519 (const uint8_t *a);
+void eddsa_compute_public_25519 (const uint8_t *a, uint8_t *);
+void ecdh_compute_public_25519 (const uint8_t *a, uint8_t *);
 int ecdh_decrypt_curve25519 (const uint8_t *input, uint8_t *output,
                             const uint8_t *key_data);
 
index 431f1e8..de0499a 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <stdint.h>
 #include <string.h>
-#include <stdlib.h>
 
 #include "config.h"
 
@@ -1083,11 +1082,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
   int attr = gpg_get_algo_attr (kk);;
   const uint8_t *p;
   int r;
-  struct prvkey_data *pd;
+  struct prvkey_data prv;
+  struct prvkey_data *pd = &prv;
   uint8_t *key_addr;
   const uint8_t *dek, *iv;
   struct key_data_internal kdi;
-  uint8_t *pubkey_allocated_here = NULL;
   int pubkey_len;
   uint8_t ks[KEYSTRING_MD_SIZE];
   enum kind_of_key kk0;
@@ -1098,10 +1097,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
   /* Delete it first, if any.  */
   gpg_do_delete_prvkey (kk, CLEAN_SINGLE);
 
-  pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
-  if (pd == NULL)
-    return -1;
-
   if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
     {
       pubkey_len = prvkey_len * 2;
@@ -1129,38 +1124,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
        return -1;
     }
 
-  if (pubkey == NULL)
-    {
-      if (attr == ALGO_SECP256K1)
-       pubkey_allocated_here = ecc_compute_public_p256k1 (key_data);
-      else if (attr == ALGO_NISTP256R1)
-       pubkey_allocated_here = ecc_compute_public_p256r1 (key_data);
-      else if (attr == ALGO_ED25519)
-       pubkey_allocated_here = eddsa_compute_public_25519 (key_data);
-      else if (attr == ALGO_CURVE25519)
-       pubkey_allocated_here = ecdh_compute_public_25519 (key_data);
-      else                             /* RSA */
-       pubkey_allocated_here = modulus_calc (key_data, prvkey_len);
-
-      if (pubkey_allocated_here == NULL)
-       {
-         free (pd);
-         return -1;
-       }
-    }
-
   DEBUG_INFO ("Getting keystore address...\r\n");
   key_addr = flash_key_alloc (kk);
   if (key_addr == NULL)
-    {
-      if (pubkey_allocated_here)
-       {
-         memset (pubkey_allocated_here, 0, pubkey_len);
-         free (pubkey_allocated_here);
-       }
-      free (pd);
-      return -1;
-    }
+    return -1;
+
   kd[kk].pubkey = key_addr + prvkey_len;
 
   num_prv_keys++;
@@ -1196,19 +1164,11 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
   encrypt (dek, iv, (uint8_t *)&kdi, kdi_len (prvkey_len));
 
   r = flash_key_write (key_addr, (const uint8_t *)kdi.data, prvkey_len,
-                      pubkey_allocated_here? pubkey_allocated_here: pubkey,
-                      pubkey_len);
-  if (pubkey_allocated_here)
-    {
-      memset (pubkey_allocated_here, 0, pubkey_len);
-      free (pubkey_allocated_here);
-    }
-
+                      pubkey, pubkey_len);
   if (r < 0)
     {
       random_bytes_free (dek);
       memset (pd, 0, sizeof (struct prvkey_data));
-      free (pd);
       return r;
     }
 
@@ -1230,7 +1190,6 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data,
 
   random_bytes_free (dek);
   memset (pd, 0, sizeof (struct prvkey_data));
-  free (pd);
   if (p == NULL)
     return -1;
 
@@ -1262,7 +1221,8 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
   uint8_t nr = get_do_ptr_nr_for_kk (kk);
   const uint8_t *do_data = do_ptr[nr];
   uint8_t dek[DATA_ENCRYPTION_KEY_SIZE];
-  struct prvkey_data *pd;
+  struct prvkey_data prv;
+  struct prvkey_data *pd = &prv;
   uint8_t *dek_p;
   int update_needed = 0;
   int r = 1;                   /* Success */
@@ -1270,10 +1230,6 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
   if (do_data == NULL)
     return 0;                  /* No private key */
 
-  pd = (struct prvkey_data *)malloc (sizeof (struct prvkey_data));
-  if (pd == NULL)
-    return -1;
-
   memcpy (pd, &do_data[1], sizeof (struct prvkey_data));
 
   dek_p = ((uint8_t *)pd) + INITIAL_VECTOR_SIZE
@@ -1315,7 +1271,6 @@ gpg_do_chks_prvkey (enum kind_of_key kk,
     }
 
   memset (pd, 0, sizeof (struct prvkey_data));
-  free (pd);
 
   return r;
 }
@@ -1372,6 +1327,7 @@ proc_key_import (const uint8_t *data, int len)
   const uint8_t *keystring_admin;
   int attr;
   const uint8_t *p = data;
+  uint8_t pubkey[512];
 
   if (admin_authorized == BY_ADMIN)
     keystring_admin = keystring_md_pw3;
@@ -1411,13 +1367,35 @@ proc_key_import (const uint8_t *data, int len)
     }
 
   if (attr == ALGO_RSA2K)
-    /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
-    r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin, NULL);
+    {
+      /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
+      r = modulus_calc (&data[26], len - 26, pubkey);
+      if (r >= 0)
+       r = gpg_do_write_prvkey (kk, &data[26], len - 26, keystring_admin,
+                                pubkey);
+    }
   else if (attr == ALGO_RSA4K)
-    /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
-    r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin, NULL);
-  else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
-    r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin, NULL);
+    {
+      /* It should starts with 00 01 00 01 (E), skiping E (4-byte) */
+      r = modulus_calc (&data[28], len - 28, pubkey);
+      if (r >= 0)
+       r = gpg_do_write_prvkey (kk, &data[28], len - 28, keystring_admin,
+                                pubkey);
+    }
+  else if (attr == ALGO_NISTP256R1)
+    {
+      r = ecc_compute_public_p256r1 (&data[12], pubkey);
+      if (r >= 0)
+       r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
+                                pubkey);
+    }
+  else if (attr == ALGO_SECP256K1)
+    {
+      r = ecc_compute_public_p256k1 (&data[12], pubkey);
+      if (r >= 0)
+       r = gpg_do_write_prvkey (kk, &data[12], len - 12, keystring_admin,
+                                pubkey);
+    }
   else if (attr == ALGO_ED25519)
     {
       uint8_t hash[64];
@@ -1429,7 +1407,8 @@ proc_key_import (const uint8_t *data, int len)
       hash[0] &= 248;
       hash[31] &= 127;
       hash[31] |= 64;
-      r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, NULL);
+      eddsa_compute_public_25519 (hash, pubkey);
+      r = gpg_do_write_prvkey (kk, hash, 64, keystring_admin, pubkey);
     }
   else if (attr == ALGO_CURVE25519)
     {
@@ -1441,7 +1420,8 @@ proc_key_import (const uint8_t *data, int len)
 
       for (i = 0; i < 32; i++)
        priv[31-i] = data[12+i];
-      r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, NULL);
+      ecdh_compute_public_25519 (priv, pubkey);
+      r = gpg_do_write_prvkey (kk, priv, 32, keystring_admin, pubkey);
     }
 
   if (r < 0)
@@ -2084,12 +2064,12 @@ gpg_do_keygen (uint8_t 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 *keystring_admin;
-  uint8_t *p_q_modulus = NULL;
-  uint8_t d[64];
   const uint8_t *rnd;
   const uint8_t *prv;
-  const uint8_t *pubkey;
-  int r;
+  uint8_t d[64];
+  uint8_t p_q[512];
+  uint8_t pubkey[512];
+  int r = 0;
 
   DEBUG_INFO ("Keygen\r\n");
   DEBUG_BYTE (kk_byte);
@@ -2101,15 +2081,13 @@ gpg_do_keygen (uint8_t kk_byte)
 
   if (attr == ALGO_RSA2K || attr == ALGO_RSA4K)
     {
-      p_q_modulus = rsa_genkey (prvkey_len);
-      if (p_q_modulus == NULL)
+      if (rsa_genkey (prvkey_len, pubkey, p_q) < 0)
        {
          GPG_MEMORY_FAILURE ();
          return;
        }
 
-      prv = p_q_modulus;
-      pubkey = p_q_modulus + prvkey_len;
+      prv = p_q;
     }
   else if (attr == ALGO_NISTP256R1 || attr == ALGO_SECP256K1)
     {
@@ -2142,7 +2120,10 @@ gpg_do_keygen (uint8_t kk_byte)
       random_bytes_free (rnd);
 
       prv = d;
-      pubkey = NULL;
+      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)
     {
@@ -2153,7 +2134,7 @@ gpg_do_keygen (uint8_t kk_byte)
       d[31] &= 127;
       d[31] |= 64;
       prv = d;
-      pubkey = NULL;
+      eddsa_compute_public_25519 (d, pubkey);
     }
   else if (attr == ALGO_CURVE25519)
     {
@@ -2164,7 +2145,7 @@ gpg_do_keygen (uint8_t kk_byte)
       d[31] &= 127;
       d[31] |= 64;
       prv = d;
-      pubkey = NULL;
+      ecdh_compute_public_25519 (prv, pubkey);
     }
   else
     {
@@ -2172,12 +2153,9 @@ gpg_do_keygen (uint8_t kk_byte)
       return;
     }
 
-  r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
-  if (p_q_modulus)
-    {
-      memset (p_q_modulus, 0, prvkey_len * 2);
-      free (p_q_modulus);
-    }
+  if (r >= 0)
+    r = gpg_do_write_prvkey (kk, prv, prvkey_len, keystring_admin, pubkey);
+  /* XXX: clear private key data on stack here.  */
   if (r < 0)
     {
       GPG_ERROR ();