1 /* keybox-search.c - Search operations
2 * Copyright (C) 2001, 2002, 2003, 2004, 2012,
3 * 2013 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 #include "../common/stringhelp.h" /* ascii_xxxx() */
30 #include "keybox-defs.h"
33 #include "mbox-util.h"
35 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
36 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
37 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
46 #define get32(a) buf32_to_ulong ((a))
47 #define get16(a) buf16_to_ulong ((a))
50 static inline unsigned int
51 blob_get_blob_flags (KEYBOXBLOB blob)
53 const unsigned char *buffer;
56 buffer = _keybox_get_blob_image (blob, &length);
60 return get16 (buffer + 6);
64 /* Return the first keyid from the blob. Returns true if
67 blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
69 const unsigned char *buffer;
70 size_t length, nkeys, keyinfolen;
72 buffer = _keybox_get_blob_image (blob, &length);
74 return 0; /* blob too short */
76 nkeys = get16 (buffer + 16);
77 keyinfolen = get16 (buffer + 18);
78 if (!nkeys || keyinfolen < 28)
79 return 0; /* invalid blob */
81 kid[0] = get32 (buffer + 32);
82 kid[1] = get32 (buffer + 36);
88 /* Return information on the flag WHAT within the blob BUFFER,LENGTH.
89 Return the offset and the length (in bytes) of the flag in
92 _keybox_get_flag_location (const unsigned char *buffer, size_t length,
93 int what, size_t *flag_off, size_t *flag_size)
96 size_t nkeys, keyinfolen;
97 size_t nuids, uidinfolen;
99 size_t nsigs, siginfolen, siginfooff;
103 case KEYBOX_FLAG_BLOB:
105 return GPG_ERR_INV_OBJ;
110 case KEYBOX_FLAG_OWNERTRUST:
111 case KEYBOX_FLAG_VALIDITY:
112 case KEYBOX_FLAG_CREATED_AT:
113 case KEYBOX_FLAG_SIG_INFO:
115 return GPG_ERR_INV_OBJ;
117 nkeys = get16 (buffer + 16);
118 keyinfolen = get16 (buffer + 18 );
120 return GPG_ERR_INV_OBJ;
121 pos = 20 + keyinfolen*nkeys;
123 return GPG_ERR_INV_OBJ; /* Out of bounds. */
125 nserial = get16 (buffer+pos);
128 return GPG_ERR_INV_OBJ; /* Out of bounds. */
130 nuids = get16 (buffer + pos); pos += 2;
131 uidinfolen = get16 (buffer + pos); pos += 2;
132 if (uidinfolen < 12 )
133 return GPG_ERR_INV_OBJ;
134 pos += uidinfolen*nuids;
136 return GPG_ERR_INV_OBJ ; /* Out of bounds. */
137 /* Signature info. */
139 nsigs = get16 (buffer + pos); pos += 2;
140 siginfolen = get16 (buffer + pos); pos += 2;
142 return GPG_ERR_INV_OBJ;
143 pos += siginfolen*nsigs;
144 if (pos+1+1+2+4+4+4+4 > length)
145 return GPG_ERR_INV_OBJ ; /* Out of bounds. */
150 case KEYBOX_FLAG_VALIDITY:
153 case KEYBOX_FLAG_CREATED_AT:
155 *flag_off += 1+2+4+4+4;
157 case KEYBOX_FLAG_SIG_INFO:
158 *flag_size = siginfolen * nsigs;
159 *flag_off = siginfooff;
167 return GPG_ERR_INV_FLAG;
174 /* Return one of the flags WHAT in VALUE from teh blob BUFFER of
175 LENGTH bytes. Return 0 on success or an raw error code. */
176 static gpg_err_code_t
177 get_flag_from_image (const unsigned char *buffer, size_t length,
178 int what, unsigned int *value)
184 ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
188 case 1: *value = buffer[pos]; break;
189 case 2: *value = get16 (buffer + pos); break;
190 case 4: *value = get32 (buffer + pos); break;
191 default: ec = GPG_ERR_BUG; break;
199 blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
201 const unsigned char *buffer;
204 size_t nkeys, keyinfolen;
207 buffer = _keybox_get_blob_image (blob, &length);
209 return 0; /* blob too short */
212 nkeys = get16 (buffer + 16);
213 keyinfolen = get16 (buffer + 18 );
215 return 0; /* invalid blob */
216 pos = 20 + keyinfolen*nkeys;
218 return 0; /* out of bounds */
221 nserial = get16 (buffer+pos);
223 if (off+nserial > length)
224 return 0; /* out of bounds */
226 return nserial == snlen && !memcmp (buffer+off, sn, snlen);
230 /* Returns 0 if not found or the number of the key which was found.
231 For X.509 this is always 1, for OpenPGP this is 1 for the primary
232 key and 2 and more for the subkeys. */
234 blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
236 const unsigned char *buffer;
239 size_t nkeys, keyinfolen;
242 buffer = _keybox_get_blob_image (blob, &length);
244 return 0; /* blob too short */
247 nkeys = get16 (buffer + 16);
248 keyinfolen = get16 (buffer + 18 );
250 return 0; /* invalid blob */
252 if (pos + keyinfolen*nkeys > length)
253 return 0; /* out of bounds */
255 for (idx=0; idx < nkeys; idx++)
257 off = pos + idx*keyinfolen;
258 if (!memcmp (buffer + off, fpr, 20))
259 return idx+1; /* found */
261 return 0; /* not found */
265 blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
266 int fproff, int fprlen)
268 const unsigned char *buffer;
271 size_t nkeys, keyinfolen;
274 buffer = _keybox_get_blob_image (blob, &length);
276 return 0; /* blob too short */
279 nkeys = get16 (buffer + 16);
280 keyinfolen = get16 (buffer + 18 );
282 return 0; /* invalid blob */
284 if (pos + keyinfolen*nkeys > length)
285 return 0; /* out of bounds */
287 for (idx=0; idx < nkeys; idx++)
289 off = pos + idx*keyinfolen;
290 if (!memcmp (buffer + off + fproff, fpr, fprlen))
291 return idx+1; /* found */
293 return 0; /* not found */
298 blob_cmp_name (KEYBOXBLOB blob, int idx,
299 const char *name, size_t namelen, int substr, int x509)
301 const unsigned char *buffer;
303 size_t pos, off, len;
304 size_t nkeys, keyinfolen;
305 size_t nuids, uidinfolen;
308 buffer = _keybox_get_blob_image (blob, &length);
310 return 0; /* blob too short */
313 nkeys = get16 (buffer + 16);
314 keyinfolen = get16 (buffer + 18 );
316 return 0; /* invalid blob */
317 pos = 20 + keyinfolen*nkeys;
319 return 0; /* out of bounds */
322 nserial = get16 (buffer+pos);
325 return 0; /* out of bounds */
328 nuids = get16 (buffer + pos); pos += 2;
329 uidinfolen = get16 (buffer + pos); pos += 2;
330 if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
331 return 0; /* invalid blob */
332 if (pos + uidinfolen*nuids > length)
333 return 0; /* out of bounds */
336 { /* Compare all names. Note that for X.509 we start with index 1
337 so to skip the issuer at index 0. */
338 for (idx = !!x509; idx < nuids; idx++)
342 mypos += idx*uidinfolen;
343 off = get32 (buffer+mypos);
344 len = get32 (buffer+mypos+4);
345 if (off+len > length)
346 return 0; /* error: better stop here out of bounds */
348 continue; /* empty name */
351 if (ascii_memcasemem (buffer+off, len, name, namelen))
352 return idx+1; /* found */
356 if (len == namelen && !memcmp (buffer+off, name, len))
357 return idx+1; /* found */
364 return 0; /* no user ID with that idx */
365 pos += idx*uidinfolen;
366 off = get32 (buffer+pos);
367 len = get32 (buffer+pos+4);
368 if (off+len > length)
369 return 0; /* out of bounds */
371 return 0; /* empty name */
375 if (ascii_memcasemem (buffer+off, len, name, namelen))
376 return idx+1; /* found */
380 if (len == namelen && !memcmp (buffer+off, name, len))
381 return idx+1; /* found */
384 return 0; /* not found */
388 /* Compare all email addresses of the subject. With SUBSTR given as
389 True a substring search is done in the mail address. The X509 flag
390 indicated whether the search is done on an X.509 blob. */
392 blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
395 const unsigned char *buffer;
397 size_t pos, off, len;
398 size_t nkeys, keyinfolen;
399 size_t nuids, uidinfolen;
403 /* fixme: this code is common to blob_cmp_mail */
404 buffer = _keybox_get_blob_image (blob, &length);
406 return 0; /* blob too short */
409 nkeys = get16 (buffer + 16);
410 keyinfolen = get16 (buffer + 18 );
412 return 0; /* invalid blob */
413 pos = 20 + keyinfolen*nkeys;
415 return 0; /* out of bounds */
418 nserial = get16 (buffer+pos);
421 return 0; /* out of bounds */
424 nuids = get16 (buffer + pos); pos += 2;
425 uidinfolen = get16 (buffer + pos); pos += 2;
426 if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
427 return 0; /* invalid blob */
428 if (pos + uidinfolen*nuids > length)
429 return 0; /* out of bounds */
434 /* Note that for X.509 we start at index 1 becuase index 0 is used
435 for the issuer name. */
436 for (idx=!!x509 ;idx < nuids; idx++)
441 mypos += idx*uidinfolen;
442 off = get32 (buffer+mypos);
443 len = get32 (buffer+mypos+4);
444 if (off+len > length)
445 return 0; /* error: better stop here - out of bounds */
448 if (len < 2 || buffer[off] != '<')
449 continue; /* empty name or trailing 0 not stored */
450 len--; /* one back */
451 if ( len < 3 || buffer[off+len] != '>')
452 continue; /* not a proper email address */
458 /* We need to forward to the mailbox part. */
461 for ( ; len && buffer[off] != '<'; len--, off++)
463 if (len < 2 || buffer[off] != '<')
465 /* Mailbox not explicitly given or too short. Restore
466 OFF and LEN and check whether the entire string
467 resembles a mailbox without the angle brackets. */
470 if (!is_valid_mailbox_mem (buffer+off, len))
471 continue; /* Not a mail address. */
473 else /* Seems to be standard user id with mail address. */
475 off++; /* Point to first char of the mail address. */
477 /* Search closing '>'. */
478 for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
480 if (!len || buffer[mypos] != '>' || off == mypos)
481 continue; /* Not a proper mail address. */
489 if (ascii_memcasemem (buffer+off, len, name, namelen))
490 return idx+1; /* found */
494 if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
495 return idx+1; /* found */
498 return 0; /* not found */
502 #ifdef KEYBOX_WITH_X509
503 /* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
504 We don't have the keygrips as meta data, thus we need to parse the
505 certificate. Fixme: We might want to return proper error codes
506 instead of failing a search for invalid certificates etc. */
508 blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
511 const unsigned char *buffer;
513 size_t cert_off, cert_len;
514 ksba_reader_t reader = NULL;
515 ksba_cert_t cert = NULL;
516 ksba_sexp_t p = NULL;
518 unsigned char array[20];
522 buffer = _keybox_get_blob_image (blob, &length);
524 return 0; /* Too short. */
525 cert_off = get32 (buffer+8);
526 cert_len = get32 (buffer+12);
527 if (cert_off+cert_len > length)
528 return 0; /* Too short. */
530 rc = ksba_reader_new (&reader);
532 return 0; /* Problem with ksba. */
533 rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
536 rc = ksba_cert_new (&cert);
539 rc = ksba_cert_read_der (cert, reader);
542 p = ksba_cert_get_public_key (cert);
545 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
548 rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
551 gcry_sexp_release (s_pkey);
554 rcp = gcry_pk_get_keygrip (s_pkey, array);
555 gcry_sexp_release (s_pkey);
557 goto failed; /* Can't calculate keygrip. */
560 ksba_cert_release (cert);
561 ksba_reader_release (reader);
562 return !memcmp (array, grip, 20);
565 ksba_cert_release (cert);
566 ksba_reader_release (reader);
569 #endif /*KEYBOX_WITH_X509*/
574 The has_foo functions are used as helpers for search
577 has_short_kid (KEYBOXBLOB blob, u32 lkid)
579 unsigned char buf[4];
584 return blob_cmp_fpr_part (blob, buf, 16, 4);
588 has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
590 unsigned char buf[8];
599 return blob_cmp_fpr_part (blob, buf, 12, 8);
603 has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr)
605 return blob_cmp_fpr (blob, fpr);
609 has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
611 #ifdef KEYBOX_WITH_X509
612 if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
613 return blob_x509_has_grip (blob, grip);
623 has_issuer (KEYBOXBLOB blob, const char *name)
627 return_val_if_fail (name, 0);
629 if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
632 namelen = strlen (name);
633 return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
637 has_issuer_sn (KEYBOXBLOB blob, const char *name,
638 const unsigned char *sn, int snlen)
642 return_val_if_fail (name, 0);
643 return_val_if_fail (sn, 0);
645 if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
648 namelen = strlen (name);
650 return (blob_cmp_sn (blob, sn, snlen)
651 && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
655 has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
657 return_val_if_fail (sn, 0);
659 if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
661 return blob_cmp_sn (blob, sn, snlen);
665 has_subject (KEYBOXBLOB blob, const char *name)
669 return_val_if_fail (name, 0);
671 if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
674 namelen = strlen (name);
675 return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
680 has_username (KEYBOXBLOB blob, const char *name, int substr)
685 return_val_if_fail (name, 0);
687 btype = blob_get_type (blob);
688 if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
691 namelen = strlen (name);
692 return blob_cmp_name (blob, -1 /* all subject/user names */, name,
693 namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
698 has_mail (KEYBOXBLOB blob, const char *name, int substr)
703 return_val_if_fail (name, 0);
705 btype = blob_get_type (blob);
706 if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
709 if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
710 name++; /* Hack to remove the leading '<' for gpg. */
712 namelen = strlen (name);
713 if (namelen && name[namelen-1] == '>')
715 return blob_cmp_mail (blob, name, namelen, substr,
716 (btype == KEYBOX_BLOBTYPE_X509));
721 release_sn_array (struct sn_array_s *array, size_t size)
725 for (n=0; n < size; n++)
738 keybox_search_reset (KEYBOX_HANDLE hd)
741 return gpg_error (GPG_ERR_INV_VALUE);
745 _keybox_release_blob (hd->found.blob);
746 hd->found.blob = NULL;
760 /* Note: When in ephemeral mode the search function does visit all
761 blobs but in standard mode, blobs flagged as ephemeral are ignored.
762 If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
763 The value at R_SKIPPED is updated by the number of skipped long
764 records (counts PGP and X.509). */
766 keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
767 keybox_blobtype_t want_blobtype,
768 size_t *r_descindex, unsigned long *r_skipped)
772 int need_words, any_skip;
773 KEYBOXBLOB blob = NULL;
774 struct sn_array_s *sn_array = NULL;
778 return gpg_error (GPG_ERR_INV_VALUE);
780 /* clear last found result */
783 _keybox_release_blob (hd->found.blob);
784 hd->found.blob = NULL;
788 return hd->error; /* still in error state */
790 return -1; /* still EOF */
792 /* figure out what information we need */
793 need_words = any_skip = 0;
794 for (n=0; n < ndesc; n++)
796 switch (desc[n].mode)
798 case KEYDB_SEARCH_MODE_WORDS:
801 case KEYDB_SEARCH_MODE_FIRST:
802 /* always restart the search in this mode */
803 keybox_search_reset (hd);
810 if (desc[n].snlen == -1 && !sn_array)
812 sn_array = xtrycalloc (ndesc, sizeof *sn_array);
814 return (hd->error = gpg_error_from_syserror ());
818 (void)need_words; /* Not yet implemented. */
822 hd->fp = fopen (hd->kb->fname, "rb");
825 hd->error = gpg_error_from_syserror ();
831 /* Kludge: We need to convert an SN given as hexstring to its binary
832 representation - in some cases we are not able to store it in the
833 search descriptor, because due to the way we use it, it is not
834 possible to free allocated memory. */
837 const unsigned char *s;
841 for (n=0; n < ndesc; n++)
845 else if (desc[n].snlen == -1)
850 for (i=0; *s && *s != '/'; s++, i++)
854 sn_array[n].sn = xtrymalloc (snlen);
857 hd->error = gpg_error_from_syserror ();
858 release_sn_array (sn_array, n);
861 sn_array[n].snlen = snlen;
869 for (; *s && *s != '/'; s += 2)
874 const unsigned char *sn;
877 snlen = desc[n].snlen;
878 sn_array[n].sn = xtrymalloc (snlen);
881 hd->error = gpg_error_from_syserror ();
882 release_sn_array (sn_array, n);
885 sn_array[n].snlen = snlen;
886 memcpy (sn_array[n].sn, sn, snlen);
895 unsigned int blobflags;
898 _keybox_release_blob (blob); blob = NULL;
899 rc = _keybox_read_blob (&blob, hd->fp);
900 if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
901 && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
904 continue; /* Skip too large records. */
910 blobtype = blob_get_type (blob);
911 if (blobtype == KEYBOX_BLOBTYPE_HEADER)
913 if (want_blobtype && blobtype != want_blobtype)
916 blobflags = blob_get_blob_flags (blob);
917 if (!hd->ephemeral && (blobflags & 2))
918 continue; /* Not in ephemeral mode but blob is flagged ephemeral. */
920 for (n=0; n < ndesc; n++)
922 switch (desc[n].mode)
924 case KEYDB_SEARCH_MODE_NONE:
927 case KEYDB_SEARCH_MODE_EXACT:
928 uid_no = has_username (blob, desc[n].u.name, 0);
932 case KEYDB_SEARCH_MODE_MAIL:
933 uid_no = has_mail (blob, desc[n].u.name, 0);
937 case KEYDB_SEARCH_MODE_MAILSUB:
938 uid_no = has_mail (blob, desc[n].u.name, 1);
942 case KEYDB_SEARCH_MODE_SUBSTR:
943 uid_no = has_username (blob, desc[n].u.name, 1);
947 case KEYDB_SEARCH_MODE_MAILEND:
948 case KEYDB_SEARCH_MODE_WORDS:
949 /* not yet implemented */
951 case KEYDB_SEARCH_MODE_ISSUER:
952 if (has_issuer (blob, desc[n].u.name))
955 case KEYDB_SEARCH_MODE_ISSUER_SN:
956 if (has_issuer_sn (blob, desc[n].u.name,
957 sn_array? sn_array[n].sn : desc[n].sn,
958 sn_array? sn_array[n].snlen : desc[n].snlen))
961 case KEYDB_SEARCH_MODE_SN:
962 if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
963 sn_array? sn_array[n].snlen : desc[n].snlen))
966 case KEYDB_SEARCH_MODE_SUBJECT:
967 if (has_subject (blob, desc[n].u.name))
970 case KEYDB_SEARCH_MODE_SHORT_KID:
971 pk_no = has_short_kid (blob, desc[n].u.kid[1]);
975 case KEYDB_SEARCH_MODE_LONG_KID:
976 pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
980 case KEYDB_SEARCH_MODE_FPR:
981 case KEYDB_SEARCH_MODE_FPR20:
982 pk_no = has_fingerprint (blob, desc[n].u.fpr);
986 case KEYDB_SEARCH_MODE_KEYGRIP:
987 if (has_keygrip (blob, desc[n].u.grip))
990 case KEYDB_SEARCH_MODE_FIRST:
993 case KEYDB_SEARCH_MODE_NEXT:
997 rc = gpg_error (GPG_ERR_INV_VALUE);
1003 /* Record which DESC we matched on. Note this value is only
1004 meaningful if this function returns with no errors. */
1007 for (n=any_skip?0:ndesc; n < ndesc; n++)
1012 && blob_get_first_keyid (blob, kid)
1013 && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
1022 hd->found.blob = blob;
1023 hd->found.pk_no = pk_no;
1024 hd->found.uid_no = uid_no;
1028 _keybox_release_blob (blob);
1033 _keybox_release_blob (blob);
1038 release_sn_array (sn_array, ndesc);
1047 Functions to return a certificate or a keyblock. To be used after
1048 a successful search operation.
1052 /* Return the last found keyblock. Returns 0 on success and stores a
1053 new iobuf at R_IOBUF and a signature status vector at R_SIGSTATUS
1054 in that case. R_UID_NO and R_PK_NO are used to retun the number of
1055 the key or user id which was matched the search criteria; if not
1056 known they are set to 0. */
1058 keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
1059 int *r_pk_no, int *r_uid_no, u32 **r_sigstatus)
1062 const unsigned char *buffer, *p;
1064 size_t image_off, image_len;
1065 size_t siginfo_off, siginfo_len;
1066 u32 *sigstatus, n, n_sigs, sigilen;
1069 *r_sigstatus = NULL;
1072 return gpg_error (GPG_ERR_INV_VALUE);
1073 if (!hd->found.blob)
1074 return gpg_error (GPG_ERR_NOTHING_FOUND);
1076 if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1077 return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1079 buffer = _keybox_get_blob_image (hd->found.blob, &length);
1081 return gpg_error (GPG_ERR_TOO_SHORT);
1082 image_off = get32 (buffer+8);
1083 image_len = get32 (buffer+12);
1084 if (image_off+image_len > length)
1085 return gpg_error (GPG_ERR_TOO_SHORT);
1087 err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1088 &siginfo_off, &siginfo_len);
1091 n_sigs = get16 (buffer + siginfo_off);
1092 sigilen = get16 (buffer + siginfo_off + 2);
1093 p = buffer + siginfo_off + 4;
1094 sigstatus = xtrymalloc ((1+n_sigs) * sizeof *sigstatus);
1096 return gpg_error_from_syserror ();
1097 sigstatus[0] = n_sigs;
1098 for (n=1; n <= n_sigs; n++, p += sigilen)
1099 sigstatus[n] = get32 (p);
1101 *r_pk_no = hd->found.pk_no;
1102 *r_uid_no = hd->found.uid_no;
1103 *r_sigstatus = sigstatus;
1104 *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1109 #ifdef KEYBOX_WITH_X509
1111 Return the last found cert. Caller must free it.
1114 keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1116 const unsigned char *buffer;
1118 size_t cert_off, cert_len;
1119 ksba_reader_t reader = NULL;
1120 ksba_cert_t cert = NULL;
1124 return gpg_error (GPG_ERR_INV_VALUE);
1125 if (!hd->found.blob)
1126 return gpg_error (GPG_ERR_NOTHING_FOUND);
1128 if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
1129 return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1131 buffer = _keybox_get_blob_image (hd->found.blob, &length);
1133 return gpg_error (GPG_ERR_TOO_SHORT);
1134 cert_off = get32 (buffer+8);
1135 cert_len = get32 (buffer+12);
1136 if (cert_off+cert_len > length)
1137 return gpg_error (GPG_ERR_TOO_SHORT);
1139 rc = ksba_reader_new (&reader);
1142 rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1145 ksba_reader_release (reader);
1146 /* fixme: need to map the error codes */
1147 return gpg_error (GPG_ERR_GENERAL);
1150 rc = ksba_cert_new (&cert);
1153 ksba_reader_release (reader);
1157 rc = ksba_cert_read_der (cert, reader);
1160 ksba_cert_release (cert);
1161 ksba_reader_release (reader);
1162 /* fixme: need to map the error codes */
1163 return gpg_error (GPG_ERR_GENERAL);
1167 ksba_reader_release (reader);
1171 #endif /*KEYBOX_WITH_X509*/
1173 /* Return the flags named WHAT at the address of VALUE. IDX is used
1174 only for certain flags and should be 0 if not required. */
1176 keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1178 const unsigned char *buffer;
1182 (void)idx; /* Not yet used. */
1185 return gpg_error (GPG_ERR_INV_VALUE);
1186 if (!hd->found.blob)
1187 return gpg_error (GPG_ERR_NOTHING_FOUND);
1189 buffer = _keybox_get_blob_image (hd->found.blob, &length);
1190 ec = get_flag_from_image (buffer, length, what, value);
1191 return ec? gpg_error (ec):0;