2 * keyindex.c - Routines to list an OpenPGP key.
4 * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include "decodekey.h"
33 #include "keystructs.h"
36 #include "onak-conf.h"
40 * Convert a Public Key algorithm to its single character representation.
42 char pkalgo2char(uint8_t algo)
47 case OPENPGP_PKALGO_DSA:
50 case OPENPGP_PKALGO_ECDSA:
53 case OPENPGP_PKALGO_EC:
56 case OPENPGP_PKALGO_ELGAMAL_SIGN:
59 case OPENPGP_PKALGO_ELGAMAL_ENC:
62 case OPENPGP_PKALGO_RSA:
65 case OPENPGP_PKALGO_RSA_ENC:
68 case OPENPGP_PKALGO_RSA_SIGN:
80 * Given a public key/subkey packet return the key length.
82 unsigned int keylength(struct openpgp_packet *keydata)
86 switch (keydata->data[0]) {
89 length = (keydata->data[8] << 8) +
93 switch (keydata->data[5]) {
94 case OPENPGP_PKALGO_EC:
95 case OPENPGP_PKALGO_ECDSA:
96 /* Elliptic curve key size is based on OID */
97 if ((keydata->data[6] == 8) &&
98 (keydata->data[7] == 0x2A) &&
99 (keydata->data[8] == 0x86) &&
100 (keydata->data[9] == 0x48) &&
101 (keydata->data[10] == 0xCE) &&
102 (keydata->data[11] == 0x3D) &&
103 (keydata->data[12] == 0x03) &&
104 (keydata->data[13] == 0x01) &&
105 (keydata->data[14] == 0x07)) {
107 } else if ((keydata->data[6] == 5) &&
108 (keydata->data[7] == 0x2B) &&
109 (keydata->data[8] == 0x81) &&
110 (keydata->data[9] == 0x04) &&
111 (keydata->data[10] == 0x00) &&
112 (keydata->data[11] == 0x22)) {
114 } else if ((keydata->data[6] == 5) &&
115 (keydata->data[7] == 0x2B) &&
116 (keydata->data[8] == 0x81) &&
117 (keydata->data[9] == 0x04) &&
118 (keydata->data[10] == 0x00) &&
119 (keydata->data[11] == 0x23)) {
122 logthing(LOGTHING_ERROR,
123 "Unknown elliptic curve size");
128 length = (keydata->data[6] << 8) +
133 logthing(LOGTHING_ERROR, "Unknown key version: %d",
141 int list_sigs(struct openpgp_packet_list *sigs, bool html)
147 while (sigs != NULL) {
148 sigid = sig_keyid(sigs->packet);
149 uid = config.dbbackend->keyid2uid(sigid);
150 if (sigs->packet->data[0] == 4 &&
151 sigs->packet->data[1] == 0x30) {
152 /* It's a Type 4 sig revocation */
157 if (html && uid != NULL) {
158 printf("%s <a href=\"lookup?op=get&"
159 "search=0x%016" PRIX64 "\">%08" PRIX64
161 "<a href=\"lookup?op=vindex&search=0x%016"
162 PRIX64 "\">%s</a>\n",
168 } else if (html && uid == NULL) {
169 printf("%s %08" PRIX64 " "
170 "[User id not found]\n",
174 printf("%s %08" PRIX64
178 (uid != NULL) ? uid :
179 "[User id not found]");
191 int list_uids(uint64_t keyid, struct openpgp_signedpacket_list *uids,
192 bool verbose, bool html)
197 while (uids != NULL) {
198 if (uids->packet->tag == OPENPGP_PACKET_UID) {
199 snprintf(buf, 1023, "%.*s",
200 (int) uids->packet->length,
203 (html) ? txt2html(buf) : buf);
204 } else if (uids->packet->tag == OPENPGP_PACKET_UAT) {
207 printf("<img src=\"lookup?op=photo&search="
208 "0x%016" PRIX64 "&idx=%d\" alt=\""
214 printf("[photo id]\n");
218 list_sigs(uids->sigs, html);
226 int list_subkeys(struct openpgp_signedpacket_list *subkeys, bool verbose,
229 struct tm *created = NULL;
230 time_t created_time = 0;
235 while (subkeys != NULL) {
236 if (subkeys->packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
238 created_time = (subkeys->packet->data[1] << 24) +
239 (subkeys->packet->data[2] << 16) +
240 (subkeys->packet->data[3] << 8) +
241 subkeys->packet->data[4];
242 created = gmtime(&created_time);
244 switch (subkeys->packet->data[0]) {
247 type = subkeys->packet->data[7];
250 type = subkeys->packet->data[5];
253 logthing(LOGTHING_ERROR,
254 "Unknown key type: %d",
255 subkeys->packet->data[0]);
257 length = keylength(subkeys->packet);
259 if (get_packetid(subkeys->packet,
260 &keyid) != ONAK_E_OK) {
261 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
263 printf("sub %5d%c/%08X %04d/%02d/%02d\n",
266 (uint32_t) (keyid & 0xFFFFFFFF),
267 created->tm_year + 1900,
273 list_sigs(subkeys->sigs, html);
275 subkeys = subkeys->next;
281 void display_fingerprint(struct openpgp_publickey *key)
285 unsigned char fp[20];
287 get_fingerprint(key->publickey, fp, &length);
288 printf(" Key fingerprint =");
289 for (i = 0; i < length; i++) {
290 if ((length == 16) ||
294 if (length == 20 && (i * 2) == length) {
295 /* Extra space in the middle of a SHA1 fingerprint */
298 printf("%02X", fp[i]);
305 void display_skshash(struct openpgp_publickey *key, bool html)
310 get_skshash(key, &hash);
311 printf(" Key hash = ");
313 printf("<a href=\"lookup?op=hget&search=");
314 for (i = 0; i < sizeof(hash.hash); i++) {
315 printf("%02X", hash.hash[i]);
319 for (i = 0; i < sizeof(hash.hash); i++) {
320 printf("%02X", hash.hash[i]);
331 * key_index - List a set of OpenPGP keys.
332 * @keys: The keys to display.
333 * @verbose: Should we list sigs as well?
334 * @fingerprint: List the fingerprint?
335 * @html: Should the output be tailored for HTML?
337 * This function takes a list of OpenPGP public keys and displays an index
338 * of them. Useful for debugging or the keyserver Index function.
340 int key_index(struct openpgp_publickey *keys, bool verbose, bool fingerprint,
341 bool skshash, bool html)
343 struct openpgp_signedpacket_list *curuid = NULL;
344 struct tm *created = NULL;
345 time_t created_time = 0;
354 puts("Type bits/keyID Date User ID");
355 while (keys != NULL) {
356 created_time = (keys->publickey->data[1] << 24) +
357 (keys->publickey->data[2] << 16) +
358 (keys->publickey->data[3] << 8) +
359 keys->publickey->data[4];
360 created = gmtime(&created_time);
362 switch (keys->publickey->data[0]) {
365 type = keys->publickey->data[7];
368 type = keys->publickey->data[5];
371 logthing(LOGTHING_ERROR, "Unknown key type: %d",
372 keys->publickey->data[0]);
374 length = keylength(keys->publickey);
376 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
377 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
381 printf("pub %5d%c/<a href=\"lookup?op=get&"
382 "search=0x%016" PRIX64 "\">%08" PRIX64
383 "</a> %04d/%02d/%02d ",
388 created->tm_year + 1900,
392 printf("pub %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
396 created->tm_year + 1900,
402 if (curuid != NULL &&
403 curuid->packet->tag == OPENPGP_PACKET_UID) {
404 snprintf(buf, 1023, "%.*s",
405 (int) curuid->packet->length,
406 curuid->packet->data);
408 printf("<a href=\"lookup?op=vindex&"
409 "search=0x%016" PRIX64 "\">",
413 (html) ? txt2html(buf) : buf,
414 (html) ? "</a>" : "",
415 (keys->revoked) ? " *** REVOKED ***" : "");
417 display_skshash(keys, html);
420 display_fingerprint(keys);
423 list_sigs(curuid->sigs, html);
425 curuid = curuid->next;
428 (keys->revoked) ? "*** REVOKED ***": "");
430 display_fingerprint(keys);
434 list_uids(keyid, curuid, verbose, html);
436 list_subkeys(keys->subkeys, verbose, html);
450 * mrkey_index - List a set of OpenPGP keys in the MRHKP format.
451 * @keys: The keys to display.
453 * This function takes a list of OpenPGP public keys and displays a
454 * machine readable list of them.
456 int mrkey_index(struct openpgp_publickey *keys)
458 struct openpgp_signedpacket_list *curuid = NULL;
459 time_t created_time = 0;
464 unsigned char fp[20];
468 while (keys != NULL) {
469 created_time = (keys->publickey->data[1] << 24) +
470 (keys->publickey->data[2] << 16) +
471 (keys->publickey->data[3] << 8) +
472 keys->publickey->data[4];
476 switch (keys->publickey->data[0]) {
479 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
480 logthing(LOGTHING_ERROR, "Couldn't get keyid");
482 printf("%016" PRIX64, keyid);
483 type = keys->publickey->data[7];
486 (void) get_fingerprint(keys->publickey, fp, &fplength);
488 for (i = 0; i < fplength; i++) {
489 printf("%02X", fp[i]);
492 type = keys->publickey->data[5];
495 logthing(LOGTHING_ERROR, "Unknown key type: %d",
496 keys->publickey->data[0]);
498 length = keylength(keys->publickey);
500 printf(":%d:%d:%ld::%s\n",
504 (keys->revoked) ? "r" : "");
506 for (curuid = keys->uids; curuid != NULL;
507 curuid = curuid->next) {
509 if (curuid->packet->tag == OPENPGP_PACKET_UID) {
511 for (i = 0; i < (int) curuid->packet->length;
513 c = curuid->packet->data[i];
517 } else if (c == ':' || c > 127) {