Changeset View
Changeset View
Standalone View
Standalone View
g10/mainproc.c
| Context not available. | |||||
| struct kidlist_item *next; | struct kidlist_item *next; | ||||
| u32 kid[2]; | u32 kid[2]; | ||||
| int pubkey_algo; | int pubkey_algo; | ||||
| int reason; | gcry_mpi_t data[2]; | ||||
| }; | }; | ||||
| Context not available. | |||||
| while (c->pkenc_list) | while (c->pkenc_list) | ||||
| { | { | ||||
| struct kidlist_item *tmp = c->pkenc_list->next; | struct kidlist_item *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; | ||||
| } | } | ||||
| Context not available. | |||||
| proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt) | proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt) | ||||
| { | { | ||||
| PKT_pubkey_enc *enc; | PKT_pubkey_enc *enc; | ||||
| int result = 0; | struct kidlist_item *x = xmalloc (sizeof *x); | ||||
| /* 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; | ||||
| Context not available. | |||||
| 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 | |||||
| * 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 | |||||
| we can prioritize what key to use. This gives a better user | |||||
| 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[0] = enc->keyid[0]; | ||||
| x->kid[1] = enc->keyid[1]; | 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); | ||||
| Context not available. | |||||
| * 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 kidlist_item *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); | ||||
| Context not available. | |||||
| algstr, keystr(list->kid)); | algstr, keystr(list->kid)); | ||||
| 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); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| static void | static void | ||||
| proc_encrypted (CTX c, PACKET *pkt) | proc_encrypted (CTX c, PACKET *pkt) | ||||
| { | { | ||||
| struct kidlist_item *item; | |||||
| int result = 0; | int result = 0; | ||||
| if (!opt.quiet) | if (!opt.quiet) | ||||
| Context not available. | |||||
| 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 ); | } | ||||
| /* Figure out the session key by looking at all pkenc packets. */ | |||||
| if (opt.list_only) | |||||
| ; | |||||
| 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 | |||||
| { | |||||
| 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 | |||||
| { | |||||
| log_info (_("public key decryption failed: %s\n"), | |||||
| gpg_strerror (GPG_ERR_PUBKEY_ALGO)); | |||||
| write_status_error ("pkdecrypt_failed", GPG_ERR_PUBKEY_ALGO); | |||||
| } | |||||
| } | } | ||||
| /* FIXME: Figure out the session key by looking at all pkenc packets. */ | 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); | ||||
| Context not available. | |||||