diff --git a/g10/keydb.h b/g10/keydb.h index f61515f42..e1a316cca 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,564 +1,565 @@ /* keydb.h - Key database * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2010 Free Software Foundation, Inc. * Copyright (C) 2015, 2016 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef G10_KEYDB_H #define G10_KEYDB_H #include "../common/types.h" #include "../common/util.h" #include "packet.h" /* What qualifies as a certification (key-signature in contrast to a * data signature)? Note that a back signature is special and can be * made by key and data signatures capable subkeys.) */ #define IS_CERT(s) (IS_KEY_SIG(s) || IS_UID_SIG(s) || IS_SUBKEY_SIG(s) \ || IS_KEY_REV(s) || IS_UID_REV(s) || IS_SUBKEY_REV(s)) #define IS_SIG(s) (!IS_CERT(s)) #define IS_KEY_SIG(s) ((s)->sig_class == 0x1f) #define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10) #define IS_SUBKEY_SIG(s) ((s)->sig_class == 0x18) #define IS_BACK_SIG(s) ((s)->sig_class == 0x19) #define IS_KEY_REV(s) ((s)->sig_class == 0x20) #define IS_UID_REV(s) ((s)->sig_class == 0x30) #define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28) struct getkey_ctx_s; typedef struct getkey_ctx_s *GETKEY_CTX; typedef struct getkey_ctx_s *getkey_ctx_t; /**************** * A Keyblock is all packets which form an entire certificate; * i.e. the public key, certificate, trust packets, user ids, * signatures, and subkey. * * This structure is also used to bind arbitrary packets together. */ struct kbnode_struct { kbnode_t next; PACKET *pkt; int flag; /* Local use during keyblock processing (not cloned).*/ unsigned int tag; /* Ditto. */ int private_flag; }; #define is_deleted_kbnode(a) ((a)->private_flag & 1) #define is_cloned_kbnode(a) ((a)->private_flag & 2) /* * A structure to store key identification as well as some stuff * needed for key validation. */ struct key_item { struct key_item *next; unsigned int ownertrust,min_ownertrust; byte trust_depth; byte trust_value; char *trust_regexp; u32 kid[2]; }; /* Bit flags used with build_pk_list. */ enum { PK_LIST_ENCRYPT_TO = 1, /* This is an encrypt-to recipient. */ PK_LIST_HIDDEN = 2, /* This is a hidden recipient. */ PK_LIST_CONFIG = 4, /* Specified via config file. */ PK_LIST_FROM_FILE = 8 /* Take key from file with that name. */ }; /* To store private data in the flags the private data must be left * shifted by this value. */ enum { PK_LIST_SHIFT = 4 }; /* Structure to hold a couple of public key certificates. */ typedef struct pk_list *PK_LIST; /* Deprecated. */ typedef struct pk_list *pk_list_t; struct pk_list { PK_LIST next; PKT_public_key *pk; int flags; /* See PK_LIST_ constants. */ }; /* Structure to hold a list of secret key certificates. */ typedef struct sk_list *SK_LIST; struct sk_list { SK_LIST next; PKT_public_key *pk; int mark; /* not used */ }; /* structure to collect all information which can be used to * identify a public key */ typedef struct pubkey_find_info *PUBKEY_FIND_INFO; struct pubkey_find_info { u32 keyid[2]; unsigned nbits; byte pubkey_algo; byte fingerprint[MAX_FINGERPRINT_LEN]; char userid[1]; }; /* Helper type for preference functions. */ -union pref_hint +struct pref_hint { - int digest_length; + int digest_length; /* We want at least this digest length. */ + int exact; /* We need to use exactly this length. */ }; /* Constants to describe from where a key was fetched or updated. */ enum { KEYORG_UNKNOWN = 0, KEYORG_KS = 1, /* Public keyserver. */ KEYORG_KS_PREF = 2, /* Preferred keysrver. */ KEYORG_DANE = 3, /* OpenPGP DANE. */ KEYORG_WKD = 4, /* Web Key Directory. */ KEYORG_URL = 5, /* Trusted URL. */ KEYORG_FILE = 6, /* Trusted file. */ KEYORG_SELF = 7 /* We generated it. */ }; /* * Check whether the signature SIG is in the klist K. */ static inline struct key_item * is_in_klist (struct key_item *k, PKT_signature *sig) { for (; k; k = k->next) { if (k->kid[0] == sig->keyid[0] && k->kid[1] == sig->keyid[1]) return k; } return NULL; } /*-- keydb.c --*/ #define KEYDB_RESOURCE_FLAG_PRIMARY 2 /* The primary resource. */ #define KEYDB_RESOURCE_FLAG_DEFAULT 4 /* The default one. */ #define KEYDB_RESOURCE_FLAG_READONLY 8 /* Open in read only mode. */ #define KEYDB_RESOURCE_FLAG_GPGVDEF 16 /* Default file for gpgv. */ /* Format a search term for debugging output. The caller must free the result. */ char *keydb_search_desc_dump (struct keydb_search_desc *desc); /* Register a resource (keyring or keybox). */ gpg_error_t keydb_add_resource (const char *url, unsigned int flags); /* Dump some statistics to the log. */ void keydb_dump_stats (void); /* Create a new database handle. Returns NULL on error, sets ERRNO, and prints an error diagnostic. */ KEYDB_HANDLE keydb_new (void); /* Free all resources owned by the database handle. */ void keydb_release (KEYDB_HANDLE hd); /* Take a lock on the files immediately and not only during insert or * update. This lock is released with keydb_release. */ gpg_error_t keydb_lock (KEYDB_HANDLE hd); /* Set a flag on the handle to suppress use of cached results. This is required for updating a keyring and for key listings. Fixme: Using a new parameter for keydb_new might be a better solution. */ void keydb_disable_caching (KEYDB_HANDLE hd); /* Save the last found state and invalidate the current selection. */ void keydb_push_found_state (KEYDB_HANDLE hd); /* Restore the previous save state. */ void keydb_pop_found_state (KEYDB_HANDLE hd); /* Return the file name of the resource. */ const char *keydb_get_resource_name (KEYDB_HANDLE hd); /* Return the keyblock last found by keydb_search. */ gpg_error_t keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); /* Update the keyblock KB. */ gpg_error_t keydb_update_keyblock (ctrl_t ctrl, KEYDB_HANDLE hd, kbnode_t kb); /* Insert a keyblock into one of the underlying keyrings or keyboxes. */ gpg_error_t keydb_insert_keyblock (KEYDB_HANDLE hd, kbnode_t kb); /* Delete the currently selected keyblock. */ gpg_error_t keydb_delete_keyblock (KEYDB_HANDLE hd); /* Find the first writable resource. */ gpg_error_t keydb_locate_writable (KEYDB_HANDLE hd); /* Rebuild the on-disk caches of all key resources. */ void keydb_rebuild_caches (ctrl_t ctrl, int noisy); /* Return the number of skipped blocks (because they were to large to read from a keybox) since the last search reset. */ unsigned long keydb_get_skipped_counter (KEYDB_HANDLE hd); /* Clears the current search result and resets the handle's position. */ gpg_error_t keydb_search_reset (KEYDB_HANDLE hd); /* Search the database for keys matching the search description. */ gpg_error_t keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex); /* Return the first non-legacy key in the database. */ gpg_error_t keydb_search_first (KEYDB_HANDLE hd); /* Return the next key (not the next matching key!). */ gpg_error_t keydb_search_next (KEYDB_HANDLE hd); /* This is a convenience function for searching for keys with a long key id. */ gpg_error_t keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); /* This is a convenience function for searching for keys with a long (20 byte) fingerprint. */ gpg_error_t keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr); /*-- pkclist.c --*/ void show_revocation_reason (ctrl_t ctrl, PKT_public_key *pk, int mode ); int check_signatures_trust (ctrl_t ctrl, PKT_signature *sig); void release_pk_list (PK_LIST pk_list); int build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list); gpg_error_t find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use, int mark_hidden, int from_file, pk_list_t *pk_list_addr); int algo_available( preftype_t preftype, int algo, - const union pref_hint *hint ); + const struct pref_hint *hint ); int select_algo_from_prefs( PK_LIST pk_list, int preftype, - int request, const union pref_hint *hint); + int request, const struct pref_hint *hint); int select_mdc_from_pklist (PK_LIST pk_list); void warn_missing_mdc_from_pklist (PK_LIST pk_list); void warn_missing_aes_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ int random_is_faked (void); void release_sk_list( SK_LIST sk_list ); gpg_error_t build_sk_list (ctrl_t ctrl, strlist_t locusr, SK_LIST *ret_sk_list, unsigned use); /*-- passphrase.h --*/ unsigned char encode_s2k_iterations (int iterations); int have_static_passphrase(void); const char *get_static_passphrase (void); void set_passphrase_from_string(const char *pass); void read_passphrase_from_fd( int fd ); void passphrase_clear_cache (const char *cacheid); DEK *passphrase_to_dek_ext(u32 *keyid, int pubkey_algo, int cipher_algo, STRING2KEY *s2k, int mode, const char *tryagain_text, const char *custdesc, const char *custprompt, int *canceled); DEK *passphrase_to_dek (int cipher_algo, STRING2KEY *s2k, int create, int nocache, const char *tryagain_text, int *canceled); void set_next_passphrase( const char *s ); char *get_last_passphrase(void); void next_to_last_passphrase(void); void emit_status_need_passphrase (ctrl_t ctrl, u32 *keyid, u32 *mainkeyid, int pubkey_algo); #define FORMAT_KEYDESC_NORMAL 0 #define FORMAT_KEYDESC_IMPORT 1 #define FORMAT_KEYDESC_EXPORT 2 #define FORMAT_KEYDESC_DELKEY 3 char *gpg_format_keydesc (ctrl_t ctrl, PKT_public_key *pk, int mode, int escaped); /*-- getkey.c --*/ /* Cache a copy of a public key in the public key cache. */ void cache_public_key( PKT_public_key *pk ); /* Disable and drop the public key cache. */ void getkey_disable_caches(void); /* Return the public key used for signature SIG and store it at PK. */ gpg_error_t get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, PKT_public_key *forced_pk); /* Return the public key with the key id KEYID and store it at PK. */ int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid); /* Similar to get_pubkey, but it does not take PK->REQ_USAGE into account nor does it merge in the self-signed data. This function also only considers primary keys. */ int get_pubkey_fast (PKT_public_key *pk, u32 *keyid); /* Return the entire keyblock used to create SIG. This is a * specialized version of get_pubkeyblock. */ kbnode_t get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig); /* Return the key block for the key with KEYID. */ kbnode_t get_pubkeyblock (ctrl_t ctrl, u32 *keyid); /* A list used by get_pubkeys to gather all of the matches. */ struct pubkey_s { struct pubkey_s *next; /* The key to use (either the public key or the subkey). */ PKT_public_key *pk; kbnode_t keyblock; }; typedef struct pubkey_s *pubkey_t; /* Free a list of public keys. */ void pubkeys_free (pubkey_t keys); /* Mode flags for get_pubkey_byname. */ enum get_pubkey_modes { GET_PUBKEY_NORMAL = 0, GET_PUBKEY_NO_AKL = 1, GET_PUBKEY_NO_LOCAL = 2 }; /* Find a public key identified by NAME. */ int get_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode, GETKEY_CTX *retctx, PKT_public_key *pk, const char *name, KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd, int include_unusable); /* Likewise, but only return the best match if NAME resembles a mail * address. */ gpg_error_t get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode, GETKEY_CTX *retctx, PKT_public_key *pk, const char *name, KBNODE *ret_keyblock, int include_unusable); /* Get a public key directly from file FNAME. */ gpg_error_t get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname); /* Get a public key from a buffer. */ gpg_error_t get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf, const void *buffer, size_t buflen, u32 *want_keyid, kbnode_t *r_keyblock); /* Return the public key with the key id KEYID iff the secret key is * available and store it at PK. */ gpg_error_t get_seckey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid); /* Lookup a key with the specified fingerprint. */ int get_pubkey_byfprint (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock, const byte *fprint, size_t fprint_len); /* This function is similar to get_pubkey_byfprint, but it doesn't merge the self-signed data into the public key and subkeys or into the user ids. */ gpg_error_t get_pubkey_byfprint_fast (PKT_public_key *pk, const byte *fprint, size_t fprint_len); /* This function is similar to get_pubkey_byfprint, but it doesn't merge the self-signed data into the public key and subkeys or into the user ids. */ gpg_error_t get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, const byte *fprint, size_t fprint_len, int lock); /* Returns true if a secret key is available for the public key with key id KEYID. */ int have_secret_key_with_kid (u32 *keyid); /* Parse the --default-key parameter. Returns the last key (in terms of when the option is given) that is available. */ const char *parse_def_secret_key (ctrl_t ctrl); /* Look up a secret key. */ gpg_error_t get_seckey_default (ctrl_t ctrl, PKT_public_key *pk); gpg_error_t get_seckey_default_or_card (ctrl_t ctrl, PKT_public_key *pk, const byte *fpr, size_t fpr_len); /* Search for keys matching some criteria. */ gpg_error_t getkey_bynames (ctrl_t ctrl, getkey_ctx_t *retctx, PKT_public_key *pk, strlist_t names, int want_secret, kbnode_t *ret_keyblock); /* Search for one key matching some criteria. */ gpg_error_t getkey_byname (ctrl_t ctrl, getkey_ctx_t *retctx, PKT_public_key *pk, const char *name, int want_secret, kbnode_t *ret_keyblock); /* Return the next search result. */ gpg_error_t getkey_next (ctrl_t ctrl, getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock); /* Release any resources used by a key listing context. */ void getkey_end (ctrl_t ctrl, getkey_ctx_t ctx); /* Return the database handle used by this context. The context still owns the handle. */ KEYDB_HANDLE get_ctx_handle(GETKEY_CTX ctx); /* Enumerate some secret keys. */ gpg_error_t enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *pk); /* Set the mainkey_id fields for all keys in KEYBLOCK. */ void setup_main_keyids (kbnode_t keyblock); /* This function merges information from the self-signed data into the data structures. */ void merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock); char *get_user_id_string_native (ctrl_t ctrl, u32 *keyid); char *get_long_user_id_string (ctrl_t ctrl, u32 *keyid); char *get_user_id (ctrl_t ctrl, u32 *keyid, size_t *rn, int *r_nouid); char *get_user_id_native (ctrl_t ctrl, u32 *keyid); char *get_user_id_byfpr (ctrl_t ctrl, const byte *fpr, size_t *rn); char *get_user_id_byfpr_native (ctrl_t ctrl, const byte *fpr); void release_akl(void); int akl_empty_or_only_local (void); int parse_auto_key_locate(const char *options); int parse_key_origin (char *string); const char *key_origin_string (int origin); /*-- keyid.c --*/ int pubkey_letter( int algo ); char *pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize); #define PUBKEY_STRING_SIZE 32 u32 v3_keyid (gcry_mpi_t a, u32 *ki); void hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ); char *format_keyid (u32 *keyid, int format, char *buffer, int len); /* Return PK's keyid. The memory is owned by PK. */ u32 *pk_keyid (PKT_public_key *pk); /* Return the keyid of the primary key associated with PK. The memory is owned by PK. */ u32 *pk_main_keyid (PKT_public_key *pk); /* Order A and B. If A < B then return -1, if A == B then return 0, and if A > B then return 1. */ static int GPGRT_ATTR_UNUSED keyid_cmp (const u32 *a, const u32 *b) { if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; if (a[1] < b[1]) return -1; if (a[1] > b[1]) return 1; return 0; } /* Return whether PK is a primary key. */ static int GPGRT_ATTR_UNUSED pk_is_primary (PKT_public_key *pk) { return keyid_cmp (pk_keyid (pk), pk_main_keyid (pk)) == 0; } /* Copy the keyid in SRC to DEST and return DEST. */ u32 *keyid_copy (u32 *dest, const u32 *src); size_t keystrlen(void); const char *keystr(u32 *keyid); const char *keystr_with_sub (u32 *main_kid, u32 *sub_kid); const char *keystr_from_pk(PKT_public_key *pk); const char *keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk); /* Return PK's key id as a string using the default format. PK owns the storage. */ const char *pk_keyid_str (PKT_public_key *pk); const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc); u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ); u32 keyid_from_sig (PKT_signature *sig, u32 *keyid ); u32 keyid_from_fingerprint (ctrl_t ctrl, const byte *fprint, size_t fprint_len, u32 *keyid); byte *namehash_from_uid(PKT_user_id *uid); unsigned nbits_from_pk( PKT_public_key *pk ); /* Convert an UTC TIMESTAMP into an UTC yyyy-mm-dd string. Return * that string. The caller should pass a buffer with at least a size * of MK_DATESTR_SIZE. */ char *mk_datestr (char *buffer, size_t bufsize, u32 timestamp); #define MK_DATESTR_SIZE 11 const char *datestr_from_pk( PKT_public_key *pk ); const char *datestr_from_sig( PKT_signature *sig ); const char *expirestr_from_pk( PKT_public_key *pk ); const char *expirestr_from_sig( PKT_signature *sig ); const char *revokestr_from_pk( PKT_public_key *pk ); const char *usagestr_from_pk (PKT_public_key *pk, int fill); const char *colon_strtime (u32 t); const char *colon_datestr_from_pk (PKT_public_key *pk); const char *colon_datestr_from_sig (PKT_signature *sig); const char *colon_expirestr_from_sig (PKT_signature *sig); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); char *hexfingerprint (PKT_public_key *pk, char *buffer, size_t buflen); char *format_hexfingerprint (const char *fingerprint, char *buffer, size_t buflen); gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array); gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip); /*-- kbnode.c --*/ KBNODE new_kbnode( PACKET *pkt ); KBNODE clone_kbnode( KBNODE node ); void release_kbnode( KBNODE n ); void delete_kbnode( KBNODE node ); void add_kbnode( KBNODE root, KBNODE node ); void insert_kbnode( KBNODE root, KBNODE node, int pkttype ); void move_kbnode( KBNODE *root, KBNODE node, KBNODE where ); void remove_kbnode( KBNODE *root, KBNODE node ); KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype ); KBNODE find_next_kbnode( KBNODE node, int pkttype ); KBNODE find_kbnode( KBNODE node, int pkttype ); KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all ); void clear_kbnode_flags( KBNODE n ); int commit_kbnode( KBNODE *root ); void dump_kbnode( KBNODE node ); #endif /*G10_KEYDB_H*/ diff --git a/g10/pkclist.c b/g10/pkclist.c index 542164949..bfc4f84e4 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -1,1695 +1,1705 @@ /* pkclist.c - create a list of public keys * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include "gpg.h" #include "options.h" #include "packet.h" #include "../common/status.h" #include "keydb.h" #include "../common/util.h" #include "main.h" #include "trustdb.h" #include "../common/ttyio.h" #include "../common/status.h" #include "photoid.h" #include "../common/i18n.h" #include "tofu.h" #define CONTROL_D ('D' - 'A' + 1) static void send_status_inv_recp (int reason, const char *name) { char buf[40]; snprintf (buf, sizeof buf, "%d ", reason); write_status_text_and_buffer (STATUS_INV_RECP, buf, name, strlen (name), -1); } /**************** * Show the revocation reason as it is stored with the given signature */ static void do_show_revocation_reason( PKT_signature *sig ) { size_t n, nn; const byte *p, *pp; int seq = 0; const char *text; while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REVOC_REASON, &n, &seq, NULL )) ) { if( !n ) continue; /* invalid - just skip it */ if( *p == 0 ) text = _("No reason specified"); else if( *p == 0x01 ) text = _("Key is superseded"); else if( *p == 0x02 ) text = _("Key has been compromised"); else if( *p == 0x03 ) text = _("Key is no longer used"); else if( *p == 0x20 ) text = _("User ID is no longer valid"); else text = NULL; log_info ( _("reason for revocation: ")); if (text) log_printf ("%s\n", text); else log_printf ("code=%02x\n", *p ); n--; p++; pp = NULL; do { /* We don't want any empty lines, so skip them */ while( n && *p == '\n' ) { p++; n--; } if( n ) { pp = memchr( p, '\n', n ); nn = pp? pp - p : n; log_info ( _("revocation comment: ") ); es_write_sanitized (log_get_stream(), p, nn, NULL, NULL); log_printf ("\n"); p += nn; n -= nn; } } while( pp ); } } /* Mode 0: try and find the revocation based on the pk (i.e. check subkeys, etc.) Mode 1: use only the revocation on the main pk */ void show_revocation_reason (ctrl_t ctrl, PKT_public_key *pk, int mode) { /* Hmmm, this is not so easy because we have to duplicate the code * used in the trustdb to calculate the keyflags. We need to find * a clean way to check revocation certificates on keys and * signatures. And there should be no duplicate code. Because we * enter this function only when the trustdb told us that we have * a revoked key, we could simply look for a revocation cert and * display this one, when there is only one. Let's try to do this * until we have a better solution. */ KBNODE node, keyblock = NULL; byte fingerprint[MAX_FINGERPRINT_LEN]; size_t fingerlen; int rc; /* get the keyblock */ fingerprint_from_pk( pk, fingerprint, &fingerlen ); rc = get_pubkey_byfprint (ctrl, NULL, &keyblock, fingerprint, fingerlen); if( rc ) { /* that should never happen */ log_debug( "failed to get the keyblock\n"); return; } for( node=keyblock; node; node = node->next ) { if( (mode && node->pkt->pkttype == PKT_PUBLIC_KEY) || ( ( node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) && !cmp_public_keys( node->pkt->pkt.public_key, pk ) ) ) break; } if( !node ) { log_debug("Oops, PK not in keyblock\n"); release_kbnode( keyblock ); return; } /* now find the revocation certificate */ for( node = node->next; node ; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) break; if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class == 0x20 || node->pkt->pkt.signature->sig_class == 0x28 ) ) { /* FIXME: we should check the signature here */ do_show_revocation_reason ( node->pkt->pkt.signature ); break; } } /* We didn't find it, so check if the whole key is revoked */ if(!node && !mode) show_revocation_reason (ctrl, pk, 1); release_kbnode( keyblock ); } /**************** * mode: 0 = standard * 1 = Without key info and additional menu option 'm' * this does also add an option to set the key to ultimately trusted. * Returns: * -2 = nothing changed - caller should show some additional info * -1 = quit operation * 0 = nothing changed * 1 = new ownertrust now in new_trust */ #ifndef NO_TRUST_MODELS static int do_edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode, unsigned *new_trust, int defer_help ) { char *p; u32 keyid[2]; int changed=0; int quit=0; int show=0; int min_num; int did_help=defer_help; unsigned int minimum = tdb_get_min_ownertrust (ctrl, pk, 0); switch(minimum) { default: case TRUST_UNDEFINED: min_num=1; break; case TRUST_NEVER: min_num=2; break; case TRUST_MARGINAL: min_num=3; break; case TRUST_FULLY: min_num=4; break; } keyid_from_pk (pk, keyid); for(;;) { /* A string with valid answers. TRANSLATORS: These are the allowed answers in lower and uppercase. Below you will find the matching strings which should be translated accordingly and the letter changed to match the one in the answer string. i = please show me more information m = back to the main menu s = skip this key q = quit */ const char *ans = _("iImMqQsS"); if( !did_help ) { if( !mode ) { KBNODE keyblock, un; tty_printf (_("No trust value assigned to:\n")); print_key_line (ctrl, NULL, pk, 0); p = get_user_id_native (ctrl, keyid); tty_printf (_(" \"%s\"\n"),p); xfree (p); keyblock = get_pubkeyblock (ctrl, keyid); if (!keyblock) BUG (); for (un=keyblock; un; un = un->next) { if (un->pkt->pkttype != PKT_USER_ID ) continue; if (un->pkt->pkt.user_id->flags.revoked) continue; if (un->pkt->pkt.user_id->flags.expired) continue; /* Only skip textual primaries */ if (un->pkt->pkt.user_id->flags.primary && !un->pkt->pkt.user_id->attrib_data ) continue; if((opt.verify_options&VERIFY_SHOW_PHOTOS) && un->pkt->pkt.user_id->attrib_data) show_photos (ctrl, un->pkt->pkt.user_id->attribs, un->pkt->pkt.user_id->numattribs, pk, un->pkt->pkt.user_id); p=utf8_to_native(un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len,0); tty_printf(_(" aka \"%s\"\n"),p); } print_fingerprint (ctrl, NULL, pk, 2); tty_printf("\n"); release_kbnode (keyblock); } if(opt.trust_model==TM_DIRECT) { tty_printf(_("How much do you trust that this key actually " "belongs to the named user?\n")); tty_printf("\n"); } else { /* This string also used in keyedit.c:trustsig_prompt */ tty_printf(_("Please decide how far you trust this user to" " correctly verify other users' keys\n" "(by looking at passports, checking fingerprints from" " different sources, etc.)\n")); tty_printf("\n"); } if(min_num<=1) tty_printf (_(" %d = I don't know or won't say\n"), 1); if(min_num<=2) tty_printf (_(" %d = I do NOT trust\n"), 2); if(min_num<=3) tty_printf (_(" %d = I trust marginally\n"), 3); if(min_num<=4) tty_printf (_(" %d = I trust fully\n"), 4); if (mode) tty_printf (_(" %d = I trust ultimately\n"), 5); #if 0 /* not yet implemented */ tty_printf (" i = please show me more information\n"); #endif if( mode ) tty_printf(_(" m = back to the main menu\n")); else { tty_printf(_(" s = skip this key\n")); tty_printf(_(" q = quit\n")); } tty_printf("\n"); if(minimum) tty_printf(_("The minimum trust level for this key is: %s\n\n"), trust_value_to_string(minimum)); did_help = 1; } if( strlen(ans) != 8 ) BUG(); p = cpr_get("edit_ownertrust.value",_("Your decision? ")); trim_spaces(p); cpr_kill_prompt(); if( !*p ) did_help = 0; else if( *p && p[1] ) ; else if( !p[1] && ((*p >= '0'+min_num) && *p <= (mode?'5':'4')) ) { unsigned int trust; switch( *p ) { case '1': trust = TRUST_UNDEFINED; break; case '2': trust = TRUST_NEVER ; break; case '3': trust = TRUST_MARGINAL ; break; case '4': trust = TRUST_FULLY ; break; case '5': trust = TRUST_ULTIMATE ; break; default: BUG(); } if (trust == TRUST_ULTIMATE && !cpr_get_answer_is_yes ("edit_ownertrust.set_ultimate.okay", _("Do you really want to set this key" " to ultimate trust? (y/N) "))) ; /* no */ else { *new_trust = trust; changed = 1; break; } } #if 0 /* not yet implemented */ else if( *p == ans[0] || *p == ans[1] ) { tty_printf(_("Certificates leading to an ultimately trusted key:\n")); show = 1; break; } #endif else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) { break ; /* back to the menu */ } else if( !mode && (*p == ans[6] || *p == ans[7] ) ) { break; /* skip */ } else if( !mode && (*p == ans[4] || *p == ans[5] ) ) { quit = 1; break ; /* back to the menu */ } xfree(p); p = NULL; } xfree(p); return show? -2: quit? -1 : changed; } #endif /*!NO_TRUST_MODELS*/ /* * Display a menu to change the ownertrust of the key PK (which should * be a primary key). * For mode values see do_edit_ownertrust () */ #ifndef NO_TRUST_MODELS int edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode ) { unsigned int trust = 0; int no_help = 0; for(;;) { switch ( do_edit_ownertrust (ctrl, pk, mode, &trust, no_help ) ) { case -1: /* quit */ return -1; case -2: /* show info */ no_help = 1; break; case 1: /* trust value set */ trust &= ~TRUST_FLAG_DISABLED; trust |= get_ownertrust (ctrl, pk) & TRUST_FLAG_DISABLED; update_ownertrust (ctrl, pk, trust ); return 1; default: return 0; } } } #endif /*!NO_TRUST_MODELS*/ /**************** * Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL * Returns: true if we trust. */ static int do_we_trust( PKT_public_key *pk, unsigned int trustlevel ) { /* We should not be able to get here with a revoked or expired key */ if(trustlevel & TRUST_FLAG_REVOKED || trustlevel & TRUST_FLAG_SUB_REVOKED || (trustlevel & TRUST_MASK) == TRUST_EXPIRED) BUG(); if( opt.trust_model==TM_ALWAYS ) { if( opt.verbose ) log_info("No trust check due to '--trust-model always' option\n"); return 1; } switch(trustlevel & TRUST_MASK) { default: log_error ("invalid trustlevel %u returned from validation layer\n", trustlevel); /* fall through */ case TRUST_UNKNOWN: case TRUST_UNDEFINED: log_info(_("%s: There is no assurance this key belongs" " to the named user\n"),keystr_from_pk(pk)); return 0; /* no */ case TRUST_MARGINAL: log_info(_("%s: There is limited assurance this key belongs" " to the named user\n"),keystr_from_pk(pk)); return 1; /* yes */ case TRUST_FULLY: if( opt.verbose ) log_info(_("This key probably belongs to the named user\n")); return 1; /* yes */ case TRUST_ULTIMATE: if( opt.verbose ) log_info(_("This key belongs to us\n")); return 1; /* yes */ case TRUST_NEVER: /* This can be returned by TOFU, which can return negative assertions. */ log_info(_("%s: This key is bad! It has been marked as untrusted!\n"), keystr_from_pk(pk)); return 0; /* no */ } return 1; /*NOTREACHED*/ } /**************** * wrapper around do_we_trust, so we can ask whether to use the * key anyway. */ static int do_we_trust_pre (ctrl_t ctrl, PKT_public_key *pk, unsigned int trustlevel ) { int rc; rc = do_we_trust( pk, trustlevel ); if( !opt.batch && !rc ) { print_pubkey_info (ctrl, NULL,pk); print_fingerprint (ctrl, NULL, pk, 2); tty_printf("\n"); if ((trustlevel & TRUST_MASK) == TRUST_NEVER) tty_printf( _("This key is bad! It has been marked as untrusted! If you\n" "*really* know what you are doing, you may answer the next\n" "question with yes.\n")); else tty_printf( _("It is NOT certain that the key belongs to the person named\n" "in the user ID. If you *really* know what you are doing,\n" "you may answer the next question with yes.\n")); tty_printf("\n"); if (is_status_enabled ()) { u32 kid[2]; char *hint_str; keyid_from_pk (pk, kid); hint_str = get_long_user_id_string (ctrl, kid); write_status_text ( STATUS_USERID_HINT, hint_str ); xfree (hint_str); } if( cpr_get_answer_is_yes("untrusted_key.override", _("Use this key anyway? (y/N) ")) ) rc = 1; /* Hmmm: Should we set a flag to tell the user about * his decision the next time he encrypts for this recipient? */ } return rc; } /* Write a TRUST_foo status line inclduing the validation model. */ static void write_trust_status (int statuscode, int trustlevel) { #ifdef NO_TRUST_MODELS write_status (statuscode); #else /* NO_TRUST_MODELS */ int tm; /* For the combined tofu+pgp method, we return the trust model which * was responsible for the trustlevel. */ if (opt.trust_model == TM_TOFU_PGP) tm = (trustlevel & TRUST_FLAG_TOFU_BASED)? TM_TOFU : TM_PGP; else tm = opt.trust_model; write_status_strings (statuscode, "0 ", trust_model_string (tm), NULL); #endif /* NO_TRUST_MODELS */ } /**************** * Check whether we can trust this signature. * Returns an error code if we should not trust this signature. */ int check_signatures_trust (ctrl_t ctrl, PKT_signature *sig) { PKT_public_key *pk = xmalloc_clear( sizeof *pk ); unsigned int trustlevel = TRUST_UNKNOWN; int rc=0; rc = get_pubkey_for_sig (ctrl, pk, sig, NULL); if (rc) { /* this should not happen */ log_error("Ooops; the key vanished - can't check the trust\n"); rc = GPG_ERR_NO_PUBKEY; goto leave; } if ( opt.trust_model==TM_ALWAYS ) { if( !opt.quiet ) log_info(_("WARNING: Using untrusted key!\n")); if (opt.with_fingerprint) print_fingerprint (ctrl, NULL, pk, 1); goto leave; } if(pk->flags.maybe_revoked && !pk->flags.revoked) log_info(_("WARNING: this key might be revoked (revocation key" " not present)\n")); trustlevel = get_validity (ctrl, NULL, pk, NULL, sig, 1); if ( (trustlevel & TRUST_FLAG_REVOKED) ) { write_status( STATUS_KEYREVOKED ); if(pk->flags.revoked == 2) log_info(_("WARNING: This key has been revoked by its" " designated revoker!\n")); else log_info(_("WARNING: This key has been revoked by its owner!\n")); log_info(_(" This could mean that the signature is forged.\n")); show_revocation_reason (ctrl, pk, 0); } else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) { write_status( STATUS_KEYREVOKED ); log_info(_("WARNING: This subkey has been revoked by its owner!\n")); show_revocation_reason (ctrl, pk, 0); } if ((trustlevel & TRUST_FLAG_DISABLED)) log_info (_("Note: This key has been disabled.\n")); /* If we have PKA information adjust the trustlevel. */ if (sig->pka_info && sig->pka_info->valid) { unsigned char fpr[MAX_FINGERPRINT_LEN]; PKT_public_key *primary_pk; size_t fprlen; int okay; primary_pk = xmalloc_clear (sizeof *primary_pk); get_pubkey (ctrl, primary_pk, pk->main_keyid); fingerprint_from_pk (primary_pk, fpr, &fprlen); free_public_key (primary_pk); if ( fprlen == 20 && !memcmp (sig->pka_info->fpr, fpr, 20) ) { okay = 1; write_status_text (STATUS_PKA_TRUST_GOOD, sig->pka_info->email); log_info (_("Note: Verified signer's address is '%s'\n"), sig->pka_info->email); } else { okay = 0; write_status_text (STATUS_PKA_TRUST_BAD, sig->pka_info->email); log_info (_("Note: Signer's address '%s' " "does not match DNS entry\n"), sig->pka_info->email); } switch ( (trustlevel & TRUST_MASK) ) { case TRUST_UNKNOWN: case TRUST_UNDEFINED: case TRUST_MARGINAL: if (okay && opt.verify_options&VERIFY_PKA_TRUST_INCREASE) { trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_FULLY); log_info (_("trustlevel adjusted to FULL" " due to valid PKA info\n")); } /* fall through */ case TRUST_FULLY: if (!okay) { trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_NEVER); log_info (_("trustlevel adjusted to NEVER" " due to bad PKA info\n")); } break; } } /* Now let the user know what up with the trustlevel. */ switch ( (trustlevel & TRUST_MASK) ) { case TRUST_EXPIRED: log_info(_("Note: This key has expired!\n")); print_fingerprint (ctrl, NULL, pk, 1); break; default: log_error ("invalid trustlevel %u returned from validation layer\n", trustlevel); /* fall through */ case TRUST_UNKNOWN: case TRUST_UNDEFINED: write_trust_status (STATUS_TRUST_UNDEFINED, trustlevel); log_info(_("WARNING: This key is not certified with" " a trusted signature!\n")); log_info(_(" There is no indication that the " "signature belongs to the owner.\n" )); print_fingerprint (ctrl, NULL, pk, 1); break; case TRUST_NEVER: /* This level can be returned by TOFU, which supports negative * assertions. */ write_trust_status (STATUS_TRUST_NEVER, trustlevel); log_info(_("WARNING: We do NOT trust this key!\n")); log_info(_(" The signature is probably a FORGERY.\n")); if (opt.with_fingerprint) print_fingerprint (ctrl, NULL, pk, 1); rc = gpg_error (GPG_ERR_BAD_SIGNATURE); break; case TRUST_MARGINAL: write_trust_status (STATUS_TRUST_MARGINAL, trustlevel); log_info(_("WARNING: This key is not certified with" " sufficiently trusted signatures!\n")); log_info(_(" It is not certain that the" " signature belongs to the owner.\n" )); print_fingerprint (ctrl, NULL, pk, 1); break; case TRUST_FULLY: write_trust_status (STATUS_TRUST_FULLY, trustlevel); if (opt.with_fingerprint) print_fingerprint (ctrl, NULL, pk, 1); break; case TRUST_ULTIMATE: write_trust_status (STATUS_TRUST_ULTIMATE, trustlevel); if (opt.with_fingerprint) print_fingerprint (ctrl, NULL, pk, 1); break; } leave: free_public_key( pk ); return rc; } void release_pk_list (pk_list_t pk_list) { PK_LIST pk_rover; for ( ; pk_list; pk_list = pk_rover) { pk_rover = pk_list->next; free_public_key ( pk_list->pk ); xfree ( pk_list ); } } static int key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk) { for( ; pk_list; pk_list = pk_list->next) if (cmp_public_keys(pk_list->pk, pk) == 0) return 0; return -1; } /* * Return a malloced string with a default recipient if there is any * Fixme: We don't distinguish between malloc failure and no-default-recipient. */ static char * default_recipient (ctrl_t ctrl) { PKT_public_key *pk; char *result; if (opt.def_recipient) return xtrystrdup (opt.def_recipient); if (!opt.def_recipient_self) return NULL; pk = xtrycalloc (1, sizeof *pk ); if (!pk) return NULL; if (get_seckey_default (ctrl, pk)) { free_public_key (pk); return NULL; } result = hexfingerprint (pk, NULL, 0); free_public_key (pk); return result; } static int expand_id(const char *id,strlist_t *into,unsigned int flags) { struct groupitem *groups; int count=0; for(groups=opt.grouplist;groups;groups=groups->next) { /* need strcasecmp() here, as this should be localized */ if(strcasecmp(groups->name,id)==0) { strlist_t each,sl; /* this maintains the current utf8-ness */ for(each=groups->values;each;each=each->next) { sl=add_to_strlist(into,each->d); sl->flags=flags; count++; } break; } } return count; } /* For simplicity, and to avoid potential loops, we only expand once - * you can't make an alias that points to an alias. */ static strlist_t expand_group (strlist_t input) { strlist_t output = NULL; strlist_t sl, rover; for (rover = input; rover; rover = rover->next) if (!(rover->flags & PK_LIST_FROM_FILE) && !expand_id(rover->d,&output,rover->flags)) { /* Didn't find any groups, so use the existing string */ sl=add_to_strlist(&output,rover->d); sl->flags=rover->flags; } return output; } /* Helper for build_pk_list to find and check one key. This helper is * also used directly in server mode by the RECIPIENTS command. On * success the new key is added to PK_LIST_ADDR. NAME is the user id * of the key. USE the requested usage and a set MARK_HIDDEN will * mark the key in the updated list as a hidden recipient. If * FROM_FILE is true, NAME is not a user ID but the name of a file * holding a key. */ gpg_error_t find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use, int mark_hidden, int from_file, pk_list_t *pk_list_addr) { int rc; PKT_public_key *pk; KBNODE keyblock = NULL; if (!name || !*name) return gpg_error (GPG_ERR_INV_USER_ID); pk = xtrycalloc (1, sizeof *pk); if (!pk) return gpg_error_from_syserror (); pk->req_usage = use; if (from_file) rc = get_pubkey_fromfile (ctrl, pk, name); else rc = get_best_pubkey_byname (ctrl, GET_PUBKEY_NORMAL, NULL, pk, name, &keyblock, 0); if (rc) { int code; /* Key not found or other error. */ log_error (_("%s: skipped: %s\n"), name, gpg_strerror (rc) ); switch (gpg_err_code (rc)) { case GPG_ERR_NO_SECKEY: case GPG_ERR_NO_PUBKEY: code = 1; break; case GPG_ERR_INV_USER_ID: code = 14; break; default: code = 0; break; } send_status_inv_recp (code, name); free_public_key (pk); return rc; } rc = openpgp_pk_test_algo2 (pk->pubkey_algo, use); if (rc) { /* Key found but not usable for us (e.g. sign-only key). */ release_kbnode (keyblock); send_status_inv_recp (3, name); /* Wrong key usage */ log_error (_("%s: skipped: %s\n"), name, gpg_strerror (rc) ); free_public_key (pk); return rc; } /* Key found and usable. Check validity. */ if (!from_file) { int trustlevel; trustlevel = get_validity (ctrl, keyblock, pk, pk->user_id, NULL, 1); release_kbnode (keyblock); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { /* Key has been disabled. */ send_status_inv_recp (13, name); log_info (_("%s: skipped: public key is disabled\n"), name); free_public_key (pk); return GPG_ERR_UNUSABLE_PUBKEY; } if ( !do_we_trust_pre (ctrl, pk, trustlevel) ) { /* We don't trust this key. */ send_status_inv_recp (10, name); free_public_key (pk); return GPG_ERR_UNUSABLE_PUBKEY; } } /* Skip the actual key if the key is already present in the list. */ if (!key_present_in_pk_list (*pk_list_addr, pk)) { if (!opt.quiet) log_info (_("%s: skipped: public key already present\n"), name); free_public_key (pk); } else { pk_list_t r; r = xtrymalloc (sizeof *r); if (!r) { rc = gpg_error_from_syserror (); free_public_key (pk); return rc; } r->pk = pk; r->next = *pk_list_addr; r->flags = mark_hidden? 1:0; *pk_list_addr = r; } return 0; } /* This is the central function to collect the keys for recipients. * It is thus used to prepare a public key encryption. encrypt-to * keys, default keys and the keys for the actual recipients are all * collected here. When not in batch mode and no recipient has been * passed on the commandline, the function will also ask for * recipients. * * RCPTS is a string list with the recipients; NULL is an allowed * value but not very useful. Group expansion is done on these names; * they may be in any of the user Id formats we can handle. The flags * bits for each string in the string list are used for: * * - PK_LIST_ENCRYPT_TO :: This is an encrypt-to recipient. * - PK_LIST_HIDDEN :: This is a hidden recipient. * - PK_LIST_FROM_FILE :: The argument is a file with a key. * * On success a list of keys is stored at the address RET_PK_LIST; the * caller must free this list. On error the value at this address is * not changed. */ int build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list) { PK_LIST pk_list = NULL; PKT_public_key *pk=NULL; int rc=0; int any_recipients=0; strlist_t rov,remusr; char *def_rec = NULL; char pkstrbuf[PUBKEY_STRING_SIZE]; /* Try to expand groups if any have been defined. */ if (opt.grouplist) remusr = expand_group (rcpts); else remusr = rcpts; /* XXX: Change this function to use get_pubkeys instead of get_pubkey_byname to detect ambiguous key specifications and warn about duplicate keyblocks. For ambiguous key specifications on the command line or provided interactively, prompt the user to select the best key. If a key specification is ambiguous and we are in batch mode, die. */ if (opt.encrypt_to_default_key) { static int warned; const char *default_key = parse_def_secret_key (ctrl); if (default_key) { PK_LIST r = xmalloc_clear (sizeof *r); r->pk = xmalloc_clear (sizeof *r->pk); r->pk->req_usage = PUBKEY_USAGE_ENC; rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL, NULL, r->pk, default_key, NULL, NULL, 0); if (rc) { xfree (r->pk); xfree (r); log_error (_("can't encrypt to '%s'\n"), default_key); if (!opt.quiet) log_info (_("(check argument of option '%s')\n"), "--default-key"); } else { r->next = pk_list; r->flags = 0; pk_list = r; } } else if (opt.def_secret_key) { if (! warned) log_info (_("option '%s' given, but no valid default keys given\n"), "--encrypt-to-default-key"); warned = 1; } else { if (! warned) log_info (_("option '%s' given, but option '%s' not given\n"), "--encrypt-to-default-key", "--default-key"); warned = 1; } } /* Check whether there are any recipients in the list and build the * list of the encrypt-to ones (we always trust them). */ for ( rov = remusr; rov; rov = rov->next ) { if ( !(rov->flags & PK_LIST_ENCRYPT_TO) ) { /* This is a regular recipient; i.e. not an encrypt-to one. */ any_recipients = 1; /* Hidden recipients are not allowed while in PGP mode, issue a warning and switch into GnuPG mode. */ if ((rov->flags & PK_LIST_HIDDEN) && (PGP6 || PGP7 || PGP8)) { log_info(_("option '%s' may not be used in %s mode\n"), "--hidden-recipient", gnupg_compliance_option_string (opt.compliance)); compliance_failure(); } } else if (!opt.no_encrypt_to) { /* --encrypt-to has not been disabled. Check this encrypt-to key. */ pk = xmalloc_clear( sizeof *pk ); pk->req_usage = PUBKEY_USAGE_ENC; /* We explicitly allow encrypt-to to an disabled key; thus we pass 1 for the second last argument and 1 as the last argument to disable AKL. */ if ((rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL, NULL, pk, rov->d, NULL, NULL, 1))) { free_public_key ( pk ); pk = NULL; log_error (_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); send_status_inv_recp (0, rov->d); goto fail; } else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, PUBKEY_USAGE_ENC)) ) { /* Skip the actual key if the key is already present * in the list. Add it to our list if not. */ if (key_present_in_pk_list(pk_list, pk) == 0) { free_public_key (pk); pk = NULL; if (!opt.quiet) log_info (_("%s: skipped: public key already present\n"), rov->d); } else { PK_LIST r; r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = (rov->flags&PK_LIST_HIDDEN)?1:0; pk_list = r; /* Hidden encrypt-to recipients are not allowed while in PGP mode, issue a warning and switch into GnuPG mode. */ if ((r->flags&PK_LIST_ENCRYPT_TO) && (PGP6 || PGP7 || PGP8)) { log_info(_("option '%s' may not be used in %s mode\n"), "--hidden-encrypt-to", gnupg_compliance_option_string (opt.compliance)); compliance_failure(); } } } else { /* The public key is not usable for encryption. */ free_public_key( pk ); pk = NULL; log_error(_("%s: skipped: %s\n"), rov->d, gpg_strerror (rc) ); send_status_inv_recp (3, rov->d); /* Wrong key usage */ goto fail; } } } /* If we don't have any recipients yet and we are not in batch mode drop into interactive selection mode. */ if ( !any_recipients && !opt.batch ) { int have_def_rec; char *answer = NULL; strlist_t backlog = NULL; if (pk_list) any_recipients = 1; def_rec = default_recipient(ctrl); have_def_rec = !!def_rec; if ( !have_def_rec ) tty_printf(_("You did not specify a user ID. (you may use \"-r\")\n")); for (;;) { rc = 0; xfree(answer); if ( have_def_rec ) { /* A default recipient is taken as the first entry. */ answer = def_rec; def_rec = NULL; } else if (backlog) { /* This is part of our trick to expand and display groups. */ answer = strlist_pop (&backlog); } else { /* Show the list of already collected recipients and ask for more. */ PK_LIST iter; tty_printf("\n"); tty_printf(_("Current recipients:\n")); for (iter=pk_list;iter;iter=iter->next) { u32 keyid[2]; keyid_from_pk(iter->pk,keyid); tty_printf ("%s/%s %s \"", pubkey_string (iter->pk, pkstrbuf, sizeof pkstrbuf), keystr(keyid), datestr_from_pk (iter->pk)); if (iter->pk->user_id) tty_print_utf8_string(iter->pk->user_id->name, iter->pk->user_id->len); else { size_t n; char *p = get_user_id (ctrl, keyid, &n, NULL); tty_print_utf8_string ( p, n ); xfree(p); } tty_printf("\"\n"); } answer = cpr_get_utf8("pklist.user_id.enter", _("\nEnter the user ID. " "End with an empty line: ")); trim_spaces(answer); cpr_kill_prompt(); } if ( !answer || !*answer ) { xfree(answer); break; /* No more recipients entered - get out of loop. */ } /* Do group expand here too. The trick here is to continue the loop if any expansion occurred. The code above will then list all expanded keys. */ if (expand_id(answer,&backlog,0)) continue; /* Get and check key for the current name. */ free_public_key (pk); pk = xmalloc_clear( sizeof *pk ); pk->req_usage = PUBKEY_USAGE_ENC; rc = get_pubkey_byname (ctrl, GET_PUBKEY_NORMAL, NULL, pk, answer, NULL, NULL, 0); if (rc) tty_printf(_("No such user ID.\n")); else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, PUBKEY_USAGE_ENC)) ) { if ( have_def_rec ) { /* No validation for a default recipient. */ if (!key_present_in_pk_list(pk_list, pk)) { free_public_key (pk); pk = NULL; log_info (_("skipped: public key " "already set as default recipient\n") ); } else { PK_LIST r = xmalloc (sizeof *r); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing default ids. */ pk_list = r; } any_recipients = 1; continue; } else { /* Check validity of this key. */ int trustlevel; trustlevel = get_validity (ctrl, NULL, pk, pk->user_id, NULL, 1); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { tty_printf (_("Public key is disabled.\n") ); } else if ( do_we_trust_pre (ctrl, pk, trustlevel) ) { /* Skip the actual key if the key is already * present in the list */ if (!key_present_in_pk_list(pk_list, pk)) { free_public_key (pk); pk = NULL; log_info(_("skipped: public key already set\n") ); } else { PK_LIST r; r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing interactive ids. */ pk_list = r; } any_recipients = 1; continue; } } } xfree(def_rec); def_rec = NULL; have_def_rec = 0; } if ( pk ) { free_public_key( pk ); pk = NULL; } } else if ( !any_recipients && (def_rec = default_recipient(ctrl)) ) { /* We are in batch mode and have only a default recipient. */ pk = xmalloc_clear( sizeof *pk ); pk->req_usage = PUBKEY_USAGE_ENC; /* The default recipient is allowed to be disabled; thus pass 1 as second last argument. We also don't want an AKL. */ rc = get_pubkey_byname (ctrl, GET_PUBKEY_NO_AKL, NULL, pk, def_rec, NULL, NULL, 1); if (rc) log_error(_("unknown default recipient \"%s\"\n"), def_rec ); else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, PUBKEY_USAGE_ENC)) ) { /* Mark any_recipients here since the default recipient would have been used if it wasn't already there. It doesn't really matter if we got this key from the default recipient or an encrypt-to. */ any_recipients = 1; if (!key_present_in_pk_list(pk_list, pk)) log_info (_("skipped: public key already set " "as default recipient\n")); else { PK_LIST r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing default ids. */ pk_list = r; } } if ( pk ) { free_public_key( pk ); pk = NULL; } xfree(def_rec); def_rec = NULL; } else { /* General case: Check all keys. */ any_recipients = 0; for (; remusr; remusr = remusr->next ) { if ( (remusr->flags & PK_LIST_ENCRYPT_TO) ) continue; /* encrypt-to keys are already handled. */ rc = find_and_check_key (ctrl, remusr->d, PUBKEY_USAGE_ENC, !!(remusr->flags&PK_LIST_HIDDEN), !!(remusr->flags&PK_LIST_FROM_FILE), &pk_list); if (rc) goto fail; any_recipients = 1; } } if ( !rc && !any_recipients ) { log_error(_("no valid addressees\n")); write_status_text (STATUS_NO_RECP, "0"); rc = GPG_ERR_NO_USER_ID; } #ifdef USE_TOFU if (! rc && (opt.trust_model == TM_TOFU_PGP || opt.trust_model == TM_TOFU)) { PK_LIST iter; for (iter = pk_list; iter; iter = iter->next) { int rc2; /* Note: we already resolved any conflict when looking up the key. Don't annoy the user again if she selected accept once. */ rc2 = tofu_register_encryption (ctrl, iter->pk, NULL, 0); if (rc2) log_info ("WARNING: Failed to register encryption to %s" " with TOFU engine\n", keystr (pk_main_keyid (iter->pk))); else if (DBG_TRUST) log_debug ("Registered encryption to %s with TOFU DB.\n", keystr (pk_main_keyid (iter->pk))); } } #endif /*USE_TOFU*/ fail: if ( rc ) release_pk_list( pk_list ); else *ret_pk_list = pk_list; if (opt.grouplist) free_strlist(remusr); return rc; } /* In pgp6 mode, disallow all ciphers except IDEA (1), 3DES (2), and CAST5 (3), all hashes except MD5 (1), SHA1 (2), and RIPEMD160 (3), and all compressions except none (0) and ZIP (1). pgp7 and pgp8 mode expands the cipher list to include AES128 (7), AES192 (8), AES256 (9), and TWOFISH (10). pgp8 adds the SHA-256 hash (8). For a true PGP key all of this is unneeded as they are the only items present in the preferences subpacket, but checking here covers the weird case of encrypting to a key that had preferences from a different implementation which was then used with PGP. I am not completely comfortable with this as the right thing to do, as it slightly alters the list of what the user is supposedly requesting. It is not against the RFC however, as the preference chosen will never be one that the user didn't specify somewhere ("The implementation may use any mechanism to pick an algorithm in the intersection"), and PGP has no mechanism to fix such a broken preference list, so I'm including it. -dms */ int -algo_available( preftype_t preftype, int algo, const union pref_hint *hint) +algo_available( preftype_t preftype, int algo, const struct pref_hint *hint) { if( preftype == PREFTYPE_SYM ) { if(PGP6 && (algo != CIPHER_ALGO_IDEA && algo != CIPHER_ALGO_3DES && algo != CIPHER_ALGO_CAST5)) return 0; if(PGP7 && (algo != CIPHER_ALGO_IDEA && algo != CIPHER_ALGO_3DES && algo != CIPHER_ALGO_CAST5 && algo != CIPHER_ALGO_AES && algo != CIPHER_ALGO_AES192 && algo != CIPHER_ALGO_AES256 && algo != CIPHER_ALGO_TWOFISH)) return 0; /* PGP8 supports all the ciphers we do.. */ return algo && !openpgp_cipher_test_algo ( algo ); } else if( preftype == PREFTYPE_HASH ) { if (hint && hint->digest_length) { - if (hint->digest_length!=20 || opt.flags.dsa2) + unsigned int n = gcry_md_get_algo_dlen (algo); + + if (hint->exact) + { + /* For example ECDSA requires an exact hash value so + * that we do not truncate. For DSA we allow truncation + * and thus exact is not set. */ + if (hint->digest_length != n) + return 0; + } + else if (hint->digest_length!=20 || opt.flags.dsa2) { /* If --enable-dsa2 is set or the hash isn't 160 bits (which implies DSA2), then we'll accept a hash that is larger than we need. Otherwise we won't accept any hash that isn't exactly the right size. */ - if (hint->digest_length > gcry_md_get_algo_dlen (algo)) + if (hint->digest_length > n) return 0; } - else if (hint->digest_length != gcry_md_get_algo_dlen (algo)) + else if (hint->digest_length != n) return 0; } if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 && algo != DIGEST_ALGO_SHA1 && algo != DIGEST_ALGO_RMD160)) return 0; if(PGP8 && (algo != DIGEST_ALGO_MD5 && algo != DIGEST_ALGO_SHA1 && algo != DIGEST_ALGO_RMD160 && algo != DIGEST_ALGO_SHA256)) return 0; return algo && !openpgp_md_test_algo (algo); } else if( preftype == PREFTYPE_ZIP ) { if((PGP6 || PGP7) && (algo != COMPRESS_ALGO_NONE && algo != COMPRESS_ALGO_ZIP)) return 0; /* PGP8 supports all the compression algos we do */ return !check_compress_algo( algo ); } else return 0; } /**************** * Return -1 if we could not find an algorithm. */ int select_algo_from_prefs(PK_LIST pk_list, int preftype, - int request, const union pref_hint *hint) + int request, const struct pref_hint *hint) { PK_LIST pkr; u32 bits[8]; const prefitem_t *prefs; int result=-1,i; u16 scores[256]; if( !pk_list ) return -1; memset(bits,0xFF,sizeof(bits)); memset(scores,0,sizeof(scores)); for( pkr = pk_list; pkr; pkr = pkr->next ) { u32 mask[8]; int rank=1,implicit=-1; memset(mask,0,sizeof(mask)); switch(preftype) { case PREFTYPE_SYM: /* IDEA is implicitly there for v3 keys with v3 selfsigs if --pgp2 mode is on. This was a 2440 thing that was dropped from 4880 but is still relevant to GPG's 1991 support. All this doesn't mean IDEA is actually available, of course. */ implicit=CIPHER_ALGO_3DES; break; case PREFTYPE_HASH: /* While I am including this code for completeness, note that currently --pgp2 mode locks the hash at MD5, so this code will never even be called. Even if the hash wasn't locked at MD5, we don't support sign+encrypt in --pgp2 mode, and that's the only time PREFTYPE_HASH is used anyway. -dms */ implicit=DIGEST_ALGO_SHA1; break; case PREFTYPE_ZIP: /* Uncompressed is always an option. */ implicit=COMPRESS_ALGO_NONE; } if (pkr->pk->user_id) /* selected by user ID */ prefs = pkr->pk->user_id->prefs; else prefs = pkr->pk->prefs; if( prefs ) { for (i=0; prefs[i].type; i++ ) { if( prefs[i].type == preftype ) { /* Make sure all scores don't add up past 0xFFFF (and roll around) */ if(rank+scores[prefs[i].value]<=0xFFFF) scores[prefs[i].value]+=rank; else scores[prefs[i].value]=0xFFFF; mask[prefs[i].value/32] |= 1<<(prefs[i].value%32); rank++; /* We saw the implicit algorithm, so we don't need tack it on the end ourselves. */ if(implicit==prefs[i].value) implicit=-1; } } } if(rank==1 && preftype==PREFTYPE_ZIP) { /* If the compression preferences are not present, they are assumed to be ZIP, Uncompressed (RFC4880:13.3.1) */ scores[1]=1; /* ZIP is first choice */ scores[0]=2; /* Uncompressed is second choice */ mask[0]|=3; } /* If the key didn't have the implicit algorithm listed explicitly, add it here at the tail of the list. */ if(implicit>-1) { scores[implicit]+=rank; mask[implicit/32] |= 1<<(implicit%32); } for(i=0;i<8;i++) bits[i]&=mask[i]; } /* We've now scored all of the algorithms, and the usable ones have bits set. Let's pick the winner. */ /* The caller passed us a request. Can we use it? */ if(request>-1 && (bits[request/32] & (1<<(request%32))) && algo_available(preftype,request,hint)) result=request; if(result==-1) { /* If we have personal prefs set, use them. */ prefs=NULL; if(preftype==PREFTYPE_SYM && opt.personal_cipher_prefs) prefs=opt.personal_cipher_prefs; else if(preftype==PREFTYPE_HASH && opt.personal_digest_prefs) prefs=opt.personal_digest_prefs; else if(preftype==PREFTYPE_ZIP && opt.personal_compress_prefs) prefs=opt.personal_compress_prefs; if( prefs ) for(i=0; prefs[i].type; i++ ) { if(bits[prefs[i].value/32] & (1<<(prefs[i].value%32)) && algo_available( preftype, prefs[i].value, hint)) { result = prefs[i].value; break; } } } if(result==-1) { unsigned int best=-1; /* At this point, we have not selected an algorithm due to a special request or via personal prefs. Pick the highest ranked algorithm (i.e. the one with the lowest score). */ if(preftype==PREFTYPE_HASH && scores[DIGEST_ALGO_MD5]) { /* "If you are building an authentication system, the recipient may specify a preferred signing algorithm. However, the signer would be foolish to use a weak algorithm simply because the recipient requests it." (RFC4880:14). If any other hash algorithm is available, pretend that MD5 isn't. Note that if the user intentionally chose MD5 by putting it in their personal prefs, then we do what the user said (as we never reach this code). */ for(i=DIGEST_ALGO_MD5+1;i<256;i++) if(scores[i]) { scores[DIGEST_ALGO_MD5]=0; break; } } for(i=0;i<256;i++) { /* Note the '<' here. This means in case of a tie, we will favor the lower algorithm number. We have a choice between the lower number (probably an older algorithm with more time in use), or the higher number (probably a newer algorithm with less time in use). Older is probably safer here, even though the newer algorithms tend to be "stronger". */ if(scores[i] && scores[i]next) { int mdc; if (pkr->pk->user_id) /* selected by user ID */ mdc = pkr->pk->user_id->flags.mdc; else mdc = pkr->pk->flags.mdc; if (!mdc) return 0; /* At least one recipient does not support it. */ } return 1; /* Can be used. */ } /* Print a warning for all keys in PK_LIST missing the MDC feature. */ void warn_missing_mdc_from_pklist (PK_LIST pk_list) { PK_LIST pkr; for (pkr = pk_list; pkr; pkr = pkr->next) { int mdc; if (pkr->pk->user_id) /* selected by user ID */ mdc = pkr->pk->user_id->flags.mdc; else mdc = pkr->pk->flags.mdc; if (!mdc) log_info (_("Note: key %s has no %s feature\n"), keystr_from_pk (pkr->pk), "MDC"); } } void warn_missing_aes_from_pklist (PK_LIST pk_list) { PK_LIST pkr; for (pkr = pk_list; pkr; pkr = pkr->next) { const prefitem_t *prefs; int i; int gotit = 0; prefs = pkr->pk->user_id? pkr->pk->user_id->prefs : pkr->pk->prefs; if (prefs) { for (i=0; !gotit && prefs[i].type; i++ ) if (prefs[i].type == PREFTYPE_SYM && prefs[i].value == CIPHER_ALGO_AES) gotit++; } if (!gotit) log_info (_("Note: key %s has no preference for %s\n"), keystr_from_pk (pkr->pk), "AES"); } } diff --git a/g10/sign.c b/g10/sign.c index b437190af..6a90fe16e 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,1804 +1,1813 @@ /* sign.c - sign data * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2007, 2010, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include "gpg.h" #include "options.h" #include "packet.h" #include "../common/status.h" #include "../common/iobuf.h" #include "keydb.h" #include "../common/util.h" #include "main.h" #include "filter.h" #include "../common/ttyio.h" #include "trustdb.h" #include "../common/status.h" #include "../common/i18n.h" #include "pkglue.h" #include "../common/sysutils.h" #include "call-agent.h" #include "../common/mbox-util.h" #include "../common/compliance.h" #ifdef HAVE_DOSISH_SYSTEM #define LF "\r\n" #else #define LF "\n" #endif /* Bitflags to convey hints on what kind of signayire is created. */ #define SIGNHINT_KEYSIG 1 #define SIGNHINT_SELFSIG 2 /* Hack */ static int recipient_digest_algo=0; /**************** * Create notations and other stuff. It is assumed that the stings in * STRLIST are already checked to contain only printable data and have * a valid NAME=VALUE format. */ static void mk_notation_policy_etc (PKT_signature *sig, PKT_public_key *pk, PKT_public_key *pksk) { const char *string; char *p = NULL; strlist_t pu = NULL; struct notation *nd = NULL; struct expando_args args; log_assert (sig->version >= 4); memset (&args, 0, sizeof(args)); args.pk = pk; args.pksk = pksk; /* Notation data. */ if (IS_SIG(sig) && opt.sig_notations) nd = opt.sig_notations; else if (IS_CERT(sig) && opt.cert_notations) nd = opt.cert_notations; if (nd) { struct notation *item; for (item = nd; item; item = item->next) { item->altvalue = pct_expando (item->value,&args); if (!item->altvalue) log_error (_("WARNING: unable to %%-expand notation " "(too large). Using unexpanded.\n")); } keygen_add_notations (sig, nd); for (item = nd; item; item = item->next) { xfree (item->altvalue); item->altvalue = NULL; } } /* Set policy URL. */ if (IS_SIG(sig) && opt.sig_policy_url) pu = opt.sig_policy_url; else if (IS_CERT(sig) && opt.cert_policy_url) pu = opt.cert_policy_url; for (; pu; pu = pu->next) { string = pu->d; p = pct_expando (string, &args); if (!p) { log_error(_("WARNING: unable to %%-expand policy URL " "(too large). Using unexpanded.\n")); p = xstrdup(string); } build_sig_subpkt (sig, (SIGSUBPKT_POLICY | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)), p, strlen (p)); xfree (p); } /* Preferred keyserver URL. */ if (IS_SIG(sig) && opt.sig_keyserver_url) pu = opt.sig_keyserver_url; for (; pu; pu = pu->next) { string = pu->d; p = pct_expando (string, &args); if (!p) { log_error (_("WARNING: unable to %%-expand preferred keyserver URL" " (too large). Using unexpanded.\n")); p = xstrdup (string); } build_sig_subpkt (sig, (SIGSUBPKT_PREF_KS | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)), p, strlen (p)); xfree (p); } /* Set signer's user id. */ if (IS_SIG (sig) && !opt.flags.disable_signer_uid) { char *mbox; /* For now we use the uid which was used to locate the key. */ if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name))) { if (DBG_LOOKUP) log_debug ("setting Signer's UID to '%s'\n", mbox); build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, mbox, strlen (mbox)); xfree (mbox); } else if (opt.sender_list) { /* If a list of --sender was given we scan that list and use * the first one matching a user id of the current key. */ /* FIXME: We need to get the list of user ids for the PKSK * packet. That requires either a function to look it up * again or we need to extend the key packet struct to link * to the primary key which in turn could link to the user * ids. Too much of a change right now. Let's take just * one from the supplied list and hope that the caller * passed a matching one. */ build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, opt.sender_list->d, strlen (opt.sender_list->d)); } } } /* * Put the Key Block subpakcet into SIG for key PKSK. Returns an * error code on failure. */ static gpg_error_t mk_sig_subpkt_key_block (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pksk) { gpg_error_t err; char *mbox; char *filterexp = NULL; int save_opt_armor = opt.armor; int save_opt_verbose = opt.verbose; char hexfpr[2*MAX_FINGERPRINT_LEN + 1]; void *data = NULL; size_t datalen; kbnode_t keyblock = NULL; push_export_filters (); opt.armor = 0; hexfingerprint (pksk, hexfpr, sizeof hexfpr); /* Get the user id so that we know which one to insert into the * key. */ if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name))) { if (DBG_LOOKUP) log_debug ("including key with UID '%s' (specified)\n", mbox); filterexp = xasprintf ("keep-uid= -- mbox = %s", mbox); xfree (mbox); } else if (opt.sender_list) { /* If --sender was given we use the first one from that list. */ if (DBG_LOOKUP) log_debug ("including key with UID '%s' (--sender)\n", opt.sender_list->d); filterexp = xasprintf ("keep-uid= -- mbox = %s", opt.sender_list->d); } else /* Use the primary user id. */ { if (DBG_LOOKUP) log_debug ("including key with primary UID\n"); filterexp = xstrdup ("keep-uid= primary -t"); } if (DBG_LOOKUP) log_debug ("export filter expression: %s\n", filterexp); err = parse_and_set_export_filter (filterexp); if (err) goto leave; xfree (filterexp); filterexp = xasprintf ("drop-subkey= fpr <> %s && usage !~ e", hexfpr); if (DBG_LOOKUP) log_debug ("export filter expression: %s\n", filterexp); err = parse_and_set_export_filter (filterexp); if (err) goto leave; opt.verbose = 0; err = export_pubkey_buffer (ctrl, hexfpr, EXPORT_MINIMAL|EXPORT_CLEAN, "", 1, /* Prefix with the reserved byte. */ NULL, &keyblock, &data, &datalen); opt.verbose = save_opt_verbose; if (err) { log_error ("failed to get to be included key: %s\n", gpg_strerror (err)); goto leave; } build_sig_subpkt (sig, SIGSUBPKT_KEY_BLOCK, data, datalen); leave: xfree (data); release_kbnode (keyblock); xfree (filterexp); opt.armor = save_opt_armor; pop_export_filters (); return err; } /* * Helper to hash a user ID packet. */ static void hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid) { byte buf[5]; (void)sigversion; if (uid->attrib_data) { buf[0] = 0xd1; /* Indicates an attribute packet. */ buf[1] = uid->attrib_len >> 24; /* Always use 4 length bytes. */ buf[2] = uid->attrib_len >> 16; buf[3] = uid->attrib_len >> 8; buf[4] = uid->attrib_len; } else { buf[0] = 0xb4; /* Indicates a userid packet. */ buf[1] = uid->len >> 24; /* Always use 4 length bytes. */ buf[2] = uid->len >> 16; buf[3] = uid->len >> 8; buf[4] = uid->len; } gcry_md_write( md, buf, 5 ); if (uid->attrib_data) gcry_md_write (md, uid->attrib_data, uid->attrib_len ); else gcry_md_write (md, uid->name, uid->len ); } /* * Helper to hash some parts from the signature */ static void hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig) { byte buf[6]; size_t n; gcry_md_putc (md, sig->version); gcry_md_putc (md, sig->sig_class); gcry_md_putc (md, sig->pubkey_algo); gcry_md_putc (md, sig->digest_algo); if (sig->hashed) { n = sig->hashed->len; gcry_md_putc (md, (n >> 8) ); gcry_md_putc (md, n ); gcry_md_write (md, sig->hashed->data, n ); n += 6; } else { gcry_md_putc (md, 0); /* Always hash the length of the subpacket. */ gcry_md_putc (md, 0); n = 6; } /* Add some magic. */ buf[0] = sig->version; buf[1] = 0xff; buf[2] = n >> 24; /* (n is only 16 bit, so this is always 0) */ buf[3] = n >> 16; buf[4] = n >> 8; buf[5] = n; gcry_md_write (md, buf, 6); } /* Perform the sign operation. If CACHE_NONCE is given the agent is * advised to use that cached passphrase for the key. SIGNHINTS has * hints so that we can do some additional checks. */ static int do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig, gcry_md_hd_t md, int mdalgo, const char *cache_nonce, unsigned int signhints) { gpg_error_t err; byte *dp; char *hexgrip; if (pksk->timestamp > sig->timestamp ) { ulong d = pksk->timestamp - sig->timestamp; log_info (ngettext("key %s was created %lu second" " in the future (time warp or clock problem)\n", "key %s was created %lu seconds" " in the future (time warp or clock problem)\n", d), keystr_from_pk (pksk), d); if (!opt.ignore_time_conflict) return gpg_error (GPG_ERR_TIME_CONFLICT); } print_pubkey_algo_note (pksk->pubkey_algo); if (!mdalgo) mdalgo = gcry_md_get_algo (md); if ((signhints & SIGNHINT_KEYSIG) && !(signhints & SIGNHINT_SELFSIG) && mdalgo == GCRY_MD_SHA1 && !opt.flags.allow_weak_key_signatures) { /* We do not allow the creation of third-party key signatures * using SHA-1 because we also reject them when verifying. Note * that this will render dsa1024 keys unsuitable for such * keysigs and in turn the WoT. */ print_sha1_keysig_rejected_note (); err = gpg_error (GPG_ERR_DIGEST_ALGO); goto leave; } /* Check compliance. */ if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo)) { log_error (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (mdalgo), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_DIGEST_ALGO); goto leave; } if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING, pksk->pubkey_algo, 0, pksk->pkey, nbits_from_pk (pksk), NULL)) { log_error (_("key %s may not be used for signing in %s mode\n"), keystr_from_pk (pksk), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_PUBKEY_ALGO); goto leave; } if (!gnupg_rng_is_compliant (opt.compliance)) { err = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", err); goto leave; } print_digest_algo_note (mdalgo); dp = gcry_md_read (md, mdalgo); sig->digest_algo = mdalgo; sig->digest_start[0] = dp[0]; sig->digest_start[1] = dp[1]; mpi_release (sig->data[0]); sig->data[0] = NULL; mpi_release (sig->data[1]); sig->data[1] = NULL; err = hexkeygrip_from_pk (pksk, &hexgrip); if (!err) { char *desc; gcry_sexp_t s_sigval; desc = gpg_format_keydesc (ctrl, pksk, FORMAT_KEYDESC_NORMAL, 1); err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc, pksk->keyid, pksk->main_keyid, pksk->pubkey_algo, dp, gcry_md_get_algo_dlen (mdalgo), mdalgo, &s_sigval); xfree (desc); if (err) ; else if (pksk->pubkey_algo == GCRY_PK_RSA || pksk->pubkey_algo == GCRY_PK_RSA_S) sig->data[0] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_USG); else if (openpgp_oid_is_ed25519 (pksk->pkey[0])) { sig->data[0] = get_mpi_from_sexp (s_sigval, "r", GCRYMPI_FMT_OPAQUE); sig->data[1] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_OPAQUE); } else { sig->data[0] = get_mpi_from_sexp (s_sigval, "r", GCRYMPI_FMT_USG); sig->data[1] = get_mpi_from_sexp (s_sigval, "s", GCRYMPI_FMT_USG); } gcry_sexp_release (s_sigval); } xfree (hexgrip); leave: if (err) log_error (_("signing failed: %s\n"), gpg_strerror (err)); else { if (opt.verbose) { char *ustr = get_user_id_string_native (ctrl, sig->keyid); log_info (_("%s/%s signature from: \"%s\"\n"), openpgp_pk_algo_name (pksk->pubkey_algo), openpgp_md_algo_name (sig->digest_algo), ustr); xfree (ustr); } } return err; } static int complete_sig (ctrl_t ctrl, PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md, const char *cache_nonce, unsigned int signhints) { int rc; /* if (!(rc = check_secret_key (pksk, 0))) */ rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce, signhints); return rc; } /* Return true if the key seems to be on a version 1 OpenPGP card. This works by asking the agent and may fail if the card has not yet been used with the agent. */ static int openpgp_card_v1_p (PKT_public_key *pk) { gpg_error_t err; int result; /* Shortcut if we are not using RSA: The v1 cards only support RSA thus there is no point in looking any further. */ if (!is_RSA (pk->pubkey_algo)) return 0; if (!pk->flags.serialno_valid) { char *hexgrip; err = hexkeygrip_from_pk (pk, &hexgrip); if (err) { log_error ("error computing a keygrip: %s\n", gpg_strerror (err)); return 0; /* Ooops. */ } xfree (pk->serialno); agent_get_keyinfo (NULL, hexgrip, &pk->serialno, NULL); xfree (hexgrip); pk->flags.serialno_valid = 1; } if (!pk->serialno) result = 0; /* Error from a past agent_get_keyinfo or no card. */ else { /* The version number of the card is included in the serialno. */ result = !strncmp (pk->serialno, "D2760001240101", 14); } return result; } /* Get a matching hash algorithm for DSA and ECDSA. */ static int match_dsa_hash (unsigned int qbytes) { if (qbytes <= 20) return DIGEST_ALGO_SHA1; if (qbytes <= 28) return DIGEST_ALGO_SHA224; if (qbytes <= 32) return DIGEST_ALGO_SHA256; if (qbytes <= 48) return DIGEST_ALGO_SHA384; if (qbytes <= 66 ) /* 66 corresponds to 521 (64 to 512) */ return DIGEST_ALGO_SHA512; return DEFAULT_DIGEST_ALGO; /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong answer we have if a digest larger than 512 bits is requested. */ } /* First try --digest-algo. If that isn't set, see if the recipient has a preferred algorithm (which is also filtered through --personal-digest-prefs). If we're making a signature without a particular recipient (i.e. signing, rather than signing+encrypting) then take the first algorithm in --personal-digest-prefs that is usable for the pubkey algorithm. If --personal-digest-prefs isn't set, then take the OpenPGP default (i.e. SHA-1). Note that Ed25519+EdDSA takes an input of arbitrary length and thus we don't enforce any particular algorithm like we do for standard ECDSA. However, we use SHA256 as the default algorithm. Possible improvement: Use the highest-ranked usable algorithm from the signing key prefs either before or after using the personal list? */ static int hash_for (PKT_public_key *pk) { if (opt.def_digest_algo) { return opt.def_digest_algo; } else if (recipient_digest_algo && !is_weak_digest (recipient_digest_algo)) { return recipient_digest_algo; } else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && openpgp_oid_is_ed25519 (pk->pkey[0])) { if (opt.personal_digest_prefs) return opt.personal_digest_prefs[0].value; else return DIGEST_ALGO_SHA256; } else if (pk->pubkey_algo == PUBKEY_ALGO_DSA || pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]); if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA) qbytes = ecdsa_qbits_from_Q (qbytes); qbytes = qbytes/8; /* It's a DSA key, so find a hash that is the same size as q or larger. If q is 160, assume it is an old DSA key and use a 160-bit hash unless --enable-dsa2 is set, in which case act like a new DSA key that just happens to have a 160-bit q (i.e. allow truncation). If q is not 160, by definition it must be a new DSA key. We ignore the personal_digest_prefs for ECDSA because they should always macth the curve and truncated hashes are not useful either. Even worse, smartcards may reject non matching hash lengths for curves (e.g. using SHA-512 with brainpooolP385r1 on a Yubikey). */ if (pk->pubkey_algo == PUBKEY_ALGO_DSA && opt.personal_digest_prefs) { prefitem_t *prefs; if (qbytes != 20 || opt.flags.dsa2) { for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) if (gcry_md_get_algo_dlen (prefs->value) >= qbytes) return prefs->value; } else { for (prefs=opt.personal_digest_prefs; prefs->type; prefs++) if (gcry_md_get_algo_dlen (prefs->value) == qbytes) return prefs->value; } } return match_dsa_hash(qbytes); } else if (openpgp_card_v1_p (pk)) { /* The sk lives on a smartcard, and old smartcards only handle SHA-1 and RIPEMD/160. Newer smartcards (v2.0) don't have this restriction anymore. Fortunately the serial number encodes the version of the card and thus we know that this key is on a v1 card. */ if(opt.personal_digest_prefs) { prefitem_t *prefs; for (prefs=opt.personal_digest_prefs;prefs->type;prefs++) if (prefs->value==DIGEST_ALGO_SHA1 || prefs->value==DIGEST_ALGO_RMD160) return prefs->value; } return DIGEST_ALGO_SHA1; } else if (opt.personal_digest_prefs) { /* It's not DSA, so we can use whatever the first hash algorithm is in the pref list */ return opt.personal_digest_prefs[0].value; } else return DEFAULT_DIGEST_ALGO; } static void print_status_sig_created (PKT_public_key *pk, PKT_signature *sig, int what) { byte array[MAX_FINGERPRINT_LEN]; char buf[100+MAX_FINGERPRINT_LEN*2]; size_t n; snprintf (buf, sizeof buf - 2*MAX_FINGERPRINT_LEN, "%c %d %d %02x %lu ", what, sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp ); fingerprint_from_pk (pk, array, &n); bin2hex (array, n, buf + strlen (buf)); write_status_text( STATUS_SIG_CREATED, buf ); } /* * Loop over the secret certificates in SK_LIST and build the one pass * signature packets. OpenPGP says that the data should be bracket by * the onepass-sig and signature-packet; so we build these onepass * packet here in reverse order */ static int write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass ) { int skcount; SK_LIST sk_rover; for (skcount=0, sk_rover=sk_list; sk_rover; sk_rover = sk_rover->next) skcount++; for (; skcount; skcount--) { PKT_public_key *pk; PKT_onepass_sig *ops; PACKET pkt; int i, rc; for (i=0, sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { if (++i == skcount) break; } pk = sk_rover->pk; ops = xmalloc_clear (sizeof *ops); ops->sig_class = sigclass; ops->digest_algo = hash_for (pk); ops->pubkey_algo = pk->pubkey_algo; keyid_from_pk (pk, ops->keyid); ops->last = (skcount == 1); init_packet(&pkt); pkt.pkttype = PKT_ONEPASS_SIG; pkt.pkt.onepass_sig = ops; rc = build_packet (out, &pkt); free_packet (&pkt, NULL); if (rc) { log_error ("build onepass_sig packet failed: %s\n", gpg_strerror (rc)); return rc; } } return 0; } /* * Helper to write the plaintext (literal data) packet */ static int write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) { PKT_plaintext *pt = NULL; u32 filesize; int rc = 0; if (!opt.no_literal) pt=setup_plaintext_name(fname,inp); /* try to calculate the length of the data */ if ( !iobuf_is_pipe_filename (fname) && *fname ) { off_t tmpsize; int overflow; if( !(tmpsize = iobuf_get_filelength(inp, &overflow)) && !overflow && opt.verbose) log_info (_("WARNING: '%s' is an empty file\n"), fname); /* We can't encode the length of very large files because OpenPGP uses only 32 bit for file sizes. So if the size of a file is larger than 2^32 minus some bytes for packet headers, we switch to partial length encoding. */ if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; /* Because the text_filter modifies the length of the * data, it is not possible to know the used length * without a double read of the file - to avoid that * we simple use partial length packets. */ if ( ptmode == 't' || ptmode == 'u' || ptmode == 'm') filesize = 0; } else filesize = opt.set_filesize? opt.set_filesize : 0; /* stdin */ if (!opt.no_literal) { PACKET pkt; /* Note that PT has been initialized above in no_literal mode. */ pt->timestamp = make_timestamp (); pt->mode = ptmode; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; init_packet(&pkt); pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; /*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/ if( (rc = build_packet (out, &pkt)) ) log_error ("build_packet(PLAINTEXT) failed: %s\n", gpg_strerror (rc) ); pt->buf = NULL; free_packet (&pkt, NULL); } else { byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1) if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) { log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); break; } wipememory(copy_buffer,4096); /* burn buffer */ } /* fixme: it seems that we never freed pt/pkt */ return rc; } /* * Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized * hash which will not be changes here. */ static int write_signature_packets (ctrl_t ctrl, SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, int sigclass, u32 timestamp, u32 duration, int status_letter, const char *cache_nonce) { SK_LIST sk_rover; /* Loop over the certificates with secret keys. */ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) { PKT_public_key *pk; PKT_signature *sig; gcry_md_hd_t md; gpg_error_t err; pk = sk_rover->pk; /* Build the signature packet. */ sig = xtrycalloc (1, sizeof *sig); if (!sig) return gpg_error_from_syserror (); if (duration || opt.sig_policy_url || opt.sig_notations || opt.sig_keyserver_url) sig->version = 4; else sig->version = pk->version; keyid_from_pk (pk, sig->keyid); sig->digest_algo = hash_for (pk); sig->pubkey_algo = pk->pubkey_algo; if (timestamp) sig->timestamp = timestamp; else sig->timestamp = make_timestamp(); if (duration) sig->expiredate = sig->timestamp + duration; sig->sig_class = sigclass; if (gcry_md_copy (&md, hash)) BUG (); if (sig->version >= 4) { build_sig_subpkt_from_sig (sig, pk); mk_notation_policy_etc (sig, NULL, pk); if (opt.flags.include_key_block && IS_SIG (sig)) err = mk_sig_subpkt_key_block (ctrl, sig, pk); else err = 0; } hash_sigversion_to_magic (md, sig); gcry_md_final (md); if (!err) err = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0); gcry_md_close (md); if (!err) { /* Write the packet. */ PACKET pkt; init_packet (&pkt); pkt.pkttype = PKT_SIGNATURE; pkt.pkt.signature = sig; err = build_packet (out, &pkt); if (!err && is_status_enabled()) print_status_sig_created (pk, sig, status_letter); free_packet (&pkt, NULL); if (err) log_error ("build signature packet failed: %s\n", gpg_strerror (err)); } else free_seckey_enc (sig); if (err) return err; } return 0; } /**************** * Sign the files whose names are in FILENAME. * If DETACHED has the value true, * make a detached signature. If FILENAMES->d is NULL read from stdin * and ignore the detached mode. Sign the file with all secret keys * which can be taken from LOCUSR, if this is NULL, use the default one * If ENCRYPTFLAG is true, use REMUSER (or ask if it is NULL) to encrypt the - * signed data for these users. + * signed data for these users. If ENCRYPTFLAG is 2 symmetric encryption + * is also used. * If OUTFILE is not NULL; this file is used for output and the function * does not ask for overwrite permission; output is then always * uncompressed, non-armored and in binary mode. */ int sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, int encryptflag, strlist_t remusr, const char *outfile ) { const char *fname; armor_filter_context_t *afx; compress_filter_context_t zfx; md_filter_context_t mfx; text_filter_context_t tfx; progress_filter_context_t *pfx; encrypt_filter_context_t efx; IOBUF inp = NULL, out = NULL; PACKET pkt; int rc = 0; PK_LIST pk_list = NULL; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; int multifile = 0; u32 duration=0; pfx = new_progress_context (); afx = new_armor_context (); memset( &zfx, 0, sizeof zfx); memset( &mfx, 0, sizeof mfx); memset( &efx, 0, sizeof efx); efx.ctrl = ctrl; init_packet( &pkt ); if( filenames ) { fname = filenames->d; multifile = !!filenames->next; } else fname = NULL; if( fname && filenames->next && (!detached || encryptflag) ) log_bug("multiple files can only be detached signed"); if(encryptflag==2 && (rc=setup_symkey(&efx.symkey_s2k,&efx.symkey_dek))) goto leave; if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval(1,opt.def_sig_expire); else duration = parse_expire_string(opt.def_sig_expire); /* Note: In the old non-agent version the following call used to unprotect the secret key. This is now done on demand by the agent. */ if( (rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) ) goto leave; if (encryptflag && (rc=build_pk_list (ctrl, remusr, &pk_list))) goto leave; /* prepare iobufs */ if( multifile ) /* have list of filenames */ inp = NULL; /* we do it later */ else { inp = iobuf_open(fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if( !inp ) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); goto leave; } handle_progress (pfx, inp, fname); } if( outfile ) { if (is_secured_filename ( outfile )) { out = NULL; gpg_err_set_errno (EPERM); } else out = iobuf_create (outfile, 0); if( !out ) { rc = gpg_error_from_syserror (); log_error(_("can't create '%s': %s\n"), outfile, strerror(errno) ); goto leave; } else if( opt.verbose ) log_info(_("writing to '%s'\n"), outfile ); } else if( (rc = open_outfile (-1, fname, opt.armor? 1: detached? 2:0, 0, &out))) goto leave; /* prepare to calculate the MD over the input */ if( opt.textmode && !outfile && !multifile ) { memset( &tfx, 0, sizeof tfx); iobuf_push_filter( inp, text_filter, &tfx ); } if ( gcry_md_open (&mfx.md, 0, 0) ) BUG (); if (DBG_HASHING) gcry_md_debug (mfx.md, "sign"); /* If we're encrypting and signing, it is reasonable to pick the hash algorithm to use out of the recipient key prefs. This is best effort only, as in a DSA2 and smartcard world there are cases where we cannot please everyone with a single hash (DSA2 wants >160 and smartcards want =160). In the future this could be more complex with different hashes for each sk, but the current design requires a single hash for all SKs. */ if(pk_list) { if(opt.def_digest_algo) { if(!opt.expert && select_algo_from_prefs(pk_list,PREFTYPE_HASH, opt.def_digest_algo, NULL)!=opt.def_digest_algo) - log_info(_("WARNING: forcing digest algorithm %s (%d)" - " violates recipient preferences\n"), - gcry_md_algo_name (opt.def_digest_algo), - opt.def_digest_algo ); + log_info(_("WARNING: forcing digest algorithm %s (%d)" + " violates recipient preferences\n"), + gcry_md_algo_name (opt.def_digest_algo), + opt.def_digest_algo ); } else { - int algo, smartcard=0; - union pref_hint hint; - - hint.digest_length = 0; + int algo; + int conflict = 0; + struct pref_hint hint = { 0 }; /* Of course, if the recipient asks for something unreasonable (like the wrong hash for a DSA key) then don't do it. Check all sk's - if any are DSA or live on a smartcard, then the hash has restrictions and we may not be able to give the recipient what they want. For DSA, pass a hint for the largest q we have. Note that this means that a q>160 key will override a q=160 key and force the use of truncation for the q=160 key. The alternative would be to ignore the recipient prefs completely and get a different hash for each DSA key in hash_for(). The override behavior here is more or less reasonable as it is under the control of the user which keys they sign with for a given message and the fact that the message with multiple signatures won't be usable on an implementation that doesn't understand DSA2 anyway. */ for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { int temp_hashlen = (gcry_mpi_get_nbits (sk_rover->pk->pkey[1])); if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) - temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen); - temp_hashlen = (temp_hashlen+7)/8; + { + temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen); + if (!temp_hashlen) + conflict = 1; /* Better don't use the prefs. */ + temp_hashlen = (temp_hashlen+7)/8; + /* Fixup for that funny nistp521 (yes, 521) + * were we need to use a 512 bit hash algo. */ + if (temp_hashlen == 66) + temp_hashlen = 64; + } + else + temp_hashlen = (temp_hashlen+7)/8; /* Pick a hash that is large enough for our - largest q */ - - if (hint.digest_lengthpk->pubkey_algo == PUBKEY_ALGO_ECDSA) + { + if (hint.exact) + conflict = 1; + hint.exact = 1; + } + hint.digest_length = temp_hashlen; + } } - /* FIXME: need to check gpg-agent for this. */ - /* else if (sk_rover->pk->is_protected */ - /* && sk_rover->pk->protect.s2k.mode == 1002) */ - /* smartcard = 1; */ } - /* Current smartcards only do 160-bit hashes. If we have - to have a >160-bit hash, then we can't use the - recipient prefs as we'd need both =160 and >160 at the - same time and recipient prefs currently require a - single hash for all signatures. All this may well have - to change as the cards add algorithms. */ - - if ((!smartcard || (smartcard && hint.digest_length==20)) - && (algo = select_algo_from_prefs(pk_list,PREFTYPE_HASH, - -1,&hint)) > 0) + if (!conflict + && (algo = select_algo_from_prefs (pk_list,PREFTYPE_HASH, + -1,&hint)) > 0) { /* Note that we later check that the algo is not weak. */ recipient_digest_algo = algo; } } } for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); if( !multifile ) iobuf_push_filter( inp, md_filter, &mfx ); if( detached && !encryptflag) afx->what = 2; if( opt.armor && !outfile ) push_armor_filter (afx, out); if( encryptflag ) { efx.pk_list = pk_list; /* fixme: set efx.cfx.datalen if known */ iobuf_push_filter( out, encrypt_filter, &efx ); } if (opt.compress_algo && !outfile && !detached) { int compr_algo=opt.compress_algo; /* If not forced by user */ if(compr_algo==-1) { /* If we're not encrypting, then select_algo_from_prefs will fail and we'll end up with the default. If we are encrypting, select_algo_from_prefs cannot fail since there is an assumed preference for uncompressed data. Still, if it did fail, we'll also end up with the default. */ if((compr_algo= select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1) compr_algo=default_compress_algo(); } else if(!opt.expert && pk_list && select_algo_from_prefs(pk_list,PREFTYPE_ZIP, compr_algo,NULL)!=compr_algo) log_info(_("WARNING: forcing compression algorithm %s (%d)" " violates recipient preferences\n"), compress_algo_to_string(compr_algo),compr_algo); /* algo 0 means no compression */ if( compr_algo ) push_compress_filter(out,&zfx,compr_algo); } /* Write the one-pass signature packets if needed */ if (!detached) { rc = write_onepass_sig_packets (sk_list, out, opt.textmode && !outfile ? 0x01:0x00); if (rc) goto leave; } write_status_begin_signing (mfx.md); /* Setup the inner packet. */ if( detached ) { if( multifile ) { strlist_t sl; if( opt.verbose ) log_info(_("signing:") ); /* must walk reverse trough this list */ for( sl = strlist_last(filenames); sl; sl = strlist_prev( filenames, sl ) ) { inp = iobuf_open(sl->d); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if( !inp ) { rc = gpg_error_from_syserror (); log_error(_("can't open '%s': %s\n"), sl->d,strerror(errno)); goto leave; } handle_progress (pfx, inp, sl->d); if( opt.verbose ) log_printf (" '%s'", sl->d ); if(opt.textmode) { memset( &tfx, 0, sizeof tfx); iobuf_push_filter( inp, text_filter, &tfx ); } iobuf_push_filter( inp, md_filter, &mfx ); while( iobuf_get(inp) != -1 ) ; iobuf_close(inp); inp = NULL; } if( opt.verbose ) log_printf ("\n"); } else { /* read, so that the filter can calculate the digest */ while( iobuf_get(inp) != -1 ) ; } } else { rc = write_plaintext_packet (out, inp, fname, opt.textmode && !outfile ? (opt.mimemode? 'm':'t'):'b'); } /* catch errors from above */ if (rc) goto leave; /* write the signatures */ rc = write_signature_packets (ctrl, sk_list, out, mfx.md, opt.textmode && !outfile? 0x01 : 0x00, 0, duration, detached ? 'D':'S', NULL); if( rc ) goto leave; leave: if( rc ) iobuf_cancel(out); else { iobuf_close(out); if (encryptflag) write_status( STATUS_END_ENCRYPTION ); } iobuf_close(inp); gcry_md_close ( mfx.md ); release_sk_list( sk_list ); release_pk_list( pk_list ); recipient_digest_algo=0; release_progress_context (pfx); release_armor_context (afx); return rc; } /**************** * make a clear signature. note that opt.armor is not needed */ int clearsign_file (ctrl_t ctrl, const char *fname, strlist_t locusr, const char *outfile ) { armor_filter_context_t *afx; progress_filter_context_t *pfx; gcry_md_hd_t textmd = NULL; IOBUF inp = NULL, out = NULL; PACKET pkt; int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; u32 duration=0; pfx = new_progress_context (); afx = new_armor_context (); init_packet( &pkt ); if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval (1,opt.def_sig_expire); else duration = parse_expire_string (opt.def_sig_expire); /* Note: In the old non-agent version the following call used to unprotect the secret key. This is now done on demand by the agent. */ if( (rc=build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) ) goto leave; /* prepare iobufs */ inp = iobuf_open(fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if( !inp ) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); goto leave; } handle_progress (pfx, inp, fname); if( outfile ) { if (is_secured_filename (outfile) ) { outfile = NULL; gpg_err_set_errno (EPERM); } else out = iobuf_create (outfile, 0); if( !out ) { rc = gpg_error_from_syserror (); log_error(_("can't create '%s': %s\n"), outfile, strerror(errno) ); goto leave; } else if( opt.verbose ) log_info(_("writing to '%s'\n"), outfile ); } else if ((rc = open_outfile (-1, fname, 1, 0, &out))) goto leave; iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF ); { const char *s; int any = 0; byte hashs_seen[256]; memset( hashs_seen, 0, sizeof hashs_seen ); iobuf_writestr(out, "Hash: " ); for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { int i = hash_for (sk_rover->pk); if( !hashs_seen[ i & 0xff ] ) { s = gcry_md_algo_name ( i ); if( s ) { hashs_seen[ i & 0xff ] = 1; if( any ) iobuf_put(out, ',' ); iobuf_writestr(out, s ); any = 1; } } } log_assert(any); iobuf_writestr(out, LF ); } if( opt.not_dash_escaped ) iobuf_writestr( out, "NotDashEscaped: You need "GPG_NAME " to verify this message" LF ); iobuf_writestr(out, LF ); if ( gcry_md_open (&textmd, 0, 0) ) BUG (); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (textmd, hash_for(sk_rover->pk)); if ( DBG_HASHING ) gcry_md_debug ( textmd, "clearsign" ); copy_clearsig_text (out, inp, textmd, !opt.not_dash_escaped, opt.escape_from); /* fixme: check for read errors */ /* now write the armor */ afx->what = 2; push_armor_filter (afx, out); /* Write the signatures. */ rc = write_signature_packets (ctrl, sk_list, out, textmd, 0x01, 0, duration, 'C', NULL); if( rc ) goto leave; leave: if( rc ) iobuf_cancel(out); else iobuf_close(out); iobuf_close(inp); gcry_md_close ( textmd ); release_sk_list( sk_list ); release_progress_context (pfx); release_armor_context (afx); return rc; } /* * Sign and conventionally encrypt the given file. * FIXME: Far too much code is duplicated - revamp the whole file. */ int sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr) { armor_filter_context_t *afx; progress_filter_context_t *pfx; compress_filter_context_t zfx; md_filter_context_t mfx; text_filter_context_t tfx; cipher_filter_context_t cfx; IOBUF inp = NULL, out = NULL; PACKET pkt; STRING2KEY *s2k = NULL; int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; int algo; u32 duration=0; int canceled; pfx = new_progress_context (); afx = new_armor_context (); memset( &zfx, 0, sizeof zfx); memset( &mfx, 0, sizeof mfx); memset( &tfx, 0, sizeof tfx); memset( &cfx, 0, sizeof cfx); init_packet( &pkt ); if (opt.ask_sig_expire && !opt.batch) duration = ask_expire_interval (1, opt.def_sig_expire); else duration = parse_expire_string (opt.def_sig_expire); /* Note: In the old non-agent version the following call used to unprotect the secret key. This is now done on demand by the agent. */ rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG); if (rc) goto leave; /* prepare iobufs */ inp = iobuf_open(fname); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if( !inp ) { rc = gpg_error_from_syserror (); log_error (_("can't open '%s': %s\n"), fname? fname: "[stdin]", strerror(errno) ); goto leave; } handle_progress (pfx, inp, fname); /* prepare key */ s2k = xmalloc_clear( sizeof *s2k ); s2k->mode = opt.s2k_mode; s2k->hash_algo = S2K_DIGEST_ALGO; algo = default_cipher_algo(); if (!opt.quiet || !opt.batch) log_info (_("%s encryption will be used\n"), openpgp_cipher_algo_name (algo) ); cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled); if (!cfx.dek || !cfx.dek->keylen) { rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE); log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc) ); goto leave; } cfx.dek->use_mdc = use_mdc (NULL, cfx.dek->algo); /* now create the outfile */ rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out); if (rc) goto leave; /* prepare to calculate the MD over the input */ if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); if ( gcry_md_open (&mfx.md, 0, 0) ) BUG (); if ( DBG_HASHING ) gcry_md_debug (mfx.md, "symc-sign"); for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) gcry_md_enable (mfx.md, hash_for (sk_rover->pk)); iobuf_push_filter (inp, md_filter, &mfx); /* Push armor output filter */ if (opt.armor) push_armor_filter (afx, out); /* Write the symmetric key packet */ /*(current filters: armor)*/ { PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; enc->s2k = *s2k; pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if( (rc = build_packet( out, &pkt )) ) log_error("build symkey packet failed: %s\n", gpg_strerror (rc) ); xfree(enc); } /* Push the encryption filter */ iobuf_push_filter( out, cipher_filter, &cfx ); /* Push the compress filter */ if (default_compress_algo()) { if (cfx.dek && cfx.dek->use_mdc) zfx.new_ctb = 1; push_compress_filter (out, &zfx,default_compress_algo() ); } /* Write the one-pass signature packets */ /*(current filters: zip - encrypt - armor)*/ rc = write_onepass_sig_packets (sk_list, out, opt.textmode? 0x01:0x00); if (rc) goto leave; write_status_begin_signing (mfx.md); /* Pipe data through all filters; i.e. write the signed stuff */ /*(current filters: zip - encrypt - armor)*/ rc = write_plaintext_packet (out, inp, fname, opt.textmode ? (opt.mimemode?'m':'t'):'b'); if (rc) goto leave; /* Write the signatures */ /*(current filters: zip - encrypt - armor)*/ rc = write_signature_packets (ctrl, sk_list, out, mfx.md, opt.textmode? 0x01 : 0x00, 0, duration, 'S', NULL); if( rc ) goto leave; leave: if( rc ) iobuf_cancel(out); else { iobuf_close(out); write_status( STATUS_END_ENCRYPTION ); } iobuf_close(inp); release_sk_list( sk_list ); gcry_md_close( mfx.md ); xfree(cfx.dek); xfree(s2k); release_progress_context (pfx); release_armor_context (afx); return rc; } /**************** * Create a v4 signature in *RET_SIG. * * PK is the primary key to sign (required for all sigs) * UID is the user id to sign (required for 0x10..0x13, 0x30) * SUBPK is subkey to sign (required for 0x18, 0x19, 0x28) * * PKSK is the signing key * * SIGCLASS is the type of signature to create. * * DIGEST_ALGO is the digest algorithm. If it is 0 the function * selects an appropriate one. * * TIMESTAMP is the timestamp to use for the signature. 0 means "now" * * DURATION is the amount of time (in seconds) until the signature * expires. * * This function creates the following subpackets: issuer, created, * and expire (if duration is not 0). Additional subpackets can be * added using MKSUBPKT, which is called after these subpackets are * added and before the signature is generated. OPAQUE is passed to * MKSUBPKT. */ int make_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int sigclass, int digest_algo, u32 timestamp, u32 duration, int (*mksubpkt)(PKT_signature *, void *), void *opaque, const char *cache_nonce) { PKT_signature *sig; int rc=0; int sigversion; gcry_md_hd_t md; u32 pk_keyid[2], pksk_keyid[2]; unsigned int signhints; log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x30 || sigclass == 0x28 ); sigversion = 4; if (sigversion < pksk->version) sigversion = pksk->version; if( !digest_algo ) { /* Basically, this means use SHA1 always unless the user specified something (use whatever they said), or it's DSA (use the best match). They still can't pick an inappropriate hash for DSA or the signature will fail. Note that this still allows the caller of make_keysig_packet to override the user setting if it must. */ if(opt.cert_digest_algo) digest_algo=opt.cert_digest_algo; else if(pksk->pubkey_algo == PUBKEY_ALGO_DSA) digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); else if (pksk->pubkey_algo == PUBKEY_ALGO_ECDSA || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) { if (openpgp_oid_is_ed25519 (pksk->pkey[0])) digest_algo = DIGEST_ALGO_SHA256; else digest_algo = match_dsa_hash (ecdsa_qbits_from_Q (gcry_mpi_get_nbits (pksk->pkey[1]))/8); } else digest_algo = DEFAULT_DIGEST_ALGO; } signhints = SIGNHINT_KEYSIG; keyid_from_pk (pk, pk_keyid); keyid_from_pk (pksk, pksk_keyid); if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) signhints |= SIGNHINT_SELFSIG; if ( gcry_md_open (&md, digest_algo, 0 ) ) BUG (); /* Hash the public key certificate. */ hash_public_key( md, pk ); if( sigclass == 0x18 || sigclass == 0x19 || sigclass == 0x28 ) { /* hash the subkey binding/backsig/revocation */ hash_public_key( md, subpk ); } else if( sigclass != 0x1F && sigclass != 0x20 ) { /* hash the user id */ hash_uid (md, sigversion, uid); } /* and make the signature packet */ sig = xmalloc_clear( sizeof *sig ); sig->version = sigversion; sig->flags.exportable=1; sig->flags.revocable=1; keyid_from_pk (pksk, sig->keyid); sig->pubkey_algo = pksk->pubkey_algo; sig->digest_algo = digest_algo; if(timestamp) sig->timestamp=timestamp; else sig->timestamp=make_timestamp(); if(duration) sig->expiredate=sig->timestamp+duration; sig->sig_class = sigclass; build_sig_subpkt_from_sig (sig, pksk); mk_notation_policy_etc (sig, pk, pksk); /* Crucial that the call to mksubpkt comes LAST before the calls to finalize the sig as that makes it possible for the mksubpkt function to get a reliable pointer to the subpacket area. */ if (mksubpkt) rc = (*mksubpkt)( sig, opaque ); if( !rc ) { hash_sigversion_to_magic (md, sig); gcry_md_final (md); rc = complete_sig (ctrl, sig, pksk, md, cache_nonce, signhints); } gcry_md_close (md); if( rc ) free_seckey_enc( sig ); else *ret_sig = sig; return rc; } /**************** * Create a new signature packet based on an existing one. * Only user ID signatures are supported for now. * PK is the public key to work on. * PKSK is the key used to make the signature. * * TODO: Merge this with make_keysig_packet. */ gpg_error_t update_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_signature *orig_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int (*mksubpkt)(PKT_signature *, void *), void *opaque) { PKT_signature *sig; gpg_error_t rc = 0; int digest_algo; gcry_md_hd_t md; u32 pk_keyid[2], pksk_keyid[2]; unsigned int signhints; if ((!orig_sig || !pk || !pksk) || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid) || (orig_sig->sig_class == 0x18 && !subpk)) return GPG_ERR_GENERAL; if ( opt.cert_digest_algo ) digest_algo = opt.cert_digest_algo; else if (pksk->pubkey_algo == PUBKEY_ALGO_DSA || pksk->pubkey_algo == PUBKEY_ALGO_ECDSA || pksk->pubkey_algo == PUBKEY_ALGO_EDDSA) digest_algo = orig_sig->digest_algo; else if (orig_sig->digest_algo == DIGEST_ALGO_SHA1 || orig_sig->digest_algo == DIGEST_ALGO_RMD160) digest_algo = DEFAULT_DIGEST_ALGO; else digest_algo = orig_sig->digest_algo; signhints = SIGNHINT_KEYSIG; keyid_from_pk (pk, pk_keyid); keyid_from_pk (pksk, pksk_keyid); if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1]) signhints |= SIGNHINT_SELFSIG; if ( gcry_md_open (&md, digest_algo, 0 ) ) BUG (); /* Hash the public key certificate and the user id. */ hash_public_key( md, pk ); if( orig_sig->sig_class == 0x18 ) hash_public_key( md, subpk ); else hash_uid (md, orig_sig->version, uid); /* create a new signature packet */ sig = copy_signature (NULL, orig_sig); sig->digest_algo=digest_algo; /* We need to create a new timestamp so that new sig expiration calculations are done correctly... */ sig->timestamp=make_timestamp(); /* ... but we won't make a timestamp earlier than the existing one. */ { int tmout = 0; while(sig->timestamp<=orig_sig->timestamp) { if (++tmout > 5 && !opt.ignore_time_conflict) { rc = gpg_error (GPG_ERR_TIME_CONFLICT); goto leave; } gnupg_sleep (1); sig->timestamp=make_timestamp(); } } /* Note that already expired sigs will remain expired (with a duration of 1) since build-packet.c:build_sig_subpkt_from_sig detects this case. */ /* Put the updated timestamp into the sig. Note that this will automagically lower any sig expiration dates to correctly correspond to the differences in the timestamps (i.e. the duration will shrink). */ build_sig_subpkt_from_sig (sig, pksk); if (mksubpkt) rc = (*mksubpkt)(sig, opaque); if (!rc) { hash_sigversion_to_magic (md, sig); gcry_md_final (md); rc = complete_sig (ctrl, sig, pksk, md, NULL, signhints); } leave: gcry_md_close (md); if( rc ) free_seckey_enc (sig); else *ret_sig = sig; return rc; }