mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
gpg: Report compliance with CO_DE_VS.
* common/compliance.c (gnupg_pk_is_compliant): Add DSA with certain parameters. (gnupg_cipher_is_compliant): New function. (gnupg_digest_is_compliant): Likewise. * common/compliance.h (gnupg_cipher_is_compliant): New prototype. (gnupg_digest_is_compliant): Likewise. * common/status.h (STATUS_DECRYPTION_COMPLIANCE_MODE): New status. (STATUS_VERIFICATION_COMPLIANCE_MODE): Likewise. * doc/DETAILS: Document the new status lines. * g10/mainproc.c (proc_encrypted): Compute compliance with CO_DE_VS and report that using the new status line. (check_sig_and_print): Likewise. * sm/decrypt.c (gpgsm_decrypt): Likewise. * sm/verify.c (gpgsm_verify): Likewise. -- When decrypting data and verifying signatures, report whether the operations are in compliance with the criteria for data classified as VS-NfD. This information will be picked up by the frontend and presented to the user. GnuPG-bug-id: 3059 Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
3b70f62423
commit
be8ca88526
@ -45,8 +45,8 @@ int
|
|||||||
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
||||||
gcry_mpi_t key[], unsigned int keylength, const char *curvename)
|
gcry_mpi_t key[], unsigned int keylength, const char *curvename)
|
||||||
{
|
{
|
||||||
enum { is_rsa, is_pgp5, is_elg_sign, is_ecc } algotype;
|
enum { is_rsa, is_dsa, is_pgp5, is_elg_sign, is_ecc } algotype;
|
||||||
int result;
|
int result = 0;
|
||||||
|
|
||||||
switch (algo)
|
switch (algo)
|
||||||
{
|
{
|
||||||
@ -56,8 +56,11 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||||||
algotype = is_rsa;
|
algotype = is_rsa;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUBKEY_ALGO_ELGAMAL_E:
|
|
||||||
case PUBKEY_ALGO_DSA:
|
case PUBKEY_ALGO_DSA:
|
||||||
|
algotype = is_dsa;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PUBKEY_ALGO_ELGAMAL_E:
|
||||||
algotype = is_pgp5;
|
algotype = is_pgp5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -91,6 +94,16 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||||||
|| keylength == 4096);
|
|| keylength == 4096);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case is_dsa:
|
||||||
|
if (key)
|
||||||
|
{
|
||||||
|
size_t L = gcry_mpi_get_nbits (key[0] /* p */);
|
||||||
|
size_t N = gcry_mpi_get_nbits (key[1] /* q */);
|
||||||
|
result = (L == 256
|
||||||
|
&& (N == 2048 || N == 3072));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case is_ecc:
|
case is_ecc:
|
||||||
if (!curvename && key)
|
if (!curvename && key)
|
||||||
{
|
{
|
||||||
@ -126,6 +139,59 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if CIPHER is compliant to the give COMPLIANCE mode. */
|
||||||
|
int
|
||||||
|
gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance, cipher_algo_t cipher)
|
||||||
|
{
|
||||||
|
switch (compliance)
|
||||||
|
{
|
||||||
|
case CO_DE_VS:
|
||||||
|
switch (cipher)
|
||||||
|
{
|
||||||
|
case CIPHER_ALGO_AES:
|
||||||
|
case CIPHER_ALGO_AES192:
|
||||||
|
case CIPHER_ALGO_AES256:
|
||||||
|
case CIPHER_ALGO_3DES:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
log_assert (!"reached");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_assert (!"reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if DIGEST is compliant to the give COMPLIANCE mode. */
|
||||||
|
int
|
||||||
|
gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance, digest_algo_t digest)
|
||||||
|
{
|
||||||
|
switch (compliance)
|
||||||
|
{
|
||||||
|
case CO_DE_VS:
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case DIGEST_ALGO_SHA256:
|
||||||
|
case DIGEST_ALGO_SHA384:
|
||||||
|
case DIGEST_ALGO_SHA512:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
log_assert (!"reached");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_assert (!"reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
|
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,10 @@ enum gnupg_compliance_mode
|
|||||||
int gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
int gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
|
||||||
gcry_mpi_t key[], unsigned int keylength,
|
gcry_mpi_t key[], unsigned int keylength,
|
||||||
const char *curvename);
|
const char *curvename);
|
||||||
|
int gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance,
|
||||||
|
cipher_algo_t cipher);
|
||||||
|
int gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
|
||||||
|
digest_algo_t digest);
|
||||||
const char *gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance);
|
const char *gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance);
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_COMPLIANCE_H*/
|
#endif /*GNUPG_COMMON_COMPLIANCE_H*/
|
||||||
|
@ -141,6 +141,9 @@ enum
|
|||||||
STATUS_TOFU_STATS_SHORT,
|
STATUS_TOFU_STATS_SHORT,
|
||||||
STATUS_TOFU_STATS_LONG,
|
STATUS_TOFU_STATS_LONG,
|
||||||
|
|
||||||
|
STATUS_DECRYPTION_COMPLIANCE_MODE,
|
||||||
|
STATUS_VERIFICATION_COMPLIANCE_MODE,
|
||||||
|
|
||||||
STATUS_TRUNCATED,
|
STATUS_TRUNCATED,
|
||||||
STATUS_MOUNTPOINT,
|
STATUS_MOUNTPOINT,
|
||||||
STATUS_BLOCKDEV,
|
STATUS_BLOCKDEV,
|
||||||
|
11
doc/DETAILS
11
doc/DETAILS
@ -638,6 +638,17 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||||||
This indicates that a signature subpacket was seen. The format is
|
This indicates that a signature subpacket was seen. The format is
|
||||||
the same as the "spk" record above.
|
the same as the "spk" record above.
|
||||||
|
|
||||||
|
*** DECRYPTION_COMPLIANCE_MODE <flags>
|
||||||
|
Indicates that the current decryption operation is in compliance
|
||||||
|
with the given set of modes. "flags" is a space separated list of
|
||||||
|
numerical flags, see "Field 18 - Compliance flags" above.
|
||||||
|
|
||||||
|
*** VERIFICATION_COMPLIANCE_MODE <flags>
|
||||||
|
Indicates that the current signature verification operation is in
|
||||||
|
compliance with the given set of modes. "flags" is a space
|
||||||
|
separated list of numerical flags, see "Field 18 - Compliance
|
||||||
|
flags" above.
|
||||||
|
|
||||||
** Key related
|
** Key related
|
||||||
*** INV_RECP, INV_SGNR
|
*** INV_RECP, INV_SGNR
|
||||||
The two similar status codes:
|
The two similar status codes:
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "photoid.h"
|
#include "photoid.h"
|
||||||
#include "../common/mbox-util.h"
|
#include "../common/mbox-util.h"
|
||||||
#include "call-dirmngr.h"
|
#include "call-dirmngr.h"
|
||||||
|
#include "../common/compliance.h"
|
||||||
|
|
||||||
/* Put an upper limit on nested packets. The 32 is an arbitrary
|
/* Put an upper limit on nested packets. The 32 is an arbitrary
|
||||||
value, a much lower should actually be sufficient. */
|
value, a much lower should actually be sufficient. */
|
||||||
@ -599,6 +600,44 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
else if (!c->dek)
|
else if (!c->dek)
|
||||||
result = GPG_ERR_NO_SECKEY;
|
result = GPG_ERR_NO_SECKEY;
|
||||||
|
|
||||||
|
/* Compute compliance with CO_DE_VS. */
|
||||||
|
if (!result && is_status_enabled ()
|
||||||
|
/* Symmetric encryption voids compliance. */
|
||||||
|
&& c->symkeys == 0
|
||||||
|
/* Overriding session key voids compliance. */
|
||||||
|
&& opt.override_session_key == NULL
|
||||||
|
/* Check symmetric cipher. */
|
||||||
|
&& gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo))
|
||||||
|
{
|
||||||
|
struct kidlist_item *i;
|
||||||
|
int compliant = 1;
|
||||||
|
PKT_public_key *pk = xmalloc (sizeof *pk);
|
||||||
|
|
||||||
|
log_assert (c->pkenc_list || !"where else did the session key come from!?");
|
||||||
|
|
||||||
|
/* Now check that every key used to encrypt the session key is
|
||||||
|
* compliant. */
|
||||||
|
for (i = c->pkenc_list; i && compliant; i = i->next)
|
||||||
|
{
|
||||||
|
memset (pk, 0, sizeof *pk);
|
||||||
|
pk->pubkey_algo = i->pubkey_algo;
|
||||||
|
if (get_pubkey (c->ctrl, pk, i->kid) != 0
|
||||||
|
|| ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
|
||||||
|
nbits_from_pk (pk), NULL))
|
||||||
|
compliant = 0;
|
||||||
|
release_public_key_parts (pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree (pk);
|
||||||
|
|
||||||
|
if (compliant)
|
||||||
|
write_status_strings (STATUS_DECRYPTION_COMPLIANCE_MODE,
|
||||||
|
gnupg_status_compliance_flag (CO_DE_VS),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
|
result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
|
||||||
|
|
||||||
@ -2196,6 +2235,15 @@ check_sig_and_print (CTX c, kbnode_t node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute compliance with CO_DE_VS. */
|
||||||
|
if (pk && is_status_enabled ()
|
||||||
|
&& gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
|
||||||
|
nbits_from_pk (pk), NULL)
|
||||||
|
&& gnupg_digest_is_compliant (CO_DE_VS, sig->digest_algo))
|
||||||
|
write_status_strings (STATUS_VERIFICATION_COMPLIANCE_MODE,
|
||||||
|
gnupg_status_compliance_flag (CO_DE_VS),
|
||||||
|
NULL);
|
||||||
|
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
release_kbnode( keyblock );
|
release_kbnode( keyblock );
|
||||||
|
25
sm/decrypt.c
25
sm/decrypt.c
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "../common/compliance.h"
|
||||||
|
|
||||||
struct decrypt_filter_parm_s
|
struct decrypt_filter_parm_s
|
||||||
{
|
{
|
||||||
@ -325,6 +326,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
int algo, mode;
|
int algo, mode;
|
||||||
const char *algoid;
|
const char *algoid;
|
||||||
int any_key = 0;
|
int any_key = 0;
|
||||||
|
int is_de_vs; /* Computed compliance with CO_DE_VS. */
|
||||||
|
|
||||||
audit_log (ctrl->audit, AUDIT_GOT_DATA);
|
audit_log (ctrl->audit, AUDIT_GOT_DATA);
|
||||||
|
|
||||||
@ -356,6 +358,10 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For CMS, CO_DE_VS demands CBC mode. */
|
||||||
|
is_de_vs = (mode == GCRY_CIPHER_MODE_CBC
|
||||||
|
&& gnupg_cipher_is_compliant (CO_DE_VS, algo));
|
||||||
|
|
||||||
audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
|
audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
|
||||||
dfparm.algo = algo;
|
dfparm.algo = algo;
|
||||||
dfparm.mode = mode;
|
dfparm.mode = mode;
|
||||||
@ -460,7 +466,21 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
|
||||||
desc = gpgsm_format_keydesc (cert);
|
desc = gpgsm_format_keydesc (cert);
|
||||||
|
|
||||||
|
/* Check that all certs are compliant with CO_DE_VS. */
|
||||||
|
if (is_de_vs)
|
||||||
|
{
|
||||||
|
unsigned int nbits;
|
||||||
|
int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
|
||||||
|
|
||||||
|
is_de_vs = gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL,
|
||||||
|
nbits, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
|
if (rc)
|
||||||
|
/* We cannot check compliance of certs that we
|
||||||
|
* don't have. */
|
||||||
|
is_de_vs = 0;
|
||||||
xfree (issuer);
|
xfree (issuer);
|
||||||
xfree (serial);
|
xfree (serial);
|
||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
@ -489,6 +509,11 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
|
|||||||
ksba_writer_set_filter (writer,
|
ksba_writer_set_filter (writer,
|
||||||
decrypt_filter,
|
decrypt_filter,
|
||||||
&dfparm);
|
&dfparm);
|
||||||
|
|
||||||
|
if (is_de_vs)
|
||||||
|
gpgsm_status (ctrl, STATUS_DECRYPTION_COMPLIANCE_MODE,
|
||||||
|
gnupg_status_compliance_flag (CO_DE_VS));
|
||||||
|
|
||||||
}
|
}
|
||||||
audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
|
audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
|
||||||
}
|
}
|
||||||
|
11
sm/verify.c
11
sm/verify.c
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "../common/compliance.h"
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
strtimestamp_r (ksba_isotime_t atime)
|
strtimestamp_r (ksba_isotime_t atime)
|
||||||
@ -631,6 +632,16 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
|
|||||||
(verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
|
(verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
|
||||||
"0 chain": "0 shell");
|
"0 chain": "0 shell");
|
||||||
|
|
||||||
|
/* Check compliance with CO_DE_VS. */
|
||||||
|
{
|
||||||
|
unsigned int nbits;
|
||||||
|
int pk_algo = gpgsm_get_key_algo_info (cert, &nbits);
|
||||||
|
|
||||||
|
if (gnupg_pk_is_compliant (CO_DE_VS, pk_algo, NULL, nbits, NULL)
|
||||||
|
&& gnupg_digest_is_compliant (CO_DE_VS, sigval_hash_algo))
|
||||||
|
gpgsm_status (ctrl, STATUS_VERIFICATION_COMPLIANCE_MODE,
|
||||||
|
gnupg_status_compliance_flag (CO_DE_VS));
|
||||||
|
}
|
||||||
|
|
||||||
next_signer:
|
next_signer:
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user