2  * decodekey.c - Routines to further decode an OpenPGP key.
 
   4  * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
 
  13 #include "decodekey.h"
 
  16 #include "keystructs.h"
 
  22  *      parse_subpackets - Parse the subpackets of a Type 4 signature.
 
  23  *      @data: The subpacket data.
 
  24  *      @keyid: A pointer to where we should return the keyid.
 
  25  *      @creationtime: A pointer to where we should return the creation time.
 
  27  *      This function parses the subkey data of a Type 4 signature and fills
 
  28  *      in the supplied variables. It also returns the length of the data
 
  29  *      processed. If the value of any piece of data is not desired a NULL
 
  30  *      can be passed instead of a pointer to a storage area for that value.
 
  32 int parse_subpackets(unsigned char *data, uint64_t *keyid, time_t *creation)
 
  38         log_assert(data != NULL);
 
  40         length = (data[0] << 8) + data[1] + 2;
 
  43         while (offset < length) {
 
  44                 packetlen = data[offset++];
 
  45                 if (packetlen > 191 && packetlen < 255) {
 
  46                         packetlen = ((packetlen - 192) << 8) +
 
  48                 } else if (packetlen == 255) {
 
  49                         packetlen = data[offset++];
 
  51                         packetlen = data[offset++];
 
  53                         packetlen = data[offset++];
 
  55                         packetlen = data[offset++];
 
  57                 switch (data[offset] & 0x7F) {
 
  58                 case OPENPGP_SIGSUB_CREATION:
 
  60                          * Signature creation time.
 
  62                         if (creation != NULL) {
 
  63                                 *creation = data[offset + packetlen - 4];
 
  65                                 *creation = data[offset + packetlen - 3];
 
  67                                 *creation = data[offset + packetlen - 2];
 
  69                                 *creation = data[offset + packetlen - 1];
 
  72                 case OPENPGP_SIGSUB_EXPIRY:
 
  74                          * Signature expiration time. Might want to output this?
 
  77                 case OPENPGP_SIGSUB_REGEX:
 
  79                          * Regular expression for UIDs this sig is over.
 
  82                 case OPENPGP_SIGSUB_ISSUER:
 
  84                                 *keyid = data[offset+packetlen - 8];
 
  86                                 *keyid += data[offset+packetlen - 7];
 
  88                                 *keyid += data[offset+packetlen - 6];
 
  90                                 *keyid += data[offset+packetlen - 5];
 
  92                                 *keyid += data[offset+packetlen - 4];
 
  94                                 *keyid += data[offset+packetlen - 3];
 
  96                                 *keyid += data[offset+packetlen - 2];
 
  98                                 *keyid += data[offset+packetlen - 1];
 
 101                 case OPENPGP_SIGSUB_NOTATION:
 
 107                 case OPENPGP_SIGSUB_KEYSERVER:
 
 109                          * Key server preferences. Including no-modify.
 
 112                 case OPENPGP_SIGSUB_PRIMARYUID:
 
 117                 case OPENPGP_SIGSUB_POLICYURI:
 
 124                          * We don't care about unrecognized packets unless bit
 
 125                          * 7 is set in which case we log a major error.
 
 127                         if (data[offset] & 0x80) {
 
 128                                 logthing(LOGTHING_CRITICAL,
 
 129                                 "Critical subpacket type not parsed: 0x%X",
 
 141  *      keysigs - Return the sigs on a given OpenPGP signature list.
 
 142  *      @curll: The current linked list. Can be NULL to create a new list.
 
 143  *      @sigs: The signature list we want the sigs on.
 
 145  *      Returns a linked list of stats_key elements containing the sigs on the
 
 146  *      supplied OpenPGP packet list.
 
 148 struct ll *keysigs(struct ll *curll,
 
 149                 struct openpgp_packet_list *sigs)
 
 153         while (sigs != NULL) {
 
 154                 keyid = sig_keyid(sigs->packet);
 
 156                 curll = lladd(curll, createandaddtohash(keyid));
 
 163  *      sig_info - Get info on a given OpenPGP signature packet
 
 164  *      @packet: The signature packet
 
 165  *      @keyid: A pointer for where to return the signature keyid
 
 166  *      @creation: A pointer for where to return the signature creation time
 
 168  *      Gets any info about a signature packet; parses the subpackets for a v4
 
 169  *      key or pulls the data directly from v2/3. NULL can be passed for any
 
 170  *      values which aren't cared about.
 
 172 void sig_info(struct openpgp_packet *packet, uint64_t *keyid, time_t *creation)
 
 176         if (packet != NULL) {
 
 177                 switch (packet->data[0]) {
 
 181                                 *keyid = packet->data[7];
 
 183                                 *keyid += packet->data[8];
 
 185                                 *keyid += packet->data[9];
 
 187                                 *keyid += packet->data[10];
 
 189                                 *keyid += packet->data[11];
 
 191                                 *keyid += packet->data[12];
 
 193                                 *keyid += packet->data[13];
 
 195                                 *keyid += packet->data[14];
 
 197                         if (creation != NULL) {
 
 198                                 *creation = packet->data[3];
 
 200                                 *creation = packet->data[4];
 
 202                                 *creation = packet->data[5];
 
 204                                 *creation = packet->data[6];
 
 208                         length = parse_subpackets(&packet->data[4],
 
 210                         parse_subpackets(&packet->data[length + 4],
 
 213                          * Don't bother to look at the unsigned packets.
 
 225  *      sig_keyid - Return the keyid for a given OpenPGP signature packet.
 
 226  *      @packet: The signature packet.
 
 228  *      Returns the keyid for the supplied signature packet.
 
 230 uint64_t sig_keyid(struct openpgp_packet *packet)
 
 234         sig_info(packet, &keyid, NULL);
 
 241  * TODO: Abstract out; all our linked lists should be generic and then we can
 
 244 int spsize(struct openpgp_signedpacket_list *list)
 
 247         struct openpgp_signedpacket_list *cur;
 
 249         for (cur = list; cur != NULL; cur = cur->next, size++) ;
 
 255  *      keyuids - Takes a key and returns an array of its UIDs
 
 256  *      @key: The key to get the uids of.
 
 257  *      @primary: A pointer to store the primary UID in.
 
 259  *      keyuids takes a public key structure and builds an array of the UIDs 
 
 260  *      on the key. It also attempts to work out the primary UID and returns a
 
 261  *      separate pointer to that particular element of the array.
 
 263 char **keyuids(struct openpgp_publickey *key, char **primary)
 
 265         struct openpgp_signedpacket_list *curuid = NULL;
 
 270         if (primary != NULL) {
 
 274         if (key != NULL && key->uids != NULL) {
 
 275                 uids = malloc((spsize(key->uids) + 1) * sizeof (char *));
 
 278                 while (curuid != NULL) {
 
 280                         if (curuid->packet->tag == OPENPGP_PACKET_UID) {
 
 281                                 snprintf(buf, 1023, "%.*s",
 
 282                                                 (int) curuid->packet->length,
 
 283                                                 curuid->packet->data);
 
 284                                 uids[count++] = strdup(buf);
 
 286                         curuid = curuid -> next;
 
 291                  * TODO: Parse subpackets for real primary ID (v4 keys)
 
 293                 if (primary != NULL) {
 
 302  *      keysubkeys - Takes a key and returns an array of its subkey keyids.
 
 303  *      @key: The key to get the subkeys of.
 
 305  *      keysubkeys takes a public key structure and returns an array of the
 
 306  *      subkey keyids for that key.
 
 308 uint64_t *keysubkeys(struct openpgp_publickey *key)
 
 310         struct openpgp_signedpacket_list *cursubkey = NULL;
 
 311         uint64_t                         *subkeys = NULL;
 
 314         if (key != NULL && key->subkeys != NULL) {
 
 315                 subkeys = malloc((spsize(key->subkeys) + 1) *
 
 317                 cursubkey = key->subkeys;
 
 318                 while (cursubkey != NULL) {
 
 319                         subkeys[count++] = get_packetid(cursubkey->packet);
 
 320                         cursubkey = cursubkey -> next;