Coverage Report

Created: 2026-02-09 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/kbx/keybox-search.c
Line
Count
Source
1
/* keybox-search.c - Search operations
2
 * Copyright (C) 2001, 2002, 2003, 2004, 2012,
3
 *               2013 Free Software Foundation, Inc.
4
 *
5
 * This file is part of GnuPG.
6
 *
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.
11
 *
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.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include <string.h>
25
#include <assert.h>
26
#include <errno.h>
27
28
#include "keybox-defs.h"
29
#include <gcrypt.h>
30
#include "../common/host2net.h"
31
#include "../common/mbox-util.h"
32
33
0
#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
34
0
                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
35
0
#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
36
37
38
struct sn_array_s {
39
    int snlen;
40
    unsigned char *sn;
41
};
42
43
44
0
#define get32(a) buf32_to_ulong ((a))
45
0
#define get16(a) buf16_to_ulong ((a))
46
47
48
static inline unsigned int
49
blob_get_blob_flags (KEYBOXBLOB blob)
50
0
{
51
0
  const unsigned char *buffer;
52
0
  size_t length;
53
54
0
  buffer = _keybox_get_blob_image (blob, &length);
55
0
  if (length < 8)
56
0
    return 0; /* oops */
57
58
0
  return get16 (buffer + 6);
59
0
}
60
61
62
/* Return the first keyid from the blob.  Returns true if
63
   available.  */
64
static int
65
blob_get_first_keyid (KEYBOXBLOB blob, u32 *kid)
66
0
{
67
0
  const unsigned char *buffer;
68
0
  size_t length, nkeys, keyinfolen;
69
0
  int fpr32;
70
71
0
  buffer = _keybox_get_blob_image (blob, &length);
72
0
  if (length < 48)
73
0
    return 0; /* blob too short */
74
0
  fpr32 = buffer[5] == 2;
75
0
  if (fpr32 && length < 56)
76
0
    return 0; /* blob to short */
77
78
0
  nkeys = get16 (buffer + 16);
79
0
  keyinfolen = get16 (buffer + 18);
80
0
  if (!nkeys || keyinfolen < (fpr32?56:28))
81
0
    return 0; /* invalid blob */
82
83
0
  if (fpr32 && (get16 (buffer + 20 + 32) & 0x80))
84
0
    {
85
      /* 32 byte fingerprint.  */
86
0
      kid[0] = get32 (buffer + 20);
87
0
      kid[1] = get32 (buffer + 20 + 4);
88
0
    }
89
0
  else /* 20 byte fingerprint.  */
90
0
    {
91
0
      kid[0] = get32 (buffer + 20 + 12);
92
0
      kid[1] = get32 (buffer + 20 + 16);
93
0
    }
94
95
0
  return 1;
96
0
}
97
98
99
/* Return information on the flag WHAT within the blob BUFFER,LENGTH.
100
   Return the offset and the length (in bytes) of the flag in
101
   FLAGOFF,FLAG_SIZE. */
102
gpg_err_code_t
103
_keybox_get_flag_location (const unsigned char *buffer, size_t length,
104
                           int what, size_t *flag_off, size_t *flag_size)
105
0
{
106
0
  size_t pos;
107
0
  size_t nkeys, keyinfolen;
108
0
  size_t nuids, uidinfolen;
109
0
  size_t nserial;
110
0
  size_t nsigs, siginfolen, siginfooff;
111
112
0
  switch (what)
113
0
    {
114
0
    case KEYBOX_FLAG_BLOB:
115
0
      if (length < 8)
116
0
        return GPG_ERR_INV_OBJ;
117
0
      *flag_off = 6;
118
0
      *flag_size = 2;
119
0
      break;
120
121
0
    case KEYBOX_FLAG_OWNERTRUST:
122
0
    case KEYBOX_FLAG_VALIDITY:
123
0
    case KEYBOX_FLAG_CREATED_AT:
124
0
    case KEYBOX_FLAG_SIG_INFO:
125
0
      if (length < 20)
126
0
        return GPG_ERR_INV_OBJ;
127
      /* Key info. */
128
0
      nkeys = get16 (buffer + 16);
129
0
      keyinfolen = get16 (buffer + 18 );
130
0
      if (keyinfolen < 28)
131
0
        return GPG_ERR_INV_OBJ;
132
0
      pos = 20 + keyinfolen*nkeys;
133
0
      if (pos+2 > length)
134
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
135
      /* Serial number. */
136
0
      nserial = get16 (buffer+pos);
137
0
      pos += 2 + nserial;
138
0
      if (pos+4 > length)
139
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
140
      /* User IDs. */
141
0
      nuids = get16 (buffer + pos); pos += 2;
142
0
      uidinfolen = get16 (buffer + pos); pos += 2;
143
0
      if (uidinfolen < 12 )
144
0
        return GPG_ERR_INV_OBJ;
145
0
      pos += uidinfolen*nuids;
146
0
      if (pos+4 > length)
147
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
148
      /* Signature info. */
149
0
      siginfooff = pos;
150
0
      nsigs = get16 (buffer + pos); pos += 2;
151
0
      siginfolen = get16 (buffer + pos); pos += 2;
152
0
      if (siginfolen < 4 )
153
0
        return GPG_ERR_INV_OBJ;
154
0
      pos += siginfolen*nsigs;
155
0
      if (pos+1+1+2+4+4+4+4 > length)
156
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
157
0
      *flag_size = 1;
158
0
      *flag_off = pos;
159
0
      switch (what)
160
0
        {
161
0
        case KEYBOX_FLAG_VALIDITY:
162
0
          *flag_off += 1;
163
0
          break;
164
0
        case KEYBOX_FLAG_CREATED_AT:
165
0
          *flag_size = 4;
166
0
          *flag_off += 1+2+4+4+4;
167
0
          break;
168
0
        case KEYBOX_FLAG_SIG_INFO:
169
0
          *flag_size = siginfolen * nsigs;
170
0
          *flag_off = siginfooff;
171
0
          break;
172
0
        default:
173
0
          break;
174
0
        }
175
0
      break;
176
177
0
    default:
178
0
      return GPG_ERR_INV_FLAG;
179
0
    }
180
0
  return 0;
181
0
}
182
183
184
185
/* Return one of the flags WHAT in VALUE from the blob BUFFER of
186
   LENGTH bytes.  Return 0 on success or an raw error code. */
187
static gpg_err_code_t
188
get_flag_from_image (const unsigned char *buffer, size_t length,
189
                     int what, unsigned int *value)
190
0
{
191
0
  gpg_err_code_t ec;
192
0
  size_t pos, size;
193
194
0
  *value = 0;
195
0
  ec = _keybox_get_flag_location (buffer, length, what, &pos, &size);
196
0
  if (!ec)
197
0
    switch (size)
198
0
      {
199
0
      case 1: *value = buffer[pos]; break;
200
0
      case 2: *value = get16 (buffer + pos); break;
201
0
      case 4: *value = get32 (buffer + pos); break;
202
0
      default: ec = GPG_ERR_BUG; break;
203
0
      }
204
205
0
  return ec;
206
0
}
207
208
209
static int
210
blob_cmp_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
211
0
{
212
0
  const unsigned char *buffer;
213
0
  size_t length;
214
0
  size_t pos, off;
215
0
  size_t nkeys, keyinfolen;
216
0
  size_t nserial;
217
218
0
  buffer = _keybox_get_blob_image (blob, &length);
219
0
  if (length < 40)
220
0
    return 0; /* blob too short */
221
222
  /*keys*/
223
0
  nkeys = get16 (buffer + 16);
224
0
  keyinfolen = get16 (buffer + 18 );
225
0
  if (keyinfolen < 28)
226
0
    return 0; /* invalid blob */
227
0
  pos = 20 + keyinfolen*nkeys;
228
0
  if (pos+2 > length)
229
0
    return 0; /* out of bounds */
230
231
  /*serial*/
232
0
  nserial = get16 (buffer+pos);
233
0
  off = pos + 2;
234
0
  if (off+nserial > length)
235
0
    return 0; /* out of bounds */
236
237
0
  return nserial == snlen && !memcmp (buffer+off, sn, snlen);
238
0
}
239
240
241
/* Returns 0 if not found or the number of the key which was found.
242
   For X.509 this is always 1, for OpenPGP this is 1 for the primary
243
   key and 2 and more for the subkeys.  */
244
static int
245
blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr, unsigned int fprlen)
246
0
{
247
0
  const unsigned char *buffer;
248
0
  size_t length;
249
0
  size_t pos, off;
250
0
  size_t nkeys, keyinfolen;
251
0
  int idx, fpr32, storedfprlen;
252
253
0
  buffer = _keybox_get_blob_image (blob, &length);
254
0
  if (length < 40)
255
0
    return 0; /* blob too short */
256
0
  fpr32 = buffer[5] == 2;
257
258
  /*keys*/
259
0
  nkeys = get16 (buffer + 16);
260
0
  keyinfolen = get16 (buffer + 18 );
261
0
  if (keyinfolen < (fpr32?56:28))
262
0
    return 0; /* invalid blob */
263
0
  pos = 20;
264
0
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
265
0
    return 0; /* out of bounds */
266
267
0
  for (idx=0; idx < nkeys; idx++)
268
0
    {
269
0
      off = pos + idx*keyinfolen;
270
0
      if (fpr32)
271
0
        storedfprlen = (get16 (buffer + off + 32) & 0x80)? 32:20;
272
0
      else
273
0
        storedfprlen = 20;
274
0
      if (storedfprlen == fprlen
275
0
          && !memcmp (buffer + off, fpr, storedfprlen))
276
0
        return idx+1; /* found */
277
0
    }
278
0
  return 0; /* not found */
279
0
}
280
281
282
/* Helper for has_short_kid and has_long_kid.  This function is called
283
 * with FPROFF 12 and FPRLEN 4 or with FPROFF 12 and FPRLEN 8.  */
284
static int
285
blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
286
                   int fproff, int fprlen)
287
0
{
288
0
  const unsigned char *buffer;
289
0
  size_t length;
290
0
  size_t pos, off;
291
0
  size_t nkeys, keyinfolen;
292
0
  int idx;
293
0
  int fpr32;    /* Set if this blob stores all fingerprints as 32 bytes. */
294
295
0
  buffer = _keybox_get_blob_image (blob, &length);
296
0
  if (length < 40)
297
0
    return 0; /* blob too short */
298
0
  fpr32 = buffer[5] == 2;
299
300
  /*keys*/
301
0
  nkeys = get16 (buffer + 16);
302
0
  keyinfolen = get16 (buffer + 18 );
303
0
  if (keyinfolen < (fpr32?56:28))
304
0
    return 0; /* invalid blob */
305
0
  pos = 20;
306
0
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
307
0
    return 0; /* out of bounds */
308
309
0
  for (idx=0; idx < nkeys; idx++)
310
0
    {
311
0
      off = pos + idx*keyinfolen;
312
0
      if (!fpr32)
313
0
        {
314
          /* Blob has only 20 fingerprints - use the FPROFF.    */
315
0
          if (!memcmp (buffer + off + fproff, fpr, fprlen))
316
0
            return idx+1; /* found */
317
0
        }
318
0
      else if ((buffer[off + 32 + 1] & 0x80))
319
0
        {
320
          /* This (sub)key has a 32 byte fpr -> use 0 as offset. */
321
0
          if (!memcmp (buffer + off, fpr, fprlen))
322
0
            return idx+1; /* found */
323
0
        }
324
0
      else
325
0
        {
326
          /* This (sub)key has a 20 byte fpr -> use the FPROFF  */
327
0
          if (!memcmp (buffer + off + fproff, fpr, fprlen))
328
0
            return idx+1; /* found */
329
0
        }
330
0
    }
331
0
  return 0; /* not found */
332
0
}
333
334
335
/* Returns true if found.  */
336
static int
337
blob_cmp_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
338
0
{
339
0
  const unsigned char *buffer;
340
0
  size_t length;
341
0
  size_t pos;
342
0
  size_t nkeys, keyinfolen;
343
0
  int fpr32;
344
345
0
  buffer = _keybox_get_blob_image (blob, &length);
346
0
  if (length < 40)
347
0
    return 0; /* blob too short */
348
0
  fpr32 = buffer[5] == 2;
349
350
  /*keys*/
351
0
  nkeys = get16 (buffer + 16);
352
0
  keyinfolen = get16 (buffer + 18 );
353
0
  if (!nkeys || keyinfolen < (fpr32?56:28))
354
0
    return 0; /* invalid blob */
355
0
  pos = 20;
356
0
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
357
0
    return 0; /* out of bounds */
358
359
0
  if (!memcmp (buffer + pos, ubid, UBID_LEN))
360
0
    return 1; /* found */
361
0
  return 0;   /* not found */
362
0
}
363
364
365
static int
366
blob_cmp_name (KEYBOXBLOB blob, int idx,
367
               const char *name, size_t namelen, int substr, int x509)
368
0
{
369
0
  const unsigned char *buffer;
370
0
  size_t length;
371
0
  size_t pos, off, len;
372
0
  size_t nkeys, keyinfolen;
373
0
  size_t nuids, uidinfolen;
374
0
  size_t nserial;
375
376
0
  buffer = _keybox_get_blob_image (blob, &length);
377
0
  if (length < 40)
378
0
    return 0; /* blob too short */
379
380
  /*keys*/
381
0
  nkeys = get16 (buffer + 16);
382
0
  keyinfolen = get16 (buffer + 18 );
383
0
  if (keyinfolen < 28)
384
0
    return 0; /* invalid blob */
385
0
  pos = 20 + keyinfolen*nkeys;
386
0
  if ((uint64_t)pos+2 > (uint64_t)length)
387
0
    return 0; /* out of bounds */
388
389
  /*serial*/
390
0
  nserial = get16 (buffer+pos);
391
0
  pos += 2 + nserial;
392
0
  if (pos+4 > length)
393
0
    return 0; /* out of bounds */
394
395
  /* user ids*/
396
0
  nuids = get16 (buffer + pos);  pos += 2;
397
0
  uidinfolen = get16 (buffer + pos);  pos += 2;
398
0
  if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
399
0
    return 0; /* invalid blob */
400
0
  if (pos + uidinfolen*nuids > length)
401
0
    return 0; /* out of bounds */
402
403
0
  if (idx < 0)
404
0
    { /* Compare all names.  Note that for X.509 we start with index 1
405
         so to skip the issuer at index 0.  */
406
0
      for (idx = !!x509; idx < nuids; idx++)
407
0
        {
408
0
          size_t mypos = pos;
409
410
0
          mypos += idx*uidinfolen;
411
0
          off = get32 (buffer+mypos);
412
0
          len = get32 (buffer+mypos+4);
413
0
          if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
414
0
            return 0; /* error: better stop here out of bounds */
415
0
          if (len < 1)
416
0
            continue; /* empty name */
417
0
          if (substr)
418
0
            {
419
0
              if (ascii_memcasemem (buffer+off, len, name, namelen))
420
0
                return idx+1; /* found */
421
0
            }
422
0
          else
423
0
            {
424
0
              if (len == namelen && !memcmp (buffer+off, name, len))
425
0
                return idx+1; /* found */
426
0
            }
427
0
        }
428
0
    }
429
0
  else
430
0
    {
431
0
      if (idx > nuids)
432
0
        return 0; /* no user ID with that idx */
433
0
      pos += idx*uidinfolen;
434
0
      off = get32 (buffer+pos);
435
0
      len = get32 (buffer+pos+4);
436
0
      if (off+len > length)
437
0
        return 0; /* out of bounds */
438
0
      if (len < 1)
439
0
        return 0; /* empty name */
440
441
0
      if (substr)
442
0
        {
443
0
          if (ascii_memcasemem (buffer+off, len, name, namelen))
444
0
            return idx+1; /* found */
445
0
        }
446
0
      else
447
0
        {
448
0
          if (len == namelen && !memcmp (buffer+off, name, len))
449
0
            return idx+1; /* found */
450
0
        }
451
0
    }
452
0
  return 0; /* not found */
453
0
}
454
455
456
/* Compare all email addresses of the subject.  With SUBSTR given as
457
   True a substring search is done in the mail address.  The X509 flag
458
   indicated whether the search is done on an X.509 blob.  */
459
static int
460
blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
461
               int x509)
462
0
{
463
0
  const unsigned char *buffer;
464
0
  size_t length;
465
0
  size_t pos, off, len;
466
0
  size_t nkeys, keyinfolen;
467
0
  size_t nuids, uidinfolen;
468
0
  size_t nserial;
469
0
  int idx;
470
471
  /* fixme: this code is common to blob_cmp_mail */
472
0
  buffer = _keybox_get_blob_image (blob, &length);
473
0
  if (length < 40)
474
0
    return 0; /* blob too short */
475
476
  /*keys*/
477
0
  nkeys = get16 (buffer + 16);
478
0
  keyinfolen = get16 (buffer + 18 );
479
0
  if (keyinfolen < 28)
480
0
    return 0; /* invalid blob */
481
0
  pos = 20 + keyinfolen*nkeys;
482
0
  if (pos+2 > length)
483
0
    return 0; /* out of bounds */
484
485
  /*serial*/
486
0
  nserial = get16 (buffer+pos);
487
0
  pos += 2 + nserial;
488
0
  if (pos+4 > length)
489
0
    return 0; /* out of bounds */
490
491
  /* user ids*/
492
0
  nuids = get16 (buffer + pos);  pos += 2;
493
0
  uidinfolen = get16 (buffer + pos);  pos += 2;
494
0
  if (uidinfolen < 12 /* should add a: || nuidinfolen > MAX_UIDINFOLEN */)
495
0
    return 0; /* invalid blob */
496
0
  if (pos + uidinfolen*nuids > length)
497
0
    return 0; /* out of bounds */
498
499
0
  if (namelen < 1)
500
0
    return 0;
501
502
  /* Note that for X.509 we start at index 1 because index 0 is used
503
     for the issuer name.  */
504
0
  for (idx=!!x509 ;idx < nuids; idx++)
505
0
    {
506
0
      size_t mypos = pos;
507
0
      size_t mylen;
508
509
0
      mypos += idx*uidinfolen;
510
0
      off = get32 (buffer+mypos);
511
0
      len = get32 (buffer+mypos+4);
512
0
      if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
513
0
        return 0; /* error: better stop here - out of bounds */
514
0
      if (x509)
515
0
        {
516
0
          if (len < 2 || buffer[off] != '<')
517
0
            continue; /* empty name or trailing 0 not stored */
518
0
          len--; /* one back */
519
0
          if ( len < 3 || buffer[off+len] != '>')
520
0
            continue; /* not a proper email address */
521
0
          off++;
522
0
          len--;
523
0
        }
524
0
      else /* OpenPGP.  */
525
0
        {
526
          /* We need to forward to the mailbox part.  */
527
0
          mypos = off;
528
0
          mylen = len;
529
0
          for ( ; len && buffer[off] != '<'; len--, off++)
530
0
            ;
531
0
          if (len < 2 || buffer[off] != '<')
532
0
            {
533
              /* Mailbox not explicitly given or too short.  Restore
534
                 OFF and LEN and check whether the entire string
535
                 resembles a mailbox without the angle brackets.  */
536
0
              off = mypos;
537
0
              len = mylen;
538
0
              if (!is_valid_mailbox_mem (buffer+off, len))
539
0
                continue; /* Not a mail address. */
540
0
            }
541
0
          else /* Seems to be standard user id with mail address.  */
542
0
            {
543
0
              off++; /* Point to first char of the mail address.  */
544
0
              len--;
545
              /* Search closing '>'.  */
546
0
              for (mypos=off; len && buffer[mypos] != '>'; len--, mypos++)
547
0
                ;
548
0
              if (!len || buffer[mypos] != '>' || off == mypos)
549
0
                continue; /* Not a proper mail address.  */
550
0
              len = mypos - off;
551
0
            }
552
553
0
        }
554
555
0
      if (substr)
556
0
        {
557
0
          if (ascii_memcasemem (buffer+off, len, name, namelen))
558
0
            return idx+1; /* found */
559
0
        }
560
0
      else
561
0
        {
562
0
          if (len == namelen && !ascii_memcasecmp (buffer+off, name, len))
563
0
            return idx+1; /* found */
564
0
        }
565
0
    }
566
0
  return 0; /* not found */
567
0
}
568
569
570
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
571
 * We don't have the keygrips as meta data, thus we need to parse the
572
 * certificate. Fixme: We might want to return proper error codes
573
 * instead of failing a search for invalid certificates etc.  */
574
static int
575
blob_openpgp_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
576
0
{
577
0
  int rc = 0;
578
0
  const unsigned char *buffer;
579
0
  size_t length;
580
0
  size_t cert_off, cert_len;
581
0
  struct _keybox_openpgp_info info;
582
0
  struct _keybox_openpgp_key_info *k;
583
584
0
  buffer = _keybox_get_blob_image (blob, &length);
585
0
  if (length < 40)
586
0
    return 0; /* Too short. */
587
0
  cert_off = get32 (buffer+8);
588
0
  cert_len = get32 (buffer+12);
589
0
  if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
590
0
    return 0; /* Too short.  */
591
592
0
  if (_keybox_parse_openpgp (buffer + cert_off, cert_len, 0, NULL, &info))
593
0
    return 0; /* Parse error.  */
594
595
0
  if (!memcmp (info.primary.grip, grip, 20))
596
0
    {
597
0
      rc = 1;
598
0
      goto leave;
599
0
    }
600
601
0
  if (info.nsubkeys)
602
0
    {
603
0
      k = &info.subkeys;
604
0
      do
605
0
        {
606
0
          if (!memcmp (k->grip, grip, 20))
607
0
            {
608
0
              rc = 1;
609
0
              goto leave;
610
0
            }
611
0
          k = k->next;
612
0
        }
613
0
      while (k);
614
0
    }
615
616
0
 leave:
617
0
  _keybox_destroy_openpgp_info (&info);
618
0
  return rc;
619
0
}
620
621
622
#ifdef KEYBOX_WITH_X509
623
/* Return true if the key in BLOB matches the 20 bytes keygrip GRIP.
624
   We don't have the keygrips as meta data, thus we need to parse the
625
   certificate. Fixme: We might want to return proper error codes
626
   instead of failing a search for invalid certificates etc.  */
627
static int
628
blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
629
{
630
  int rc;
631
  const unsigned char *buffer;
632
  size_t length;
633
  size_t cert_off, cert_len;
634
  ksba_reader_t reader = NULL;
635
  ksba_cert_t cert = NULL;
636
  ksba_sexp_t p = NULL;
637
  gcry_sexp_t s_pkey;
638
  unsigned char array[20];
639
  unsigned char *rcp;
640
  size_t n;
641
642
  buffer = _keybox_get_blob_image (blob, &length);
643
  if (length < 40)
644
    return 0; /* Too short. */
645
  cert_off = get32 (buffer+8);
646
  cert_len = get32 (buffer+12);
647
  if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
648
    return 0; /* Too short.  */
649
650
  rc = ksba_reader_new (&reader);
651
  if (rc)
652
    return 0; /* Problem with ksba. */
653
  rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
654
  if (rc)
655
    goto failed;
656
  rc = ksba_cert_new (&cert);
657
  if (rc)
658
    goto failed;
659
  rc = ksba_cert_read_der (cert, reader);
660
  if (rc)
661
    goto failed;
662
  p = ksba_cert_get_public_key (cert);
663
  if (!p)
664
    goto failed;
665
  n = gcry_sexp_canon_len (p, 0, NULL, NULL);
666
  if (!n)
667
    goto failed;
668
  rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
669
  if (rc)
670
    {
671
      gcry_sexp_release (s_pkey);
672
      goto failed;
673
    }
674
  rcp = gcry_pk_get_keygrip (s_pkey, array);
675
  gcry_sexp_release (s_pkey);
676
  if (!rcp)
677
    goto failed; /* Can't calculate keygrip. */
678
679
  xfree (p);
680
  ksba_cert_release (cert);
681
  ksba_reader_release (reader);
682
  return !memcmp (array, grip, 20);
683
 failed:
684
  xfree (p);
685
  ksba_cert_release (cert);
686
  ksba_reader_release (reader);
687
  return 0;
688
}
689
#endif /*KEYBOX_WITH_X509*/
690
691
692

693
/*
694
  The has_foo functions are used as helpers for search
695
*/
696
static inline int
697
has_short_kid (KEYBOXBLOB blob, u32 lkid)
698
0
{
699
0
  size_t length;
700
0
  unsigned char buf[4];
701
702
0
  _keybox_get_blob_image (blob, &length);
703
0
  if (length < 48)
704
0
    return 0; /* blob too short */
705
706
0
  buf[0] = lkid >> 24;
707
0
  buf[1] = lkid >> 16;
708
0
  buf[2] = lkid >> 8;
709
0
  buf[3] = lkid;
710
711
0
  return blob_cmp_fpr_part (blob, buf, 16, 4);
712
0
}
713
714
static inline int
715
has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid)
716
0
{
717
0
  size_t length;
718
0
  unsigned char buf[8];
719
720
0
  _keybox_get_blob_image (blob, &length);
721
0
  if (length < 48)
722
0
    return 0; /* blob too short */
723
724
0
  buf[0] = mkid >> 24;
725
0
  buf[1] = mkid >> 16;
726
0
  buf[2] = mkid >> 8;
727
0
  buf[3] = mkid;
728
0
  buf[4] = lkid >> 24;
729
0
  buf[5] = lkid >> 16;
730
0
  buf[6] = lkid >> 8;
731
0
  buf[7] = lkid;
732
733
0
  return blob_cmp_fpr_part (blob, buf, 12, 8);
734
0
}
735
736
static inline int
737
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr, unsigned int fprlen)
738
0
{
739
0
  return blob_cmp_fpr (blob, fpr, fprlen);
740
0
}
741
742
static inline int
743
has_keygrip (KEYBOXBLOB blob, const unsigned char *grip)
744
0
{
745
0
  if (blob_get_type (blob) == KEYBOX_BLOBTYPE_PGP)
746
0
    return blob_openpgp_has_grip (blob, grip);
747
#ifdef KEYBOX_WITH_X509
748
  if (blob_get_type (blob) == KEYBOX_BLOBTYPE_X509)
749
    return blob_x509_has_grip (blob, grip);
750
#endif
751
0
  return 0;
752
0
}
753
754
755
/* The UBID is the primary fingerprint.  For OpenPGP v5 keys only the
756
 * leftmost 20 bytes (UBID_LEN) are used.  */
757
static inline int
758
has_ubid (KEYBOXBLOB blob, const unsigned char *ubid)
759
0
{
760
0
  return blob_cmp_ubid (blob, ubid);
761
0
}
762
763
764
static inline int
765
has_issuer (KEYBOXBLOB blob, const char *name)
766
0
{
767
0
  size_t namelen;
768
769
0
  return_val_if_fail (name, 0);
770
771
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
772
0
    return 0;
773
774
0
  namelen = strlen (name);
775
0
  return blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1);
776
0
}
777
778
static inline int
779
has_issuer_sn (KEYBOXBLOB blob, const char *name,
780
               const unsigned char *sn, int snlen)
781
0
{
782
0
  size_t namelen;
783
784
0
  return_val_if_fail (name, 0);
785
0
  return_val_if_fail (sn, 0);
786
787
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
788
0
    return 0;
789
790
0
  namelen = strlen (name);
791
792
0
  return (blob_cmp_sn (blob, sn, snlen)
793
0
          && blob_cmp_name (blob, 0 /* issuer */, name, namelen, 0, 1));
794
0
}
795
796
static inline int
797
has_sn (KEYBOXBLOB blob, const unsigned char *sn, int snlen)
798
0
{
799
0
  return_val_if_fail (sn, 0);
800
801
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
802
0
    return 0;
803
0
  return blob_cmp_sn (blob, sn, snlen);
804
0
}
805
806
static inline int
807
has_subject (KEYBOXBLOB blob, const char *name)
808
0
{
809
0
  size_t namelen;
810
811
0
  return_val_if_fail (name, 0);
812
813
0
  if (blob_get_type (blob) != KEYBOX_BLOBTYPE_X509)
814
0
    return 0;
815
816
0
  namelen = strlen (name);
817
0
  return blob_cmp_name (blob, 1 /* subject */, name, namelen, 0, 1);
818
0
}
819
820
821
static inline int
822
has_username (KEYBOXBLOB blob, const char *name, int substr)
823
0
{
824
0
  size_t namelen;
825
0
  int btype;
826
827
0
  return_val_if_fail (name, 0);
828
829
0
  btype = blob_get_type (blob);
830
0
  if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
831
0
    return 0;
832
833
0
  namelen = strlen (name);
834
0
  return blob_cmp_name (blob, -1 /* all subject/user names */, name,
835
0
                        namelen, substr, (btype == KEYBOX_BLOBTYPE_X509));
836
0
}
837
838
839
static inline int
840
has_mail (KEYBOXBLOB blob, const char *name, int substr)
841
0
{
842
0
  size_t namelen;
843
0
  int btype;
844
845
0
  return_val_if_fail (name, 0);
846
847
0
  btype = blob_get_type (blob);
848
0
  if (btype != KEYBOX_BLOBTYPE_PGP && btype != KEYBOX_BLOBTYPE_X509)
849
0
    return 0;
850
851
0
  if (btype == KEYBOX_BLOBTYPE_PGP && *name == '<')
852
0
    name++; /* Hack to remove the leading '<' for gpg.  */
853
854
0
  namelen = strlen (name);
855
0
  if (namelen && name[namelen-1] == '>')
856
0
    namelen--;
857
0
  return blob_cmp_mail (blob, name, namelen, substr,
858
0
                        (btype == KEYBOX_BLOBTYPE_X509));
859
0
}
860
861
862
static void
863
release_sn_array (struct sn_array_s *array, size_t size)
864
0
{
865
0
  size_t n;
866
867
0
  for (n=0; n < size; n++)
868
0
    xfree (array[n].sn);
869
0
  xfree (array);
870
0
}
871
872
873

874
/*
875
 *
876
 * The search API
877
 *
878
 */
879
880
gpg_error_t
881
keybox_search_reset (KEYBOX_HANDLE hd)
882
1.33M
{
883
1.33M
  if (!hd)
884
0
    return gpg_error (GPG_ERR_INV_VALUE);
885
886
1.33M
  if (hd->found.blob)
887
0
    {
888
0
      _keybox_release_blob (hd->found.blob);
889
0
      hd->found.blob = NULL;
890
0
    }
891
892
1.33M
  if (hd->fp)
893
28.7k
    {
894
28.7k
      if (es_fseeko (hd->fp, 0, SEEK_SET))
895
0
        {
896
          /* Ooops.  Seek did not work.  Close so that the search will
897
           * open the file again.  */
898
0
          _keybox_ll_close (hd->fp);
899
0
          hd->fp = NULL;
900
0
        }
901
28.7k
    }
902
1.33M
  hd->error = 0;
903
1.33M
  hd->eof = 0;
904
1.33M
  return 0;
905
1.33M
}
906
907
908
/* Note: When in ephemeral mode the search function does visit all
909
   blobs but in standard mode, blobs flagged as ephemeral are ignored.
910
   If WANT_BLOBTYPE is not 0 only blobs of this type are considered.
911
   The value at R_SKIPPED is updated by the number of skipped long
912
   records (counts PGP and X.509). */
913
gpg_error_t
914
keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc,
915
               keybox_blobtype_t want_blobtype,
916
               size_t *r_descindex, unsigned long *r_skipped)
917
5.09k
{
918
5.09k
  gpg_error_t rc;
919
5.09k
  size_t n;
920
5.09k
  int need_words, any_skip;
921
5.09k
  KEYBOXBLOB blob = NULL;
922
5.09k
  struct sn_array_s *sn_array = NULL;
923
5.09k
  int pk_no, uid_no;
924
5.09k
  off_t lastfoundoff;
925
926
5.09k
  if (!hd)
927
0
    return gpg_error (GPG_ERR_INV_VALUE);
928
929
  /* Clear last found result but record the offset of the last found
930
   * blob which we may need later. */
931
5.09k
  if (hd->found.blob)
932
0
    {
933
0
      lastfoundoff = _keybox_get_blob_fileoffset (hd->found.blob);
934
0
      _keybox_release_blob (hd->found.blob);
935
0
      hd->found.blob = NULL;
936
0
    }
937
5.09k
  else
938
5.09k
    lastfoundoff = 0;
939
940
5.09k
  if (hd->error)
941
0
    return hd->error; /* still in error state */
942
5.09k
  if (hd->eof)
943
0
    return -1; /* still EOF */
944
945
  /* figure out what information we need */
946
5.09k
  need_words = any_skip = 0;
947
10.1k
  for (n=0; n < ndesc; n++)
948
5.09k
    {
949
5.09k
      switch (desc[n].mode)
950
5.09k
        {
951
0
        case KEYDB_SEARCH_MODE_WORDS:
952
0
          need_words = 1;
953
0
          break;
954
4.80k
        case KEYDB_SEARCH_MODE_FIRST:
955
          /* always restart the search in this mode */
956
4.80k
          keybox_search_reset (hd);
957
4.80k
          lastfoundoff = 0;
958
4.80k
          break;
959
298
        default:
960
298
          break;
961
5.09k
  }
962
5.09k
      if (desc[n].skipfnc)
963
0
        any_skip = 1;
964
5.09k
      if (desc[n].snhex && !sn_array)
965
0
        {
966
0
          sn_array = xtrycalloc (ndesc, sizeof *sn_array);
967
0
          if (!sn_array)
968
0
            return (hd->error = gpg_error_from_syserror ());
969
0
        }
970
5.09k
    }
971
972
5.09k
  (void)need_words;  /* Not yet implemented.  */
973
974
5.09k
  if (!hd->fp)
975
5.04k
    {
976
5.04k
      rc = _keybox_ll_open (&hd->fp, hd->kb->fname, 0);
977
5.04k
      if (rc)
978
0
        {
979
0
          xfree (sn_array);
980
0
          return rc;
981
0
        }
982
      /* log_debug ("%s: re-opened file\n", __func__); */
983
5.04k
      if (ndesc && desc[0].mode != KEYDB_SEARCH_MODE_FIRST && lastfoundoff)
984
0
        {
985
          /* Search mode is not first and the last search operation
986
           * returned a blob which also was not the first one.  We now
987
           * need to skip over that blob and hope that the file has
988
           * not changed.  */
989
0
          if (es_fseeko (hd->fp, lastfoundoff, SEEK_SET))
990
0
            {
991
0
              rc = gpg_error_from_syserror ();
992
0
              log_debug ("%s: seeking to last found offset failed: %s\n",
993
0
                         __func__, gpg_strerror (rc));
994
0
              xfree (sn_array);
995
0
              return gpg_error (GPG_ERR_NOTHING_FOUND);
996
0
            }
997
          /* log_debug ("%s: re-opened file and sought to last offset\n", */
998
          /*            __func__); */
999
0
          rc = _keybox_read_blob (NULL, hd->fp, NULL);
1000
0
          if (rc)
1001
0
            {
1002
0
              log_debug ("%s: skipping last found blob failed: %s\n",
1003
0
                         __func__, gpg_strerror (rc));
1004
0
              xfree (sn_array);
1005
0
              return gpg_error (GPG_ERR_NOTHING_FOUND);
1006
0
            }
1007
0
        }
1008
5.04k
    }
1009
1010
  /* Kludge: We need to convert an SN given as hexstring to its binary
1011
     representation - in some cases we are not able to store it in the
1012
     search descriptor, because due to the way we use it, it is not
1013
     possible to free allocated memory. */
1014
5.09k
  if (sn_array)
1015
0
    {
1016
0
      const unsigned char *s;
1017
0
      int i, odd;
1018
0
      size_t snlen;
1019
1020
0
      for (n=0; n < ndesc; n++)
1021
0
        {
1022
0
          if (!desc[n].sn)
1023
0
            ;
1024
0
          else if (desc[n].snhex)
1025
0
            {
1026
0
              unsigned char *sn;
1027
1028
0
              s = desc[n].sn;
1029
0
              for (i=0; *s && *s != '/' && i < desc[n].snlen; s++, i++)
1030
0
                ;
1031
0
              odd = (i & 1);
1032
0
              snlen = (i+1)/2;
1033
0
              sn_array[n].sn = xtrymalloc (snlen);
1034
0
              if (!sn_array[n].sn)
1035
0
                {
1036
0
                  hd->error = gpg_error_from_syserror ();
1037
0
                  release_sn_array (sn_array, n);
1038
0
                  return hd->error;
1039
0
                }
1040
0
              sn_array[n].snlen = snlen;
1041
0
              sn = sn_array[n].sn;
1042
0
              s = desc[n].sn;
1043
0
              if (odd)
1044
0
                {
1045
0
                  *sn++ = xtoi_1 (s);
1046
0
                  s++;
1047
0
                }
1048
0
              for (; *s && *s != '/';  s += 2)
1049
0
                *sn++ = xtoi_2 (s);
1050
0
            }
1051
0
          else
1052
0
            {
1053
0
              const unsigned char *sn;
1054
1055
0
              sn = desc[n].sn;
1056
0
              snlen = desc[n].snlen;
1057
0
              sn_array[n].sn = xtrymalloc (snlen);
1058
0
              if (!sn_array[n].sn)
1059
0
                {
1060
0
                  hd->error = gpg_error_from_syserror ();
1061
0
                  release_sn_array (sn_array, n);
1062
0
                  return hd->error;
1063
0
                }
1064
0
              sn_array[n].snlen = snlen;
1065
0
              memcpy (sn_array[n].sn, sn, snlen);
1066
0
            }
1067
0
        }
1068
0
    }
1069
1070
1071
5.09k
  pk_no = uid_no = 0;
1072
5.09k
  for (;;)
1073
10.1k
    {
1074
10.1k
      unsigned int blobflags;
1075
10.1k
      int blobtype;
1076
1077
10.1k
      _keybox_release_blob (blob); blob = NULL;
1078
10.1k
      rc = _keybox_read_blob (&blob, hd->fp, NULL);
1079
10.1k
      if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
1080
0
          && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
1081
0
        {
1082
0
          ++*r_skipped;
1083
0
          continue; /* Skip too large records.  */
1084
0
        }
1085
1086
10.1k
      if (rc)
1087
5.09k
        break;
1088
1089
5.09k
      blobtype = blob_get_type (blob);
1090
5.09k
      if (blobtype == KEYBOX_BLOBTYPE_HEADER)
1091
5.09k
        continue;
1092
0
      if (want_blobtype && blobtype != want_blobtype)
1093
0
        continue;
1094
1095
0
      blobflags = blob_get_blob_flags (blob);
1096
0
      if (!hd->ephemeral && (blobflags & 2))
1097
0
        continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
1098
1099
0
      for (n=0; n < ndesc; n++)
1100
0
        {
1101
0
          switch (desc[n].mode)
1102
0
            {
1103
0
            case KEYDB_SEARCH_MODE_NONE:
1104
0
              never_reached ();
1105
0
              break;
1106
0
            case KEYDB_SEARCH_MODE_EXACT:
1107
0
              uid_no = has_username (blob, desc[n].u.name, 0);
1108
0
              if (uid_no)
1109
0
                goto found;
1110
0
              break;
1111
0
            case KEYDB_SEARCH_MODE_MAIL:
1112
0
              uid_no = has_mail (blob, desc[n].u.name, 0);
1113
0
              if (uid_no)
1114
0
                goto found;
1115
0
              break;
1116
0
            case KEYDB_SEARCH_MODE_MAILSUB:
1117
0
              uid_no = has_mail (blob, desc[n].u.name, 1);
1118
0
              if (uid_no)
1119
0
                goto found;
1120
0
              break;
1121
0
            case KEYDB_SEARCH_MODE_SUBSTR:
1122
0
              uid_no =  has_username (blob, desc[n].u.name, 1);
1123
0
              if (uid_no)
1124
0
                goto found;
1125
0
              break;
1126
0
            case KEYDB_SEARCH_MODE_MAILEND:
1127
0
            case KEYDB_SEARCH_MODE_WORDS:
1128
              /* not yet implemented */
1129
0
              break;
1130
0
            case KEYDB_SEARCH_MODE_ISSUER:
1131
0
              if (has_issuer (blob, desc[n].u.name))
1132
0
                goto found;
1133
0
              break;
1134
0
            case KEYDB_SEARCH_MODE_ISSUER_SN:
1135
0
              if (has_issuer_sn (blob, desc[n].u.name,
1136
0
                                 sn_array? sn_array[n].sn : desc[n].sn,
1137
0
                                 sn_array? sn_array[n].snlen : desc[n].snlen))
1138
0
                goto found;
1139
0
              break;
1140
0
            case KEYDB_SEARCH_MODE_SN:
1141
0
              if (has_sn (blob, sn_array? sn_array[n].sn : desc[n].sn,
1142
0
                                sn_array? sn_array[n].snlen : desc[n].snlen))
1143
0
                goto found;
1144
0
              break;
1145
0
            case KEYDB_SEARCH_MODE_SUBJECT:
1146
0
              if (has_subject (blob, desc[n].u.name))
1147
0
                goto found;
1148
0
              break;
1149
0
            case KEYDB_SEARCH_MODE_SHORT_KID:
1150
0
              pk_no = has_short_kid (blob, desc[n].u.kid[1]);
1151
0
              if (pk_no)
1152
0
                goto found;
1153
0
              break;
1154
0
            case KEYDB_SEARCH_MODE_LONG_KID:
1155
0
              pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
1156
0
              if (pk_no)
1157
0
                goto found;
1158
0
              break;
1159
1160
0
            case KEYDB_SEARCH_MODE_FPR:
1161
0
              pk_no = has_fingerprint (blob, desc[n].u.fpr, desc[n].fprlen);
1162
0
              if (pk_no)
1163
0
                goto found;
1164
0
              break;
1165
1166
0
            case KEYDB_SEARCH_MODE_KEYGRIP:
1167
0
              if (has_keygrip (blob, desc[n].u.grip))
1168
0
                goto found;
1169
0
              break;
1170
0
            case KEYDB_SEARCH_MODE_UBID:
1171
0
              if (has_ubid (blob, desc[n].u.ubid))
1172
0
                goto found;
1173
0
              break;
1174
0
            case KEYDB_SEARCH_MODE_FIRST:
1175
0
              goto found;
1176
0
              break;
1177
0
            case KEYDB_SEARCH_MODE_NEXT:
1178
0
              goto found;
1179
0
              break;
1180
0
            default:
1181
0
              rc = gpg_error (GPG_ERR_INV_VALUE);
1182
0
              goto found;
1183
0
            }
1184
0
  }
1185
0
      continue;
1186
0
    found:
1187
      /* Record which DESC we matched on.  Note this value is only
1188
   meaningful if this function returns with no errors. */
1189
0
      if(r_descindex)
1190
0
  *r_descindex = n;
1191
0
      for (n=any_skip?0:ndesc; n < ndesc; n++)
1192
0
        {
1193
0
          u32 kid[2];
1194
1195
0
          if (desc[n].skipfnc
1196
0
              && blob_get_first_keyid (blob, kid)
1197
0
        && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no))
1198
0
    break;
1199
0
        }
1200
0
      if (n == ndesc)
1201
0
        break; /* got it */
1202
0
    }
1203
1204
5.09k
  if (!rc)
1205
0
    {
1206
0
      hd->found.blob = blob;
1207
0
      hd->found.pk_no = pk_no;
1208
0
      hd->found.uid_no = uid_no;
1209
0
    }
1210
5.09k
  else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
1211
5.09k
    {
1212
5.09k
      _keybox_release_blob (blob);
1213
5.09k
      hd->eof = 1;
1214
5.09k
    }
1215
0
  else
1216
0
    {
1217
0
      _keybox_release_blob (blob);
1218
0
      hd->error = rc;
1219
0
    }
1220
1221
5.09k
  if (sn_array)
1222
0
    release_sn_array (sn_array, ndesc);
1223
1224
5.09k
  return rc;
1225
5.09k
}
1226
1227
1228
1229

1230
/*
1231
 * Functions to return a certificate or a keyblock.  To be used after
1232
 * a successful search operation.
1233
 */
1234
1235
/* Return the raw data from the last found blob.  Caller must release
1236
 * the value stored at R_BUFFER.  If called with NULL for R_BUFFER
1237
 * only the needed length for the buffer and the public key type is
1238
 * returned.  R_PUBKEY_TYPE and R_UBID can be used to return these
1239
 * attributes. */
1240
gpg_error_t
1241
keybox_get_data (KEYBOX_HANDLE hd, void **r_buffer, size_t *r_length,
1242
                 enum pubkey_types *r_pubkey_type, unsigned char *r_ubid)
1243
0
{
1244
0
  const unsigned char *buffer;
1245
0
  size_t length;
1246
0
  size_t image_off, image_len;
1247
1248
0
  if (r_buffer)
1249
0
    *r_buffer = NULL;
1250
0
  if (r_length)
1251
0
    *r_length = 0;
1252
0
  if (r_pubkey_type)
1253
0
    *r_pubkey_type = PUBKEY_TYPE_UNKNOWN;
1254
1255
0
  if (!hd)
1256
0
    return gpg_error (GPG_ERR_INV_VALUE);
1257
0
  if (!hd->found.blob)
1258
0
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1259
1260
0
  switch (blob_get_type (hd->found.blob))
1261
0
    {
1262
0
    case KEYBOX_BLOBTYPE_PGP:
1263
0
      if (r_pubkey_type)
1264
0
        *r_pubkey_type = PUBKEY_TYPE_OPGP;
1265
0
      break;
1266
0
    case KEYBOX_BLOBTYPE_X509:
1267
0
      if (r_pubkey_type)
1268
0
        *r_pubkey_type = PUBKEY_TYPE_X509;
1269
0
      break;
1270
0
    default:
1271
0
      return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1272
0
    }
1273
1274
0
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1275
0
  if (length < 40)
1276
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1277
0
  image_off = get32 (buffer+8);
1278
0
  image_len = get32 (buffer+12);
1279
0
  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
1280
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1281
1282
0
  if (r_ubid)
1283
0
    {
1284
0
      size_t keyinfolen;
1285
1286
      /* We do a quick but sufficient consistency check.  For the full
1287
       * check see blob_cmp_ubid.  */
1288
0
      if (!get16 (buffer + 16)         /* No keys.  */
1289
0
          || (keyinfolen = get16 (buffer + 18)) < 28
1290
0
          || (20 + (uint64_t)keyinfolen) > (uint64_t)length)
1291
0
        return gpg_error (GPG_ERR_TOO_SHORT);
1292
1293
0
      memcpy (r_ubid, buffer + 20, UBID_LEN);
1294
0
    }
1295
1296
0
  if (r_length)
1297
0
    *r_length = image_len;
1298
0
  if (r_buffer)
1299
0
    {
1300
0
      *r_buffer = xtrymalloc (image_len);
1301
0
      if (!*r_buffer)
1302
0
        return gpg_error_from_syserror ();
1303
0
      memcpy (*r_buffer, buffer + image_off, image_len);
1304
0
    }
1305
1306
0
  return 0;
1307
0
}
1308
1309
1310
/* Return the last found keyblock.  Returns 0 on success and stores a
1311
 * new iobuf at R_IOBUF.  R_UID_NO and R_PK_NO are used to return the
1312
 * index of the key or user id which matched the search criteria; if
1313
 * not known they are set to 0. */
1314
gpg_error_t
1315
keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
1316
                     int *r_pk_no, int *r_uid_no)
1317
0
{
1318
0
  gpg_error_t err;
1319
0
  const unsigned char *buffer;
1320
0
  size_t length;
1321
0
  size_t image_off, image_len;
1322
0
  size_t siginfo_off, siginfo_len;
1323
1324
0
  *r_iobuf = NULL;
1325
1326
0
  if (!hd)
1327
0
    return gpg_error (GPG_ERR_INV_VALUE);
1328
0
  if (!hd->found.blob)
1329
0
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1330
1331
0
  if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1332
0
    return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1333
1334
0
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1335
0
  if (length < 40)
1336
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1337
0
  image_off = get32 (buffer+8);
1338
0
  image_len = get32 (buffer+12);
1339
0
  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
1340
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1341
1342
0
  err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1343
0
                                   &siginfo_off, &siginfo_len);
1344
0
  if (err)
1345
0
    return err;
1346
1347
0
  *r_pk_no  = hd->found.pk_no;
1348
0
  *r_uid_no = hd->found.uid_no;
1349
0
  *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1350
0
  return 0;
1351
0
}
1352
1353
1354
#ifdef KEYBOX_WITH_X509
1355
/*
1356
  Return the last found cert.  Caller must free it.
1357
 */
1358
int
1359
keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
1360
{
1361
  const unsigned char *buffer;
1362
  size_t length;
1363
  size_t cert_off, cert_len;
1364
  ksba_reader_t reader = NULL;
1365
  ksba_cert_t cert = NULL;
1366
  unsigned int blobflags;
1367
  int rc;
1368
1369
  if (!hd)
1370
    return gpg_error (GPG_ERR_INV_VALUE);
1371
  if (!hd->found.blob)
1372
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1373
1374
  if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_X509)
1375
    return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1376
1377
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1378
  if (length < 40)
1379
    return gpg_error (GPG_ERR_TOO_SHORT);
1380
  cert_off = get32 (buffer+8);
1381
  cert_len = get32 (buffer+12);
1382
  if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
1383
    return gpg_error (GPG_ERR_TOO_SHORT);
1384
1385
  rc = ksba_reader_new (&reader);
1386
  if (rc)
1387
    return rc;
1388
  rc = ksba_reader_set_mem (reader, buffer+cert_off, cert_len);
1389
  if (rc)
1390
    {
1391
      ksba_reader_release (reader);
1392
      /* fixme: need to map the error codes */
1393
      return gpg_error (GPG_ERR_GENERAL);
1394
    }
1395
1396
  rc = ksba_cert_new (&cert);
1397
  if (rc)
1398
    {
1399
      ksba_reader_release (reader);
1400
      return rc;
1401
    }
1402
1403
  rc = ksba_cert_read_der (cert, reader);
1404
  if (rc)
1405
    {
1406
      ksba_cert_release (cert);
1407
      ksba_reader_release (reader);
1408
      /* fixme: need to map the error codes */
1409
      return gpg_error (GPG_ERR_GENERAL);
1410
    }
1411
1412
  rc = get_flag_from_image (buffer, length, KEYBOX_FLAG_BLOB, &blobflags);
1413
  if (!rc)
1414
    rc = ksba_cert_set_user_data (cert, "keydb.blobflags",
1415
                                  &blobflags, sizeof blobflags);
1416
  if (rc)
1417
    {
1418
      ksba_cert_release (cert);
1419
      ksba_reader_release (reader);
1420
      return gpg_error (rc);
1421
    }
1422
1423
  *r_cert = cert;
1424
  ksba_reader_release (reader);
1425
  return 0;
1426
}
1427
1428
#endif /*KEYBOX_WITH_X509*/
1429
1430
/* Return the flags named WHAT at the address of VALUE. IDX is used
1431
   only for certain flags and should be 0 if not required. */
1432
int
1433
keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value)
1434
0
{
1435
0
  const unsigned char *buffer;
1436
0
  size_t length;
1437
0
  gpg_err_code_t ec;
1438
1439
0
  (void)idx; /* Not yet used.  */
1440
1441
0
  if (!hd)
1442
0
    return gpg_error (GPG_ERR_INV_VALUE);
1443
0
  if (!hd->found.blob)
1444
0
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1445
1446
0
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1447
0
  ec = get_flag_from_image (buffer, length, what, value);
1448
0
  return ec? gpg_error (ec):0;
1449
0
}
1450
1451
off_t
1452
keybox_offset (KEYBOX_HANDLE hd)
1453
0
{
1454
0
  if (!hd->fp)
1455
0
    return 0;
1456
0
  return es_ftello (hd->fp);
1457
0
}
1458
1459
gpg_error_t
1460
keybox_seek (KEYBOX_HANDLE hd, off_t offset)
1461
0
{
1462
0
  gpg_error_t err;
1463
1464
0
  if (hd->error)
1465
0
    return hd->error; /* still in error state */
1466
1467
0
  if (! hd->fp)
1468
0
    {
1469
0
      if (!offset)
1470
0
        {
1471
          /* No need to open the file.  An unopened file is effectively at
1472
             offset 0.  */
1473
0
          return 0;
1474
0
        }
1475
1476
0
      err = _keybox_ll_open (&hd->fp, hd->kb->fname, 0);
1477
0
      if (err)
1478
0
        return err;
1479
0
    }
1480
1481
0
  err = es_fseeko (hd->fp, offset, SEEK_SET);
1482
0
  hd->error = gpg_error_from_errno (err);
1483
1484
0
  return hd->error;
1485
0
}