aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/gpgme.texi9
-rw-r--r--lang/cpp/src/context.cpp10
-rw-r--r--lang/cpp/src/context.h3
-rw-r--r--lang/qt/src/qgpgmequickjob.cpp11
-rw-r--r--lang/qt/src/qgpgmequickjob.h1
-rw-r--r--lang/qt/src/quickjob.h3
-rw-r--r--src/engine-gpg.c33
-rw-r--r--src/genkey.c8
-rw-r--r--src/gpgme.h.in1
-rw-r--r--tests/run-genkey.c41
10 files changed, 116 insertions, 4 deletions
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index aaa2ab3f..48cca032 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -4390,6 +4390,11 @@ override this check.
Request generation of keys that do not expire.
+@item GPGME_CREATE_ADSK
+@since{1.24.0}
+
+Add an ADSK to the key.
+
@end table
After the operation completed successfully, information about the
@@ -4465,6 +4470,10 @@ values for timestamps and thus can only encode dates up to the year
@var{flags} takes the same values as described above for
@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
created key can be retrieved with @code{gpgme_op_genkey_result}.
diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp
index 7d04e9cc..57f92394 100644
--- a/lang/cpp/src/context.cpp
+++ b/lang/cpp/src/context.cpp
@@ -1799,6 +1799,16 @@ Error Context::startRevokeSignature(const Key &key, const Key &signingKey,
key.impl(), signingKey.impl(), uids.c_str(), flags));
}
+Error Context::addAdsk(const Key &k, const char *adsk)
+{
+ return Error(d->lasterr = gpgme_op_createsubkey(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
+}
+
+Error Context::startAddAdsk(const Key &k, const char *adsk)
+{
+ return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
+}
+
Error Context::setFlag(const char *name, const char *value)
{
return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h
index 4d7fedf0..c4f968f4 100644
--- a/lang/cpp/src/context.h
+++ b/lang/cpp/src/context.h
@@ -324,6 +324,9 @@ public:
Error startRevokeSignature(const Key &key, const Key &signingKey,
const std::vector<UserID> &userIds = std::vector<UserID>());
+ Error addAdsk(const Key &k, const char *adsk);
+ Error startAddAdsk(const Key &k, const char *adsk);
+
// using TofuInfo::Policy
Error setTofuPolicy(const Key &k, unsigned int policy);
Error setTofuPolicyStart(const Key &k, unsigned int policy);
diff --git a/lang/qt/src/qgpgmequickjob.cpp b/lang/qt/src/qgpgmequickjob.cpp
index 33f1178a..1c6023a4 100644
--- a/lang/qt/src/qgpgmequickjob.cpp
+++ b/lang/qt/src/qgpgmequickjob.cpp
@@ -109,6 +109,12 @@ static QGpgMEQuickJob::result_type revokeSignatureWorker(Context *ctx,
return std::make_tuple(err, QString(), Error());
}
+static QGpgMEQuickJob::result_type addAdskWorker(Context *ctx, const Key &key, const char *adsk)
+{
+ const auto err = ctx->addAdsk(key, adsk);
+ return std::make_tuple(err, QString(), Error());
+}
+
void QGpgMEQuickJob::startCreate(const QString &uid,
const char *algo,
const QDateTime &expires,
@@ -142,4 +148,9 @@ void QGpgMEQuickJob::startRevokeSignature(const Key &key, const Key &signingKey,
run(std::bind(&revokeSignatureWorker, std::placeholders::_1, key, signingKey, userIds));
}
+void QGpgMEQuickJob::startAddAdsk(const GpgME::Key &key, const char *adsk)
+{
+ run(std::bind(&addAdskWorker, std::placeholders::_1, key, adsk));
+}
+
#include "qgpgmequickjob.moc"
diff --git a/lang/qt/src/qgpgmequickjob.h b/lang/qt/src/qgpgmequickjob.h
index 2f59d8d4..07b89e18 100644
--- a/lang/qt/src/qgpgmequickjob.h
+++ b/lang/qt/src/qgpgmequickjob.h
@@ -71,6 +71,7 @@ public:
unsigned int flags = 0) override;
void startRevokeSignature(const GpgME::Key &key, const GpgME::Key &signingKey,
const std::vector<GpgME::UserID> &userIds = std::vector<GpgME::UserID>()) override;
+ void startAddAdsk(const GpgME::Key &key, const char *adsk) override;
};
}
diff --git a/lang/qt/src/quickjob.h b/lang/qt/src/quickjob.h
index 612a53d0..2d159bbe 100644
--- a/lang/qt/src/quickjob.h
+++ b/lang/qt/src/quickjob.h
@@ -85,6 +85,9 @@ public:
virtual void startRevokeSignature(const GpgME::Key &key, const GpgME::Key &signingKey,
const std::vector<GpgME::UserID> &userIds = std::vector<GpgME::UserID>()) = 0;
+ /** Start --quick-add-adsk */
+ virtual void startAddAdsk(const GpgME::Key &key, const char *adsk) = 0;
+
Q_SIGNALS:
void result(const GpgME::Error &error,
const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index d5b2ab71..e212f1f8 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -2856,6 +2856,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
gpg_genkey (void *engine,
const char *userid, const char *algo,
unsigned long reserved, unsigned long expires,
@@ -2878,6 +2905,8 @@ gpg_genkey (void *engine,
* !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).
* or set a flag on a user id.
+ * !USERID && KEY && ALGO
+ * && GPGME_CREATE_ADSK - Add ALGO as an ADSK to KEY.
*/
if (help_data)
{
@@ -2894,10 +2923,12 @@ gpg_genkey (void *engine,
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else if (userid && !key)
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);
else if (userid && key && !algo)
err = gpg_adduid (gpg, key, userid, extraflags);
+ else if (!userid && key && algo && (flags & GPGME_CREATE_ADSK))
+ err = gpg_addadsk (gpg, key, algo);
else
err = gpg_error (GPG_ERR_INV_VALUE);
diff --git a/src/genkey.c b/src/genkey.c
index 89e1d985..11ca5cbe 100644
--- a/src/genkey.c
+++ b/src/genkey.c
@@ -48,6 +48,9 @@ typedef struct
/* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter;
+
+ /* Flag to indicate that an ADSK is to be added. */
+ unsigned int adskmode : 1;
} *op_data_t;
@@ -180,7 +183,7 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
case GPGME_STATUS_EOF:
if (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);
else if (opd->failure_code)
return opd->failure_code;
@@ -445,6 +448,9 @@ createsubkey_start (gpgme_ctx_t ctx, int synchronous,
return err;
}
+ if (flags & GPGME_CREATE_ADSK)
+ opd->adskmode = 1;
+
return _gpgme_engine_op_genkey (ctx->engine,
NULL, algo, reserved, expires,
key, flags,
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index eaeb22aa..0ee3e088 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1866,6 +1866,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_FORCE (1 << 12) /* Force creation. */
#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.
diff --git a/tests/run-genkey.c b/tests/run-genkey.c
index 8572db26..56404dd3 100644
--- a/tests/run-genkey.c
+++ b/tests/run-genkey.c
@@ -215,6 +215,7 @@ show_usage (int ex)
" for revuid: FPR USERID\n"
" for setexpire: FPR EXPIRE [SUBFPRS]\n"
" for set-primary: FPR USERID\n"
+ " for addadsk: FPR ADSKFPR\n"
"Options:\n"
" --addkey add a subkey 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"
" --setexpire set the expiration time of the key FPR\n"
" or of its subkeys SUBFPRS\n"
+ " --addadsk add the subkey with ADSKFPR to the key FPR\n"
" --verbose run in verbose mode\n"
" --status print status lines from the backend\n"
" --progress print progress info\n"
@@ -250,6 +252,7 @@ main (int argc, char **argv)
int revuid = 0;
int setpri = 0;
int setexpire = 0;
+ int addadsk = 0;
const char *userid;
const char *algo = NULL;
const char *newuserid = NULL;
@@ -260,6 +263,7 @@ main (int argc, char **argv)
int i;
size_t n;
char *subfprs_buffer = NULL;
+ char *adskfpr = NULL;
if (argc)
{ argc--; argv++; }
@@ -281,6 +285,7 @@ main (int argc, char **argv)
revuid = 0;
setpri = 0;
setexpire = 0;
+ addadsk = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--adduid"))
@@ -290,6 +295,7 @@ main (int argc, char **argv)
revuid = 0;
setpri = 0;
setexpire = 0;
+ addadsk = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--revuid"))
@@ -299,6 +305,7 @@ main (int argc, char **argv)
revuid = 1;
setpri = 0;
setexpire = 0;
+ addadsk = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--set-primary"))
@@ -308,6 +315,7 @@ main (int argc, char **argv)
revuid = 0;
setpri = 1;
setexpire = 0;
+ addadsk = 0;
argc--; argv++;
}
else if (!strcmp (*argv, "--setexpire"))
@@ -317,6 +325,17 @@ main (int argc, char **argv)
revuid = 0;
setpri = 0;
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++;
}
else if (!strcmp (*argv, "--verbose"))
@@ -412,6 +431,13 @@ main (int argc, char **argv)
subfprs = NULL;
}
}
+ else if (addadsk)
+ {
+ if (argc != 2)
+ show_usage(1);
+ userid = argv[0];
+ adskfpr = argv[1];
+ }
else
{
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;
@@ -507,6 +533,17 @@ main (int argc, char **argv)
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);
}
@@ -521,7 +558,7 @@ main (int argc, char **argv)
}
}
- if (!setpri && !setexpire)
+ if (!setpri && !setexpire && !addadsk)
{
result = gpgme_op_genkey_result (ctx);
if (!result)