mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
g10: Change decryption key selection for public key encryption.
* g10/mainproc.c (struct mainproc_context): It's now pubkey_enc_list. (do_proc_packets): Remove the first arg CTRL. Fix call of proc_pubkey_enc. (release_list): Handle pubkey_enc_list. (proc_pubkey_enc): Remove the first arg CTRL. Simply put the packet to pubkey_enc_list. (print_pkenc_list): Remove the last arg FAILED. (proc_encrypted): Only call print_pkenc_list once. Handle DEK here. (proc_packets, proc_signature_packets, proc_signature_packets_by_fd) (proc_encryption_packets): Fix call of do_proc_packets. * g10/packet.h (struct pubkey_enc_list): Define. * g10/pubkey-enc.c (get_it): Change the second argument K. (get_session_key): Select session key by LIST, using enum_secret_keys. * g10/gpgv.c (get_session_key): Change the second argument K. * g10/test-stubs.c (get_session_key): Likewise. -- Collect all PKT_PUBKEY_ENC packets, and then, process the PKT_ENCRYPTED* packet. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
1b309d9f61
commit
ce2f717601
@ -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.
|
* No encryption here but mainproc links to these functions.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
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)ctrl;
|
||||||
(void)k;
|
(void)k;
|
||||||
|
200
g10/mainproc.c
200
g10/mainproc.c
@ -46,16 +46,6 @@
|
|||||||
#define MAX_NESTING_DEPTH 32
|
#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;
|
|
||||||
int reason;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Object to hold the processing context.
|
* Object to hold the processing context.
|
||||||
*/
|
*/
|
||||||
@ -95,7 +85,7 @@ struct mainproc_context
|
|||||||
iobuf_t iobuf; /* Used to get the filename etc. */
|
iobuf_t iobuf; /* Used to get the filename etc. */
|
||||||
int trustletter; /* Temporary usage in list_node. */
|
int trustletter; /* Temporary usage in list_node. */
|
||||||
ulong symkeys; /* Number of symmetrically encrypted session keys. */
|
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 {
|
struct {
|
||||||
unsigned int sig_seen:1; /* Set to true if a signature packet
|
unsigned int sig_seen:1; /* Set to true if a signature packet
|
||||||
has been seen. */
|
has been seen. */
|
||||||
@ -112,7 +102,7 @@ static int literals_seen;
|
|||||||
|
|
||||||
|
|
||||||
/*** Local prototypes. ***/
|
/*** Local prototypes. ***/
|
||||||
static int do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a);
|
static int do_proc_packets (CTX c, iobuf_t a);
|
||||||
static void list_node (CTX c, kbnode_t node);
|
static void list_node (CTX c, kbnode_t node);
|
||||||
static void proc_tree (CTX c, kbnode_t node);
|
static void proc_tree (CTX c, kbnode_t node);
|
||||||
|
|
||||||
@ -135,7 +125,10 @@ release_list( CTX c )
|
|||||||
release_kbnode (c->list);
|
release_kbnode (c->list);
|
||||||
while (c->pkenc_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]);
|
||||||
xfree (c->pkenc_list);
|
xfree (c->pkenc_list);
|
||||||
c->pkenc_list = tmp;
|
c->pkenc_list = tmp;
|
||||||
}
|
}
|
||||||
@ -458,10 +451,9 @@ proc_symkey_enc (CTX c, PACKET *pkt)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
proc_pubkey_enc (CTX c, PACKET *pkt)
|
||||||
{
|
{
|
||||||
PKT_pubkey_enc *enc;
|
PKT_pubkey_enc *enc;
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
/* Check whether the secret key is available and store in this case. */
|
/* Check whether the secret key is available and store in this case. */
|
||||||
c->last_was_session_key = 1;
|
c->last_was_session_key = 1;
|
||||||
@ -472,76 +464,29 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
|||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (_("public key is %s\n"), keystr (enc->keyid));
|
log_info (_("public key is %s\n"), keystr (enc->keyid));
|
||||||
|
|
||||||
if (is_status_enabled())
|
if (is_status_enabled ())
|
||||||
{
|
{
|
||||||
char buf[50];
|
char buf[50];
|
||||||
snprintf (buf, sizeof buf, "%08lX%08lX %d 0",
|
snprintf (buf, sizeof buf, "%08lX%08lX %d 0",
|
||||||
(ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
|
(ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
|
||||||
write_status_text (STATUS_ENC_TO, buf);
|
write_status_text (STATUS_ENC_TO, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt.list_only && opt.override_session_key)
|
if (!opt.list_only && !opt.override_session_key)
|
||||||
{
|
{
|
||||||
/* It does not make much sense to store the session key in
|
struct pubkey_enc_list *x = xmalloc (sizeof *x);
|
||||||
* secure memory because it has already been passed on the
|
|
||||||
* command line and the GCHQ knows about it. */
|
|
||||||
c->dek = xmalloc_clear (sizeof *c->dek);
|
|
||||||
result = get_override_session_key (c->dek, opt.override_session_key);
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
xfree (c->dek);
|
|
||||||
c->dek = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
|
|
||||||
|| enc->pubkey_algo == PUBKEY_ALGO_ECDH
|
|
||||||
|| enc->pubkey_algo == PUBKEY_ALGO_RSA
|
|
||||||
|| enc->pubkey_algo == PUBKEY_ALGO_RSA_E
|
|
||||||
|| enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
|
|
||||||
{
|
|
||||||
/* Note that we also allow type 20 Elgamal keys for decryption.
|
|
||||||
There are still a couple of those keys in active use as a
|
|
||||||
subkey. */
|
|
||||||
|
|
||||||
/* FIXME: Store this all in a list and process it later so that
|
x->keyid[0] = enc->keyid[0];
|
||||||
we can prioritize what key to use. This gives a better user
|
x->keyid[1] = enc->keyid[1];
|
||||||
experience if wildcard keyids are used. */
|
|
||||||
if (!c->dek && ((!enc->keyid[0] && !enc->keyid[1])
|
|
||||||
|| opt.try_all_secrets
|
|
||||||
|| have_secret_key_with_kid (enc->keyid)))
|
|
||||||
{
|
|
||||||
if(opt.list_only)
|
|
||||||
result = GPG_ERR_MISSING_ACTION; /* fixme: Use better error code. */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
|
||||||
if ((result = get_session_key (ctrl, enc, c->dek)))
|
|
||||||
{
|
|
||||||
/* Error: Delete the DEK. */
|
|
||||||
xfree (c->dek);
|
|
||||||
c->dek = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = GPG_ERR_NO_SECKEY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = GPG_ERR_PUBKEY_ALGO;
|
|
||||||
|
|
||||||
if (1)
|
|
||||||
{
|
|
||||||
/* Store it for later display. */
|
|
||||||
struct kidlist_item *x = xmalloc (sizeof *x);
|
|
||||||
x->kid[0] = enc->keyid[0];
|
|
||||||
x->kid[1] = enc->keyid[1];
|
|
||||||
x->pubkey_algo = enc->pubkey_algo;
|
x->pubkey_algo = enc->pubkey_algo;
|
||||||
x->reason = result;
|
x->data[0] = x->data[1] = NULL;
|
||||||
|
if (enc->data[0])
|
||||||
|
{
|
||||||
|
x->data[0] = mpi_copy (enc->data[0]);
|
||||||
|
x->data[1] = mpi_copy (enc->data[1]);
|
||||||
|
}
|
||||||
x->next = c->pkenc_list;
|
x->next = c->pkenc_list;
|
||||||
c->pkenc_list = x;
|
c->pkenc_list = x;
|
||||||
|
|
||||||
if (!result && opt.verbose > 1)
|
|
||||||
log_info (_("public key encrypted data: good DEK\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free_packet(pkt, NULL);
|
free_packet(pkt, NULL);
|
||||||
@ -553,60 +498,34 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
|
|||||||
* not decrypt.
|
* not decrypt.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
print_pkenc_list (ctrl_t ctrl, struct kidlist_item *list, int failed)
|
print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list)
|
||||||
{
|
{
|
||||||
for (; list; list = list->next)
|
for (; list; list = list->next)
|
||||||
{
|
{
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
const char *algstr;
|
const char *algstr;
|
||||||
|
|
||||||
if (failed && !list->reason)
|
|
||||||
continue;
|
|
||||||
if (!failed && list->reason)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
algstr = openpgp_pk_algo_name (list->pubkey_algo);
|
algstr = openpgp_pk_algo_name (list->pubkey_algo);
|
||||||
pk = xmalloc_clear (sizeof *pk);
|
pk = xmalloc_clear (sizeof *pk);
|
||||||
|
|
||||||
if (!algstr)
|
if (!algstr)
|
||||||
algstr = "[?]";
|
algstr = "[?]";
|
||||||
pk->pubkey_algo = list->pubkey_algo;
|
pk->pubkey_algo = list->pubkey_algo;
|
||||||
if (!get_pubkey (ctrl, pk, list->kid))
|
if (!get_pubkey (ctrl, pk, list->keyid))
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
|
log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"),
|
||||||
nbits_from_pk (pk), algstr, keystr_from_pk(pk),
|
nbits_from_pk (pk), algstr, keystr_from_pk(pk),
|
||||||
strtimestamp (pk->timestamp));
|
strtimestamp (pk->timestamp));
|
||||||
p = get_user_id_native (ctrl, list->kid);
|
p = get_user_id_native (ctrl, list->keyid);
|
||||||
log_printf (_(" \"%s\"\n"), p);
|
log_printf (_(" \"%s\"\n"), p);
|
||||||
xfree (p);
|
xfree (p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log_info (_("encrypted with %s key, ID %s\n"),
|
log_info (_("encrypted with %s key, ID %s\n"),
|
||||||
algstr, keystr(list->kid));
|
algstr, keystr(list->keyid));
|
||||||
|
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
|
|
||||||
if (gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY)
|
|
||||||
{
|
|
||||||
if (is_status_enabled())
|
|
||||||
{
|
|
||||||
char buf[20];
|
|
||||||
snprintf (buf, sizeof buf, "%08lX%08lX",
|
|
||||||
(ulong)list->kid[0], (ulong)list->kid[1]);
|
|
||||||
write_status_text (STATUS_NO_SECKEY, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (gpg_err_code (list->reason) == GPG_ERR_MISSING_ACTION)
|
|
||||||
{
|
|
||||||
/* Not tested for secret key due to --list-only mode. */
|
|
||||||
}
|
|
||||||
else if (list->reason)
|
|
||||||
{
|
|
||||||
log_info (_("public key decryption failed: %s\n"),
|
|
||||||
gpg_strerror (list->reason));
|
|
||||||
write_status_error ("pkdecrypt_failed", list->reason);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,11 +549,58 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
log_info (_("encrypted with %lu passphrases\n"), c->symkeys);
|
log_info (_("encrypted with %lu passphrases\n"), c->symkeys);
|
||||||
else if (c->symkeys == 1)
|
else if (c->symkeys == 1)
|
||||||
log_info (_("encrypted with 1 passphrase\n"));
|
log_info (_("encrypted with 1 passphrase\n"));
|
||||||
print_pkenc_list (c->ctrl, c->pkenc_list, 1 );
|
print_pkenc_list (c->ctrl, c->pkenc_list);
|
||||||
print_pkenc_list (c->ctrl, c->pkenc_list, 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Figure out the session key by looking at all pkenc packets. */
|
/* Figure out the session key by looking at all pkenc packets. */
|
||||||
|
if (opt.list_only || c->dek)
|
||||||
|
;
|
||||||
|
else if (opt.override_session_key)
|
||||||
|
{
|
||||||
|
c->dek = xmalloc_clear (sizeof *c->dek);
|
||||||
|
result = get_override_session_key (c->dek, opt.override_session_key);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
xfree (c->dek);
|
||||||
|
c->dek = NULL;
|
||||||
|
log_info (_("public key decryption failed: %s\n"),
|
||||||
|
gpg_strerror (result));
|
||||||
|
write_status_error ("pkdecrypt_failed", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->dek = xmalloc_secure_clear (sizeof *c->dek);
|
||||||
|
result = get_session_key (c->ctrl, c->pkenc_list, c->dek);
|
||||||
|
if (result == GPG_ERR_NO_SECKEY)
|
||||||
|
{
|
||||||
|
if (is_status_enabled ())
|
||||||
|
{
|
||||||
|
struct pubkey_enc_list *list;
|
||||||
|
|
||||||
|
for (list = c->pkenc_list; list; list = list->next)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
snprintf (buf, sizeof buf, "%08lX%08lX",
|
||||||
|
(ulong)list->keyid[0], (ulong)list->keyid[1]);
|
||||||
|
write_status_text (STATUS_NO_SECKEY, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (result)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->dek && opt.verbose > 1)
|
||||||
|
log_info (_("public key encrypted data: good DEK\n"));
|
||||||
|
|
||||||
write_status (STATUS_BEGIN_DECRYPTION);
|
write_status (STATUS_BEGIN_DECRYPTION);
|
||||||
|
|
||||||
@ -709,7 +675,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
&& gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo,
|
&& gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo,
|
||||||
GCRY_CIPHER_MODE_CFB))
|
GCRY_CIPHER_MODE_CFB))
|
||||||
{
|
{
|
||||||
struct kidlist_item *i;
|
struct pubkey_enc_list *i;
|
||||||
int compliant = 1;
|
int compliant = 1;
|
||||||
PKT_public_key *pk = xmalloc (sizeof *pk);
|
PKT_public_key *pk = xmalloc (sizeof *pk);
|
||||||
|
|
||||||
@ -722,7 +688,7 @@ proc_encrypted (CTX c, PACKET *pkt)
|
|||||||
{
|
{
|
||||||
memset (pk, 0, sizeof *pk);
|
memset (pk, 0, sizeof *pk);
|
||||||
pk->pubkey_algo = i->pubkey_algo;
|
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,
|
|| ! gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, pk->pkey,
|
||||||
nbits_from_pk (pk), NULL))
|
nbits_from_pk (pk), NULL))
|
||||||
compliant = 0;
|
compliant = 0;
|
||||||
@ -1367,7 +1333,7 @@ proc_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
|
|||||||
|
|
||||||
c->ctrl = ctrl;
|
c->ctrl = ctrl;
|
||||||
c->anchor = anchor;
|
c->anchor = anchor;
|
||||||
rc = do_proc_packets (ctrl, c, a);
|
rc = do_proc_packets (c, a);
|
||||||
xfree (c);
|
xfree (c);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -1390,7 +1356,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a,
|
|||||||
c->signed_data.used = !!signedfiles;
|
c->signed_data.used = !!signedfiles;
|
||||||
|
|
||||||
c->sigfilename = sigfilename;
|
c->sigfilename = sigfilename;
|
||||||
rc = do_proc_packets (ctrl, c, a);
|
rc = do_proc_packets (c, a);
|
||||||
|
|
||||||
/* If we have not encountered any signature we print an error
|
/* If we have not encountered any signature we print an error
|
||||||
messages, send a NODATA status back and return an error code.
|
messages, send a NODATA status back and return an error code.
|
||||||
@ -1433,7 +1399,7 @@ proc_signature_packets_by_fd (ctrl_t ctrl,
|
|||||||
c->signed_data.data_names = NULL;
|
c->signed_data.data_names = NULL;
|
||||||
c->signed_data.used = (signed_data_fd != -1);
|
c->signed_data.used = (signed_data_fd != -1);
|
||||||
|
|
||||||
rc = do_proc_packets (ctrl, c, a);
|
rc = do_proc_packets (c, a);
|
||||||
|
|
||||||
/* If we have not encountered any signature we print an error
|
/* If we have not encountered any signature we print an error
|
||||||
messages, send a NODATA status back and return an error code.
|
messages, send a NODATA status back and return an error code.
|
||||||
@ -1466,7 +1432,7 @@ proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
|
|||||||
c->ctrl = ctrl;
|
c->ctrl = ctrl;
|
||||||
c->anchor = anchor;
|
c->anchor = anchor;
|
||||||
c->encrypt_only = 1;
|
c->encrypt_only = 1;
|
||||||
rc = do_proc_packets (ctrl, c, a);
|
rc = do_proc_packets (c, a);
|
||||||
xfree (c);
|
xfree (c);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1492,7 +1458,7 @@ check_nesting (CTX c)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
|
do_proc_packets (CTX c, iobuf_t a)
|
||||||
{
|
{
|
||||||
PACKET *pkt;
|
PACKET *pkt;
|
||||||
struct parse_packet_ctx_s parsectx;
|
struct parse_packet_ctx_s parsectx;
|
||||||
@ -1526,7 +1492,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
|
|||||||
{
|
{
|
||||||
switch (pkt->pkttype)
|
switch (pkt->pkttype)
|
||||||
{
|
{
|
||||||
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
|
case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
|
||||||
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
||||||
case PKT_ENCRYPTED:
|
case PKT_ENCRYPTED:
|
||||||
case PKT_ENCRYPTED_MDC:
|
case PKT_ENCRYPTED_MDC:
|
||||||
@ -1572,7 +1538,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
|
|||||||
|
|
||||||
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
|
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
|
||||||
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
||||||
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
|
case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
|
||||||
case PKT_ENCRYPTED:
|
case PKT_ENCRYPTED:
|
||||||
case PKT_ENCRYPTED_MDC:
|
case PKT_ENCRYPTED_MDC:
|
||||||
case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break;
|
case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break;
|
||||||
@ -1599,7 +1565,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
|
|||||||
break;
|
break;
|
||||||
case PKT_USER_ID: newpkt = add_user_id (c, pkt); break;
|
case PKT_USER_ID: newpkt = add_user_id (c, pkt); break;
|
||||||
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
|
case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break;
|
||||||
case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break;
|
case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break;
|
||||||
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break;
|
||||||
case PKT_ENCRYPTED:
|
case PKT_ENCRYPTED:
|
||||||
case PKT_ENCRYPTED_MDC:
|
case PKT_ENCRYPTED_MDC:
|
||||||
|
12
g10/packet.h
12
g10/packet.h
@ -131,6 +131,16 @@ typedef struct {
|
|||||||
} PKT_pubkey_enc;
|
} 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
|
/* A one-pass signature packet as defined in RFC 4880, Section
|
||||||
5.4. All fields are serialized. */
|
5.4. All fields are serialized. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -889,7 +899,7 @@ gpg_error_t check_signature2 (ctrl_t ctrl,
|
|||||||
|
|
||||||
|
|
||||||
/*-- pubkey-enc.c --*/
|
/*-- 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);
|
gpg_error_t get_override_session_key (DEK *dek, const char *string);
|
||||||
|
|
||||||
/*-- compress.c --*/
|
/*-- compress.c --*/
|
||||||
|
118
g10/pubkey-enc.c
118
g10/pubkey-enc.c
@ -38,7 +38,7 @@
|
|||||||
#include "../common/compliance.h"
|
#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);
|
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.
|
* which should have been allocated in secure memory by the caller.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
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;
|
PKT_public_key *sk = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
void *enum_context = NULL;
|
||||||
|
u32 keyid[2];
|
||||||
|
int search_for_secret_keys = 1;
|
||||||
|
|
||||||
if (DBG_CLOCK)
|
if (DBG_CLOCK)
|
||||||
log_clock ("get_session_key enter");
|
log_clock ("get_session_key enter");
|
||||||
|
|
||||||
rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
|
while (search_for_secret_keys)
|
||||||
if (rc)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
if ((k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets)
|
|
||||||
{
|
{
|
||||||
|
struct pubkey_enc_list *k;
|
||||||
|
|
||||||
|
free_public_key (sk);
|
||||||
sk = xmalloc_clear (sizeof *sk);
|
sk = xmalloc_clear (sizeof *sk);
|
||||||
sk->pubkey_algo = k->pubkey_algo; /* We want a pubkey with this algo. */
|
rc = enum_secret_keys (ctrl, &enum_context, sk);
|
||||||
if (!(rc = get_seckey (ctrl, sk, k->keyid)))
|
if (rc)
|
||||||
{
|
{
|
||||||
/* Check compliance. */
|
rc = GPG_ERR_NO_SECKEY;
|
||||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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);
|
log_info (_("key %s is not suitable for decryption"
|
||||||
sk = xmalloc_clear (sizeof *sk);
|
" in %s mode\n"),
|
||||||
rc = enum_secret_keys (ctrl, &enum_context, sk);
|
keystr_from_pk (sk),
|
||||||
if (rc)
|
gnupg_compliance_option_string (opt.compliance));
|
||||||
{
|
continue;
|
||||||
rc = GPG_ERR_NO_SECKEY;
|
}
|
||||||
break;
|
|
||||||
}
|
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)
|
if (sk->pubkey_algo != k->pubkey_algo)
|
||||||
continue;
|
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. */
|
keyid_from_pk (sk, keyid);
|
||||||
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
|
|
||||||
sk->pubkey_algo,
|
if (!k->keyid[0] && !k->keyid[1])
|
||||||
sk->pkey, nbits_from_pk (sk), NULL))
|
|
||||||
{
|
{
|
||||||
log_info (_("key %s is not suitable for decryption"
|
if (!opt.quiet)
|
||||||
" in %s mode\n"),
|
log_info (_("anonymous recipient; trying secret key %s ...\n"),
|
||||||
keystr_from_pk (sk),
|
keystr (keyid));
|
||||||
gnupg_compliance_option_string (opt.compliance));
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
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);
|
rc = get_it (ctrl, k, dek, sk, keyid);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
if (!opt.quiet)
|
if (!opt.quiet && !k->keyid[0] && !k->keyid[1])
|
||||||
log_info (_("okay, we are the anonymous recipient.\n"));
|
log_info (_("okay, we are the anonymous recipient.\n"));
|
||||||
|
search_for_secret_keys = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
|
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 */
|
|
||||||
}
|
}
|
||||||
|
enum_secret_keys (ctrl, &enum_context, NULL); /* free context */
|
||||||
leave:
|
|
||||||
free_public_key (sk);
|
free_public_key (sk);
|
||||||
|
|
||||||
if (DBG_CLOCK)
|
if (DBG_CLOCK)
|
||||||
log_clock ("get_session_key leave");
|
log_clock ("get_session_key leave");
|
||||||
return rc;
|
return rc;
|
||||||
@ -166,7 +166,7 @@ get_session_key (ctrl_t ctrl, PKT_pubkey_enc * k, DEK * dek)
|
|||||||
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
get_it (ctrl_t ctrl,
|
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;
|
gpg_error_t err;
|
||||||
byte *frame = NULL;
|
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.
|
* No encryption here but mainproc links to these functions.
|
||||||
*/
|
*/
|
||||||
gpg_error_t
|
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)ctrl;
|
||||||
(void)k;
|
(void)k;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user