]> the.earth.li Git - onak.git/blobdiff - keyindex.c
Fix compilation with later versions of Nettle
[onak.git] / keyindex.c
index 6aab5d3c73da891faeebe6d3262d3420a464fead..eeac56cac47d238c7c3c3e270a7178e535418095 100644 (file)
@@ -2,6 +2,18 @@
  * keyindex.c - Routines to list an OpenPGP key.
  *
  * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program 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; version 2 of the License.
+ *
+ * This program 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 <https://www.gnu.org/licenses/>.
  */
 
 #include <inttypes.h>
 
 #include "decodekey.h"
 #include "getcgi.h"
-#include "hash.h"
 #include "keydb.h"
 #include "keyid.h"
 #include "keyindex.h"
 #include "keystructs.h"
 #include "log.h"
-#include "onak-conf.h"
+#include "onak.h"
 #include "openpgp.h"
 
-int list_sigs(struct openpgp_packet_list *sigs, bool html)
+/*
+ * Convert a Public Key algorithm to its single character representation.
+ */
+char pkalgo2char(uint8_t algo)
+{
+       char typech;
+
+       switch (algo) {
+       case OPENPGP_PKALGO_DSA:
+               typech = 'D';
+               break;
+       case OPENPGP_PKALGO_ECDSA:
+       case OPENPGP_PKALGO_EDDSA:
+               typech = 'E';
+               break;
+       case OPENPGP_PKALGO_EC:
+               typech = 'e';
+               break;
+       case OPENPGP_PKALGO_ELGAMAL_SIGN:
+               typech = 'G';
+               break;
+       case OPENPGP_PKALGO_ELGAMAL_ENC:
+               typech = 'g';
+               break;
+       case OPENPGP_PKALGO_RSA:
+               typech = 'R';
+               break;
+       case OPENPGP_PKALGO_RSA_ENC:
+               typech = 'r';
+               break;
+       case OPENPGP_PKALGO_RSA_SIGN:
+               typech = 's';
+               break;
+       default:
+               typech = '?';
+               break;
+       }
+
+       return typech;
+}
+
+/*
+ * Given a public key/subkey packet return the key length.
+ */
+unsigned int keylength(struct openpgp_packet *keydata)
+{
+       unsigned int length;
+       uint8_t keyofs;
+       enum onak_oid oid;
+
+       switch (keydata->data[0]) {
+       case 2:
+       case 3:
+               length = (keydata->data[8] << 8) +
+                               keydata->data[9];
+               break;
+       case 4:
+       case 5:
+               /* v5 has an additional 4 bytes of key length data */
+               keyofs = (keydata->data[0] == 4) ? 6 : 10;
+               switch (keydata->data[5]) {
+               case OPENPGP_PKALGO_EC:
+               case OPENPGP_PKALGO_ECDSA:
+               case OPENPGP_PKALGO_EDDSA:
+                       /* Elliptic curve key size is based on OID */
+                       oid = onak_parse_oid(&keydata->data[keyofs],
+                                       keydata->length - keyofs);
+                       if (oid == ONAK_OID_CURVE25519) {
+                               length = 255;
+                       } else if (oid == ONAK_OID_ED25519) {
+                               length = 255;
+                       } else if (oid == ONAK_OID_NISTP256) {
+                               length = 256;
+                       } else if (oid == ONAK_OID_NISTP384) {
+                               length = 384;
+                       } else if (oid == ONAK_OID_NISTP521) {
+                               length = 521;
+                       } else if (oid == ONAK_OID_BRAINPOOLP256R1) {
+                               length = 256;
+                       } else if (oid == ONAK_OID_BRAINPOOLP384R1) {
+                               length = 384;
+                       } else if (oid == ONAK_OID_BRAINPOOLP512R1) {
+                               length = 512;
+                       } else if (oid == ONAK_OID_SECP256K1) {
+                               length = 256;
+                       } else {
+                               logthing(LOGTHING_ERROR,
+                                       "Unknown elliptic curve size");
+                               length = 0;
+                       }
+                       break;
+               default:
+                       length = (keydata->data[keyofs] << 8) +
+                               keydata->data[keyofs + 1];
+               }
+               break;
+       default:
+               logthing(LOGTHING_ERROR, "Unknown key version: %d",
+                       keydata->data[0]);
+               length = 0;
+       }
+
+       return length;
+}
+
+int list_sigs(struct onak_dbctx *dbctx,
+               struct openpgp_packet_list *sigs, bool html)
 {
        char *uid = NULL;
        uint64_t sigid = 0;
@@ -30,7 +147,9 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
 
        while (sigs != NULL) {
                sigid = sig_keyid(sigs->packet);
-               uid = config.dbbackend->keyid2uid(sigid);
+               if (dbctx) {
+                       uid = dbctx->keyid2uid(dbctx, sigid);
+               }
                if (sigs->packet->data[0] == 4 &&
                                sigs->packet->data[1] == 0x30) {
                        /* It's a Type 4 sig revocation */
@@ -40,25 +159,25 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
                }
                if (html && uid != NULL) {
                        printf("%s         <a href=\"lookup?op=get&"
-                               "search=%016" PRIX64 "\">%08" PRIX64
+                               "search=0x%016" PRIX64 "\">0x%016" PRIX64
                                "</a>             "
                                "<a href=\"lookup?op=vindex&search=0x%016"
                                PRIX64 "\">%s</a>\n",
                                sig,
                                sigid,
-                               sigid & 0xFFFFFFFF,
+                               sigid,
                                sigid,
                                txt2html(uid));
                } else if (html && uid == NULL) {
-                       printf("%s         %08" PRIX64 "             "
+                       printf("%s         0x%016" PRIX64 "             "
                                "[User id not found]\n",
                                sig,
-                               sigid & 0xFFFFFFFF);
+                               sigid);
                } else {
-                       printf("%s         %08" PRIX64
+                       printf("%s         0x%016" PRIX64
                                "             %s\n",
                                sig,
-                               sigid & 0xFFFFFFFF,
+                               sigid,
                                (uid != NULL) ? uid :
                                "[User id not found]");
                }
@@ -72,7 +191,8 @@ int list_sigs(struct openpgp_packet_list *sigs, bool html)
        return 0;
 }
 
-int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
+int list_uids(struct onak_dbctx *dbctx,
+               uint64_t keyid, struct openpgp_signedpacket_list *uids,
                bool verbose, bool html)
 {
        char buf[1024];
@@ -99,7 +219,7 @@ int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
                        }
                }
                if (verbose) {
-                       list_sigs(uids->sigs, html);
+                       list_sigs(dbctx, uids->sigs, html);
                }
                uids = uids->next;
        }
@@ -107,13 +227,15 @@ int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
        return 0;
 }
 
-int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
+int list_subkeys(struct onak_dbctx *dbctx,
+               struct openpgp_signedpacket_list *subkeys, bool verbose,
                bool html)
 {
        struct tm       *created = NULL;
        time_t          created_time = 0;
        int             type = 0;
        int             length = 0;
+       uint64_t        keyid = 0;
 
        while (subkeys != NULL) {
                if (subkeys->packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
@@ -128,34 +250,33 @@ int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
                        case 2:
                        case 3:
                                type = subkeys->packet->data[7];
-                               length = (subkeys->packet->data[8] << 8) +
-                                       subkeys->packet->data[9];
                                break;
                        case 4:
+                       case 5:
                                type = subkeys->packet->data[5];
-                               length = (subkeys->packet->data[6] << 8) +
-                                       subkeys->packet->data[7];
                                break;
                        default:
                                logthing(LOGTHING_ERROR,
-                                       "Unknown key type: %d",
+                                       "Unknown key version: %d",
                                        subkeys->packet->data[0]);
                        }
-               
-                       printf("sub  %5d%c/%08X %04d/%02d/%02d\n",
+                       length = keylength(subkeys->packet);
+
+                       if (get_packetid(subkeys->packet,
+                                       &keyid) != ONAK_E_OK) {
+                               logthing(LOGTHING_ERROR, "Couldn't get keyid.");
+                       }
+                       printf("sub  %5d%c/0x%016" PRIX64 " %04d/%02d/%02d\n",
                                length,
-                               (type == OPENPGP_PKALGO_RSA) ? 'R' :
-                               ((type == OPENPGP_PKALGO_ELGAMAL) ? 'g' :
-                               ((type == OPENPGP_PKALGO_DSA) ? 'D' : '?')),
-                               (uint32_t) (get_packetid(subkeys->packet) &
-                                           0xFFFFFFFF),
+                               pkalgo2char(type),
+                               keyid,
                                created->tm_year + 1900,
                                created->tm_mon + 1,
                                created->tm_mday);
 
                }
                if (verbose) {
-                       list_sigs(subkeys->sigs, html);
+                       list_sigs(dbctx, subkeys->sigs, html);
                }
                subkeys = subkeys->next;
        }
@@ -166,20 +287,21 @@ int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
 void display_fingerprint(struct openpgp_publickey *key)
 {
        int             i = 0;
-       size_t          length = 0;
-       unsigned char   fp[20];
+       struct openpgp_fingerprint fingerprint;
 
-       get_fingerprint(key->publickey, fp, &length);
+       get_fingerprint(key->publickey, &fingerprint);
        printf("      Key fingerprint =");
-       for (i = 0; i < length; i++) {
-               if ((length == 16) ||
+       for (i = 0; i < fingerprint.length; i++) {
+               if ((fingerprint.length == 16) ||
                        (i % 2 == 0)) {
                        printf(" ");
                }
-               printf("%02X", fp[i]);
-               if ((i * 2) == length) {
+               if (fingerprint.length == 20 &&
+                               (i * 2) == fingerprint.length) {
+                       /* Extra space in the middle of a SHA1 fingerprint */
                        printf(" ");
                }
+               printf("%02X", fingerprint.fp[i]);
        }
        printf("\n");
 
@@ -221,14 +343,14 @@ void display_skshash(struct openpgp_publickey *key, bool html)
  *     This function takes a list of OpenPGP public keys and displays an index
  *     of them. Useful for debugging or the keyserver Index function.
  */
-int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
+int key_index(struct onak_dbctx *dbctx,
+               struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                        bool skshash, bool html)
 {
        struct openpgp_signedpacket_list        *curuid = NULL;
        struct tm                               *created = NULL;
        time_t                                   created_time = 0;
        int                                      type = 0;
-       char                                     typech;
        int                                      length = 0;
        char                                     buf[1024];
        uint64_t                                 keyid;
@@ -248,55 +370,37 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                case 2:
                case 3:
                        type = keys->publickey->data[7];
-                       length = (keys->publickey->data[8] << 8) +
-                                       keys->publickey->data[9];
                        break;
                case 4:
+               case 5:
                        type = keys->publickey->data[5];
-                       length = (keys->publickey->data[6] << 8) +
-                                       keys->publickey->data[7];
                        break;
                default:
-                       logthing(LOGTHING_ERROR, "Unknown key type: %d",
+                       logthing(LOGTHING_ERROR, "Unknown key version: %d",
                                keys->publickey->data[0]);
                }
-               
-               keyid = get_keyid(keys);
+               length = keylength(keys->publickey);
 
-               switch (type) {
-               case OPENPGP_PKALGO_RSA:
-                       typech = 'R';
-                       break;
-               case OPENPGP_PKALGO_ELGAMAL:
-                       typech = 'g';
-                       break;
-               case OPENPGP_PKALGO_DSA:
-                       typech = 'D';
-                       break;
-               case OPENPGP_PKALGO_ELGAMAL_SIGN:
-                       typech = 'G';
-                       break;
-               default:
-                       typech = '?';
-                       break;
+               if (get_keyid(keys, &keyid) != ONAK_E_OK) {
+                       logthing(LOGTHING_ERROR, "Couldn't get keyid.");
                }
 
                if (html) {
                        printf("pub  %5d%c/<a href=\"lookup?op=get&"
-                               "search=%016" PRIX64 "\">%08" PRIX64
+                               "search=0x%016" PRIX64 "\">0x%016" PRIX64
                                "</a> %04d/%02d/%02d ",
                                length,
-                               typech,
+                               pkalgo2char(type),
+                               keyid,
                                keyid,
-                               keyid & 0xFFFFFFFF,
                                created->tm_year + 1900,
                                created->tm_mon + 1,
                                created->tm_mday);
                } else {
-                       printf("pub  %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
+                       printf("pub  %5d%c/0x%016" PRIX64 " %04d/%02d/%02d ",
                                length,
-                               typech,
-                               keyid & 0xFFFFFFFF,
+                               pkalgo2char(type),
+                               keyid,
                                created->tm_year + 1900,
                                created->tm_mon + 1,
                                created->tm_mday);
@@ -324,7 +428,7 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                                display_fingerprint(keys);
                        }
                        if (verbose) {
-                               list_sigs(curuid->sigs, html);
+                               list_sigs(dbctx, curuid->sigs, html);
                        }
                        curuid = curuid->next;
                } else {
@@ -335,9 +439,9 @@ int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
                        }
                }
 
-               list_uids(keyid, curuid, verbose, html);
+               list_uids(dbctx, keyid, curuid, verbose, html);
                if (verbose) {
-                       list_subkeys(keys->subkeys, verbose, html);
+                       list_subkeys(dbctx, keys->subkeys, verbose, html);
                }
 
                keys = keys->next;
@@ -364,9 +468,9 @@ int mrkey_index(struct openpgp_publickey *keys)
        int                                      type = 0;
        int                                      length = 0;
        int                                      i = 0;
-       size_t                                   fplength = 0;
-       unsigned char                            fp[20];
        int                                      c;
+       uint64_t                                 keyid;
+       struct openpgp_fingerprint fingerprint;
 
        while (keys != NULL) {
                created_time = (keys->publickey->data[1] << 24) +
@@ -379,26 +483,27 @@ int mrkey_index(struct openpgp_publickey *keys)
                switch (keys->publickey->data[0]) {
                case 2:
                case 3:
-                       printf("%016" PRIX64, get_keyid(keys));
+                       if (get_keyid(keys, &keyid) != ONAK_E_OK) {
+                               logthing(LOGTHING_ERROR, "Couldn't get keyid");
+                       }
+                       printf("%016" PRIX64, keyid);
                        type = keys->publickey->data[7];
-                       length = (keys->publickey->data[8] << 8) +
-                                       keys->publickey->data[9];
                        break;
                case 4:
-                       (void) get_fingerprint(keys->publickey, fp, &fplength);
+               case 5:
+                       (void) get_fingerprint(keys->publickey, &fingerprint);
 
-                       for (i = 0; i < fplength; i++) {
-                               printf("%02X", fp[i]);
+                       for (i = 0; i < fingerprint.length; i++) {
+                               printf("%02X", fingerprint.fp[i]);
                        }
 
                        type = keys->publickey->data[5];
-                       length = (keys->publickey->data[6] << 8) +
-                                       keys->publickey->data[7];
                        break;
                default:
-                       logthing(LOGTHING_ERROR, "Unknown key type: %d",
+                       logthing(LOGTHING_ERROR, "Unknown key version: %d",
                                keys->publickey->data[0]);
                }
+               length = keylength(keys->publickey);
 
                printf(":%d:%d:%ld::%s\n",
                        type,