From 8103eeba809b6e7156d861783309574b93909169 Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Mon, 20 Aug 2018 16:38:36 +0200 Subject: [PATCH] json: Add subkey_algo and defaults to createkey * src/gpgme-json.c (op_createkey, hlp_createkey): Add subkey_algo handling. (hlp_createkey): Fix documentation of expiry. -- Due to the funny quick-gen-key interface generating a key with an explicit algo would result in bad defaults (only an SC key), without a subkey. This adds handling that should probably be in GnuPG proper to fix the semantics of createkey by adding default subkey_algo handling. --- src/gpgme-json.c | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/src/gpgme-json.c b/src/gpgme-json.c index 5a9b9cf7..99c6652a 100644 --- a/src/gpgme-json.c +++ b/src/gpgme-json.c @@ -2878,8 +2878,15 @@ static const char hlp_createkey[] = "userid: The user id. E.g. \"Foo Bar \"\n" "\n" "Optional parameters:\n" - "algo: Algo of the key as string. See doc for gpg --quick-gen-key.\n" - "expires: Seconds since epoch to expiry as Number. 0 means no expiry.\n" + "algo: Algo of the key as string. See doc for gpg --quick-gen-key.\n" + "subkey-algo: Algo of the encryption subkey. If ommited the same as algo\n" + " is used.\n" + " Except for dsa and ed25519 where the according\n" + " elg / cv25519 algo will be used as subkey-algo.\n" + "\n" + " If algo is omitted or default or future-default subkey-algo\n" + " is ignored.\n" + "expires: Seconds from now to expiry as Number. 0 means no expiry.\n" "\n" "Response on success:\n" "fingerprint: The fingerprint of the created key.\n" @@ -2891,12 +2898,14 @@ op_createkey (cjson_t request, cjson_t result) { gpg_error_t err; gpgme_ctx_t ctx = NULL; - unsigned int flags = 0; + unsigned int flags = GPGME_CREATE_FORCE; /* Always force as the GUI should + handle checks, if required. */ unsigned long expires = 0; cjson_t j_tmp; const char *algo = "default"; const char *userid; gpgme_genkey_result_t res; + char *new_fpr = NULL; #ifdef GPG_AGENT_ALLOWS_KEYGEN_TRHOUGH_BROWSER /* GnuPG forbids keygen through the browser socket so for @@ -2950,9 +2959,58 @@ op_createkey (cjson_t request, cjson_t result) goto leave; } - xjson_AddStringToObject0 (result, "fingerprint", res->fpr); + /* Dup the fpr as the result might become invalid after context reuse. */ + new_fpr = xstrdup (res->fpr); + + if (algo && strcmp ("default", algo) && strcmp ("future-default", algo)) + { + /* We need to add the encryption subkey manually */ + gpgme_ctx_t keylistctx = create_onetime_context (GPGME_PROTOCOL_OpenPGP); + gpgme_key_t new_key = NULL; + char *subkey_algo = NULL; + + j_tmp = cJSON_GetObjectItem (request, "subkey_algo"); + if (j_tmp && cjson_is_string (j_tmp)) + { + subkey_algo = xstrdup (j_tmp->valuestring); + } + + if (!subkey_algo) + { + subkey_algo = strdup (algo); + if (!strncmp ("dsa", subkey_algo, 3)) + { + subkey_algo[0] = 'e'; + subkey_algo[1] = 'l'; + subkey_algo[2] = 'g'; + } + if (!strcmp ("ed25519", subkey_algo)) + { + strcpy (subkey_algo, "cv25519"); + } + } + + err = gpgme_get_key (keylistctx, new_fpr, &new_key, 1); + release_onetime_context (keylistctx); + if (err) + { + gpg_error_object (result, err, "Error finding created key: %s", + gpg_strerror (err)); + xfree (subkey_algo); + goto leave; + } + + err = gpgme_op_createsubkey (ctx, new_key, subkey_algo, + 0, expires, flags |= GPGME_CREATE_ENCR); + xfree (subkey_algo); + if (err) + goto leave; + } + + xjson_AddStringToObject0 (result, "fingerprint", new_fpr); leave: + xfree (new_fpr); #ifdef GPG_AGENT_ALLOWS_KEYGEN_TRHOUGH_BROWSER release_context (ctx); #else