diff options
| -rw-r--r-- | NEWS | 2 | ||||
| -rw-r--r-- | doc/gpgme.texi | 2 | ||||
| -rw-r--r-- | src/engine-gpg.c | 95 | ||||
| -rw-r--r-- | src/genkey.c | 85 | ||||
| -rw-r--r-- | src/gpgme.def | 2 | ||||
| -rw-r--r-- | src/libgpgme.vers | 2 | ||||
| -rw-r--r-- | tests/run-genkey.c | 41 | 
7 files changed, 196 insertions, 33 deletions
| @@ -17,6 +17,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]   gpgme_data_set_flag            NEW.   gpgme_op_createkey             NEW.   gpgme_op_createkey_start       NEW. + gpgme_op_createsubkey          NEW. + gpgme_op_createsubkey_start    NEW.   gpgme_genkey_result_t          EXTENDED: New fields pubkey and seckey.   gpgme_signature_t              EXTENDED: New field key.   gpgme_key_t                    EXTENDED: New field fpr. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index dfc9548b..ef39d81b 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -3792,7 +3792,7 @@ The function @code{gpgme_op_genkey} generates a new key pair in the  context @var{ctx}.  The meaning of @var{public} and @var{secret}  depends on the crypto backend. -GnuPG does not support @var{public} and @var{secret}, they should be +GPG does not support @var{public} and @var{secret}, they should be  @code{NULL}.  GnuPG will generate a key pair and add it to the  standard key ring.  The fingerprint of the generated key is available  with @code{gpgme_op_genkey_result}. diff --git a/src/engine-gpg.c b/src/engine-gpg.c index f22d8b44..5a16f805 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1969,6 +1969,47 @@ gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,  } + +/* Helper to add algo, usage, and expire to the list of args.  */ +static gpgme_error_t +gpg_add_algo_usage_expire (engine_gpg_t gpg, +                           const char *algo, +                           unsigned long expires, +                           unsigned int flags) +{ +  gpg_error_t err; + +  /* This condition is only required to allow the use of gpg < 2.1.16 */ +  if (algo +      || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR +                   | GPGME_CREATE_CERT | GPGME_CREATE_AUTH)) +      || expires) +    { +      err = add_arg (gpg, algo? algo : "default"); +      if (!err) +        { +          char tmpbuf[5*4+1]; +          snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s", +                    (flags & GPGME_CREATE_SIGN)? " sign":"", +                    (flags & GPGME_CREATE_ENCR)? " encr":"", +                    (flags & GPGME_CREATE_CERT)? " cert":"", +                    (flags & GPGME_CREATE_AUTH)? " auth":""); +          err = add_arg (gpg, *tmpbuf? tmpbuf : "default"); +        } +      if (!err && expires) +        { +          char tmpbuf[8+20]; +          snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires); +          err = add_arg (gpg, tmpbuf); +        } +    } +  else +    err = 0; + +  return err; +} + +  static gpgme_error_t  gpg_createkey_from_param (engine_gpg_t gpg,                            gpgme_data_t help_data, int use_armor) @@ -2026,32 +2067,8 @@ gpg_createkey (engine_gpg_t gpg,    if (!err)      err = add_arg (gpg, userid); -  /* This condition is only required to allow the use of gpg < 2.1.16 */ -  if (algo -      || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR -                   | GPGME_CREATE_CERT | GPGME_CREATE_AUTH)) -      || expires) -    { - -      if (!err) -        err = add_arg (gpg, algo? algo : "default"); -      if (!err) -        { -          char tmpbuf[5*4+1]; -          snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s", -                    (flags & GPGME_CREATE_SIGN)? " sign":"", -                    (flags & GPGME_CREATE_ENCR)? " encr":"", -                    (flags & GPGME_CREATE_CERT)? " cert":"", -                    (flags & GPGME_CREATE_AUTH)? " auth":""); -          err = add_arg (gpg, *tmpbuf? tmpbuf : "default"); -        } -      if (!err && expires) -        { -          char tmpbuf[8+20]; -          snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires); -          err = add_arg (gpg, tmpbuf); -        } -    } +  if (!err) +    err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);    if (!err)      err = start (gpg); @@ -2067,7 +2084,31 @@ gpg_addkey (engine_gpg_t gpg,              unsigned int flags,              int use_armor)  { -  return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +  gpgme_error_t err; + +  if (!key || !key->fpr) +    return gpg_error (GPG_ERR_INV_ARG); + +  err = add_arg (gpg, "--quick-addkey"); +  if (!err && use_armor) +    err = add_arg (gpg, "--armor"); +  if (!err && (flags & GPGME_CREATE_NOPASSWD)) +    { +      err = add_arg (gpg, "--passphrase"); +      if (!err) +        err = add_arg (gpg, ""); +    } +  if (!err) +    err = add_arg (gpg, "--"); +  if (!err) +    err = add_arg (gpg, key->fpr); + +  if (!err) +    err = gpg_add_algo_usage_expire (gpg, algo, expires, flags); + +  if (!err) +    err = start (gpg); +  return err;  } diff --git a/src/genkey.c b/src/genkey.c index 0b795f43..26bcca6e 100644 --- a/src/genkey.c +++ b/src/genkey.c @@ -387,3 +387,88 @@ gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,      err = _gpgme_wait_one (ctx);    return TRACE_ERR (err);  } + + + +static gpgme_error_t +createsubkey_start (gpgme_ctx_t ctx, int synchronous, +                    gpgme_key_t key, +                    const char *algo, +                    unsigned long reserved, unsigned long expires, +                    unsigned int flags) +{ +  gpgme_error_t err; +  void *hook; +  op_data_t opd; + +  if (ctx->protocol != GPGME_PROTOCOL_OPENPGP) +    return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + +  err = _gpgme_op_reset (ctx, synchronous); +  if (err) +    return err; + +  if (reserved || !key) +    return gpg_error (GPG_ERR_INV_VALUE); + +  err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, +			       sizeof (*opd), release_op_data); +  opd = hook; +  if (err) +    return err; + +  _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx); + +  if (ctx->passphrase_cb) +    { +      err = _gpgme_engine_set_command_handler +        (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL); +      if (err) +        return err; +    } + +  return _gpgme_engine_op_genkey (ctx->engine, +                                  NULL, algo, reserved, expires, +                                  key, flags, +                                  NULL, ctx->use_armor, NULL, NULL); + +} + + +/* Add a subkey to an existing KEY.  */ +gpgme_error_t +gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo, +                             unsigned long reserved, unsigned long expires, +                             unsigned int flags) +{ +  gpgme_error_t err; + +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey_start", ctx, +	      "key=%p, algo='%s' flags=0x%x", key, algo, flags); + +  if (!ctx) +    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + +  err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags); +  return TRACE_ERR (err); +} + + +gpgme_error_t +gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo, +                       unsigned long reserved, unsigned long expires, +                       unsigned int flags) +{ +  gpgme_error_t err; + +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey", ctx, +	      "key=%p, algo='%s' flags=0x%x", key, algo, flags); + +  if (!ctx) +    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + +  err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags); +  if (!err) +    err = _gpgme_wait_one (ctx); +  return TRACE_ERR (err); +} diff --git a/src/gpgme.def b/src/gpgme.def index a56b9efa..7b7b1f20 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -231,6 +231,8 @@ EXPORTS      gpgme_op_createkey_start              @172      gpgme_op_createkey                    @173 +    gpgme_op_createsubkey_start           @174 +    gpgme_op_createsubkey                 @175  ; END diff --git a/src/libgpgme.vers b/src/libgpgme.vers index b06c9c65..2a3e9fc3 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -105,6 +105,8 @@ GPGME_1.1 {      gpgme_op_createkey_start;      gpgme_op_createkey; +    gpgme_op_createsubkey_start; +    gpgme_op_createsubkey;  }; diff --git a/tests/run-genkey.c b/tests/run-genkey.c index 74d4038e..3b645025 100644 --- a/tests/run-genkey.c +++ b/tests/run-genkey.c @@ -201,6 +201,7 @@ show_usage (int ex)  {    fputs ("usage: " PGM " [options] USERID [ALGO [USAGE [EXPIRESECONDS]]]\n\n"           "Options:\n" +         "  --addkey         add a subkey to the key with USERID\n"           "  --verbose        run in verbose mode\n"           "  --status         print status lines from the backend\n"           "  --progress       print progress info\n" @@ -224,6 +225,7 @@ main (int argc, char **argv)    int print_status = 0;    int print_progress = 0;    int use_loopback = 0; +  int addkey = 0;    const char *userid;    const char *algo = NULL;    unsigned int flags = 0; @@ -243,6 +245,11 @@ main (int argc, char **argv)          }        else if (!strcmp (*argv, "--help"))          show_usage (0); +      else if (!strcmp (*argv, "--addkey")) +        { +          addkey = 1; +          argc--; argv++; +        }        else if (!strcmp (*argv, "--verbose"))          {            verbose = 1; @@ -316,12 +323,36 @@ main (int argc, char **argv)        gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);      } -  err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags); -  if (err) +  if (addkey)      { -      fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n", -               gpg_strerror (err)); -      exit (1); +      gpgme_key_t akey; + +      err = gpgme_get_key (ctx, userid, &akey, 1); +      if (err) +        { +          fprintf (stderr, PGM ": error getting secret key for '%s': %s\n", +                   userid, gpg_strerror (err)); +          exit (1); +        } + +      err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags); +      if (err) +        { +          fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n", +                   gpg_strerror (err)); +          exit (1); +        } +      gpgme_key_unref (akey); +    } +  else +    { +      err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags); +      if (err) +        { +          fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n", +                   gpg_strerror (err)); +          exit (1); +        }      }    result = gpgme_op_genkey_result (ctx); | 
