corrected copyright notices
[gnutls.git] / lib / opencdk / keydb.c
blob646904dbe30b29b796c8046bca296238fff949bd
1 /* keydb.c - Key database routines
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz
6 * This file is part of OpenCDK.
8 * The OpenCDK library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
32 #include "opencdk.h"
33 #include "main.h"
34 #include "packet.h"
35 #include "filters.h"
36 #include "stream.h"
37 #include "keydb.h"
39 #define KEYID_CMP(a, b) ((a[0]) == (b[0]) && (a[1]) == (b[1]))
40 #define KEYDB_CACHE_ENTRIES 8
42 static void keydb_cache_free (key_table_t cache);
43 static int classify_data (const byte * buf, size_t len);
44 static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk);
46 static char *
47 keydb_idx_mkname (const char *file)
49 static const char *fmt = "%s.idx";
50 char *fname;
51 size_t len = strlen (file) + strlen (fmt);
53 fname = cdk_calloc (1, len + 1);
54 if (!fname)
55 return NULL;
56 if (snprintf (fname, len, fmt, file) <= 0)
57 return NULL;
58 return fname;
62 /* This functions builds an index of the keyring into a separate file
63 with the name keyring.ext.idx. It contains the offset of all public-
64 and public subkeys. The format of the file is:
65 --------
66 4 octets offset of the packet
67 8 octets keyid
68 20 octets fingerprint
69 --------
70 We store the keyid and the fingerprint due to the fact we can't get
71 the keyid from a v3 fingerprint directly.
73 static cdk_error_t
74 keydb_idx_build (const char *file)
76 cdk_packet_t pkt;
77 cdk_stream_t inp, out = NULL;
78 byte buf[4 + 8 + KEY_FPR_LEN];
79 char *idx_name;
80 u32 keyid[2];
81 cdk_error_t rc;
83 if (!file)
85 gnutls_assert ();
86 return CDK_Inv_Value;
89 rc = cdk_stream_open (file, &inp);
90 if (rc)
92 gnutls_assert ();
93 return rc;
96 idx_name = keydb_idx_mkname (file);
97 if (!idx_name)
99 cdk_stream_close (inp);
100 gnutls_assert ();
101 return CDK_Out_Of_Core;
103 rc = cdk_stream_create (idx_name, &out);
104 cdk_free (idx_name);
105 if (rc)
107 cdk_stream_close (inp);
108 gnutls_assert ();
109 return rc;
112 cdk_pkt_new (&pkt);
113 while (!cdk_stream_eof (inp))
115 off_t pos = cdk_stream_tell (inp);
117 rc = cdk_pkt_read (inp, pkt);
118 if (rc)
120 _cdk_log_debug ("index build failed packet off=%lu\n", (unsigned long)pos);
121 /* FIXME: The index is incomplete */
122 break;
124 if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
125 pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
127 _cdk_u32tobuf (pos, buf);
128 cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
129 _cdk_u32tobuf (keyid[0], buf + 4);
130 _cdk_u32tobuf (keyid[1], buf + 8);
131 cdk_pk_get_fingerprint (pkt->pkt.public_key, buf + 12);
132 cdk_stream_write (out, buf, 4 + 8 + KEY_FPR_LEN);
134 cdk_pkt_free (pkt);
137 cdk_pkt_release (pkt);
139 cdk_stream_close (out);
140 cdk_stream_close (inp);
141 gnutls_assert ();
142 return rc;
147 * cdk_keydb_idx_rebuild:
148 * @hd: key database handle
150 * Rebuild the key index files for the given key database.
152 cdk_error_t
153 cdk_keydb_idx_rebuild (cdk_keydb_hd_t db, cdk_keydb_search_t dbs)
155 struct stat stbuf;
156 char *tmp_idx_name;
157 cdk_error_t rc;
158 int err;
160 if (!db || !db->name || !dbs)
162 gnutls_assert ();
163 return CDK_Inv_Value;
165 if (db->secret)
166 return 0;
168 tmp_idx_name = keydb_idx_mkname (db->name);
169 if (!tmp_idx_name)
171 gnutls_assert ();
172 return CDK_Out_Of_Core;
174 err = stat (tmp_idx_name, &stbuf);
175 cdk_free (tmp_idx_name);
176 /* This function expects an existing index which can be rebuild,
177 if no index exists we do not build one and just return. */
178 if (err)
179 return 0;
181 cdk_stream_close (dbs->idx);
182 dbs->idx = NULL;
183 if (!dbs->idx_name)
185 dbs->idx_name = keydb_idx_mkname (db->name);
186 if (!dbs->idx_name)
188 gnutls_assert ();
189 return CDK_Out_Of_Core;
192 rc = keydb_idx_build (db->name);
193 if (!rc)
194 rc = cdk_stream_open (dbs->idx_name, &dbs->idx);
195 else
196 gnutls_assert ();
197 return rc;
201 static cdk_error_t
202 keydb_idx_parse (cdk_stream_t inp, key_idx_t * r_idx)
204 key_idx_t idx;
205 byte buf[4];
207 if (!inp || !r_idx)
209 gnutls_assert ();
210 return CDK_Inv_Value;
213 idx = cdk_calloc (1, sizeof *idx);
214 if (!idx)
216 gnutls_assert ();
217 return CDK_Out_Of_Core;
220 while (!cdk_stream_eof (inp))
222 if (cdk_stream_read (inp, buf, 4) == CDK_EOF)
223 break;
224 idx->offset = _cdk_buftou32 (buf);
225 cdk_stream_read (inp, buf, 4);
226 idx->keyid[0] = _cdk_buftou32 (buf);
227 cdk_stream_read (inp, buf, 4);
228 idx->keyid[1] = _cdk_buftou32 (buf);
229 cdk_stream_read (inp, idx->fpr, KEY_FPR_LEN);
230 break;
232 *r_idx = idx;
233 return cdk_stream_eof (inp) ? CDK_EOF : 0;
237 static cdk_error_t
238 keydb_idx_search (cdk_stream_t inp, u32 * keyid, const byte * fpr,
239 off_t * r_off)
241 key_idx_t idx;
243 if (!inp || !r_off)
245 gnutls_assert ();
246 return CDK_Inv_Value;
248 if ((keyid && fpr) || (!keyid && !fpr))
250 gnutls_assert ();
251 return CDK_Inv_Mode;
254 /* We need an initialize the offset var with a value
255 because it might be possible the returned offset will
256 be 0 and then we cannot differ between the begin and an EOF. */
257 *r_off = 0xFFFFFFFF;
258 cdk_stream_seek (inp, 0);
259 while (keydb_idx_parse (inp, &idx) != CDK_EOF)
261 if (keyid && KEYID_CMP (keyid, idx->keyid))
263 *r_off = idx->offset;
264 break;
266 else if (fpr && !memcmp (idx->fpr, fpr, KEY_FPR_LEN))
268 *r_off = idx->offset;
269 break;
271 cdk_free (idx);
272 idx = NULL;
274 cdk_free (idx);
275 return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF;
280 * cdk_keydb_new_from_mem:
281 * @r_hd: The keydb output handle.
282 * @secret: does the stream contain secret key data
283 * @armor: the stream is base64
284 * @data: The raw key data.
285 * @datlen: The length of the raw data.
287 * Create a new keyring db handle from the contents of a buffer.
289 cdk_error_t
290 cdk_keydb_new_from_mem (cdk_keydb_hd_t * r_db, int secret, int armor,
291 const void *data, size_t datlen)
293 cdk_keydb_hd_t db;
294 cdk_error_t rc;
296 if (!r_db)
298 gnutls_assert ();
299 return CDK_Inv_Value;
301 *r_db = NULL;
302 db = calloc (1, sizeof *db);
303 rc = cdk_stream_tmp_from_mem (data, datlen, &db->fp);
304 if (!db->fp)
306 cdk_free (db);
307 gnutls_assert ();
308 return rc;
311 if (armor)
312 cdk_stream_set_armor_flag (db->fp, 0);
313 db->type = CDK_DBTYPE_DATA;
314 db->secret = secret;
315 *r_db = db;
316 return 0;
320 * cdk_keydb_free:
321 * @hd: the keydb object
323 * Free the keydb object.
325 void
326 cdk_keydb_free (cdk_keydb_hd_t hd)
328 if (!hd)
329 return;
331 if (hd->name)
333 cdk_free (hd->name);
334 hd->name = NULL;
337 if (hd->fp && !hd->fp_ref)
339 cdk_stream_close (hd->fp);
340 hd->fp = NULL;
344 hd->isopen = 0;
345 hd->secret = 0;
346 cdk_free (hd);
350 static cdk_error_t
351 _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t * ret_kr)
353 cdk_error_t rc;
354 cdk_stream_t kr;
356 if (!hd || !ret_kr)
358 gnutls_assert ();
359 return CDK_Inv_Value;
362 rc = 0;
363 if ((hd->type == CDK_DBTYPE_DATA)
364 && hd->fp)
366 kr = hd->fp;
367 cdk_stream_seek (kr, 0);
369 else if (hd->type == CDK_DBTYPE_PK_KEYRING ||
370 hd->type == CDK_DBTYPE_SK_KEYRING)
372 rc = cdk_stream_open (hd->name, &kr);
374 if (rc)
375 goto leave;
377 else
379 gnutls_assert ();
380 return CDK_Inv_Mode;
383 leave:
385 *ret_kr = kr;
386 return rc;
390 static int
391 find_by_keyid (cdk_kbnode_t knode, cdk_keydb_search_t ks)
393 cdk_kbnode_t node;
394 u32 keyid[2];
396 for (node = knode; node; node = node->next)
398 if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
399 node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
400 node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
401 node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
403 _cdk_pkt_get_keyid (node->pkt, keyid);
404 switch (ks->type)
406 case CDK_DBSEARCH_SHORT_KEYID:
407 if (keyid[1] == ks->u.keyid[1])
408 return 1;
409 break;
411 case CDK_DBSEARCH_KEYID:
412 if (KEYID_CMP (keyid, ks->u.keyid))
413 return 1;
414 break;
416 default:
417 _cdk_log_debug ("find_by_keyid: invalid mode = %d\n", ks->type);
418 return 0;
422 return 0;
426 static int
427 find_by_fpr (cdk_kbnode_t knode, cdk_keydb_search_t ks)
429 cdk_kbnode_t node;
430 byte fpr[KEY_FPR_LEN];
432 if (ks->type != CDK_DBSEARCH_FPR)
433 return 0;
435 for (node = knode; node; node = node->next)
437 if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
438 node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
439 node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
440 node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
442 _cdk_pkt_get_fingerprint (node->pkt, fpr);
443 if (!memcmp (ks->u.fpr, fpr, KEY_FPR_LEN))
444 return 1;
445 break;
449 return 0;
453 static int
454 find_by_pattern (cdk_kbnode_t knode, cdk_keydb_search_t ks)
456 cdk_kbnode_t node;
457 size_t uidlen;
458 char *name;
460 for (node = knode; node; node = node->next)
462 if (node->pkt->pkttype != CDK_PKT_USER_ID)
463 continue;
464 if (node->pkt->pkt.user_id->attrib_img != NULL)
465 continue; /* Skip attribute packets. */
466 uidlen = node->pkt->pkt.user_id->len;
467 name = node->pkt->pkt.user_id->name;
468 switch (ks->type)
470 case CDK_DBSEARCH_EXACT:
471 if (name &&
472 (strlen (ks->u.pattern) == uidlen &&
473 !strncmp (ks->u.pattern, name, uidlen)))
474 return 1;
475 break;
477 case CDK_DBSEARCH_SUBSTR:
478 if (uidlen > 65536)
479 break;
480 if (name && strlen (ks->u.pattern) > uidlen)
481 break;
482 if (name && _cdk_memistr (name, uidlen, ks->u.pattern))
483 return 1;
484 break;
486 default: /* Invalid mode */
487 return 0;
490 return 0;
494 static void
495 keydb_cache_free (key_table_t cache)
497 key_table_t c2;
499 while (cache)
501 c2 = cache->next;
502 cache->offset = 0;
503 cdk_free (cache);
504 cache = c2;
509 static key_table_t
510 keydb_cache_find (cdk_keydb_search_t desc)
512 key_table_t cache = desc->cache;
513 key_table_t t;
515 for (t = cache; t; t = t->next)
517 switch (desc->type)
519 case CDK_DBSEARCH_SHORT_KEYID:
520 case CDK_DBSEARCH_KEYID:
521 if (KEYID_CMP (desc->u.keyid, desc->u.keyid))
522 return t;
523 break;
525 case CDK_DBSEARCH_EXACT:
526 if (strlen (desc->u.pattern) == strlen (desc->u.pattern) &&
527 !strcmp (desc->u.pattern, desc->u.pattern))
528 return t;
529 break;
531 case CDK_DBSEARCH_SUBSTR:
532 if (strstr (desc->u.pattern, desc->u.pattern))
533 return t;
534 break;
536 case CDK_DBSEARCH_FPR:
537 if (!memcmp (desc->u.fpr, desc->u.fpr, KEY_FPR_LEN))
538 return t;
539 break;
543 return NULL;
547 static cdk_error_t
548 keydb_cache_add (cdk_keydb_search_t dbs, off_t offset)
550 key_table_t k;
552 if (dbs->ncache > KEYDB_CACHE_ENTRIES)
553 return 0; /* FIXME: we should replace the last entry. */
554 k = cdk_calloc (1, sizeof *k);
555 if (!k)
557 gnutls_assert ();
558 return CDK_Out_Of_Core;
561 k->offset = offset;
563 k->next = dbs->cache;
564 dbs->cache = k;
565 dbs->ncache++;
566 _cdk_log_debug ("cache: add entry off=%d type=%d\n", (int) offset,
567 (int) dbs->type);
568 return 0;
571 static cdk_error_t
572 idx_init (cdk_keydb_hd_t db, cdk_keydb_search_t dbs)
574 cdk_error_t ec, rc = 0;
576 if (cdk_stream_get_length (db->fp) < 524288)
578 dbs->no_cache = 1;
579 goto leave;
582 dbs->idx_name = keydb_idx_mkname (db->name);
583 if (!dbs->idx_name)
585 rc = CDK_Out_Of_Core;
586 goto leave;
588 ec = cdk_stream_open (dbs->idx_name, &dbs->idx);
590 if (ec && !db->secret)
592 rc = keydb_idx_build (db->name);
593 if (!rc)
594 rc = cdk_stream_open (dbs->idx_name, &dbs->idx);
595 if (!rc)
597 _cdk_log_debug ("create key index table\n");
599 else
601 /* This is no real error, it just means we can't create
602 the index at the given directory. maybe we've no write
603 access. in this case, we simply disable the index. */
604 _cdk_log_debug ("disable key index table err=%d\n", rc);
605 rc = 0;
606 dbs->no_cache = 1;
610 leave:
612 return rc;
616 * cdk_keydb_search_start:
617 * @st: search handle
618 * @db: key database handle
619 * @type: specifies the search type
620 * @desc: description which depends on the type
622 * Create a new keydb search object.
624 cdk_error_t
625 cdk_keydb_search_start (cdk_keydb_search_t * st, cdk_keydb_hd_t db, int type,
626 void *desc)
628 u32 *keyid;
629 char *p, tmp[3];
630 int i;
631 cdk_error_t rc;
633 if (!db)
635 gnutls_assert ();
636 return CDK_Inv_Value;
638 if (type != CDK_DBSEARCH_NEXT && !desc)
640 gnutls_assert ();
641 return CDK_Inv_Mode;
644 *st = cdk_calloc (1, sizeof (cdk_keydb_search_s));
645 if (!(*st))
647 gnutls_assert ();
648 return CDK_Out_Of_Core;
651 rc = idx_init (db, *st);
652 if (rc != CDK_Success)
654 free (*st);
655 gnutls_assert ();
656 return rc;
659 (*st)->type = type;
660 switch (type)
662 case CDK_DBSEARCH_EXACT:
663 case CDK_DBSEARCH_SUBSTR:
664 cdk_free ((*st)->u.pattern);
665 (*st)->u.pattern = cdk_strdup (desc);
666 if (!(*st)->u.pattern)
668 cdk_free (*st);
669 gnutls_assert ();
670 return CDK_Out_Of_Core;
672 break;
674 case CDK_DBSEARCH_SHORT_KEYID:
675 keyid = desc;
676 (*st)->u.keyid[1] = keyid[0];
677 break;
679 case CDK_DBSEARCH_KEYID:
680 keyid = desc;
681 (*st)->u.keyid[0] = keyid[0];
682 (*st)->u.keyid[1] = keyid[1];
683 break;
685 case CDK_DBSEARCH_FPR:
686 memcpy ((*st)->u.fpr, desc, KEY_FPR_LEN);
687 break;
689 case CDK_DBSEARCH_NEXT:
690 break;
692 case CDK_DBSEARCH_AUTO:
693 /* Override the type with the actual db search type. */
694 (*st)->type = classify_data (desc, strlen (desc));
695 switch ((*st)->type)
697 case CDK_DBSEARCH_SUBSTR:
698 case CDK_DBSEARCH_EXACT:
699 cdk_free ((*st)->u.pattern);
700 p = (*st)->u.pattern = cdk_strdup (desc);
701 if (!p)
703 cdk_free (*st);
704 gnutls_assert ();
705 return CDK_Out_Of_Core;
707 break;
709 case CDK_DBSEARCH_SHORT_KEYID:
710 case CDK_DBSEARCH_KEYID:
711 p = desc;
712 if (!strncmp (p, "0x", 2))
713 p += 2;
714 if (strlen (p) == 8)
716 (*st)->u.keyid[0] = 0;
717 (*st)->u.keyid[1] = strtoul (p, NULL, 16);
719 else if (strlen (p) == 16)
721 (*st)->u.keyid[0] = strtoul (p, NULL, 16);
722 (*st)->u.keyid[1] = strtoul (p + 8, NULL, 16);
724 else
725 { /* Invalid key ID object. */
726 cdk_free (*st);
727 gnutls_assert ();
728 return CDK_Inv_Mode;
730 break;
732 case CDK_DBSEARCH_FPR:
733 p = desc;
734 if (strlen (p) != 2 * KEY_FPR_LEN)
736 cdk_free (*st);
737 gnutls_assert ();
738 return CDK_Inv_Mode;
740 for (i = 0; i < KEY_FPR_LEN; i++)
742 tmp[0] = p[2 * i];
743 tmp[1] = p[2 * i + 1];
744 tmp[2] = 0x00;
745 (*st)->u.fpr[i] = strtoul (tmp, NULL, 16);
747 break;
749 break;
751 default:
752 cdk_free (*st);
753 _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type);
754 gnutls_assert ();
755 return CDK_Inv_Mode;
758 return 0;
762 static cdk_error_t
763 keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_keydb_search_t ks,
764 int *r_cache_hit, off_t * r_off)
766 key_table_t c;
768 if (!hd || !r_cache_hit || !r_off)
770 gnutls_assert ();
771 return CDK_Inv_Value;
774 /* Reset the values. */
775 *r_cache_hit = 0;
776 *r_off = 0;
778 c = keydb_cache_find (ks);
779 if (c != NULL)
781 _cdk_log_debug ("cache: found entry in cache.\n");
782 *r_cache_hit = 1;
783 *r_off = c->offset;
784 return 0;
787 /* No index cache available so we just return here. */
788 if (!ks->idx)
789 return 0;
791 if (ks->idx)
793 if (ks->type == CDK_DBSEARCH_KEYID)
795 if (keydb_idx_search (ks->idx, ks->u.keyid, NULL, r_off))
797 gnutls_assert ();
798 return CDK_Error_No_Key;
800 _cdk_log_debug ("cache: found keyid entry in idx table.\n");
801 *r_cache_hit = 1;
803 else if (ks->type == CDK_DBSEARCH_FPR)
805 if (keydb_idx_search (ks->idx, NULL, ks->u.fpr, r_off))
807 gnutls_assert ();
808 return CDK_Error_No_Key;
810 _cdk_log_debug ("cache: found fpr entry in idx table.\n");
811 *r_cache_hit = 1;
815 return 0;
818 void
819 cdk_keydb_search_release (cdk_keydb_search_t st)
821 keydb_cache_free (st->cache);
823 if (st->idx)
824 cdk_stream_close (st->idx);
826 if (!st)
827 return;
828 if (st->type == CDK_DBSEARCH_EXACT || st->type == CDK_DBSEARCH_SUBSTR)
829 cdk_free (st->u.pattern);
831 cdk_free (st);
835 * cdk_keydb_search:
836 * @st: the search handle
837 * @hd: the keydb object
838 * @ret_key: kbnode object to store the key
840 * Search for a key in the given keyring. The search mode is handled
841 * via @ks. If the key was found, @ret_key contains the key data.
843 cdk_error_t
844 cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd,
845 cdk_kbnode_t * ret_key)
847 cdk_stream_t kr;
848 cdk_kbnode_t knode;
849 cdk_error_t rc = 0;
850 off_t pos = 0, off = 0;
851 int key_found = 0, cache_hit = 0;
853 if (!hd || !ret_key || !st)
855 gnutls_assert ();
856 return CDK_Inv_Value;
859 *ret_key = NULL;
860 kr = NULL;
862 rc = _cdk_keydb_open (hd, &kr);
863 if (rc)
865 gnutls_assert ();
866 return rc;
869 if (!st->no_cache)
871 /* It is possible the index is not up-to-date and thus we do
872 not find the requesed key. In this case, we reset cache hit
873 and continue our normal search procedure. */
874 rc = keydb_pos_from_cache (hd, st, &cache_hit, &off);
875 if (rc)
876 cache_hit = 0;
879 knode = NULL;
881 while (!key_found && !rc)
883 if (cache_hit && st->type != CDK_DBSEARCH_NEXT)
884 cdk_stream_seek (kr, off);
885 else if (st->type == CDK_DBSEARCH_NEXT)
886 cdk_stream_seek (kr, st->off);
888 pos = cdk_stream_tell (kr);
890 rc = cdk_keydb_get_keyblock (kr, &knode);
892 if (rc)
894 if (rc == CDK_EOF)
895 break;
896 else
898 gnutls_assert ();
899 return rc;
903 switch (st->type)
905 case CDK_DBSEARCH_SHORT_KEYID:
906 case CDK_DBSEARCH_KEYID:
907 key_found = find_by_keyid (knode, st);
908 break;
910 case CDK_DBSEARCH_FPR:
911 key_found = find_by_fpr (knode, st);
912 break;
914 case CDK_DBSEARCH_EXACT:
915 case CDK_DBSEARCH_SUBSTR:
916 key_found = find_by_pattern (knode, st);
917 break;
919 case CDK_DBSEARCH_NEXT:
920 st->off = cdk_stream_tell (kr);
921 key_found = knode ? 1 : 0;
922 break;
925 if (key_found)
927 if (!keydb_cache_find (st))
928 keydb_cache_add (st, pos);
929 break;
932 cdk_kbnode_release (knode);
933 knode = NULL;
936 if (key_found && rc == CDK_EOF)
937 rc = 0;
938 else if (rc == CDK_EOF && !key_found)
940 gnutls_assert ();
941 rc = CDK_Error_No_Key;
943 *ret_key = key_found ? knode : NULL;
944 return rc;
947 cdk_error_t
948 cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, u32 * keyid, cdk_kbnode_t * ret_key)
950 cdk_error_t rc;
951 cdk_keydb_search_t st;
953 if (!hd || !keyid || !ret_key)
955 gnutls_assert ();
956 return CDK_Inv_Value;
959 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
960 if (!rc)
961 rc = cdk_keydb_search (st, hd, ret_key);
963 cdk_keydb_search_release (st);
964 return rc;
968 cdk_error_t
969 cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const byte * fpr,
970 cdk_kbnode_t * r_key)
972 cdk_error_t rc;
973 cdk_keydb_search_t st;
975 if (!hd || !fpr || !r_key)
977 gnutls_assert ();
978 return CDK_Inv_Value;
981 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_FPR, (byte *) fpr);
982 if (!rc)
983 rc = cdk_keydb_search (st, hd, r_key);
985 cdk_keydb_search_release (st);
986 return rc;
990 cdk_error_t
991 cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt,
992 cdk_kbnode_t * ret_key)
994 cdk_error_t rc;
995 cdk_keydb_search_t st;
997 if (!hd || !patt || !ret_key)
999 gnutls_assert ();
1000 return CDK_Inv_Value;
1003 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_SUBSTR, (char *) patt);
1004 if (!rc)
1005 rc = cdk_keydb_search (st, hd, ret_key);
1007 if (rc)
1008 gnutls_assert ();
1010 cdk_keydb_search_release (st);
1011 return rc;
1015 static int
1016 keydb_check_key (cdk_packet_t pkt)
1018 cdk_pkt_pubkey_t pk;
1019 int is_sk, valid;
1021 if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1022 pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1024 pk = pkt->pkt.public_key;
1025 is_sk = 0;
1027 else if (pkt->pkttype == CDK_PKT_SECRET_KEY ||
1028 pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1030 pk = pkt->pkt.secret_key->pk;
1031 is_sk = 1;
1033 else /* No key object. */
1034 return 0;
1035 valid = !pk->is_revoked && !pk->has_expired;
1036 if (is_sk)
1037 return valid;
1038 return valid && !pk->is_invalid;
1042 /* Find the first kbnode with the requested packet type
1043 that represents a valid key. */
1044 static cdk_kbnode_t
1045 kbnode_find_valid (cdk_kbnode_t root, cdk_packet_type_t pkttype)
1047 cdk_kbnode_t n;
1049 for (n = root; n; n = n->next)
1051 if (n->pkt->pkttype != pkttype)
1052 continue;
1053 if (keydb_check_key (n->pkt))
1054 return n;
1057 return NULL;
1061 static cdk_kbnode_t
1062 keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk)
1064 cdk_kbnode_t node, key;
1065 int req_type;
1066 long timestamp;
1068 req_type = is_pk ? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY;
1069 if (!req_usage)
1070 return kbnode_find_valid (root, req_type);
1072 node = cdk_kbnode_find (root, req_type);
1073 if (node && !keydb_check_key (node->pkt))
1074 return NULL;
1076 key = NULL;
1077 timestamp = 0;
1078 /* We iteratre over the all nodes and search for keys or
1079 subkeys which match the usage and which are not invalid.
1080 A timestamp is used to figure out the newest valid key. */
1081 for (node = root; node; node = node->next)
1083 if (is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1084 node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1085 && keydb_check_key (node->pkt)
1086 && (node->pkt->pkt.public_key->pubkey_usage & req_usage))
1088 if (node->pkt->pkt.public_key->timestamp > timestamp)
1089 key = node;
1091 if (!is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY ||
1092 node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1093 && keydb_check_key (node->pkt)
1094 && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage))
1096 if (node->pkt->pkt.secret_key->pk->timestamp > timestamp)
1097 key = node;
1101 return key;
1105 static cdk_kbnode_t
1106 keydb_find_bykeyid (cdk_kbnode_t root, const u32 * keyid, int search_mode)
1108 cdk_kbnode_t node;
1109 u32 kid[2];
1111 for (node = root; node; node = node->next)
1113 if (!_cdk_pkt_get_keyid (node->pkt, kid))
1114 continue;
1115 if (search_mode == CDK_DBSEARCH_SHORT_KEYID && kid[1] == keyid[1])
1116 return node;
1117 else if (kid[0] == keyid[0] && kid[1] == keyid[1])
1118 return node;
1120 return NULL;
1124 cdk_error_t
1125 _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name,
1126 cdk_seckey_t * ret_sk, int usage)
1128 cdk_kbnode_t knode = NULL;
1129 cdk_kbnode_t node, sk_node, pk_node;
1130 cdk_pkt_seckey_t sk;
1131 cdk_error_t rc;
1132 const char *s;
1133 int pkttype;
1134 cdk_keydb_search_t st;
1136 if (!ret_sk || !usage)
1138 gnutls_assert ();
1139 return CDK_Inv_Value;
1142 if (!hd)
1144 gnutls_assert ();
1145 return CDK_Error_No_Keyring;
1148 *ret_sk = NULL;
1149 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name);
1150 if (rc)
1152 gnutls_assert ();
1153 return rc;
1156 rc = cdk_keydb_search (st, hd, &knode);
1157 if (rc)
1159 gnutls_assert ();
1160 return rc;
1163 cdk_keydb_search_release (st);
1165 sk_node = keydb_find_byusage (knode, usage, 0);
1166 if (!sk_node)
1168 cdk_kbnode_release (knode);
1169 gnutls_assert ();
1170 return CDK_Unusable_Key;
1173 /* We clone the node with the secret key to avoid that the
1174 packet will be released. */
1175 _cdk_kbnode_clone (sk_node);
1176 sk = sk_node->pkt->pkt.secret_key;
1178 for (node = knode; node; node = node->next)
1180 if (node->pkt->pkttype == CDK_PKT_USER_ID)
1182 s = node->pkt->pkt.user_id->name;
1183 if (sk && !sk->pk->uid && _cdk_memistr (s, strlen (s), name))
1185 _cdk_copy_userid (&sk->pk->uid, node->pkt->pkt.user_id);
1186 break;
1191 /* To find the self signature, we need the primary public key because
1192 the selected secret key might be different from the primary key. */
1193 pk_node = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
1194 if (!pk_node)
1196 cdk_kbnode_release (knode);
1197 gnutls_assert ();
1198 return CDK_Unusable_Key;
1200 node = find_selfsig_node (knode, pk_node->pkt->pkt.secret_key->pk);
1201 if (sk && sk->pk && sk->pk->uid && node)
1202 _cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature);
1204 /* We only release the outer packet. */
1205 _cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void *) &sk);
1206 cdk_kbnode_release (knode);
1207 *ret_sk = sk;
1208 return rc;
1212 cdk_error_t
1213 _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name,
1214 cdk_pubkey_t * ret_pk, int usage)
1216 cdk_kbnode_t knode, node, pk_node;
1217 cdk_pkt_pubkey_t pk;
1218 const char *s;
1219 cdk_error_t rc;
1220 cdk_keydb_search_t st;
1222 if (!ret_pk || !usage)
1224 gnutls_assert ();
1225 return CDK_Inv_Value;
1227 if (!hd)
1229 gnutls_assert ();
1230 return CDK_Error_No_Keyring;
1233 *ret_pk = NULL;
1234 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, (char *) name);
1235 if (!rc)
1236 rc = cdk_keydb_search (st, hd, &knode);
1237 if (rc)
1239 gnutls_assert ();
1240 return rc;
1243 cdk_keydb_search_release (st);
1245 node = keydb_find_byusage (knode, usage, 1);
1246 if (!node)
1248 cdk_kbnode_release (knode);
1249 gnutls_assert ();
1250 return CDK_Unusable_Key;
1253 pk = NULL;
1254 _cdk_copy_pubkey (&pk, node->pkt->pkt.public_key);
1255 for (node = knode; node; node = node->next)
1257 if (node->pkt->pkttype == CDK_PKT_USER_ID)
1259 s = node->pkt->pkt.user_id->name;
1260 if (pk && !pk->uid && _cdk_memistr (s, strlen (s), name))
1262 _cdk_copy_userid (&pk->uid, node->pkt->pkt.user_id);
1263 break;
1268 /* Same as in the sk code, the selected key can be a sub key
1269 and thus we need the primary key to find the self sig. */
1270 pk_node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1271 if (!pk_node)
1273 cdk_kbnode_release (knode);
1274 gnutls_assert ();
1275 return CDK_Unusable_Key;
1277 node = find_selfsig_node (knode, pk_node->pkt->pkt.public_key);
1278 if (pk && pk->uid && node)
1279 _cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature);
1280 cdk_kbnode_release (knode);
1282 *ret_pk = pk;
1283 return rc;
1288 * cdk_keydb_get_pk:
1289 * @hd: key db handle
1290 * @keyid: keyid of the key
1291 * @r_pk: the allocated public key
1293 * Perform a key database search by keyid and return the raw public
1294 * key without any signatures or user id's.
1296 cdk_error_t
1297 cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 * keyid, cdk_pubkey_t * r_pk)
1299 cdk_kbnode_t knode = NULL, node;
1300 cdk_pubkey_t pk;
1301 cdk_error_t rc;
1302 size_t s_type;
1303 int pkttype;
1304 cdk_keydb_search_t st;
1306 if (!keyid || !r_pk)
1308 gnutls_assert ();
1309 return CDK_Inv_Value;
1311 if (!hd)
1313 gnutls_assert ();
1314 return CDK_Error_No_Keyring;
1317 *r_pk = NULL;
1318 s_type = !keyid[0] ? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID;
1319 rc = cdk_keydb_search_start (&st, hd, s_type, keyid);
1320 if (rc)
1322 gnutls_assert ();
1323 return rc;
1325 rc = cdk_keydb_search (st, hd, &knode);
1326 cdk_keydb_search_release (st);
1327 if (rc)
1329 gnutls_assert ();
1330 return rc;
1333 node = keydb_find_bykeyid (knode, keyid, s_type);
1334 if (!node)
1336 cdk_kbnode_release (knode);
1337 gnutls_assert ();
1338 return CDK_Error_No_Key;
1341 /* See comment in cdk_keydb_get_sk() */
1342 _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &pk);
1343 *r_pk = pk;
1344 _cdk_kbnode_clone (node);
1345 cdk_kbnode_release (knode);
1347 return rc;
1352 * cdk_keydb_get_sk:
1353 * @hd: key db handle
1354 * @keyid: the keyid of the key
1355 * @ret_sk: the allocated secret key
1357 * Perform a key database search by keyid and return
1358 * only the raw secret key without the additional nodes,
1359 * like the user id or the signatures.
1361 cdk_error_t
1362 cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 * keyid, cdk_seckey_t * ret_sk)
1364 cdk_kbnode_t snode, node;
1365 cdk_seckey_t sk;
1366 cdk_error_t rc;
1367 int pkttype;
1369 if (!keyid || !ret_sk)
1371 gnutls_assert ();
1372 return CDK_Inv_Value;
1374 if (!hd)
1376 gnutls_assert ();
1377 return CDK_Error_No_Keyring;
1380 *ret_sk = NULL;
1381 rc = cdk_keydb_get_bykeyid (hd, keyid, &snode);
1382 if (rc)
1384 gnutls_assert ();
1385 return rc;
1388 node = keydb_find_bykeyid (snode, keyid, CDK_DBSEARCH_KEYID);
1389 if (!node)
1391 cdk_kbnode_release (snode);
1392 gnutls_assert ();
1393 return CDK_Error_No_Key;
1396 /* We need to release the packet itself but not its contents
1397 and thus we detach the openpgp packet and release the structure. */
1398 _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &sk);
1399 _cdk_kbnode_clone (node);
1400 cdk_kbnode_release (snode);
1402 *ret_sk = sk;
1403 return 0;
1407 static int
1408 is_selfsig (cdk_kbnode_t node, const u32 * keyid)
1410 cdk_pkt_signature_t sig;
1412 if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
1413 return 0;
1414 sig = node->pkt->pkt.signature;
1415 if ((sig->sig_class >= 0x10 && sig->sig_class <= 0x13) &&
1416 sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1])
1417 return 1;
1419 return 0;
1423 /* Find the newest self signature for the public key @pk
1424 and return the signature node. */
1425 static cdk_kbnode_t
1426 find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk)
1428 cdk_kbnode_t n, sig;
1429 unsigned int ts;
1430 u32 keyid[2];
1432 cdk_pk_get_keyid (pk, keyid);
1433 sig = NULL;
1434 ts = 0;
1435 for (n = key; n; n = n->next)
1437 if (is_selfsig (n, keyid) && n->pkt->pkt.signature->timestamp > ts)
1439 ts = n->pkt->pkt.signature->timestamp;
1440 sig = n;
1444 return sig;
1447 static unsigned int
1448 key_usage_to_cdk_usage (unsigned int usage)
1450 unsigned key_usage = 0;
1452 if (usage & 0x01) /* cert + sign data */
1453 key_usage |= CDK_KEY_USG_CERT_SIGN;
1454 if (usage & 0x02) /* cert + sign data */
1455 key_usage |= CDK_KEY_USG_DATA_SIGN;
1456 if (usage & 0x04) /* encrypt comm. + storage */
1457 key_usage |= CDK_KEY_USG_COMM_ENCR;
1458 if (usage & 0x08) /* encrypt comm. + storage */
1459 key_usage |= CDK_KEY_USG_STORAGE_ENCR;
1460 if (usage & 0x10) /* encrypt comm. + storage */
1461 key_usage |= CDK_KEY_USG_SPLIT_KEY;
1462 if (usage & 0x20)
1463 key_usage |= CDK_KEY_USG_AUTH;
1464 if (usage & 0x80) /* encrypt comm. + storage */
1465 key_usage |= CDK_KEY_USG_SHARED_KEY;
1467 return key_usage;
1470 static cdk_error_t
1471 keydb_merge_selfsig (cdk_kbnode_t key, u32 * keyid)
1473 cdk_kbnode_t node, kbnode, unode;
1474 cdk_subpkt_t s = NULL;
1475 cdk_pkt_signature_t sig = NULL;
1476 cdk_pkt_userid_t uid = NULL;
1477 const byte *symalg = NULL, *hashalg = NULL, *compalg = NULL;
1478 size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0;
1479 size_t key_expire = 0;
1481 if (!key)
1483 gnutls_assert ();
1484 return CDK_Inv_Value;
1487 for (node = key; node; node = node->next)
1489 if (!is_selfsig (node, keyid))
1490 continue;
1491 unode = cdk_kbnode_find_prev (key, node, CDK_PKT_USER_ID);
1492 if (!unode)
1494 gnutls_assert ();
1495 return CDK_Error_No_Key;
1497 uid = unode->pkt->pkt.user_id;
1498 sig = node->pkt->pkt.signature;
1499 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID);
1500 if (s)
1501 uid->is_primary = 1;
1502 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_FEATURES);
1503 if (s && s->size == 1 && s->d[0] & 0x01)
1504 uid->mdc_feature = 1;
1505 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE);
1506 if (s && s->size == 4)
1507 key_expire = _cdk_buftou32 (s->d);
1508 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM);
1509 if (s)
1511 symalg = s->d;
1512 nsymalg = s->size;
1513 n += s->size + 1;
1515 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_HASH);
1516 if (s)
1518 hashalg = s->d;
1519 nhashalg = s->size;
1520 n += s->size + 1;
1522 s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP);
1523 if (s)
1525 compalg = s->d;
1526 ncompalg = s->size;
1527 n += s->size + 1;
1529 if (uid->prefs != NULL)
1530 cdk_free (uid->prefs);
1531 if (!n || !hashalg || !compalg || !symalg)
1532 uid->prefs = NULL;
1533 else
1535 uid->prefs = cdk_calloc (1, sizeof (*uid->prefs) * (n + 1));
1536 if (!uid->prefs)
1538 gnutls_assert ();
1539 return CDK_Out_Of_Core;
1541 n = 0;
1542 for (; nsymalg; nsymalg--, n++)
1544 uid->prefs[n].type = CDK_PREFTYPE_SYM;
1545 uid->prefs[n].value = *symalg++;
1547 for (; nhashalg; nhashalg--, n++)
1549 uid->prefs[n].type = CDK_PREFTYPE_HASH;
1550 uid->prefs[n].value = *hashalg++;
1552 for (; ncompalg; ncompalg--, n++)
1554 uid->prefs[n].type = CDK_PREFTYPE_ZIP;
1555 uid->prefs[n].value = *compalg++;
1558 uid->prefs[n].type = CDK_PREFTYPE_NONE; /* end of list marker */
1559 uid->prefs[n].value = 0;
1560 uid->prefs_size = n;
1564 /* Now we add the extracted information to the primary key. */
1565 kbnode = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY);
1566 if (kbnode)
1568 cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key;
1569 if (uid && uid->prefs && n)
1571 if (pk->prefs != NULL)
1572 cdk_free (pk->prefs);
1573 pk->prefs = _cdk_copy_prefs (uid->prefs);
1574 pk->prefs_size = n;
1576 if (key_expire)
1578 pk->expiredate = pk->timestamp + key_expire;
1579 pk->has_expired = pk->expiredate > (u32) gnutls_time (NULL) ? 0 : 1;
1582 pk->is_invalid = 0;
1585 return 0;
1589 static cdk_error_t
1590 keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check)
1592 cdk_kbnode_t node, kb;
1593 cdk_pkt_signature_t sig;
1594 cdk_pkt_pubkey_t pk;
1595 cdk_subpkt_t s = NULL;
1596 u32 expiredate = 0, curtime = (u32) gnutls_time (NULL);
1597 u32 keyid[2];
1599 if (!knode)
1601 gnutls_assert ();
1602 return CDK_Inv_Value;
1604 if (check && !hd)
1606 gnutls_assert ();
1607 return CDK_Inv_Mode;
1610 kb = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY);
1611 if (kb)
1612 return 0;
1614 /* Reset */
1615 for (node = knode; node; node = node->next)
1617 if (node->pkt->pkttype == CDK_PKT_USER_ID)
1618 node->pkt->pkt.user_id->is_revoked = 0;
1619 else if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1620 node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1621 node->pkt->pkt.public_key->is_revoked = 0;
1624 kb = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1625 if (!kb)
1627 gnutls_assert ();
1628 return CDK_Wrong_Format;
1630 cdk_pk_get_keyid (kb->pkt->pkt.public_key, keyid);
1632 for (node = knode; node; node = node->next)
1634 if (node->pkt->pkttype == CDK_PKT_SIGNATURE)
1636 sig = node->pkt->pkt.signature;
1637 /* Revocation certificates for primary keys */
1638 if (sig->sig_class == 0x20)
1640 kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
1641 if (kb)
1643 kb->pkt->pkt.public_key->is_revoked = 1;
1644 if (check)
1645 _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1647 else
1649 gnutls_assert ();
1650 return CDK_Error_No_Key;
1653 /* Revocation certificates for subkeys */
1654 else if (sig->sig_class == 0x28)
1656 kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
1657 if (kb)
1659 kb->pkt->pkt.public_key->is_revoked = 1;
1660 if (check)
1661 _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1663 else
1665 gnutls_assert ();
1666 return CDK_Error_No_Key;
1669 /* Revocation certifcates for user ID's */
1670 else if (sig->sig_class == 0x30)
1672 if (sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1])
1673 continue; /* revokes an earlier signature, no userID. */
1674 kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID);
1675 if (kb)
1677 kb->pkt->pkt.user_id->is_revoked = 1;
1678 if (check)
1679 _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1681 else
1683 gnutls_assert ();
1684 return CDK_Error_No_Key;
1687 /* Direct certificates for primary keys */
1688 else if (sig->sig_class == 0x1F)
1690 kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY);
1691 if (kb)
1693 pk = kb->pkt->pkt.public_key;
1694 pk->is_invalid = 0;
1695 s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
1696 CDK_SIGSUBPKT_KEY_EXPIRE);
1697 if (s)
1699 expiredate = _cdk_buftou32 (s->d);
1700 pk->expiredate = pk->timestamp + expiredate;
1701 pk->has_expired = pk->expiredate > curtime ? 0 : 1;
1703 if (check)
1704 _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1706 else
1708 gnutls_assert ();
1709 return CDK_Error_No_Key;
1712 /* Direct certificates for subkeys */
1713 else if (sig->sig_class == 0x18)
1715 kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY);
1716 if (kb)
1718 pk = kb->pkt->pkt.public_key;
1719 pk->is_invalid = 0;
1720 s = cdk_subpkt_find (node->pkt->pkt.signature->hashed,
1721 CDK_SIGSUBPKT_KEY_EXPIRE);
1722 if (s)
1724 expiredate = _cdk_buftou32 (s->d);
1725 pk->expiredate = pk->timestamp + expiredate;
1726 pk->has_expired = pk->expiredate > curtime ? 0 : 1;
1728 if (check)
1729 _cdk_pk_check_sig (hd, kb, node, NULL, NULL);
1731 else
1733 gnutls_assert ();
1734 return CDK_Error_No_Key;
1739 node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1740 if (node && node->pkt->pkt.public_key->version == 3)
1742 /* v3 public keys have no additonal signatures for the key directly.
1743 we say the key is valid when we have at least a self signature. */
1744 pk = node->pkt->pkt.public_key;
1745 for (node = knode; node; node = node->next)
1747 if (is_selfsig (node, keyid))
1749 pk->is_invalid = 0;
1750 break;
1754 if (node && (node->pkt->pkt.public_key->is_revoked ||
1755 node->pkt->pkt.public_key->has_expired))
1757 /* If the primary key has been revoked, mark all subkeys as invalid
1758 because without a primary key they are not useable */
1759 for (node = knode; node; node = node->next)
1761 if (node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1762 node->pkt->pkt.public_key->is_invalid = 1;
1766 return 0;
1769 static void
1770 add_key_usage (cdk_kbnode_t knode, u32 keyid[2], unsigned int usage)
1772 cdk_kbnode_t p, ctx;
1773 cdk_packet_t pkt;
1775 ctx = NULL;
1776 while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
1778 pkt = cdk_kbnode_get_packet (p);
1779 if ((pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY
1780 || pkt->pkttype == CDK_PKT_PUBLIC_KEY)
1781 && pkt->pkt.public_key->keyid[0] == keyid[0]
1782 && pkt->pkt.public_key->keyid[1] == keyid[1])
1784 pkt->pkt.public_key->pubkey_usage = usage;
1785 return;
1788 return;
1791 cdk_error_t
1792 cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * r_knode)
1794 cdk_packet_t pkt;
1795 cdk_kbnode_t knode, node;
1796 cdk_desig_revoker_t revkeys;
1797 cdk_error_t rc;
1798 u32 keyid[2], main_keyid[2];
1799 off_t old_off;
1800 int key_seen, got_key;
1802 if (!inp || !r_knode)
1804 gnutls_assert ();
1805 return CDK_Inv_Value;
1808 /* Reset all values. */
1809 keyid[0] = keyid[1] = 0;
1810 main_keyid[0] = main_keyid[1] = 0;
1811 revkeys = NULL;
1812 knode = NULL;
1813 key_seen = got_key = 0;
1815 *r_knode = NULL;
1816 rc = CDK_EOF;
1817 while (!cdk_stream_eof (inp))
1819 cdk_pkt_new (&pkt);
1820 old_off = cdk_stream_tell (inp);
1821 rc = cdk_pkt_read (inp, pkt);
1822 if (rc)
1824 cdk_pkt_release (pkt);
1825 if (rc == CDK_EOF)
1826 break;
1827 else
1828 { /* Release all packets we reached so far. */
1829 _cdk_log_debug ("keydb_get_keyblock: error %d\n", rc);
1830 cdk_kbnode_release (knode);
1831 gnutls_assert ();
1832 return rc;
1836 if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1837 pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
1838 pkt->pkttype == CDK_PKT_SECRET_KEY ||
1839 pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1841 if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1842 pkt->pkttype == CDK_PKT_SECRET_KEY))
1844 /* The next key starts here so set the file pointer
1845 and leave the loop. */
1846 cdk_stream_seek (inp, old_off);
1847 cdk_pkt_release (pkt);
1848 break;
1850 if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
1851 pkt->pkttype == CDK_PKT_SECRET_KEY)
1853 _cdk_pkt_get_keyid (pkt, main_keyid);
1854 key_seen = 1;
1856 else if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ||
1857 pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
1859 if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
1861 pkt->pkt.public_key->main_keyid[0] = main_keyid[0];
1862 pkt->pkt.public_key->main_keyid[1] = main_keyid[1];
1864 else
1866 pkt->pkt.secret_key->main_keyid[0] = main_keyid[0];
1867 pkt->pkt.secret_key->main_keyid[1] = main_keyid[1];
1870 /* We save this for the signature */
1871 _cdk_pkt_get_keyid (pkt, keyid);
1872 got_key = 1;
1874 else if (pkt->pkttype == CDK_PKT_USER_ID)
1876 else if (pkt->pkttype == CDK_PKT_SIGNATURE)
1878 cdk_subpkt_t s;
1880 pkt->pkt.signature->key[0] = keyid[0];
1881 pkt->pkt.signature->key[1] = keyid[1];
1882 if (pkt->pkt.signature->sig_class == 0x1F &&
1883 pkt->pkt.signature->revkeys)
1884 revkeys = pkt->pkt.signature->revkeys;
1887 cdk_subpkt_find (pkt->pkt.signature->hashed,
1888 CDK_SIGSUBPKT_KEY_FLAGS);
1889 if (s)
1891 unsigned int key_usage = key_usage_to_cdk_usage (s->d[0]);
1892 add_key_usage (knode, pkt->pkt.signature->key, key_usage);
1895 node = cdk_kbnode_new (pkt);
1896 if (!knode)
1897 knode = node;
1898 else
1899 _cdk_kbnode_add (knode, node);
1902 if (got_key)
1904 keydb_merge_selfsig (knode, main_keyid);
1905 rc = keydb_parse_allsigs (knode, NULL, 0);
1906 if (revkeys)
1908 node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
1909 if (node)
1910 node->pkt->pkt.public_key->revkeys = revkeys;
1913 else
1914 cdk_kbnode_release (knode);
1915 *r_knode = got_key ? knode : NULL;
1917 /* It is possible that we are in an EOF condition after we
1918 successfully read a keyblock. For example if the requested
1919 key is the last in the file. */
1920 if (rc == CDK_EOF && got_key)
1921 rc = 0;
1922 return rc;
1926 /* Return the type of the given data. In case it cannot be classified,
1927 a substring search will be performed. */
1928 static int
1929 classify_data (const byte * buf, size_t len)
1931 int type;
1932 unsigned int i;
1934 if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X'))
1935 { /* Skip hex prefix. */
1936 buf += 2;
1937 len -= 2;
1940 /* The length of the data does not match either a keyid or a fingerprint. */
1941 if (len != 8 && len != 16 && len != 40)
1942 return CDK_DBSEARCH_SUBSTR;
1944 for (i = 0; i < len; i++)
1946 if (!isxdigit (buf[i]))
1947 return CDK_DBSEARCH_SUBSTR;
1949 if (i != len)
1950 return CDK_DBSEARCH_SUBSTR;
1951 switch (len)
1953 case 8:
1954 type = CDK_DBSEARCH_SHORT_KEYID;
1955 break;
1956 case 16:
1957 type = CDK_DBSEARCH_KEYID;
1958 break;
1959 case 40:
1960 type = CDK_DBSEARCH_FPR;
1961 break;
1962 default:
1963 type = CDK_DBSEARCH_SUBSTR;
1964 break;
1967 return type;
1972 * cdk_keydb_export:
1973 * @hd: the keydb handle
1974 * @out: the output stream
1975 * @remusr: the list of key pattern to export
1977 * Export a list of keys to the given output stream.
1978 * Use string list with names for pattering searching.
1979 * This procedure strips local signatures.
1981 cdk_error_t
1982 cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr)
1984 cdk_kbnode_t knode, node;
1985 cdk_strlist_t r;
1986 cdk_error_t rc;
1987 int old_ctb;
1988 cdk_keydb_search_t st;
1990 for (r = remusr; r; r = r->next)
1992 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_AUTO, r->d);
1993 if (rc)
1995 gnutls_assert ();
1996 return rc;
1998 rc = cdk_keydb_search (st, hd, &knode);
1999 cdk_keydb_search_release (st);
2001 if (rc)
2003 gnutls_assert ();
2004 return rc;
2007 node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
2008 if (!node)
2010 gnutls_assert ();
2011 return CDK_Error_No_Key;
2014 /* If the key is a version 3 key, use the old packet
2015 format for the output. */
2016 if (node->pkt->pkt.public_key->version == 3)
2017 old_ctb = 1;
2018 else
2019 old_ctb = 0;
2021 for (node = knode; node; node = node->next)
2023 /* No specified format; skip them */
2024 if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
2025 continue;
2026 /* We never export local signed signatures */
2027 if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2028 !node->pkt->pkt.signature->flags.exportable)
2029 continue;
2030 /* Filter out invalid signatures */
2031 if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2032 (!KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo)))
2033 continue;
2035 /* Adjust the ctb flag if needed. */
2036 node->pkt->old_ctb = old_ctb;
2037 rc = cdk_pkt_write (out, node->pkt);
2038 if (rc)
2040 cdk_kbnode_release (knode);
2041 gnutls_assert ();
2042 return rc;
2045 cdk_kbnode_release (knode);
2046 knode = NULL;
2048 return 0;
2052 static cdk_packet_t
2053 find_key_packet (cdk_kbnode_t knode, int *r_is_sk)
2055 cdk_packet_t pkt;
2057 pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY);
2058 if (!pkt)
2060 pkt = cdk_kbnode_find_packet (knode, CDK_PKT_SECRET_KEY);
2061 if (r_is_sk)
2062 *r_is_sk = pkt ? 1 : 0;
2064 return pkt;
2068 /* Return 1 if the is allowd in a key node. */
2069 static int
2070 is_key_node (cdk_kbnode_t node)
2072 switch (node->pkt->pkttype)
2074 case CDK_PKT_SIGNATURE:
2075 case CDK_PKT_SECRET_KEY:
2076 case CDK_PKT_PUBLIC_KEY:
2077 case CDK_PKT_SECRET_SUBKEY:
2078 case CDK_PKT_PUBLIC_SUBKEY:
2079 case CDK_PKT_USER_ID:
2080 case CDK_PKT_ATTRIBUTE:
2081 return 1;
2083 default:
2084 return 0;
2087 return 0;
2091 cdk_error_t
2092 cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode)
2094 cdk_kbnode_t node, chk;
2095 cdk_packet_t pkt;
2096 cdk_stream_t out;
2097 cdk_error_t rc;
2098 u32 keyid[2];
2100 if (!hd || !knode)
2102 gnutls_assert ();
2103 return CDK_Inv_Value;
2106 pkt = find_key_packet (knode, NULL);
2107 if (!pkt)
2109 gnutls_assert ();
2110 return CDK_Inv_Packet;
2113 _cdk_pkt_get_keyid (pkt, keyid);
2114 chk = NULL;
2115 cdk_keydb_get_bykeyid (hd, keyid, &chk);
2116 if (chk)
2117 { /* FIXME: search for new signatures */
2118 cdk_kbnode_release (chk);
2119 return 0;
2122 /* We append data to the stream so we need to close
2123 the stream here to re-open it later. */
2124 if (hd->fp)
2126 cdk_stream_close (hd->fp);
2127 hd->fp = NULL;
2130 rc = _cdk_stream_append (hd->name, &out);
2131 if (rc)
2133 gnutls_assert ();
2134 return rc;
2137 for (node = knode; node; node = node->next)
2139 if (node->pkt->pkttype == CDK_PKT_RING_TRUST)
2140 continue; /* No uniformed syntax for this packet */
2141 if (node->pkt->pkttype == CDK_PKT_SIGNATURE &&
2142 !node->pkt->pkt.signature->flags.exportable)
2144 _cdk_log_debug ("key db import: skip local signature\n");
2145 continue;
2148 if (!is_key_node (node))
2150 _cdk_log_debug ("key db import: skip invalid node of type %d\n",
2151 node->pkt->pkttype);
2152 continue;
2155 rc = cdk_pkt_write (out, node->pkt);
2156 if (rc)
2158 cdk_stream_close (out);
2159 gnutls_assert ();
2160 return rc;
2164 cdk_stream_close (out);
2165 hd->stats.new_keys++;
2167 return 0;
2171 cdk_error_t
2172 _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id)
2174 cdk_kbnode_t knode = NULL, unode = NULL;
2175 cdk_error_t rc;
2176 int check;
2177 cdk_keydb_search_t st;
2179 if (!hd)
2181 gnutls_assert ();
2182 return CDK_Inv_Value;
2185 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
2186 if (rc)
2188 gnutls_assert ();
2189 return rc;
2191 rc = cdk_keydb_search (st, hd, &knode);
2192 cdk_keydb_search_release (st);
2194 if (rc)
2196 gnutls_assert ();
2197 return rc;
2200 rc = cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id);
2201 if (!rc)
2203 rc = cdk_keydb_search (st, hd, &unode);
2204 cdk_keydb_search_release (st);
2206 if (rc)
2208 cdk_kbnode_release (knode);
2209 gnutls_assert ();
2210 return rc;
2213 check = 0;
2214 cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid);
2215 if (unode && find_by_keyid (unode, st))
2216 check++;
2217 cdk_keydb_search_release (st);
2218 cdk_kbnode_release (unode);
2220 cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *) id);
2221 if (knode && find_by_pattern (knode, st))
2222 check++;
2223 cdk_keydb_search_release (st);
2224 cdk_kbnode_release (knode);
2226 return check == 2 ? 0 : CDK_Inv_Value;
2231 * cdk_keydb_check_sk:
2232 * @hd: the key db handle
2233 * @keyid: the 64-bit keyid
2235 * Check if a secret key with the given key ID is available
2236 * in the key database.
2238 cdk_error_t
2239 cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 * keyid)
2241 cdk_stream_t db;
2242 cdk_packet_t pkt;
2243 cdk_error_t rc;
2244 u32 kid[2];
2246 if (!hd || !keyid)
2248 gnutls_assert ();
2249 return CDK_Inv_Value;
2251 if (!hd->secret)
2253 gnutls_assert ();
2254 return CDK_Inv_Mode;
2257 rc = _cdk_keydb_open (hd, &db);
2258 if (rc)
2260 gnutls_assert ();
2261 return rc;
2263 cdk_pkt_new (&pkt);
2264 while (!cdk_pkt_read (db, pkt))
2266 if (pkt->pkttype != CDK_PKT_SECRET_KEY &&
2267 pkt->pkttype != CDK_PKT_SECRET_SUBKEY)
2269 cdk_pkt_free (pkt);
2270 continue;
2272 cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
2273 if (KEYID_CMP (kid, keyid))
2275 cdk_pkt_release (pkt);
2276 return 0;
2278 cdk_pkt_free (pkt);
2280 cdk_pkt_release (pkt);
2281 gnutls_assert ();
2282 return CDK_Error_No_Key;
2287 * cdk_listkey_start:
2288 * @r_ctx: pointer to store the new context
2289 * @db: the key database handle
2290 * @patt: string pattern
2291 * @fpatt: recipients from a stringlist to show
2293 * Prepare a key listing with the given parameters. Two modes are supported.
2294 * The first mode uses string pattern to determine if the key should be
2295 * returned or not. The other mode uses a string list to request the key
2296 * which should be listed.
2298 cdk_error_t
2299 cdk_listkey_start (cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
2300 const char *patt, cdk_strlist_t fpatt)
2302 cdk_listkey_t ctx;
2303 cdk_stream_t inp;
2304 cdk_error_t rc;
2306 if (!r_ctx || !db)
2308 gnutls_assert ();
2309 return CDK_Inv_Value;
2311 if ((patt && fpatt) || (!patt && !fpatt))
2313 gnutls_assert ();
2314 return CDK_Inv_Mode;
2316 rc = _cdk_keydb_open (db, &inp);
2317 if (rc)
2319 gnutls_assert ();
2320 return rc;
2322 ctx = cdk_calloc (1, sizeof *ctx);
2323 if (!ctx)
2325 gnutls_assert ();
2326 return CDK_Out_Of_Core;
2328 ctx->db = db;
2329 ctx->inp = inp;
2330 if (patt)
2332 ctx->u.patt = cdk_strdup (patt);
2333 if (!ctx->u.patt)
2335 gnutls_assert ();
2336 return CDK_Out_Of_Core;
2339 else if (fpatt)
2341 cdk_strlist_t l;
2342 for (l = fpatt; l; l = l->next)
2343 cdk_strlist_add (&ctx->u.fpatt, l->d);
2345 ctx->type = patt ? 1 : 0;
2346 ctx->init = 1;
2347 *r_ctx = ctx;
2348 return 0;
2353 * cdk_listkey_close:
2354 * @ctx: the list key context
2356 * Free the list key context.
2358 void
2359 cdk_listkey_close (cdk_listkey_t ctx)
2361 if (!ctx)
2362 return;
2364 if (ctx->type)
2365 cdk_free (ctx->u.patt);
2366 else
2367 cdk_strlist_free (ctx->u.fpatt);
2368 cdk_free (ctx);
2373 * cdk_listkey_next:
2374 * @ctx: list key context
2375 * @r_key: the pointer to the new key node object
2377 * Retrieve the next key from the pattern of the key list context.
2379 cdk_error_t
2380 cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t * ret_key)
2382 if (!ctx || !ret_key)
2384 gnutls_assert ();
2385 return CDK_Inv_Value;
2387 if (!ctx->init)
2389 gnutls_assert ();
2390 return CDK_Inv_Mode;
2393 if (ctx->type && ctx->u.patt[0] == '*')
2394 return cdk_keydb_get_keyblock (ctx->inp, ret_key);
2395 else if (ctx->type)
2397 cdk_kbnode_t node;
2398 struct cdk_keydb_search_s ks;
2399 cdk_error_t rc;
2401 for (;;)
2403 rc = cdk_keydb_get_keyblock (ctx->inp, &node);
2404 if (rc)
2406 gnutls_assert ();
2407 return rc;
2409 memset (&ks, 0, sizeof (ks));
2410 ks.type = CDK_DBSEARCH_SUBSTR;
2411 ks.u.pattern = ctx->u.patt;
2412 if (find_by_pattern (node, &ks))
2414 *ret_key = node;
2415 return 0;
2417 cdk_kbnode_release (node);
2418 node = NULL;
2421 else
2423 if (!ctx->t)
2424 ctx->t = ctx->u.fpatt;
2425 else if (ctx->t->next)
2426 ctx->t = ctx->t->next;
2427 else
2428 return CDK_EOF;
2429 return cdk_keydb_get_bypattern (ctx->db, ctx->t->d, ret_key);
2431 gnutls_assert ();
2432 return CDK_General_Error;
2437 _cdk_keydb_is_secret (cdk_keydb_hd_t db)
2439 return db->secret;