Add support for pulling out the creation time of a signature, then use
this information when we're merging key signatures. This allows for
updating of signatures (eg key preferences) or adding new signatures eg
with later expiry dates. As reported in Debian bug #410796
/*
* parse_subpackets - Parse the subpackets of a Type 4 signature.
* @data: The subpacket data.
/*
* parse_subpackets - Parse the subpackets of a Type 4 signature.
* @data: The subpacket data.
- * @keyid: A pointer to where we should return the keyid.
+ * @keyid: A pointer to where we should return the keyid.
+ * @creationtime: A pointer to where we should return the creation time.
*
* This function parses the subkey data of a Type 4 signature and fills
* in the supplied variables. It also returns the length of the data
*
* This function parses the subkey data of a Type 4 signature and fills
* in the supplied variables. It also returns the length of the data
+ * processed. If the value of any piece of data is not desired a NULL
+ * can be passed instead of a pointer to a storage area for that value.
-int parse_subpackets(unsigned char *data, uint64_t *keyid)
+int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation)
{
int offset = 0;
int length = 0;
{
int offset = 0;
int length = 0;
switch (data[offset] & 0x7F) {
case 2:
/*
switch (data[offset] & 0x7F) {
case 2:
/*
- * Signature creation time. Might want to output this?
+ * Signature creation time.
+ if (creation != NULL) {
+ *creation = data[offset + packetlen - 4];
+ *creation <<= 8;
+ *creation = data[offset + packetlen - 3];
+ *creation <<= 8;
+ *creation = data[offset + packetlen - 2];
+ *creation <<= 8;
+ *creation = data[offset + packetlen - 1];
+ }
- *keyid = data[offset+packetlen - 8];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 7];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 6];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 5];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 4];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 3];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 2];
- *keyid <<= 8;
- *keyid += data[offset+packetlen - 1];
+ if (keyid != NULL) {
+ *keyid = data[offset+packetlen - 8];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 7];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 6];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 5];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 4];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 3];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 2];
+ *keyid <<= 8;
+ *keyid += data[offset+packetlen - 1];
+ }
- * sig_keyid - Return the keyid for a given OpenPGP signature packet.
- * @packet: The signature packet.
+ * sig_info - Get info on a given OpenPGP signature packet
+ * @packet: The signature packet
+ * @keyid: A pointer for where to return the signature keyid
+ * @creation: A pointer for where to return the signature creation time
- * Returns the keyid for the supplied signature packet.
+ * Gets any info about a signature packet; parses the subpackets for a v4
+ * key or pulls the data directly from v2/3. NULL can be passed for any
+ * values which aren't cared about.
-uint64_t sig_keyid(struct openpgp_packet *packet)
+void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation)
switch (packet->data[0]) {
case 2:
case 3:
switch (packet->data[0]) {
case 2:
case 3:
- keyid = packet->data[7];
- keyid <<= 8;
- keyid += packet->data[8];
- keyid <<= 8;
- keyid += packet->data[9];
- keyid <<= 8;
- keyid += packet->data[10];
- keyid <<= 8;
- keyid += packet->data[11];
- keyid <<= 8;
- keyid += packet->data[12];
- keyid <<= 8;
- keyid += packet->data[13];
- keyid <<= 8;
- keyid += packet->data[14];
+ if (keyid != NULL) {
+ *keyid = packet->data[7];
+ *keyid <<= 8;
+ *keyid += packet->data[8];
+ *keyid <<= 8;
+ *keyid += packet->data[9];
+ *keyid <<= 8;
+ *keyid += packet->data[10];
+ *keyid <<= 8;
+ *keyid += packet->data[11];
+ *keyid <<= 8;
+ *keyid += packet->data[12];
+ *keyid <<= 8;
+ *keyid += packet->data[13];
+ *keyid <<= 8;
+ *keyid += packet->data[14];
+ }
+ if (creation != NULL) {
+ *creation = packet->data[3];
+ *creation <<= 8;
+ *creation = packet->data[4];
+ *creation <<= 8;
+ *creation = packet->data[5];
+ *creation <<= 8;
+ *creation = packet->data[6];
+ }
break;
case 4:
length = parse_subpackets(&packet->data[4],
break;
case 4:
length = parse_subpackets(&packet->data[4],
parse_subpackets(&packet->data[length + 4],
parse_subpackets(&packet->data[length + 4],
/*
* Don't bother to look at the unsigned packets.
*/
/*
* Don't bother to look at the unsigned packets.
*/
+ return;
+}
+
+/**
+ * sig_keyid - Return the keyid for a given OpenPGP signature packet.
+ * @packet: The signature packet.
+ *
+ * Returns the keyid for the supplied signature packet.
+ */
+uint64_t sig_keyid(struct openpgp_packet *packet)
+{
+ uint64_t keyid = 0;
+
+ sig_info(packet, &keyid, NULL);
+
/*
* TODO: Abstract out; all our linked lists should be generic and then we can
* llsize them.
/*
* TODO: Abstract out; all our linked lists should be generic and then we can
* llsize them.
struct ll *keysigs(struct ll *curll,
struct openpgp_packet_list *sigs);
struct ll *keysigs(struct ll *curll,
struct openpgp_packet_list *sigs);
+/**
+ * sig_info - Get info on a given OpenPGP signature packet
+ * @packet: The signature packet
+ * @keyid: A pointer for where to return the signature keyid
+ * @creation: A pointer for where to return the signature creation time
+ *
+ * Gets any info about a signature packet; parses the subpackets for a v4
+ * key or pulls the data directly from v2/3. NULL can be passed for any
+ * values which aren't cared about.
+ */
+void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation);
+
/**
* sig_keyid - Return the keyid for a given OpenPGP signature packet.
* @packet: The signature packet.
/**
* sig_keyid - Return the keyid for a given OpenPGP signature packet.
* @packet: The signature packet.
*/
bool compare_signatures(struct openpgp_packet *a, struct openpgp_packet *b)
{
*/
bool compare_signatures(struct openpgp_packet *a, struct openpgp_packet *b)
{
+ uint64_t a_keyid, b_keyid;
+ time_t a_creation, b_creation;
+
if (a->data[0] != b->data[0]) {
/* Different signature versions, so not the same */
return false;
} else if (a->data[0] == 4 && a->data[1] != b->data[1]) {
/* Type 4 signature, but different types */
return false;
if (a->data[0] != b->data[0]) {
/* Different signature versions, so not the same */
return false;
} else if (a->data[0] == 4 && a->data[1] != b->data[1]) {
/* Type 4 signature, but different types */
return false;
- /* TODO: Check signature time? */
- return (sig_keyid(a) == sig_keyid(b));
+ sig_info(a, &a_keyid, &a_creation);
+ sig_info(b, &b_keyid, &b_creation);
+ return (a_creation == b_creation) && (a_keyid == b_keyid);