generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
{
  gpg_error_t err = 0;
  kbnode_t node;
  PKT_public_key *pri_psk = NULL;
  PKT_public_key *sub_psk = NULL;
  int algo;
  unsigned int use;
  u32 expire;
  unsigned int nbits = 0;
  char *curve = NULL;
  u32 cur_time;
  char *hexgrip = NULL;
  char *serialno = NULL;

  /* Break out the primary key.  */
  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
  if (!node)
    {
      log_error ("Oops; primary key missing in keyblock!\n");
      err = gpg_error (GPG_ERR_BUG);
      goto leave;
    }
  pri_psk = node->pkt->pkt.public_key;

  cur_time = make_timestamp ();

  if (pri_psk->timestamp > cur_time)
    {
      ulong d = pri_psk->timestamp - cur_time;
      log_info ( d==1 ? _("key has been created %lu second "
                          "in future (time warp or clock problem)\n")
                 : _("key has been created %lu seconds "
                     "in future (time warp or clock problem)\n"), d );
      if (!opt.ignore_time_conflict)
        {
          err = gpg_error (GPG_ERR_TIME_CONFLICT);
          goto leave;
        }
    }

  if (pri_psk->version < 4)
    {
      log_info (_("Note: creating subkeys for v3 keys "
                  "is not OpenPGP compliant\n"));
      err = gpg_error (GPG_ERR_CONFLICT);
      goto leave;
    }

  err = hexkeygrip_from_pk (pri_psk, &hexgrip);
  if (err)
    goto leave;
  if (agent_get_keyinfo (NULL, hexgrip, &serialno))
    {
      tty_printf (_("Secret parts of primary key are not available.\n"));
      goto leave;
    }
  if (serialno)
    tty_printf (_("Secret parts of primary key are stored on-card.\n"));

  xfree (hexgrip);
  hexgrip = NULL;
  algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
  assert (algo);

  if (hexgrip)
    nbits = 0;
  else if (algo == PUBKEY_ALGO_ECDSA
           || algo == PUBKEY_ALGO_EDDSA
           || algo == PUBKEY_ALGO_ECDH)
    curve = ask_curve (&algo, 0);
  else
    nbits = ask_keysize (algo, 0);

  expire = ask_expire_interval (0, NULL);
  if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
                                               _("Really create? (y/N) ")))
    {
      err = gpg_error (GPG_ERR_CANCELED);
      goto leave;
    }

  if (hexgrip)
    err = do_create_from_keygrip (ctrl, algo, hexgrip,
                                  keyblock, cur_time, expire, 1);
  else
    err = do_create (algo, nbits, curve,
                     keyblock, cur_time, expire, 1, 0, NULL, NULL);
  if (err)
    goto leave;

  /* Get the pointer to the generated public subkey packet.  */
  for (node = keyblock; node; node = node->next)
    if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
      sub_psk = node->pkt->pkt.public_key;

  /* Write the binding signature.  */
  err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL);
  if (err)
    goto leave;

  write_status_text (STATUS_KEY_CREATED, "S");

 leave:
  xfree (curve);
  xfree (hexgrip);
  xfree (serialno);
  if (err)
    log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
  return err;
}
generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
{
  gpg_error_t err = 0;
  kbnode_t node;
  PKT_public_key *pri_psk = NULL;
  PKT_public_key *sub_psk = NULL;
  int algo;
  unsigned int use;
  u32 expire;
  unsigned int nbits = 0;
  char *curve = NULL;
  u32 cur_time;
  char *hexgrip = NULL;
  char *serialno = NULL;

   
  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
  if (!node)
    {
      log_error ("Oops; primary key missing in keyblock!\n");
      err = gpg_error (GPG_ERR_BUG);
      goto leave;
    }
  pri_psk = node->pkt->pkt.public_key;

  cur_time = make_timestamp ();

  if (pri_psk->timestamp > cur_time)
    {
      ulong d = pri_psk->timestamp - cur_time;
      log_info ( d==1 ? _("key has been created %lu second "
                          "in future (time warp or clock problem)\n")
                 : _("key has been created %lu seconds "
                     "in future (time warp or clock problem)\n"), d );
      if (!opt.ignore_time_conflict)
        {
          err = gpg_error (GPG_ERR_TIME_CONFLICT);
          goto leave;
        }
    }

  if (pri_psk->version < 4)
    {
      log_info (_("Note: creating subkeys for v3 keys "
                  "is not OpenPGP compliant\n"));
      err = gpg_error (GPG_ERR_CONFLICT);
      goto leave;
    }

  err = hexkeygrip_from_pk (pri_psk, &hexgrip);
  if (err)
    goto leave;
  if (agent_get_keyinfo (NULL, hexgrip, &serialno))
    {
      tty_printf (_("Secret parts of primary key are not available.\n"));
      goto leave;
    }
  if (serialno)
    tty_printf (_("Secret parts of primary key are stored on-card.\n"));

  xfree (hexgrip);
  hexgrip = NULL;
  algo = ask_algo (ctrl, 1, NULL, &use, &hexgrip);
  assert (algo);

  if (hexgrip)
    nbits = 0;
  else if (algo == PUBKEY_ALGO_ECDSA
           || algo == PUBKEY_ALGO_EDDSA
           || algo == PUBKEY_ALGO_ECDH)
    curve = ask_curve (&algo, 0);
  else
    nbits = ask_keysize (algo, 0);

  expire = ask_expire_interval (0, NULL);
  if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
                                               _("Really create? (y/N) ")))
    {
      err = gpg_error (GPG_ERR_CANCELED);
      goto leave;
    }

  if (hexgrip)
    err = do_create_from_keygrip (ctrl, algo, hexgrip,
                                  keyblock, cur_time, expire, 1);
  else
    err = do_create (algo, nbits, curve,
                     keyblock, cur_time, expire, 1, 0, NULL, NULL);
  if (err)
    goto leave;

   
  for (node = keyblock; node; node = node->next)
    if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
      sub_psk = node->pkt->pkt.public_key;

   
  err = write_keybinding (keyblock, pri_psk, sub_psk, use, cur_time, NULL);
  if (err)
    goto leave;

  write_status_text (STATUS_KEY_CREATED, "S");

 leave:
  xfree (curve);
  xfree (hexgrip);
  xfree (serialno);
  if (err)
    log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
  return err;
}