diff --git a/g10/build-packet.c b/g10/build-packet.c index 86d42efe1..0115d64a1 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -1,1701 +1,1696 @@ /* build-packet.c - assemble packets and write them * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2010, 2011 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 "util.h" #include "packet.h" #include "status.h" #include "iobuf.h" #include "i18n.h" #include "options.h" #include "host2net.h" static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); static int do_key (iobuf_t out, int ctb, PKT_public_key *pk); static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); static u32 calc_plaintext( PKT_plaintext *pt ); static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ); static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ); static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ); static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ); static int do_signature( IOBUF out, int ctb, PKT_signature *sig ); static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ); static int calc_header_length( u32 len, int new_ctb ); static int write_16(IOBUF inp, u16 a); static int write_32(IOBUF inp, u32 a); static int write_header( IOBUF out, int ctb, u32 len ); static int write_sign_packet_header( IOBUF out, int ctb, u32 len ); static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen ); static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ); /* Returns 1 if CTB is a new format ctb and 0 if CTB is an old format ctb. */ static int ctb_new_format_p (int ctb) { /* Bit 7 must always be set. */ log_assert ((ctb & (1 << 7))); /* Bit 6 indicates whether the packet is a new format packet. */ return (ctb & (1 << 6)); } /* Extract the packet type from a CTB. */ static int ctb_pkttype (int ctb) { if (ctb_new_format_p (ctb)) /* Bits 0 through 5 are the packet type. */ return (ctb & ((1 << 6) - 1)); else /* Bits 2 through 5 are the packet type. */ return (ctb & ((1 << 6) - 1)) >> 2; } /**************** * Build a packet and write it to INP * Returns: 0 := okay * >0 := error * Note: Caller must free the packet */ int build_packet( IOBUF out, PACKET *pkt ) { int new_ctb=0, rc=0, ctb; int pkttype; if( DBG_PACKET ) log_debug("build_packet() type=%d\n", pkt->pkttype ); log_assert( pkt->pkt.generic ); switch ((pkttype = pkt->pkttype)) { case PKT_PUBLIC_KEY: if (pkt->pkt.public_key->seckey_info) pkttype = PKT_SECRET_KEY; break; case PKT_PUBLIC_SUBKEY: if (pkt->pkt.public_key->seckey_info) pkttype = PKT_SECRET_SUBKEY; break; case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break; case PKT_USER_ID: if( pkt->pkt.user_id->attrib_data ) pkttype = PKT_ATTRIBUTE; break; default: break; } if( new_ctb || pkttype > 15 ) /* new format */ ctb = 0xc0 | (pkttype & 0x3f); else ctb = 0x80 | ((pkttype & 15)<<2); switch( pkttype ) { case PKT_ATTRIBUTE: case PKT_USER_ID: rc = do_user_id( out, ctb, pkt->pkt.user_id ); break; case PKT_OLD_COMMENT: case PKT_COMMENT: /* Ignore these. Theoretically, this will never be called as we have no way to output comment packets any longer, but just in case there is some code path that would end up outputting a comment that was written before comments were dropped (in the public key?) this is a no-op. */ break; case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_KEY: case PKT_SECRET_SUBKEY: case PKT_SECRET_KEY: rc = do_key (out, ctb, pkt->pkt.public_key); break; case PKT_SYMKEY_ENC: rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc ); break; case PKT_PUBKEY_ENC: rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc ); break; case PKT_PLAINTEXT: rc = do_plaintext( out, ctb, pkt->pkt.plaintext ); break; case PKT_ENCRYPTED: rc = do_encrypted( out, ctb, pkt->pkt.encrypted ); break; case PKT_ENCRYPTED_MDC: rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted ); break; case PKT_COMPRESSED: rc = do_compressed( out, ctb, pkt->pkt.compressed ); break; case PKT_SIGNATURE: rc = do_signature( out, ctb, pkt->pkt.signature ); break; case PKT_ONEPASS_SIG: rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig ); break; case PKT_RING_TRUST: break; /* ignore it (keyring.c does write it directly)*/ case PKT_MDC: /* we write it directly, so we should never see it here. */ default: log_bug("invalid packet type in build_packet()\n"); break; } return rc; } /* * Write the mpi A to OUT. */ gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a) { int rc; if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; const unsigned char *p; unsigned char lenhdr[2]; /* gcry_log_debugmpi ("a", a); */ p = gcry_mpi_get_opaque (a, &nbits); if (p) { /* Strip leading zero bits. */ for (; nbits >= 8 && !*p; p++, nbits -= 8) ; if (nbits >= 8 && !(*p & 0x80)) if (--nbits >= 7 && !(*p & 0x40)) if (--nbits >= 6 && !(*p & 0x20)) if (--nbits >= 5 && !(*p & 0x10)) if (--nbits >= 4 && !(*p & 0x08)) if (--nbits >= 3 && !(*p & 0x04)) if (--nbits >= 2 && !(*p & 0x02)) if (--nbits >= 1 && !(*p & 0x01)) --nbits; } /* gcry_log_debug (" [%u bit]\n", nbits); */ /* gcry_log_debughex (" ", p, (nbits+7)/8); */ lenhdr[0] = nbits >> 8; lenhdr[1] = nbits; rc = iobuf_write (out, lenhdr, 2); if (!rc && p) rc = iobuf_write (out, p, (nbits+7)/8); } else { char buffer[(MAX_EXTERN_MPI_BITS+7)/8+2]; /* 2 is for the mpi length. */ size_t nbytes; nbytes = DIM(buffer); rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); if( !rc ) rc = iobuf_write( out, buffer, nbytes ); else if (gpg_err_code(rc) == GPG_ERR_TOO_SHORT ) { log_info ("mpi too large (%u bits)\n", gcry_mpi_get_nbits (a)); /* The buffer was too small. We better tell the user about the MPI. */ rc = gpg_error (GPG_ERR_TOO_LARGE); } } return rc; } /* * Write an opaque MPI to the output stream without length info. */ gpg_error_t gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a) { int rc; if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; const void *p; p = gcry_mpi_get_opaque (a, &nbits); rc = p ? iobuf_write (out, p, (nbits+7)/8) : 0; } else rc = gpg_error (GPG_ERR_BAD_MPI); return rc; } /* Calculate the length of a packet described by PKT. */ u32 calc_packet_length( PACKET *pkt ) { u32 n=0; int new_ctb = 0; log_assert (pkt->pkt.generic); switch( pkt->pkttype ) { case PKT_PLAINTEXT: n = calc_plaintext( pkt->pkt.plaintext ); new_ctb = pkt->pkt.plaintext->new_ctb; break; case PKT_ATTRIBUTE: case PKT_USER_ID: case PKT_COMMENT: case PKT_PUBLIC_KEY: case PKT_SECRET_KEY: case PKT_SYMKEY_ENC: case PKT_PUBKEY_ENC: case PKT_ENCRYPTED: case PKT_SIGNATURE: case PKT_ONEPASS_SIG: case PKT_RING_TRUST: case PKT_COMPRESSED: default: log_bug("invalid packet type in calc_packet_length()"); break; } n += calc_header_length(n, new_ctb); return n; } static gpg_error_t write_fake_data (IOBUF out, gcry_mpi_t a) { unsigned int n; void *p; if (!a) return 0; if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) return 0; /* e.g. due to generating a key with wrong usage. */ p = gcry_mpi_get_opaque ( a, &n); if (!p) return 0; /* For example due to a read error in parse-packet.c:read_rest. */ return iobuf_write (out, p, (n+7)/8 ); } /* Serialize the user id (RFC 4880, Section 5.11) or the user attribute UID (Section 5.12) and write it to OUT. CTB is the serialization's CTB. It specifies the header format and the packet's type. The header length must not be set. */ static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { int rc; log_assert (ctb_pkttype (ctb) == PKT_USER_ID || ctb_pkttype (ctb) == PKT_ATTRIBUTE); if (uid->attrib_data) { write_header(out, ctb, uid->attrib_len); rc = iobuf_write( out, uid->attrib_data, uid->attrib_len ); } else { write_header2( out, ctb, uid->len, 0 ); rc = iobuf_write( out, uid->name, uid->len ); } return rc; } /* Serialize the key (RFC 4880, Section 5.5) described by PK and write it to OUT. This function serializes both primary keys and subkeys with or without a secret part. CTB is the serialization's CTB. It specifies the header format and the packet's type. The header length must not be set. PK->VERSION specifies the serialization format. A value of 0 means to use the default version. Currently, only version 4 packets are supported. */ static int do_key (iobuf_t out, int ctb, PKT_public_key *pk) { gpg_error_t err = 0; /* The length of the body is stored in the packet's header, which occurs before the body. Unfortunately, we don't know the length of the packet's body until we've written all of the data! To work around this, we first write the data into this temporary buffer, then generate the header, and finally copy the contents of this buffer to OUT. */ iobuf_t a = iobuf_temp(); int i, nskey, npkey; log_assert (pk->version == 0 || pk->version == 4); log_assert (ctb_pkttype (ctb) == PKT_PUBLIC_KEY || ctb_pkttype (ctb) == PKT_PUBLIC_SUBKEY || ctb_pkttype (ctb) == PKT_SECRET_KEY || ctb_pkttype (ctb) == PKT_SECRET_SUBKEY); /* Write the version number - if none is specified, use 4 */ if ( !pk->version ) iobuf_put ( a, 4 ); else iobuf_put ( a, pk->version ); write_32 (a, pk->timestamp ); iobuf_put (a, pk->pubkey_algo ); /* Get number of secret and public parameters. They are held in one array: the public ones followed by the secret ones. */ nskey = pubkey_get_nskey (pk->pubkey_algo); npkey = pubkey_get_npkey (pk->pubkey_algo); /* If we don't have any public parameters - which is for example the case if we don't know the algorithm used - the parameters are stored as one blob in a faked (opaque) MPI. */ if (!npkey) { write_fake_data (a, pk->pkey[0]); goto leave; } log_assert (npkey < nskey); for (i=0; i < npkey; i++ ) { if ( (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && (i == 0)) || (pk->pubkey_algo == PUBKEY_ALGO_EDDSA && (i == 0)) || (pk->pubkey_algo == PUBKEY_ALGO_ECDH && (i == 0 || i == 2))) err = gpg_mpi_write_nohdr (a, pk->pkey[i]); else err = gpg_mpi_write (a, pk->pkey[i]); if (err) goto leave; } if (pk->seckey_info) { /* This is a secret key packet. */ struct seckey_info *ski = pk->seckey_info; /* Build the header for protected (encrypted) secret parameters. */ if (ski->is_protected) { /* OpenPGP protection according to rfc2440. */ iobuf_put (a, ski->sha1chk? 0xfe : 0xff); iobuf_put (a, ski->algo); if (ski->s2k.mode >= 1000) { /* These modes are not possible in OpenPGP, we use them to implement our extensions, 101 can be viewed as a private/experimental extension (this is not specified in rfc2440 but the same scheme is used for all other algorithm identifiers). */ iobuf_put (a, 101); iobuf_put (a, ski->s2k.hash_algo); iobuf_write (a, "GNU", 3 ); iobuf_put (a, ski->s2k.mode - 1000); } else { iobuf_put (a, ski->s2k.mode); iobuf_put (a, ski->s2k.hash_algo); } if (ski->s2k.mode == 1 || ski->s2k.mode == 3) iobuf_write (a, ski->s2k.salt, 8); if (ski->s2k.mode == 3) iobuf_put (a, ski->s2k.count); /* For our special modes 1001, 1002 we do not need an IV. */ if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002) iobuf_write (a, ski->iv, ski->ivlen); } else /* Not protected. */ iobuf_put (a, 0 ); if (ski->s2k.mode == 1001) ; /* GnuPG extension - don't write a secret key at all. */ else if (ski->s2k.mode == 1002) { /* GnuPG extension - divert to OpenPGP smartcard. */ /* Length of the serial number or 0 for no serial number. */ iobuf_put (a, ski->ivlen ); /* The serial number gets stored in the IV field. */ iobuf_write (a, ski->iv, ski->ivlen); } else if (ski->is_protected) { /* The secret key is protected - write it out as it is. */ byte *p; unsigned int ndatabits; log_assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE)); p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits); if (p) iobuf_write (a, p, (ndatabits+7)/8 ); } else { /* Non-protected key. */ for ( ; i < nskey; i++ ) if ( (err = gpg_mpi_write (a, pk->pkey[i]))) goto leave; write_16 (a, ski->csum ); } } leave: if (!err) { /* Build the header of the packet - which we must do after writing all the other stuff, so that we know the length of the packet */ write_header2 (out, ctb, iobuf_get_temp_length(a), 0); /* And finally write it out to the real stream. */ err = iobuf_write_temp (out, a); } iobuf_close (a); /* Close the temporary buffer */ return err; } /* Serialize the symmetric-key encrypted session key packet (RFC 4880, 5.3) described by ENC and write it to OUT. CTB is the serialization's CTB. It specifies the header format and the packet's type. The header length must not be set. */ static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ) { int rc = 0; IOBUF a = iobuf_temp(); log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC); /* The only acceptable version. */ log_assert( enc->version == 4 ); /* RFC 4880, Section 3.7. */ switch( enc->s2k.mode ) { /* Simple S2K. */ case 0: /* Salted S2K. */ case 1: /* Iterated and salted S2K. */ case 3: /* Reasonable values. */ break; default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode ); } iobuf_put( a, enc->version ); iobuf_put( a, enc->cipher_algo ); iobuf_put( a, enc->s2k.mode ); iobuf_put( a, enc->s2k.hash_algo ); if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) { iobuf_write(a, enc->s2k.salt, 8 ); if( enc->s2k.mode == 3 ) iobuf_put(a, enc->s2k.count); } if( enc->seskeylen ) iobuf_write(a, enc->seskey, enc->seskeylen ); write_header(out, ctb, iobuf_get_temp_length(a) ); rc = iobuf_write_temp( out, a ); iobuf_close(a); return rc; } /* Serialize the public-key encrypted session key packet (RFC 4880, 5.1) described by ENC and write it to OUT. CTB is the serialization's CTB. It specifies the header format and the packet's type. The header length must not be set. */ static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) { int rc = 0; int n, i; IOBUF a = iobuf_temp(); log_assert (ctb_pkttype (ctb) == PKT_PUBKEY_ENC); iobuf_put (a, 3); /* Version. */ if ( enc->throw_keyid ) { write_32(a, 0 ); /* Don't tell Eve who can decrypt the message. */ write_32(a, 0 ); } else { write_32(a, enc->keyid[0] ); write_32(a, enc->keyid[1] ); } iobuf_put(a,enc->pubkey_algo ); n = pubkey_get_nenc( enc->pubkey_algo ); if ( !n ) write_fake_data( a, enc->data[0] ); for (i=0; i < n && !rc ; i++ ) { if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1) rc = gpg_mpi_write_nohdr (a, enc->data[i]); else rc = gpg_mpi_write (a, enc->data[i]); } if (!rc) { write_header (out, ctb, iobuf_get_temp_length(a) ); rc = iobuf_write_temp (out, a); } iobuf_close(a); return rc; } /* Calculate the length of the serialized plaintext packet PT (RFC 4480, Section 5.9). */ static u32 calc_plaintext( PKT_plaintext *pt ) { /* Truncate namelen to the maximum 255 characters. Note this means that a function that calls build_packet with an illegal literal packet will get it back legalized. */ if(pt->namelen>255) pt->namelen=255; return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0; } /* Serialize the plaintext packet (RFC 4880, 5.9) described by PT and write it to OUT. The body of the message is stored in PT->BUF. The amount of data to write is PT->LEN. (PT->BUF should be configured to return EOF after this much data has been read.) If PT->LEN is 0 and CTB indicates that this is a new format packet, then partial block mode is assumed to have been enabled on OUT. On success, partial block mode is disabled. If PT->BUF is NULL, the the caller must write out the data. In this case, if PT->LEN was 0, then partial body length mode was enabled and the caller must disable it by calling iobuf_set_partial_body_length_mode (out, 0). */ static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) { int rc = 0; size_t nbytes; log_assert (ctb_pkttype (ctb) == PKT_PLAINTEXT); write_header(out, ctb, calc_plaintext( pt ) ); log_assert (pt->mode == 'b' || pt->mode == 't' || pt->mode == 'u' || pt->mode == 'm' || pt->mode == 'l' || pt->mode == '1'); iobuf_put(out, pt->mode ); iobuf_put(out, pt->namelen ); iobuf_write (out, pt->name, pt->namelen); rc = write_32(out, pt->timestamp ); if (rc) return rc; if (pt->buf) { nbytes = iobuf_copy (out, pt->buf); if(ctb_new_format_p (ctb) && !pt->len) /* Turn off partial body length mode. */ iobuf_set_partial_body_length_mode (out, 0); if( pt->len && nbytes != pt->len ) log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n", (ulong)nbytes, (ulong)pt->len ); } return rc; } /* Serialize the symmetrically encrypted data packet (RFC 4880, Section 5.7) described by ED and write it to OUT. Note: this only writes the packets header! The call must then follow up and write the initial random data and the body to OUT. (If you use the encryption iobuf filter (cipher_filter), then this is done automatically.) */ static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; log_assert (! ed->mdc_method); log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED); n = ed->len ? (ed->len + ed->extralen) : 0; write_header(out, ctb, n ); /* This is all. The caller has to write the real data */ return rc; } /* Serialize the symmetrically encrypted integrity protected data packet (RFC 4880, Section 5.13) described by ED and write it to OUT. Note: this only writes the packet's header! The caller must then follow up and write the initial random data, the body and the MDC packet to OUT. (If you use the encryption iobuf filter (cipher_filter), then this is done automatically.) */ static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed ) { int rc = 0; u32 n; log_assert (ed->mdc_method); log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED_MDC); /* Take version number and the following MDC packet in account. */ n = ed->len ? (ed->len + ed->extralen + 1 + 22) : 0; write_header(out, ctb, n ); iobuf_put(out, 1 ); /* version */ /* This is all. The caller has to write the real data */ return rc; } /* Serialize the compressed packet (RFC 4880, Section 5.6) described by CD and write it to OUT. Note: this only writes the packet's header! The caller must then follow up and write the body to OUT. */ static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) { int rc = 0; log_assert (ctb_pkttype (ctb) == PKT_COMPRESSED); /* We must use the old convention and don't use blockmode for the sake of PGP 2 compatibility. However if the new_ctb flag was set, CTB is already formatted as new style and write_header2 does create a partial length encoding using new the new style. */ write_header2(out, ctb, 0, 0); iobuf_put(out, cd->algorithm ); /* This is all. The caller has to write the real data */ return rc; } /**************** * Delete all subpackets of type REQTYPE and return a bool whether a packet * was deleted. */ int delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) { int buflen; sigsubpkttype_t type; byte *buffer, *bufstart; size_t n; size_t unused = 0; int okay = 0; if( !area ) return 0; buflen = area->len; buffer = area->data; for(;;) { if( !buflen ) { okay = 1; break; } bufstart = buffer; n = *buffer++; buflen--; if( n == 255 ) { if( buflen < 4 ) break; n = buf32_to_size_t (buffer); buffer += 4; buflen -= 4; } else if( n >= 192 ) { if( buflen < 2 ) break; n = (( n - 192 ) << 8) + *buffer + 192; buffer++; buflen--; } if( buflen < n ) break; type = *buffer & 0x7f; if( type == reqtype ) { buffer++; buflen--; n--; if( n > buflen ) break; buffer += n; /* point to next subpkt */ buflen -= n; memmove (bufstart, buffer, buflen); /* shift */ unused += buffer - bufstart; buffer = bufstart; } else { buffer += n; buflen -=n; } } if (!okay) log_error ("delete_subpkt: buffer shorter than subpacket\n"); log_assert (unused <= area->len); area->len -= unused; return !!unused; } /**************** * Create or update a signature subpacket for SIG of TYPE. This * functions knows where to put the data (hashed or unhashed). The * function may move data from the unhashed part to the hashed one. * Note: All pointers into sig->[un]hashed (e.g. returned by * parse_sig_subpkt) are not valid after a call to this function. The * data to put into the subpaket should be in a buffer with a length * of buflen. */ void build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ) { byte *p; int critical, hashed; subpktarea_t *oldarea, *newarea; size_t nlen, n, n0; critical = (type & SIGSUBPKT_FLAG_CRITICAL); type &= ~SIGSUBPKT_FLAG_CRITICAL; /* Sanity check buffer sizes */ if(parse_one_sig_subpkt(buffer,buflen,type)<0) BUG(); switch(type) { case SIGSUBPKT_NOTATION: case SIGSUBPKT_POLICY: case SIGSUBPKT_REV_KEY: case SIGSUBPKT_SIGNATURE: /* we do allow multiple subpackets */ break; default: /* we don't allow multiple subpackets */ delete_sig_subpkt(sig->hashed,type); delete_sig_subpkt(sig->unhashed,type); break; } /* Any special magic that needs to be done for this type so the packet doesn't need to be reparsed? */ switch(type) { case SIGSUBPKT_NOTATION: sig->flags.notation=1; break; case SIGSUBPKT_POLICY: sig->flags.policy_url=1; break; case SIGSUBPKT_PREF_KS: sig->flags.pref_ks=1; break; case SIGSUBPKT_EXPORTABLE: if(buffer[0]) sig->flags.exportable=1; else sig->flags.exportable=0; break; case SIGSUBPKT_REVOCABLE: if(buffer[0]) sig->flags.revocable=1; else sig->flags.revocable=0; break; case SIGSUBPKT_TRUST: sig->trust_depth=buffer[0]; sig->trust_value=buffer[1]; break; case SIGSUBPKT_REGEXP: sig->trust_regexp=buffer; break; /* This should never happen since we don't currently allow creating such a subpacket, but just in case... */ case SIGSUBPKT_SIG_EXPIRE: if(buf32_to_u32(buffer)+sig->timestamp<=make_timestamp()) sig->flags.expired=1; else sig->flags.expired=0; break; default: break; } if( (buflen+1) >= 8384 ) nlen = 5; /* write 5 byte length header */ else if( (buflen+1) >= 192 ) nlen = 2; /* write 2 byte length header */ else nlen = 1; /* just a 1 byte length header */ switch( type ) { /* The issuer being unhashed is a historical oddity. It should work equally as well hashed. Of course, if even an unhashed issuer is tampered with, it makes it awfully hard to verify the sig... */ case SIGSUBPKT_ISSUER: case SIGSUBPKT_SIGNATURE: hashed = 0; break; default: hashed = 1; break; } if( critical ) type |= SIGSUBPKT_FLAG_CRITICAL; oldarea = hashed? sig->hashed : sig->unhashed; /* Calculate new size of the area and allocate */ n0 = oldarea? oldarea->len : 0; n = n0 + nlen + 1 + buflen; /* length, type, buffer */ if (oldarea && n <= oldarea->size) { /* fits into the unused space */ newarea = oldarea; /*log_debug ("updating area for type %d\n", type );*/ } else if (oldarea) { newarea = xrealloc (oldarea, sizeof (*newarea) + n - 1); newarea->size = n; /*log_debug ("reallocating area for type %d\n", type );*/ } else { newarea = xmalloc (sizeof (*newarea) + n - 1); newarea->size = n; /*log_debug ("allocating area for type %d\n", type );*/ } newarea->len = n; p = newarea->data + n0; if (nlen == 5) { *p++ = 255; *p++ = (buflen+1) >> 24; *p++ = (buflen+1) >> 16; *p++ = (buflen+1) >> 8; *p++ = (buflen+1); *p++ = type; memcpy (p, buffer, buflen); } else if (nlen == 2) { *p++ = (buflen+1-192) / 256 + 192; *p++ = (buflen+1-192) % 256; *p++ = type; memcpy (p, buffer, buflen); } else { *p++ = buflen+1; *p++ = type; memcpy (p, buffer, buflen); } if (hashed) sig->hashed = newarea; else sig->unhashed = newarea; } /* * Put all the required stuff from SIG into subpackets of sig. * PKSK is the signing key. * Hmmm, should we delete those subpackets which are in a wrong area? */ void build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk) { u32 u; byte buf[1+MAX_FINGERPRINT_LEN]; size_t fprlen; /* For v4 keys we need to write the ISSUER subpacket. We do not * want that for a future v5 format. */ if (pksk->version < 5) { u = sig->keyid[0]; buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; buf[2] = (u >> 8) & 0xff; buf[3] = u & 0xff; u = sig->keyid[1]; buf[4] = (u >> 24) & 0xff; buf[5] = (u >> 16) & 0xff; buf[6] = (u >> 8) & 0xff; buf[7] = u & 0xff; build_sig_subpkt (sig, SIGSUBPKT_ISSUER, buf, 8); } - /* For a future v5 keys we write the ISSUER_FPR subpacket. We - * also write that for a v4 key is experimental support for - * RFC4880bis is requested. */ - if (pksk->version > 4 || opt.flags.rfc4880bis) + /* Write the new ISSUER_FPR subpacket. */ + fingerprint_from_pk (pksk, buf+1, &fprlen); + if (fprlen == 20) { - fingerprint_from_pk (pksk, buf+1, &fprlen); - if (fprlen == 20) - { - buf[0] = pksk->version; - build_sig_subpkt (sig, SIGSUBPKT_ISSUER_FPR, buf, 21); - } + buf[0] = pksk->version; + build_sig_subpkt (sig, SIGSUBPKT_ISSUER_FPR, buf, 21); } /* Write the timestamp. */ u = sig->timestamp; buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; buf[2] = (u >> 8) & 0xff; buf[3] = u & 0xff; build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 ); if(sig->expiredate) { if(sig->expiredate>sig->timestamp) u=sig->expiredate-sig->timestamp; else u=1; /* A 1-second expiration time is the shortest one OpenPGP has */ buf[0] = (u >> 24) & 0xff; buf[1] = (u >> 16) & 0xff; buf[2] = (u >> 8) & 0xff; buf[3] = u & 0xff; /* Mark this CRITICAL, so if any implementation doesn't understand sigs that can expire, it'll just disregard this sig altogether. */ build_sig_subpkt( sig, SIGSUBPKT_SIG_EXPIRE | SIGSUBPKT_FLAG_CRITICAL, buf, 4 ); } } void build_attribute_subpkt(PKT_user_id *uid,byte type, const void *buf,u32 buflen, const void *header,u32 headerlen) { byte *attrib; int idx; if(1+headerlen+buflen>8383) idx=5; else if(1+headerlen+buflen>191) idx=2; else idx=1; /* realloc uid->attrib_data to the right size */ uid->attrib_data=xrealloc(uid->attrib_data, uid->attrib_len+idx+1+headerlen+buflen); attrib=&uid->attrib_data[uid->attrib_len]; if(idx==5) { attrib[0]=255; attrib[1]=(1+headerlen+buflen) >> 24; attrib[2]=(1+headerlen+buflen) >> 16; attrib[3]=(1+headerlen+buflen) >> 8; attrib[4]=1+headerlen+buflen; } else if(idx==2) { attrib[0]=(1+headerlen+buflen-192) / 256 + 192; attrib[1]=(1+headerlen+buflen-192) % 256; } else attrib[0]=1+headerlen+buflen; /* Good luck finding a JPEG this small! */ attrib[idx++]=type; /* Tack on our data at the end */ if(headerlen>0) memcpy(&attrib[idx],header,headerlen); memcpy(&attrib[idx+headerlen],buf,buflen); uid->attrib_len+=idx+headerlen+buflen; } /* Returns a human-readable string corresponding to the notation. This ignores notation->value. The caller must free the result. */ static char * notation_value_to_human_readable_string (struct notation *notation) { if(notation->bdat) /* Binary data. */ { size_t len = notation->blen; int i; char preview[20]; for (i = 0; i < len && i < sizeof (preview) - 1; i ++) if (isprint (notation->bdat[i])) preview[i] = notation->bdat[i]; else preview[i] = '?'; preview[i] = 0; return xasprintf (_("[ not human readable (%zu bytes: %s%s) ]"), len, preview, i < len ? "..." : ""); } else /* The value is human-readable. */ return xstrdup (notation->value); } /* Turn the notation described by the string STRING into a notation. STRING has the form: - -name - Delete the notation. - name@domain.name=value - Normal notation - !name@domain.name=value - Notation with critical bit set. The caller must free the result using free_notation(). */ struct notation * string_to_notation(const char *string,int is_utf8) { const char *s; int saw_at=0; struct notation *notation; notation=xmalloc_clear(sizeof(*notation)); if(*string=='-') { notation->flags.ignore=1; string++; } if(*string=='!') { notation->flags.critical=1; string++; } /* If and when the IETF assigns some official name tags, we'll have to add them here. */ for( s=string ; *s != '='; s++ ) { if( *s=='@') saw_at++; /* -notationname is legal without an = sign */ if(!*s && notation->flags.ignore) break; if( !*s || !isascii (*s) || (!isgraph(*s) && !isspace(*s)) ) { log_error(_("a notation name must have only printable characters" " or spaces, and end with an '='\n") ); goto fail; } } notation->name=xmalloc((s-string)+1); strncpy(notation->name,string,s-string); notation->name[s-string]='\0'; if(!saw_at && !opt.expert) { log_error(_("a user notation name must contain the '@' character\n")); goto fail; } if (saw_at > 1) { log_error(_("a notation name must not contain more than" " one '@' character\n")); goto fail; } if(*s) { const char *i=s+1; int highbit=0; /* we only support printable text - therefore we enforce the use of only printable characters (an empty value is valid) */ for(s++; *s ; s++ ) { if ( !isascii (*s) ) highbit=1; else if (iscntrl(*s)) { log_error(_("a notation value must not use any" " control characters\n")); goto fail; } } if(!highbit || is_utf8) notation->value=xstrdup(i); else notation->value=native_to_utf8(i); } return notation; fail: free_notation(notation); return NULL; } /* Like string_to_notation, but store opaque data rather than human readable data. */ struct notation * blob_to_notation(const char *name, const char *data, size_t len) { const char *s; int saw_at=0; struct notation *notation; notation=xmalloc_clear(sizeof(*notation)); if(*name=='-') { notation->flags.ignore=1; name++; } if(*name=='!') { notation->flags.critical=1; name++; } /* If and when the IETF assigns some official name tags, we'll have to add them here. */ for( s=name ; *s; s++ ) { if( *s=='@') saw_at++; /* -notationname is legal without an = sign */ if(!*s && notation->flags.ignore) break; if (*s == '=') { log_error(_("a notation name may not contain an '=' character\n")); goto fail; } if (!isascii (*s) || (!isgraph(*s) && !isspace(*s))) { log_error(_("a notation name must have only printable characters" " or spaces\n") ); goto fail; } } notation->name=xstrdup (name); if(!saw_at && !opt.expert) { log_error(_("a user notation name must contain the '@' character\n")); goto fail; } if (saw_at > 1) { log_error(_("a notation name must not contain more than" " one '@' character\n")); goto fail; } notation->bdat = xmalloc (len); memcpy (notation->bdat, data, len); notation->blen = len; notation->value = notation_value_to_human_readable_string (notation); return notation; fail: free_notation(notation); return NULL; } struct notation * sig_to_notation(PKT_signature *sig) { const byte *p; size_t len; int seq = 0; int crit; notation_t list = NULL; /* See RFC 4880, 5.2.3.16 for the format of notation data. In short, a notation has: - 4 bytes of flags - 2 byte name length (n1) - 2 byte value length (n2) - n1 bytes of name data - n2 bytes of value data */ while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,&len,&seq,&crit))) { int n1,n2; struct notation *n=NULL; if(len<8) { log_info(_("WARNING: invalid notation data found\n")); continue; } /* name length. */ n1=(p[4]<<8)|p[5]; /* value length. */ n2=(p[6]<<8)|p[7]; if(8+n1+n2!=len) { log_info(_("WARNING: invalid notation data found\n")); continue; } n=xmalloc_clear(sizeof(*n)); n->name=xmalloc(n1+1); memcpy(n->name,&p[8],n1); n->name[n1]='\0'; if(p[0]&0x80) /* The value is human-readable. */ { n->value=xmalloc(n2+1); memcpy(n->value,&p[8+n1],n2); n->value[n2]='\0'; n->flags.human = 1; } else /* Binary data. */ { n->bdat=xmalloc(n2); n->blen=n2; memcpy(n->bdat,&p[8+n1],n2); n->value = notation_value_to_human_readable_string (n); } n->flags.critical=crit; n->next=list; list=n; } return list; } /* Release the resources associated with the *list* of notations. To release a single notation, make sure that notation->next is NULL. */ void free_notation(struct notation *notation) { while(notation) { struct notation *n=notation; xfree(n->name); xfree(n->value); xfree(n->altvalue); xfree(n->bdat); notation=n->next; xfree(n); } } /* Serialize the signature packet (RFC 4880, Section 5.2) described by SIG and write it to OUT. */ static int do_signature( IOBUF out, int ctb, PKT_signature *sig ) { int rc = 0; int n, i; IOBUF a = iobuf_temp(); log_assert (ctb_pkttype (ctb) == PKT_SIGNATURE); if ( !sig->version || sig->version == 3) { iobuf_put( a, 3 ); /* Version 3 packets don't support subpackets. */ log_assert (! sig->hashed); log_assert (! sig->unhashed); } else iobuf_put( a, sig->version ); if ( sig->version < 4 ) iobuf_put (a, 5 ); /* Constant */ iobuf_put (a, sig->sig_class ); if ( sig->version < 4 ) { write_32(a, sig->timestamp ); write_32(a, sig->keyid[0] ); write_32(a, sig->keyid[1] ); } iobuf_put(a, sig->pubkey_algo ); iobuf_put(a, sig->digest_algo ); if ( sig->version >= 4 ) { size_t nn; /* Timestamp and keyid must have been packed into the subpackets prior to the call of this function, because these subpackets are hashed. */ nn = sig->hashed? sig->hashed->len : 0; write_16(a, nn); if (nn) iobuf_write( a, sig->hashed->data, nn ); nn = sig->unhashed? sig->unhashed->len : 0; write_16(a, nn); if (nn) iobuf_write( a, sig->unhashed->data, nn ); } iobuf_put(a, sig->digest_start[0] ); iobuf_put(a, sig->digest_start[1] ); n = pubkey_get_nsig( sig->pubkey_algo ); if ( !n ) write_fake_data( a, sig->data[0] ); for (i=0; i < n && !rc ; i++ ) rc = gpg_mpi_write (a, sig->data[i] ); if (!rc) { if ( is_RSA(sig->pubkey_algo) && sig->version < 4 ) write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) ); else write_header(out, ctb, iobuf_get_temp_length(a) ); rc = iobuf_write_temp( out, a ); } iobuf_close(a); return rc; } /* Serialize the one-pass signature packet (RFC 4880, Section 5.4) described by OPS and write it to OUT. */ static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops ) { log_assert (ctb_pkttype (ctb) == PKT_ONEPASS_SIG); write_header(out, ctb, 4 + 8 + 1); iobuf_put (out, 3); /* Version. */ iobuf_put(out, ops->sig_class ); iobuf_put(out, ops->digest_algo ); iobuf_put(out, ops->pubkey_algo ); write_32(out, ops->keyid[0] ); write_32(out, ops->keyid[1] ); iobuf_put(out, ops->last ); return 0; } /* Write a 16-bit quantity to OUT in big endian order. */ static int write_16(IOBUF out, u16 a) { iobuf_put(out, a>>8); if( iobuf_put(out,a) ) return -1; return 0; } /* Write a 32-bit quantity to OUT in big endian order. */ static int write_32(IOBUF out, u32 a) { iobuf_put(out, a>> 24); iobuf_put(out, a>> 16); iobuf_put(out, a>> 8); return iobuf_put(out, a); } /**************** * calculate the length of a header. * * LEN is the length of the packet's body. NEW_CTB is whether we are * using a new or old format packet. * * This function does not handle indeterminate lengths or partial body * lengths. (If you pass LEN as 0, then this function assumes you * really mean an empty body.) */ static int calc_header_length( u32 len, int new_ctb ) { if( new_ctb ) { if( len < 192 ) return 2; if( len < 8384 ) return 3; else return 6; } if( len < 256 ) return 2; if( len < 65536 ) return 3; return 5; } /**************** * Write the CTB and the packet length */ static int write_header( IOBUF out, int ctb, u32 len ) { return write_header2( out, ctb, len, 0 ); } static int write_sign_packet_header (IOBUF out, int ctb, u32 len) { (void)ctb; /* Work around a bug in the pgp read function for signature packets, which are not correctly coded and silently assume at some point 2 byte length headers.*/ iobuf_put (out, 0x89 ); iobuf_put (out, len >> 8 ); return iobuf_put (out, len) == -1 ? -1:0; } /**************** * Write a packet header to OUT. * * CTB is the ctb. It determines whether a new or old format packet * header should be written. The length field is adjusted, but the * CTB is otherwise written out as is. * * LEN is the length of the packet's body. * * If HDRLEN is set, then we don't necessarily use the most efficient * encoding to store LEN, but the specified length. (If this is not * possible, this is a bug.) In this case, LEN=0 means a 0 length * packet. Note: setting HDRLEN is only supported for old format * packets! * * If HDRLEN is not set, then the shortest encoding is used. In this * case, LEN=0 means the body has an indeterminate length and a * partial body length header (if a new format packet) or an * indeterminate length header (if an old format packet) is written * out. Further, if using partial body lengths, this enables partial * body length mode on OUT. */ static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen ) { if (ctb_new_format_p (ctb)) return write_new_header( out, ctb, len, hdrlen ); /* An old format packet. Refer to RFC 4880, Section 4.2.1 to understand how lengths are encoded in this case. */ /* The length encoding is stored in the two least significant bits. Make sure they are cleared. */ log_assert ((ctb & 3) == 0); log_assert (hdrlen == 0 || hdrlen == 2 || hdrlen == 3 || hdrlen == 5); if (hdrlen) /* Header length is given. */ { if( hdrlen == 2 && len < 256 ) /* 00 => 1 byte length. */ ; else if( hdrlen == 3 && len < 65536 ) /* 01 => 2 byte length. If len < 256, this is not the most compact encoding, but it is a correct encoding. */ ctb |= 1; else if (hdrlen == 5) /* 10 => 4 byte length. If len < 65536, this is not the most compact encoding, but it is a correct encoding. */ ctb |= 2; else log_bug ("Can't encode length=%d in a %d byte header!\n", len, hdrlen); } else { if( !len ) /* 11 => Indeterminate length. */ ctb |= 3; else if( len < 256 ) /* 00 => 1 byte length. */ ; else if( len < 65536 ) /* 01 => 2 byte length. */ ctb |= 1; else /* 10 => 4 byte length. */ ctb |= 2; } if( iobuf_put(out, ctb ) ) return -1; if( len || hdrlen ) { if( ctb & 2 ) { if(iobuf_put(out, len >> 24 )) return -1; if(iobuf_put(out, len >> 16 )) return -1; } if( ctb & 3 ) if(iobuf_put(out, len >> 8 )) return -1; if( iobuf_put(out, len ) ) return -1; } return 0; } /* Write a new format header to OUT. CTB is the ctb. LEN is the length of the packet's body. If LEN is 0, then enables partial body length mode (i.e., the body is of an indeterminant length) on OUT. Note: this function cannot be used to generate a header for a zero length packet. HDRLEN is the length of the packet's header. If HDRLEN is 0, the shortest encoding is chosen based on the length of the packet's body. Currently, values other than 0 are not supported. Returns 0 on success. */ static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen ) { if( hdrlen ) log_bug("can't cope with hdrlen yet\n"); if( iobuf_put(out, ctb ) ) return -1; if( !len ) { iobuf_set_partial_body_length_mode(out, 512 ); } else { if( len < 192 ) { if( iobuf_put(out, len ) ) return -1; } else if( len < 8384 ) { len -= 192; if( iobuf_put( out, (len / 256) + 192) ) return -1; if( iobuf_put( out, (len % 256) ) ) return -1; } else { if( iobuf_put( out, 0xff ) ) return -1; if( iobuf_put( out, (len >> 24)&0xff ) ) return -1; if( iobuf_put( out, (len >> 16)&0xff ) ) return -1; if( iobuf_put( out, (len >> 8)&0xff ) ) return -1; if( iobuf_put( out, len & 0xff ) ) return -1; } } return 0; } diff --git a/g10/mainproc.c b/g10/mainproc.c index ce4c5951c..63f726097 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1,2485 +1,2484 @@ /* mainproc.c - handle packets * Copyright (C) 1998-2009 Free Software Foundation, Inc. * Copyright (C) 2013-2014 Werner Koch * * 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 "util.h" #include "packet.h" #include "iobuf.h" #include "options.h" #include "keydb.h" #include "filter.h" #include "main.h" #include "status.h" #include "i18n.h" #include "trustdb.h" #include "keyserver-internal.h" #include "photoid.h" #include "mbox-util.h" #include "call-dirmngr.h" /* Put an upper limit on nested packets. The 32 is an arbitrary value, a much lower should actually be sufficient. */ #define MAX_NESTING_DEPTH 32 /* An object to build a list of keyid related info. */ struct kidlist_item { struct kidlist_item *next; u32 kid[2]; int pubkey_algo; int reason; }; /* * Object to hold the processing context. */ typedef struct mainproc_context *CTX; struct mainproc_context { ctrl_t ctrl; struct mainproc_context *anchor; /* May be useful in the future. */ PKT_public_key *last_pubkey; PKT_user_id *last_user_id; md_filter_context_t mfx; int sigs_only; /* Process only signatures and reject all other stuff. */ int encrypt_only; /* Process only encryption messages. */ /* Name of the file with the complete signature or the file with the detached signature. This is currently only used to deduce the file name of the data file if that has not been given. */ const char *sigfilename; /* A structure to describe the signed data in case of a detached signature. */ struct { /* A file descriptor of the the signed data. Only used if not -1. */ int data_fd; /* A list of filenames with the data files or NULL. This is only used if DATA_FD is -1. */ strlist_t data_names; /* Flag to indicated that either one of the next previous fields is used. This is only needed for better readability. */ int used; } signed_data; DEK *dek; int last_was_session_key; kbnode_t list; /* The current list of packets. */ iobuf_t iobuf; /* Used to get the filename etc. */ int trustletter; /* Temporary usage in list_node. */ ulong symkeys; struct kidlist_item *pkenc_list; /* List of encryption packets. */ struct { unsigned int sig_seen:1; /* Set to true if a signature packet has been seen. */ unsigned int data:1; /* Any data packet seen */ unsigned int uncompress_failed:1; } any; }; /*** Local prototypes. ***/ static int do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a); static void list_node (CTX c, kbnode_t node); static void proc_tree (CTX c, kbnode_t node); static int literals_seen; /*** Functions. ***/ void reset_literals_seen(void) { literals_seen = 0; } static void release_list( CTX c ) { proc_tree (c, c->list); release_kbnode (c->list); while (c->pkenc_list) { struct kidlist_item *tmp = c->pkenc_list->next; xfree (c->pkenc_list); c->pkenc_list = tmp; } c->pkenc_list = NULL; c->list = NULL; c->any.data = 0; c->any.uncompress_failed = 0; c->last_was_session_key = 0; xfree (c->dek); c->dek = NULL; } static int add_onepass_sig (CTX c, PACKET *pkt) { kbnode_t node; if (c->list) /* Add another packet. */ add_kbnode (c->list, new_kbnode (pkt)); else /* Insert the first one. */ c->list = node = new_kbnode (pkt); return 1; } static int add_gpg_control (CTX c, PACKET *pkt) { if ( pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) { /* New clear text signature. * Process the last one and reset everything */ release_list(c); } if (c->list) /* Add another packet. */ add_kbnode (c->list, new_kbnode (pkt)); else /* Insert the first one. */ c->list = new_kbnode (pkt); return 1; } static int add_user_id (CTX c, PACKET *pkt) { if (!c->list) { log_error ("orphaned user ID\n"); return 0; } add_kbnode (c->list, new_kbnode (pkt)); return 1; } static int add_subkey (CTX c, PACKET *pkt) { if (!c->list) { log_error ("subkey w/o mainkey\n"); return 0; } add_kbnode (c->list, new_kbnode (pkt)); return 1; } static int add_ring_trust (CTX c, PACKET *pkt) { if (!c->list) { log_error ("ring trust w/o key\n"); return 0; } add_kbnode (c->list, new_kbnode (pkt)); return 1; } static int add_signature (CTX c, PACKET *pkt) { kbnode_t node; c->any.sig_seen = 1; if (pkt->pkttype == PKT_SIGNATURE && !c->list) { /* This is the first signature for the following datafile. * GPG does not write such packets; instead it always uses * onepass-sig packets. The drawback of PGP's method * of prepending the signature to the data is * that it is not possible to make a signature from data read * from stdin. (GPG is able to read PGP stuff anyway.) */ node = new_kbnode (pkt); c->list = node; return 1; } else if (!c->list) return 0; /* oops (invalid packet sequence)*/ else if (!c->list->pkt) BUG(); /* so nicht */ /* Add a new signature node item at the end. */ node = new_kbnode (pkt); add_kbnode (c->list, node); return 1; } static int symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen) { gcry_cipher_hd_t hd; if(slen < 17 || slen > 33) { log_error ( _("weird size for an encrypted session key (%d)\n"), (int)slen); return GPG_ERR_BAD_KEY; } if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1)) BUG (); if (gcry_cipher_setkey ( hd, dek->key, dek->keylen )) BUG (); gcry_cipher_setiv ( hd, NULL, 0 ); gcry_cipher_decrypt ( hd, seskey, slen, NULL, 0 ); gcry_cipher_close ( hd ); /* Now we replace the dek components with the real session key to decrypt the contents of the sequencing packet. */ dek->keylen=slen-1; dek->algo=seskey[0]; if(dek->keylen > DIM(dek->key)) BUG (); memcpy(dek->key, seskey + 1, dek->keylen); /*log_hexdump( "thekey", dek->key, dek->keylen );*/ return 0; } static void proc_symkey_enc (CTX c, PACKET *pkt) { PKT_symkey_enc *enc; enc = pkt->pkt.symkey_enc; if (!enc) log_error ("invalid symkey encrypted packet\n"); else if(!c->dek) { int algo = enc->cipher_algo; const char *s = openpgp_cipher_algo_name (algo); if (!openpgp_cipher_test_algo (algo)) { if (!opt.quiet) { if (enc->seskeylen) log_info (_("%s encrypted session key\n"), s ); else log_info (_("%s encrypted data\n"), s ); } } else log_error (_("encrypted with unknown algorithm %d\n"), algo); if (openpgp_md_test_algo (enc->s2k.hash_algo)) { log_error(_("passphrase generated with unknown digest" " algorithm %d\n"),enc->s2k.hash_algo); s = NULL; } c->last_was_session_key = 2; if (!s || opt.list_only) goto leave; if (opt.override_session_key) { c->dek = xmalloc_clear (sizeof *c->dek); if (get_override_session_key (c->dek, opt.override_session_key)) { xfree (c->dek); c->dek = NULL; } } else { c->dek = passphrase_to_dek (algo, &enc->s2k, 0, 0, NULL, NULL); if (c->dek) { c->dek->symmetric = 1; /* FIXME: This doesn't work perfectly if a symmetric key comes before a public key in the message - if the user doesn't know the passphrase, then there is a chance that the "decrypted" algorithm will happen to be a valid one, which will make the returned dek appear valid, so we won't try any public keys that come later. */ if (enc->seskeylen) { if (symkey_decrypt_seskey (c->dek, enc->seskey, enc->seskeylen)) { xfree (c->dek); c->dek = NULL; } } else c->dek->algo_info_printed = 1; } } } leave: c->symkeys++; free_packet (pkt); } static void proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt) { PKT_pubkey_enc *enc; int result = 0; /* Check whether the secret key is available and store in this case. */ c->last_was_session_key = 1; enc = pkt->pkt.pubkey_enc; /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/ /* Hmmm: why do I have this algo check here - anyway there is * function to check it. */ if (opt.verbose) log_info (_("public key is %s\n"), keystr (enc->keyid)); if (is_status_enabled()) { char buf[50]; /* FIXME: For ECC support we need to map the OpenPGP algo number to the Libgcrypt defined one. This is due a chicken-egg problem: We need to have code in Libgcrypt for a new algorithm so to implement a proposed new algorithm before the IANA will finally assign an OpenPGP identifier. */ snprintf (buf, sizeof buf, "%08lX%08lX %d 0", (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo); write_status_text (STATUS_ENC_TO, buf); } if (!opt.list_only && opt.override_session_key) { /* It does not make much sense to store the session key in * secure memory because it has already been passed on the * command line and the GCHQ knows about it. */ c->dek = xmalloc_clear (sizeof *c->dek); result = get_override_session_key (c->dek, opt.override_session_key); if (result) { xfree (c->dek); c->dek = NULL; } } else if (enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E || enc->pubkey_algo == PUBKEY_ALGO_ECDH || enc->pubkey_algo == PUBKEY_ALGO_RSA || enc->pubkey_algo == PUBKEY_ALGO_RSA_E || enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL) { /* Note that we also allow type 20 Elgamal keys for decryption. There are still a couple of those keys in active use as a subkey. */ /* FIXME: Store this all in a list and process it later so that we can prioritize what key to use. This gives a better user experience if wildcard keyids are used. */ if (!c->dek && ((!enc->keyid[0] && !enc->keyid[1]) || opt.try_all_secrets || have_secret_key_with_kid (enc->keyid))) { if(opt.list_only) result = -1; else { c->dek = xmalloc_secure_clear (sizeof *c->dek); if ((result = get_session_key (ctrl, enc, c->dek))) { /* Error: Delete the DEK. */ xfree (c->dek); c->dek = NULL; } } } else result = GPG_ERR_NO_SECKEY; } else result = GPG_ERR_PUBKEY_ALGO; if (result == -1) ; else { /* Store it for later display. */ struct kidlist_item *x = xmalloc (sizeof *x); x->kid[0] = enc->keyid[0]; x->kid[1] = enc->keyid[1]; x->pubkey_algo = enc->pubkey_algo; x->reason = result; x->next = c->pkenc_list; c->pkenc_list = x; if (!result && opt.verbose > 1) log_info (_("public key encrypted data: good DEK\n")); } free_packet(pkt); } /* * Print the list of public key encrypted packets which we could * not decrypt. */ static void print_pkenc_list (struct kidlist_item *list, int failed) { for (; list; list = list->next) { PKT_public_key *pk; const char *algstr; if (failed && !list->reason) continue; if (!failed && list->reason) continue; algstr = openpgp_pk_algo_name (list->pubkey_algo); pk = xmalloc_clear (sizeof *pk); if (!algstr) algstr = "[?]"; pk->pubkey_algo = list->pubkey_algo; if (!get_pubkey (pk, list->kid)) { char *p; log_info (_("encrypted with %u-bit %s key, ID %s, created %s\n"), nbits_from_pk (pk), algstr, keystr_from_pk(pk), strtimestamp (pk->timestamp)); p = get_user_id_native (list->kid); log_printf (_(" \"%s\"\n"), p); xfree (p); } else log_info (_("encrypted with %s key, ID %s\n"), algstr, keystr(list->kid)); free_public_key (pk); if (gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY) { if (is_status_enabled()) { char buf[20]; snprintf (buf, sizeof buf, "%08lX%08lX", (ulong)list->kid[0], (ulong)list->kid[1]); write_status_text (STATUS_NO_SECKEY, buf); } } else if (list->reason) { log_info (_("public key decryption failed: %s\n"), gpg_strerror (list->reason)); write_status_error ("pkdecrypt_failed", list->reason); } } } static void proc_encrypted (CTX c, PACKET *pkt) { int result = 0; if (!opt.quiet) { if (c->symkeys>1) log_info (_("encrypted with %lu passphrases\n"), c->symkeys); else if (c->symkeys == 1) log_info (_("encrypted with 1 passphrase\n")); print_pkenc_list ( c->pkenc_list, 1 ); print_pkenc_list ( c->pkenc_list, 0 ); } /* FIXME: Figure out the session key by looking at all pkenc packets. */ write_status (STATUS_BEGIN_DECRYPTION); /*log_debug("dat: %sencrypted data\n", c->dek?"":"conventional ");*/ if (opt.list_only) result = -1; else if (!c->dek && !c->last_was_session_key) { int algo; STRING2KEY s2kbuf; STRING2KEY *s2k = NULL; int canceled; if (opt.override_session_key) { c->dek = xmalloc_clear (sizeof *c->dek); result = get_override_session_key (c->dek, opt.override_session_key); if (result) { xfree (c->dek); c->dek = NULL; } } else { /* Assume this is old style conventional encrypted data. */ algo = opt.def_cipher_algo; if (algo) log_info (_("assuming %s encrypted data\n"), openpgp_cipher_algo_name (algo)); else if (openpgp_cipher_test_algo (CIPHER_ALGO_IDEA)) { algo = opt.def_cipher_algo; if (!algo) algo = opt.s2k_cipher_algo; log_info (_("IDEA cipher unavailable, " "optimistically attempting to use %s instead\n"), openpgp_cipher_algo_name (algo)); } else { algo = CIPHER_ALGO_IDEA; if (!opt.s2k_digest_algo) { /* If no digest is given we assume SHA-1. */ s2kbuf.mode = 0; s2kbuf.hash_algo = DIGEST_ALGO_SHA1; s2k = &s2kbuf; } log_info (_("assuming %s encrypted data\n"), "IDEA"); } c->dek = passphrase_to_dek (algo, s2k, 0, 0, NULL, &canceled); if (c->dek) c->dek->algo_info_printed = 1; else if (canceled) result = gpg_error (GPG_ERR_CANCELED); else result = gpg_error (GPG_ERR_INV_PASSPHRASE); } } else if (!c->dek) result = GPG_ERR_NO_SECKEY; if (!result) result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek ); if (result == -1) ; else if (!result && !opt.ignore_mdc_error && !pkt->pkt.encrypted->mdc_method && openpgp_cipher_get_algo_blklen (c->dek->algo) != 8 && c->dek->algo != CIPHER_ALGO_TWOFISH) { /* The message has been decrypted but has no MDC despite that a modern cipher (blocklength != 64 bit, except for Twofish) is used and the option to ignore MDC errors is not used: To avoid attacks changing an MDC message to a non-MDC message, we fail here. */ log_error (_("WARNING: message was not integrity protected\n")); if (opt.verbose > 1) log_info ("decryption forced to fail\n"); write_status (STATUS_DECRYPTION_FAILED); } else if (!result || (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE && opt.ignore_mdc_error)) { write_status (STATUS_DECRYPTION_OKAY); if (opt.verbose > 1) log_info(_("decryption okay\n")); if (pkt->pkt.encrypted->mdc_method && !result) write_status (STATUS_GOODMDC); else if (!opt.no_mdc_warn) log_info (_("WARNING: message was not integrity protected\n")); } else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE) { glo_ctrl.lasterr = result; log_error (_("WARNING: encrypted message has been manipulated!\n")); write_status (STATUS_BADMDC); write_status (STATUS_DECRYPTION_FAILED); } else { if (gpg_err_code (result) == GPG_ERR_BAD_KEY && *c->dek->s2k_cacheid != '\0') { if (opt.debug) log_debug ("cleared passphrase cached with ID: %s\n", c->dek->s2k_cacheid); passphrase_clear_cache (c->dek->s2k_cacheid); } glo_ctrl.lasterr = result; write_status (STATUS_DECRYPTION_FAILED); log_error (_("decryption failed: %s\n"), gpg_strerror (result)); /* Hmmm: does this work when we have encrypted using multiple * ways to specify the session key (symmmetric and PK). */ } xfree (c->dek); c->dek = NULL; free_packet (pkt); c->last_was_session_key = 0; write_status (STATUS_END_DECRYPTION); } static void proc_plaintext( CTX c, PACKET *pkt ) { PKT_plaintext *pt = pkt->pkt.plaintext; int any, clearsig, rc; kbnode_t n; literals_seen++; if (pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8)) log_info (_("Note: sender requested \"for-your-eyes-only\"\n")); else if (opt.verbose) log_info (_("original file name='%.*s'\n"), pt->namelen, pt->name); free_md_filter_context (&c->mfx); if (gcry_md_open (&c->mfx.md, 0, 0)) BUG (); /* fixme: we may need to push the textfilter if we have sigclass 1 * and no armoring - Not yet tested * Hmmm, why don't we need it at all if we have sigclass 1 * Should we assume that plaintext in mode 't' has always sigclass 1?? * See: Russ Allbery's mail 1999-02-09 */ any = clearsig = 0; for (n=c->list; n; n = n->next ) { if (n->pkt->pkttype == PKT_ONEPASS_SIG) { /* The onepass signature case. */ if (n->pkt->pkt.onepass_sig->digest_algo) { gcry_md_enable (c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo); any = 1; } } else if (n->pkt->pkttype == PKT_GPG_CONTROL && n->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START) { /* The clearsigned message case. */ size_t datalen = n->pkt->pkt.gpg_control->datalen; const byte *data = n->pkt->pkt.gpg_control->data; /* Check that we have at least the sigclass and one hash. */ if (datalen < 2) log_fatal ("invalid control packet CTRLPKT_CLEARSIGN_START\n"); /* Note that we don't set the clearsig flag for not-dash-escaped * documents. */ clearsig = (*data == 0x01); for (data++, datalen--; datalen; datalen--, data++) gcry_md_enable (c->mfx.md, *data); any = 1; break; /* Stop here as one-pass signature packets are not expected. */ } else if (n->pkt->pkttype == PKT_SIGNATURE) { /* The SIG+LITERAL case that PGP used to use. */ gcry_md_enable ( c->mfx.md, n->pkt->pkt.signature->digest_algo ); any = 1; } } if (!any && !opt.skip_verify) { /* This is for the old GPG LITERAL+SIG case. It's not legal according to 2440, so hopefully it won't come up that often. There is no good way to specify what algorithms to use in that case, so these there are the historical answer. */ gcry_md_enable (c->mfx.md, DIGEST_ALGO_RMD160); gcry_md_enable (c->mfx.md, DIGEST_ALGO_SHA1); } if (DBG_HASHING) { gcry_md_debug (c->mfx.md, "verify"); if (c->mfx.md2) gcry_md_debug (c->mfx.md2, "verify2"); } rc=0; if (literals_seen > 1) { log_info (_("WARNING: multiple plaintexts seen\n")); if (!opt.flags.allow_multiple_messages) { write_status_text (STATUS_ERROR, "proc_pkt.plaintext 89_BAD_DATA"); log_inc_errorcount (); rc = gpg_error (GPG_ERR_UNEXPECTED); } } if (!rc) { /* It we are in --verify mode, we do not want to output the * signed text. However, if --output is also used we do what * has been requested and write out the signed data. */ rc = handle_plaintext (pt, &c->mfx, (opt.outfp || opt.outfile)? 0 : c->sigs_only, clearsig); if (gpg_err_code (rc) == GPG_ERR_EACCES && !c->sigs_only) { /* Can't write output but we hash it anyway to check the signature. */ rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); } } if (rc) log_error ("handle plaintext failed: %s\n", gpg_strerror (rc)); free_packet(pkt); c->last_was_session_key = 0; /* We add a marker control packet instead of the plaintext packet. * This is so that we can later detect invalid packet sequences. */ n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, NULL, 0)); if (c->list) add_kbnode (c->list, n); else c->list = n; } static int proc_compressed_cb (iobuf_t a, void *info) { if ( ((CTX)info)->signed_data.used && ((CTX)info)->signed_data.data_fd != -1) return proc_signature_packets_by_fd (((CTX)info)->ctrl, info, a, ((CTX)info)->signed_data.data_fd); else return proc_signature_packets (((CTX)info)->ctrl, info, a, ((CTX)info)->signed_data.data_names, ((CTX)info)->sigfilename ); } static int proc_encrypt_cb (iobuf_t a, void *info ) { CTX c = info; return proc_encryption_packets (c->ctrl, info, a ); } static int proc_compressed (CTX c, PACKET *pkt) { PKT_compressed *zd = pkt->pkt.compressed; int rc; /*printf("zip: compressed data packet\n");*/ if (c->sigs_only) rc = handle_compressed (c->ctrl, c, zd, proc_compressed_cb, c); else if( c->encrypt_only ) rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c); else rc = handle_compressed (c->ctrl, c, zd, NULL, NULL); if (gpg_err_code (rc) == GPG_ERR_BAD_DATA) { if (!c->any.uncompress_failed) { CTX cc; for (cc=c; cc; cc = cc->anchor) cc->any.uncompress_failed = 1; log_error ("uncompressing failed: %s\n", gpg_strerror (rc)); } } else if (rc) log_error ("uncompressing failed: %s\n", gpg_strerror (rc)); free_packet(pkt); c->last_was_session_key = 0; return rc; } /* * Check the signature. If R_PK is not NULL a copy of the public key * used to verify the signature will be stored tehre, or NULL if not * found. Returns: 0 = valid signature or an error code */ static int do_check_sig (CTX c, kbnode_t node, int *is_selfsig, int *is_expkey, int *is_revkey, PKT_public_key **r_pk) { PKT_signature *sig; gcry_md_hd_t md = NULL; gcry_md_hd_t md2 = NULL; gcry_md_hd_t md_good = NULL; int algo, rc; if (r_pk) *r_pk = NULL; log_assert (node->pkt->pkttype == PKT_SIGNATURE); if (is_selfsig) *is_selfsig = 0; sig = node->pkt->pkt.signature; algo = sig->digest_algo; rc = openpgp_md_test_algo (algo); if (rc) return rc; if (sig->sig_class == 0x00) { if (c->mfx.md) { if (gcry_md_copy (&md, c->mfx.md )) BUG (); } else /* detached signature */ { /* check_signature() will enable the md. */ if (gcry_md_open (&md, 0, 0 )) BUG (); } } else if (sig->sig_class == 0x01) { /* How do we know that we have to hash the (already hashed) text in canonical mode ??? (calculating both modes???) */ if (c->mfx.md) { if (gcry_md_copy (&md, c->mfx.md )) BUG (); if (c->mfx.md2 && gcry_md_copy (&md2, c->mfx.md2)) BUG (); } else /* detached signature */ { log_debug ("Do we really need this here?"); /* check_signature() will enable the md*/ if (gcry_md_open (&md, 0, 0 )) BUG (); if (gcry_md_open (&md2, 0, 0 )) BUG (); } } else if ((sig->sig_class&~3) == 0x10 || sig->sig_class == 0x18 || sig->sig_class == 0x1f || sig->sig_class == 0x20 || sig->sig_class == 0x28 || sig->sig_class == 0x30) { if (c->list->pkt->pkttype == PKT_PUBLIC_KEY || c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY) { return check_key_signature( c->list, node, is_selfsig ); } else if (sig->sig_class == 0x20) { log_error (_("standalone revocation - " "use \"gpg --import\" to apply\n")); return GPG_ERR_NOT_PROCESSED; } else { log_error ("invalid root packet for sigclass %02x\n", sig->sig_class); return GPG_ERR_SIG_CLASS; } } else return GPG_ERR_SIG_CLASS; /* We only get here if we are checking the signature of a binary (0x00) or text document (0x01). */ rc = check_signature2 (sig, md, NULL, is_expkey, is_revkey, r_pk); if (! rc) md_good = md; else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2) { PKT_public_key *pk2; rc = check_signature2 (sig, md2, NULL, is_expkey, is_revkey, r_pk? &pk2 : NULL); if (!rc) { md_good = md2; if (r_pk) { free_public_key (*r_pk); *r_pk = pk2; } } } if (md_good) { unsigned char *buffer = gcry_md_read (md_good, sig->digest_algo); sig->digest_len = gcry_md_get_algo_dlen (map_md_openpgp_to_gcry (algo)); memcpy (sig->digest, buffer, sig->digest_len); } gcry_md_close (md); gcry_md_close (md2); return rc; } static void print_userid (PACKET *pkt) { if (!pkt) BUG(); if (pkt->pkttype != PKT_USER_ID) { es_printf ("ERROR: unexpected packet type %d", pkt->pkttype ); return; } if (opt.with_colons) { if (pkt->pkt.user_id->attrib_data) es_printf("%u %lu", pkt->pkt.user_id->numattribs, pkt->pkt.user_id->attrib_len); else es_write_sanitized (es_stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len, ":", NULL); } else print_utf8_buffer (es_stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len ); } /* * List the keyblock in a user friendly way */ static void list_node (CTX c, kbnode_t node) { if (!node) ; else if (node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { PKT_public_key *pk = node->pkt->pkt.public_key; if (opt.with_colons) { u32 keyid[2]; keyid_from_pk( pk, keyid ); if (pk->flags.primary) c->trustletter = (opt.fast_list_mode? 0 : get_validity_info (c->ctrl, pk, NULL)); es_printf ("%s:", pk->flags.primary? "pub":"sub" ); if (c->trustletter) es_putc (c->trustletter, es_stdout); es_printf (":%u:%d:%08lX%08lX:%s:%s::", nbits_from_pk( pk ), pk->pubkey_algo, (ulong)keyid[0],(ulong)keyid[1], colon_datestr_from_pk( pk ), colon_strtime (pk->expiredate) ); if (pk->flags.primary && !opt.fast_list_mode) es_putc (get_ownertrust_info (pk), es_stdout); es_putc (':', es_stdout); es_putc ('\n', es_stdout); } else { print_key_line (es_stdout, pk, 0); } if (opt.keyid_format == KF_NONE && !opt.with_colons) ; /* Already printed. */ else if ((pk->flags.primary && opt.fingerprint) || opt.fingerprint > 1) print_fingerprint (NULL, pk, 0); if (opt.with_colons) { if (node->next && node->next->pkt->pkttype == PKT_RING_TRUST) es_printf ("rtv:1:%u:\n", node->next->pkt->pkt.ring_trust->trustval); } if (pk->flags.primary) { int kl = opt.keyid_format == KF_NONE? 0 : keystrlen (); /* Now list all userids with their signatures. */ for (node = node->next; node; node = node->next) { if (node->pkt->pkttype == PKT_SIGNATURE) { list_node (c, node ); } else if (node->pkt->pkttype == PKT_USER_ID) { if (opt.with_colons) es_printf ("%s:::::::::", node->pkt->pkt.user_id->attrib_data?"uat":"uid"); else es_printf ("uid%*s", kl + (opt.legacy_list_mode? 9:11), "" ); print_userid (node->pkt); if (opt.with_colons) es_putc (':', es_stdout); es_putc ('\n', es_stdout); if (opt.with_colons && node->next && node->next->pkt->pkttype == PKT_RING_TRUST) { es_printf ("rtv:2:%u:\n", node->next->pkt->pkt.ring_trust? node->next->pkt->pkt.ring_trust->trustval : 0); } } else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { list_node(c, node ); } } } } else if (node->pkt->pkttype == PKT_SECRET_KEY || node->pkt->pkttype == PKT_SECRET_SUBKEY) { log_debug ("FIXME: No way to print secret key packets here\n"); /* fixme: We may use a function to turn a secret key packet into a public key one and use that here. */ } else if (node->pkt->pkttype == PKT_SIGNATURE) { PKT_signature *sig = node->pkt->pkt.signature; int is_selfsig = 0; int rc2 = 0; size_t n; char *p; int sigrc = ' '; if (!opt.verbose) return; if (sig->sig_class == 0x20 || sig->sig_class == 0x30) es_fputs ("rev", es_stdout); else es_fputs ("sig", es_stdout); if (opt.check_sigs) { fflush (stdout); rc2 = do_check_sig (c, node, &is_selfsig, NULL, NULL, NULL); switch (gpg_err_code (rc2)) { case 0: sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: case GPG_ERR_UNUSABLE_PUBKEY: sigrc = '?'; break; default: sigrc = '%'; break; } } else /* Check whether this is a self signature. */ { u32 keyid[2]; if (c->list->pkt->pkttype == PKT_PUBLIC_KEY || c->list->pkt->pkttype == PKT_SECRET_KEY ) { keyid_from_pk (c->list->pkt->pkt.public_key, keyid); if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]) is_selfsig = 1; } } if (opt.with_colons) { es_putc (':', es_stdout); if (sigrc != ' ') es_putc (sigrc, es_stdout); es_printf ("::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo, (ulong)sig->keyid[0], (ulong)sig->keyid[1], colon_datestr_from_sig (sig), colon_expirestr_from_sig (sig)); if (sig->trust_depth || sig->trust_value) es_printf ("%d %d",sig->trust_depth,sig->trust_value); es_putc (':', es_stdout); if (sig->trust_regexp) es_write_sanitized (es_stdout, sig->trust_regexp, strlen (sig->trust_regexp), ":", NULL); es_putc (':', es_stdout); } else es_printf ("%c %s %s ", sigrc, keystr (sig->keyid), datestr_from_sig(sig)); if (sigrc == '%') es_printf ("[%s] ", gpg_strerror (rc2) ); else if (sigrc == '?') ; else if (is_selfsig) { if (opt.with_colons) es_putc (':', es_stdout); es_fputs (sig->sig_class == 0x18? "[keybind]":"[selfsig]", es_stdout); if (opt.with_colons) es_putc (':', es_stdout); } else if (!opt.fast_list_mode) { p = get_user_id (sig->keyid, &n); es_write_sanitized (es_stdout, p, n, opt.with_colons?":":NULL, NULL ); xfree (p); } if (opt.with_colons) es_printf (":%02x%c:", sig->sig_class, sig->flags.exportable?'x':'l'); es_putc ('\n', es_stdout); } else log_error ("invalid node with packet of type %d\n", node->pkt->pkttype); } int proc_packets (ctrl_t ctrl, void *anchor, iobuf_t a ) { int rc; CTX c = xmalloc_clear (sizeof *c); c->ctrl = ctrl; c->anchor = anchor; rc = do_proc_packets (ctrl, c, a); xfree (c); return rc; } int proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a, strlist_t signedfiles, const char *sigfilename ) { CTX c = xmalloc_clear (sizeof *c); int rc; c->ctrl = ctrl; c->anchor = anchor; c->sigs_only = 1; c->signed_data.data_fd = -1; c->signed_data.data_names = signedfiles; c->signed_data.used = !!signedfiles; c->sigfilename = sigfilename; rc = do_proc_packets (ctrl, c, a); /* If we have not encountered any signature we print an error messages, send a NODATA status back and return an error code. Using log_error is required because verify_files does not check error codes for each file but we want to terminate the process with an error. */ if (!rc && !c->any.sig_seen) { write_status_text (STATUS_NODATA, "4"); log_error (_("no signature found\n")); rc = GPG_ERR_NO_DATA; } /* Propagate the signature seen flag upward. Do this only on success so that we won't issue the nodata status several times. */ if (!rc && c->anchor && c->any.sig_seen) c->anchor->any.sig_seen = 1; xfree (c); return rc; } int proc_signature_packets_by_fd (ctrl_t ctrl, void *anchor, iobuf_t a, int signed_data_fd ) { int rc; CTX c; c = xtrycalloc (1, sizeof *c); if (!c) return gpg_error_from_syserror (); c->ctrl = ctrl; c->anchor = anchor; c->sigs_only = 1; c->signed_data.data_fd = signed_data_fd; c->signed_data.data_names = NULL; c->signed_data.used = (signed_data_fd != -1); rc = do_proc_packets (ctrl, c, a); /* If we have not encountered any signature we print an error messages, send a NODATA status back and return an error code. Using log_error is required because verify_files does not check error codes for each file but we want to terminate the process with an error. */ if (!rc && !c->any.sig_seen) { write_status_text (STATUS_NODATA, "4"); log_error (_("no signature found\n")); rc = gpg_error (GPG_ERR_NO_DATA); } /* Propagate the signature seen flag upward. Do this only on success so that we won't issue the nodata status several times. */ if (!rc && c->anchor && c->any.sig_seen) c->anchor->any.sig_seen = 1; xfree ( c ); return rc; } int proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a ) { CTX c = xmalloc_clear (sizeof *c); int rc; c->ctrl = ctrl; c->anchor = anchor; c->encrypt_only = 1; rc = do_proc_packets (ctrl, c, a); xfree (c); return rc; } static int check_nesting (CTX c) { int level; for (level=0; c; c = c->anchor) level++; if (level > MAX_NESTING_DEPTH) { log_error ("input data with too deeply nested packets\n"); write_status_text (STATUS_UNEXPECTED, "1"); return GPG_ERR_BAD_DATA; } return 0; } static int do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a) { PACKET *pkt; int rc = 0; int any_data = 0; int newpkt; rc = check_nesting (c); if (rc) return rc; pkt = xmalloc( sizeof *pkt ); c->iobuf = a; init_packet(pkt); while ((rc=parse_packet(a, pkt)) != -1) { any_data = 1; if (rc) { free_packet (pkt); /* Stop processing when an invalid packet has been encountered * but don't do so when we are doing a --list-packets. */ if (gpg_err_code (rc) == GPG_ERR_INV_PACKET && opt.list_packets == 0) break; continue; } newpkt = -1; if (opt.list_packets) { switch (pkt->pkttype) { case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break; case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break; case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break; default: newpkt = 0; break; } } else if (c->sigs_only) { switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_SECRET_KEY: case PKT_USER_ID: case PKT_SYMKEY_ENC: case PKT_PUBKEY_ENC: case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: write_status_text( STATUS_UNEXPECTED, "0" ); rc = GPG_ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break; case PKT_PLAINTEXT: proc_plaintext (c, pkt); break; case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break; case PKT_ONEPASS_SIG: newpkt = add_onepass_sig (c, pkt); break; case PKT_GPG_CONTROL: newpkt = add_gpg_control (c, pkt); break; default: newpkt = 0; break; } } else if (c->encrypt_only) { switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_SECRET_KEY: case PKT_USER_ID: write_status_text (STATUS_UNEXPECTED, "0"); rc = GPG_ERR_UNEXPECTED; goto leave; case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break; case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break; case PKT_PLAINTEXT: proc_plaintext (c, pkt); break; case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break; case PKT_ONEPASS_SIG: newpkt = add_onepass_sig (c, pkt); break; case PKT_GPG_CONTROL: newpkt = add_gpg_control (c, pkt); break; default: newpkt = 0; break; } } else { switch (pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_SECRET_KEY: release_list (c); c->list = new_kbnode (pkt); newpkt = 1; break; case PKT_PUBLIC_SUBKEY: case PKT_SECRET_SUBKEY: newpkt = add_subkey (c, pkt); break; case PKT_USER_ID: newpkt = add_user_id (c, pkt); break; case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break; case PKT_PUBKEY_ENC: proc_pubkey_enc (ctrl, c, pkt); break; case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break; case PKT_PLAINTEXT: proc_plaintext (c, pkt); break; case PKT_COMPRESSED: rc = proc_compressed (c, pkt); break; case PKT_ONEPASS_SIG: newpkt = add_onepass_sig (c, pkt); break; case PKT_GPG_CONTROL: newpkt = add_gpg_control(c, pkt); break; case PKT_RING_TRUST: newpkt = add_ring_trust (c, pkt); break; default: newpkt = 0; break; } } if (rc) goto leave; /* This is a very ugly construct and frankly, I don't remember why * I used it. Adding the MDC check here is a hack. * The right solution is to initiate another context for encrypted * packet and not to reuse the current one ... It works right * when there is a compression packet between which adds just * an extra layer. * Hmmm: Rewrite this whole module here?? */ if (pkt->pkttype != PKT_SIGNATURE && pkt->pkttype != PKT_MDC) c->any.data = (pkt->pkttype == PKT_PLAINTEXT); if (newpkt == -1) ; else if (newpkt) { pkt = xmalloc (sizeof *pkt); init_packet (pkt); } else free_packet(pkt); } if (rc == GPG_ERR_INV_PACKET) write_status_text (STATUS_NODATA, "3"); if (any_data) rc = 0; else if (rc == -1) write_status_text (STATUS_NODATA, "2"); leave: release_list (c); xfree(c->dek); free_packet (pkt); xfree (pkt); free_md_filter_context (&c->mfx); return rc; } /* Helper for pka_uri_from_sig to parse the to-be-verified address out of the notation data. */ static pka_info_t * get_pka_address (PKT_signature *sig) { pka_info_t *pka = NULL; struct notation *nd,*notation; notation=sig_to_notation(sig); for(nd=notation;nd;nd=nd->next) { if(strcmp(nd->name,"pka-address@gnupg.org")!=0) continue; /* Not the notation we want. */ /* For now we only use the first valid PKA notation. In future we might want to keep additional PKA notations in a linked list. */ if (is_valid_mailbox (nd->value)) { pka = xmalloc (sizeof *pka + strlen(nd->value)); pka->valid = 0; pka->checked = 0; pka->uri = NULL; strcpy (pka->email, nd->value); break; } } free_notation(notation); return pka; } /* Return the URI from a DNS PKA record. If this record has already be retrieved for the signature we merely return it; if not we go out and try to get that DNS record. */ static const char * pka_uri_from_sig (CTX c, PKT_signature *sig) { if (!sig->flags.pka_tried) { log_assert (!sig->pka_info); sig->flags.pka_tried = 1; sig->pka_info = get_pka_address (sig); if (sig->pka_info) { char *url; unsigned char *fpr; size_t fprlen; if (!gpg_dirmngr_get_pka (c->ctrl, sig->pka_info->email, &fpr, &fprlen, &url)) { if (fpr && fprlen == sizeof sig->pka_info->fpr) { memcpy (sig->pka_info->fpr, fpr, fprlen); if (url) { sig->pka_info->valid = 1; if (!*url) xfree (url); else sig->pka_info->uri = url; url = NULL; } } xfree (fpr); xfree (url); } } } return sig->pka_info? sig->pka_info->uri : NULL; } /* Return true if the AKL has the WKD method specified. */ static int akl_has_wkd_method (void) { struct akl *akl; for (akl = opt.auto_key_locate; akl; akl = akl->next) if (akl->type == AKL_WKD) return 1; return 0; } /* Return the ISSUER fingerprint string in human readbale format if * available. Caller must release the string. */ static char * issuer_fpr_string (PKT_signature *sig) { const byte *p; size_t n; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_ISSUER_FPR, &n); if (p && n == 21 && p[0] == 4) return bin2hex (p+1, n-1, NULL); return NULL; } static void print_good_bad_signature (int statno, const char *keyid_str, kbnode_t un, PKT_signature *sig, int rc) { char *p; write_status_text_and_buffer (statno, keyid_str, un? un->pkt->pkt.user_id->name:"[?]", un? un->pkt->pkt.user_id->len:3, -1); if (un) p = utf8_to_native (un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len, 0); else p = xstrdup ("[?]"); if (rc) log_info (_("BAD signature from \"%s\""), p); else if (sig->flags.expired) log_info (_("Expired signature from \"%s\""), p); else log_info (_("Good signature from \"%s\""), p); xfree (p); } static int check_sig_and_print (CTX c, kbnode_t node) { PKT_signature *sig = node->pkt->pkt.signature; const char *astr; int rc; int is_expkey = 0; int is_revkey = 0; char *issuer_fpr; PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */ if (opt.skip_verify) { log_info(_("signature verification suppressed\n")); return 0; } /* Check that the message composition is valid. * * Per RFC-2440bis (-15) allowed: * * S{1,n} -- detached signature. * S{1,n} P -- old style PGP2 signature * O{1,n} P S{1,n} -- standard OpenPGP signature. * C P S{1,n} -- cleartext signature. * * * O = One-Pass Signature packet. * S = Signature packet. * P = OpenPGP Message packet (Encrypted | Compressed | Literal) * (Note that the current rfc2440bis draft also allows * for a signed message but that does not work as it * introduces ambiguities.) * We keep track of these packages using the marker packet * CTRLPKT_PLAINTEXT_MARK. * C = Marker packet for cleartext signatures. * * We reject all other messages. * * Actually we are calling this too often, i.e. for verification of * each message but better have some duplicate work than to silently * introduce a bug here. */ { kbnode_t n; int n_onepass, n_sig; /* log_debug ("checking signature packet composition\n"); */ /* dump_kbnode (c->list); */ n = c->list; log_assert (n); if ( n->pkt->pkttype == PKT_SIGNATURE ) { /* This is either "S{1,n}" case (detached signature) or "S{1,n} P" (old style PGP2 signature). */ for (n = n->next; n; n = n->next) if (n->pkt->pkttype != PKT_SIGNATURE) break; if (!n) ; /* Okay, this is a detached signature. */ else if (n->pkt->pkttype == PKT_GPG_CONTROL && (n->pkt->pkt.gpg_control->control == CTRLPKT_PLAINTEXT_MARK) ) { if (n->next) goto ambiguous; /* We only allow one P packet. */ } else goto ambiguous; } else if (n->pkt->pkttype == PKT_ONEPASS_SIG) { /* This is the "O{1,n} P S{1,n}" case (standard signature). */ for (n_onepass=1, n = n->next; n && n->pkt->pkttype == PKT_ONEPASS_SIG; n = n->next) n_onepass++; if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL && (n->pkt->pkt.gpg_control->control == CTRLPKT_PLAINTEXT_MARK))) goto ambiguous; for (n_sig=0, n = n->next; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next) n_sig++; if (!n_sig) goto ambiguous; /* If we wanted to disallow multiple sig verification, we'd do something like this: if (n && !opt.allow_multisig_verification) goto ambiguous; However, now that we have --allow-multiple-messages, this can stay allowable as we can't get here unless multiple messages (i.e. multiple literals) are allowed. */ if (n_onepass != n_sig) { log_info ("number of one-pass packets does not match " "number of signature packets\n"); goto ambiguous; } } else if (n->pkt->pkttype == PKT_GPG_CONTROL && n->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START ) { /* This is the "C P S{1,n}" case (clear text signature). */ n = n->next; if (!n || !(n->pkt->pkttype == PKT_GPG_CONTROL && (n->pkt->pkt.gpg_control->control == CTRLPKT_PLAINTEXT_MARK))) goto ambiguous; for (n_sig=0, n = n->next; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next) n_sig++; if (n || !n_sig) goto ambiguous; } else { ambiguous: log_error(_("can't handle this ambiguous signature data\n")); return 0; } } if (sig->signers_uid) write_status_buffer (STATUS_NEWSIG, sig->signers_uid, strlen (sig->signers_uid), 0); else write_status_text (STATUS_NEWSIG, NULL); astr = openpgp_pk_algo_name ( sig->pubkey_algo ); - if (opt.flags.rfc4880bis && (issuer_fpr = issuer_fpr_string (sig))) + if ((issuer_fpr = issuer_fpr_string (sig))) { log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp)); log_info (_(" using %s key %s\n"), astr? astr: "?", issuer_fpr); xfree (issuer_fpr); } else if (!keystrlen () || keystrlen () > 8) { log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp)); log_info (_(" using %s key %s\n"), astr? astr: "?", keystr(sig->keyid)); } else /* Legacy format. */ log_info (_("Signature made %s using %s key ID %s\n"), asctimestamp(sig->timestamp), astr? astr: "?", keystr(sig->keyid)); /* In verbose mode print the signers UID. */ if (sig->signers_uid) log_info (_(" issuer \"%s\"\n"), sig->signers_uid); rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); /* If the key isn't found, check for a preferred keyserver. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks) { const byte *p; int seq = 0; size_t n; while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL))) { /* According to my favorite copy editor, in English grammar, you say "at" if the key is located on a web page, but "from" if it is located on a keyserver. I'm not going to even try to make two strings here :) */ log_info(_("Key available at: ") ); print_utf8_buffer (log_get_stream(), p, n); log_printf ("\n"); if (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) { struct keyserver_spec *spec; spec = parse_preferred_keyserver (sig); if (spec) { int res; free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); free_keyserver_spec (spec); if (!rc) break; } } } } /* If the avove methods didn't work, our next try is to use the URI * from a DNS PKA record. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE) && (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD)) { const char *uri = pka_uri_from_sig (c, sig); if (uri) { /* FIXME: We might want to locate the key using the fingerprint instead of the keyid. */ int res; struct keyserver_spec *spec; spec = parse_keyserver_uri (uri, 1); if (spec) { free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_keyid (c->ctrl, sig->keyid, spec, 1); glo_ctrl.in_auto_key_retrieve--; free_keyserver_spec (spec); if (!res) rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); } } } /* If the above methods didn't work, our next try is to locate * the key via its fingerprint from a keyserver. This requires * that the signers fingerprint is encoded in the signature. We * favor this over the WKD method (to be tried next), because an * arbitrary keyserver is less subject to web bug like monitoring. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY - && opt.flags.rfc4880bis && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) && keyserver_any_configured (c->ctrl)) { int res; const byte *p; size_t n; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_ISSUER_FPR, &n); if (p && n == 21 && p[0] == 4) { /* v4 packet with a SHA-1 fingerprint. */ free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_fprint (c->ctrl, p+1, n-1, opt.keyserver, 1); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); } } /* If the above methods didn't work, our next try is to retrieve the * key from the WKD. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE) && !opt.flags.disable_signer_uid && akl_has_wkd_method () && sig->signers_uid) { int res; free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL); glo_ctrl.in_auto_key_retrieve--; /* Fixme: If the fingerprint is embedded in the signature, * compare it to the fingerprint of the returned key. */ if (!res) rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); } /* If the above methods did't work, our next try is to use a * keyserver. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) && keyserver_any_configured (c->ctrl)) { int res; free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver, 1); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk); } if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) { kbnode_t un, keyblock; int count = 0; int statno; char keyid_str[50]; PKT_public_key *mainpk = NULL; if (rc) statno = STATUS_BADSIG; else if (sig->flags.expired) statno = STATUS_EXPSIG; else if (is_expkey) statno = STATUS_EXPKEYSIG; else if(is_revkey) statno = STATUS_REVKEYSIG; else statno = STATUS_GOODSIG; /* FIXME: We should have the public key in PK and thus the * keyboock has already been fetched. Thus we could use the * fingerprint or PK itself to lookup the entire keyblock. That * would best be done with a cache. */ keyblock = get_pubkeyblock (sig->keyid); snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ", (ulong)sig->keyid[0], (ulong)sig->keyid[1]); /* Find and print the primary user ID along with the "Good|Expired|Bad signature" line. */ for (un=keyblock; un; un = un->next) { int valid; if (un->pkt->pkttype==PKT_PUBLIC_KEY) { mainpk = un->pkt->pkt.public_key; continue; } if (un->pkt->pkttype != PKT_USER_ID) continue; if (!un->pkt->pkt.user_id->created) continue; if (un->pkt->pkt.user_id->is_revoked) continue; if (un->pkt->pkt.user_id->is_expired) continue; if (!un->pkt->pkt.user_id->is_primary) continue; /* We want the textual primary user ID here */ if (un->pkt->pkt.user_id->attrib_data) continue; log_assert (mainpk); /* Since this is just informational, don't actually ask the user to update any trust information. (Note: we register the signature later.) Because print_good_bad_signature does not print a LF we need to compute the validity before calling that function. */ if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) valid = get_validity (c->ctrl, mainpk, un->pkt->pkt.user_id, NULL, 0); else valid = 0; /* Not used. */ keyid_str[17] = 0; /* cut off the "[uncertain]" part */ print_good_bad_signature (statno, keyid_str, un, sig, rc); if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) log_printf (" [%s]\n",trust_value_to_string(valid)); else log_printf ("\n"); count++; } log_assert (mainpk); /* In case we did not found a valid valid textual userid above we print the first user id packet or a "[?]" instead along with the "Good|Expired|Bad signature" line. */ if (!count) { /* Try for an invalid textual userid */ for (un=keyblock; un; un = un->next) { if (un->pkt->pkttype == PKT_USER_ID && !un->pkt->pkt.user_id->attrib_data) break; } /* Try for any userid at all */ if (!un) { for (un=keyblock; un; un = un->next) { if (un->pkt->pkttype == PKT_USER_ID) break; } } if (opt.trust_model==TM_ALWAYS || !un) keyid_str[17] = 0; /* cut off the "[uncertain]" part */ print_good_bad_signature (statno, keyid_str, un, sig, rc); if (opt.trust_model != TM_ALWAYS && un) log_printf (" %s",_("[uncertain]") ); log_printf ("\n"); } /* If we have a good signature and already printed * the primary user ID, print all the other user IDs */ if (count && !rc && !(opt.verify_options & VERIFY_SHOW_PRIMARY_UID_ONLY)) { char *p; for( un=keyblock; un; un = un->next) { if (un->pkt->pkttype != PKT_USER_ID) continue; if ((un->pkt->pkt.user_id->is_revoked || un->pkt->pkt.user_id->is_expired) && !(opt.verify_options & VERIFY_SHOW_UNUSABLE_UIDS)) continue; /* Skip textual primary user ids which we printed above. */ if (un->pkt->pkt.user_id->is_primary && !un->pkt->pkt.user_id->attrib_data ) continue; /* If this user id has attribute data, print that. */ if (un->pkt->pkt.user_id->attrib_data) { dump_attribs (un->pkt->pkt.user_id, mainpk); if (opt.verify_options&VERIFY_SHOW_PHOTOS) show_photos (c->ctrl, un->pkt->pkt.user_id->attribs, un->pkt->pkt.user_id->numattribs, mainpk ,un->pkt->pkt.user_id); } p = utf8_to_native (un->pkt->pkt.user_id->name, un->pkt->pkt.user_id->len, 0); log_info (_(" aka \"%s\""), p); xfree (p); if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) { const char *valid; if (un->pkt->pkt.user_id->is_revoked) valid = _("revoked"); else if (un->pkt->pkt.user_id->is_expired) valid = _("expired"); else /* Since this is just informational, don't actually ask the user to update any trust information. */ valid = (trust_value_to_string (get_validity (c->ctrl, mainpk, un->pkt->pkt.user_id, NULL, 0))); log_printf (" [%s]\n",valid); } else log_printf ("\n"); } } /* For good signatures print notation data. */ if (!rc) { if ((opt.verify_options & VERIFY_SHOW_POLICY_URLS)) show_policy_url (sig, 0, 1); else show_policy_url (sig, 0, 2); if ((opt.verify_options & VERIFY_SHOW_KEYSERVER_URLS)) show_keyserver_url (sig, 0, 1); else show_keyserver_url (sig, 0, 2); if ((opt.verify_options & VERIFY_SHOW_NOTATIONS)) show_notation (sig, 0, 1, (((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0) + ((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0))); else show_notation (sig, 0, 2, 0); } /* For good signatures print the VALIDSIG status line. */ if (!rc && is_status_enabled () && pk) { char pkhex[MAX_FINGERPRINT_LEN*2+1]; char mainpkhex[MAX_FINGERPRINT_LEN*2+1]; hexfingerprint (pk, pkhex, sizeof pkhex); hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex); /* TODO: Replace the reserved '0' in the field below with bits for status flags (policy url, notation, etc.). */ write_status_printf (STATUS_VALIDSIG, "%s %s %lu %lu %d 0 %d %d %02X %s", pkhex, strtimestamp (sig->timestamp), (ulong)sig->timestamp, (ulong)sig->expiredate, sig->version, sig->pubkey_algo, sig->digest_algo, sig->sig_class, mainpkhex); } /* For good signatures compute and print the trust information. Note that in the Tofu trust model this may ask the user on how to resolve a conflict. */ if (!rc) { if ((opt.verify_options & VERIFY_PKA_LOOKUPS)) pka_uri_from_sig (c, sig); /* Make sure PKA info is available. */ rc = check_signatures_trust (c->ctrl, sig); } /* Print extra information about the signature. */ if (sig->flags.expired) { log_info (_("Signature expired %s\n"), asctimestamp(sig->expiredate)); rc = GPG_ERR_GENERAL; /* Need a better error here? */ } else if (sig->expiredate) log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate)); if (opt.verbose) { char pkstrbuf[PUBKEY_STRING_SIZE]; if (pk) pubkey_string (pk, pkstrbuf, sizeof pkstrbuf); else *pkstrbuf = 0; log_info (_("%s signature, digest algorithm %s%s%s\n"), sig->sig_class==0x00?_("binary"): sig->sig_class==0x01?_("textmode"):_("unknown"), gcry_md_algo_name (sig->digest_algo), *pkstrbuf?_(", key algorithm "):"", pkstrbuf); } /* Print final warnings. */ if (!rc && !c->signed_data.used) { /* Signature is basically good but we test whether the deprecated command gpg --verify FILE.sig was used instead of gpg --verify FILE.sig FILE to verify a detached signature. If we figure out that a data file with a matching name exists, we print a warning. The problem is that the first form would also verify a standard signature. This behavior could be used to create a made up .sig file for a tarball by creating a standard signature from a valid detached signature packet (for example from a signed git tag). Then replace the sig file on the FTP server along with a changed tarball. Using the first form the verify command would correctly verify the signature but don't even consider the tarball. */ kbnode_t n; char *dfile; dfile = get_matching_datafile (c->sigfilename); if (dfile) { for (n = c->list; n; n = n->next) if (n->pkt->pkttype != PKT_SIGNATURE) break; if (n) { /* Not only signature packets in the tree thus this is not a detached signature. */ log_info (_("WARNING: not a detached signature; " "file '%s' was NOT verified!\n"), dfile); } xfree (dfile); } } release_kbnode( keyblock ); if (rc) g10_errors_seen = 1; if (opt.batch && rc) g10_exit (1); } else { char buf[50]; snprintf (buf, sizeof buf, "%08lX%08lX %d %d %02x %lu %d", (ulong)sig->keyid[0], (ulong)sig->keyid[1], sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, rc); write_status_text (STATUS_ERRSIG, buf); if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY) { buf[16] = 0; write_status_text (STATUS_NO_PUBKEY, buf); } if (gpg_err_code (rc) != GPG_ERR_NOT_PROCESSED) log_error (_("Can't check signature: %s\n"), gpg_strerror (rc)); } return rc; } /* * Process the tree which starts at node */ static void proc_tree (CTX c, kbnode_t node) { kbnode_t n1; int rc; if (opt.list_packets || opt.list_only) return; /* We must skip our special plaintext marker packets here because they may be the root packet. These packets are only used in additional checks and skipping them here doesn't matter. */ while (node && node->pkt->pkttype == PKT_GPG_CONTROL && node->pkt->pkt.gpg_control->control == CTRLPKT_PLAINTEXT_MARK) { node = node->next; } if (!node) return; c->trustletter = ' '; if (node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) { merge_keys_and_selfsig (node); list_node (c, node); } else if (node->pkt->pkttype == PKT_SECRET_KEY) { merge_keys_and_selfsig (node); list_node (c, node); } else if (node->pkt->pkttype == PKT_ONEPASS_SIG) { /* Check all signatures. */ if (!c->any.data) { int use_textmode = 0; free_md_filter_context (&c->mfx); /* Prepare to create all requested message digests. */ rc = gcry_md_open (&c->mfx.md, 0, 0); if (rc) goto hash_err; /* Fixme: why looking for the signature packet and not the one-pass packet? */ for (n1 = node; (n1 = find_next_kbnode (n1, PKT_SIGNATURE));) gcry_md_enable (c->mfx.md, n1->pkt->pkt.signature->digest_algo); if (n1 && n1->pkt->pkt.onepass_sig->sig_class == 0x01) use_textmode = 1; /* Ask for file and hash it. */ if (c->sigs_only) { if (c->signed_data.used && c->signed_data.data_fd != -1) rc = hash_datafile_by_fd (c->mfx.md, NULL, c->signed_data.data_fd, use_textmode); else rc = hash_datafiles (c->mfx.md, NULL, c->signed_data.data_names, c->sigfilename, use_textmode); } else { rc = ask_for_detached_datafile (c->mfx.md, c->mfx.md2, iobuf_get_real_fname (c->iobuf), use_textmode); } hash_err: if (rc) { log_error ("can't hash datafile: %s\n", gpg_strerror (rc)); return; } } else if (c->signed_data.used) { log_error (_("not a detached signature\n")); return; } for (n1 = node; (n1 = find_next_kbnode (n1, PKT_SIGNATURE));) check_sig_and_print (c, n1); } else if (node->pkt->pkttype == PKT_GPG_CONTROL && node->pkt->pkt.gpg_control->control == CTRLPKT_CLEARSIGN_START) { /* Clear text signed message. */ if (!c->any.data) { log_error ("cleartext signature without data\n"); return; } else if (c->signed_data.used) { log_error (_("not a detached signature\n")); return; } for (n1 = node; (n1 = find_next_kbnode (n1, PKT_SIGNATURE));) check_sig_and_print (c, n1); } else if (node->pkt->pkttype == PKT_SIGNATURE) { PKT_signature *sig = node->pkt->pkt.signature; int multiple_ok = 1; n1 = find_next_kbnode (node, PKT_SIGNATURE); if (n1) { byte class = sig->sig_class; byte hash = sig->digest_algo; for (; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE))) { /* We can't currently handle multiple signatures of * different classes (we'd pretty much have to run a * different hash context for each), but if they are all * the same and it is detached signature, we make an * exception. Note that the old code also disallowed * multiple signatures if the digest algorithms are * different. We softened this restriction only for * detached signatures, to be on the safe side. */ if (n1->pkt->pkt.signature->sig_class != class || (c->any.data && n1->pkt->pkt.signature->digest_algo != hash)) { multiple_ok = 0; log_info (_("WARNING: multiple signatures detected. " "Only the first will be checked.\n")); break; } } } if (sig->sig_class != 0x00 && sig->sig_class != 0x01) { log_info(_("standalone signature of class 0x%02x\n"), sig->sig_class); } else if (!c->any.data) { /* Detached signature */ free_md_filter_context (&c->mfx); rc = gcry_md_open (&c->mfx.md, sig->digest_algo, 0); if (rc) goto detached_hash_err; if (multiple_ok) { /* If we have and want to handle multiple signatures we * need to enable all hash algorithms for the context. */ for (n1 = node; (n1 = find_next_kbnode (n1, PKT_SIGNATURE)); ) if (!openpgp_md_test_algo (n1->pkt->pkt.signature->digest_algo)) gcry_md_enable (c->mfx.md, map_md_openpgp_to_gcry (n1->pkt->pkt.signature->digest_algo)); } if (RFC2440 || RFC4880) ; /* Strict RFC mode. */ else if (sig->digest_algo == DIGEST_ALGO_SHA1 && sig->pubkey_algo == PUBKEY_ALGO_DSA && sig->sig_class == 0x01) { /* Enable a workaround for a pgp5 bug when the detached * signature has been created in textmode. Note that we * do not implement this for multiple signatures with * different hash algorithms. */ rc = gcry_md_open (&c->mfx.md2, sig->digest_algo, 0); if (rc) goto detached_hash_err; } /* Here we used to have another hack to work around a pgp * 2 bug: It worked by not using the textmode for detached * signatures; this would let the first signature check * (on md) fail but the second one (on md2), which adds an * extra CR would then have produced the "correct" hash. * This is very, very ugly hack but it may haved help in * some cases (and break others). * c->mfx.md2? 0 :(sig->sig_class == 0x01) */ if (DBG_HASHING) { gcry_md_debug (c->mfx.md, "verify"); if (c->mfx.md2) gcry_md_debug (c->mfx.md2, "verify2"); } if (c->sigs_only) { if (c->signed_data.used && c->signed_data.data_fd != -1) rc = hash_datafile_by_fd (c->mfx.md, c->mfx.md2, c->signed_data.data_fd, (sig->sig_class == 0x01)); else rc = hash_datafiles (c->mfx.md, c->mfx.md2, c->signed_data.data_names, c->sigfilename, (sig->sig_class == 0x01)); } else { rc = ask_for_detached_datafile (c->mfx.md, c->mfx.md2, iobuf_get_real_fname(c->iobuf), (sig->sig_class == 0x01)); } detached_hash_err: if (rc) { log_error ("can't hash datafile: %s\n", gpg_strerror (rc)); return; } } else if (c->signed_data.used) { log_error (_("not a detached signature\n")); return; } else if (!opt.quiet) log_info (_("old style (PGP 2.x) signature\n")); if (multiple_ok) { for (n1 = node; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE))) check_sig_and_print (c, n1); } else check_sig_and_print (c, node); } else { dump_kbnode (c->list); log_error ("invalid root packet detected in proc_tree()\n"); dump_kbnode (node); } }