core: Implement adding ADSKs through gpgme_createsubkey

* src/engine-gpg.c: Add and use function for adding ADSKs.
* src/genkey.c: Prevent error due to no status line.
* src/gpgme.h.in: Add flag GPGME_CREATE_ADSK
* doc/gpgme.texi: Add documentation for ADSKs
* tests/run-genkey.c: Add test for adding ADSKs
--

This adds the ability to add ADSKs through
the gpgme_createsubkey interface.
The function must be called with NULL userid,
the ADSK fingerprint in algo
and the GPGME_CREATE_ADSK flag.
This commit is contained in:
Tobias Fella 2024-01-03 14:21:41 +01:00
parent ac4bf86bb6
commit e42b72bc2b
No known key found for this signature in database
GPG Key ID: F315CBBEE5E1889B
5 changed files with 88 additions and 4 deletions

View File

@ -4355,6 +4355,11 @@ override this check.
Request generation of keys that do not expire. Request generation of keys that do not expire.
@item GPGME_CREATE_ADSK
@since{1.24.0}
Add an ADSK to the key.
@end table @end table
After the operation completed successfully, information about the After the operation completed successfully, information about the
@ -4430,6 +4435,10 @@ values for timestamps and thus can only encode dates up to the year
@var{flags} takes the same values as described above for @var{flags} takes the same values as described above for
@code{gpgme_op_createkey}. @code{gpgme_op_createkey}.
If the @code{GPGME_CREATE_ADSK} flag is set, the subkey fingerprint
given in the @code{algo} parameter is added as an ADSK
to the key.
After the operation completed successfully, information about the After the operation completed successfully, information about the
created key can be retrieved with @code{gpgme_op_genkey_result}. created key can be retrieved with @code{gpgme_op_genkey_result}.

View File

@ -2855,6 +2855,33 @@ gpg_adduid (engine_gpg_t gpg,
} }
static gpgme_error_t
gpg_addadsk (engine_gpg_t gpg, gpgme_key_t key, const char *adskfpr)
{
gpgme_error_t err;
if (!key || !key->fpr)
return gpg_error (GPG_ERR_INV_ARG);
if (!adskfpr || !*adskfpr)
return gpg_error (GPG_ERR_INV_ARG);
if (!have_gpg_version (gpg, "2.4.1"))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
err = add_arg (gpg, "--quick-add-adsk");
if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_arg (gpg, key->fpr);
if (!err)
err = add_arg (gpg, adskfpr);
if (!err)
err = start (gpg);
return err;
}
static gpgme_error_t static gpgme_error_t
gpg_genkey (void *engine, gpg_genkey (void *engine,
const char *userid, const char *algo, const char *userid, const char *algo,
@ -2878,6 +2905,8 @@ gpg_genkey (void *engine,
* !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14) * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
* USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14). * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
* or set a flag on a user id. * or set a flag on a user id.
* !USERID && KEY && ALGO
* && GPGME_CREATE_ADSK - Add ALGO as an ADSK to KEY.
*/ */
if (help_data) if (help_data)
{ {
@ -2894,10 +2923,12 @@ gpg_genkey (void *engine,
err = gpg_error (GPG_ERR_NOT_SUPPORTED); err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else if (userid && !key) else if (userid && !key)
err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags); err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags);
else if (!userid && key) else if (!userid && key && !(flags & GPGME_CREATE_ADSK))
err = gpg_addkey (gpg, algo, expires, key, flags, extraflags); err = gpg_addkey (gpg, algo, expires, key, flags, extraflags);
else if (userid && key && !algo) else if (userid && key && !algo)
err = gpg_adduid (gpg, key, userid, extraflags); err = gpg_adduid (gpg, key, userid, extraflags);
else if (!userid && key && algo && (flags & GPGME_CREATE_ADSK))
err = gpg_addadsk (gpg, key, algo);
else else
err = gpg_error (GPG_ERR_INV_VALUE); err = gpg_error (GPG_ERR_INV_VALUE);

View File

@ -48,6 +48,9 @@ typedef struct
/* The key parameters passed to the crypto engine. */ /* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter; gpgme_data_t key_parameter;
/* Flag to indicate that an ADSK is to be added. */
unsigned int adskmode : 1;
} *op_data_t; } *op_data_t;
@ -180,7 +183,7 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
case GPGME_STATUS_EOF: case GPGME_STATUS_EOF:
if (opd->error_code) if (opd->error_code)
return opd->error_code; return opd->error_code;
else if (!opd->uidmode && !opd->result.primary && !opd->result.sub) else if (!opd->uidmode && !opd->adskmode && !opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
else if (opd->failure_code) else if (opd->failure_code)
return opd->failure_code; return opd->failure_code;
@ -445,6 +448,9 @@ createsubkey_start (gpgme_ctx_t ctx, int synchronous,
return err; return err;
} }
if (flags & GPGME_CREATE_ADSK)
opd->adskmode = 1;
return _gpgme_engine_op_genkey (ctx->engine, return _gpgme_engine_op_genkey (ctx->engine,
NULL, algo, reserved, expires, NULL, algo, reserved, expires,
key, flags, key, flags,

View File

@ -1838,6 +1838,7 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx,
#define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */ #define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */
#define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */ #define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */
#define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */ #define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */
#define GPGME_CREATE_ADSK (1 << 14) /* Add an ADSK */
/* An object to return result from a key generation. /* An object to return result from a key generation.

View File

@ -215,6 +215,7 @@ show_usage (int ex)
" for revuid: FPR USERID\n" " for revuid: FPR USERID\n"
" for setexpire: FPR EXPIRE [SUBFPRS]\n" " for setexpire: FPR EXPIRE [SUBFPRS]\n"
" for set-primary: FPR USERID\n" " for set-primary: FPR USERID\n"
" for addadsk: FPR ADSKFPR\n"
"Options:\n" "Options:\n"
" --addkey add a subkey to the key with FPR\n" " --addkey add a subkey to the key with FPR\n"
" --adduid add a user id to the key with FPR\n" " --adduid add a user id to the key with FPR\n"
@ -222,6 +223,7 @@ show_usage (int ex)
" --set-primary set the primary key flag on USERID\n" " --set-primary set the primary key flag on USERID\n"
" --setexpire set the expiration time of the key FPR\n" " --setexpire set the expiration time of the key FPR\n"
" or of its subkeys SUBFPRS\n" " or of its subkeys SUBFPRS\n"
" --addadsk add the subkey with ADSKFPR to the key FPR\n"
" --verbose run in verbose mode\n" " --verbose run in verbose mode\n"
" --status print status lines from the backend\n" " --status print status lines from the backend\n"
" --progress print progress info\n" " --progress print progress info\n"
@ -250,6 +252,7 @@ main (int argc, char **argv)
int revuid = 0; int revuid = 0;
int setpri = 0; int setpri = 0;
int setexpire = 0; int setexpire = 0;
int addadsk = 0;
const char *userid; const char *userid;
const char *algo = NULL; const char *algo = NULL;
const char *newuserid = NULL; const char *newuserid = NULL;
@ -260,6 +263,7 @@ main (int argc, char **argv)
int i; int i;
size_t n; size_t n;
char *subfprs_buffer = NULL; char *subfprs_buffer = NULL;
char *adskfpr = NULL;
if (argc) if (argc)
{ argc--; argv++; } { argc--; argv++; }
@ -281,6 +285,7 @@ main (int argc, char **argv)
revuid = 0; revuid = 0;
setpri = 0; setpri = 0;
setexpire = 0; setexpire = 0;
addadsk = 0;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--adduid")) else if (!strcmp (*argv, "--adduid"))
@ -290,6 +295,7 @@ main (int argc, char **argv)
revuid = 0; revuid = 0;
setpri = 0; setpri = 0;
setexpire = 0; setexpire = 0;
addadsk = 0;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--revuid")) else if (!strcmp (*argv, "--revuid"))
@ -299,6 +305,7 @@ main (int argc, char **argv)
revuid = 1; revuid = 1;
setpri = 0; setpri = 0;
setexpire = 0; setexpire = 0;
addadsk = 0;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--set-primary")) else if (!strcmp (*argv, "--set-primary"))
@ -308,6 +315,7 @@ main (int argc, char **argv)
revuid = 0; revuid = 0;
setpri = 1; setpri = 1;
setexpire = 0; setexpire = 0;
addadsk = 0;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--setexpire")) else if (!strcmp (*argv, "--setexpire"))
@ -317,6 +325,17 @@ main (int argc, char **argv)
revuid = 0; revuid = 0;
setpri = 0; setpri = 0;
setexpire = 1; setexpire = 1;
addadsk = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--addadsk"))
{
addkey = 0;
adduid = 0;
revuid = 0;
setpri = 0;
setexpire = 0;
addadsk = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--verbose")) else if (!strcmp (*argv, "--verbose"))
@ -412,6 +431,13 @@ main (int argc, char **argv)
subfprs = NULL; subfprs = NULL;
} }
} }
else if (addadsk)
{
if (argc != 2)
show_usage(1);
userid = argv[0];
adskfpr = argv[1];
}
else else
{ {
if (!argc || argc > 4) if (!argc || argc > 4)
@ -445,7 +471,7 @@ main (int argc, char **argv)
} }
if (addkey || adduid || revuid || setpri || setexpire) if (addkey || adduid || revuid || setpri || setexpire || addadsk)
{ {
gpgme_key_t akey; gpgme_key_t akey;
@ -507,6 +533,17 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
} }
else if (addadsk)
{
err = gpgme_op_createsubkey(ctx, akey, adskfpr, 0, 0,
GPGME_CREATE_ADSK);
if (err)
{
fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
gpg_strerror (err));
exit (1);
}
}
gpgme_key_unref (akey); gpgme_key_unref (akey);
} }
@ -521,7 +558,7 @@ main (int argc, char **argv)
} }
} }
if (!setpri && !setexpire) if (!setpri && !setexpire && !addadsk)
{ {
result = gpgme_op_genkey_result (ctx); result = gpgme_op_genkey_result (ctx);
if (!result) if (!result)