mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-24 15:17:02 +01:00
g10: Change the order of handling private key for encryption.
* g10/packet.h (struct pubkey_enc_list): New. * g10/gpgv.c (get_session_key): Supply struct pubkey_enc_list. * g10/test-stubs.c (get_session_key): Likewise. * g10/mainproc.c (struct kidlist_item): Remove. (release_list): Use struct pubkey_enc_list. (proc_pubkey_enc, print_pkenc_list): Likewise. (proc_encrypted): Don't loop for pkenc_list, but just supply the list to get_session_key. * g10/pubkey-enc.c (get_session_key): Loop for secret key available, and check pkenc_list for each secret key. -- Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
2d6f17c776
commit
fed3e10121
@ -490,7 +490,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
* No encryption here but mainproc links to these functions.
|
||||
*/
|
||||
gpg_error_t
|
||||
get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
|
||||
get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)k;
|
||||
|
@ -46,16 +46,6 @@
|
||||
#define MAX_NESTING_DEPTH 32
|
||||
|
||||
|
||||
/* An object to build a list of keyid related info. */
|
||||
struct kidlist_item
|
||||
{
|
||||
struct kidlist_item *next;
|
||||
u32 kid[2];
|
||||
int pubkey_algo;
|
||||
gcry_mpi_t data[2];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Object to hold the processing context.
|
||||
*/
|
||||
@ -95,7 +85,7 @@ struct mainproc_context
|
||||
iobuf_t iobuf; /* Used to get the filename etc. */
|
||||
int trustletter; /* Temporary usage in list_node. */
|
||||
ulong symkeys; /* Number of symmetrically encrypted session keys. */
|
||||
struct kidlist_item *pkenc_list; /* List of encryption packets. */
|
||||
struct pubkey_enc_list *pkenc_list; /* List of encryption packets. */
|
||||
struct {
|
||||
unsigned int sig_seen:1; /* Set to true if a signature packet
|
||||
has been seen. */
|
||||
@ -135,7 +125,7 @@ release_list( CTX c )
|
||||
release_kbnode (c->list);
|
||||
while (c->pkenc_list)
|
||||
{
|
||||
struct kidlist_item *tmp = c->pkenc_list->next;
|
||||
struct pubkey_enc_list *tmp = c->pkenc_list->next;
|
||||
|
||||
mpi_release (c->pkenc_list->data[0]);
|
||||
mpi_release (c->pkenc_list->data[1]);
|
||||
@ -464,7 +454,7 @@ static void
|
||||
proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
||||
{
|
||||
PKT_pubkey_enc *enc;
|
||||
struct kidlist_item *x = xmalloc (sizeof *x);
|
||||
struct pubkey_enc_list *x = xmalloc (sizeof *x);
|
||||
|
||||
/* Check whether the secret key is available and store in this case. */
|
||||
c->last_was_session_key = 1;
|
||||
@ -485,8 +475,8 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
||||
|
||||
if (!opt.list_only && !opt.override_session_key)
|
||||
{
|
||||
x->kid[0] = enc->keyid[0];
|
||||
x->kid[1] = enc->keyid[1];
|
||||
x->keyid[0] = enc->keyid[0];
|
||||
x->keyid[1] = enc->keyid[1];
|
||||
x->pubkey_algo = enc->pubkey_algo;
|
||||
x->data[0] = x->data[1] = NULL;
|
||||
if (enc->data[0])
|
||||
@ -507,7 +497,7 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
||||
* not decrypt.
|
||||
*/
|
||||
static void
|
||||
print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
|
||||
print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
|
||||
{
|
||||
for (; list; list = list->next)
|
||||
{
|
||||
@ -520,19 +510,19 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
|
||||
if (!algstr)
|
||||
algstr = "[?]";
|
||||
pk->pubkey_algo = list->pubkey_algo;
|
||||
if (!get_pubkey (ctrl, pk, list->kid))
|
||||
if (!get_pubkey (ctrl, pk, list->keyid))
|
||||
{
|
||||
char *p;
|
||||
log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
|
||||
nbits_from_pk (pk), algstr, keystr_from_pk(pk),
|
||||
strtimestamp (pk->timestamp));
|
||||
p = get_user_id_native (ctrl, list->kid);
|
||||
p = get_user_id_native (ctrl, list->keyid);
|
||||
log_printf (_(" \"%s\"\n"), p);
|
||||
xfree (p);
|
||||
}
|
||||
else
|
||||
log_info (_("encrypted with %s key, ID %s\n"),
|
||||
algstr, keystr(list->kid));
|
||||
algstr, keystr(list->keyid));
|
||||
|
||||
free_public_key (pk);
|
||||
}
|
||||
@ -542,7 +532,6 @@ print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list)
|
||||
static void
|
||||
proc_encrypted (CTX c, PACKET *pkt)
|
||||
{
|
||||
struct kidlist_item *item;
|
||||
int result = 0;
|
||||
|
||||
if (!opt.quiet)
|
||||
@ -555,7 +544,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
||||
}
|
||||
|
||||
/* Figure out the session key by looking at all pkenc packets. */
|
||||
if (opt.list_only)
|
||||
if (opt.list_only || c->dek)
|
||||
;
|
||||
else if (opt.override_session_key)
|
||||
{
|
||||
@ -572,53 +561,16 @@ proc_encrypted (CTX c, PACKET *pkt)
|
||||
}
|
||||
else
|
||||
{
|
||||
for (item = c->pkenc_list; item; item = item->next)
|
||||
if (item->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
|
||||
|| item->pubkey_algo == PUBKEY_ALGO_ECDH
|
||||
|| item->pubkey_algo == PUBKEY_ALGO_RSA
|
||||
|| item->pubkey_algo == PUBKEY_ALGO_RSA_E
|
||||
|| item->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
|
||||
{
|
||||
if (((!item->kid[0] && !item->kid[1])
|
||||
|| opt.try_all_secrets
|
||||
|| have_secret_key_with_kid (item->kid)))
|
||||
{
|
||||
PKT_pubkey_enc enc;
|
||||
|
||||
enc.keyid[0] = item->kid[0];
|
||||
enc.keyid[1] = item->kid[1];
|
||||
enc.pubkey_algo = item->pubkey_algo;
|
||||
enc.data[0] = item->data[0];
|
||||
enc.data[1] = item->data[1];
|
||||
|
||||
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
||||
if (!(result = get_session_key (c->ctrl, &enc, c->dek)))
|
||||
break;
|
||||
|
||||
log_info (_("public key decryption failed: %s\n"),
|
||||
gpg_strerror (result));
|
||||
write_status_error ("pkdecrypt_failed", result);
|
||||
|
||||
/* Error: Delete the DEK. */
|
||||
xfree (c->dek);
|
||||
c->dek = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_status_enabled ())
|
||||
{
|
||||
char buf[20];
|
||||
snprintf (buf, sizeof buf, "%08lX%08lX",
|
||||
(ulong)item->kid[0], (ulong)item->kid[1]);
|
||||
write_status_text (STATUS_NO_SECKEY, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
||||
if ((result = get_session_key (c->ctrl, c->pkenc_list, c->dek)))
|
||||
{
|
||||
log_info (_("public key decryption failed: %s\n"),
|
||||
gpg_strerror (GPG_ERR_PUBKEY_ALGO));
|
||||
write_status_error ("pkdecrypt_failed", GPG_ERR_PUBKEY_ALGO);
|
||||
gpg_strerror (result));
|
||||
write_status_error ("pkdecrypt_failed", result);
|
||||
|
||||
/* Error: Delete the DEK. */
|
||||
xfree (c->dek);
|
||||
c->dek = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,7 +650,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
||||
&& gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo,
|
||||
GCRY_CIPHER_MODE_CFB))
|
||||
{
|
||||
struct kidlist_item *i;
|
||||
struct pubkey_enc_list *i;
|
||||
int compliant = 1;
|
||||
PKT_public_key *pk = xmalloc (sizeof *pk);
|
||||
|
||||
@ -711,7 +663,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
||||
{
|
||||
memset (pk, 0, sizeof *pk);
|
||||
pk->pubkey_algo = i->pubkey_algo;
|
||||
if (get_pubkey (c->ctrl, pk, i->kid) != 0
|
||||
if (get_pubkey (c->ctrl, pk, i->keyid) != 0
|
||||
|| ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
|
||||
nbits_from_pk (pk), NULL))
|
||||
compliant = 0;
|
||||
|
12
g10/packet.h
12
g10/packet.h
@ -131,6 +131,16 @@ typedef struct {
|
||||
} PKT_pubkey_enc;
|
||||
|
||||
|
||||
/* An object to build a list of public-key encrypted session key. */
|
||||
struct pubkey_enc_list
|
||||
{
|
||||
struct pubkey_enc_list *next;
|
||||
u32 keyid[2];
|
||||
int pubkey_algo;
|
||||
gcry_mpi_t data[PUBKEY_MAX_NENC];
|
||||
};
|
||||
|
||||
|
||||
/* A one-pass signature packet as defined in RFC 4880, Section
|
||||
5.4. All fields are serialized. */
|
||||
typedef struct {
|
||||
@ -887,7 +897,7 @@ gpg_error_t check_signature2 (ctrl_t ctrl,
|
||||
|
||||
|
||||
/*-- pubkey-enc.c --*/
|
||||
gpg_error_t get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek);
|
||||
gpg_error_t get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek);
|
||||
gpg_error_t get_override_session_key (DEK *dek, const char *string);
|
||||
|
||||
/*-- compress.c --*/
|
||||
|
118
g10/pubkey-enc.c
118
g10/pubkey-enc.c
@ -38,7 +38,7 @@
|
||||
#include "../common/compliance.h"
|
||||
|
||||
|
||||
static gpg_error_t get_it (ctrl_t ctrl, PKT_pubkey_enc *k,
|
||||
static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *k,
|
||||
DEK *dek, PKT_public_key *sk, u32 *keyid);
|
||||
|
||||
|
||||
@ -72,92 +72,92 @@ is_algo_in_prefs (kbnode_t keyblock, preftype_t type, int algo)
|
||||
* which should have been allocated in secure memory by the caller.
|
||||
*/
|
||||
gpg_error_t
|
||||
get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
|
||||
get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek)
|
||||
{
|
||||
PKT_public_key *sk = NULL;
|
||||
int rc;
|
||||
void *enum_context = NULL;
|
||||
u32 keyid[2];
|
||||
int search_for_secret_keys = 1;
|
||||
|
||||
if (DBG_CLOCK)
|
||||
log_clock ("get_session_key enter");
|
||||
|
||||
rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
if ((k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets)
|
||||
while (search_for_secret_keys)
|
||||
{
|
||||
struct pubkey_enc_list *k;
|
||||
|
||||
free_public_key (sk);
|
||||
sk = xmalloc_clear (sizeof *sk);
|
||||
sk->pubkey_algo = k->pubkey_algo; /* We want a pubkey with this algo. */
|
||||
if (!(rc = get_seckey (ctrl, sk, k->keyid)))
|
||||
rc = enum_secret_keys (ctrl, &enum_context, sk);
|
||||
if (rc)
|
||||
{
|
||||
/* Check compliance. */
|
||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
|
||||
sk->pubkey_algo,
|
||||
sk->pkey, nbits_from_pk (sk), NULL))
|
||||
{
|
||||
log_info (_("key %s is not suitable for decryption"
|
||||
" in %s mode\n"),
|
||||
keystr_from_pk (sk),
|
||||
gnupg_compliance_option_string (opt.compliance));
|
||||
rc = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||
}
|
||||
else
|
||||
rc = get_it (ctrl, k, dek, sk, k->keyid);
|
||||
rc = GPG_ERR_NO_SECKEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (opt.skip_hidden_recipients)
|
||||
rc = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
else /* Anonymous receiver: Try all available secret keys. */
|
||||
{
|
||||
void *enum_context = NULL;
|
||||
u32 keyid[2];
|
||||
|
||||
for (;;)
|
||||
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
|
||||
continue;
|
||||
|
||||
/* Check compliance. */
|
||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
|
||||
sk->pubkey_algo,
|
||||
sk->pkey, nbits_from_pk (sk), NULL))
|
||||
{
|
||||
free_public_key (sk);
|
||||
sk = xmalloc_clear (sizeof *sk);
|
||||
rc = enum_secret_keys (ctrl, &enum_context, sk);
|
||||
if (rc)
|
||||
{
|
||||
rc = GPG_ERR_NO_SECKEY;
|
||||
break;
|
||||
}
|
||||
log_info (_("key %s is not suitable for decryption"
|
||||
" in %s mode\n"),
|
||||
keystr_from_pk (sk),
|
||||
gnupg_compliance_option_string (opt.compliance));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (k = list; k; k = k->next)
|
||||
{
|
||||
if (!(k->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
|
||||
|| k->pubkey_algo == PUBKEY_ALGO_ECDH
|
||||
|| k->pubkey_algo == PUBKEY_ALGO_RSA
|
||||
|| k->pubkey_algo == PUBKEY_ALGO_RSA_E
|
||||
|| k->pubkey_algo == PUBKEY_ALGO_ELGAMAL))
|
||||
continue;
|
||||
|
||||
if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC))
|
||||
continue;
|
||||
|
||||
if (sk->pubkey_algo != k->pubkey_algo)
|
||||
continue;
|
||||
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
|
||||
continue;
|
||||
keyid_from_pk (sk, keyid);
|
||||
if (!opt.quiet)
|
||||
log_info (_("anonymous recipient; trying secret key %s ...\n"),
|
||||
keystr (keyid));
|
||||
|
||||
/* Check compliance. */
|
||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
|
||||
sk->pubkey_algo,
|
||||
sk->pkey, nbits_from_pk (sk), NULL))
|
||||
keyid_from_pk (sk, keyid);
|
||||
|
||||
if (!k->keyid[0] && !k->keyid[1])
|
||||
{
|
||||
log_info (_("key %s is not suitable for decryption"
|
||||
" in %s mode\n"),
|
||||
keystr_from_pk (sk),
|
||||
gnupg_compliance_option_string (opt.compliance));
|
||||
continue;
|
||||
if (!opt.quiet)
|
||||
log_info (_("anonymous recipient; trying secret key %s ...\n"),
|
||||
keystr (keyid));
|
||||
}
|
||||
else if (opt.try_all_secrets
|
||||
|| (k->keyid[0] == keyid[0] && k->keyid[1] == keyid[1]))
|
||||
;
|
||||
else
|
||||
continue;
|
||||
|
||||
rc = get_it (ctrl, k, dek, sk, keyid);
|
||||
if (!rc)
|
||||
{
|
||||
if (!opt.quiet)
|
||||
if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
|
||||
log_info (_("okay, we are the anonymous recipient.\n"));
|
||||
search_for_secret_keys = 0;
|
||||
break;
|
||||
}
|
||||
else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
|
||||
break; /* Don't try any more secret keys. */
|
||||
{
|
||||
search_for_secret_keys = 0;
|
||||
break; /* Don't try any more secret keys. */
|
||||
}
|
||||
}
|
||||
enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
|
||||
}
|
||||
|
||||
leave:
|
||||
enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
|
||||
free_public_key (sk);
|
||||
|
||||
if (DBG_CLOCK)
|
||||
log_clock ("get_session_key leave");
|
||||
return rc;
|
||||
@ -166,7 +166,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
|
||||
|
||||
static gpg_error_t
|
||||
get_it (ctrl_t ctrl,
|
||||
PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
||||
struct pubkey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
||||
{
|
||||
gpg_error_t err;
|
||||
byte *frame = NULL;
|
||||
|
@ -253,7 +253,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
|
||||
* No encryption here but mainproc links to these functions.
|
||||
*/
|
||||
gpg_error_t
|
||||
get_session_key (ctrl_t ctrl, PKT_pubkey_enc *k, DEK *dek)
|
||||
get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek)
|
||||
{
|
||||
(void)ctrl;
|
||||
(void)k;
|
||||
|
Loading…
x
Reference in New Issue
Block a user