core: Always fail if an OpenPG message is not integrity protected.
* src/decrypt.c (struct op_data_t): Add field not_integrity_protected. (parse_decryption_info): Set this. Also rename mode to aead_algo for clarity. (_gpgme_decrypt_status_handler): Force failure in case of a missing MDC. -- This extra check makes sure that a missing or stripped MDC in - gpg < 2.1 - or gpg 2.2 with an old cipher algorithm will lead to a decryption failure. gpg 2.3 will always fail in this case. Implementing this check here and not backporting the 2.3 change to 2.2 has the benefit that all GPGME using applications are protected but scripts relying on rfc2440 (i.e. without MDC) will only break when migrating to 2.3. Note that S/MIME has no integrity protection mechanism but gpgsm neither emits a DECRYPTION_INFO status line, so an error will not be triggered. If in the future gpgsm supports authenticated encryption it may issue a DECRYPTION_INFO line to force a failure here but it will in that case also emit a DECRYPTION_FAILED anyway. GnuPG-bug-id: 3981 Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
e54b110aec
commit
8a0c8c5251
3
NEWS
3
NEWS
@ -1,6 +1,9 @@
|
|||||||
Noteworthy changes in version 1.11.2 (unreleased)
|
Noteworthy changes in version 1.11.2 (unreleased)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
|
* Even for old versions of gpg a missing MDC will now lead to a
|
||||||
|
decryption failure.
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.11.1 (2018-04-20)
|
Noteworthy changes in version 1.11.1 (2018-04-20)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
@ -5408,7 +5408,7 @@ or @code{gpgme_get_ctx_flag (ctx, "export-session-key")} returns true
|
|||||||
@since{1.11.0}
|
@since{1.11.0}
|
||||||
|
|
||||||
A string with the symmetric encryption algorithm and mode using the
|
A string with the symmetric encryption algorithm and mode using the
|
||||||
format "<algo>.<mode>". Note that old non-MDC encryption mode of
|
format "<algo>.<mode>". Note that the deprecated non-MDC encryption mode of
|
||||||
OpenPGP is given as "PGPCFB".
|
OpenPGP is given as "PGPCFB".
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
@ -56,6 +56,11 @@ typedef struct
|
|||||||
* message that the general DECRYPTION_FAILED. */
|
* message that the general DECRYPTION_FAILED. */
|
||||||
int any_no_seckey;
|
int any_no_seckey;
|
||||||
|
|
||||||
|
/* If the engine emits a DECRYPTION_INFO status and that does not
|
||||||
|
* indicate that an integrity proetction mode is active, this flag
|
||||||
|
* is set. */
|
||||||
|
int not_integrity_protected;
|
||||||
|
|
||||||
/* A pointer to the next pointer of the last recipient in the list.
|
/* A pointer to the next pointer of the last recipient in the list.
|
||||||
This makes appending new invalid signers painless while
|
This makes appending new invalid signers painless while
|
||||||
preserving the order. */
|
preserving the order. */
|
||||||
@ -280,7 +285,7 @@ parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
|
|||||||
char *field[3];
|
char *field[3];
|
||||||
int nfields;
|
int nfields;
|
||||||
char *args2;
|
char *args2;
|
||||||
int mdc, mode;
|
int mdc, aead_algo;
|
||||||
const char *algostr, *modestr;
|
const char *algostr, *modestr;
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
@ -296,19 +301,22 @@ parse_decryption_info (char *args, op_data_t opd, gpgme_protocol_t protocol)
|
|||||||
|
|
||||||
mdc = atoi (field[0]);
|
mdc = atoi (field[0]);
|
||||||
algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
|
algostr = _gpgme_cipher_algo_name (atoi (field[1]), protocol);
|
||||||
mode = nfields < 3? 0 : atoi (field[2]);
|
aead_algo = nfields < 3? 0 : atoi (field[2]);
|
||||||
modestr = _gpgme_cipher_mode_name (mode, protocol);
|
modestr = _gpgme_cipher_mode_name (aead_algo, protocol);
|
||||||
|
|
||||||
free (args2);
|
free (args2);
|
||||||
|
|
||||||
free (opd->result.symkey_algo);
|
free (opd->result.symkey_algo);
|
||||||
if (!mode && mdc != 2)
|
if (!aead_algo && mdc != 2)
|
||||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
|
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".PGPCFB", NULL);
|
||||||
else
|
else
|
||||||
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
|
opd->result.symkey_algo = _gpgme_strconcat (algostr, ".", modestr, NULL);
|
||||||
if (!opd->result.symkey_algo)
|
if (!opd->result.symkey_algo)
|
||||||
return gpg_error_from_syserror ();
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
if (!mdc && !aead_algo)
|
||||||
|
opd->not_integrity_protected = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,13 +346,18 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GPGME_STATUS_EOF:
|
case GPGME_STATUS_EOF:
|
||||||
/* FIXME: These error values should probably be attributed to
|
/* We force an encryption failure if we know that integrity
|
||||||
the underlying crypto engine (as error source). */
|
* protection is missing. For modern version of gpg using
|
||||||
|
* modern cipher algorithms this is not required because gpg
|
||||||
|
* will issue a failure anyway. However older gpg versions emit
|
||||||
|
* only a warning.
|
||||||
|
* Fixme: These error values should probably be attributed to
|
||||||
|
* the underlying crypto engine (as error source). */
|
||||||
if (opd->failed && opd->pkdecrypt_failed)
|
if (opd->failed && opd->pkdecrypt_failed)
|
||||||
return opd->pkdecrypt_failed;
|
return opd->pkdecrypt_failed;
|
||||||
else if (opd->failed && opd->any_no_seckey)
|
else if (opd->failed && opd->any_no_seckey)
|
||||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
return gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
else if (opd->failed)
|
else if (opd->failed || opd->not_integrity_protected)
|
||||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||||
else if (!opd->okay)
|
else if (!opd->okay)
|
||||||
return gpg_error (GPG_ERR_NO_DATA);
|
return gpg_error (GPG_ERR_NO_DATA);
|
||||||
|
Loading…
Reference in New Issue
Block a user