diff --git a/g10/build-packet.c b/g10/build-packet.c index 78828c8dc..fd315b313 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -1,2215 +1,2220 @@ /* 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 "../common/util.h" #include "packet.h" #include "../common/status.h" #include "../common/iobuf.h" #include "../common/i18n.h" #include "options.h" #include "../common/host2net.h" static gpg_error_t do_ring_trust (iobuf_t out, PKT_ring_trust *rt); 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_encrypted_aead (iobuf_t 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 keyblock image from KEYBLOCK. Returns 0 on success and * only then stores a new iobuf object at R_IOBUF; the returned iobuf * can be access with the iobuf_get_temp_buffer and * iobuf_get_temp_length macros. */ gpg_error_t build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf) { gpg_error_t err; iobuf_t iobuf; kbnode_t kbctx, node; *r_iobuf = NULL; iobuf = iobuf_temp (); for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));) { /* Make sure to use only packets valid on a keyblock. */ switch (node->pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SIGNATURE: case PKT_USER_ID: case PKT_ATTRIBUTE: case PKT_RING_TRUST: break; default: continue; } err = build_packet_and_meta (iobuf, node->pkt); if (err) { iobuf_close (iobuf); return err; } } *r_iobuf = iobuf; return 0; } /* Build a packet and write it to the stream OUT. * Returns: 0 on success or on an error code. */ int build_packet (IOBUF out, PACKET *pkt) { int rc = 0; int new_ctb = 0; int ctb, 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: case PKT_ENCRYPTED_AEAD: 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_ENCRYPTED_AEAD: rc = do_encrypted_aead (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: /* Ignore it (only written by build_packet_and_meta) */ break; 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; } /* Build a packet and write it to the stream OUT. This variant also * writes the meta data using ring trust packets. Returns: 0 on * success or on error code. */ gpg_error_t build_packet_and_meta (iobuf_t out, PACKET *pkt) { gpg_error_t err; PKT_ring_trust rt = {0}; err = build_packet (out, pkt); if (err) ; else if (pkt->pkttype == PKT_SIGNATURE) { PKT_signature *sig = pkt->pkt.signature; rt.subtype = RING_TRUST_SIG; /* Note: trustval is not yet used. */ if (sig->flags.checked) { rt.sigcache = 1; if (sig->flags.valid) rt.sigcache |= 2; } err = do_ring_trust (out, &rt); } else if (pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE) { PKT_user_id *uid = pkt->pkt.user_id; rt.subtype = RING_TRUST_UID; rt.keyorg = uid->keyorg; rt.keyupdate = uid->keyupdate; rt.url = uid->updateurl; err = do_ring_trust (out, &rt); rt.url = NULL; } else if (pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_SECRET_KEY) { PKT_public_key *pk = pkt->pkt.public_key; rt.subtype = RING_TRUST_KEY; rt.keyorg = pk->keyorg; rt.keyupdate = pk->keyupdate; rt.url = pk->updateurl; err = do_ring_trust (out, &rt); rt.url = NULL; } return err; } /* * Write the mpi A to OUT. If R_NWRITTEN is not NULL the number of * bytes written is stored there. To only get the number of bytes * which would be written NULL may be passed for OUT. */ gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten) { gpg_error_t err; unsigned int nwritten = 0; 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) { /* First get nbits back to full bytes. */ nbits = ((nbits + 7) / 8) * 8; /* Then 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; err = out? iobuf_write (out, lenhdr, 2) : 0; if (!err) { nwritten += 2; if (p) { err = out? iobuf_write (out, p, (nbits+7)/8) : 0; if (!err) nwritten += (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); err = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a ); if (!err) { err = out? iobuf_write (out, buffer, nbytes) : 0; if (!err) nwritten += nbytes; } else if (gpg_err_code (err) == 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. */ err = gpg_error (GPG_ERR_TOO_LARGE); } } if (r_nwritten) *r_nwritten = nwritten; return err; } /* * Write the mpi A to the output stream OUT as "SOS" (Strange Octet * String). If R_NWRITTEN is not NULL the number of bytes written is * stored there. To only get the number of bytes which would be * written, NULL may be passed for OUT. */ static gpg_error_t sos_write (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten) { gpg_error_t err; unsigned int nwritten = 0; 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); /* gcry_log_debug (" [%u bit]\n", nbits); */ /* gcry_log_debughex (" ", p, (nbits+7)/8); */ if (p && *p) { nbits = ((nbits + 7) / 8) * 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; } lenhdr[0] = nbits >> 8; lenhdr[1] = nbits; err = out? iobuf_write (out, lenhdr, 2) : 0; if (!err) { nwritten += 2; if (p) { err = out? iobuf_write (out, p, (nbits+7)/8) : 0; if (!err) nwritten += (nbits+7)/8; } } } else { log_info ("non-opaque MPI (%u bits) for SOS\n", gcry_mpi_get_nbits (a)); err = gpg_error (GPG_ERR_INV_DATA); } if (r_nwritten) *r_nwritten = nwritten; return err; } /* * Write an opaque string to the output stream without length info. */ gpg_error_t gpg_mpi_write_opaque_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; } /* * Write an opaque MPI string with a four-byte octet count to the * output stream. If R_NWRITTEN is not NULL the number of written * bytes is stored there. OUT may be NULL in which case only * R_NWRITTEN is updated and error checking is done. */ gpg_error_t gpg_mpi_write_opaque_32 (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten) { gpg_error_t err; if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits, nbytes; const void *p; p = gcry_mpi_get_opaque (a, &nbits); nbytes = (nbits + 7)/8; if (out) { write_32 (out, nbytes); err = p ? iobuf_write (out, p, nbytes) : 0; } else err = 0; if (r_nwritten) *r_nwritten = 4 + (p? nbytes : 0); } else { err = gpg_error (GPG_ERR_BAD_MPI); if (r_nwritten) *r_nwritten = 0; } return err; } /* 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 ); } /* Write a ring trust meta packet. */ static gpg_error_t do_ring_trust (iobuf_t out, PKT_ring_trust *rt) { unsigned int namelen = 0; unsigned int pktlen = 6; if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID) { if (rt->url) namelen = strlen (rt->url); pktlen += 1 + 4 + 1 + namelen; } write_header (out, (0x80 | ((PKT_RING_TRUST & 15)<<2)), pktlen); iobuf_put (out, rt->trustval); iobuf_put (out, rt->sigcache); iobuf_write (out, "gpg", 3); iobuf_put (out, rt->subtype); if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID) { iobuf_put (out, rt->keyorg); write_32 (out, rt->keyupdate); iobuf_put (out, namelen); if (namelen) iobuf_write (out, rt->url, namelen); } return 0; } /* 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; int hdrlen; log_assert (ctb_pkttype (ctb) == PKT_USER_ID || ctb_pkttype (ctb) == PKT_ATTRIBUTE); /* We need to take special care of a user ID with a length of 0: * Without forcing HDRLEN to 2 in this case an indeterminate length * packet would be written which is not allowed. Note that we are * always called with a CTB indicating an old packet header format, * so that forcing a 2 octet header works. We also check for the * maximum allowed packet size by the parser using an arbitrary * extra 10 bytes for header data. */ if (uid->attrib_data) { if (uid->attrib_len > MAX_ATTR_PACKET_LENGTH - 10) return gpg_error (GPG_ERR_TOO_LARGE); hdrlen = uid->attrib_len? 0 : 2; write_header2 (out, ctb, uid->attrib_len, hdrlen); rc = iobuf_write( out, uid->attrib_data, uid->attrib_len ); } else { if (uid->len > MAX_UID_PACKET_LENGTH - 10) return gpg_error (GPG_ERR_TOO_LARGE); hdrlen = uid->len? 0 : 2; write_header2 (out, ctb, uid->len, hdrlen); 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; iobuf_t a; int i, nskey, npkey; u32 pkbytes = 0; int is_v5; log_assert (pk->version == 0 || pk->version == 4 || pk->version == 5); 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); /* 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 content * of this buffer to OUT. */ a = iobuf_temp(); /* Note that the Version number, Timestamp, Algo, and the v5 Key * material count are written at the end of the function. */ is_v5 = (pk->version == 5); /* 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)) || (pk->pubkey_algo == PUBKEY_ALGO_KYBER && (i == 0))) err = gpg_mpi_write_opaque_nohdr (a, pk->pkey[i]); else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2) { /* Write a four-octet count prefixed Kyber public key. */ err = gpg_mpi_write_opaque_32 (a, pk->pkey[2], NULL); } else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA || pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_ECDH) err = sos_write (a, pk->pkey[i], NULL); else err = gpg_mpi_write (a, pk->pkey[i], NULL); if (err) goto leave; } /* Record the length of the public key part. */ pkbytes = iobuf_get_temp_length (a); 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) { iobuf_put (a, ski->sha1chk? 0xfe : 0xff); /* S2k usage. */ if (is_v5) { /* For a v5 key determine the count of the following * key-protection material and write it. */ int count = 1; /* Pubkey algo octet. */ if (ski->s2k.mode >= 1000) count += 6; /* GNU specific mode descriptor. */ else count += 2; /* Mode and hash algo. */ if (ski->s2k.mode == 1 || ski->s2k.mode == 3) count += 8; /* Salt. */ if (ski->s2k.mode == 3) count++; /* S2K.COUNT */ if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002 && ski->s2k.mode != 1003) count += ski->ivlen; iobuf_put (a, count); } iobuf_put (a, ski->algo); /* Pubkey algo octet. */ 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..1003 we do not need an IV. */ if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002 && ski->s2k.mode != 1003) iobuf_write (a, ski->iv, ski->ivlen); } else /* Not protected. */ { iobuf_put (a, 0 ); /* S2K usage = not protected. */ if (is_v5) iobuf_put (a, 0); /* Zero octets of key-protection * material follows. */ } if (ski->s2k.mode == 1001) { /* GnuPG extension - don't write a secret key at all. */ if (is_v5) write_32 (a, 0); /* Zero octets of key material. */ } else if (ski->s2k.mode == 1002) { /* GnuPG extension - divert to OpenPGP smartcard. */ if (is_v5) write_32 (a, 1 + ski->ivlen); /* 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->s2k.mode == 1003) { /* GnuPG extension - Store raw s-expression. */ 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); /* For v5 keys we first write the number of octets of the * following key material. */ if (is_v5) write_32 (a, p? (ndatabits+7)/8 : 0); if (p) iobuf_write (a, p, (ndatabits+7)/8 ); } 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); /* For v5 keys we first write the number of octets of the * following encrypted key material. */ if (is_v5) write_32 (a, p? (ndatabits+7)/8 : 0); if (p) iobuf_write (a, p, (ndatabits+7)/8 ); } else { /* Non-protected key. */ if (is_v5) { unsigned int skbytes = 0; unsigned int n; int j; for (j=i; j < nskey; j++ ) { if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && j == 4) { if ((err=gpg_mpi_write_opaque_32 (NULL,pk->pkey[j], &n))) goto leave; } else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA || pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_ECDH || pk->pubkey_algo == PUBKEY_ALGO_KYBER) { if ((err = sos_write (NULL, pk->pkey[j], &n))) goto leave; } else { if ( (err = gpg_mpi_write (a, pk->pkey[i], NULL))) goto leave; } skbytes += n; } write_32 (a, skbytes); } for ( ; i < nskey; i++ ) { if (pk->pubkey_algo == PUBKEY_ALGO_KYBER && i == 4) { err = gpg_mpi_write_opaque_32 (a, pk->pkey[i], NULL); if (err) goto leave; } else if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA || pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_ECDH) { if ((err = sos_write (a, pk->pkey[i], NULL))) goto leave; } else { if ((err = gpg_mpi_write (a, pk->pkey[i], NULL))) 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 */ u32 len = iobuf_get_temp_length (a); len += 1; /* version number */ len += 4; /* timestamp */ len += 1; /* algo */ if (is_v5) len += 4; /* public key material count */ write_header2 (out, ctb, len, 0); /* And finally write it out to the real stream. */ iobuf_put (out, pk->version? pk->version : 4); /* version number */ write_32 (out, pk->timestamp ); iobuf_put (out, pk->pubkey_algo); /* algo */ if (is_v5) write_32 (out, pkbytes); /* public key material count */ err = iobuf_write_temp (out, a); /* pub and sec key material */ } 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); log_assert (enc->version == 4 || enc->version == 5); switch (enc->s2k.mode) { case 0: /* Simple S2K. */ case 1: /* Salted S2K. */ case 3: /* Iterated and salted S2K. */ break; /* Reasonable values. */ default: log_bug ("do_symkey_enc: s2k=%d\n", enc->s2k.mode); } iobuf_put (a, enc->version); iobuf_put (a, enc->cipher_algo); if (enc->version == 5) iobuf_put (a, enc->aead_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++ ) { + /* For Kyber we need to insert the algo before the final data + * element because it is not stored in the data array. */ + if (enc->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2) + iobuf_put (a, enc->seskey_algo); + if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1) rc = gpg_mpi_write_opaque_nohdr (a, enc->data[i]); else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH) rc = sos_write (a, enc->data[i], NULL); else rc = gpg_mpi_write (a, enc->data[i], NULL); } 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 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 (nbytes == (size_t)(-1) && (iobuf_error (out) || iobuf_error (pt->buf))) return iobuf_error (out)? iobuf_error (out):iobuf_error (pt->buf); /* Always get the error to catch write errors because * iobuf_copy does not reliable return (-1) in that case. */ rc = iobuf_error (out); 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 ); if (!rc) /* Just in case no error was set */ rc = gpg_error (GPG_ERR_EIO); } } 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 symmetrically AEAD encrypted data packet * (rfc4880bis-03, Section 5.16) described by ED and write it to OUT. * * Note: this only writes only packet's header. The caller must then * follow up and write the actual encrypted data. This should be done * by pushing the the cipher_filter_aead. */ static int do_encrypted_aead (iobuf_t out, int ctb, PKT_encrypted *ed) { u32 n; log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED_AEAD); n = ed->len ? (ed->len + ed->extralen + 4) : 0; write_header (out, ctb, n ); iobuf_writebyte (out, 1); /* Version. */ iobuf_writebyte (out, ed->cipher_algo); iobuf_writebyte (out, ed->aead_algo); iobuf_writebyte (out, ed->chunkbyte); /* This is all. The caller has to write the encrypted data */ return 0; } /* 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. SIGNHINTS are various flags like * SIGNHINT_ADSK. * 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, unsigned int signhints) { 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. We also don't write it if * only the new RENC keyflag is set (implementations with support * for this key flag should understand the ISSUER_FPR). */ if (pksk->version < 5 && !(signhints & SIGNHINT_ADSK)) { 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); } /* Write the new ISSUER_FPR subpacket. */ fingerprint_from_pk (pksk, buf+1, &fprlen); if (fprlen == 20 || fprlen == 32) { buf[0] = pksk->version; build_sig_subpkt (sig, SIGSUBPKT_ISSUER_FPR, buf, fprlen + 1); } /* 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); memcpy(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, 1, 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; } /* Return a list of notation data matching NAME. The caller needs to * to free the list using free_notation. Other than sig_to_notation * this function does not return the notation in human readable format * but always returns the raw data. The human readable flag is set * anyway set but .value is always NULL. */ struct notation * search_sig_notations (PKT_signature *sig, const char *name) { const byte *p; size_t len; int seq = 0; int crit; notation_t list = NULL; while((p=enum_sig_subpkt (sig, 1, 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; } if (!name) ; /* Return everything. */ else if (n1 != strlen (name) || memcmp (p+8, name, n1)) continue; /* Not the requested name. */ n = xmalloc_clear (sizeof *n); n->name = xmalloc (n1+1); memcpy (n->name,p + 8, n1); n->name[n1]='\0'; /* In any case append a Nul. */ n->bdat = xmalloc (n2+1); memcpy (n->bdat, p + 8 + n1, n2); n->bdat[n2] = '\0'; n->blen = n2; n->flags.human = !!(p[0] & 0x80); 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. Actually we * should never get to here but real life is different and thus * we now use a log_fatal instead of a log_assert here. */ if (sig->hashed || sig->unhashed) log_fatal ("trying to write a subpacket to a v3 signature (%d,%d)\n", !!sig->hashed, !!sig->unhashed); } else iobuf_put( a, sig->version ); if ( sig->version < 4 ) iobuf_put (a, 5 ); /* Constant used by pre-v4 signatures. */ 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] ); if (sig->pubkey_algo == PUBKEY_ALGO_ECDSA || sig->pubkey_algo == PUBKEY_ALGO_EDDSA) for (i=0; i < n && !rc ; i++ ) rc = sos_write (a, sig->data[i], NULL); else for (i=0; i < n && !rc ; i++ ) rc = gpg_mpi_write (a, sig->data[i], NULL); 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/encrypt.c b/g10/encrypt.c index aa0c3c6dd..f416cde53 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -1,1249 +1,1250 @@ /* encrypt.c - Main encryption driver * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * 2006, 2009 Free Software Foundation, Inc. * Copyright (C) 2016, 2023 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: GPL-3.0-or-later */ #include #include #include #include #include #include "gpg.h" #include "options.h" #include "packet.h" #include "../common/status.h" #include "../common/iobuf.h" #include "keydb.h" #include "../common/util.h" #include "main.h" #include "filter.h" #include "trustdb.h" #include "../common/i18n.h" #include "../common/status.h" #include "pkglue.h" #include "../common/compliance.h" static int encrypt_simple( const char *filename, int mode, int use_seskey ); static int write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out); /**************** * Encrypt FILENAME with only the symmetric cipher. Take input from * stdin if FILENAME is NULL. If --force-aead is used we use an SKESK. */ int encrypt_symmetric (const char *filename) { return encrypt_simple( filename, 1, opt.force_aead); } /**************** * Encrypt FILENAME as a literal data packet only. Take input from * stdin if FILENAME is NULL. */ int encrypt_store (const char *filename) { return encrypt_simple( filename, 0, 0 ); } /* Create and setup a DEK structure and print approriate warnings. * PK_LIST gives the list of public keys. Always returns a DEK. The * actual session needs to be added later. */ static DEK * create_dek_with_warnings (pk_list_t pk_list) { DEK *dek; dek = xmalloc_secure_clear (sizeof *dek); if (!opt.def_cipher_algo) { /* Try to get it from the prefs. */ dek->algo = select_algo_from_prefs (pk_list, PREFTYPE_SYM, -1, NULL); if (dek->algo == -1) { /* If does not make sense to fallback to the rfc4880 * required 3DES if we will reject that algo later. Thus we * fallback to AES anticipating RFC4880bis rules. */ if (opt.flags.allow_old_cipher_algos) dek->algo = CIPHER_ALGO_3DES; else dek->algo = CIPHER_ALGO_AES; } /* In case 3DES has been selected, print a warning if any key * does not have a preference for AES. This should help to * indentify why encrypting to several recipients falls back to * 3DES. */ if (opt.verbose && dek->algo == CIPHER_ALGO_3DES) warn_missing_aes_from_pklist (pk_list); } else { if (!opt.expert && (select_algo_from_prefs (pk_list, PREFTYPE_SYM, opt.def_cipher_algo, NULL) != opt.def_cipher_algo)) { log_info(_("WARNING: forcing symmetric cipher %s (%d)" " violates recipient preferences\n"), openpgp_cipher_algo_name (opt.def_cipher_algo), opt.def_cipher_algo); } dek->algo = opt.def_cipher_algo; } return dek; } /* Check whether all encryption keys are compliant with the current * mode and issue respective status lines. DEK has the info about the * session key and PK_LIST the list of public keys. */ static gpg_error_t check_encryption_compliance (DEK *dek, pk_list_t pk_list) { gpg_error_t err = 0; pk_list_t pkr; int compliant; /* First check whether we should use the algo at all. */ if (openpgp_cipher_blocklen (dek->algo) < 16 && !opt.flags.allow_old_cipher_algos) { log_error (_("cipher algorithm '%s' may not be used for encryption\n"), openpgp_cipher_algo_name (dek->algo)); if (!opt.quiet) log_info (_("(use option \"%s\" to override)\n"), "--allow-old-cipher-algos"); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } /* Now check the compliance. */ if (! gnupg_cipher_is_allowed (opt.compliance, 1, dek->algo, GCRY_CIPHER_MODE_CFB)) { log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (dek->algo), gnupg_compliance_option_string (opt.compliance)); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } if (!gnupg_rng_is_compliant (opt.compliance)) { err = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", err); goto leave; } /* From here on we only test for CO_DE_VS - if we ever want to * return other compliance mode values we need to change this to * loop over all those values. */ compliant = gnupg_gcrypt_is_compliant (CO_DE_VS); if (!gnupg_cipher_is_compliant (CO_DE_VS, dek->algo, GCRY_CIPHER_MODE_CFB)) compliant = 0; for (pkr = pk_list; pkr; pkr = pkr->next) { PKT_public_key *pk = pkr->pk; unsigned int nbits = nbits_from_pk (pk); if (!gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0, pk->pkey, nbits, NULL)) log_info (_("WARNING: key %s is not suitable for encryption" " in %s mode\n"), keystr_from_pk (pk), gnupg_compliance_option_string (opt.compliance)); if (compliant && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey, nbits, NULL)) compliant = 0; /* Not compliant - reset flag. */ } /* If we are compliant print the status for de-vs compliance. */ if (compliant) write_status_strings (STATUS_ENCRYPTION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS), NULL); /* Check whether we should fail the operation. */ if (opt.flags.require_compliance && opt.compliance == CO_DE_VS && !compliant) { compliance_failure (); err = gpg_error (GPG_ERR_FORBIDDEN); goto leave; } leave: return err; } /* Encrypt a session key using DEK and store a pointer to the result * at R_ENCKEY and its length at R_ENCKEYLEN. * * R_SESKEY points to the unencrypted session key (.KEY, .KEYLEN) and * the algorithm that will be used to encrypt the contents of the * SKESK packet (.ALGO). If R_SESKEY points to NULL, then a random * session key that is appropriate for DEK->ALGO is generated and * stored at R_SESKEY. If AEAD_ALGO is not 0 the given AEAD algorithm * is used for encryption. */ static gpg_error_t encrypt_seskey (DEK *dek, aead_algo_t aead_algo, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen) { gpg_error_t err; gcry_cipher_hd_t hd = NULL; byte *buf = NULL; DEK *seskey; *r_enckey = NULL; *r_enckeylen = 0; if (*r_seskey) seskey = *r_seskey; else { seskey = xtrycalloc (1, sizeof(DEK)); if (!seskey) { err = gpg_error_from_syserror (); goto leave; } seskey->algo = dek->algo; make_session_key (seskey); /*log_hexdump( "thekey", c->key, c->keylen );*/ } if (aead_algo) { unsigned int noncelen; enum gcry_cipher_modes ciphermode; byte ad[4]; err = openpgp_aead_algo_info (aead_algo, &ciphermode, &noncelen); if (err) goto leave; /* Allocate space for the nonce, the key, and the authentication * tag (16). */ buf = xtrymalloc_secure (noncelen + seskey->keylen + 16); if (!buf) { err = gpg_error_from_syserror (); goto leave; } gcry_randomize (buf, noncelen, GCRY_STRONG_RANDOM); err = openpgp_cipher_open (&hd, dek->algo, ciphermode, GCRY_CIPHER_SECURE); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, buf, noncelen); if (err) goto leave; ad[0] = (0xc0 | PKT_SYMKEY_ENC); ad[1] = 5; ad[2] = dek->algo; ad[3] = aead_algo; err = gcry_cipher_authenticate (hd, ad, 4); if (err) goto leave; memcpy (buf + noncelen, seskey->key, seskey->keylen); gcry_cipher_final (hd); err = gcry_cipher_encrypt (hd, buf + noncelen, seskey->keylen, NULL,0); if (err) goto leave; err = gcry_cipher_gettag (hd, buf + noncelen + seskey->keylen, 16); if (err) goto leave; *r_enckeylen = noncelen + seskey->keylen + 16; *r_enckey = buf; buf = NULL; } else { /* In the old version 4 SKESK the encrypted session key is * prefixed with a one-octet algorithm id. */ buf = xtrymalloc_secure (1 + seskey->keylen); if (!buf) { err = gpg_error_from_syserror (); goto leave; } buf[0] = seskey->algo; memcpy (buf + 1, seskey->key, seskey->keylen); err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, NULL, 0); if (!err) err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0); if (err) goto leave; *r_enckeylen = seskey->keylen + 1; *r_enckey = buf; buf = NULL; } /* Return the session key in case we allocated it. */ *r_seskey = seskey; seskey = NULL; leave: gcry_cipher_close (hd); if (seskey != *r_seskey) xfree (seskey); xfree (buf); return err; } /* Return the AEAD algo if we shall use AEAD mode. Returns 0 if AEAD * shall not be used. */ aead_algo_t use_aead (pk_list_t pk_list, int algo) { int can_use; can_use = openpgp_cipher_get_algo_blklen (algo) == 16; /* With --force-aead we want AEAD. */ if (opt.force_aead) { if (!can_use) { log_info ("Warning: request to use OCB ignored for cipher '%s'\n", openpgp_cipher_algo_name (algo)); return 0; } return AEAD_ALGO_OCB; } /* AEAD does only work with 128 bit cipher blocklength. */ if (!can_use) return 0; /* Note the user which keys have no AEAD feature flag set. */ if (opt.verbose) warn_missing_aead_from_pklist (pk_list); /* If all keys support AEAD we can use it. */ return select_aead_from_pklist (pk_list); } /* Shall we use the MDC? Yes - unless rfc-2440 compatibility is * requested. */ int use_mdc (pk_list_t pk_list,int algo) { (void)pk_list; (void)algo; /* RFC-2440 don't has MDC - this is the only way to create a legacy * non-MDC encryption packet. */ if (RFC2440) return 0; return 1; /* In all other cases we use the MDC */ } /* We don't want to use use_seskey yet because older gnupg versions can't handle it, and there isn't really any point unless we're making a message that can be decrypted by a public key or passphrase. */ static int encrypt_simple (const char *filename, int mode, int use_seskey) { iobuf_t inp, out; PACKET pkt; PKT_plaintext *pt = NULL; STRING2KEY *s2k = NULL; void *enckey = NULL; size_t enckeylen = 0; int rc = 0; u32 filesize; cipher_filter_context_t cfx; armor_filter_context_t *afx = NULL; compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t *pfx; int do_compress = !!default_compress_algo(); if (!gnupg_rng_is_compliant (opt.compliance)) { rc = gpg_error (GPG_ERR_FORBIDDEN); log_error (_("%s is not compliant with %s mode\n"), "RNG", gnupg_compliance_option_string (opt.compliance)); write_status_error ("random-compliance", rc); return rc; } pfx = new_progress_context (); memset( &cfx, 0, sizeof cfx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet(&pkt); /* Prepare iobufs. */ inp = iobuf_open(filename); if (inp) iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { rc = gpg_error_from_syserror (); log_error(_("can't open '%s': %s\n"), filename? filename: "[stdin]", strerror(errno) ); release_progress_context (pfx); return rc; } handle_progress (pfx, inp, filename); if (opt.textmode) iobuf_push_filter( inp, text_filter, &tfx ); cfx.dek = NULL; if ( mode ) { aead_algo_t aead_algo; rc = setup_symkey (&s2k, &cfx.dek); if (rc) { iobuf_close (inp); if (gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO || gpg_err_code (rc) == GPG_ERR_DIGEST_ALGO) ; /* Error has already been printed. */ else log_error (_("error creating passphrase: %s\n"), gpg_strerror (rc)); release_progress_context (pfx); return rc; } if (use_seskey && s2k->mode != 1 && s2k->mode != 3) { use_seskey = 0; log_info (_("can't use a SKESK packet due to the S2K mode\n")); } /* See whether we want to use AEAD. */ aead_algo = use_aead (NULL, cfx.dek->algo); if ( use_seskey ) { DEK *dek = NULL; rc = encrypt_seskey (cfx.dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) { xfree (cfx.dek); xfree (s2k); iobuf_close (inp); release_progress_context (pfx); return rc; } /* Replace key in DEK. */ xfree (cfx.dek); cfx.dek = dek; } if (aead_algo) cfx.dek->use_aead = aead_algo; else cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); if (opt.verbose) log_info(_("using cipher %s.%s\n"), openpgp_cipher_algo_name (cfx.dek->algo), cfx.dek->use_aead? openpgp_aead_algo_name (cfx.dek->use_aead) /**/ : "CFB"); } if (rc || (rc = open_outfile (GNUPG_INVALID_FD, filename, opt.armor? 1:0, 0, &out ))) { iobuf_cancel (inp); xfree (cfx.dek); xfree (s2k); release_progress_context (pfx); return rc; } if ( opt.armor ) { afx = new_armor_context (); push_armor_filter (afx, out); } if ( s2k ) { /* Fixme: This is quite similar to write_symkey_enc. */ PKT_symkey_enc *enc = xmalloc_clear (sizeof *enc + enckeylen); enc->version = cfx.dek->use_aead ? 5 : 4; enc->cipher_algo = cfx.dek->algo; enc->aead_algo = cfx.dek->use_aead; enc->s2k = *s2k; if (enckeylen) { enc->seskeylen = enckeylen; memcpy (enc->seskey, enckey, enckeylen); } pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if ((rc = build_packet( out, &pkt ))) log_error("build symkey packet failed: %s\n", gpg_strerror (rc) ); xfree (enc); xfree (enckey); enckey = NULL; } if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); /* Note that PGP 5 has problems decrypting symmetrically encrypted data if the file length is in the inner packet. It works when only partial length headers are use. In the past, we always used partial body length here, but since PGP 2, PGP 6, and PGP 7 need the file length, and nobody should be using PGP 5 nowadays anyway, this is now set to the file length. Note also that this only applies to the RFC-1991 style symmetric messages, and not the RFC-2440 style. PGP 6 and 7 work with either partial length or fixed length with the new style messages. */ if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) { uint64_t tmpsize; tmpsize = iobuf_get_filelength(inp); if (!tmpsize && opt.verbose) log_info(_("WARNING: '%s' is an empty file\n"), filename ); /* We can't encode the length of very large files because OpenPGP uses only 32 bit for file sizes. So if the size of a file is larger than 2^32 minus some bytes for packet headers, we switch to partial length encoding. */ if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; } else filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ /* Register the cipher filter. */ if (mode) iobuf_push_filter (out, cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &cfx ); if (do_compress && cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead) && !opt.explicit_compress_option && is_file_compressed (inp)) { if (opt.verbose) log_info(_("'%s' already compressed\n"), filename? filename: "[stdin]"); do_compress = 0; } if (!opt.no_literal) { /* Note that PT has been initialized above in !no_literal mode. */ pt->timestamp = make_timestamp(); pt->mode = opt.mimemode? 'm' : opt.textmode? 't' : 'b'; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0; } else { cfx.datalen = filesize && !do_compress ? filesize : 0; pkt.pkttype = 0; pkt.pkt.generic = NULL; } /* Register the compress filter. */ if ( do_compress ) { if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead)) zfx.new_ctb = 1; push_compress_filter (out, &zfx, default_compress_algo()); } /* Do the work. */ if (!opt.no_literal) { if ( (rc = build_packet( out, &pkt )) ) log_error("build_packet failed: %s\n", gpg_strerror (rc) ); } else { /* User requested not to create a literal packet, so we copy the plain data. */ rc = iobuf_copy (out, inp); if (rc) log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); } /* Finish the stuff. */ iobuf_close (inp); if (rc) iobuf_cancel(out); else { iobuf_close (out); /* fixme: check returncode */ if (mode) write_status ( STATUS_END_ENCRYPTION ); } if (pt) pt->buf = NULL; free_packet (&pkt, NULL); xfree (enckey); xfree (cfx.dek); xfree (s2k); release_armor_context (afx); release_progress_context (pfx); return rc; } gpg_error_t setup_symkey (STRING2KEY **symkey_s2k, DEK **symkey_dek) { int canceled; int defcipher; int s2kdigest; defcipher = default_cipher_algo (); if (openpgp_cipher_blocklen (defcipher) < 16 && !opt.flags.allow_old_cipher_algos) { log_error (_("cipher algorithm '%s' may not be used for encryption\n"), openpgp_cipher_algo_name (defcipher)); if (!opt.quiet) log_info (_("(use option \"%s\" to override)\n"), "--allow-old-cipher-algos"); return gpg_error (GPG_ERR_CIPHER_ALGO); } if (!gnupg_cipher_is_allowed (opt.compliance, 1, defcipher, GCRY_CIPHER_MODE_CFB)) { log_error (_("cipher algorithm '%s' may not be used in %s mode\n"), openpgp_cipher_algo_name (defcipher), gnupg_compliance_option_string (opt.compliance)); return gpg_error (GPG_ERR_CIPHER_ALGO); } s2kdigest = S2K_DIGEST_ALGO; if (!gnupg_digest_is_allowed (opt.compliance, 1, s2kdigest)) { log_error (_("digest algorithm '%s' may not be used in %s mode\n"), gcry_md_algo_name (s2kdigest), gnupg_compliance_option_string (opt.compliance)); return gpg_error (GPG_ERR_DIGEST_ALGO); } *symkey_s2k = xmalloc_clear (sizeof **symkey_s2k); (*symkey_s2k)->mode = opt.s2k_mode; (*symkey_s2k)->hash_algo = s2kdigest; *symkey_dek = passphrase_to_dek (defcipher, *symkey_s2k, 1, 0, NULL, 0, &canceled); if (!*symkey_dek || !(*symkey_dek)->keylen) { xfree(*symkey_dek); xfree(*symkey_s2k); return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE); } return 0; } static int write_symkey_enc (STRING2KEY *symkey_s2k, aead_algo_t aead_algo, DEK *symkey_dek, DEK *dek, iobuf_t out) { int rc; void *enckey; size_t enckeylen; PKT_symkey_enc *enc; PACKET pkt; rc = encrypt_seskey (symkey_dek, aead_algo, &dek, &enckey, &enckeylen); if (rc) return rc; enc = xtrycalloc (1, sizeof (PKT_symkey_enc) + enckeylen); if (!enc) { rc = gpg_error_from_syserror (); xfree (enckey); return rc; } enc->version = aead_algo? 5 : 4; enc->cipher_algo = opt.s2k_cipher_algo; enc->aead_algo = aead_algo; enc->s2k = *symkey_s2k; enc->seskeylen = enckeylen; memcpy (enc->seskey, enckey, enckeylen); xfree (enckey); pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkt.symkey_enc = enc; if ((rc=build_packet(out,&pkt))) log_error("build symkey_enc packet failed: %s\n",gpg_strerror (rc)); xfree (enc); return rc; } /* * Encrypt the file with the given userids (or ask if none is * supplied). Either FILENAME or FILEFD must be given, but not both. * The caller may provide a checked list of public keys in * PROVIDED_KEYS; if not the function builds a list of keys on its own. * * Note that FILEFD is currently only used by cmd_encrypt in the * not yet finished server.c. */ int encrypt_crypt (ctrl_t ctrl, gnupg_fd_t filefd, const char *filename, strlist_t remusr, int use_symkey, pk_list_t provided_keys, gnupg_fd_t outputfd) { iobuf_t inp = NULL; iobuf_t out = NULL; PACKET pkt; PKT_plaintext *pt = NULL; DEK *symkey_dek = NULL; STRING2KEY *symkey_s2k = NULL; int rc = 0; u32 filesize; cipher_filter_context_t cfx; armor_filter_context_t *afx = NULL; compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t *pfx; PK_LIST pk_list; int do_compress; if (filefd != GNUPG_INVALID_FD && filename) return gpg_error (GPG_ERR_INV_ARG); /* Both given. */ do_compress = !!opt.compress_algo; pfx = new_progress_context (); memset( &cfx, 0, sizeof cfx); memset( &zfx, 0, sizeof zfx); memset( &tfx, 0, sizeof tfx); init_packet(&pkt); if (use_symkey && (rc=setup_symkey(&symkey_s2k,&symkey_dek))) { release_progress_context (pfx); return rc; } if (provided_keys) pk_list = provided_keys; else { if ((rc = build_pk_list (ctrl, remusr, &pk_list))) { release_progress_context (pfx); return rc; } } /* Prepare iobufs. */ #ifdef HAVE_W32_SYSTEM if (filefd == GNUPG_INVALID_FD) inp = iobuf_open (filename); else { inp = NULL; gpg_err_set_errno (ENOSYS); } #else if (filefd == GNUPG_INVALID_FD) inp = iobuf_open (filename); else inp = iobuf_fdopen_nc (filefd, "rb"); #endif if (inp) iobuf_ioctl (inp, IOBUF_IOCTL_NO_CACHE, 1, NULL); if (inp && is_secured_file (iobuf_get_fd (inp))) { iobuf_close (inp); inp = NULL; gpg_err_set_errno (EPERM); } if (!inp) { char xname[64]; rc = gpg_error_from_syserror (); if (filefd != GNUPG_INVALID_FD) snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (filefd)); else if (!filename) strcpy (xname, "[stdin]"); else *xname = 0; log_error (_("can't open '%s': %s\n"), *xname? xname : filename, gpg_strerror (rc) ); goto leave; } if (opt.verbose) log_info (_("reading from '%s'\n"), iobuf_get_fname_nonnull (inp)); handle_progress (pfx, inp, filename); if (opt.textmode) iobuf_push_filter (inp, text_filter, &tfx); rc = open_outfile (outputfd, filename, opt.armor? 1:0, 0, &out); if (rc) goto leave; if (opt.armor) { afx = new_armor_context (); push_armor_filter (afx, out); } /* Create a session key. */ cfx.dek = create_dek_with_warnings (pk_list); rc = check_encryption_compliance (cfx.dek, pk_list); if (rc) goto leave; cfx.dek->use_aead = use_aead (pk_list, cfx.dek->algo); if (!cfx.dek->use_aead) cfx.dek->use_mdc = !!use_mdc (pk_list, cfx.dek->algo); make_session_key (cfx.dek); if (DBG_CRYPTO) log_printhex (cfx.dek->key, cfx.dek->keylen, "DEK is: "); rc = write_pubkey_enc_from_list (ctrl, pk_list, cfx.dek, out); if (rc) goto leave; /* We put the passphrase (if any) after any public keys as this * seems to be the most useful on the recipient side - there is no * point in prompting a user for a passphrase if they have the * secret key needed to decrypt. */ if (use_symkey && (rc = write_symkey_enc (symkey_s2k, cfx.dek->use_aead, symkey_dek, cfx.dek, out))) goto leave; if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); /* Get the size of the file if possible, i.e., if it is a real file. */ if (filename && *filename && !iobuf_is_pipe_filename (filename) && !opt.textmode ) { uint64_t tmpsize; tmpsize = iobuf_get_filelength (inp); if (!tmpsize && opt.verbose) log_info(_("WARNING: '%s' is an empty file\n"), filename ); /* We can't encode the length of very large files because OpenPGP uses only 32 bit for file sizes. So if the size of a file is larger than 2^32 minus some bytes for packet headers, we switch to partial length encoding. */ if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) ) filesize = tmpsize; else filesize = 0; } else filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */ /* Register the cipher filter. */ iobuf_push_filter (out, cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &cfx); /* Only do the is-file-already-compressed check if we are using a * MDC or AEAD. This forces compressed files to be re-compressed if * we do not have a MDC to give some protection against chosen * ciphertext attacks. */ if (do_compress && (cfx.dek->use_mdc || cfx.dek->use_aead) && !opt.explicit_compress_option && is_file_compressed (inp)) { if (opt.verbose) log_info(_("'%s' already compressed\n"), filename? filename: "[stdin]"); do_compress = 0; } if (!opt.no_literal) { pt->timestamp = make_timestamp(); pt->mode = opt.mimemode? 'm' : opt.textmode ? 't' : 'b'; pt->len = filesize; pt->new_ctb = !pt->len; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0; } else cfx.datalen = filesize && !do_compress ? filesize : 0; /* Register the compress filter. */ if (do_compress) { int compr_algo = opt.compress_algo; if (compr_algo == -1) { compr_algo = select_algo_from_prefs (pk_list, PREFTYPE_ZIP, -1, NULL); if (compr_algo == -1) compr_algo = DEFAULT_COMPRESS_ALGO; /* Theoretically impossible to get here since uncompressed is implicit. */ } else if (!opt.expert && select_algo_from_prefs(pk_list, PREFTYPE_ZIP, compr_algo, NULL) != compr_algo) { log_info (_("WARNING: forcing compression algorithm %s (%d)" " violates recipient preferences\n"), compress_algo_to_string(compr_algo), compr_algo); } /* Algo 0 means no compression. */ if (compr_algo) { if (cfx.dek && (cfx.dek->use_mdc || cfx.dek->use_aead)) zfx.new_ctb = 1; push_compress_filter (out,&zfx,compr_algo); } } /* Do the work. */ if (!opt.no_literal) { if ((rc = build_packet( out, &pkt ))) log_error ("build_packet failed: %s\n", gpg_strerror (rc)); } else { /* User requested not to create a literal packet, so we copy the plain data. */ byte copy_buffer[4096]; int bytes_copied; while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1) { rc = iobuf_write (out, copy_buffer, bytes_copied); if (rc) { log_error ("copying input to output failed: %s\n", gpg_strerror (rc)); break; } } wipememory (copy_buffer, 4096); /* Burn the buffer. */ } /* Finish the stuff. */ leave: iobuf_close (inp); if (rc) iobuf_cancel (out); else { iobuf_close (out); /* fixme: check returncode */ write_status (STATUS_END_ENCRYPTION); } if (pt) pt->buf = NULL; free_packet (&pkt, NULL); xfree (cfx.dek); xfree (symkey_dek); xfree (symkey_s2k); if (!provided_keys) release_pk_list (pk_list); release_armor_context (afx); release_progress_context (pfx); return rc; } /* * Filter to do a complete public key encryption. */ int encrypt_filter (void *opaque, int control, iobuf_t a, byte *buf, size_t *ret_len) { size_t size = *ret_len; encrypt_filter_context_t *efx = opaque; int rc = 0; if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */ { BUG(); /* not used */ } else if ( control == IOBUFCTRL_FLUSH ) /* encrypt */ { if ( !efx->header_okay ) { efx->header_okay = 1; efx->cfx.dek = create_dek_with_warnings (efx->pk_list); rc = check_encryption_compliance (efx->cfx.dek, efx->pk_list); if (rc) return rc; efx->cfx.dek->use_aead = use_aead (efx->pk_list, efx->cfx.dek->algo); if (!efx->cfx.dek->use_aead) efx->cfx.dek->use_mdc = !!use_mdc (efx->pk_list,efx->cfx.dek->algo); make_session_key ( efx->cfx.dek ); if (DBG_CRYPTO) log_printhex (efx->cfx.dek->key, efx->cfx.dek->keylen, "DEK is: "); rc = write_pubkey_enc_from_list (efx->ctrl, efx->pk_list, efx->cfx.dek, a); if (rc) return rc; if(efx->symkey_s2k && efx->symkey_dek) { rc = write_symkey_enc (efx->symkey_s2k, efx->cfx.dek->use_aead, efx->symkey_dek, efx->cfx.dek, a); if (rc) return rc; } iobuf_push_filter (a, efx->cfx.dek->use_aead? cipher_filter_aead /**/ : cipher_filter_cfb, &efx->cfx); } rc = iobuf_write (a, buf, size); } else if (control == IOBUFCTRL_FREE) { xfree (efx->symkey_dek); xfree (efx->symkey_s2k); } else if ( control == IOBUFCTRL_DESC ) { mem2str (buf, "encrypt_filter", *ret_len); } return rc; } /* * Write a pubkey-enc packet for the public key PK to OUT. */ int write_pubkey_enc (ctrl_t ctrl, PKT_public_key *pk, int throw_keyid, DEK *dek, iobuf_t out) { PACKET pkt; PKT_pubkey_enc *enc; int rc; gcry_mpi_t frame; print_pubkey_algo_note ( pk->pubkey_algo ); enc = xmalloc_clear ( sizeof *enc ); enc->pubkey_algo = pk->pubkey_algo; keyid_from_pk( pk, enc->keyid ); enc->throw_keyid = throw_keyid; + enc->seskey_algo = dek->algo; /* (Used only by PUBKEY_ALGO_KYBER.) */ /* Okay, what's going on: We have the session key somewhere in * the structure DEK and want to encode this session key in an * integer value of n bits. pubkey_nbits gives us the number of * bits we have to use. We then encode the session key in some * way and we get it back in the big intger value FRAME. Then * we use FRAME, the public key PK->PKEY and the algorithm * number PK->PUBKEY_ALGO and pass it to pubkey_encrypt which * returns the encrypted value in the array ENC->DATA. This * array has a size which depends on the used algorithm (e.g. 2 * for Elgamal). We don't need frame anymore because we have * everything now in enc->data which is the passed to * build_packet(). */ frame = encode_session_key (pk->pubkey_algo, dek, pubkey_nbits (pk->pubkey_algo, pk->pkey)); rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk, pk->pkey); gcry_mpi_release (frame); if (rc) log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) ); else { if ( opt.verbose ) { char *ustr = get_user_id_string_native (ctrl, enc->keyid); if ((pk->pubkey_usage & PUBKEY_USAGE_RENC)) { char *tmpustr = xstrconcat (ustr, " [ADSK]", NULL); xfree (ustr); ustr = tmpustr; } log_info (_("%s/%s.%s encrypted for: \"%s\"\n"), openpgp_pk_algo_name (enc->pubkey_algo), openpgp_cipher_algo_name (dek->algo), dek->use_aead? openpgp_aead_algo_name (dek->use_aead) /**/ : "CFB", ustr ); xfree (ustr); } /* And write it. */ init_packet (&pkt); pkt.pkttype = PKT_PUBKEY_ENC; pkt.pkt.pubkey_enc = enc; rc = build_packet (out, &pkt); if (rc) log_error ("build_packet(pubkey_enc) failed: %s\n", gpg_strerror (rc)); } free_pubkey_enc(enc); return rc; } /* * Write pubkey-enc packets from the list of PKs to OUT. */ static int write_pubkey_enc_from_list (ctrl_t ctrl, PK_LIST pk_list, DEK *dek, iobuf_t out) { if (opt.throw_keyids && (PGP7 || PGP8)) { log_info(_("option '%s' may not be used in %s mode\n"), "--throw-keyids", gnupg_compliance_option_string (opt.compliance)); compliance_failure(); } for ( ; pk_list; pk_list = pk_list->next ) { PKT_public_key *pk = pk_list->pk; int throw_keyid = (opt.throw_keyids || (pk_list->flags&1)); int rc = write_pubkey_enc (ctrl, pk, throw_keyid, dek, out); if (rc) return rc; } return 0; } void encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr) { int rc = 0; if (opt.outfile) { log_error(_("--output doesn't work for this command\n")); return; } if (!nfiles) { char line[2048]; unsigned int lno = 0; while ( fgets(line, DIM(line), stdin) ) { lno++; if (!*line || line[strlen(line)-1] != '\n') { log_error("input line %u too long or missing LF\n", lno); return; } line[strlen(line)-1] = '\0'; print_file_status(STATUS_FILE_START, line, 2); rc = encrypt_crypt (ctrl, GNUPG_INVALID_FD, line, remusr, 0, NULL, GNUPG_INVALID_FD); if (rc) log_error ("encryption of '%s' failed: %s\n", print_fname_stdin(line), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); } } else { while (nfiles--) { print_file_status(STATUS_FILE_START, *files, 2); if ((rc = encrypt_crypt (ctrl, GNUPG_INVALID_FD, *files, remusr, 0, NULL, GNUPG_INVALID_FD))) log_error("encryption of '%s' failed: %s\n", print_fname_stdin(*files), gpg_strerror (rc) ); write_status( STATUS_FILE_DONE ); files++; } } } diff --git a/g10/mainproc.c b/g10/mainproc.c index 6f3254e88..48bc463c5 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1,2835 +1,2836 @@ /* mainproc.c - handle packets * Copyright (C) 1998-2009 Free Software Foundation, Inc. * Copyright (C) 2013-2014 Werner Koch * Copyright (C) 2020 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include "gpg.h" #include "../common/util.h" #include "packet.h" #include "../common/iobuf.h" #include "options.h" #include "keydb.h" #include "filter.h" #include "main.h" #include "../common/status.h" #include "../common/i18n.h" #include "trustdb.h" #include "keyserver-internal.h" #include "photoid.h" #include "../common/mbox-util.h" #include "call-dirmngr.h" #include "../common/compliance.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 symkey packet info. */ struct symlist_item { struct symlist_item *next; int cipher_algo; int cfb_mode; int other_error; }; /* * 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 signed data. Only used if not -1. */ gnupg_fd_t 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; /* Number of symmetrically encrypted session keys. */ struct pubkey_enc_list *pkenc_list; /* List of encryption packets. */ struct symlist_item *symenc_list; /* List of sym. encryption packets. */ int seen_pkt_encrypted_aead; /* PKT_ENCRYPTED_AEAD packet seen. */ int seen_pkt_encrypted_mdc; /* PKT_ENCRYPTED_MDC packet seen. */ 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; }; /* Counter with the number of literal data packets seen. Note that * this is also bumped at the end of an encryption. This counter is * used for a basic consistency check of a received PGP message. */ static int literals_seen; /*** Local prototypes. ***/ static int do_proc_packets (CTX c, iobuf_t a); static void list_node (CTX c, kbnode_t node); static void proc_tree (CTX c, kbnode_t node); /*** Functions. ***/ /* Reset the literal data counter. This is required to setup a new * decryption or verification context. */ 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 pubkey_enc_list *tmp = c->pkenc_list->next; mpi_release (c->pkenc_list->data[0]); mpi_release (c->pkenc_list->data[1]); mpi_release (c->pkenc_list->data[2]); mpi_release (c->pkenc_list->data[3]); xfree (c->pkenc_list); c->pkenc_list = tmp; } c->pkenc_list = NULL; while (c->symenc_list) { struct symlist_item *tmp = c->symenc_list->next; xfree (c->symenc_list); c->symenc_list = tmp; } c->symenc_list = NULL; c->list = NULL; c->any.data = 0; c->any.uncompress_failed = 0; c->last_was_session_key = 0; c->seen_pkt_encrypted_aead = 0; c->seen_pkt_encrypted_mdc = 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 gpg_error_t symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen) { gpg_error_t err; gcry_cipher_hd_t hd; unsigned int noncelen, keylen; enum gcry_cipher_modes ciphermode; if (dek->use_aead) { err = openpgp_aead_algo_info (dek->use_aead, &ciphermode, &noncelen); if (err) return err; } else { ciphermode = GCRY_CIPHER_MODE_CFB; noncelen = 0; } /* Check that the session key has a size of 16 to 32 bytes. */ if ((dek->use_aead && (slen < (noncelen + 16 + 16) || slen > (noncelen + 32 + 16))) || (!dek->use_aead && (slen < 17 || slen > 33))) { log_error ( _("weird size for an encrypted session key (%d)\n"), (int)slen); return gpg_error (GPG_ERR_BAD_KEY); } err = openpgp_cipher_open (&hd, dek->algo, ciphermode, GCRY_CIPHER_SECURE); if (!err) err = gcry_cipher_setkey (hd, dek->key, dek->keylen); if (!err) err = gcry_cipher_setiv (hd, noncelen? seskey : NULL, noncelen); if (err) goto leave; if (dek->use_aead) { byte ad[4]; ad[0] = (0xc0 | PKT_SYMKEY_ENC); ad[1] = 5; ad[2] = dek->algo; ad[3] = dek->use_aead; err = gcry_cipher_authenticate (hd, ad, 4); if (err) goto leave; gcry_cipher_final (hd); keylen = slen - noncelen - 16; err = gcry_cipher_decrypt (hd, seskey+noncelen, keylen, NULL, 0); if (err) goto leave; err = gcry_cipher_checktag (hd, seskey+noncelen+keylen, 16); if (err) goto leave; /* Now we replace the dek components with the real session key to * decrypt the contents of the sequencing packet. */ if (keylen > DIM(dek->key)) { err = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } dek->keylen = keylen; memcpy (dek->key, seskey + noncelen, dek->keylen); } else { gcry_cipher_decrypt (hd, seskey, slen, NULL, 0 ); /* Here we can only test whether the algo given in decrypted * session key is a valid OpenPGP algo. With 11 defined * symmetric algorithms we will miss 4.3% of wrong passphrases * here. The actual checking is done later during bulk * decryption; we can't bring this check forward easily. We * need to use the GPG_ERR_CHECKSUM so that we won't run into * the gnupg < 2.2 bug compatible case which would terminate the * process on GPG_ERR_CIPHER_ALGO. Note that with AEAD (above) * we will have a reliable test here. */ if (openpgp_cipher_test_algo (seskey[0]) || openpgp_cipher_get_algo_keylen (seskey[0]) != slen - 1) { err = gpg_error (GPG_ERR_CHECKSUM); goto leave; } /* Now we replace the dek components with the real session key to * decrypt the contents of the sequencing packet. */ keylen = slen-1; if (keylen > DIM(dek->key)) { err = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } dek->algo = seskey[0]; dek->keylen = keylen; memcpy (dek->key, seskey + 1, dek->keylen); } /*log_hexdump( "thekey", dek->key, dek->keylen );*/ leave: gcry_cipher_close (hd); return err; } static void proc_symkey_enc (CTX c, PACKET *pkt) { gpg_error_t err; 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); const char *a = (enc->aead_algo ? openpgp_aead_algo_name (enc->aead_algo) /**/ : "CFB"); if (!openpgp_cipher_test_algo (algo)) { if (!opt.quiet) { if (enc->seskeylen) log_info (_("%s.%s encrypted session key\n"), s, a ); else log_info (_("%s.%s encrypted data\n"), s, a ); } } else { log_error (_("encrypted with unknown algorithm %d.%s\n"), algo, a); s = NULL; /* Force a goto leave. */ } 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, GETPASSWORD_FLAG_SYMDECRYPT, NULL); if (c->dek) { c->dek->symmetric = 1; c->dek->use_aead = enc->aead_algo; /* 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) { err = symkey_decrypt_seskey (c->dek, enc->seskey, enc->seskeylen); if (err) { log_info ("decryption of the symmetrically encrypted" " session key failed: %s\n", gpg_strerror (err)); if (gpg_err_code (err) != GPG_ERR_BAD_KEY && gpg_err_code (err) != GPG_ERR_CHECKSUM) log_fatal ("process terminated to be bug compatible" " with GnuPG <= 2.2\n"); else write_status_text (STATUS_ERROR, "symkey_decrypt.maybe_error" " 11_BAD_PASSPHRASE"); if (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); } xfree (c->dek); c->dek = NULL; } } else c->dek->algo_info_printed = 1; } } } leave: /* Record infos from the packet. */ { struct symlist_item *symitem; symitem = xcalloc (1, sizeof *symitem); if (enc) { symitem->cipher_algo = enc->cipher_algo; symitem->cfb_mode = !enc->aead_algo; } else symitem->other_error = 1; symitem->next = c->symenc_list; c->symenc_list = symitem; } c->symkeys++; free_packet (pkt, NULL); } static void proc_pubkey_enc (CTX c, PACKET *pkt) { PKT_pubkey_enc *enc; /* 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]; 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) { struct pubkey_enc_list *x = xmalloc (sizeof *x); x->keyid[0] = enc->keyid[0]; x->keyid[1] = enc->keyid[1]; x->pubkey_algo = enc->pubkey_algo; x->result = -1; + x->seskey_algo = enc->seskey_algo; x->data[0] = x->data[1] = x->data[2] = x->data[3] = NULL; if (enc->data[0]) { x->data[0] = mpi_copy (enc->data[0]); x->data[1] = mpi_copy (enc->data[1]); x->data[2] = mpi_copy (enc->data[2]); x->data[3] = mpi_copy (enc->data[3]); } x->next = c->pkenc_list; c->pkenc_list = x; } free_packet(pkt, NULL); } /* * Print the list of public key encrypted packets which we could * not decrypt. */ static void print_pkenc_list (ctrl_t ctrl, struct pubkey_enc_list *list) { for (; list; list = list->next) { PKT_public_key *pk; char pkstrbuf[PUBKEY_STRING_SIZE]; char *p; pk = xmalloc_clear (sizeof *pk); pk->pubkey_algo = list->pubkey_algo; if (!get_pubkey (ctrl, pk, list->keyid)) { pubkey_string (pk, pkstrbuf, sizeof pkstrbuf); log_info (_("encrypted with %s key, ID %s, created %s\n"), pkstrbuf, keystr_from_pk (pk), strtimestamp (pk->timestamp)); p = get_user_id_native (ctrl, list->keyid); log_printf (_(" \"%s\"\n"), p); xfree (p); } else log_info (_("encrypted with %s key, ID %s\n"), openpgp_pk_algo_name (list->pubkey_algo), keystr(list->keyid)); free_public_key (pk); } } static void proc_encrypted (CTX c, PACKET *pkt) { int result = 0; int early_plaintext = literals_seen; unsigned int compliance_de_vs = 0; if (pkt->pkttype == PKT_ENCRYPTED_AEAD) c->seen_pkt_encrypted_aead = 1; if (pkt->pkttype == PKT_ENCRYPTED_MDC) c->seen_pkt_encrypted_mdc = 1; if (early_plaintext) { log_info (_("WARNING: multiple plaintexts seen\n")); write_status_errcode ("decryption.early_plaintext", GPG_ERR_BAD_DATA); /* We fail only later so that we can print some more info first. */ } 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->ctrl, c->pkenc_list); } /* Figure out the session key by looking at all pkenc packets. */ if (opt.list_only || c->dek) ; else if (opt.override_session_key) { c->dek = xmalloc_clear (sizeof *c->dek); result = get_override_session_key (c->dek, opt.override_session_key); if (result) { xfree (c->dek); c->dek = NULL; log_info (_("public key decryption failed: %s\n"), gpg_strerror (result)); write_status_error ("pkdecrypt_failed", result); } } else if (c->pkenc_list) { c->dek = xmalloc_secure_clear (sizeof *c->dek); result = get_session_key (c->ctrl, c->pkenc_list, c->dek); if (is_status_enabled ()) { struct pubkey_enc_list *list; for (list = c->pkenc_list; list; list = list->next) if (list->result) { /* Key was not tried or it caused an error. */ char buf[20]; snprintf (buf, sizeof buf, "%08lX%08lX", (ulong)list->keyid[0], (ulong)list->keyid[1]); write_status_text (STATUS_NO_SECKEY, buf); } } if (result) { log_info (_("public key decryption failed: %s\n"), gpg_strerror (result)); write_status_error ("pkdecrypt_failed", result); /* Error: Delete the DEK. */ xfree (c->dek); c->dek = NULL; } } if (c->dek && opt.verbose > 1) log_info (_("public key encrypted data: good DEK\n")); write_status (STATUS_BEGIN_DECRYPTION); /*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, GETPASSWORD_FLAG_SYMDECRYPT, &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) { if (c->symkeys && !c->pkenc_list) result = gpg_error (GPG_ERR_BAD_KEY); if (!result) result = gpg_error (GPG_ERR_NO_SECKEY); } /* Compute compliance with CO_DE_VS. */ if (!result && (is_status_enabled () || opt.flags.require_compliance) /* Overriding session key voids compliance. */ && !opt.override_session_key /* Check symmetric cipher. */ && gnupg_gcrypt_is_compliant (CO_DE_VS) && gnupg_cipher_is_compliant (CO_DE_VS, c->dek->algo, GCRY_CIPHER_MODE_CFB)) { struct pubkey_enc_list *i; struct symlist_item *si; int compliant = 1; PKT_public_key *pk = xmalloc (sizeof *pk); if ( !(c->pkenc_list || c->symkeys) ) log_debug ("%s: where else did the session key come from?\n", __func__); /* Check that all seen symmetric key packets use compliant * algos. This is so that no non-compliant encrypted session * key can be sneaked in. */ for (si = c->symenc_list; si && compliant; si = si->next) { if (!si->cfb_mode || !gnupg_cipher_is_compliant (CO_DE_VS, si->cipher_algo, GCRY_CIPHER_MODE_CFB)) compliant = 0; } /* Check that every known public key used to encrypt the session key * is compliant. */ for (i = c->pkenc_list; i && compliant; i = i->next) { memset (pk, 0, sizeof *pk); pk->pubkey_algo = i->pubkey_algo; if (!get_pubkey (c->ctrl, pk, i->keyid) && !gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey, nbits_from_pk (pk), NULL)) compliant = 0; release_public_key_parts (pk); } xfree (pk); if (compliant) compliance_de_vs |= 1; } if (!result) { int compl_error; result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek, &compl_error); if (!result && !compl_error) compliance_de_vs |= 2; } /* Trigger the deferred error. The second condition makes sure that a * log_error printed in the cry_cipher_checktag never gets ignored. */ if (!result && early_plaintext) result = gpg_error (GPG_ERR_BAD_DATA); else if (!result && pkt->pkt.encrypted->aead_algo && log_get_errorcount (0)) result = gpg_error (GPG_ERR_BAD_SIGNATURE); if (result == -1) ; else if (!result && !opt.ignore_mdc_error && !pkt->pkt.encrypted->mdc_method && !pkt->pkt.encrypted->aead_algo) { /* The message has been decrypted but does not carry an MDC or * uses AEAD encryption. --ignore-mdc-error has also not been * 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 (!pkt->pkt.encrypted->mdc_method && (openpgp_cipher_get_algo_blklen (c->dek->algo) == 8 || c->dek->algo == CIPHER_ALGO_TWOFISH)) { /* Before 2.2.8 we did not fail hard for a missing MDC if * one of the old ciphers where used. Although these cases * are rare in practice we print a hint on how to decrypt * such messages. */ log_string (GPGRT_LOGLVL_INFO, _("Hint: If this message was created before the year 2003 it is\n" "likely that this message is legitimate. This is because back\n" "then integrity protection was not widely used.\n")); log_info (_("Use the option '%s' to decrypt anyway.\n"), "--ignore-mdc-error"); write_status_errcode ("nomdc_with_legacy_cipher", GPG_ERR_DECRYPT_FAILED); } log_info (_("decryption forced to fail!\n")); write_status (STATUS_DECRYPTION_FAILED); } else if (!result || (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE && !pkt->pkt.encrypted->aead_algo && opt.ignore_mdc_error)) { /* All is fine or for an MDC message the MDC failed but the * --ignore-mdc-error option is active. For compatibility * reasons we issue GOODMDC also for AEAD messages. */ write_status (STATUS_DECRYPTION_OKAY); if (opt.verbose > 1) log_info(_("decryption okay\n")); if (pkt->pkt.encrypted->aead_algo) { write_status (STATUS_GOODMDC); compliance_de_vs |= 4; } else if (pkt->pkt.encrypted->mdc_method && !result) { write_status (STATUS_GOODMDC); compliance_de_vs |= 4; } else log_info (_("WARNING: message was not integrity protected\n")); } else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE || gpg_err_code (result) == GPG_ERR_TRUNCATED) { 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 || gpg_err_code (result) == GPG_ERR_CHECKSUM || gpg_err_code (result) == GPG_ERR_CIPHER_ALGO) { if (c->symkeys) write_status_text (STATUS_ERROR, "symkey_decrypt.maybe_error" " 11_BAD_PASSPHRASE"); if (c->dek && *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). */ } /* If we concluded that the decryption was compliant, issue a * compliance status before the end of the decryption status. */ if (compliance_de_vs == (4|2|1)) { write_status_strings (STATUS_DECRYPTION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS), NULL); } xfree (c->dek); c->dek = NULL; free_packet (pkt, NULL); c->last_was_session_key = 0; write_status (STATUS_END_DECRYPTION); /* Bump the counter even if we have not seen a literal data packet * inside an encryption container. This acts as a sentinel in case * a misplace extra literal data packets follows after this * encrypted packet. */ literals_seen++; /* The --require-compliance option allows one to simplify decryption in * de-vs compliance mode by just looking at the exit status. */ if (opt.flags.require_compliance && opt.compliance == CO_DE_VS && compliance_de_vs != (4|2|1)) { log_error (_("operation forced to fail due to" " unfulfilled compliance rules\n")); g10_errors_seen = 1; } } static int have_seen_pkt_encrypted_aead_or_mdc( CTX c ) { CTX cc; for (cc = c; cc; cc = cc->anchor) { if (cc->seen_pkt_encrypted_aead) return 1; if (cc->seen_pkt_encrypted_mdc) return 1; } return 0; } static void proc_plaintext( CTX c, PACKET *pkt ) { PKT_plaintext *pt = pkt->pkt.plaintext; int any, clearsig, rc; kbnode_t n; unsigned char *extrahash; size_t extrahashlen; /* This is a literal data packet. Bump a counter for later checks. */ 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) { /* We don't use print_utf8_buffer because that would require a * string change which we don't want in 2.2. It is also not * clear whether the filename is always utf-8 encoded. */ char *tmp = make_printable_string (pt->name, pt->namelen, 0); log_info (_("original file name='%.*s'\n"), (int)strlen (tmp), tmp); xfree (tmp); } 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) { if (!opt.skip_verify) 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++) if (!opt.skip_verify) 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. */ if (!opt.skip_verify) gcry_md_enable (c->mfx.md, n->pkt->pkt.signature->digest_algo); any = 1; } } if (!any && !opt.skip_verify && !have_seen_pkt_encrypted_aead_or_mdc(c)) { /* 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")); 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)); /* We add a marker control packet instead of the plaintext packet. * This is so that we can later detect invalid packet sequences. * The packet is further used to convey extra data from the * plaintext packet to the signature verification. */ extrahash = xtrymalloc (6 + pt->namelen); if (!extrahash) { /* No way to return an error. */ rc = gpg_error_from_syserror (); log_error ("malloc failed in %s: %s\n", __func__, gpg_strerror (rc)); extrahashlen = 0; } else { extrahash[0] = pt->mode; extrahash[1] = pt->namelen; if (pt->namelen) memcpy (extrahash+2, pt->name, pt->namelen); extrahashlen = 2 + pt->namelen; extrahash[extrahashlen++] = pt->timestamp >> 24; extrahash[extrahashlen++] = pt->timestamp >> 16; extrahash[extrahashlen++] = pt->timestamp >> 8; extrahash[extrahashlen++] = pt->timestamp ; } free_packet (pkt, NULL); c->last_was_session_key = 0; n = new_kbnode (create_gpg_control (CTRLPKT_PLAINTEXT_MARK, extrahash, extrahashlen)); xfree (extrahash); 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 != GNUPG_INVALID_FD) 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, NULL); 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 there, or NULL if not * found. If FORCED_PK is not NULL, this public key is used to verify * _data signatures_ and no key lookup is done. Returns: 0 = valid * signature or an error code */ static int do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, PKT_public_key *forced_pk, 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->ctrl, 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 (c->ctrl, sig, md, extrahash, extrahashlen, forced_pk, 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 (c->ctrl, sig, md2, extrahash, extrahashlen, forced_pk, 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, node->pkt->pkttype == PKT_PUBLIC_KEY ? node : NULL, 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 (c->ctrl, pk, 1), es_stdout); es_putc (':', es_stdout); es_putc ('\n', es_stdout); } else { print_key_line (c->ctrl, 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 (c->ctrl, NULL, pk, 0); 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); } 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, NULL, 0, NULL, &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 (c->ctrl, sig->keyid, &n, NULL); 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 (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 = GNUPG_INVALID_FD; c->signed_data.data_names = signedfiles; c->signed_data.used = !!signedfiles; c->sigfilename = sigfilename; rc = do_proc_packets (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, gnupg_fd_t 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 != GNUPG_INVALID_FD); rc = do_proc_packets (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 (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 (CTX c, iobuf_t a) { PACKET *pkt; struct parse_packet_ctx_s parsectx; 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); init_parse_packet (&parsectx, a); while ((rc=parse_packet (&parsectx, pkt)) != -1) { any_data = 1; if (rc) { free_packet (pkt, &parsectx); /* 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 (c, pkt); break; case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: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: case PKT_ENCRYPTED_AEAD: 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 (c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: 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 (c, pkt); break; case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: 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, &parsectx); } 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, &parsectx); deinit_parse_packet (&parsectx); xfree (pkt); free_md_filter_context (&c->mfx); return rc; } /* 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 buffer and its length at R_LEN. * Returns NULL if not available. The returned buffer is valid as * long as SIG is not modified. */ const byte * issuer_fpr_raw (PKT_signature *sig, size_t *r_len) { const byte *p; size_t n; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_ISSUER_FPR, &n); if (p && ((n == 21 && p[0] == 4) || (n == 33 && p[0] == 5))) { *r_len = n - 1; return p+1; } *r_len = 0; return NULL; } /* Return the ISSUER fingerprint string in human readable format if * available. Caller must release the string. */ /* FIXME: Move to another file. */ char * issuer_fpr_string (PKT_signature *sig) { const byte *p; size_t n; p = issuer_fpr_raw (sig, &n); return p? bin2hex (p, n, NULL) : 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; gpg_error_t rc; int is_expkey = 0; int is_revkey = 0; char *issuer_fpr = NULL; PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */ const void *extrahash = NULL; size_t extrahashlen = 0; kbnode_t included_keyblock = NULL; char pkstrbuf[PUBKEY_STRING_SIZE] = { 0 }; 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. */ extrahash = n->pkt->pkt.gpg_control->data; extrahashlen = n->pkt->pkt.gpg_control->datalen; } 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; extrahash = n->pkt->pkt.gpg_control->data; extrahashlen = n->pkt->pkt.gpg_control->datalen; 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) * goto ambiguous; * * However, this can stay allowable as we can't get here. */ 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; extrahash = n->pkt->pkt.gpg_control->data; extrahashlen = n->pkt->pkt.gpg_control->datalen; 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; } } /* End checking signature packet composition. */ 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 ); issuer_fpr = issuer_fpr_string (sig); if (issuer_fpr) { log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp)); log_info (_(" using %s key %s\n"), astr? astr: "?", 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, extrahash, extrahashlen, NULL, NULL, &is_expkey, &is_revkey, &pk); /* If the key is not found but the signature includes a key block we * use that key block for verification and on success import it. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.key_block && opt.flags.auto_key_import) { PKT_public_key *included_pk; const byte *kblock; size_t kblock_len; included_pk = xcalloc (1, sizeof *included_pk); kblock = parse_sig_subpkt (sig, 1, SIGSUBPKT_KEY_BLOCK, &kblock_len); if (kblock && kblock_len > 1 && !get_pubkey_from_buffer (c->ctrl, included_pk, kblock+1, kblock_len-1, sig->keyid, &included_keyblock)) { rc = do_check_sig (c, node, extrahash, extrahashlen, included_pk, NULL, &is_expkey, &is_revkey, &pk); if (opt.verbose) log_debug ("checked signature using included key block: %s\n", gpg_strerror (rc)); if (!rc) { /* The keyblock has been verified, we now import it. */ rc = import_included_key_block (c->ctrl, included_keyblock); } } free_public_key (included_pk); } /* If the key isn't found, check for a preferred keyserver. Note * that this is only done if honor-keyserver-url has been set. We * test for this in the loop so that we can show info about the * preferred keyservers. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks) { const byte *p; int seq = 0; size_t n; int any_pref_ks = 0; while ((p=enum_sig_subpkt (sig, 1, 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"); any_pref_ks = 1; 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; if (DBG_LOOKUP) log_debug ("trying auto-key-retrieve method %s\n", "Pref-KS"); free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, NULL, &is_expkey, &is_revkey, &pk); else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "Pref-KS", gpg_strerror (res)); free_keyserver_spec (spec); if (!rc) break; } } } if (any_pref_ks && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) && !(opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL)) log_info (_("Note: Use '%s' to make use of this info\n"), "--keyserver-option honor-keyserver-url"); } /* If the above methods didn't work, our next try is to retrieve the * key from the WKD. This requires that WKD is in the AKL and the * Signer's UID is in the signature. */ 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; if (DBG_LOOKUP) log_debug ("trying auto-key-retrieve method %s\n", "WKD"); free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_wkd (c->ctrl, sig->signers_uid, KEYSERVER_IMPORT_FLAG_QUICK, 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, extrahash, extrahashlen, NULL, NULL, &is_expkey, &is_revkey, &pk); else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res)); } /* 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. */ if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) && keyserver_any_configured (c->ctrl)) { int res; const byte *p; size_t n; p = issuer_fpr_raw (sig, &n); if (p) { if (DBG_LOOKUP) log_debug ("trying auto-key-retrieve method %s\n", "KS"); /* v4 or v5 packet with a SHA-1/256 fingerprint. */ free_public_key (pk); pk = NULL; glo_ctrl.in_auto_key_retrieve++; res = keyserver_import_fprint (c->ctrl, p, n, opt.keyserver, KEYSERVER_IMPORT_FLAG_QUICK); glo_ctrl.in_auto_key_retrieve--; if (!res) rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, NULL, &is_expkey, &is_revkey, &pk); else if (DBG_LOOKUP) log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res)); } } /* Do do something with the result of the signature checking. */ if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) { /* We have checked the signature and the result is either a good * signature or a bad signature. Further examination follows. */ kbnode_t un, keyblock; int count = 0; int keyblock_has_pk = 0; /* For failsafe check. */ 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 * keyblock 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. */ if (included_keyblock) { keyblock = included_keyblock; included_keyblock = NULL; } else keyblock = get_pubkeyblock_for_sig (c->ctrl, sig); 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 (!keyblock_has_pk && (un->pkt->pkttype == PKT_PUBLIC_KEY || un->pkt->pkttype == PKT_PUBLIC_SUBKEY) && !cmp_public_keys (un->pkt->pkt.public_key, pk)) { keyblock_has_pk = 1; } 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->flags.revoked) continue; if (un->pkt->pkt.user_id->flags.expired) continue; if (!un->pkt->pkt.user_id->flags.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, keyblock, 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++; /* At this point we could in theory stop because the primary * UID flag is never set for more than one User ID per * keyblock. However, we use this loop also for a failsafe * check that the public key used to create the signature is * contained in the keyring.*/ } log_assert (mainpk); if (!keyblock_has_pk) { log_error ("signature key lost from keyblock\n"); rc = gpg_error (GPG_ERR_INTERNAL); } /* In case we did not found a 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->flags.revoked || un->pkt->pkt.user_id->flags.expired) && !(opt.verify_options & VERIFY_SHOW_UNUSABLE_UIDS)) continue; /* Skip textual primary user ids which we printed above. */ if (un->pkt->pkt.user_id->flags.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->flags.revoked) valid = _("revoked"); else if (un->pkt->pkt.user_id->flags.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, keyblock, 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); } /* Fill PKSTRBUF with the algostring in case we later need it. */ if (pk) pubkey_string (pk, pkstrbuf, sizeof pkstrbuf); /* For good signatures print the VALIDSIG status line. */ if (!rc && (is_status_enabled () || opt.assert_signer_list || opt.assert_pubkey_algos) && 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); /* Handle the --assert-signer option. */ check_assert_signer_list (mainpkhex, pkhex); /* Handle the --assert-pubkey-algo option. */ check_assert_pubkey_algo (pkstrbuf, pkhex); } /* Print compliance warning for Good signatures. */ if (!rc && pk && !opt.quiet && !gnupg_pk_is_compliant (opt.compliance, pk->pubkey_algo, 0, pk->pkey, nbits_from_pk (pk), NULL)) { log_info (_("WARNING: This key is not suitable for signing" " in %s mode\n"), gnupg_compliance_option_string (opt.compliance)); } /* 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) { rc = check_signatures_trust (c->ctrl, keyblock, pk, sig); } /* Print extra information about the signature. */ if (sig->flags.expired) { log_info (_("Signature expired %s\n"), asctimestamp(sig->expiredate)); if (!rc) rc = gpg_error (GPG_ERR_GENERAL); /* Need a better error here? */ } else if (sig->expiredate) log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate)); if (opt.verbose) { 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); assert_signer_true = 0; } xfree (dfile); } } /* Compute compliance with CO_DE_VS. */ if (pk && gnupg_gcrypt_is_compliant (CO_DE_VS) && gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey, nbits_from_pk (pk), NULL) && gnupg_digest_is_compliant (CO_DE_VS, sig->digest_algo)) write_status_strings (STATUS_VERIFICATION_COMPLIANCE_MODE, gnupg_status_compliance_flag (CO_DE_VS), NULL); else if (opt.flags.require_compliance && opt.compliance == CO_DE_VS) { log_error (_("operation forced to fail due to" " unfulfilled compliance rules\n")); if (!rc) rc = gpg_error (GPG_ERR_FORBIDDEN); } free_public_key (pk); pk = NULL; release_kbnode( keyblock ); if (rc) g10_errors_seen = 1; } else /* Error checking the signature. (neither Good nor Bad). */ { write_status_printf (STATUS_ERRSIG, "%08lX%08lX %d %d %02x %lu %d %s", (ulong)sig->keyid[0], (ulong)sig->keyid[1], sig->pubkey_algo, sig->digest_algo, sig->sig_class, (ulong)sig->timestamp, gpg_err_code (rc), issuer_fpr? issuer_fpr:"-"); if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY) { write_status_printf (STATUS_NO_PUBKEY, "%08lX%08lX", (ulong)sig->keyid[0], (ulong)sig->keyid[1]); } if (gpg_err_code (rc) != GPG_ERR_NOT_PROCESSED) log_error (_("Can't check signature: %s\n"), gpg_strerror (rc)); } free_public_key (pk); release_kbnode (included_keyblock); xfree (issuer_fpr); 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 (c->ctrl, node); list_node (c, node); } else if (node->pkt->pkttype == PKT_SECRET_KEY) { merge_keys_and_selfsig (c->ctrl, 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 != GNUPG_INVALID_FD) 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, NULL, 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));) if (check_sig_and_print (c, n1) && opt.batch) break; } 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));) if (check_sig_and_print (c, n1) && opt.batch) break; } 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 != GNUPG_INVALID_FD) 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))) if (check_sig_and_print (c, n1) && opt.batch) break; } 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); } } diff --git a/g10/misc.c b/g10/misc.c index ce0c04b3b..1359987d2 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1,1950 +1,1950 @@ /* misc.c - miscellaneous functions * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * 2008, 2009, 2010 Free Software Foundation, Inc. * Copyright (C) 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 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 #include #include #endif #ifdef HAVE_SETRLIMIT #include #include #include #endif #ifdef ENABLE_SELINUX_HACKS #include #endif #ifdef HAVE_W32_SYSTEM #include #include #ifdef HAVE_WINSOCK2_H # define WIN32_LEAN_AND_MEAN 1 # include #endif #include #include #ifndef CSIDL_APPDATA #define CSIDL_APPDATA 0x001a #endif #ifndef CSIDL_LOCAL_APPDATA #define CSIDL_LOCAL_APPDATA 0x001c #endif #ifndef CSIDL_FLAG_CREATE #define CSIDL_FLAG_CREATE 0x8000 #endif #endif /*HAVE_W32_SYSTEM*/ #include "gpg.h" #ifdef HAVE_W32_SYSTEM # include "../common/status.h" #endif /*HAVE_W32_SYSTEM*/ #include "../common/util.h" #include "main.h" #include "photoid.h" #include "options.h" #include "call-agent.h" #include "../common/i18n.h" #include "../common/zb32.h" /* FIXME: Libgcrypt 1.9 will support EAX. Until we name this a * requirement we hardwire the enum used for EAX. */ #define MY_GCRY_CIPHER_MODE_EAX 14 #ifdef ENABLE_SELINUX_HACKS /* A object and a global variable to keep track of files marked as secured. */ struct secured_file_item { struct secured_file_item *next; ino_t ino; dev_t dev; }; static struct secured_file_item *secured_files; #endif /*ENABLE_SELINUX_HACKS*/ /* For the sake of SELinux we want to restrict access through gpg to certain files we keep under our own control. This function registers such a file and is_secured_file may then be used to check whether a file has ben registered as secured. */ void register_secured_file (const char *fname) { #ifdef ENABLE_SELINUX_HACKS struct stat buf; struct secured_file_item *sf; /* Note that we stop immediately if something goes wrong here. */ if (gnupg_stat (fname, &buf)) log_fatal (_("fstat of '%s' failed in %s: %s\n"), fname, "register_secured_file", strerror (errno)); /* log_debug ("registering '%s' i=%lu.%lu\n", fname, */ /* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ for (sf=secured_files; sf; sf = sf->next) { if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) return; /* Already registered. */ } sf = xmalloc (sizeof *sf); sf->ino = buf.st_ino; sf->dev = buf.st_dev; sf->next = secured_files; secured_files = sf; #else /*!ENABLE_SELINUX_HACKS*/ (void)fname; #endif /*!ENABLE_SELINUX_HACKS*/ } /* Remove a file registered as secure. */ void unregister_secured_file (const char *fname) { #ifdef ENABLE_SELINUX_HACKS struct stat buf; struct secured_file_item *sf, *sfprev; if (gnupg_stat (fname, &buf)) { log_error (_("fstat of '%s' failed in %s: %s\n"), fname, "unregister_secured_file", strerror (errno)); return; } /* log_debug ("unregistering '%s' i=%lu.%lu\n", fname, */ /* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ for (sfprev=NULL,sf=secured_files; sf; sfprev=sf, sf = sf->next) { if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) { if (sfprev) sfprev->next = sf->next; else secured_files = sf->next; xfree (sf); return; } } #else /*!ENABLE_SELINUX_HACKS*/ (void)fname; #endif /*!ENABLE_SELINUX_HACKS*/ } /* Return true if FD is corresponds to a secured file. Using -1 for FS is allowed and will return false. */ int is_secured_file (gnupg_fd_t fd) { #ifdef ENABLE_SELINUX_HACKS struct stat buf; struct secured_file_item *sf; if (fd == -1) return 0; /* No file descriptor so it can't be secured either. */ /* Note that we print out a error here and claim that a file is secure if something went wrong. */ if (fstat (fd, &buf)) { log_error (_("fstat(%d) failed in %s: %s\n"), fd, "is_secured_file", strerror (errno)); return 1; } /* log_debug ("is_secured_file (%d) i=%lu.%lu\n", fd, */ /* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ for (sf=secured_files; sf; sf = sf->next) { if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) return 1; /* Yes. */ } #else /*!ENABLE_SELINUX_HACKS*/ (void)fd; #endif /*!ENABLE_SELINUX_HACKS*/ return 0; /* No. */ } /* Return true if FNAME is corresponds to a secured file. Using NULL, "" or "-" for FS is allowed and will return false. This function is used before creating a file, thus it won't fail if the file does not exist. */ int is_secured_filename (const char *fname) { #ifdef ENABLE_SELINUX_HACKS struct stat buf; struct secured_file_item *sf; if (iobuf_is_pipe_filename (fname) || !*fname) return 0; /* Note that we print out a error here and claim that a file is secure if something went wrong. */ if (gnupg_stat (fname, &buf)) { if (errno == ENOENT || errno == EPERM || errno == EACCES) return 0; log_error (_("fstat of '%s' failed in %s: %s\n"), fname, "is_secured_filename", strerror (errno)); return 1; } /* log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */ /* (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */ for (sf=secured_files; sf; sf = sf->next) { if (sf->ino == buf.st_ino && sf->dev == buf.st_dev) return 1; /* Yes. */ } #else /*!ENABLE_SELINUX_HACKS*/ (void)fname; #endif /*!ENABLE_SELINUX_HACKS*/ return 0; /* No. */ } u16 checksum_u16( unsigned n ) { u16 a; a = (n >> 8) & 0xff; a += n & 0xff; return a; } u16 checksum (const byte *p, unsigned n) { u16 a; for(a=0; n; n-- ) a += *p++; return a; } u16 checksum_mpi (gcry_mpi_t a) { u16 csum; byte *buffer; size_t nbytes; /* * This code can be skipped when gcry_mpi_print * supports opaque MPI. */ if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { const byte *p; unsigned int nbits; p = gcry_mpi_get_opaque (a, &nbits); if (!p) return 0; csum = nbits >> 8; csum += (nbits & 0xff); csum += checksum (p, (nbits+7)/8); return csum; } if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) ) BUG (); /* Fixme: For numbers not in secure memory we should use a stack * based buffer and only allocate a larger one if mpi_print returns * an error. */ buffer = (gcry_is_secure(a)? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes)); if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) ) BUG (); csum = checksum (buffer, nbytes); xfree (buffer); return csum; } void print_pubkey_algo_note (pubkey_algo_t algo) { if(algo >= 100 && algo <= 110) { static int warn=0; if(!warn) { warn=1; es_fflush (es_stdout); log_info (_("WARNING: using experimental public key algorithm %s\n"), openpgp_pk_algo_name (algo)); } } else if (algo == PUBKEY_ALGO_ELGAMAL) { es_fflush (es_stdout); log_info (_("WARNING: Elgamal sign+encrypt keys are deprecated\n")); } } void print_cipher_algo_note (cipher_algo_t algo) { if(algo >= 100 && algo <= 110) { static int warn=0; if(!warn) { warn=1; es_fflush (es_stdout); log_info (_("WARNING: using experimental cipher algorithm %s\n"), openpgp_cipher_algo_name (algo)); } } } void print_digest_algo_note (digest_algo_t algo) { if(algo >= 100 && algo <= 110) { static int warn=0; const enum gcry_md_algos galgo = map_md_openpgp_to_gcry (algo); if(!warn) { warn=1; es_fflush (es_stdout); log_info (_("WARNING: using experimental digest algorithm %s\n"), gcry_md_algo_name (galgo)); } } else if (is_weak_digest (algo)) { const enum gcry_md_algos galgo = map_md_openpgp_to_gcry (algo); es_fflush (es_stdout); log_info (_("WARNING: digest algorithm %s is deprecated\n"), gcry_md_algo_name (galgo)); } } void print_digest_rejected_note (enum gcry_md_algos algo) { struct weakhash* weak; int show = 1; if (opt.quiet) return; for (weak = opt.weak_digests; weak; weak = weak->next) if (weak->algo == algo) { if (weak->rejection_shown) show = 0; else weak->rejection_shown = 1; break; } if (show) { es_fflush (es_stdout); log_info (_("Note: signatures using the %s algorithm are rejected\n"), gcry_md_algo_name(algo)); } } void print_sha1_keysig_rejected_note (void) { static int shown; if (shown || opt.quiet) return; shown = 1; es_fflush (es_stdout); log_info (_("Note: third-party key signatures using" " the %s algorithm are rejected\n"), gcry_md_algo_name (GCRY_MD_SHA1)); if (!opt.quiet) log_info (_("(use option \"%s\" to override)\n"), "--allow-weak-key-signatures"); } /* Print a message * "(reported error: %s)\n * in verbose mode to further explain an error. If the error code has * the value IGNORE_EC no message is printed. A message is also not * printed if ERR is 0. */ void print_reported_error (gpg_error_t err, gpg_err_code_t ignore_ec) { if (!opt.verbose) return; if (!gpg_err_code (err)) ; else if (gpg_err_code (err) == ignore_ec) ; else if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT) log_info (_("(reported error: %s)\n"), gpg_strerror (err)); else log_info (_("(reported error: %s <%s>)\n"), gpg_strerror (err), gpg_strsource (err)); } /* Print a message * "(further info: %s)\n * in verbose mode to further explain an error. That message is * intended to help debug a problem and should not be translated. */ void print_further_info (const char *format, ...) { va_list arg_ptr; if (!opt.verbose) return; log_info (_("(further info: ")); va_start (arg_ptr, format); log_logv (GPGRT_LOGLVL_CONT, format, arg_ptr); va_end (arg_ptr); log_printf (")\n"); } /* Map OpenPGP algo numbers to those used by Libgcrypt. We need to do this for algorithms we implemented in Libgcrypt after they become part of OpenPGP. */ enum gcry_cipher_algos map_cipher_openpgp_to_gcry (cipher_algo_t algo) { switch (algo) { case CIPHER_ALGO_NONE: return GCRY_CIPHER_NONE; #ifdef GPG_USE_IDEA case CIPHER_ALGO_IDEA: return GCRY_CIPHER_IDEA; #else case CIPHER_ALGO_IDEA: return 0; #endif case CIPHER_ALGO_3DES: return GCRY_CIPHER_3DES; #ifdef GPG_USE_CAST5 case CIPHER_ALGO_CAST5: return GCRY_CIPHER_CAST5; #else case CIPHER_ALGO_CAST5: return 0; #endif #ifdef GPG_USE_BLOWFISH case CIPHER_ALGO_BLOWFISH: return GCRY_CIPHER_BLOWFISH; #else case CIPHER_ALGO_BLOWFISH: return 0; #endif #ifdef GPG_USE_AES128 case CIPHER_ALGO_AES: return GCRY_CIPHER_AES; #else case CIPHER_ALGO_AES: return 0; #endif #ifdef GPG_USE_AES192 case CIPHER_ALGO_AES192: return GCRY_CIPHER_AES192; #else case CIPHER_ALGO_AES192: return 0; #endif #ifdef GPG_USE_AES256 case CIPHER_ALGO_AES256: return GCRY_CIPHER_AES256; #else case CIPHER_ALGO_AES256: return 0; #endif #ifdef GPG_USE_TWOFISH case CIPHER_ALGO_TWOFISH: return GCRY_CIPHER_TWOFISH; #else case CIPHER_ALGO_TWOFISH: return 0; #endif #ifdef GPG_USE_CAMELLIA128 case CIPHER_ALGO_CAMELLIA128: return GCRY_CIPHER_CAMELLIA128; #else case CIPHER_ALGO_CAMELLIA128: return 0; #endif #ifdef GPG_USE_CAMELLIA192 case CIPHER_ALGO_CAMELLIA192: return GCRY_CIPHER_CAMELLIA192; #else case CIPHER_ALGO_CAMELLIA192: return 0; #endif #ifdef GPG_USE_CAMELLIA256 case CIPHER_ALGO_CAMELLIA256: return GCRY_CIPHER_CAMELLIA256; #else case CIPHER_ALGO_CAMELLIA256: return 0; #endif default: return 0; } } /* The inverse function of above. */ static cipher_algo_t map_cipher_gcry_to_openpgp (enum gcry_cipher_algos algo) { switch (algo) { case GCRY_CIPHER_NONE: return CIPHER_ALGO_NONE; case GCRY_CIPHER_IDEA: return CIPHER_ALGO_IDEA; case GCRY_CIPHER_3DES: return CIPHER_ALGO_3DES; case GCRY_CIPHER_CAST5: return CIPHER_ALGO_CAST5; case GCRY_CIPHER_BLOWFISH: return CIPHER_ALGO_BLOWFISH; case GCRY_CIPHER_AES: return CIPHER_ALGO_AES; case GCRY_CIPHER_AES192: return CIPHER_ALGO_AES192; case GCRY_CIPHER_AES256: return CIPHER_ALGO_AES256; case GCRY_CIPHER_TWOFISH: return CIPHER_ALGO_TWOFISH; case GCRY_CIPHER_CAMELLIA128: return CIPHER_ALGO_CAMELLIA128; case GCRY_CIPHER_CAMELLIA192: return CIPHER_ALGO_CAMELLIA192; case GCRY_CIPHER_CAMELLIA256: return CIPHER_ALGO_CAMELLIA256; default: return 0; } } /* Return the block length of an OpenPGP cipher algorithm. */ int openpgp_cipher_blocklen (cipher_algo_t algo) { /* We use the numbers from OpenPGP to be sure that we get the right block length. This is so that the packet parsing code works even for unknown algorithms (for which we assume 8 due to tradition). NOTE: If you change the returned blocklen above 16, check the callers because they may use a fixed size buffer of that size. */ switch (algo) { case CIPHER_ALGO_AES: case CIPHER_ALGO_AES192: case CIPHER_ALGO_AES256: case CIPHER_ALGO_TWOFISH: case CIPHER_ALGO_CAMELLIA128: case CIPHER_ALGO_CAMELLIA192: case CIPHER_ALGO_CAMELLIA256: return 16; default: return 8; } } /**************** * Wrapper around the libgcrypt function with additional checks on * the OpenPGP constraints for the algo ID. */ int openpgp_cipher_test_algo (cipher_algo_t algo) { enum gcry_cipher_algos ga; ga = map_cipher_openpgp_to_gcry (algo); if (!ga) return gpg_error (GPG_ERR_CIPHER_ALGO); return gcry_cipher_test_algo (ga); } /* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a string representation of the algorithm name. For unknown algorithm IDs this function returns "?". */ const char * openpgp_cipher_algo_name (cipher_algo_t algo) { switch (algo) { case CIPHER_ALGO_IDEA: return "IDEA"; case CIPHER_ALGO_3DES: return "3DES"; case CIPHER_ALGO_CAST5: return "CAST5"; case CIPHER_ALGO_BLOWFISH: return "BLOWFISH"; case CIPHER_ALGO_AES: return "AES"; case CIPHER_ALGO_AES192: return "AES192"; case CIPHER_ALGO_AES256: return "AES256"; case CIPHER_ALGO_TWOFISH: return "TWOFISH"; case CIPHER_ALGO_CAMELLIA128: return "CAMELLIA128"; case CIPHER_ALGO_CAMELLIA192: return "CAMELLIA192"; case CIPHER_ALGO_CAMELLIA256: return "CAMELLIA256"; case CIPHER_ALGO_NONE: default: return "?"; } } /* Same as openpgp_cipher_algo_name but returns a string in the form * "ALGO.MODE". If AEAD is 0 "CFB" is used for the mode. */ const char * openpgp_cipher_algo_mode_name (cipher_algo_t algo, aead_algo_t aead) { return map_static_strings ("openpgp_cipher_algo_mode_name", algo, aead, openpgp_cipher_algo_name (algo), ".", aead? openpgp_aead_algo_name (aead) : "CFB", NULL); } /* Return 0 if ALGO is supported. Return an error if not. */ gpg_error_t openpgp_aead_test_algo (aead_algo_t algo) { /* FIXME: We currently have no easy way to test whether libgcrypt * implements a mode. The only way we can do this is to open a * cipher context with that mode and close it immediately. That is * a bit costly. Thus in case we add another algo we need to look * at the libgcrypt version and assume nothing has been patched out. */ switch (algo) { case AEAD_ALGO_NONE: break; case AEAD_ALGO_EAX: case AEAD_ALGO_OCB: return 0; } return gpg_error (GPG_ERR_INV_CIPHER_MODE); } /* Map the OpenPGP AEAD algorithm with ID ALGO to a string * representation of the algorithm name. For unknown algorithm IDs * this function returns "?". */ const char * openpgp_aead_algo_name (aead_algo_t algo) { switch (algo) { case AEAD_ALGO_NONE: break; case AEAD_ALGO_EAX: return "EAX"; case AEAD_ALGO_OCB: return "OCB"; } return "?"; } /* Return information for the AEAD algorithm ALGO. The corresponding * Libgcrypt ciphermode is stored at R_MODE and the required number of * octets for the nonce at R_NONCELEN. On error and error code is * returned. Note that the taglen is always 128 bits. */ gpg_error_t openpgp_aead_algo_info (aead_algo_t algo, enum gcry_cipher_modes *r_mode, unsigned int *r_noncelen) { switch (algo) { case AEAD_ALGO_OCB: *r_mode = GCRY_CIPHER_MODE_OCB; *r_noncelen = 15; break; case AEAD_ALGO_EAX: *r_mode = MY_GCRY_CIPHER_MODE_EAX; *r_noncelen = 16; break; default: log_error ("unsupported AEAD algo %d\n", algo); return gpg_error (GPG_ERR_INV_CIPHER_MODE); } return 0; } /* Return 0 if ALGO is a supported OpenPGP public key algorithm. */ int openpgp_pk_test_algo (pubkey_algo_t algo) { return openpgp_pk_test_algo2 (algo, 0); } /* Return 0 if ALGO is a supported OpenPGP public key algorithm and allows the usage USE. */ int openpgp_pk_test_algo2 (pubkey_algo_t algo, unsigned int use) { enum gcry_pk_algos ga = 0; size_t use_buf = use; switch (algo) { #ifdef GPG_USE_RSA case PUBKEY_ALGO_RSA: ga = GCRY_PK_RSA; break; case PUBKEY_ALGO_RSA_E: ga = GCRY_PK_RSA_E; break; case PUBKEY_ALGO_RSA_S: ga = GCRY_PK_RSA_S; break; #else case PUBKEY_ALGO_RSA: break; case PUBKEY_ALGO_RSA_E: break; case PUBKEY_ALGO_RSA_S: break; #endif case PUBKEY_ALGO_ELGAMAL_E: ga = GCRY_PK_ELG; break; case PUBKEY_ALGO_DSA: ga = GCRY_PK_DSA; break; #ifdef GPG_USE_ECDH case PUBKEY_ALGO_ECDH: ga = GCRY_PK_ECC; break; #else case PUBKEY_ALGO_ECDH: break; #endif #ifdef GPG_USE_ECDSA case PUBKEY_ALGO_ECDSA: ga = GCRY_PK_ECC; break; #else case PUBKEY_ALGO_ECDSA: break; #endif #ifdef GPG_USE_EDDSA case PUBKEY_ALGO_EDDSA: ga = GCRY_PK_ECC; break; #else case PUBKEY_ALGO_EDDSA: break; #endif case PUBKEY_ALGO_ELGAMAL: /* Don't allow type 20 keys unless in rfc2440 mode. */ if (RFC2440) ga = GCRY_PK_ELG; break; case PUBKEY_ALGO_KYBER: ga = GCRY_PK_KEM; break; default: break; } if (!ga) return gpg_error (GPG_ERR_PUBKEY_ALGO); /* Elgamal in OpenPGP used to support signing and Libgcrypt still * does. However, we removed the signing capability from gpg ages * ago. This function should reflect this so that errors are thrown * early and not only when we try to sign using Elgamal. */ if (ga == GCRY_PK_ELG && (use & (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG))) return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); /* Now check whether Libgcrypt has support for the algorithm. */ return gcry_pk_algo_info (ga, GCRYCTL_TEST_ALGO, NULL, &use_buf); } int openpgp_pk_algo_usage ( int algo ) { int use = 0; /* They are hardwired in gpg 1.0. */ switch ( algo ) { case PUBKEY_ALGO_RSA: use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC | PUBKEY_USAGE_AUTH); break; case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_ECDH: use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC; break; case PUBKEY_ALGO_RSA_S: use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG; break; case PUBKEY_ALGO_ELGAMAL: if (RFC2440) use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC; break; case PUBKEY_ALGO_ELGAMAL_E: use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC; break; case PUBKEY_ALGO_DSA: use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; break; case PUBKEY_ALGO_ECDSA: case PUBKEY_ALGO_EDDSA: use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; break; case PUBKEY_ALGO_KYBER: use = PUBKEY_USAGE_ENC | PUBKEY_USAGE_RENC; break; case PUBKEY_ALGO_DIL3_25519: case PUBKEY_ALGO_DIL5_448: case PUBKEY_ALGO_SPHINX_SHA2: use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG; break; default: break; } return use; } /* Map the OpenPGP pubkey algorithm whose ID is contained in ALGO to a string representation of the algorithm name. For unknown algorithm IDs this function returns "?". */ const char * openpgp_pk_algo_name (pubkey_algo_t algo) { switch (algo) { case PUBKEY_ALGO_RSA: case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: return "RSA"; case PUBKEY_ALGO_ELGAMAL: case PUBKEY_ALGO_ELGAMAL_E: return "ELG"; case PUBKEY_ALGO_DSA: return "DSA"; case PUBKEY_ALGO_ECDH: return "ECDH"; case PUBKEY_ALGO_ECDSA: return "ECDSA"; case PUBKEY_ALGO_EDDSA: return "EDDSA"; default: return "?"; } } /* Explicit mapping of OpenPGP digest algos to Libgcrypt. */ /* FIXME: We do not yes use it everywhere. */ enum gcry_md_algos map_md_openpgp_to_gcry (digest_algo_t algo) { switch (algo) { #ifdef GPG_USE_MD5 case DIGEST_ALGO_MD5: return GCRY_MD_MD5; #else case DIGEST_ALGO_MD5: return 0; #endif case DIGEST_ALGO_SHA1: return GCRY_MD_SHA1; #ifdef GPG_USE_RMD160 case DIGEST_ALGO_RMD160: return GCRY_MD_RMD160; #else case DIGEST_ALGO_RMD160: return 0; #endif #ifdef GPG_USE_SHA224 case DIGEST_ALGO_SHA224: return GCRY_MD_SHA224; #else case DIGEST_ALGO_SHA224: return 0; #endif case DIGEST_ALGO_SHA256: return GCRY_MD_SHA256; #ifdef GPG_USE_SHA384 case DIGEST_ALGO_SHA384: return GCRY_MD_SHA384; #else case DIGEST_ALGO_SHA384: return 0; #endif #ifdef GPG_USE_SHA512 case DIGEST_ALGO_SHA512: return GCRY_MD_SHA512; #else case DIGEST_ALGO_SHA512: return 0; #endif default: return 0; } } /* Return 0 if ALGO is suitable and implemented OpenPGP hash algorithm. */ int openpgp_md_test_algo (digest_algo_t algo) { enum gcry_md_algos ga; ga = map_md_openpgp_to_gcry (algo); if (!ga) return gpg_error (GPG_ERR_DIGEST_ALGO); return gcry_md_test_algo (ga); } /* Map the OpenPGP digest algorithm whose ID is contained in ALGO to a string representation of the algorithm name. For unknown algorithm IDs this function returns "?". */ const char * openpgp_md_algo_name (int algo) { switch (algo) { case DIGEST_ALGO_MD5: return "MD5"; case DIGEST_ALGO_SHA1: return "SHA1"; case DIGEST_ALGO_RMD160: return "RIPEMD160"; case DIGEST_ALGO_SHA256: return "SHA256"; case DIGEST_ALGO_SHA384: return "SHA384"; case DIGEST_ALGO_SHA512: return "SHA512"; case DIGEST_ALGO_SHA224: return "SHA224"; } return "?"; } static unsigned long get_signature_count (PKT_public_key *pk) { #ifdef ENABLE_CARD_SUPPORT struct agent_card_info_s info; (void)pk; if (!agent_scd_getattr ("SIG-COUNTER",&info)) return info.sig_counter; else return 0; #else (void)pk; return 0; #endif } /* Expand %-strings. Returns a string which must be xfreed. Returns NULL if the string cannot be expanded (too large). */ char * pct_expando (ctrl_t ctrl, const char *string,struct expando_args *args) { const char *ch=string; int idx=0,maxlen=0,done=0; u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0}; char *ret=NULL; /* The parser below would return NULL for an empty string, thus we * catch it here. Also catch NULL here. */ if (!string || !*string) return xstrdup (""); if(args->pk) keyid_from_pk(args->pk,pk_keyid); if(args->pksk) keyid_from_pk (args->pksk, sk_keyid); /* This is used so that %k works in photoid command strings in --list-secret-keys (which of course has a sk, but no pk). */ if(!args->pk && args->pksk) keyid_from_pk (args->pksk, pk_keyid); while(*ch!='\0') { if(!done) { /* 8192 is way bigger than we'll need here */ if(maxlen>=8192) goto fail; maxlen+=1024; ret=xrealloc(ret,maxlen); } done=0; if(*ch=='%') { switch(*(ch+1)) { case 's': /* short key id */ if(idx+8namehash) { char *tmp = zb32_encode (args->namehash, 8*20); if (tmp) { if (idx + strlen (tmp) < maxlen) { strcpy (ret+idx, tmp); idx += strlen (tmp); } xfree (tmp); done = 1; } } break; case 'c': /* signature count from card, if any. */ if(idx+10pksk)); idx+=strlen(&ret[idx]); done=1; } break; case 'f': /* Fingerprint of key being signed */ case 'p': /* Fingerprint of the primary key making the signature. */ case 'g': /* Fingerprint of the key making the signature. */ { byte array[MAX_FINGERPRINT_LEN]; size_t len; int i; if ((*(ch+1))=='f' && args->pk) fingerprint_from_pk (args->pk, array, &len); else if ((*(ch+1))=='p' && args->pksk) { if(args->pksk->flags.primary) fingerprint_from_pk (args->pksk, array, &len); else if (args->pksk->main_keyid[0] || args->pksk->main_keyid[1]) { /* Not the primary key: Find the fingerprint of the primary key. */ PKT_public_key *pk= xmalloc_clear(sizeof(PKT_public_key)); if (!get_pubkey_fast (ctrl, pk,args->pksk->main_keyid)) fingerprint_from_pk (pk, array, &len); else memset (array, 0, (len=MAX_FINGERPRINT_LEN)); free_public_key (pk); } else /* Oops: info about the primary key missing. */ memset(array,0,(len=MAX_FINGERPRINT_LEN)); } else if((*(ch+1))=='g' && args->pksk) fingerprint_from_pk (args->pksk, array, &len); else memset(array,0,(len=MAX_FINGERPRINT_LEN)); if(idx+(len*2)validity_info && idx+1validity_info; ret[idx]='\0'; done=1; } break; /* The text string types */ case 't': case 'T': case 'V': { const char *str=NULL; switch(*(ch+1)) { case 't': /* e.g. "jpg" */ str=image_type_to_string(args->imagetype,0); break; case 'T': /* e.g. "image/jpeg" */ str=image_type_to_string(args->imagetype,2); break; case 'V': /* e.g. "full", "expired", etc. */ str=args->validity_string; break; } if(str && idx+strlen(str) 2) result = 0; } else result = 0; return result; } /* * Wrapper around gcry_md_map_name to provide a fallback using the * "Hn" syntax as used by the preference strings. */ int string_to_digest_algo (const char *string) { int val; /* FIXME: We should make use of our wrapper function and not assume that there is a 1 to 1 mapping between OpenPGP and Libgcrypt. */ val = gcry_md_map_name (string); if (!val && string && (string[0]=='H' || string[0]=='h')) { char *endptr; string++; val = strtol (string, &endptr, 10); if (!*string || *endptr || openpgp_md_test_algo (val)) val = 0; } return val; } const char * compress_algo_to_string(int algo) { const char *s=NULL; switch(algo) { case COMPRESS_ALGO_NONE: s=_("Uncompressed"); break; case COMPRESS_ALGO_ZIP: s="ZIP"; break; case COMPRESS_ALGO_ZLIB: s="ZLIB"; break; #ifdef HAVE_BZIP2 case COMPRESS_ALGO_BZIP2: s="BZIP2"; break; #endif } return s; } int string_to_compress_algo(const char *string) { /* TRANSLATORS: See doc/TRANSLATE about this string. */ if(match_multistr(_("uncompressed|none"),string)) return 0; else if(ascii_strcasecmp(string,"uncompressed")==0) return 0; else if(ascii_strcasecmp(string,"none")==0) return 0; else if(ascii_strcasecmp(string,"zip")==0) return 1; else if(ascii_strcasecmp(string,"zlib")==0) return 2; #ifdef HAVE_BZIP2 else if(ascii_strcasecmp(string,"bzip2")==0) return 3; #endif else if(ascii_strcasecmp(string,"z0")==0) return 0; else if(ascii_strcasecmp(string,"z1")==0) return 1; else if(ascii_strcasecmp(string,"z2")==0) return 2; #ifdef HAVE_BZIP2 else if(ascii_strcasecmp(string,"z3")==0) return 3; #endif else return -1; } int check_compress_algo(int algo) { switch (algo) { case 0: return 0; #ifdef HAVE_ZIP case 1: case 2: return 0; #endif #ifdef HAVE_BZIP2 case 3: return 0; #endif default: return GPG_ERR_COMPR_ALGO; } } int default_cipher_algo(void) { if(opt.def_cipher_algo) return opt.def_cipher_algo; else if(opt.personal_cipher_prefs) return opt.personal_cipher_prefs[0].value; else return opt.s2k_cipher_algo; } /* There is no default_digest_algo function, but see sign.c:hash_for() */ int default_compress_algo(void) { if(opt.compress_algo!=-1) return opt.compress_algo; else if(opt.personal_compress_prefs) return opt.personal_compress_prefs[0].value; else return DEFAULT_COMPRESS_ALGO; } void compliance_failure(void) { char *ver="???"; switch(opt.compliance) { case CO_GNUPG: ver="GnuPG"; break; case CO_RFC4880: ver="OpenPGP"; break; case CO_RFC2440: ver="OpenPGP (older)"; break; case CO_PGP7: ver="PGP 7.x"; break; case CO_PGP8: ver="PGP 8.x"; break; case CO_DE_VS: ver="DE-VS applications"; break; } log_info(_("this message may not be usable by %s\n"),ver); opt.compliance=CO_GNUPG; } /* Break a string into successive option pieces. Accepts single word options and key=value argument options. */ char * optsep(char **stringp) { char *tok,*end; tok=*stringp; if(tok) { end=strpbrk(tok," ,="); if(end) { int sawequals=0; char *ptr=end; /* what we need to do now is scan along starting with *end, If the next character we see (ignoring spaces) is an = sign, then there is an argument. */ while(*ptr) { if(*ptr=='=') sawequals=1; else if(*ptr!=' ') break; ptr++; } /* There is an argument, so grab that too. At this point, ptr points to the first character of the argument. */ if(sawequals) { /* Is it a quoted argument? */ if(*ptr=='"') { ptr++; end=strchr(ptr,'"'); if(end) end++; } else end=strpbrk(ptr," ,"); } if(end && *end) { *end='\0'; *stringp=end+1; } else *stringp=NULL; } else *stringp=NULL; } return tok; } /* Breaks an option value into key and value. Returns NULL if there is no value. Note that "string" is modified to remove the =value part. */ char * argsplit(char *string) { char *equals,*arg=NULL; equals=strchr(string,'='); if(equals) { char *quote,*space; *equals='\0'; arg=equals+1; /* Quoted arg? */ quote=strchr(arg,'"'); if(quote) { arg=quote+1; quote=strchr(arg,'"'); if(quote) *quote='\0'; } else { size_t spaces; /* Trim leading spaces off of the arg */ spaces=strspn(arg," "); arg+=spaces; } /* Trim tailing spaces off of the tag */ space=strchr(string,' '); if(space) *space='\0'; } return arg; } /* Return the length of the initial token, leaving off any argument. */ static size_t optlen(const char *s) { char *end=strpbrk(s," ="); if(end) return end-s; else return strlen(s); } /* Note: This function returns true on success. */ int parse_options(char *str,unsigned int *options, struct parse_options *opts,int noisy) { char *tok; if (str && (!strcmp (str, "help") || !strcmp (str, "full-help"))) { int i,maxlen=0; int full = *str == 'f'; /* Figure out the longest option name so we can line these up neatly. */ for(i=0;opts[i].name;i++) if(opts[i].help && maxlen='A' && file[0]<='Z') || (file[0]>='a' && file[0]<='z')) && file[1]==':') #else || file[0]=='/' #endif ) return access(file,mode); else { /* At least as large as, but most often larger than we need. */ char *buffer=xmalloc(strlen(envpath)+1+strlen(file)+1); char *split,*item,*path=xstrdup(envpath); split=path; while((item=strsep(&split,PATHSEP_S))) { strcpy(buffer,item); strcat(buffer,"/"); strcat(buffer,file); ret=access(buffer,mode); if(ret==0) break; } xfree(path); xfree(buffer); } return ret; } /* Return the number of public key parameters as used by OpenPGP. */ int pubkey_get_npkey (pubkey_algo_t algo) { switch (algo) { case PUBKEY_ALGO_RSA: case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: return 2; case PUBKEY_ALGO_ELGAMAL_E: return 3; case PUBKEY_ALGO_DSA: return 4; case PUBKEY_ALGO_ECDH: return 3; case PUBKEY_ALGO_ECDSA: return 2; case PUBKEY_ALGO_ELGAMAL: return 3; case PUBKEY_ALGO_EDDSA: return 2; case PUBKEY_ALGO_KYBER: return 3; default: return 0; } } /* Return the number of secret key parameters as used by OpenPGP. */ int pubkey_get_nskey (pubkey_algo_t algo) { switch (algo) { case PUBKEY_ALGO_RSA: case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: return 6; case PUBKEY_ALGO_ELGAMAL_E: return 4; case PUBKEY_ALGO_DSA: return 5; case PUBKEY_ALGO_ECDH: return 4; case PUBKEY_ALGO_ECDSA: return 3; case PUBKEY_ALGO_ELGAMAL: return 4; case PUBKEY_ALGO_EDDSA: return 3; case PUBKEY_ALGO_KYBER: return 5; default: return 0; } } /* Temporary helper. */ int pubkey_get_nsig (pubkey_algo_t algo) { switch (algo) { case PUBKEY_ALGO_RSA: case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: return 1; case PUBKEY_ALGO_ELGAMAL_E: return 0; case PUBKEY_ALGO_DSA: return 2; case PUBKEY_ALGO_ECDH: return 0; case PUBKEY_ALGO_ECDSA: return 2; case PUBKEY_ALGO_ELGAMAL: return 2; case PUBKEY_ALGO_EDDSA: return 2; default: return 0; } } /* Temporary helper. */ int pubkey_get_nenc (pubkey_algo_t algo) { switch (algo) { case PUBKEY_ALGO_RSA: case PUBKEY_ALGO_RSA_E: case PUBKEY_ALGO_RSA_S: return 1; case PUBKEY_ALGO_ELGAMAL_E: return 2; case PUBKEY_ALGO_DSA: return 0; case PUBKEY_ALGO_ECDH: return 2; case PUBKEY_ALGO_ECDSA: return 0; case PUBKEY_ALGO_ELGAMAL: return 2; case PUBKEY_ALGO_EDDSA: return 0; - case PUBKEY_ALGO_KYBER: return 4; + case PUBKEY_ALGO_KYBER: return 3; default: return 0; } } /* Temporary helper. */ unsigned int pubkey_nbits( int algo, gcry_mpi_t *key ) { int rc, nbits; gcry_sexp_t sexp; if (algo == PUBKEY_ALGO_DSA && key[0] && key[1] && key[2] && key[3]) { rc = gcry_sexp_build (&sexp, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", key[0], key[1], key[2], key[3] ); } else if ((algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E) && key[0] && key[1] && key[2]) { rc = gcry_sexp_build (&sexp, NULL, "(public-key(elg(p%m)(g%m)(y%m)))", key[0], key[1], key[2] ); } else if (is_RSA (algo) && key[0] && key[1]) { rc = gcry_sexp_build (&sexp, NULL, "(public-key(rsa(n%m)(e%m)))", key[0], key[1] ); } else if ((algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_EDDSA) && key[0] && key[1]) { char *curve = openpgp_oid_to_str (key[0]); if (!curve) rc = gpg_error_from_syserror (); else { rc = gcry_sexp_build (&sexp, NULL, "(public-key(ecc(curve%s)(q%m)))", curve, key[1]); xfree (curve); } } else return 0; if (rc) BUG (); nbits = gcry_pk_get_nbits (sexp); gcry_sexp_release (sexp); return nbits; } int mpi_print (estream_t fp, gcry_mpi_t a, int mode) { int n = 0; size_t nwritten; if (!a) return es_fprintf (fp, "[MPI_NULL]"); if (!mode) { unsigned int n1; n1 = gcry_mpi_get_nbits(a); n += es_fprintf (fp, "[%u bits]", n1); } else if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; unsigned char *p = gcry_mpi_get_opaque (a, &nbits); if (!p) n += es_fprintf (fp, "[invalid opaque value]"); else { if (!es_write_hexstring (fp, p, (nbits + 7)/8, 0, &nwritten)) n += nwritten; } } else { unsigned char *buffer; size_t buflen; if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &buflen, a)) BUG (); if (!es_write_hexstring (fp, buffer, buflen, 0, &nwritten)) n += nwritten; gcry_free (buffer); } return n; } /* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ unsigned int ecdsa_qbits_from_Q (unsigned int qbits) { if ((qbits%8) > 3) { log_error (_("ECDSA public key is expected to be in SEC encoding " "multiple of 8 bits\n")); return 0; } qbits -= qbits%8; qbits /= 2; return qbits; } /* Ignore signatures and certifications made over certain digest * algorithms by default, MD5 is considered weak. This allows users * to deprecate support for other algorithms as well. */ void additional_weak_digest (const char* digestname) { struct weakhash *weak = NULL; const enum gcry_md_algos algo = string_to_digest_algo(digestname); if (algo == GCRY_MD_NONE) { log_error (_("unknown weak digest '%s'\n"), digestname); return; } /* Check to ensure it's not already present. */ for (weak = opt.weak_digests; weak; weak = weak->next) if (algo == weak->algo) return; /* Add it to the head of the list. */ weak = xmalloc(sizeof(*weak)); weak->algo = algo; weak->rejection_shown = 0; weak->next = opt.weak_digests; opt.weak_digests = weak; } /* Return true if ALGO is in the list of weak digests. */ int is_weak_digest (digest_algo_t algo) { const enum gcry_md_algos galgo = map_md_openpgp_to_gcry (algo); const struct weakhash *weak; for (weak = opt.weak_digests; weak; weak = weak->next) if (weak->algo == galgo) return 1; return 0; } diff --git a/g10/packet.h b/g10/packet.h index 40e5051c0..459e38dda 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -1,965 +1,968 @@ /* packet.h - OpenPGP packet definitions * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2007 Free Software Foundation, Inc. * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef G10_PACKET_H #define G10_PACKET_H #include "../common/types.h" #include "../common/iobuf.h" #include "../common/strlist.h" #include "dek.h" #include "filter.h" #include "../common/openpgpdefs.h" #include "../common/userids.h" #include "../common/util.h" #define DEBUG_PARSE_PACKET 1 /* Maximum length of packets to avoid excessive memory allocation. */ #define MAX_KEY_PACKET_LENGTH (256 * 1024) #define MAX_UID_PACKET_LENGTH ( 2 * 1024) #define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024) #define MAX_ATTR_PACKET_LENGTH ( 16 * 1024*1024) /* Constants to allocate static MPI arrays. */ #define PUBKEY_MAX_NPKEY OPENPGP_MAX_NPKEY #define PUBKEY_MAX_NSKEY OPENPGP_MAX_NSKEY #define PUBKEY_MAX_NSIG OPENPGP_MAX_NSIG #define PUBKEY_MAX_NENC OPENPGP_MAX_NENC /* Usage flags */ #define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */ #define PUBKEY_USAGE_ENC GCRY_PK_USAGE_ENCR /* Good for encryption. */ #define PUBKEY_USAGE_CERT GCRY_PK_USAGE_CERT /* Also good to certify keys.*/ #define PUBKEY_USAGE_AUTH GCRY_PK_USAGE_AUTH /* Good for authentication. */ #define PUBKEY_USAGE_UNKNOWN GCRY_PK_USAGE_UNKN /* Unknown usage flag. */ #define PUBKEY_USAGE_NONE 256 /* No usage given. */ #if (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR | GCRY_PK_USAGE_CERT \ | GCRY_PK_USAGE_AUTH | GCRY_PK_USAGE_UNKN) >= 256 # error Please choose another value for PUBKEY_USAGE_NONE #endif #define PUBKEY_USAGE_GROUP 512 /* Group flag. */ #define PUBKEY_USAGE_RENC 1024 /* Restricted encryption. */ #define PUBKEY_USAGE_TIME 2048 /* Timestamp use. */ /* Bitflags to convey hints on what kind of signature is created. */ #define SIGNHINT_KEYSIG 1 #define SIGNHINT_SELFSIG 2 #define SIGNHINT_ADSK 4 /* Helper macros. */ #define is_RSA(a) ((a)==PUBKEY_ALGO_RSA || (a)==PUBKEY_ALGO_RSA_E \ || (a)==PUBKEY_ALGO_RSA_S ) #define is_ELGAMAL(a) ((a)==PUBKEY_ALGO_ELGAMAL_E) #define is_DSA(a) ((a)==PUBKEY_ALGO_DSA) /* A pointer to the packet object. */ typedef struct packet_struct PACKET; /* PKT_GPG_CONTROL types */ typedef enum { CTRLPKT_CLEARSIGN_START = 1, CTRLPKT_PIPEMODE = 2, CTRLPKT_PLAINTEXT_MARK =3 } ctrlpkttype_t; typedef enum { PREFTYPE_NONE = 0, PREFTYPE_SYM = 1, PREFTYPE_HASH = 2, PREFTYPE_ZIP = 3, PREFTYPE_AEAD = 4 } preftype_t; typedef struct { byte type; byte value; } prefitem_t; /* A string-to-key specifier as defined in RFC 4880, Section 3.7. */ typedef struct { int mode; /* Must be an integer due to the GNU modes 1001 et al. */ byte hash_algo; byte salt[8]; /* The *coded* (i.e., the serialized version) iteration count. */ u32 count; } STRING2KEY; /* A symmetric-key encrypted session key packet as defined in RFC 4880, Section 5.3. All fields are serialized. */ typedef struct { /* We support version 4 (rfc4880) and 5 (rfc4880bis). */ byte version; /* The cipher algorithm used to encrypt the session key. Note that * this may be different from the algorithm that is used to encrypt * bulk data. */ byte cipher_algo; /* The AEAD algorithm or 0 for CFB encryption. */ byte aead_algo; /* The string-to-key specifier. */ STRING2KEY s2k; /* The length of SESKEY in bytes or 0 if this packet does not encrypt a session key. (In the latter case, the results of the S2K function on the password is the session key. See RFC 4880, Section 5.3.) */ byte seskeylen; /* The session key as encrypted by the S2K specifier. For AEAD this * includes the nonce and the authentication tag. */ byte seskey[1]; } PKT_symkey_enc; /* A public-key encrypted session key packet as defined in RFC 4880, Section 5.1. All fields are serialized. */ typedef struct { /* The 64-bit keyid. */ u32 keyid[2]; /* The packet's version. Currently, only version 3 is defined. */ byte version; /* The algorithm used for the public key encryption scheme. */ byte pubkey_algo; + /* The session key algorithm used by some pubkey algos. */ + byte seskey_algo; /* Whether to hide the key id. This value is not directly serialized. */ byte throw_keyid; /* The session key. */ gcry_mpi_t data[PUBKEY_MAX_NENC]; } PKT_pubkey_enc; /* An object to build a list of public-key encrypted session key. */ struct pubkey_enc_list { struct pubkey_enc_list *next; u32 keyid[2]; int pubkey_algo; + int seskey_algo; int result; gcry_mpi_t data[PUBKEY_MAX_NENC]; }; /* A one-pass signature packet as defined in RFC 4880, Section 5.4. All fields are serialized. */ typedef struct { u32 keyid[2]; /* The 64-bit keyid */ /* The signature's classification (RFC 4880, Section 5.2.1). */ byte sig_class; byte digest_algo; /* algorithm used for digest */ byte pubkey_algo; /* algorithm used for public key scheme */ /* A message can be signed by multiple keys. In this case, there are n one-pass signature packets before the message to sign and n signatures packets after the message. It is conceivable that someone wants to not only sign the message, but all of the signatures. Now we need to distinguish between signing the message and signing the message plus the surrounding signatures. This is the point of this flag. If set, it means: I sign all of the data starting at the next packet. */ byte last; } PKT_onepass_sig; /* A v4 OpenPGP signature has a hashed and unhashed area containing co-called signature subpackets (RFC 4880, Section 5.2.3). These areas are described by this data structure. Use enum_sig_subpkt to parse this area. */ typedef struct { size_t size; /* allocated */ size_t len; /* used (serialized) */ byte data[1]; /* the serialized subpackes (serialized) */ } subpktarea_t; /* The in-memory representation of a designated revoker signature subpacket (RFC 4880, Section 5.2.3.15). */ struct revocation_key { /* A bit field. 0x80 must be set. 0x40 means this information is sensitive (and should not be uploaded to a keyserver by default). */ byte class; /* The public-key algorithm ID. */ byte algid; /* The length of the fingerprint. */ byte fprlen; /* The fingerprint of the authorized key. */ byte fpr[MAX_FINGERPRINT_LEN]; }; /* A signature packet (RFC 4880, Section 5.2). Only a subset of these fields are directly serialized (these are marked as such); the rest are read from the subpackets, which are not synthesized when serializing this data structure (i.e., when using build_packet()). Instead, the subpackets must be created by hand. */ typedef struct { struct { unsigned checked:1; /* Signature has been checked. */ unsigned valid:1; /* Signature is good (if checked is set). */ unsigned chosen_selfsig:1; /* A selfsig that is the chosen one. */ unsigned unknown_critical:1; unsigned exportable:1; unsigned revocable:1; unsigned policy_url:1; /* At least one policy URL is present */ unsigned notation:1; /* At least one notation is present */ unsigned pref_ks:1; /* At least one preferred keyserver is present */ unsigned key_block:1; /* A key block subpacket is present. */ unsigned expired:1; } flags; /* The key that allegedly generated this signature. (Directly serialized in v3 sigs; for v4 sigs, this must be explicitly added as an issuer subpacket (5.2.3.5.) */ u32 keyid[2]; /* When the signature was made (seconds since the Epoch). (Directly serialized in v3 sigs; for v4 sigs, this must be explicitly added as a signature creation time subpacket (5.2.3.4).) */ u32 timestamp; u32 expiredate; /* Expires at this date or 0 if not at all. */ /* The serialization format used / to use. If 0, then defaults to version 3. (Serialized.) */ byte version; /* The signature type. (See RFC 4880, Section 5.2.1.) */ byte sig_class; /* Algorithm used for public key scheme (e.g., PUBKEY_ALGO_RSA). (Serialized.) */ byte pubkey_algo; /* Algorithm used for digest (e.g., DIGEST_ALGO_SHA1). (Serialized.) */ byte digest_algo; byte trust_depth; byte trust_value; const byte *trust_regexp; struct revocation_key *revkey; int numrevkeys; int help_counter; /* Used internally bu some functions. */ char *signers_uid; /* Malloced value of the SIGNERS_UID * subpacket or NULL. This string has * already been sanitized. */ subpktarea_t *hashed; /* All subpackets with hashed data (v4 only). */ subpktarea_t *unhashed; /* Ditto for unhashed data. */ /* First 2 bytes of the digest. (Serialized. Note: this is not automatically filled in when serializing a signature!) */ byte digest_start[2]; /* The signature. (Serialized.) */ gcry_mpi_t data[PUBKEY_MAX_NSIG]; /* The message digest and its length (in bytes). Note the maximum digest length is 512 bits (64 bytes). If DIGEST_LEN is 0, then the digest's value has not been saved here. */ byte digest[512 / 8]; int digest_len; } PKT_signature; #define ATTRIB_IMAGE 1 /* This is the cooked form of attributes. */ struct user_attribute { byte type; const byte *data; u32 len; }; /* A user id (RFC 4880, Section 5.11) or a user attribute packet (RFC 4880, Section 5.12). Only a subset of these fields are directly serialized (these are marked as such); the rest are read from the self-signatures in merge_keys_and_selfsig()). */ typedef struct { int ref; /* reference counter */ /* The length of NAME. */ int len; struct user_attribute *attribs; int numattribs; /* If this is not NULL, the packet is a user attribute rather than a user id (See RFC 4880 5.12). (Serialized.) */ byte *attrib_data; /* The length of ATTRIB_DATA. */ unsigned long attrib_len; byte *namehash; u16 help_key_usage; u32 help_key_expire; int help_full_count; int help_marginal_count; u32 expiredate; /* expires at this date or 0 if not at all */ prefitem_t *prefs; /* list of preferences (may be NULL)*/ u32 created; /* according to the self-signature */ u32 keyupdate; /* From the ring trust packet. */ char *updateurl; /* NULL or the URL of the last update origin. */ byte keyorg; /* From the ring trust packet. */ byte selfsigversion; struct { unsigned int mdc:1; unsigned int aead:1; unsigned int ks_modify:1; unsigned int compacted:1; unsigned int primary:2; /* 2 if set via the primary flag, 1 if calculated */ /* Note that this flag is set in a * keyblock at max for one User ID and for * one User Attribute per keyblock. */ unsigned int revoked:1; unsigned int expired:1; } flags; char *mbox; /* NULL or the result of mailbox_from_userid. */ /* The text contained in the user id packet, which is normally the * name and email address of the key holder (See RFC 4880 5.11). * (Serialized.). For convenience an extra Nul is always appended. */ char name[1]; } PKT_user_id; struct revoke_info { /* revoked at this date */ u32 date; /* the keyid of the revoking key (selfsig or designated revoker) */ u32 keyid[2]; /* the algo of the revoking key */ byte algo; }; /* Information pertaining to secret keys. */ struct seckey_info { unsigned int is_protected:1; /* The secret info is protected and must */ /* be decrypted before use, the protected */ /* MPIs are simply (void*) pointers to memory */ /* and should never be passed to a mpi_xxx() */ unsigned int sha1chk:1; /* SHA1 is used instead of a 16 bit checksum */ u16 csum; /* Checksum for old protection modes. */ byte algo; /* Cipher used to protect the secret information. */ STRING2KEY s2k; /* S2K parameter. */ byte ivlen; /* Used length of the IV. */ byte iv[16]; /* Initialization vector for CFB mode. */ }; /**************** * The in-memory representation of a public key (RFC 4880, Section * 5.5). Note: this structure contains significantly more information * than is contained in an OpenPGP public key packet. This * information is derived from the self-signed signatures (by * merge_keys_and_selfsig()) and is ignored when serializing the * packet. The fields that are actually written out when serializing * this packet are marked as accordingly. * * We assume that secret keys have the same number of parameters as * the public key and that the public parameters are the first items * in the PKEY array. Thus NPKEY is always less than NSKEY and it is * possible to compare the secret and public keys by comparing the * first NPKEY elements of the PKEY array. Note that since GnuPG 2.1 * we don't use secret keys anymore directly because they are managed * by gpg-agent. However for parsing OpenPGP key files we need a way * to temporary store those secret keys. We do this by putting them * into the public key structure and extending the PKEY field to NSKEY * elements; the extra secret key information are stored in the * SECKEY_INFO field. */ typedef struct { /* When the key was created. (Serialized.) */ u32 timestamp; u32 expiredate; /* expires at this date or 0 if not at all */ u32 max_expiredate; /* must not expire past this date */ struct revoke_info revoked; /* An OpenPGP packet consists of a header and a body. This is the size of the header. If this is 0, an appropriate size is automatically chosen based on the size of the body. (Serialized.) */ byte hdrbytes; /* The serialization format. If 0, the default version (4) is used when serializing. (Serialized.) */ byte version; byte selfsigversion; /* highest version of all of the self-sigs */ /* The public key algorithm. (Serialized.) */ byte pubkey_algo; u16 pubkey_usage; /* carries the usage info. */ byte req_usage; /* hack to pass a request to getkey() */ byte fprlen; /* 0 or length of FPR. */ u32 has_expired; /* set to the expiration date if expired */ /* keyid of the primary key. Never access this value directly. Instead, use pk_main_keyid(). */ u32 main_keyid[2]; /* keyid of this key. Never access this value directly! Instead, use pk_keyid(). */ u32 keyid[2]; /* Fingerprint of the key. Only valid if FPRLEN is not 0. */ byte fpr[MAX_FINGERPRINT_LEN]; prefitem_t *prefs; /* list of preferences (may be NULL) */ struct { unsigned int mdc:1; /* MDC feature set. */ unsigned int aead:1; /* AEAD feature set. */ unsigned int disabled_valid:1;/* The next flag is valid. */ unsigned int disabled:1; /* The key has been disabled. */ unsigned int primary:1; /* This is a primary key. */ unsigned int revoked:2; /* Key has been revoked. 1 = revoked by the owner 2 = revoked by designated revoker. */ unsigned int maybe_revoked:1; /* A designated revocation is present, but without the key to check it. */ unsigned int valid:1; /* Key (especially subkey) is valid. */ unsigned int dont_cache:1; /* Do not cache this key. */ unsigned int backsig:2; /* 0=none, 1=bad, 2=good. */ unsigned int serialno_valid:1;/* SERIALNO below is valid. */ unsigned int exact:1; /* Found via exact (!) search. */ } flags; PKT_user_id *user_id; /* If != NULL: found by that uid. */ struct revocation_key *revkey; int numrevkeys; u32 trust_timestamp; byte trust_depth; byte trust_value; byte keyorg; /* From the ring trust packet. */ u32 keyupdate; /* From the ring trust packet. */ char *updateurl; /* NULL or the URL of the last update origin. */ const byte *trust_regexp; char *serialno; /* Malloced hex string or NULL if it is likely not on a card. See also flags.serialno_valid. */ /* If not NULL this malloced structure describes a secret key. (Serialized.) */ struct seckey_info *seckey_info; /* The public key. Contains pubkey_get_npkey (pubkey_algo) + pubkey_get_nskey (pubkey_algo) MPIs. (If pubkey_get_npkey returns 0, then the algorithm is not understood and the PKEY contains a single opaque MPI.) (Serialized.) */ gcry_mpi_t pkey[PUBKEY_MAX_NSKEY]; /* Right, NSKEY elements. */ } PKT_public_key; /* Evaluates as true if the pk is disabled, and false if it isn't. If there is no disable value cached, fill one in. */ #define pk_is_disabled(a) \ (((a)->flags.disabled_valid)? \ ((a)->flags.disabled):(cache_disabled_value(ctrl,(a)))) typedef struct { int len; /* length of data */ char data[1]; } PKT_comment; /* A compression packet (RFC 4880, Section 5.6). */ typedef struct { /* Not used. */ u32 len; /* Whether the serialized version of the packet used / should use the new format. */ byte new_ctb; /* The compression algorithm. */ byte algorithm; /* An iobuf holding the data to be decompressed. (This is not used for compression!) */ iobuf_t buf; } PKT_compressed; /* A symmetrically encrypted data packet (RFC 4880, Section 5.7) or a symmetrically encrypted integrity protected data packet (Section 5.13) */ typedef struct { /* Remaining length of encrypted data. */ u32 len; /* When encrypting in CFB mode, the first block size bytes of data * are random data and the following 2 bytes are copies of the last * two bytes of the random data (RFC 4880, Section 5.7). This * provides a simple check that the key is correct. EXTRALEN is the * size of this extra data or, in AEAD mode, the length of the * headers and the tags. This is used by build_packet when writing * out the packet's header. */ int extralen; /* Whether the serialized version of the packet used / should use the new format. */ byte new_ctb; /* Whether the packet has an indeterminate length (old format) or was encoded using partial body length headers (new format). Note: this is ignored when encrypting. */ byte is_partial; /* If 0, MDC is disabled. Otherwise, the MDC method that was used (only DIGEST_ALGO_SHA1 has ever been defined). */ byte mdc_method; /* If 0, AEAD is not used. Otherwise, the used AEAD algorithm. * MDC_METHOD (above) shall be zero if AEAD is used. */ byte aead_algo; /* The cipher algo for/from the AEAD packet. 0 for other encryption * packets. */ byte cipher_algo; /* The chunk byte from the AEAD packet. */ byte chunkbyte; /* An iobuf holding the data to be decrypted. (This is not used for encryption!) */ iobuf_t buf; } PKT_encrypted; typedef struct { byte hash[20]; } PKT_mdc; /* Subtypes for the ring trust packet. */ #define RING_TRUST_SIG 0 /* The classical signature cache. */ #define RING_TRUST_KEY 1 /* A KEYORG on a primary key. */ #define RING_TRUST_UID 2 /* A KEYORG on a user id. */ /* The local only ring trust packet which OpenPGP declares as * implementation defined. GnuPG uses this to cache signature * verification status and since 2.1.18 also to convey information * about the origin of a key. Note that this packet is not part * struct packet_struct because we use it only local in the packet * parser and builder. */ typedef struct { unsigned int trustval; unsigned int sigcache; unsigned char subtype; /* The subtype of this ring trust packet. */ unsigned char keyorg; /* The origin of the key (KEYORG_*). */ u32 keyupdate; /* The wall time the key was last updated. */ char *url; /* NULL or the URL of the source. */ } PKT_ring_trust; /* A plaintext packet (see RFC 4880, 5.9). */ typedef struct { /* The length of data in BUF or 0 if unknown. */ u32 len; /* A buffer containing the data stored in the packet's body. */ iobuf_t buf; byte new_ctb; byte is_partial; /* partial length encoded */ /* The data's formatting. This is either 'b', 't', 'u', 'l' or '1' (however, the last two are deprecated). */ int mode; u32 timestamp; /* The name of the file. This can be at most 255 characters long, since namelen is just a byte in the serialized format. */ int namelen; char name[1]; } PKT_plaintext; typedef struct { int control; size_t datalen; char data[1]; } PKT_gpg_control; /* combine all packets into a union */ struct packet_struct { pkttype_t pkttype; union { void *generic; PKT_symkey_enc *symkey_enc; /* PKT_SYMKEY_ENC */ PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */ PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */ PKT_signature *signature; /* PKT_SIGNATURE */ PKT_public_key *public_key; /* PKT_PUBLIC_[SUB]KEY */ PKT_public_key *secret_key; /* PKT_SECRET_[SUB]KEY */ PKT_comment *comment; /* PKT_COMMENT */ PKT_user_id *user_id; /* PKT_USER_ID */ PKT_compressed *compressed; /* PKT_COMPRESSED */ PKT_encrypted *encrypted; /* PKT_ENCRYPTED[_MDC] */ PKT_mdc *mdc; /* PKT_MDC */ PKT_plaintext *plaintext; /* PKT_PLAINTEXT */ PKT_gpg_control *gpg_control; /* PKT_GPG_CONTROL */ } pkt; }; #define init_packet(a) do { (a)->pkttype = 0; \ (a)->pkt.generic = NULL; \ } while(0) /* A notation. See RFC 4880, Section 5.2.3.16. */ struct notation { /* The notation's name. */ char *name; /* If the notation is human readable, then the value is stored here as a NUL-terminated string. If it is not human readable a human readable approximation of the binary value _may_ be stored here. */ char *value; /* Sometimes we want to %-expand the value. In these cases, we save that transformed value here. */ char *altvalue; /* If the notation is not human readable or the function does not want to distinguish that, then the value is stored here. */ unsigned char *bdat; /* The amount of data stored in BDAT. Note: if this is 0 and BDAT is NULL, this does not necessarily mean that the value is human readable. It could be that we have a 0-length value. To determine whether the notation is human readable, always check if VALUE is not NULL. This works, because if a human-readable value has a length of 0, we will still allocate space for the NUL byte. */ size_t blen; struct { /* The notation is critical. */ unsigned int critical:1; /* The notation is human readable. */ unsigned int human:1; /* The notation should be deleted. */ unsigned int ignore:1; } flags; /* A field to facilitate creating a list of notations. */ struct notation *next; }; typedef struct notation *notation_t; /*-- mainproc.c --*/ void reset_literals_seen(void); int proc_packets (ctrl_t ctrl, void *ctx, iobuf_t a ); int proc_signature_packets (ctrl_t ctrl, void *ctx, iobuf_t a, strlist_t signedfiles, const char *sigfile ); int proc_signature_packets_by_fd (ctrl_t ctrl, void *anchor, IOBUF a, gnupg_fd_t signed_data_fd); int proc_encryption_packets (ctrl_t ctrl, void *ctx, iobuf_t a); int list_packets( iobuf_t a ); const byte *issuer_fpr_raw (PKT_signature *sig, size_t *r_len); char *issuer_fpr_string (PKT_signature *sig); /*-- parse-packet.c --*/ void register_known_notation (const char *string); /* Sets the packet list mode to MODE (i.e., whether we are dumping a packet or not). Returns the current mode. This allows for temporarily suspending dumping by doing the following: int saved_mode = set_packet_list_mode (0); ... set_packet_list_mode (saved_mode); */ int set_packet_list_mode( int mode ); /* A context used with parse_packet. */ struct parse_packet_ctx_s { iobuf_t inp; /* The input stream with the packets. */ struct packet_struct last_pkt; /* The last parsed packet. */ int free_last_pkt; /* Indicates that LAST_PKT must be freed. */ int skip_meta; /* Skip ring trust packets. */ unsigned int n_parsed_packets; /* Number of parsed packets. */ }; typedef struct parse_packet_ctx_s *parse_packet_ctx_t; #define init_parse_packet(a,i) do { \ (a)->inp = (i); \ (a)->last_pkt.pkttype = 0; \ (a)->last_pkt.pkt.generic= NULL;\ (a)->free_last_pkt = 0; \ (a)->skip_meta = 0; \ (a)->n_parsed_packets = 0; \ } while (0) #define deinit_parse_packet(a) do { \ if ((a)->free_last_pkt) \ free_packet (NULL, (a)); \ } while (0) #if DEBUG_PARSE_PACKET /* There are debug functions and should not be used directly. */ int dbg_search_packet (parse_packet_ctx_t ctx, PACKET *pkt, off_t *retpos, int with_uid, const char* file, int lineno ); int dbg_parse_packet (parse_packet_ctx_t ctx, PACKET *ret_pkt, const char *file, int lineno); int dbg_copy_all_packets( iobuf_t inp, iobuf_t out, const char* file, int lineno ); int dbg_copy_some_packets( iobuf_t inp, iobuf_t out, off_t stopoff, const char* file, int lineno ); int dbg_skip_some_packets( iobuf_t inp, unsigned n, const char* file, int lineno ); #define search_packet( a,b,c,d ) \ dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) #define parse_packet( a, b ) \ dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) #define copy_all_packets( a,b ) \ dbg_copy_all_packets((a),(b), __FILE__, __LINE__ ) #define copy_some_packets( a,b,c ) \ dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ ) #define skip_some_packets( a,b ) \ dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) #else /* Return the next valid OpenPGP packet in *PKT. (This function will * skip any packets whose type is 0.) CTX must have been setup prior to * calling this function. * * Returns 0 on success, -1 if EOF is reached, and an error code * otherwise. In the case of an error, the packet in *PKT may be * partially constructed. As such, even if there is an error, it is * necessary to free *PKT to avoid a resource leak. To detect what * has been allocated, clear *PKT before calling this function. */ int parse_packet (parse_packet_ctx_t ctx, PACKET *pkt); /* Return the first OpenPGP packet in *PKT that contains a key (either * a public subkey, a public key, a secret subkey or a secret key) or, * if WITH_UID is set, a user id. * * Saves the position in the pipeline of the start of the returned * packet (according to iobuf_tell) in RETPOS, if it is not NULL. * * The return semantics are the same as parse_packet. */ int search_packet (parse_packet_ctx_t ctx, PACKET *pkt, off_t *retpos, int with_uid); /* Copy all packets (except invalid packets, i.e., those with a type * of 0) from INP to OUT until either an error occurs or EOF is * reached. * * Returns -1 when end of file is reached or an error code, if an * error occurred. (Note: this function never returns 0, because it * effectively keeps going until it gets an EOF.) */ int copy_all_packets (iobuf_t inp, iobuf_t out ); /* Like copy_all_packets, but stops at the first packet that starts at * or after STOPOFF (as indicated by iobuf_tell). * * Example: if STOPOFF is 100, the first packet in INP goes from * 0 to 110 and the next packet starts at offset 111, then the packet * starting at offset 0 will be completely processed (even though it * extends beyond STOPOFF) and the packet starting at offset 111 will * not be processed at all. */ int copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff); /* Skips the next N packets from INP. * * If parsing a packet returns an error code, then the function stops * immediately and returns the error code. Note: in the case of an * error, this function does not indicate how many packets were * successfully processed. */ int skip_some_packets (iobuf_t inp, unsigned int n); #endif /* Parse a signature packet and store it in *SIG. The signature packet is read from INP. The OpenPGP header (the tag and the packet's length) have already been read; the next byte read from INP should be the first byte of the packet's contents. The packet's type (as extract from the tag) must be passed as PKTTYPE and the packet's length must be passed as PKTLEN. This is used as the upper bound on the amount of data read from INP. If the packet is shorter than PKTLEN, the data at the end will be silently skipped. If an error occurs, an error code will be returned. -1 means the EOF was encountered. 0 means parsing was successful. */ int parse_signature( iobuf_t inp, int pkttype, unsigned long pktlen, PKT_signature *sig ); /* Given a signature packet, either: * * - test whether there are any subpackets with the critical bit set * that we don't understand, * * - list the subpackets, or, * * - find a subpacket with a specific type. * * The WANT_HASHED flag indicates that the hashed area shall be * considered. * * REQTYPE indicates the type of operation. * * If REQTYPE is SIGSUBPKT_TEST_CRITICAL, then this function checks * whether there are any subpackets that have the critical bit and * which GnuPG cannot handle. If GnuPG understands all subpackets * whose critical bit is set, then this function returns simply * returns SUBPKTS. If there is a subpacket whose critical bit is set * and which GnuPG does not understand, then this function returns * NULL and, if START is not NULL, sets *START to the 1-based index of * the subpacket that violates the constraint. * * If REQTYPE is SIGSUBPKT_LIST_HASHED or SIGSUBPKT_LIST_UNHASHED, the * packets are dumped. Note: if REQTYPE is SIGSUBPKT_LIST_HASHED, * this function does not check whether the hash is correct; this is * merely an indication of the section that the subpackets came from. * * If REQTYPE is anything else, then this function interprets the * values as a subpacket type and looks for the first subpacket with * that type. If such a packet is found, *CRITICAL (if not NULL) is * set if the critical bit was set, *RET_N is set to the offset of the * subpacket's content within the SUBPKTS buffer, *START is set to the * 1-based index of the subpacket within the buffer, and returns * &SUBPKTS[*RET_N]. * * *START is the number of initial subpackets to not consider. Thus, * if *START is 2, then the first 2 subpackets are ignored. */ const byte *enum_sig_subpkt (PKT_signature *sig, int want_hashed, sigsubpkttype_t reqtype, size_t *ret_n, int *start, int *critical ); /* Shorthand for: * * enum_sig_subpkt (sig, want_hashed, reqtype, ret_n, NULL, NULL); */ const byte *parse_sig_subpkt (PKT_signature *sig, int want_hashed, sigsubpkttype_t reqtype, size_t *ret_n ); /* This calls parse_sig_subpkt first on the hashed signature area in * SIG and then, if that returns NULL, calls parse_sig_subpkt on the * unhashed subpacket area in SIG. */ const byte *parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype); /* Returns whether the N byte large buffer BUFFER is sufficient to hold a subpacket of type TYPE. Note: the buffer refers to the contents of the subpacket (not the header) and it must already be initialized: for some subpackets, it checks some internal constraints. Returns 0 if the size is acceptable. Returns -2 if the buffer is definitely too short. To check for an error, check whether the return value is less than 0. */ int parse_one_sig_subpkt( const byte *buffer, size_t n, int type ); /* Looks for revocation key subpackets (see RFC 4880 5.2.3.15) in the hashed area of the signature packet. Any that are found are added to SIG->REVKEY and SIG->NUMREVKEYS is updated appropriately. */ void parse_revkeys(PKT_signature *sig); /* Extract the attributes from the buffer at UID->ATTRIB_DATA and update UID->ATTRIBS and UID->NUMATTRIBS accordingly. */ int parse_attribute_subpkts(PKT_user_id *uid); /* Set the UID->NAME field according to the attributes. MAX_NAMELEN must be at least 71. */ void make_attribute_uidname(PKT_user_id *uid, size_t max_namelen); /* Allocate and initialize a new GPG control packet. DATA is the data to save in the packet. */ PACKET *create_gpg_control ( ctrlpkttype_t type, const byte *data, size_t datalen ); /*-- build-packet.c --*/ gpg_error_t build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf); int build_packet (iobuf_t out, PACKET *pkt); gpg_error_t build_packet_and_meta (iobuf_t out, PACKET *pkt); gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a, unsigned int *t_nwritten); gpg_error_t gpg_mpi_write_opaque_nohdr (iobuf_t out, gcry_mpi_t a); gpg_error_t gpg_mpi_write_opaque_32 (iobuf_t out, gcry_mpi_t a, unsigned int *r_nwritten); u32 calc_packet_length( PACKET *pkt ); void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ); void build_sig_subpkt_from_sig (PKT_signature *sig, PKT_public_key *pksk, unsigned int signhints); int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); void build_attribute_subpkt(PKT_user_id *uid,byte type, const void *buf,u32 buflen, const void *header,u32 headerlen); struct notation *string_to_notation(const char *string,int is_utf8); struct notation *blob_to_notation(const char *name, const char *data, size_t len); struct notation *sig_to_notation(PKT_signature *sig); struct notation *search_sig_notations (PKT_signature *sig, const char *name); void free_notation (struct notation *notation); /*-- free-packet.c --*/ void free_symkey_enc( PKT_symkey_enc *enc ); void free_pubkey_enc( PKT_pubkey_enc *enc ); void free_seckey_enc( PKT_signature *enc ); void release_public_key_parts( PKT_public_key *pk ); void free_public_key( PKT_public_key *key ); void free_attributes(PKT_user_id *uid); void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet (PACKET *pkt, parse_packet_ctx_t parsectx); prefitem_t *copy_prefs (const prefitem_t *prefs); PKT_public_key *copy_public_key_basics (PKT_public_key *d, PKT_public_key *s); PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); PKT_user_id *scopy_user_id (PKT_user_id *sd ); int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); int cmp_signatures( PKT_signature *a, PKT_signature *b ); int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); /*-- sig-check.c --*/ /* Check a signature. This is shorthand for check_signature2 with the unnamed arguments passed as NULL. */ int check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest); /* Check a signature. Looks up the public key from the key db. (If * R_PK is not NULL, it is stored at RET_PK.) DIGEST contains a * valid hash context that already includes the signed data. This * function adds the relevant meta-data to the hash before finalizing * it and verifying the signature. FOCRED_PK is usually NULL. */ gpg_error_t check_signature2 (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest, const void *extrahash, size_t extrahashlen, PKT_public_key *forced_pk, u32 *r_expiredate, int *r_expired, int *r_revoked, PKT_public_key **r_pk); /*-- pubkey-enc.c --*/ gpg_error_t get_session_key (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek); gpg_error_t get_override_session_key (DEK *dek, const char *string); /*-- compress.c --*/ int handle_compressed (ctrl_t ctrl, void *ctx, PKT_compressed *cd, int (*callback)(iobuf_t, void *), void *passthru ); /*-- decrypt-data.c --*/ int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek, int *compliance_error); /*-- plaintext.c --*/ gpg_error_t get_output_file (const byte *embedded_name, int embedded_namelen, iobuf_t data, char **fnamep, estream_t *fpp); int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, int nooutput, int clearsig ); int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2, const char *inname, int textmode ); /*-- sign.c --*/ int make_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int sigclass, u32 timestamp, u32 duration, int (*mksubpkt)(PKT_signature *, void *), void *opaque, const char *cache_nonce); gpg_error_t update_keysig_packet (ctrl_t ctrl, PKT_signature **ret_sig, PKT_signature *orig_sig, PKT_public_key *pk, PKT_user_id *uid, PKT_public_key *subpk, PKT_public_key *pksk, int (*mksubpkt)(PKT_signature *, void *), void *opaque ); /*-- keygen.c --*/ PKT_user_id *generate_user_id (kbnode_t keyblock, const char *uidstr); #endif /*G10_PACKET_H*/ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index c55bb1b71..8bd283b4b 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1,3956 +1,3962 @@ /* parse-packet.c - read packets * Copyright (C) 1998-2007, 2009-2010 Free Software Foundation, Inc. * Copyright (C) 2014, 2018 Werner Koch * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: GPL-3.0+ */ #include #include #include #include #include "gpg.h" #include "../common/util.h" #include "packet.h" #include "../common/iobuf.h" #include "filter.h" #include "photoid.h" #include "options.h" #include "main.h" #include "../common/i18n.h" #include "../common/host2net.h" #include "../common/mbox-util.h" static int mpi_print_mode; static int list_mode; static estream_t listfp; /* A linked list of known notation names. Note that the FLAG is used * to store the length of the name to speed up the check. */ static strlist_t known_notations_list; static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos, int *skip, IOBUF out, int do_skip #if DEBUG_PARSE_PACKET , const char *dbg_w, const char *dbg_f, int dbg_l #endif ); static int copy_packet (IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen, int partial); static void skip_packet (IOBUF inp, int pkttype, unsigned long pktlen, int partial); static void *read_rest (IOBUF inp, size_t pktlen); static int parse_marker (IOBUF inp, int pkttype, unsigned long pktlen); static int parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet); static int parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet); static int parse_onepass_sig (IOBUF inp, int pkttype, unsigned long pktlen, PKT_onepass_sig * ops); static int parse_key (IOBUF inp, int pkttype, unsigned long pktlen, byte * hdr, int hdrlen, PACKET * packet); static int parse_user_id (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet); static int parse_attribute (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet); static int parse_comment (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet); static gpg_error_t parse_ring_trust (parse_packet_ctx_t ctx, unsigned long pktlen); static int parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int new_ctb, int partial); static int parse_compressed (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int new_ctb); static int parse_encrypted (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int new_ctb, int partial); static gpg_error_t parse_encrypted_aead (IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet, int partial); static int parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int new_ctb); static int parse_gpg_control (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int partial); /* Read a 16-bit value in MSB order (big endian) from an iobuf. */ static unsigned short read_16 (IOBUF inp) { unsigned short a; a = (unsigned short)iobuf_get_noeof (inp) << 8; a |= iobuf_get_noeof (inp); return a; } /* Read a 32-bit value in MSB order (big endian) from an iobuf. */ static unsigned long read_32 (IOBUF inp) { unsigned long a; a = (unsigned long)iobuf_get_noeof (inp) << 24; a |= iobuf_get_noeof (inp) << 16; a |= iobuf_get_noeof (inp) << 8; a |= iobuf_get_noeof (inp); return a; } /* Read an external representation of an MPI and return the MPI. The external format is a 16-bit unsigned value stored in network byte order giving the number of bits for the following integer. The integer is stored MSB first and is left padded with zero bits to align on a byte boundary. The caller must set *RET_NREAD to the maximum number of bytes to read from the pipeline INP. This function sets *RET_NREAD to be the number of bytes actually read from the pipeline. If SECURE is true, the integer is stored in secure memory (allocated using gcry_xmalloc_secure). */ static gcry_mpi_t mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure) { int c, c1, c2, i; unsigned int nmax = *ret_nread; unsigned int nbits, nbytes; size_t nread = 0; gcry_mpi_t a = NULL; byte *buf = NULL; byte *p; if (!nmax) goto overflow; if ((c = c1 = iobuf_get (inp)) == -1) goto leave; if (++nread == nmax) goto overflow; nbits = c << 8; if ((c = c2 = iobuf_get (inp)) == -1) goto leave; ++nread; nbits |= c; if (nbits > MAX_EXTERN_MPI_BITS) { log_error ("mpi too large (%u bits)\n", nbits); goto leave; } nbytes = (nbits + 7) / 8; buf = secure ? gcry_xmalloc_secure (nbytes + 2) : gcry_xmalloc (nbytes + 2); p = buf; p[0] = c1; p[1] = c2; for (i = 0; i < nbytes; i++) { if (nread == nmax) goto overflow; c = iobuf_get (inp); if (c == -1) goto leave; p[i + 2] = c; nread ++; } if (gcry_mpi_scan (&a, GCRYMPI_FMT_PGP, buf, nread, &nread)) a = NULL; *ret_nread = nread; gcry_free(buf); return a; overflow: log_error ("mpi larger than indicated length (%u bits)\n", 8*nmax); leave: *ret_nread = nread; gcry_free(buf); return a; } /* If NLENGTH is zero read an octet string of length NBYTES from INP * and return it at R_DATA. * * If NLENGTH is either 1, 2, or 4 and NLENGTH is zero read an * NLENGTH-octet count and use this count number octets from INP and * return it at R_DATA. * * On error return an error code and store NULL at R_DATA. PKTLEN * shall give the current length of the packet and is updated with * each read. If SECURE is true, the integer is stored in secure * memory (allocated using gcry_xmalloc_secure). */ static gpg_error_t read_octet_string (iobuf_t inp, unsigned long *pktlen, unsigned int nlength, unsigned int nbytes, int secure, gcry_mpi_t *r_data) { gpg_error_t err; int c, i; byte *buf = NULL; byte *p; *r_data = NULL; if ((nbytes && nlength) || (!nbytes && !(nlength == 1 || nlength == 2 || nlength == 4))) { err = gpg_error (GPG_ERR_INV_ARG); goto leave; } if (nlength) { for (i = 0; i < nlength; i++) { if (!*pktlen) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } c = iobuf_readbyte (inp); if (c < 0) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } --*pktlen; nbytes <<= 8; nbytes |= c; } if (!nbytes) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } } if (nbytes*8 > (nbytes==4? MAX_EXTERN_KEYPARM_BITS:MAX_EXTERN_MPI_BITS) || (nbytes*8 < nbytes)) { log_error ("octet string too large (%u octets)\n", nbytes); err = gpg_error (GPG_ERR_TOO_LARGE); goto leave; } if (nbytes > *pktlen) { log_error ("octet string larger than packet (%u octets)\n", nbytes); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } buf = secure ? gcry_malloc_secure (nbytes) : gcry_malloc (nbytes); if (!buf) { err = gpg_error_from_syserror (); goto leave; } p = buf; for (i = 0; i < nbytes; i++) { c = iobuf_get (inp); if (c == -1) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } p[i] = c; --*pktlen; } *r_data = gcry_mpi_set_opaque (NULL, buf, nbytes*8); gcry_mpi_set_flag (*r_data, GCRYMPI_FLAG_USER2); return 0; leave: gcry_free (buf); return err; } /* Read an external representation of an SOS and return the opaque MPI with GCRYMPI_FLAG_USER2. The external format is a 16-bit unsigned value stored in network byte order giving information for the following octets. The caller must set *RET_NREAD to the maximum number of bytes to read from the pipeline INP. This function sets *RET_NREAD to be the number of bytes actually read from the pipeline. If SECURE is true, the integer is stored in secure memory (allocated using gcry_xmalloc_secure). */ static gcry_mpi_t sos_read (iobuf_t inp, unsigned int *ret_nread, int secure) { int c, c1, c2, i; unsigned int nmax = *ret_nread; unsigned int nbits, nbytes; size_t nread = 0; gcry_mpi_t a = NULL; byte *buf = NULL; byte *p; if (!nmax) goto overflow; if ((c = c1 = iobuf_get (inp)) == -1) goto leave; if (++nread == nmax) goto overflow; nbits = c << 8; if ((c = c2 = iobuf_get (inp)) == -1) goto leave; ++nread; nbits |= c; if (nbits > MAX_EXTERN_MPI_BITS) { log_error ("mpi too large (%u bits)\n", nbits); goto leave; } nbytes = (nbits + 7) / 8; buf = secure ? gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes); p = buf; for (i = 0; i < nbytes; i++) { if (nread == nmax) goto overflow; c = iobuf_get (inp); if (c == -1) goto leave; p[i] = c; nread ++; } a = gcry_mpi_set_opaque (NULL, buf, nbits); gcry_mpi_set_flag (a, GCRYMPI_FLAG_USER2); *ret_nread = nread; return a; overflow: log_error ("mpi larger than indicated length (%u bits)\n", 8*nmax); leave: *ret_nread = nread; gcry_free(buf); return a; } /* Register STRING as a known critical notation name. */ void register_known_notation (const char *string) { strlist_t sl; if (!known_notations_list) { sl = add_to_strlist (&known_notations_list, "preferred-email-encoding@pgp.com"); sl->flags = 32; /* Length of the string. */ } if (!string) return; /* Only initialized the default known notations. */ /* In --set-notation we use an exclamation mark to indicate a * critical notation. As a convenience skip this here. */ if (*string == '!') string++; if (!*string || strlist_find (known_notations_list, string)) return; /* Empty string or already registered. */ sl = add_to_strlist (&known_notations_list, string); sl->flags = strlen (string); } int set_packet_list_mode (int mode) { int old = list_mode; list_mode = mode; /* We use stdout only if invoked by the --list-packets command but switch to stderr in all other cases. This breaks the previous behaviour but that seems to be more of a bug than intentional. I don't believe that any application makes use of this long standing annoying way of printing to stdout except when doing a --list-packets. If this assumption fails, it will be easy to add an option for the listing stream. Note that we initialize it only once; mainly because there is code which switches opt.list_mode back to 1 and we want to have all output to the same stream. The MPI_PRINT_MODE will be enabled if the corresponding debug flag is set or if we are in --list-packets and --verbose is given. Using stderr is not actually very clean because it bypasses the logging code but it is a special thing anyway. I am not sure whether using log_stream() would be better. Perhaps we should enable the list mode only with a special option. */ if (!listfp) { if (opt.list_packets) { listfp = es_stdout; if (opt.verbose) mpi_print_mode = 1; } else listfp = es_stderr; if (DBG_MPI) mpi_print_mode = 1; } return old; } /* If OPT.VERBOSE is set, print a warning that the algorithm ALGO is not suitable for signing and encryption. */ static void unknown_pubkey_warning (int algo) { static byte unknown_pubkey_algos[256]; /* First check whether the algorithm is usable but not suitable for encryption/signing. */ if (pubkey_get_npkey (algo)) { if (opt.verbose && !glo_ctrl.silence_parse_warnings) { if (!pubkey_get_nsig (algo)) log_info ("public key algorithm %s not suitable for %s\n", openpgp_pk_algo_name (algo), "signing"); if (!pubkey_get_nenc (algo)) log_info ("public key algorithm %s not suitable for %s\n", openpgp_pk_algo_name (algo), "encryption"); } } else { algo &= 0xff; if (!unknown_pubkey_algos[algo]) { if (opt.verbose && !glo_ctrl.silence_parse_warnings) log_info (_("can't handle public key algorithm %d\n"), algo); unknown_pubkey_algos[algo] = 1; } } } #if DEBUG_PARSE_PACKET int dbg_parse_packet (parse_packet_ctx_t ctx, PACKET *pkt, const char *dbg_f, int dbg_l) { int skip, rc; do { rc = parse (ctx, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l); } while (skip && ! rc); return rc; } #else /*!DEBUG_PARSE_PACKET*/ int parse_packet (parse_packet_ctx_t ctx, PACKET *pkt) { int skip, rc; do { rc = parse (ctx, pkt, 0, NULL, &skip, NULL, 0); } while (skip && ! rc); return rc; } #endif /*!DEBUG_PARSE_PACKET*/ /* * Like parse packet, but only return secret or public (sub)key * packets. */ #if DEBUG_PARSE_PACKET int dbg_search_packet (parse_packet_ctx_t ctx, PACKET *pkt, off_t * retpos, int with_uid, const char *dbg_f, int dbg_l) { int skip, rc; do { rc = parse (ctx, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l); } while (skip && ! rc); return rc; } #else /*!DEBUG_PARSE_PACKET*/ int search_packet (parse_packet_ctx_t ctx, PACKET *pkt, off_t * retpos, int with_uid) { int skip, rc; do { rc = parse (ctx, pkt, with_uid ? 2 : 1, retpos, &skip, NULL, 0); } while (skip && ! rc); return rc; } #endif /*!DEBUG_PARSE_PACKET*/ /* * Copy all packets from INP to OUT, thereby removing unused spaces. */ #if DEBUG_PARSE_PACKET int dbg_copy_all_packets (iobuf_t inp, iobuf_t out, const char *dbg_f, int dbg_l) { PACKET pkt; struct parse_packet_ctx_s parsectx; int skip, rc = 0; if (! out) log_bug ("copy_all_packets: OUT may not be NULL.\n"); init_parse_packet (&parsectx, inp); do { init_packet (&pkt); } while (! (rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l))); deinit_parse_packet (&parsectx); return rc; } #else /*!DEBUG_PARSE_PACKET*/ int copy_all_packets (iobuf_t inp, iobuf_t out) { PACKET pkt; struct parse_packet_ctx_s parsectx; int skip, rc = 0; if (! out) log_bug ("copy_all_packets: OUT may not be NULL.\n"); init_parse_packet (&parsectx, inp); do { init_packet (&pkt); } while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0))); deinit_parse_packet (&parsectx); return rc; } #endif /*!DEBUG_PARSE_PACKET*/ /* * Copy some packets from INP to OUT, thereby removing unused spaces. * Stop at offset STOPoff (i.e. don't copy packets at this or later * offsets) */ #if DEBUG_PARSE_PACKET int dbg_copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff, const char *dbg_f, int dbg_l) { int rc = 0; PACKET pkt; int skip; struct parse_packet_ctx_s parsectx; init_parse_packet (&parsectx, inp); do { if (iobuf_tell (inp) >= stopoff) { deinit_parse_packet (&parsectx); return 0; } init_packet (&pkt); } while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0, "some", dbg_f, dbg_l))); deinit_parse_packet (&parsectx); return rc; } #else /*!DEBUG_PARSE_PACKET*/ int copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff) { int rc = 0; PACKET pkt; struct parse_packet_ctx_s parsectx; int skip; init_parse_packet (&parsectx, inp); do { if (iobuf_tell (inp) >= stopoff) { deinit_parse_packet (&parsectx); return 0; } init_packet (&pkt); } while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0))); deinit_parse_packet (&parsectx); return rc; } #endif /*!DEBUG_PARSE_PACKET*/ /* * Skip over N packets */ #if DEBUG_PARSE_PACKET int dbg_skip_some_packets (iobuf_t inp, unsigned n, const char *dbg_f, int dbg_l) { int rc = 0; int skip; PACKET pkt; struct parse_packet_ctx_s parsectx; init_parse_packet (&parsectx, inp); for (; n && !rc; n--) { init_packet (&pkt); rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l); } deinit_parse_packet (&parsectx); return rc; } #else /*!DEBUG_PARSE_PACKET*/ int skip_some_packets (iobuf_t inp, unsigned int n) { int rc = 0; int skip; PACKET pkt; struct parse_packet_ctx_s parsectx; init_parse_packet (&parsectx, inp); for (; n && !rc; n--) { init_packet (&pkt); rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1); } deinit_parse_packet (&parsectx); return rc; } #endif /*!DEBUG_PARSE_PACKET*/ /* Parse a packet and save it in *PKT. If OUT is not NULL and the packet is valid (its type is not 0), then the header, the initial length field and the packet's contents are written to OUT. In this case, the packet is not saved in *PKT. ONLYKEYPKTS is a simple packet filter. If ONLYKEYPKTS is set to 1, then only public subkey packets, public key packets, private subkey packets and private key packets are parsed. The rest are skipped (i.e., the header and the contents are read from the pipeline and discarded). If ONLYKEYPKTS is set to 2, then in addition to the above 4 types of packets, user id packets are also accepted. DO_SKIP is a more coarse grained filter. Unless ONLYKEYPKTS is set to 2 and the packet is a user id packet, all packets are skipped. Finally, if a packet is invalid (it's type is 0), it is skipped. If a packet is skipped and SKIP is not NULL, then *SKIP is set to 1. Note: ONLYKEYPKTS and DO_SKIP are only respected if OUT is NULL, i.e., the packets are not simply being copied. If RETPOS is not NULL, then the position of CTX->INP (as returned by iobuf_tell) is saved there before any data is read from CTX->INP. */ static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos, int *skip, IOBUF out, int do_skip #if DEBUG_PARSE_PACKET , const char *dbg_w, const char *dbg_f, int dbg_l #endif ) { int rc = 0; iobuf_t inp; int c, ctb, pkttype, lenbytes; unsigned long pktlen; byte hdr[8]; int hdrlen; int new_ctb = 0, partial = 0; int with_uid = (onlykeypkts == 2); off_t pos; *skip = 0; inp = ctx->inp; again: log_assert (!pkt->pkt.generic); if (retpos || list_mode) { pos = iobuf_tell (inp); if (retpos) *retpos = pos; } else pos = 0; /* (silence compiler warning) */ /* The first byte of a packet is the so-called tag. The highest bit must be set. */ if ((ctb = iobuf_get (inp)) == -1) { rc = -1; goto leave; } hdrlen = 0; hdr[hdrlen++] = ctb; if (!(ctb & 0x80)) { log_error ("%s: invalid packet (ctb=%02x)\n", iobuf_where (inp), ctb); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Immediately following the header is the length. There are two formats: the old format and the new format. If bit 6 (where the least significant bit is bit 0) is set in the tag, then we are dealing with a new format packet. Otherwise, it is an old format packet. */ pktlen = 0; new_ctb = !!(ctb & 0x40); if (new_ctb) { /* Get the packet's type. This is encoded in the 6 least significant bits of the tag. */ pkttype = ctb & 0x3f; /* Extract the packet's length. New format packets have 4 ways to encode the packet length. The value of the first byte determines the encoding and partially determines the length. See section 4.2.2 of RFC 4880 for details. */ if ((c = iobuf_get (inp)) == -1) { log_error ("%s: 1st length byte missing\n", iobuf_where (inp)); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } hdr[hdrlen++] = c; if (c < 192) pktlen = c; else if (c < 224) { pktlen = (c - 192) * 256; if ((c = iobuf_get (inp)) == -1) { log_error ("%s: 2nd length byte missing\n", iobuf_where (inp)); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } hdr[hdrlen++] = c; pktlen += c + 192; } else if (c == 255) { int i; char value[4]; for (i = 0; i < 4; i ++) { if ((c = iobuf_get (inp)) == -1) { log_error ("%s: 4 byte length invalid\n", iobuf_where (inp)); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } value[i] = hdr[hdrlen++] = c; } pktlen = buf32_to_ulong (value); } else /* Partial body length. */ { switch (pkttype) { case PKT_PLAINTEXT: case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: case PKT_COMPRESSED: iobuf_set_partial_body_length_mode (inp, c & 0xff); pktlen = 0; /* To indicate partial length. */ partial = 1; break; default: log_error ("%s: partial length invalid for" " packet type %d\n", iobuf_where (inp), pkttype); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } } } else /* This is an old format packet. */ { /* Extract the packet's type. This is encoded in bits 2-5. */ pkttype = (ctb >> 2) & 0xf; /* The type of length encoding is encoded in bits 0-1 of the tag. */ lenbytes = ((ctb & 3) == 3) ? 0 : (1 << (ctb & 3)); if (!lenbytes) { pktlen = 0; /* Don't know the value. */ /* This isn't really partial, but we can treat it the same in a "read until the end" sort of way. */ partial = 1; if (pkttype != PKT_ENCRYPTED && pkttype != PKT_PLAINTEXT && pkttype != PKT_COMPRESSED) { log_error ("%s: indeterminate length for invalid" " packet type %d\n", iobuf_where (inp), pkttype); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } } else { for (; lenbytes; lenbytes--) { pktlen <<= 8; c = iobuf_get (inp); if (c == -1) { log_error ("%s: length invalid\n", iobuf_where (inp)); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } pktlen |= hdr[hdrlen++] = c; } } } /* Sometimes the decompressing layer enters an error state in which it simply outputs 0xff for every byte read. If we have a stream of 0xff bytes, then it will be detected as a new format packet with type 63 and a 4-byte encoded length that is 4G-1. Since packets with type 63 are private and we use them as a control packet, which won't be 4 GB, we reject such packets as invalid. */ if (pkttype == 63 && pktlen == 0xFFFFFFFF) { /* With some probability this is caused by a problem in the * the uncompressing layer - in some error cases it just loops * and spits out 0xff bytes. */ log_error ("%s: garbled packet detected\n", iobuf_where (inp)); g10_exit (2); } if (out && pkttype) { /* This type of copying won't work if the packet uses a partial body length. (In other words, this only works if HDR is actually the length.) Currently, no callers require this functionality so we just log this as an error. */ if (partial) { log_error ("parse: Can't copy partial packet. Aborting.\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } rc = iobuf_write (out, hdr, hdrlen); if (!rc) rc = copy_packet (inp, out, pkttype, pktlen, partial); goto leave; } if (with_uid && pkttype == PKT_USER_ID) /* If ONLYKEYPKTS is set to 2, then we never skip user id packets, even if DO_SKIP is set. */ ; else if (do_skip /* type==0 is not allowed. This is an invalid packet. */ || !pkttype /* When ONLYKEYPKTS is set, we don't skip keys. */ || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY && pkttype != PKT_PUBLIC_KEY && pkttype != PKT_SECRET_SUBKEY && pkttype != PKT_SECRET_KEY)) { iobuf_skip_rest (inp, pktlen, partial); *skip = 1; rc = 0; goto leave; } if (DBG_PACKET) { #if DEBUG_PARSE_PACKET log_debug ("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n", iobuf_id (inp), pkttype, pktlen, new_ctb ? " (new_ctb)" : "", dbg_w, dbg_f, dbg_l); #else log_debug ("parse_packet(iob=%d): type=%d length=%lu%s\n", iobuf_id (inp), pkttype, pktlen, new_ctb ? " (new_ctb)" : ""); #endif } if (list_mode) es_fprintf (listfp, "# off=%lu ctb=%02x tag=%d hlen=%d plen=%lu%s%s\n", (unsigned long)pos, ctb, pkttype, hdrlen, pktlen, partial? (new_ctb ? " partial" : " indeterminate") :"", new_ctb? " new-ctb":""); /* Count it. */ ctx->n_parsed_packets++; pkt->pkttype = pkttype; rc = GPG_ERR_UNKNOWN_PACKET; /* default error */ switch (pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: case PKT_SECRET_KEY: case PKT_SECRET_SUBKEY: pkt->pkt.public_key = xmalloc_clear (sizeof *pkt->pkt.public_key); rc = parse_key (inp, pkttype, pktlen, hdr, hdrlen, pkt); break; case PKT_SYMKEY_ENC: rc = parse_symkeyenc (inp, pkttype, pktlen, pkt); break; case PKT_PUBKEY_ENC: rc = parse_pubkeyenc (inp, pkttype, pktlen, pkt); break; case PKT_SIGNATURE: pkt->pkt.signature = xmalloc_clear (sizeof *pkt->pkt.signature); rc = parse_signature (inp, pkttype, pktlen, pkt->pkt.signature); break; case PKT_ONEPASS_SIG: pkt->pkt.onepass_sig = xmalloc_clear (sizeof *pkt->pkt.onepass_sig); rc = parse_onepass_sig (inp, pkttype, pktlen, pkt->pkt.onepass_sig); break; case PKT_USER_ID: rc = parse_user_id (inp, pkttype, pktlen, pkt); break; case PKT_ATTRIBUTE: pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */ rc = parse_attribute (inp, pkttype, pktlen, pkt); break; case PKT_OLD_COMMENT: case PKT_COMMENT: rc = parse_comment (inp, pkttype, pktlen, pkt); break; case PKT_RING_TRUST: { rc = parse_ring_trust (ctx, pktlen); if (!rc) goto again; /* Directly read the next packet. */ } break; case PKT_PLAINTEXT: rc = parse_plaintext (inp, pkttype, pktlen, pkt, new_ctb, partial); break; case PKT_COMPRESSED: rc = parse_compressed (inp, pkttype, pktlen, pkt, new_ctb); break; case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: rc = parse_encrypted (inp, pkttype, pktlen, pkt, new_ctb, partial); break; case PKT_MDC: rc = parse_mdc (inp, pkttype, pktlen, pkt, new_ctb); break; case PKT_ENCRYPTED_AEAD: rc = parse_encrypted_aead (inp, pkttype, pktlen, pkt, partial); break; case PKT_GPG_CONTROL: rc = parse_gpg_control (inp, pkttype, pktlen, pkt, partial); break; case PKT_MARKER: rc = parse_marker (inp, pkttype, pktlen); break; default: /* Unknown packet. Skip it. */ skip_packet (inp, pkttype, pktlen, partial); break; } /* Store a shallow copy of certain packets in the context. */ free_packet (NULL, ctx); if (!rc && (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY || pkttype == PKT_USER_ID || pkttype == PKT_ATTRIBUTE || pkttype == PKT_SIGNATURE)) { ctx->last_pkt = *pkt; } leave: /* FIXME: We leak in case of an error (see the xmalloc's above). */ if (!rc && iobuf_error (inp)) rc = GPG_ERR_INV_KEYRING; /* FIXME: We use only the error code for now to avoid problems with callers which have not been checked to always use gpg_err_code() when comparing error codes. */ return rc == -1? -1 : gpg_err_code (rc); } static void dump_hex_line (int c, int *i) { if (*i && !(*i % 8)) { if (*i && !(*i % 24)) es_fprintf (listfp, "\n%4d:", *i); else es_putc (' ', listfp); } if (c == -1) es_fprintf (listfp, " EOF"); else es_fprintf (listfp, " %02x", c); ++*i; } /* Copy the contents of a packet from the pipeline IN to the pipeline OUT. The header and length have already been read from INP and the decoded values are given as PKGTYPE and PKTLEN. If the packet is a partial body length packet (RFC 4880, Section 4.2.2.4), then iobuf_set_partial_block_modeiobuf_set_partial_block_mode should already have been called on INP and PARTIAL should be set. If PARTIAL is set or PKTLEN is 0 and PKTTYPE is PKT_COMPRESSED, copy until the first EOF is encountered on INP. Returns 0 on success and an error code if an error occurs. */ static int copy_packet (IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen, int partial) { int rc; int n; char buf[100]; if (partial) { while ((n = iobuf_read (inp, buf, sizeof (buf))) != -1) if ((rc = iobuf_write (out, buf, n))) return rc; /* write error */ } else if (!pktlen && pkttype == PKT_COMPRESSED) { log_debug ("copy_packet: compressed!\n"); /* compressed packet, copy till EOF */ while ((n = iobuf_read (inp, buf, sizeof (buf))) != -1) if ((rc = iobuf_write (out, buf, n))) return rc; /* write error */ } else { for (; pktlen; pktlen -= n) { n = pktlen > sizeof (buf) ? sizeof (buf) : pktlen; n = iobuf_read (inp, buf, n); if (n == -1) return gpg_error (GPG_ERR_EOF); if ((rc = iobuf_write (out, buf, n))) return rc; /* write error */ } } return 0; } /* Skip an unknown packet. PKTTYPE is the packet's type, PKTLEN is the length of the packet's content and PARTIAL is whether partial body length encoding in used (in this case PKTLEN is ignored). */ static void skip_packet (IOBUF inp, int pkttype, unsigned long pktlen, int partial) { if (list_mode) { es_fprintf (listfp, ":unknown packet: type %2d, length %lu\n", pkttype, pktlen); if (pkttype) { int c, i = 0; es_fputs ("dump:", listfp); if (partial) { while ((c = iobuf_get (inp)) != -1) dump_hex_line (c, &i); } else { for (; pktlen; pktlen--) { dump_hex_line ((c = iobuf_get (inp)), &i); if (c == -1) break; } } es_putc ('\n', listfp); return; } } iobuf_skip_rest (inp, pktlen, partial); } /* Read PKTLEN bytes from INP and return them in a newly allocated * buffer. In case of an error (including reading fewer than PKTLEN * bytes from INP before EOF is returned), NULL is returned and an * error message is logged. */ static void * read_rest (IOBUF inp, size_t pktlen) { int c; byte *buf, *p; buf = xtrymalloc (pktlen); if (!buf) { gpg_error_t err = gpg_error_from_syserror (); log_error ("error reading rest of packet: %s\n", gpg_strerror (err)); return NULL; } for (p = buf; pktlen; pktlen--) { c = iobuf_get (inp); if (c == -1) { log_error ("premature eof while reading rest of packet\n"); xfree (buf); return NULL; } *p++ = c; } return buf; } /* Read a special size+body from INP. On success store an opaque MPI * with it at R_DATA. The caller shall store the remaining size of * the packet at PKTLEN. On error return an error code and store NULL * at R_DATA. Even in the error case store the number of read bytes * at PKTLEN is updated. */ static gpg_error_t read_sized_octet_string (iobuf_t inp, unsigned long *pktlen, gcry_mpi_t *r_data) { char buffer[256]; char *tmpbuf; int i, c, nbytes; *r_data = NULL; if (!*pktlen) return gpg_error (GPG_ERR_INV_PACKET); c = iobuf_readbyte (inp); if (c < 0) return gpg_error (GPG_ERR_INV_PACKET); --*pktlen; nbytes = c; if (nbytes < 2 || nbytes > 254) return gpg_error (GPG_ERR_INV_PACKET); if (nbytes > *pktlen) return gpg_error (GPG_ERR_INV_PACKET); buffer[0] = nbytes; for (i = 0; i < nbytes; i++) { c = iobuf_get (inp); if (c < 0) return gpg_error (GPG_ERR_INV_PACKET); --*pktlen; buffer[1+i] = c; } tmpbuf = xtrymalloc (1 + nbytes); if (!tmpbuf) return gpg_error_from_syserror (); memcpy (tmpbuf, buffer, 1 + nbytes); *r_data = gcry_mpi_set_opaque (NULL, tmpbuf, 8 * (1 + nbytes)); if (!*r_data) { xfree (tmpbuf); return gpg_error_from_syserror (); } return 0; } /* Parse a marker packet. */ static int parse_marker (IOBUF inp, int pkttype, unsigned long pktlen) { (void) pkttype; if (pktlen != 3) goto fail; if (iobuf_get (inp) != 'P') { pktlen--; goto fail; } if (iobuf_get (inp) != 'G') { pktlen--; goto fail; } if (iobuf_get (inp) != 'P') { pktlen--; goto fail; } if (list_mode) es_fputs (":marker packet: PGP\n", listfp); return 0; fail: log_error ("invalid marker packet\n"); if (list_mode) es_fputs (":marker packet: [invalid]\n", listfp); iobuf_skip_rest (inp, pktlen, 0); return GPG_ERR_INV_PACKET; } static int parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet) { PKT_symkey_enc *k; int rc = 0; int i, version, s2kmode, cipher_algo, aead_algo, hash_algo, seskeylen, minlen; if (pktlen < 4) goto too_short; version = iobuf_get_noeof (inp); pktlen--; if (version == 4) ; else if (version == 5) ; else { log_error ("packet(%d) with unknown version %d\n", pkttype, version); if (list_mode) es_fprintf (listfp, ":symkey enc packet: [unknown version]\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if (pktlen > 200) { /* (we encode the seskeylen in a byte) */ log_error ("packet(%d) too large\n", pkttype); if (list_mode) es_fprintf (listfp, ":symkey enc packet: [too large]\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } cipher_algo = iobuf_get_noeof (inp); pktlen--; if (version == 5) { aead_algo = iobuf_get_noeof (inp); pktlen--; } else aead_algo = 0; if (pktlen < 2) goto too_short; s2kmode = iobuf_get_noeof (inp); pktlen--; hash_algo = iobuf_get_noeof (inp); pktlen--; switch (s2kmode) { case 0: /* Simple S2K. */ minlen = 0; break; case 1: /* Salted S2K. */ minlen = 8; break; case 3: /* Iterated+salted S2K. */ minlen = 9; break; default: log_error ("unknown S2K mode %d\n", s2kmode); if (list_mode) es_fprintf (listfp, ":symkey enc packet: [unknown S2K mode]\n"); goto leave; } if (minlen > pktlen) { log_error ("packet with S2K %d too short\n", s2kmode); if (list_mode) es_fprintf (listfp, ":symkey enc packet: [too short]\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } seskeylen = pktlen - minlen; k = packet->pkt.symkey_enc = xmalloc_clear (sizeof *packet->pkt.symkey_enc + seskeylen - 1); k->version = version; k->cipher_algo = cipher_algo; k->aead_algo = aead_algo; k->s2k.mode = s2kmode; k->s2k.hash_algo = hash_algo; if (s2kmode == 1 || s2kmode == 3) { for (i = 0; i < 8 && pktlen; i++, pktlen--) k->s2k.salt[i] = iobuf_get_noeof (inp); } if (s2kmode == 3) { k->s2k.count = iobuf_get_noeof (inp); pktlen--; } k->seskeylen = seskeylen; if (k->seskeylen) { for (i = 0; i < seskeylen && pktlen; i++, pktlen--) k->seskey[i] = iobuf_get_noeof (inp); /* What we're watching out for here is a session key decryptor with no salt. The RFC says that using salt for this is a MUST. */ if (s2kmode != 1 && s2kmode != 3) log_info (_("WARNING: potentially insecure symmetrically" " encrypted session key\n")); } log_assert (!pktlen); if (list_mode) { es_fprintf (listfp, ":symkey enc packet: version %d, cipher %d, aead %d," " s2k %d, hash %d", version, cipher_algo, aead_algo, s2kmode, hash_algo); if (seskeylen) { /* To compute the size of the session key we need to know * the size of the AEAD nonce which we may not know. Thus * we show only the size of the entire encrypted session * key. */ if (aead_algo) es_fprintf (listfp, ", encrypted seskey %d bytes", seskeylen); else es_fprintf (listfp, ", seskey %d bits", (seskeylen - 1) * 8); } es_fprintf (listfp, "\n"); if (s2kmode == 1 || s2kmode == 3) { es_fprintf (listfp, "\tsalt "); es_write_hexstring (listfp, k->s2k.salt, 8, 0, NULL); if (s2kmode == 3) es_fprintf (listfp, ", count %lu (%lu)", S2K_DECODE_COUNT ((ulong) k->s2k.count), (ulong) k->s2k.count); es_fprintf (listfp, "\n"); } } leave: iobuf_skip_rest (inp, pktlen, 0); return rc; too_short: log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fprintf (listfp, ":symkey enc packet: [too short]\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Parse a public key encrypted packet (Tag 1). */ static int parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet) { int rc = 0; int i, ndata; unsigned int n; PKT_pubkey_enc *k; k = packet->pkt.pubkey_enc = xmalloc_clear (sizeof *packet->pkt.pubkey_enc); if (pktlen < 12) { log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":pubkey enc packet: [too short]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } k->version = iobuf_get_noeof (inp); pktlen--; if (k->version != 2 && k->version != 3) { log_error ("packet(%d) with unknown version %d\n", pkttype, k->version); if (list_mode) es_fputs (":pubkey enc packet: [unknown version]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } k->keyid[0] = read_32 (inp); pktlen -= 4; k->keyid[1] = read_32 (inp); pktlen -= 4; k->pubkey_algo = iobuf_get_noeof (inp); pktlen--; k->throw_keyid = 0; /* Only used as flag for build_packet. */ if (list_mode) es_fprintf (listfp, ":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n", k->version, k->pubkey_algo, (ulong) k->keyid[0], (ulong) k->keyid[1]); ndata = pubkey_get_nenc (k->pubkey_algo); if (!ndata) { if (list_mode) es_fprintf (listfp, "\tunsupported algorithm %d\n", k->pubkey_algo); unknown_pubkey_warning (k->pubkey_algo); k->data[0] = NULL; /* No need to store the encrypted data. */ } else if (k->pubkey_algo == PUBKEY_ALGO_ECDH) { log_assert (ndata == 2); /* Get the ephemeral public key. */ n = pktlen; k->data[0] = sos_read (inp, &n, 0); pktlen -= n; if (!k->data[0]) { rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Get the wrapped symmetric key. */ rc = read_sized_octet_string (inp, &pktlen, k->data + 1); if (rc) goto leave; } else if (k->pubkey_algo == PUBKEY_ALGO_KYBER) { - log_assert (ndata == 4); + log_assert (ndata == 3); /* Get the ephemeral public key. */ n = pktlen; k->data[0] = sos_read (inp, &n, 0); pktlen -= n; if (!k->data[0]) { rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Get the Kyber ciphertext. */ rc = read_octet_string (inp, &pktlen, 4, 0, 0, k->data + 1); if (rc) goto leave; - /* Get the algorithm id. */ - rc = read_octet_string (inp, &pktlen, 0, 1, 0, k->data + 2); - if (rc) - goto leave; - /* Get the wrapped symmetric key. */ - rc = read_sized_octet_string (inp, &pktlen, k->data + 3); + /* Get the algorithm id for the session key. */ + if (!pktlen) + { + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + k->seskey_algo = iobuf_get_noeof (inp); + pktlen--; + /* Get the encrypted symmetric key. */ + rc = read_octet_string (inp, &pktlen, 1, 0, 0, k->data + 2); if (rc) goto leave; } else { for (i = 0; i < ndata; i++) { n = pktlen; k->data[i] = mpi_read (inp, &n, 0); pktlen -= n; if (!k->data[i]) rc = gpg_error (GPG_ERR_INV_PACKET); } if (rc) goto leave; } if (list_mode) { + if (k->seskey_algo) + es_fprintf (listfp, "\tsession key algo: %d\n", k->seskey_algo); for (i = 0; i < ndata; i++) { es_fprintf (listfp, "\tdata: "); mpi_print (listfp, k->data[i], mpi_print_mode); es_putc ('\n', listfp); } } leave: iobuf_skip_rest (inp, pktlen, 0); return rc; } /* Dump a subpacket to LISTFP. BUFFER contains the subpacket in * question and points to the type field in the subpacket header (not * the start of the header). TYPE is the subpacket's type with the * critical bit cleared. CRITICAL is the value of the CRITICAL bit. * BUFLEN is the length of the buffer and LENGTH is the length of the * subpacket according to the subpacket's header. DIGEST_ALGO is the * digest algo of the signature. */ static void dump_sig_subpkt (int hashed, int type, int critical, const byte * buffer, size_t buflen, size_t length, int digest_algo) { const char *p = NULL; int i; int nprinted; /* The CERT has warning out with explains how to use GNUPG to detect * the ARRs - we print our old message here when it is a faked ARR * and add an additional notice. */ if (type == SIGSUBPKT_ARR && !hashed) { es_fprintf (listfp, "\tsubpkt %d len %u (additional recipient request)\n" "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically " "encrypt to this key and thereby reveal the plaintext to " "the owner of this ARR key. Detailed info follows:\n", type, (unsigned) length); } buffer++; length--; nprinted = es_fprintf (listfp, "\t%s%ssubpkt %d len %u (", /*) */ critical ? "critical " : "", hashed ? "hashed " : "", type, (unsigned) length); if (nprinted < 1) nprinted = 1; /*(we use (nprinted-1) later.)*/ if (length > buflen) { es_fprintf (listfp, "too short: buffer is only %u)\n", (unsigned) buflen); return; } switch (type) { case SIGSUBPKT_SIG_CREATED: if (length >= 4) es_fprintf (listfp, "sig created %s", strtimestamp (buf32_to_u32 (buffer))); break; case SIGSUBPKT_SIG_EXPIRE: if (length >= 4) { if (buf32_to_u32 (buffer)) es_fprintf (listfp, "sig expires after %s", strtimevalue (buf32_to_u32 (buffer))); else es_fprintf (listfp, "sig does not expire"); } break; case SIGSUBPKT_EXPORTABLE: if (length) es_fprintf (listfp, "%sexportable", *buffer ? "" : "not "); break; case SIGSUBPKT_TRUST: if (length != 2) p = "[invalid trust subpacket]"; else es_fprintf (listfp, "trust signature of depth %d, value %d", buffer[0], buffer[1]); break; case SIGSUBPKT_REGEXP: if (!length) p = "[invalid regexp subpacket]"; else { es_fprintf (listfp, "regular expression: \""); es_write_sanitized (listfp, buffer, length, "\"", NULL); p = "\""; } break; case SIGSUBPKT_REVOCABLE: if (length) es_fprintf (listfp, "%srevocable", *buffer ? "" : "not "); break; case SIGSUBPKT_KEY_EXPIRE: if (length >= 4) { if (buf32_to_u32 (buffer)) es_fprintf (listfp, "key expires after %s", strtimevalue (buf32_to_u32 (buffer))); else es_fprintf (listfp, "key does not expire"); } break; case SIGSUBPKT_PREF_SYM: es_fputs ("pref-sym-algos:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %d", buffer[i]); break; case SIGSUBPKT_PREF_AEAD: es_fputs ("pref-aead-algos:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %d", buffer[i]); break; case SIGSUBPKT_REV_KEY: es_fputs ("revocation key: ", listfp); if (length < 22) p = "[too short]"; else { es_fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1]); for (i = 2; i < length; i++) es_fprintf (listfp, "%02X", buffer[i]); } break; case SIGSUBPKT_ISSUER: if (length >= 8) es_fprintf (listfp, "issuer key ID %08lX%08lX", (ulong) buf32_to_u32 (buffer), (ulong) buf32_to_u32 (buffer + 4)); break; case SIGSUBPKT_ISSUER_FPR: if (length >= 21) { char *tmp; es_fprintf (listfp, "issuer fpr v%d ", buffer[0]); tmp = bin2hex (buffer+1, length-1, NULL); if (tmp) { es_fputs (tmp, listfp); xfree (tmp); } } break; case SIGSUBPKT_NOTATION: { es_fputs ("notation: ", listfp); if (length < 8) p = "[too short]"; else { const byte *s = buffer; size_t n1, n2; n1 = (s[4] << 8) | s[5]; n2 = (s[6] << 8) | s[7]; s += 8; if (8 + n1 + n2 != length) p = "[error]"; else { es_write_sanitized (listfp, s, n1, ")", NULL); es_putc ('=', listfp); if (*buffer & 0x80) es_write_sanitized (listfp, s + n1, n2, ")", NULL); else p = "[not human readable]"; } } } break; case SIGSUBPKT_PREF_HASH: es_fputs ("pref-hash-algos:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %d", buffer[i]); break; case SIGSUBPKT_PREF_COMPR: es_fputs ("pref-zip-algos:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %d", buffer[i]); break; case SIGSUBPKT_KS_FLAGS: es_fputs ("keyserver preferences:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %02X", buffer[i]); break; case SIGSUBPKT_PREF_KS: es_fputs ("preferred keyserver: ", listfp); es_write_sanitized (listfp, buffer, length, ")", NULL); break; case SIGSUBPKT_PRIMARY_UID: p = "primary user ID"; break; case SIGSUBPKT_POLICY: es_fputs ("policy: ", listfp); es_write_sanitized (listfp, buffer, length, ")", NULL); break; case SIGSUBPKT_KEY_FLAGS: es_fputs ("key flags:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %02X", buffer[i]); break; case SIGSUBPKT_SIGNERS_UID: p = "signer's user ID"; break; case SIGSUBPKT_REVOC_REASON: if (length) { es_fprintf (listfp, "revocation reason 0x%02x (", *buffer); es_write_sanitized (listfp, buffer + 1, length - 1, ")", NULL); p = ")"; } break; case SIGSUBPKT_ARR: es_fputs ("Big Brother's key (ignored): ", listfp); if (length < 22) p = "[too short]"; else { es_fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1]); if (length > 2) es_write_hexstring (listfp, buffer+2, length-2, 0, NULL); } break; case SIGSUBPKT_FEATURES: es_fputs ("features:", listfp); for (i = 0; i < length; i++) es_fprintf (listfp, " %02x", buffer[i]); break; case SIGSUBPKT_SIGNATURE: es_fputs ("signature: ", listfp); if (length < 17) p = "[too short]"; else es_fprintf (listfp, "v%d, class 0x%02X, algo %d, digest algo %d", buffer[0], buffer[0] == 3 ? buffer[2] : buffer[1], buffer[0] == 3 ? buffer[15] : buffer[2], buffer[0] == 3 ? buffer[16] : buffer[3]); break; case SIGSUBPKT_ATTST_SIGS: { unsigned int hlen; es_fputs ("attst-sigs: ", listfp); hlen = gcry_md_get_algo_dlen (map_md_openpgp_to_gcry (digest_algo)); if (!hlen) p = "[unknown digest algo]"; else if ((length % hlen)) p = "[invalid length]"; else { es_fprintf (listfp, "%u", (unsigned int)length/hlen); while (length) { es_fprintf (listfp, "\n\t%*s", nprinted-1, ""); es_write_hexstring (listfp, buffer, hlen, 0, NULL); buffer += hlen; length -= hlen; } } } break; case SIGSUBPKT_KEY_BLOCK: es_fputs ("key-block: ", listfp); if (length && buffer[0]) p = "[unknown reserved octet]"; else if (length < 50) /* 50 is an arbitrary min. length. */ p = "[invalid subpacket]"; else { /* estream_t fp; */ /* fp = es_fopen ("a.key-block", "wb"); */ /* log_assert (fp); */ /* es_fwrite ( buffer+1, length-1, 1, fp); */ /* es_fclose (fp); */ es_fprintf (listfp, "[%u octets]", (unsigned int)length-1); } break; default: if (type >= 100 && type <= 110) p = "experimental / private subpacket"; else p = "?"; break; } es_fprintf (listfp, "%s)\n", p ? p : ""); } /* * Returns: >= 0 use this offset into buffer * -1 explicitly reject returning this type * -2 subpacket too short */ int parse_one_sig_subpkt (const byte * buffer, size_t n, int type) { switch (type) { case SIGSUBPKT_REV_KEY: if (n < 22) break; return 0; case SIGSUBPKT_SIG_CREATED: case SIGSUBPKT_SIG_EXPIRE: case SIGSUBPKT_KEY_EXPIRE: if (n < 4) break; return 0; case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_KS_FLAGS: case SIGSUBPKT_PREF_SYM: case SIGSUBPKT_PREF_AEAD: case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_POLICY: case SIGSUBPKT_PREF_KS: case SIGSUBPKT_FEATURES: case SIGSUBPKT_REGEXP: case SIGSUBPKT_ATTST_SIGS: return 0; case SIGSUBPKT_SIGNATURE: case SIGSUBPKT_EXPORTABLE: case SIGSUBPKT_REVOCABLE: case SIGSUBPKT_REVOC_REASON: if (!n) break; return 0; case SIGSUBPKT_ISSUER: /* issuer key ID */ if (n < 8) break; return 0; case SIGSUBPKT_ISSUER_FPR: /* issuer key fingerprint */ if (n < 21) break; return 0; case SIGSUBPKT_NOTATION: /* minimum length needed, and the subpacket must be well-formed where the name length and value length all fit inside the packet. */ if (n < 8 || 8 + ((buffer[4] << 8) | buffer[5]) + ((buffer[6] << 8) | buffer[7]) != n) break; return 0; case SIGSUBPKT_PRIMARY_UID: if (n != 1) break; return 0; case SIGSUBPKT_TRUST: if (n != 2) break; return 0; case SIGSUBPKT_KEY_BLOCK: if (n && buffer[0]) return -1; /* Unknown version - ignore. */ if (n < 50) break; /* Definitely too short to carry a key block. */ return 0; default: return 0; } return -2; } /* Return true if we understand the critical notation. */ static int can_handle_critical_notation (const byte *name, size_t len) { strlist_t sl; register_known_notation (NULL); /* Make sure it is initialized. */ for (sl = known_notations_list; sl; sl = sl->next) if (sl->flags == len && !memcmp (sl->d, name, len)) return 1; /* Known */ if (opt.verbose && !glo_ctrl.silence_parse_warnings) { log_info(_("Unknown critical signature notation: ") ); print_utf8_buffer (log_get_stream(), name, len); log_printf ("\n"); } return 0; /* Unknown. */ } static int can_handle_critical (const byte * buffer, size_t n, int type) { switch (type) { case SIGSUBPKT_NOTATION: if (n >= 8) { size_t notation_len = ((buffer[4] << 8) | buffer[5]); if (n - 8 >= notation_len) return can_handle_critical_notation (buffer + 8, notation_len); } return 0; case SIGSUBPKT_SIGNATURE: case SIGSUBPKT_SIG_CREATED: case SIGSUBPKT_SIG_EXPIRE: case SIGSUBPKT_KEY_EXPIRE: case SIGSUBPKT_EXPORTABLE: case SIGSUBPKT_REVOCABLE: case SIGSUBPKT_REV_KEY: case SIGSUBPKT_ISSUER: /* issuer key ID */ case SIGSUBPKT_ISSUER_FPR: /* issuer fingerprint */ case SIGSUBPKT_PREF_SYM: case SIGSUBPKT_PREF_AEAD: case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_FEATURES: case SIGSUBPKT_TRUST: case SIGSUBPKT_REGEXP: case SIGSUBPKT_ATTST_SIGS: /* Is it enough to show the policy or keyserver? */ case SIGSUBPKT_POLICY: case SIGSUBPKT_PREF_KS: case SIGSUBPKT_REVOC_REASON: /* At least we know about it. */ return 1; case SIGSUBPKT_KEY_BLOCK: if (n && !buffer[0]) return 1; else return 0; default: return 0; } } const byte * enum_sig_subpkt (PKT_signature *sig, int want_hashed, sigsubpkttype_t reqtype, size_t *ret_n, int *start, int *critical) { const byte *buffer; int buflen; int type; int critical_dummy; int offset; size_t n; const subpktarea_t *pktbuf = want_hashed? sig->hashed : sig->unhashed; int seq = 0; int reqseq = start ? *start : 0; if (!critical) critical = &critical_dummy; if (!pktbuf || reqseq == -1) { static char dummy[] = "x"; /* Return a value different from NULL to indicate that * there is no critical bit we do not understand. */ return reqtype == SIGSUBPKT_TEST_CRITICAL ? dummy : NULL; } buffer = pktbuf->data; buflen = pktbuf->len; while (buflen) { n = *buffer++; buflen--; if (n == 255) /* 4 byte length header. */ { if (buflen < 4) goto too_short; n = buf32_to_size_t (buffer); buffer += 4; buflen -= 4; } else if (n >= 192) /* 4 byte special encoded length header. */ { if (buflen < 2) goto too_short; n = ((n - 192) << 8) + *buffer + 192; buffer++; buflen--; } if (buflen < n) goto too_short; if (!buflen) goto no_type_byte; type = *buffer; if (type & 0x80) { type &= 0x7f; *critical = 1; } else *critical = 0; if (!(++seq > reqseq)) ; else if (reqtype == SIGSUBPKT_TEST_CRITICAL) { if (*critical) { if (n - 1 > buflen + 1) goto too_short; if (!can_handle_critical (buffer + 1, n - 1, type)) { if (opt.verbose && !glo_ctrl.silence_parse_warnings) log_info (_("subpacket of type %d has " "critical bit set\n"), type); if (start) *start = seq; return NULL; /* This is an error. */ } } } else if (reqtype < 0) /* List packets. */ dump_sig_subpkt (reqtype == SIGSUBPKT_LIST_HASHED, type, *critical, buffer, buflen, n, sig->digest_algo); else if (type == reqtype) /* Found. */ { buffer++; n--; if (n > buflen) goto too_short; if (ret_n) *ret_n = n; offset = parse_one_sig_subpkt (buffer, n, type); switch (offset) { case -2: log_error ("subpacket of type %d too short\n", type); return NULL; case -1: return NULL; default: break; } if (start) *start = seq; return buffer + offset; } buffer += n; buflen -= n; } if (reqtype == SIGSUBPKT_TEST_CRITICAL) /* Returning NULL means we found a subpacket with the critical bit set that we don't grok. We've iterated over all the subpackets and haven't found such a packet so we need to return a non-NULL value. */ return buffer; /* Critical bit we don't understand. */ if (start) *start = -1; return NULL; /* End of packets; not found. */ too_short: if (opt.debug && !glo_ctrl.silence_parse_warnings) { es_fflush (es_stdout); log_printhex (pktbuf->data, pktbuf->len > 16? 16 : pktbuf->len, "buffer shorter than subpacket (%zu/%d/%zu); dump:", pktbuf->len, buflen, n); } if (start) *start = -1; return NULL; no_type_byte: if (opt.verbose && !glo_ctrl.silence_parse_warnings) log_info ("type octet missing in subpacket\n"); if (start) *start = -1; return NULL; } const byte * parse_sig_subpkt (PKT_signature *sig, int want_hashed, sigsubpkttype_t reqtype, size_t *ret_n) { return enum_sig_subpkt (sig, want_hashed, reqtype, ret_n, NULL, NULL); } const byte * parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype) { const byte *p; p = parse_sig_subpkt (sig, 1, reqtype, NULL); if (!p) p = parse_sig_subpkt (sig, 0, reqtype, NULL); return p; } /* Find all revocation keys. Look in hashed area only. */ void parse_revkeys (PKT_signature * sig) { const byte *revkey; int seq = 0; size_t len; if (sig->sig_class != 0x1F) return; while ((revkey = enum_sig_subpkt (sig, 1, SIGSUBPKT_REV_KEY, &len, &seq, NULL))) { /* Consider only valid packets. They must have a length of * either 2+20 or 2+32 octets and bit 7 of the class octet must * be set. */ if ((len == 22 || len == 34) && (revkey[0] & 0x80)) { sig->revkey = xrealloc (sig->revkey, sizeof (struct revocation_key) * (sig->numrevkeys + 1)); sig->revkey[sig->numrevkeys].class = revkey[0]; sig->revkey[sig->numrevkeys].algid = revkey[1]; len -= 2; sig->revkey[sig->numrevkeys].fprlen = len; memcpy (sig->revkey[sig->numrevkeys].fpr, revkey+2, len); memset (sig->revkey[sig->numrevkeys].fpr+len, 0, sizeof (sig->revkey[sig->numrevkeys].fpr) - len); sig->numrevkeys++; } } } int parse_signature (IOBUF inp, int pkttype, unsigned long pktlen, PKT_signature * sig) { int md5_len = 0; unsigned n; int is_v4or5 = 0; int rc = 0; int i, ndata; if (pktlen < 16) { log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":signature packet: [too short]\n", listfp); goto leave; } sig->version = iobuf_get_noeof (inp); pktlen--; if (sig->version == 4 || sig->version == 5) is_v4or5 = 1; else if (sig->version != 2 && sig->version != 3) { log_error ("packet(%d) with unknown version %d\n", pkttype, sig->version); if (list_mode) es_fputs (":signature packet: [unknown version]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if (!is_v4or5) { if (pktlen == 0) goto underflow; md5_len = iobuf_get_noeof (inp); pktlen--; } if (pktlen == 0) goto underflow; sig->sig_class = iobuf_get_noeof (inp); pktlen--; if (!is_v4or5) { if (pktlen < 12) goto underflow; sig->timestamp = read_32 (inp); pktlen -= 4; sig->keyid[0] = read_32 (inp); pktlen -= 4; sig->keyid[1] = read_32 (inp); pktlen -= 4; } if (pktlen < 2) goto underflow; sig->pubkey_algo = iobuf_get_noeof (inp); pktlen--; sig->digest_algo = iobuf_get_noeof (inp); pktlen--; sig->flags.exportable = 1; sig->flags.revocable = 1; if (is_v4or5) /* Read subpackets. */ { if (pktlen < 2) goto underflow; n = read_16 (inp); pktlen -= 2; /* Length of hashed data. */ if (pktlen < n) goto underflow; if (n > 10000) { log_error ("signature packet: hashed data too long\n"); if (list_mode) es_fputs (":signature packet: [hashed data too long]\n", listfp); rc = GPG_ERR_INV_PACKET; goto leave; } if (n) { sig->hashed = xmalloc (sizeof (*sig->hashed) + n - 1); sig->hashed->size = n; sig->hashed->len = n; if (iobuf_read (inp, sig->hashed->data, n) != n) { log_error ("premature eof while reading " "hashed signature data\n"); if (list_mode) es_fputs (":signature packet: [premature eof]\n", listfp); rc = -1; goto leave; } pktlen -= n; } if (pktlen < 2) goto underflow; n = read_16 (inp); pktlen -= 2; /* Length of unhashed data. */ if (pktlen < n) goto underflow; if (n > 10000) { log_error ("signature packet: unhashed data too long\n"); if (list_mode) es_fputs (":signature packet: [unhashed data too long]\n", listfp); rc = GPG_ERR_INV_PACKET; goto leave; } if (n) { sig->unhashed = xmalloc (sizeof (*sig->unhashed) + n - 1); sig->unhashed->size = n; sig->unhashed->len = n; if (iobuf_read (inp, sig->unhashed->data, n) != n) { log_error ("premature eof while reading " "unhashed signature data\n"); if (list_mode) es_fputs (":signature packet: [premature eof]\n", listfp); rc = -1; goto leave; } pktlen -= n; } } if (pktlen < 2) goto underflow; sig->digest_start[0] = iobuf_get_noeof (inp); pktlen--; sig->digest_start[1] = iobuf_get_noeof (inp); pktlen--; if (is_v4or5 && sig->pubkey_algo) /* Extract required information. */ { const byte *p; size_t len; /* Set sig->flags.unknown_critical if there is a critical bit * set for packets which we do not understand. */ if (!parse_sig_subpkt (sig, 1, SIGSUBPKT_TEST_CRITICAL, NULL) || !parse_sig_subpkt (sig, 0, SIGSUBPKT_TEST_CRITICAL, NULL)) sig->flags.unknown_critical = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_SIG_CREATED, NULL); if (p) sig->timestamp = buf32_to_u32 (p); else if (!(sig->pubkey_algo >= 100 && sig->pubkey_algo <= 110) && opt.verbose > 1 && !glo_ctrl.silence_parse_warnings) log_info ("signature packet without timestamp\n"); /* Set the key id. We first try the issuer fingerprint and if * it is a v4 signature the fallback to the issuer. Note that * only the issuer packet is also searched in the unhashed area. */ p = parse_sig_subpkt (sig, 1, SIGSUBPKT_ISSUER_FPR, &len); if (p && len == 21 && p[0] == 4) { sig->keyid[0] = buf32_to_u32 (p + 1 + 12); sig->keyid[1] = buf32_to_u32 (p + 1 + 16); } else if (p && len == 33 && p[0] == 5) { sig->keyid[0] = buf32_to_u32 (p + 1 ); sig->keyid[1] = buf32_to_u32 (p + 1 + 4); } else if ((p = parse_sig_subpkt2 (sig, SIGSUBPKT_ISSUER))) { sig->keyid[0] = buf32_to_u32 (p); sig->keyid[1] = buf32_to_u32 (p + 4); } else if (!(sig->pubkey_algo >= 100 && sig->pubkey_algo <= 110) && opt.verbose > 1 && !glo_ctrl.silence_parse_warnings) log_info ("signature packet without keyid\n"); p = parse_sig_subpkt (sig, 1, SIGSUBPKT_SIG_EXPIRE, NULL); if (p && buf32_to_u32 (p)) sig->expiredate = sig->timestamp + buf32_to_u32 (p); if (sig->expiredate && sig->expiredate <= make_timestamp ()) sig->flags.expired = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_POLICY, NULL); if (p) sig->flags.policy_url = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_PREF_KS, NULL); if (p) sig->flags.pref_ks = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_SIGNERS_UID, &len); if (p && len) { char *mbox; sig->signers_uid = try_make_printable_string (p, len, 0); if (!sig->signers_uid) { rc = gpg_error_from_syserror (); goto leave; } mbox = mailbox_from_userid (sig->signers_uid, 0); if (mbox) { xfree (sig->signers_uid); sig->signers_uid = mbox; } } p = parse_sig_subpkt (sig, 1, SIGSUBPKT_KEY_BLOCK, NULL); if (p) sig->flags.key_block = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_NOTATION, NULL); if (p) sig->flags.notation = 1; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_REVOCABLE, NULL); if (p && *p == 0) sig->flags.revocable = 0; p = parse_sig_subpkt (sig, 1, SIGSUBPKT_TRUST, &len); if (p && len == 2) { sig->trust_depth = p[0]; sig->trust_value = p[1]; /* Only look for a regexp if there is also a trust subpacket. */ sig->trust_regexp = parse_sig_subpkt (sig, 1, SIGSUBPKT_REGEXP, &len); /* If the regular expression is of 0 length, there is no regular expression. */ if (len == 0) sig->trust_regexp = NULL; } /* We accept the exportable subpacket from either the hashed or unhashed areas as older versions of gpg put it in the unhashed area. In theory, anyway, we should never see this packet off of a local keyring. */ p = parse_sig_subpkt2 (sig, SIGSUBPKT_EXPORTABLE); if (p && *p == 0) sig->flags.exportable = 0; /* Find all revocation keys. */ if (sig->sig_class == 0x1F) parse_revkeys (sig); } if (list_mode) { es_fprintf (listfp, ":signature packet: algo %d, keyid %08lX%08lX\n" "\tversion %d, created %lu, md5len %d, sigclass 0x%02x\n" "\tdigest algo %d, begin of digest %02x %02x\n", sig->pubkey_algo, (ulong) sig->keyid[0], (ulong) sig->keyid[1], sig->version, (ulong) sig->timestamp, md5_len, sig->sig_class, sig->digest_algo, sig->digest_start[0], sig->digest_start[1]); if (is_v4or5) { parse_sig_subpkt (sig, 1, SIGSUBPKT_LIST_HASHED, NULL); parse_sig_subpkt (sig, 0, SIGSUBPKT_LIST_UNHASHED, NULL); } } ndata = pubkey_get_nsig (sig->pubkey_algo); if (!ndata) { if (list_mode) es_fprintf (listfp, "\tunknown algorithm %d\n", sig->pubkey_algo); unknown_pubkey_warning (sig->pubkey_algo); /* We store the plain material in data[0], so that we are able * to write it back with build_packet(). */ if (pktlen > (5 * MAX_EXTERN_MPI_BITS / 8)) { /* We include a limit to avoid too trivial DoS attacks by having gpg allocate too much memory. */ log_error ("signature packet: too much data\n"); rc = GPG_ERR_INV_PACKET; } else { void *tmpp; tmpp = read_rest (inp, pktlen); sig->data[0] = gcry_mpi_set_opaque (NULL, tmpp, tmpp? pktlen * 8 : 0); pktlen = 0; } } else { for (i = 0; i < ndata; i++) { n = pktlen; if (sig->pubkey_algo == PUBKEY_ALGO_ECDSA || sig->pubkey_algo == PUBKEY_ALGO_EDDSA) sig->data[i] = sos_read (inp, &n, 0); else sig->data[i] = mpi_read (inp, &n, 0); pktlen -= n; if (list_mode) { es_fprintf (listfp, "\tdata: "); mpi_print (listfp, sig->data[i], mpi_print_mode); es_putc ('\n', listfp); } if (!sig->data[i]) rc = GPG_ERR_INV_PACKET; } } leave: iobuf_skip_rest (inp, pktlen, 0); return rc; underflow: log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":signature packet: [too short]\n", listfp); iobuf_skip_rest (inp, pktlen, 0); return GPG_ERR_INV_PACKET; } static int parse_onepass_sig (IOBUF inp, int pkttype, unsigned long pktlen, PKT_onepass_sig * ops) { int version; int rc = 0; if (pktlen < 13) { log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":onepass_sig packet: [too short]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } version = iobuf_get_noeof (inp); pktlen--; if (version != 3) { log_error ("onepass_sig with unknown version %d\n", version); if (list_mode) es_fputs (":onepass_sig packet: [unknown version]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ops->sig_class = iobuf_get_noeof (inp); pktlen--; ops->digest_algo = iobuf_get_noeof (inp); pktlen--; ops->pubkey_algo = iobuf_get_noeof (inp); pktlen--; ops->keyid[0] = read_32 (inp); pktlen -= 4; ops->keyid[1] = read_32 (inp); pktlen -= 4; ops->last = iobuf_get_noeof (inp); pktlen--; if (list_mode) es_fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n" "\tversion %d, sigclass 0x%02x, digest %d, pubkey %d, " "last=%d\n", (ulong) ops->keyid[0], (ulong) ops->keyid[1], version, ops->sig_class, ops->digest_algo, ops->pubkey_algo, ops->last); leave: iobuf_skip_rest (inp, pktlen, 0); return rc; } static int parse_key (IOBUF inp, int pkttype, unsigned long pktlen, byte * hdr, int hdrlen, PACKET * pkt) { gpg_error_t err = 0; int i, version, algorithm; unsigned long timestamp, expiredate, max_expiredate; int npkey, nskey; u32 keyid[2]; PKT_public_key *pk; int is_v5; unsigned int pkbytes; /* For v5 keys: Number of bytes in the public * key material. For v4 keys: 0. */ (void) hdr; pk = pkt->pkt.public_key; /* PK has been cleared. */ version = iobuf_get_noeof (inp); pktlen--; if (pkttype == PKT_PUBLIC_SUBKEY && version == '#') { /* Early versions of G10 used the old PGP comments packets; * luckily all those comments are started by a hash. */ if (list_mode) { es_fprintf (listfp, ":rfc1991 comment packet: \""); for (; pktlen; pktlen--) { int c; c = iobuf_get (inp); if (c == -1) break; /* Ooops: shorter than indicated. */ if (c >= ' ' && c <= 'z') es_putc (c, listfp); else es_fprintf (listfp, "\\x%02x", c); } es_fprintf (listfp, "\"\n"); } iobuf_skip_rest (inp, pktlen, 0); return 0; } else if (version == 4) is_v5 = 0; else if (version == 5) is_v5 = 1; else if (version == 2 || version == 3) { /* Not anymore supported since 2.1. Use an older gpg version * (i.e. gpg 1.4) to parse v3 packets. */ if (opt.verbose > 1 && !glo_ctrl.silence_parse_warnings) log_info ("packet(%d) with obsolete version %d\n", pkttype, version); if (list_mode) es_fprintf (listfp, ":key packet: [obsolete version %d]\n", version); pk->version = version; err = gpg_error (GPG_ERR_LEGACY_KEY); goto leave; } else { log_error ("packet(%d) with unknown version %d\n", pkttype, version); if (list_mode) es_fputs (":key packet: [unknown version]\n", listfp); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if (pktlen < (is_v5? 15:11)) { log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":key packet: [too short]\n", listfp); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } else if (pktlen > MAX_KEY_PACKET_LENGTH) { log_error ("packet(%d) too large\n", pkttype); if (list_mode) es_fputs (":key packet: [too large]\n", listfp); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } timestamp = read_32 (inp); pktlen -= 4; expiredate = 0; /* have to get it from the selfsignature */ max_expiredate = 0; algorithm = iobuf_get_noeof (inp); pktlen--; if (is_v5) { pkbytes = read_32 (inp); pktlen -= 4; } else pkbytes = 0; if (list_mode) { es_fprintf (listfp, ":%s key packet:\n" "\tversion %d, algo %d, created %lu, expires %lu", pkttype == PKT_PUBLIC_KEY ? "public" : pkttype == PKT_SECRET_KEY ? "secret" : pkttype == PKT_PUBLIC_SUBKEY ? "public sub" : pkttype == PKT_SECRET_SUBKEY ? "secret sub" : "??", version, algorithm, timestamp, expiredate); if (is_v5) es_fprintf (listfp, ", pkbytes %u\n", pkbytes); else es_fprintf (listfp, "\n"); } pk->timestamp = timestamp; pk->expiredate = expiredate; pk->max_expiredate = max_expiredate; pk->hdrbytes = hdrlen; pk->version = version; pk->flags.primary = (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY); pk->pubkey_algo = algorithm; nskey = pubkey_get_nskey (algorithm); npkey = pubkey_get_npkey (algorithm); if (!npkey) { if (list_mode) es_fprintf (listfp, "\tunknown algorithm %d\n", algorithm); unknown_pubkey_warning (algorithm); } if (!npkey) { /* Unknown algorithm - put data into an opaque MPI. */ void *tmpp = read_rest (inp, pktlen); /* Current gcry_mpi_cmp does not handle a (NULL,n>0) nicely and * thus we avoid to create such an MPI. */ pk->pkey[0] = gcry_mpi_set_opaque (NULL, tmpp, tmpp? pktlen * 8 : 0); pktlen = 0; goto leave; } else { for (i = 0; i < npkey; i++) { if ( (algorithm == PUBKEY_ALGO_ECDSA && (i == 0)) || (algorithm == PUBKEY_ALGO_EDDSA && (i == 0)) || (algorithm == PUBKEY_ALGO_ECDH && (i == 0 || i == 2)) || (algorithm == PUBKEY_ALGO_KYBER && (i == 0))) { /* Read the OID (i==0) or the KDF params (i==2). */ err = read_sized_octet_string (inp, &pktlen, pk->pkey+i); } else if (algorithm == PUBKEY_ALGO_KYBER && i == 2) { /* Read the four-octet count prefixed Kyber public key. */ err = read_octet_string (inp, &pktlen, 4, 0, 0, pk->pkey+i); } else { /* Read MPI or SOS. */ unsigned int n = pktlen; if (algorithm == PUBKEY_ALGO_ECDSA || algorithm == PUBKEY_ALGO_EDDSA || algorithm == PUBKEY_ALGO_ECDH || algorithm == PUBKEY_ALGO_KYBER) pk->pkey[i] = sos_read (inp, &n, 0); else pk->pkey[i] = mpi_read (inp, &n, 0); pktlen -= n; if (!pk->pkey[i]) err = gpg_error (GPG_ERR_INV_PACKET); } if (err) goto leave; if (list_mode) { es_fprintf (listfp, "\tpkey[%d]: ", i); mpi_print (listfp, pk->pkey[i], mpi_print_mode); if ((algorithm == PUBKEY_ALGO_ECDSA || algorithm == PUBKEY_ALGO_EDDSA || algorithm == PUBKEY_ALGO_ECDH || algorithm == PUBKEY_ALGO_KYBER) && i==0) { char *curve = openpgp_oid_to_str (pk->pkey[0]); const char *name = openpgp_oid_to_curve (curve, 0); es_fprintf (listfp, " %s (%s)", name?name:"", curve); xfree (curve); } es_putc ('\n', listfp); } } } if (list_mode) keyid_from_pk (pk, keyid); if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY) { struct seckey_info *ski; byte temp[16]; size_t snlen = 0; unsigned int skbytes; if (pktlen < 1) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } pk->seckey_info = ski = xtrycalloc (1, sizeof *ski); if (!pk->seckey_info) { err = gpg_error_from_syserror (); goto leave; } ski->algo = iobuf_get_noeof (inp); pktlen--; if (is_v5) { unsigned int protcount = 0; /* Read the one octet count of the following key-protection * material. Only required in case of unknown values. */ if (!pktlen) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } protcount = iobuf_get_noeof (inp); pktlen--; if (list_mode) es_fprintf (listfp, "\tprotbytes: %u\n", protcount); } if (ski->algo) { ski->is_protected = 1; ski->s2k.count = 0; if (ski->algo == 253) { if (list_mode) es_fprintf (listfp, "\tS2K pseudo algo %d is not yet supported\n", ski->algo); err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); goto leave; } else if (ski->algo == 254 || ski->algo == 255) { if (pktlen < 3) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ski->sha1chk = (ski->algo == 254); ski->algo = iobuf_get_noeof (inp); pktlen--; /* Note that a ski->algo > 110 is illegal, but I'm not * erroring out here as otherwise there would be no way * to delete such a key. */ ski->s2k.mode = iobuf_get_noeof (inp); pktlen--; ski->s2k.hash_algo = iobuf_get_noeof (inp); pktlen--; /* Check for the special GNU extension. */ if (ski->s2k.mode == 101) { for (i = 0; i < 4 && pktlen; i++, pktlen--) temp[i] = iobuf_get_noeof (inp); if (i < 4 || memcmp (temp, "GNU", 3)) { if (list_mode) es_fprintf (listfp, "\tunknown S2K %d\n", ski->s2k.mode); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Here we know that it is a GNU extension. What * follows is the GNU protection mode: All values * have special meanings and they are mapped to MODE * with a base of 1000. */ ski->s2k.mode = 1000 + temp[3]; } /* Read the salt. */ if (ski->s2k.mode == 3 || ski->s2k.mode == 1) { for (i = 0; i < 8 && pktlen; i++, pktlen--) temp[i] = iobuf_get_noeof (inp); if (i < 8) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } memcpy (ski->s2k.salt, temp, 8); } /* Check the mode. */ switch (ski->s2k.mode) { case 0: if (list_mode) es_fprintf (listfp, "\tsimple S2K"); break; case 1: if (list_mode) es_fprintf (listfp, "\tsalted S2K"); break; case 3: if (list_mode) es_fprintf (listfp, "\titer+salt S2K"); break; case 1001: if (list_mode) es_fprintf (listfp, "\tgnu-dummy"); break; case 1002: if (list_mode) es_fprintf (listfp, "\tgnu-divert-to-card"); break; case 1003: if (list_mode) es_fprintf (listfp, "\tgnu-mode1003"); break; default: if (list_mode) es_fprintf (listfp, "\tunknown %sS2K %d\n", ski->s2k.mode < 1000 ? "" : "GNU ", ski->s2k.mode); err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Print some info. */ if (list_mode && ski->s2k.mode != 1003) { es_fprintf (listfp, ", algo: %d,%s hash: %d", ski->algo, ski->sha1chk ? " SHA1 protection," : " simple checksum,", ski->s2k.hash_algo); if (ski->s2k.mode == 1 || ski->s2k.mode == 3) { es_fprintf (listfp, ", salt: "); es_write_hexstring (listfp, ski->s2k.salt, 8, 0, NULL); } } if (list_mode) es_putc ('\n', listfp); /* Read remaining protection parameters. */ if (ski->s2k.mode == 3) { if (pktlen < 1) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ski->s2k.count = iobuf_get_noeof (inp); pktlen--; if (list_mode) es_fprintf (listfp, "\tprotect count: %lu (%lu)\n", (ulong)S2K_DECODE_COUNT ((ulong)ski->s2k.count), (ulong) ski->s2k.count); } else if (ski->s2k.mode == 1002) { /* Read the serial number. */ if (pktlen < 1) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } snlen = iobuf_get (inp); pktlen--; if (pktlen < snlen || snlen == (size_t)(-1)) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } } } else /* Old version; no S2K, so we set mode to 0, hash MD5. */ { /* Note that a ski->algo > 110 is illegal, but I'm not erroring on it here as otherwise there would be no way to delete such a key. */ ski->s2k.mode = 0; ski->s2k.hash_algo = DIGEST_ALGO_MD5; if (list_mode) es_fprintf (listfp, "\tprotect algo: %d (hash algo: %d)\n", ski->algo, ski->s2k.hash_algo); } /* It is really ugly that we don't know the size * of the IV here in cases we are not aware of the algorithm. * so a * ski->ivlen = cipher_get_blocksize (ski->algo); * won't work. The only solution I see is to hardwire it. * NOTE: if you change the ivlen above 16, don't forget to * enlarge temp. * FIXME: For v5 keys we can deduce this info! */ ski->ivlen = openpgp_cipher_blocklen (ski->algo); log_assert (ski->ivlen <= sizeof (temp)); if (ski->s2k.mode == 1001 || ski->s2k.mode == 1003) ski->ivlen = 0; else if (ski->s2k.mode == 1002) ski->ivlen = snlen < 16 ? snlen : 16; if (pktlen < ski->ivlen) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } for (i = 0; i < ski->ivlen; i++, pktlen--) temp[i] = iobuf_get_noeof (inp); if (list_mode && ski->s2k.mode != 1003) { es_fprintf (listfp, ski->s2k.mode == 1002 ? "\tserial-number: " : "\tprotect IV: "); for (i = 0; i < ski->ivlen; i++) es_fprintf (listfp, " %02x", temp[i]); es_putc ('\n', listfp); } memcpy (ski->iv, temp, ski->ivlen); } /* Skip count of secret key material. */ if (is_v5) { if (pktlen < 4) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } skbytes = read_32 (inp); pktlen -= 4; if (list_mode) es_fprintf (listfp, "\tskbytes: %u\n", skbytes); } /* It does not make sense to read it into secure memory. * If the user is so careless, not to protect his secret key, * we can assume, that he operates an open system :=(. * So we put the key into secure memory when we unprotect it. */ if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002) { /* Better set some dummy stuff here. */ pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10 * 8); pktlen = 0; } else if (ski->s2k.mode == 1003) { void *tmpp; if (pktlen < 2) /* At least two bytes for parenthesis. */ { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } tmpp = read_rest (inp, pktlen); if (list_mode) { if (mpi_print_mode) { char *tmpsxp = canon_sexp_to_string (tmpp, pktlen); es_fprintf (listfp, "\tskey[%d]: %s\n", npkey, tmpsxp? trim_trailing_spaces (tmpsxp) /* */: "[invalid S-expression]"); xfree (tmpsxp); } else es_fprintf (listfp, "\tskey[%d]: [s-expression %lu octets]\n", npkey, pktlen); } pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, tmpp, tmpp? pktlen * 8 : 0); pktlen = 0; } else if (ski->is_protected) { void *tmpp; if (pktlen < 2) /* At least two bytes for the length. */ { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } /* Ugly: The length is encrypted too, so we read all stuff * up to the end of the packet into the first SKEY * element. * FIXME: We can do better for v5 keys. */ tmpp = read_rest (inp, pktlen); pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, tmpp, tmpp? pktlen * 8 : 0); /* Mark that MPI as protected - we need this information for * importing a key. The OPAQUE flag can't be used because * we also store public EdDSA values in opaque MPIs. */ if (pk->pkey[npkey]) gcry_mpi_set_flag (pk->pkey[npkey], GCRYMPI_FLAG_USER1); pktlen = 0; if (list_mode) es_fprintf (listfp, "\tskey[%d]: [v4 protected]\n", npkey); } else { /* Not encrypted. */ for (i = npkey; i < nskey; i++) { if (pktlen < 2) /* At least two bytes for the length. */ { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } if (algorithm == PUBKEY_ALGO_KYBER && i == npkey+1) { err = read_octet_string (inp, &pktlen, 4, 0, 1, pk->pkey+i); if (err) goto leave; } else { unsigned int n = pktlen; if (algorithm == PUBKEY_ALGO_ECDSA || algorithm == PUBKEY_ALGO_EDDSA || algorithm == PUBKEY_ALGO_ECDH || algorithm == PUBKEY_ALGO_KYBER) pk->pkey[i] = sos_read (inp, &n, 0); else pk->pkey[i] = mpi_read (inp, &n, 0); pktlen -= n; } if (list_mode) { es_fprintf (listfp, "\tskey[%d]: ", i); mpi_print (listfp, pk->pkey[i], mpi_print_mode); es_putc ('\n', listfp); } if (!pk->pkey[i]) err = gpg_error (GPG_ERR_INV_PACKET); } if (err) goto leave; if (pktlen < 2) { err = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ski->csum = read_16 (inp); pktlen -= 2; if (list_mode) es_fprintf (listfp, "\tchecksum: %04hx\n", ski->csum); } } /* Note that KEYID below has been initialized above in list_mode. */ if (list_mode) es_fprintf (listfp, "\tkeyid: %08lX%08lX\n", (ulong) keyid[0], (ulong) keyid[1]); leave: iobuf_skip_rest (inp, pktlen, 0); return err; } /* Attribute subpackets have the same format as v4 signature subpackets. This is not part of OpenPGP, but is done in several versions of PGP nevertheless. */ int parse_attribute_subpkts (PKT_user_id * uid) { size_t n; int count = 0; struct user_attribute *attribs = NULL; const byte *buffer = uid->attrib_data; int buflen = uid->attrib_len; byte type; xfree (uid->attribs); while (buflen) { n = *buffer++; buflen--; if (n == 255) /* 4 byte length header. */ { if (buflen < 4) goto too_short; n = buf32_to_size_t (buffer); buffer += 4; buflen -= 4; } else if (n >= 192) /* 2 byte special encoded length header. */ { if (buflen < 2) goto too_short; n = ((n - 192) << 8) + *buffer + 192; buffer++; buflen--; } if (buflen < n) goto too_short; if (!n) { /* Too short to encode the subpacket type. */ if (opt.verbose) log_info ("attribute subpacket too short\n"); break; } attribs = xrealloc (attribs, (count + 1) * sizeof (struct user_attribute)); memset (&attribs[count], 0, sizeof (struct user_attribute)); type = *buffer; buffer++; buflen--; n--; attribs[count].type = type; attribs[count].data = buffer; attribs[count].len = n; buffer += n; buflen -= n; count++; } uid->attribs = attribs; uid->numattribs = count; return count; too_short: if (opt.verbose && !glo_ctrl.silence_parse_warnings) log_info ("buffer shorter than attribute subpacket\n"); uid->attribs = attribs; uid->numattribs = count; return count; } static int parse_user_id (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet) { byte *p; /* Cap the size of a user ID at 2k: a value absurdly large enough that there is no sane user ID string (which is printable text as of RFC2440bis) that won't fit in it, but yet small enough to avoid allocation problems. A large pktlen may not be allocatable, and a very large pktlen could actually cause our allocation to wrap around in xmalloc to a small number. */ if (pktlen > MAX_UID_PACKET_LENGTH) { log_error ("packet(%d) too large\n", pkttype); if (list_mode) es_fprintf (listfp, ":user ID packet: [too large]\n"); iobuf_skip_rest (inp, pktlen, 0); return GPG_ERR_INV_PACKET; } packet->pkt.user_id = xmalloc_clear (sizeof *packet->pkt.user_id + pktlen); packet->pkt.user_id->len = pktlen; packet->pkt.user_id->ref = 1; p = packet->pkt.user_id->name; for (; pktlen; pktlen--, p++) *p = iobuf_get_noeof (inp); *p = 0; if (list_mode) { int n = packet->pkt.user_id->len; es_fprintf (listfp, ":user ID packet: \""); /* fixme: Hey why don't we replace this with es_write_sanitized?? */ for (p = packet->pkt.user_id->name; n; p++, n--) { if (*p >= ' ' && *p <= 'z') es_putc (*p, listfp); else es_fprintf (listfp, "\\x%02x", *p); } es_fprintf (listfp, "\"\n"); } return 0; } void make_attribute_uidname (PKT_user_id * uid, size_t max_namelen) { log_assert (max_namelen > 70); if (uid->numattribs <= 0) sprintf (uid->name, "[bad attribute packet of size %lu]", uid->attrib_len); else if (uid->numattribs > 1) sprintf (uid->name, "[%d attributes of size %lu]", uid->numattribs, uid->attrib_len); else { /* Only one attribute, so list it as the "user id" */ if (uid->attribs->type == ATTRIB_IMAGE) { u32 len; byte type; if (parse_image_header (uid->attribs, &type, &len)) sprintf (uid->name, "[%.20s image of size %lu]", image_type_to_string (type, 1), (ulong) len); else sprintf (uid->name, "[invalid image]"); } else sprintf (uid->name, "[unknown attribute of size %lu]", (ulong) uid->attribs->len); } uid->len = strlen (uid->name); } static int parse_attribute (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet) { byte *p; (void) pkttype; /* We better cap the size of an attribute packet to make DoS not too easy. 16MB should be more then enough for one attribute packet (ie. a photo). */ if (pktlen > MAX_ATTR_PACKET_LENGTH) { log_error ("packet(%d) too large\n", pkttype); if (list_mode) es_fprintf (listfp, ":attribute packet: [too large]\n"); iobuf_skip_rest (inp, pktlen, 0); return GPG_ERR_INV_PACKET; } #define EXTRA_UID_NAME_SPACE 71 packet->pkt.user_id = xmalloc_clear (sizeof *packet->pkt.user_id + EXTRA_UID_NAME_SPACE); packet->pkt.user_id->ref = 1; packet->pkt.user_id->attrib_data = xmalloc (pktlen? pktlen:1); packet->pkt.user_id->attrib_len = pktlen; p = packet->pkt.user_id->attrib_data; for (; pktlen; pktlen--, p++) *p = iobuf_get_noeof (inp); /* Now parse out the individual attribute subpackets. This is somewhat pointless since there is only one currently defined attribute type (jpeg), but it is correct by the spec. */ parse_attribute_subpkts (packet->pkt.user_id); make_attribute_uidname (packet->pkt.user_id, EXTRA_UID_NAME_SPACE); if (list_mode) { es_fprintf (listfp, ":attribute packet: %s\n", packet->pkt.user_id->name); } return 0; } static int parse_comment (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet) { byte *p; /* Cap comment packet at a reasonable value to avoid an integer overflow in the malloc below. Comment packets are actually not anymore define my OpenPGP and we even stopped to use our private comment packet. */ if (pktlen > MAX_COMMENT_PACKET_LENGTH) { log_error ("packet(%d) too large\n", pkttype); if (list_mode) es_fprintf (listfp, ":%scomment packet: [too large]\n", pkttype == PKT_OLD_COMMENT ? "OpenPGP draft " : ""); iobuf_skip_rest (inp, pktlen, 0); return GPG_ERR_INV_PACKET; } packet->pkt.comment = xmalloc (sizeof *packet->pkt.comment + pktlen - 1); packet->pkt.comment->len = pktlen; p = packet->pkt.comment->data; for (; pktlen; pktlen--, p++) *p = iobuf_get_noeof (inp); if (list_mode) { int n = packet->pkt.comment->len; es_fprintf (listfp, ":%scomment packet: \"", pkttype == PKT_OLD_COMMENT ? "OpenPGP draft " : ""); for (p = packet->pkt.comment->data; n; p++, n--) { if (*p >= ' ' && *p <= 'z') es_putc (*p, listfp); else es_fprintf (listfp, "\\x%02x", *p); } es_fprintf (listfp, "\"\n"); } return 0; } /* Parse a ring trust packet RFC4880 (5.10). * * This parser is special in that the packet is not stored as a packet * but its content is merged into the previous packet. */ static gpg_error_t parse_ring_trust (parse_packet_ctx_t ctx, unsigned long pktlen) { gpg_error_t err; iobuf_t inp = ctx->inp; PKT_ring_trust rt = {0}; int c; int not_gpg = 0; if (!pktlen) { if (list_mode) es_fprintf (listfp, ":trust packet: empty\n"); err = 0; goto leave; } c = iobuf_get_noeof (inp); pktlen--; rt.trustval = c; if (pktlen) { if (!c) { c = iobuf_get_noeof (inp); /* We require that bit 7 of the sigcache is 0 (easier * eof handling). */ if (!(c & 0x80)) rt.sigcache = c; } else iobuf_get_noeof (inp); /* Dummy read. */ pktlen--; } /* Next is the optional subtype. */ if (pktlen > 3) { char tmp[4]; tmp[0] = iobuf_get_noeof (inp); tmp[1] = iobuf_get_noeof (inp); tmp[2] = iobuf_get_noeof (inp); tmp[3] = iobuf_get_noeof (inp); pktlen -= 4; if (!memcmp (tmp, "gpg", 3)) rt.subtype = tmp[3]; else not_gpg = 1; } /* If it is a key or uid subtype read the remaining data. */ if ((rt.subtype == RING_TRUST_KEY || rt.subtype == RING_TRUST_UID) && pktlen >= 6 ) { int i; unsigned int namelen; rt.keyorg = iobuf_get_noeof (inp); pktlen--; rt.keyupdate = read_32 (inp); pktlen -= 4; namelen = iobuf_get_noeof (inp); pktlen--; if (namelen && pktlen) { rt.url = xtrymalloc (namelen + 1); if (!rt.url) { err = gpg_error_from_syserror (); goto leave; } for (i = 0; pktlen && i < namelen; pktlen--, i++) rt.url[i] = iobuf_get_noeof (inp); rt.url[i] = 0; } } if (list_mode) { if (rt.subtype == RING_TRUST_SIG) es_fprintf (listfp, ":trust packet: sig flag=%02x sigcache=%02x\n", rt.trustval, rt.sigcache); else if (rt.subtype == RING_TRUST_UID || rt.subtype == RING_TRUST_KEY) { unsigned char *p; es_fprintf (listfp, ":trust packet: %s upd=%lu src=%d%s", (rt.subtype == RING_TRUST_UID? "uid" : "key"), (unsigned long)rt.keyupdate, rt.keyorg, (rt.url? " url=":"")); if (rt.url) { for (p = rt.url; *p; p++) { if (*p >= ' ' && *p <= 'z') es_putc (*p, listfp); else es_fprintf (listfp, "\\x%02x", *p); } } es_putc ('\n', listfp); } else if (not_gpg) es_fprintf (listfp, ":trust packet: not created by gpg\n"); else es_fprintf (listfp, ":trust packet: subtype=%02x\n", rt.subtype); } /* Now transfer the data to the respective packet. Do not do this * if SKIP_META is set. */ if (!ctx->last_pkt.pkt.generic || ctx->skip_meta) ; else if (rt.subtype == RING_TRUST_SIG && ctx->last_pkt.pkttype == PKT_SIGNATURE) { PKT_signature *sig = ctx->last_pkt.pkt.signature; if ((rt.sigcache & 1)) { sig->flags.checked = 1; sig->flags.valid = !!(rt.sigcache & 2); } } else if (rt.subtype == RING_TRUST_UID && (ctx->last_pkt.pkttype == PKT_USER_ID || ctx->last_pkt.pkttype == PKT_ATTRIBUTE)) { PKT_user_id *uid = ctx->last_pkt.pkt.user_id; uid->keyorg = rt.keyorg; uid->keyupdate = rt.keyupdate; uid->updateurl = rt.url; rt.url = NULL; } else if (rt.subtype == RING_TRUST_KEY && (ctx->last_pkt.pkttype == PKT_PUBLIC_KEY || ctx->last_pkt.pkttype == PKT_SECRET_KEY)) { PKT_public_key *pk = ctx->last_pkt.pkt.public_key; pk->keyorg = rt.keyorg; pk->keyupdate = rt.keyupdate; pk->updateurl = rt.url; rt.url = NULL; } err = 0; leave: xfree (rt.url); free_packet (NULL, ctx); /* This sets ctx->last_pkt to NULL. */ iobuf_skip_rest (inp, pktlen, 0); return err; } static int parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt, int new_ctb, int partial) { int rc = 0; int mode, namelen; PKT_plaintext *pt; byte *p; int c, i; if (!partial && pktlen < 6) { log_error ("packet(%d) too short (%lu)\n", pkttype, (ulong) pktlen); if (list_mode) es_fputs (":literal data packet: [too short]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } mode = iobuf_get_noeof (inp); if (pktlen) pktlen--; namelen = iobuf_get_noeof (inp); if (pktlen) pktlen--; /* Note that namelen will never exceed 255 bytes. */ pt = pkt->pkt.plaintext = xmalloc (sizeof *pkt->pkt.plaintext + namelen - 1); pt->new_ctb = new_ctb; pt->mode = mode; pt->namelen = namelen; pt->is_partial = partial; if (pktlen) { for (i = 0; pktlen > 4 && i < namelen; pktlen--, i++) pt->name[i] = iobuf_get_noeof (inp); } else { for (i = 0; i < namelen; i++) if ((c = iobuf_get (inp)) == -1) break; else pt->name[i] = c; } /* Fill up NAME so that a check with valgrind won't complain about * reading from uninitialized memory. This case may be triggred by * corrupted packets. */ for (; i < namelen; i++) pt->name[i] = 0; pt->timestamp = read_32 (inp); if (pktlen) pktlen -= 4; pt->len = pktlen; pt->buf = inp; if (list_mode) { es_fprintf (listfp, ":literal data packet:\n" "\tmode %c (%X), created %lu, name=\"", mode >= ' ' && mode < 'z' ? mode : '?', mode, (ulong) pt->timestamp); for (p = pt->name, i = 0; i < namelen; p++, i++) { if (*p >= ' ' && *p <= 'z') es_putc (*p, listfp); else es_fprintf (listfp, "\\x%02x", *p); } es_fprintf (listfp, "\",\n\traw data: "); if (partial) es_fprintf (listfp, "unknown length\n"); else es_fprintf (listfp, "%lu bytes\n", (ulong) pt->len); } leave: return rc; } static int parse_compressed (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt, int new_ctb) { PKT_compressed *zd; /* PKTLEN is here 0, but data follows (this should be the last object in a file or the compress algorithm should know the length). */ (void) pkttype; (void) pktlen; zd = pkt->pkt.compressed = xmalloc (sizeof *pkt->pkt.compressed); zd->algorithm = iobuf_get_noeof (inp); zd->len = 0; /* not used */ zd->new_ctb = new_ctb; zd->buf = inp; if (list_mode) es_fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm); return 0; } static int parse_encrypted (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt, int new_ctb, int partial) { int rc = 0; PKT_encrypted *ed; unsigned long orig_pktlen = pktlen; ed = pkt->pkt.encrypted = xmalloc (sizeof *pkt->pkt.encrypted); /* ed->len is set below. */ ed->extralen = 0; /* Unknown here; only used in build_packet. */ ed->buf = NULL; ed->new_ctb = new_ctb; ed->is_partial = partial; ed->aead_algo = 0; ed->cipher_algo = 0; /* Only used with AEAD. */ ed->chunkbyte = 0; /* Only used with AEAD. */ if (pkttype == PKT_ENCRYPTED_MDC) { /* Fixme: add some pktlen sanity checks. */ int version; version = iobuf_get_noeof (inp); if (orig_pktlen) pktlen--; if (version != 1) { log_error ("encrypted_mdc packet with unknown version %d\n", version); if (list_mode) es_fputs (":encrypted data packet: [unknown version]\n", listfp); /*skip_rest(inp, pktlen); should we really do this? */ rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ed->mdc_method = DIGEST_ALGO_SHA1; } else ed->mdc_method = 0; /* A basic sanity check. We need at least an 8 byte IV plus the 2 detection bytes. Note that we don't known the algorithm and thus we may only check against the minimum blocksize. */ if (orig_pktlen && pktlen < 10) { /* Actually this is blocksize+2. */ log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":encrypted data packet: [too short]\n", listfp); rc = GPG_ERR_INV_PACKET; iobuf_skip_rest (inp, pktlen, partial); goto leave; } /* Store the remaining length of the encrypted data (i.e. without the MDC version number but with the IV etc.). This value is required during decryption. */ ed->len = pktlen; if (list_mode) { if (orig_pktlen) es_fprintf (listfp, ":encrypted data packet:\n\tlength: %lu\n", orig_pktlen); else es_fprintf (listfp, ":encrypted data packet:\n\tlength: unknown\n"); if (ed->mdc_method) es_fprintf (listfp, "\tmdc_method: %d\n", ed->mdc_method); } ed->buf = inp; leave: return rc; } /* Note, that this code is not anymore used in real life because the MDC checking is now done right after the decryption in decrypt_data. */ static int parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt, int new_ctb) { int rc = 0; PKT_mdc *mdc; byte *p; (void) pkttype; mdc = pkt->pkt.mdc = xmalloc (sizeof *pkt->pkt.mdc); if (list_mode) es_fprintf (listfp, ":mdc packet: length=%lu\n", pktlen); if (!new_ctb || pktlen != 20) { log_error ("mdc_packet with invalid encoding\n"); rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } p = mdc->hash; for (; pktlen; pktlen--, p++) *p = iobuf_get_noeof (inp); leave: return rc; } static gpg_error_t parse_encrypted_aead (iobuf_t inp, int pkttype, unsigned long pktlen, PACKET *pkt, int partial) { int rc = 0; PKT_encrypted *ed; unsigned long orig_pktlen = pktlen; int version; ed = pkt->pkt.encrypted = xtrymalloc (sizeof *pkt->pkt.encrypted); if (!ed) return gpg_error_from_syserror (); ed->len = 0; ed->extralen = 0; /* (only used in build_packet.) */ ed->buf = NULL; ed->new_ctb = 1; /* (packet number requires a new CTB anyway.) */ ed->is_partial = partial; ed->mdc_method = 0; /* A basic sanity check. We need one version byte, one algo byte, * one aead algo byte, one chunkbyte, at least 15 byte IV. */ if (orig_pktlen && pktlen < 19) { log_error ("packet(%d) too short\n", pkttype); if (list_mode) es_fputs (":aead encrypted packet: [too short]\n", listfp); rc = gpg_error (GPG_ERR_INV_PACKET); iobuf_skip_rest (inp, pktlen, partial); goto leave; } version = iobuf_get_noeof (inp); if (orig_pktlen) pktlen--; if (version != 1) { log_error ("aead encrypted packet with unknown version %d\n", version); if (list_mode) es_fputs (":aead encrypted packet: [unknown version]\n", listfp); /*skip_rest(inp, pktlen); should we really do this? */ rc = gpg_error (GPG_ERR_INV_PACKET); goto leave; } ed->cipher_algo = iobuf_get_noeof (inp); if (orig_pktlen) pktlen--; ed->aead_algo = iobuf_get_noeof (inp); if (orig_pktlen) pktlen--; ed->chunkbyte = iobuf_get_noeof (inp); if (orig_pktlen) pktlen--; /* Store the remaining length of the encrypted data. We read the * rest during decryption. */ ed->len = pktlen; if (list_mode) { es_fprintf (listfp, ":aead encrypted packet: cipher=%u aead=%u cb=%u\n", ed->cipher_algo, ed->aead_algo, ed->chunkbyte); if (orig_pktlen) es_fprintf (listfp, "\tlength: %lu\n", orig_pktlen); else es_fprintf (listfp, "\tlength: unknown\n"); } ed->buf = inp; leave: return rc; } /* * This packet is internally generated by us (in armor.c) to transfer * some information to the lower layer. To make sure that this packet * is really a GPG faked one and not one coming from outside, we * first check that there is a unique tag in it. * * The format of such a control packet is: * n byte session marker * 1 byte control type CTRLPKT_xxxxx * m byte control data */ static int parse_gpg_control (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet, int partial) { byte *p; const byte *sesmark; size_t sesmarklen; int i; (void) pkttype; if (list_mode) es_fprintf (listfp, ":packet 63: length %lu ", pktlen); sesmark = get_session_marker (&sesmarklen); if (pktlen < sesmarklen + 1) /* 1 is for the control bytes */ goto skipit; for (i = 0; i < sesmarklen; i++, pktlen--) { if (sesmark[i] != iobuf_get_noeof (inp)) goto skipit; } if (pktlen > 4096) goto skipit; /* Definitely too large. We skip it to avoid an overflow in the malloc. */ if (list_mode) es_fputs ("- gpg control packet", listfp); packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + pktlen - 1); packet->pkt.gpg_control->control = iobuf_get_noeof (inp); pktlen--; packet->pkt.gpg_control->datalen = pktlen; p = packet->pkt.gpg_control->data; for (; pktlen; pktlen--, p++) *p = iobuf_get_noeof (inp); return 0; skipit: if (list_mode) { int c; i = 0; es_fprintf (listfp, "- private (rest length %lu)\n", pktlen); if (partial) { while ((c = iobuf_get (inp)) != -1) dump_hex_line (c, &i); } else { for (; pktlen; pktlen--) { dump_hex_line ((c = iobuf_get (inp)), &i); if (c == -1) break; } } es_putc ('\n', listfp); } iobuf_skip_rest (inp, pktlen, 0); return gpg_error (GPG_ERR_INV_PACKET); } /* Create a GPG control packet to be used internally as a placeholder. */ PACKET * create_gpg_control (ctrlpkttype_t type, const byte * data, size_t datalen) { PACKET *packet; byte *p; if (!data) datalen = 0; packet = xmalloc (sizeof *packet); init_packet (packet); packet->pkttype = PKT_GPG_CONTROL; packet->pkt.gpg_control = xmalloc (sizeof *packet->pkt.gpg_control + datalen); packet->pkt.gpg_control->control = type; packet->pkt.gpg_control->datalen = datalen; p = packet->pkt.gpg_control->data; for (; datalen; datalen--, p++) *p = *data++; return packet; } diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 873b864b5..da32ebc7b 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -1,515 +1,547 @@ /* pubkey-enc.c - Process a public key encoded packet. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006, 2009, * 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include "gpg.h" #include "../common/util.h" #include "packet.h" #include "keydb.h" #include "trustdb.h" #include "../common/status.h" #include "options.h" #include "main.h" #include "../common/i18n.h" #include "pkglue.h" #include "call-agent.h" #include "../common/host2net.h" #include "../common/compliance.h" static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *k, DEK *dek, PKT_public_key *sk, u32 *keyid); /* Check that the given algo is mentioned in one of the valid user-ids. */ static int is_algo_in_prefs (kbnode_t keyblock, preftype_t type, int algo) { kbnode_t k; for (k = keyblock; k; k = k->next) { if (k->pkt->pkttype == PKT_USER_ID) { PKT_user_id *uid = k->pkt->pkt.user_id; prefitem_t *prefs = uid->prefs; if (uid->created && prefs && !uid->flags.revoked && !uid->flags.expired) { for (; prefs->type; prefs++) if (prefs->type == type && prefs->value == algo) return 1; } } } return 0; } /* * Get the session key from a pubkey enc packet and return it in DEK, * which should have been allocated in secure memory by the caller. */ gpg_error_t get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek) { PKT_public_key *sk = NULL; gpg_error_t err; void *enum_context = NULL; u32 keyid[2]; int search_for_secret_keys = 1; struct pubkey_enc_list *k; if (DBG_CLOCK) log_clock ("get_session_key enter"); while (search_for_secret_keys) { sk = xmalloc_clear (sizeof *sk); err = enum_secret_keys (ctrl, &enum_context, sk); if (err) break; /* Check compliance. */ if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION, sk->pubkey_algo, 0, sk->pkey, nbits_from_pk (sk), NULL)) { log_info (_("key %s is not suitable for decryption" " in %s mode\n"), keystr_from_pk (sk), gnupg_compliance_option_string (opt.compliance)); continue; } /* FIXME: The list needs to be sorted so that we try the keys in * an appropriate order. For example: * - On-disk keys w/o protection * - On-disk keys with a cached passphrase * - On-card keys of an active card * - On-disk keys with protection * - On-card keys from cards which are not plugged it. Here a * cancel-all button should stop asking for other cards. * Without any anonymous keys the sorting can be skipped. */ for (k = list; k; k = k->next) { if (!(k->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E || k->pubkey_algo == PUBKEY_ALGO_ECDH || k->pubkey_algo == PUBKEY_ALGO_KYBER || k->pubkey_algo == PUBKEY_ALGO_RSA || k->pubkey_algo == PUBKEY_ALGO_RSA_E || k->pubkey_algo == PUBKEY_ALGO_ELGAMAL)) continue; if (openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC)) continue; if (sk->pubkey_algo != k->pubkey_algo) continue; keyid_from_pk (sk, keyid); if (!k->keyid[0] && !k->keyid[1]) { if (opt.skip_hidden_recipients) continue; if (!opt.quiet) log_info (_("anonymous recipient; trying secret key %s ...\n"), keystr (keyid)); } else if (opt.try_all_secrets || (k->keyid[0] == keyid[0] && k->keyid[1] == keyid[1])) { if (!opt.quiet && !(sk->pubkey_usage & PUBKEY_USAGE_ENC)) log_info (_("used key is not marked for encryption use.\n")); } else continue; err = get_it (ctrl, k, dek, sk, keyid); k->result = err; if (!err) { if (!opt.quiet && !k->keyid[0] && !k->keyid[1]) { log_info (_("okay, we are the anonymous recipient.\n")); if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC)) log_info (_("used key is not marked for encryption use.\n") ); } search_for_secret_keys = 0; break; } else if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED) { search_for_secret_keys = 0; break; /* Don't try any more secret keys. */ } } } enum_secret_keys (ctrl, &enum_context, NULL); /* free context */ if (gpg_err_code (err) == GPG_ERR_EOF) { err = gpg_error (GPG_ERR_NO_SECKEY); /* Return the last specific error, if any. */ for (k = list; k; k = k->next) if (k->result != -1) err = k->result; } if (DBG_CLOCK) log_clock ("get_session_key leave"); return err; } static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) { gpg_error_t err; byte *frame = NULL; - unsigned int n; + unsigned int frameidx; size_t nframe; u16 csum, csum2; int padding; gcry_sexp_t s_data; char *desc; char *keygrip; byte fp[MAX_FINGERPRINT_LEN]; if (DBG_CLOCK) log_clock ("decryption start"); /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); if (err) goto leave; /* Convert the data to an S-expression. */ if (sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL || sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", enc->data[0], enc->data[1]); } else if (sk->pubkey_algo == PUBKEY_ALGO_RSA || sk->pubkey_algo == PUBKEY_ALGO_RSA_E) { if (!enc->data[0]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", enc->data[0]); } else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))", enc->data[1], enc->data[0]); } else if (sk->pubkey_algo == PUBKEY_ALGO_KYBER) { - if (!enc->data[0] || !enc->data[1] || !enc->data[2] || !enc->data[3]) + log_debug ("seskey_algo: %d\n", enc->seskey_algo); + if (!enc->data[0] || !enc->data[1] || !enc->data[2]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, - "(enc-val(pqc(e%m)(k%m)(s%m)(fixed-info%s)))", - enc->data[0], enc->data[1], enc->data[3], - "\x1d" /*PUBKEY_ALGO_KYBER*/); + "(enc-val(pqc(e%m)(k%m)(s%m)(c%d)(fixed-info%s)))", + enc->data[0], enc->data[1], enc->data[2], + enc->seskey_algo, + "\x69"); } else err = gpg_error (GPG_ERR_BUG); if (err) goto leave; if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) fingerprint_from_pk (sk, fp, NULL); /* Decrypt. */ desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1); err = agent_pkdecrypt (NULL, keygrip, desc, sk->keyid, sk->main_keyid, sk->pubkey_algo, s_data, &frame, &nframe, &padding); xfree (desc); gcry_sexp_release (s_data); if (err) goto leave; /* Now get the DEK (data encryption key) from the frame * * Old versions encode the DEK in this format (msb is left): * * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 * * Later versions encode the DEK like this: * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * (mpi_get_buffer already removed the leading zero). * * RND are non-zero randow bytes. * A is the cipher algorithm * DEK is the encryption key (session key) with length k * CSUM */ if (DBG_CRYPTO) log_printhex (frame, nframe, "DEK frame:"); - n = 0; + frameidx = 0; - if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) + if (sk->pubkey_algo == PUBKEY_ALGO_KYBER) + { + /* We expect a 32 byte session key. We should not see this + * error here because due to the KEM mode the agent_pkdecrypt + * should have already failed. */ + if (nframe != 32) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + dek->keylen = nframe; + dek->algo = enc->seskey_algo; + } + else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { gcry_mpi_t decoded; /* At the beginning the frame are the bytes of shared point MPI. */ err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, frame, nframe, sk->pkey); if(err) goto leave; xfree (frame); err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded); mpi_release (decoded); if (err) goto leave; /* Now the frame are the bytes decrypted but padded session key. */ if (!nframe || nframe <= 8 || frame[nframe-1] > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } nframe -= frame[nframe-1]; /* Remove padding. */ - log_assert (!n); /* (used just below) */ + if (4 > nframe) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + + dek->keylen = nframe - 3; + dek->algo = frame[0]; + frameidx = 1; } else { if (padding) { - if (n + 7 > nframe) + if (7 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } /* FIXME: Actually the leading zero is required but due to * the way we encode the output in libgcrypt as an MPI we * are not able to encode that leading zero. However, when * using a Smartcard we are doing it the right way and * therefore we have to skip the zero. This should be fixed * in gpg-agent of course. */ - if (!frame[n]) - n++; + frameidx = 0; + if (!frame[frameidx]) + frameidx++; - if (frame[n] == 1 && frame[nframe - 1] == 2) + if (frame[frameidx] == 1 && frame[nframe - 1] == 2) { log_info (_("old encoding of the DEK is not supported\n")); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } - if (frame[n] != 2) /* Something went wrong. */ + if (frame[frameidx] != 2) /* Something went wrong. */ { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } - for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ + /* Skip the random bytes. */ + for (frameidx++; frameidx < nframe && frame[frameidx]; frameidx++) ; - n++; /* Skip the zero byte. */ + frameidx++; /* Skip the zero byte. */ } - } - if (n + 4 > nframe) - { - err = gpg_error (GPG_ERR_WRONG_SECKEY); - goto leave; + if (frameidx + 4 > nframe) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + + dek->keylen = nframe - (frameidx + 1) - 2; + dek->algo = frame[frameidx++]; } - dek->keylen = nframe - (n + 1) - 2; - dek->algo = frame[n++]; + /* Check whether we support the ago. */ err = openpgp_cipher_test_algo (dek->algo); if (err) { if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO) { log_info (_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : ""); } dek->algo = 0; goto leave; } if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo)) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } - /* Copy the key to DEK and compare the checksum. */ - csum = buf16_to_u16 (frame+nframe-2); - memcpy (dek->key, frame + n, dek->keylen); - for (csum2 = 0, n = 0; n < dek->keylen; n++) - csum2 += dek->key[n]; - if (csum != csum2) + /* Copy the key to DEK and compare the checksum if needed. */ + /* We use the frameidx as flag for the need of a checksum. */ + memcpy (dek->key, frame + frameidx, dek->keylen); + if (frameidx) { - err = gpg_error (GPG_ERR_WRONG_SECKEY); - goto leave; + csum = buf16_to_u16 (frame+nframe-2); + for (csum2 = 0, frameidx = 0; frameidx < dek->keylen; frameidx++) + csum2 += dek->key[frameidx]; + if (csum != csum2) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } } + if (DBG_CLOCK) log_clock ("decryption ready"); if (DBG_CRYPTO) log_printhex (dek->key, dek->keylen, "DEK is:"); /* Check that the algo is in the preferences and whether it has * expired. Also print a status line with the key's fingerprint. */ { PKT_public_key *pk = NULL; PKT_public_key *mainpk = NULL; KBNODE pkb = get_pubkeyblock (ctrl, keyid); if (!pkb) { err = -1; log_error ("oops: public key not found for preference check\n"); } else if (pkb->pkt->pkt.public_key->selfsigversion > 3 && dek->algo != CIPHER_ALGO_3DES && !opt.quiet && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo)) log_info (_("WARNING: cipher algorithm %s not found in recipient" " preferences\n"), openpgp_cipher_algo_name (dek->algo)); if (!err) { kbnode_t k; int first = 1; for (k = pkb; k; k = k->next) { if (k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY) { u32 aki[2]; if (first) { first = 0; mainpk = k->pkt->pkt.public_key; } keyid_from_pk (k->pkt->pkt.public_key, aki); if (aki[0] == keyid[0] && aki[1] == keyid[1]) { pk = k->pkt->pkt.public_key; break; } } } if (!pk) BUG (); if (pk->expiredate && pk->expiredate <= make_timestamp ()) { log_info (_("Note: secret key %s expired at %s\n"), keystr (keyid), asctimestamp (pk->expiredate)); } } if (pk && pk->flags.revoked) { log_info (_("Note: key has been revoked")); log_printf ("\n"); show_revocation_reason (ctrl, pk, 1); } if (is_status_enabled () && pk && mainpk) { char pkhex[MAX_FINGERPRINT_LEN*2+1]; char mainpkhex[MAX_FINGERPRINT_LEN*2+1]; hexfingerprint (pk, pkhex, sizeof pkhex); hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex); /* Note that we do not want to create a trustdb just for * getting the ownertrust: If there is no trustdb there can't * be ulitmately trusted key anyway and thus the ownertrust * value is irrelevant. */ write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c", pkhex, mainpkhex, get_ownertrust_info (ctrl, mainpk, 1)); } release_kbnode (pkb); err = 0; } leave: xfree (frame); xfree (keygrip); return err; } /* * Get the session key from the given string. * String is supposed to be formatted as this: * : */ gpg_error_t get_override_session_key (DEK *dek, const char *string) { const char *s; int i; if (!string) return GPG_ERR_BAD_KEY; dek->algo = atoi (string); if (dek->algo < 1) return GPG_ERR_BAD_KEY; if (!(s = strchr (string, ':'))) return GPG_ERR_BAD_KEY; s++; for (i = 0; i < DIM (dek->key) && *s; i++, s += 2) { int c = hextobyte (s); if (c == -1) return GPG_ERR_BAD_KEY; dek->key[i] = c; } if (*s) return GPG_ERR_BAD_KEY; dek->keylen = i; return 0; } diff --git a/g10/seskey.c b/g10/seskey.c index e5397080d..2fe8e9de7 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,354 +1,368 @@ /* seskey.c - make session keys etc. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, * 2006, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include "gpg.h" #include "../common/util.h" #include "options.h" #include "main.h" #include "../common/i18n.h" /* Generate a new session key in *DEK that is appropriate for the * algorithm DEK->ALGO (i.e., ensure that the key is not weak). * * This function overwrites DEK->KEYLEN, DEK->KEY. The rest of the * fields are left as is. */ void make_session_key( DEK *dek ) { gcry_cipher_hd_t chd; int i, rc; dek->keylen = openpgp_cipher_get_algo_keylen (dek->algo); if (openpgp_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB, (GCRY_CIPHER_SECURE | (dek->algo >= 100 ? 0 : GCRY_CIPHER_ENABLE_SYNC))) ) BUG(); gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); for (i=0; i < 16; i++ ) { rc = gcry_cipher_setkey (chd, dek->key, dek->keylen); if (!rc) { gcry_cipher_close (chd); return; } if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) BUG(); log_info(_("weak key created - retrying\n") ); /* Renew the session key until we get a non-weak key. */ gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM); } log_fatal (_("cannot avoid weak key for symmetric cipher; " "tried %d times!\n"), i); } /* Encode the session key stored in DEK as an MPI in preparation to * encrypt it with the public key algorithm OPENPGP_PK_ALGO with a key * whose length (the size of the public key) is NBITS. * * On success, returns an MPI, which the caller must free using * gcry_mpi_release(). */ gcry_mpi_t encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits) { size_t nframe = (nbits+7) / 8; byte *p; byte *frame; int i,n; u16 csum; if (DBG_CRYPTO) log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen); + if (openpgp_pk_algo == PUBKEY_ALGO_KYBER) + { + /* Straightforward encoding w/o extra checksum as used by ECDH. */ + nframe = dek->keylen; + log_assert (nframe > 4); /*(for the log_debug)*/ + frame = xmalloc_secure (nframe); + memcpy (frame, dek->key, nframe); + if (DBG_CRYPTO) + log_debug ("encode_session_key: " + "[%d] %02x %02x %02x ... %02x %02x %02x\n", + (int) dek->keylen, frame[0], frame[1], frame[2], + frame[nframe-3], frame[nframe-2], frame[nframe-1]); + + return gcry_mpi_set_opaque (NULL, frame, 8*nframe); + } + csum = 0; for (p = dek->key, i=0; i < dek->keylen; i++) csum += *p++; /* Shortcut for ECDH. It's padding is minimal to simply make the output be a multiple of 8 bytes. */ - /* FIXME: We use the ECDH also for Kyber for now. */ - if (openpgp_pk_algo == PUBKEY_ALGO_ECDH - || openpgp_pk_algo == PUBKEY_ALGO_KYBER) + if (openpgp_pk_algo == PUBKEY_ALGO_ECDH) { /* Pad to 8 byte granularity; the padding byte is the number of * padded bytes. * * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x * +---- x times ---+ */ nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */ + 7 ) & (~7)); /* alg+key+csum fit and the size is congruent to 8. */ log_assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 ); frame = xmalloc_secure (nframe); n = 0; frame[n++] = dek->algo; memcpy (frame+n, dek->key, dek->keylen); n += dek->keylen; frame[n++] = csum >> 8; frame[n++] = csum; i = nframe - n; /* Number of padded bytes. */ memset (frame+n, i, i); /* Use it as the value of each padded byte. */ log_assert (n+i == nframe); if (DBG_CRYPTO) log_debug ("encode_session_key: " "[%d] %02x %02x %02x ... %02x %02x %02x\n", (int) nframe, frame[0], frame[1], frame[2], frame[nframe-3], frame[nframe-2], frame[nframe-1]); return gcry_mpi_set_opaque (NULL, frame, 8*nframe); } /* The current limitation is that we can only use a session key * whose length is a multiple of BITS_PER_MPI_LIMB * I think we can live with that. */ if (dek->keylen + 7 > nframe || !nframe) log_bug ("can't encode a %d bit key in a %d bits frame\n", dek->keylen*8, nbits ); /* We encode the session key according to PKCS#1 v1.5 (see section * 13.1.1 of RFC 4880): * * 0 2 RND(i bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * (But how can we store the leading 0 - the external representation * of MPIs doesn't allow leading zeroes =:-) * * RND are (at least 1) non-zero random bytes. * A is the cipher algorithm * DEK is the encryption key (session key) length k depends on the * cipher algorithm (20 is used with blowfish160). * CSUM is the 16 bit checksum over the DEK */ frame = xmalloc_secure( nframe ); n = 0; frame[n++] = 0; frame[n++] = 2; /* The number of random bytes are the number of otherwise unused bytes. See diagram above. */ i = nframe - 6 - dek->keylen; log_assert( i > 0 ); p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); /* Replace zero bytes by new values. */ for (;;) { int j, k; byte *pp; /* Count the zero bytes. */ for (j=k=0; j < i; j++ ) if (!p[j]) k++; if (!k) break; /* Okay: no zero bytes. */ k += k/128 + 3; /* Better get some more. */ pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); for (j=0; j < i && k ;) { if (!p[j]) p[j] = pp[--k]; if (p[j]) j++; } xfree (pp); } memcpy (frame+n, p, i); xfree (p); n += i; frame[n++] = 0; frame[n++] = dek->algo; memcpy (frame+n, dek->key, dek->keylen ); n += dek->keylen; frame[n++] = csum >>8; frame[n++] = csum; log_assert (n == nframe); return gcry_mpi_set_opaque (NULL, frame, 8*n); } static gcry_mpi_t do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, const byte *asn, size_t asnlen ) { size_t nframe = (nbits+7) / 8; byte *frame; int i,n; gcry_mpi_t a; if (len + asnlen + 4 > nframe) { log_error ("can't encode a %d bit MD into a %d bits frame, algo=%d\n", (int)(len*8), (int)nbits, algo); return NULL; } /* We encode the MD in this way: * * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) * * PAD consists of FF bytes. */ frame = gcry_md_is_secure (md)? xmalloc_secure (nframe) : xmalloc (nframe); n = 0; frame[n++] = 0; frame[n++] = 1; /* block type */ i = nframe - len - asnlen -3 ; log_assert( i > 1 ); memset( frame+n, 0xff, i ); n += i; frame[n++] = 0; memcpy( frame+n, asn, asnlen ); n += asnlen; memcpy( frame+n, gcry_md_read (md, algo), len ); n += len; log_assert( n == nframe ); if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe )) BUG(); xfree(frame); /* Note that PGP before version 2.3 encoded the MD as: * * 0 1 MD(16 bytes) 0 PAD(n bytes) 1 * * The MD is always 16 bytes here because it's always MD5. We do * not support pre-v2.3 signatures, but I'm including this comment * so the information is easily found in the future. */ return a; } /**************** * Encode a message digest into an MPI. * If it's for a DSA signature, make sure that the hash is large * enough to fill up q. If the hash is too big, take the leftmost * bits. */ gcry_mpi_t encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) { gcry_mpi_t frame; size_t mdlen; log_assert (hash_algo); log_assert (pk); if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA) { /* EdDSA signs data of arbitrary length. Thus no special treatment is required. */ frame = gcry_mpi_set_opaque_copy (NULL, gcry_md_read (md, hash_algo), 8*gcry_md_get_algo_dlen (hash_algo)); } else if (pk->pubkey_algo == PUBKEY_ALGO_DSA || pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { /* It's a DSA signature, so find out the size of q. */ size_t qbits = gcry_mpi_get_nbits (pk->pkey[1]); /* pkey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA) qbits = ecdsa_qbits_from_Q (qbits); /* Make sure it is a multiple of 8 bits. */ if ((qbits%8)) { log_error(_("DSA requires the hash length to be a" " multiple of 8 bits\n")); return NULL; } /* Don't allow any q smaller than 160 bits. This might need a revisit as the DSA2 design firms up, but for now, we don't want someone to issue signatures from a key with a 16-bit q or something like that, which would look correct but allow trivial forgeries. Yes, I know this rules out using MD5 with DSA. ;) */ if (qbits < 160) { log_error (_("%s key %s uses an unsafe (%zu bit) hash\n"), openpgp_pk_algo_name (pk->pubkey_algo), keystr_from_pk (pk), qbits); return NULL; } /* ECDSA 521 is special has it is larger than the largest hash we have (SHA-512). Thus we change the size for further processing to 512. */ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA && qbits > 512) qbits = 512; /* Check if we're too short. Too long is safe as we'll automatically left-truncate. */ mdlen = gcry_md_get_algo_dlen (hash_algo); if (mdlen < qbits/8) { log_error (_("%s key %s requires a %zu bit or larger hash " "(hash is %s)\n"), openpgp_pk_algo_name (pk->pubkey_algo), keystr_from_pk (pk), qbits, gcry_md_algo_name (hash_algo)); return NULL; } /* Note that we do the truncation by passing QBITS/8 as length to mpi_scan. */ if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, gcry_md_read (md, hash_algo), qbits/8, NULL)) BUG(); } else { gpg_error_t rc; byte *asn; size_t asnlen; rc = gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, NULL, &asnlen); if (rc) log_fatal ("can't get OID of digest algorithm %d: %s\n", hash_algo, gpg_strerror (rc)); asn = xtrymalloc (asnlen); if (!asn) return NULL; if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) ) BUG(); frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo), gcry_mpi_get_nbits (pk->pkey[0]), asn, asnlen); xfree (asn); } return frame; }