core: Extend decryption result with symkey_algo.
authorWerner Koch <wk@gnupg.org>
Tue, 17 Apr 2018 11:48:56 +0000 (13:48 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 17 Apr 2018 11:48:56 +0000 (13:48 +0200)
* src/gpgme.h.in (gpgme_op_decrypt_result_t): Add field 'symkey_algo'.
* src/decrypt.c (release_op_data): Free SYMKEY_ALGO.
(gpgme_op_decrypt_result): Make sure SYMKEY_ALGO is not NULL.
(parse_decryption_info): New.
(_gpgme_decrypt_status_handler): Parse DECRYPTION_INFO status.
* src/conversion.c (_gpgme_cipher_algo_name): New.
(_gpgme_cipher_mode_name): New.

* tests/run-decrypt.c (print_result): Print SYMKEY_ALGO

* src/util.h (_gpgme_map_gnupg_error): Remove obsolete prototype.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
NEWS
doc/gpgme.texi
src/conversion.c
src/decrypt.c
src/gpgme.h.in
src/util.h
tests/run-decrypt.c

diff --git a/NEWS b/NEWS
index 162212c..92a9673 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ Noteworthy changes in version 1.10.1 (unreleased)
  gpgme_op_encrypt_sign_ext_start  NEW.
  GPGME_ENCRYPT_WANT_ADDRESS       NEW.
  gpgme_import_result_t            EXTENDED: New field 'skipped_v3_keys'.
+ gpgme_decrypt_result_t           EXTENDED: New field 'symkey_algo'.
  cpp: Key::locate                 NEW.
  cpp: Data::toString              NEW.
  cpp: ImportResult::numV3KeysSkipped  NEW.
index f5efec6..5a09ea0 100644 (file)
@@ -5399,6 +5399,13 @@ You must not try to access this member of the struct unless
 or @code{gpgme_get_ctx_flag (ctx, "export-session-key")} returns true
 (non-empty string).
 
+@item char *symkey_algo
+@since{1.11.0}
+
+A string with the symmetric encryption algorithm and mode using the
+format "<algo>.<mode>".  Note that old non-MDC encryption mode of
+OpenPGP is given as "PGPCFB".
+
 @end table
 @end deftp
 
index 5b84f67..4bfd3d3 100644 (file)
@@ -575,3 +575,49 @@ _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
 
   return algo;
 }
+
+
+/* Return a string with a cipher algorithm.  */
+const char *
+_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol)
+{
+  if (protocol == GPGME_PROTOCOL_OPENPGP)
+    {
+      /* The algo is given according to OpenPGP specs.  */
+      switch (algo)
+        {
+        case 1:  return "IDEA";
+        case 2:         return "3DES";
+        case 3:         return "CAST5";
+        case 4:  return "BLOWFISH";
+        case 7:  return "AES";
+        case 8:  return "AES192";
+        case 9:  return "AES256";
+        case 10: return "TWOFISH";
+        case 11: return "CAMELLIA128";
+        case 12: return "CAMELLIA192";
+        case 13: return "CAMELLIA256";
+        }
+    }
+
+  return "Unknown";
+}
+
+
+/* Return a string with the cipher mode.  */
+const char *
+_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol)
+{
+  if (protocol == GPGME_PROTOCOL_OPENPGP)
+    {
+      /* The algo is given according to OpenPGP specs.  */
+      switch (algo)
+        {
+        case 0:  return "CFB";
+        case 1:  return "EAX";
+        case 2:         return "OCB";
+        }
+    }
+
+  return "Unknown";
+}
index 8c2cd4d..e4de6e4 100644 (file)
@@ -69,14 +69,10 @@ release_op_data (void *hook)
   op_data_t opd = (op_data_t) hook;
   gpgme_recipient_t recipient = opd->result.recipients;
 
-  if (opd->result.unsupported_algorithm)
-    free (opd->result.unsupported_algorithm);
-
-  if (opd->result.file_name)
-    free (opd->result.file_name);
-
-  if (opd->result.session_key)
-    free (opd->result.session_key);
+  free (opd->result.unsupported_algorithm);
+  free (opd->result.file_name);
+  free (opd->result.session_key);
+  free (opd->result.symkey_algo);
 
   while (recipient)
     {
@@ -104,6 +100,17 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx)
       return NULL;
     }
 
+  /* Make sure that SYMKEY_ALGO has a value.  */
+  if (!opd->result.symkey_algo)
+    {
+      opd->result.symkey_algo = strdup ("?.?");
+      if (!opd->result.symkey_algo)
+        {
+          TRACE_SUC0 ("result=(null)");
+          return NULL;
+        }
+    }
+
   if (_gpgme_debug_trace ())
     {
       gpgme_recipient_t rcp;
@@ -263,6 +270,49 @@ parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
 }
 
 
+/* Parse the ARGS of a
+ *   DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
+ * status.  Returns 0 on success and updates the OPD.
+ */
+static gpgme_error_t
+parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
+{
+  char *field[3];
+  int nfields;
+  char *args2;
+  int mdc, mode;
+  const char *algostr, *modestr;
+
+  if (!args)
+    return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+  args2 = strdup (args); /* Split modifies the input string. */
+  nfields = _gpgme_split_fields (args2, field, DIM (field));
+  if (nfields < 2)
+    {
+      free (args2);
+      return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required arg missing.  */
+    }
+
+  mdc     = atoi (field[0]);
+  algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
+  mode    = nfields < 3? 0 : atoi (field[2]);
+  modestr = _gpgme_cipher_mode_name (mode, protocol);
+
+  free (args2);
+
+  free (opd->result.symkey_algo);
+  if (!mode && mdc != 2)
+    opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
+  else
+    opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
+  if (!opd->result.symkey_algo)
+    return gpg_error_from_syserror ();
+
+  return 0;
+}
+
+
 gpgme_error_t
 _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
                               char *args)
@@ -303,7 +353,9 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
       break;
 
     case GPGME_STATUS_DECRYPTION_INFO:
-      /* Fixme: Provide a way to return the used symmetric algorithm. */
+      err = parse_decryption_info (args, opd, ctx->protocol);
+      if (err)
+       return err;
       break;
 
     case GPGME_STATUS_DECRYPTION_OKAY:
index 860e093..202859c 100644 (file)
@@ -1368,6 +1368,10 @@ struct _gpgme_op_decrypt_result
   /* A textual representation of the session key used to decrypt the
    * message, if available */
   char *session_key;
+
+   /* A string with the symmetric encryption algorithm and mode using
+    * the format "<algo>.<mode>".  */
+  char *symkey_algo;
 };
 typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t;
 
index b4043ed..da929eb 100644 (file)
@@ -165,10 +165,11 @@ time_t _gpgme_parse_timestamp (const char *timestamp, char **endp);
  * on error or missing timestamp.  */
 unsigned long _gpgme_parse_timestamp_ul (const char *timestamp);
 
-gpgme_error_t _gpgme_map_gnupg_error (char *err);
-
 int _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol);
 
+const char *_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol);
+const char *_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol);
+
 \f
 /*-- b64dec.c --*/
 
index a2e82a0..8eb6ba0 100644 (file)
@@ -59,6 +59,7 @@ print_result (gpgme_decrypt_result_t result)
           nonnull(result->unsupported_algorithm));
   if (result->session_key)
     printf ("Session key: %s\n", result->session_key);
+  printf ("Symmetric algorithm: %s\n", result->symkey_algo);
 
   for (recp = result->recipients; recp && recp->next; recp = recp->next)
     {