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 onak_dbctx *dbctx,
142 struct openpgp_packet_list *sigs, bool html)
148 while (sigs != NULL) {
149 sigid = sig_keyid(sigs->packet);
150 uid = dbctx->keyid2uid(dbctx, sigid);
151 if (sigs->packet->data[0] == 4 &&
152 sigs->packet->data[1] == 0x30) {
153 /* It's a Type 4 sig revocation */
158 if (html && uid != NULL) {
159 printf("%s <a href=\"lookup?op=get&"
160 "search=0x%016" PRIX64 "\">%08" PRIX64
162 "<a href=\"lookup?op=vindex&search=0x%016"
163 PRIX64 "\">%s</a>\n",
169 } else if (html && uid == NULL) {
170 printf("%s %08" PRIX64 " "
171 "[User id not found]\n",
175 printf("%s %08" PRIX64
179 (uid != NULL) ? uid :
180 "[User id not found]");
192 int list_uids(struct onak_dbctx *dbctx,
193 uint64_t keyid, struct openpgp_signedpacket_list *uids,
194 bool verbose, bool html)
199 while (uids != NULL) {
200 if (uids->packet->tag == OPENPGP_PACKET_UID) {
201 snprintf(buf, 1023, "%.*s",
202 (int) uids->packet->length,
205 (html) ? txt2html(buf) : buf);
206 } else if (uids->packet->tag == OPENPGP_PACKET_UAT) {
209 printf("<img src=\"lookup?op=photo&search="
210 "0x%016" PRIX64 "&idx=%d\" alt=\""
216 printf("[photo id]\n");
220 list_sigs(dbctx, uids->sigs, html);
228 int list_subkeys(struct onak_dbctx *dbctx,
229 struct openpgp_signedpacket_list *subkeys, bool verbose,
232 struct tm *created = NULL;
233 time_t created_time = 0;
238 while (subkeys != NULL) {
239 if (subkeys->packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
241 created_time = (subkeys->packet->data[1] << 24) +
242 (subkeys->packet->data[2] << 16) +
243 (subkeys->packet->data[3] << 8) +
244 subkeys->packet->data[4];
245 created = gmtime(&created_time);
247 switch (subkeys->packet->data[0]) {
250 type = subkeys->packet->data[7];
253 type = subkeys->packet->data[5];
256 logthing(LOGTHING_ERROR,
257 "Unknown key type: %d",
258 subkeys->packet->data[0]);
260 length = keylength(subkeys->packet);
262 if (get_packetid(subkeys->packet,
263 &keyid) != ONAK_E_OK) {
264 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
266 printf("sub %5d%c/%08X %04d/%02d/%02d\n",
269 (uint32_t) (keyid & 0xFFFFFFFF),
270 created->tm_year + 1900,
276 list_sigs(dbctx, subkeys->sigs, html);
278 subkeys = subkeys->next;
284 void display_fingerprint(struct openpgp_publickey *key)
287 struct openpgp_fingerprint fingerprint;
289 get_fingerprint(key->publickey, &fingerprint);
290 printf(" Key fingerprint =");
291 for (i = 0; i < fingerprint.length; i++) {
292 if ((fingerprint.length == 16) ||
296 if (fingerprint.length == 20 &&
297 (i * 2) == fingerprint.length) {
298 /* Extra space in the middle of a SHA1 fingerprint */
301 printf("%02X", fingerprint.fp[i]);
308 void display_skshash(struct openpgp_publickey *key, bool html)
313 get_skshash(key, &hash);
314 printf(" Key hash = ");
316 printf("<a href=\"lookup?op=hget&search=");
317 for (i = 0; i < sizeof(hash.hash); i++) {
318 printf("%02X", hash.hash[i]);
322 for (i = 0; i < sizeof(hash.hash); i++) {
323 printf("%02X", hash.hash[i]);
334 * key_index - List a set of OpenPGP keys.
335 * @keys: The keys to display.
336 * @verbose: Should we list sigs as well?
337 * @fingerprint: List the fingerprint?
338 * @html: Should the output be tailored for HTML?
340 * This function takes a list of OpenPGP public keys and displays an index
341 * of them. Useful for debugging or the keyserver Index function.
343 int key_index(struct onak_dbctx *dbctx,
344 struct openpgp_publickey *keys, bool verbose, bool fingerprint,
345 bool skshash, bool html)
347 struct openpgp_signedpacket_list *curuid = NULL;
348 struct tm *created = NULL;
349 time_t created_time = 0;
358 puts("Type bits/keyID Date User ID");
359 while (keys != NULL) {
360 created_time = (keys->publickey->data[1] << 24) +
361 (keys->publickey->data[2] << 16) +
362 (keys->publickey->data[3] << 8) +
363 keys->publickey->data[4];
364 created = gmtime(&created_time);
366 switch (keys->publickey->data[0]) {
369 type = keys->publickey->data[7];
372 type = keys->publickey->data[5];
375 logthing(LOGTHING_ERROR, "Unknown key type: %d",
376 keys->publickey->data[0]);
378 length = keylength(keys->publickey);
380 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
381 logthing(LOGTHING_ERROR, "Couldn't get keyid.");
385 printf("pub %5d%c/<a href=\"lookup?op=get&"
386 "search=0x%016" PRIX64 "\">%08" PRIX64
387 "</a> %04d/%02d/%02d ",
392 created->tm_year + 1900,
396 printf("pub %5d%c/%08" PRIX64 " %04d/%02d/%02d ",
400 created->tm_year + 1900,
406 if (curuid != NULL &&
407 curuid->packet->tag == OPENPGP_PACKET_UID) {
408 snprintf(buf, 1023, "%.*s",
409 (int) curuid->packet->length,
410 curuid->packet->data);
412 printf("<a href=\"lookup?op=vindex&"
413 "search=0x%016" PRIX64 "\">",
417 (html) ? txt2html(buf) : buf,
418 (html) ? "</a>" : "",
419 (keys->revoked) ? " *** REVOKED ***" : "");
421 display_skshash(keys, html);
424 display_fingerprint(keys);
427 list_sigs(dbctx, curuid->sigs, html);
429 curuid = curuid->next;
432 (keys->revoked) ? "*** REVOKED ***": "");
434 display_fingerprint(keys);
438 list_uids(dbctx, keyid, curuid, verbose, html);
440 list_subkeys(dbctx, keys->subkeys, verbose, html);
454 * mrkey_index - List a set of OpenPGP keys in the MRHKP format.
455 * @keys: The keys to display.
457 * This function takes a list of OpenPGP public keys and displays a
458 * machine readable list of them.
460 int mrkey_index(struct openpgp_publickey *keys)
462 struct openpgp_signedpacket_list *curuid = NULL;
463 time_t created_time = 0;
469 struct openpgp_fingerprint fingerprint;
471 while (keys != NULL) {
472 created_time = (keys->publickey->data[1] << 24) +
473 (keys->publickey->data[2] << 16) +
474 (keys->publickey->data[3] << 8) +
475 keys->publickey->data[4];
479 switch (keys->publickey->data[0]) {
482 if (get_keyid(keys, &keyid) != ONAK_E_OK) {
483 logthing(LOGTHING_ERROR, "Couldn't get keyid");
485 printf("%016" PRIX64, keyid);
486 type = keys->publickey->data[7];
489 (void) get_fingerprint(keys->publickey, &fingerprint);
491 for (i = 0; i < fingerprint.length; i++) {
492 printf("%02X", fingerprint.fp[i]);
495 type = keys->publickey->data[5];
498 logthing(LOGTHING_ERROR, "Unknown key type: %d",
499 keys->publickey->data[0]);
501 length = keylength(keys->publickey);
503 printf(":%d:%d:%ld::%s\n",
507 (keys->revoked) ? "r" : "");
509 for (curuid = keys->uids; curuid != NULL;
510 curuid = curuid->next) {
512 if (curuid->packet->tag == OPENPGP_PACKET_UID) {
514 for (i = 0; i < (int) curuid->packet->length;
516 c = curuid->packet->data[i];
520 } else if (c == ':' || c > 127) {