Coverage Report

Created: 2026-08-13 06:32

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
23.5k
#define get32(a) buf32_to_ulong ((a))
45
632k
#define get16(a) buf16_to_ulong ((a))
46
47
48
static inline unsigned int
49
blob_get_blob_flags (KEYBOXBLOB blob)
50
182k
{
51
182k
  const unsigned char *buffer;
52
182k
  size_t length;
53
54
182k
  buffer = _keybox_get_blob_image (blob, &length);
55
182k
  if (length < 8)
56
0
    return 0; /* oops */
57
58
182k
  return get16 (buffer + 6);
59
182k
}
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
11.7k
{
106
11.7k
  size_t pos;
107
11.7k
  size_t nkeys, keyinfolen;
108
11.7k
  size_t nuids, uidinfolen;
109
11.7k
  size_t nserial;
110
11.7k
  size_t nsigs, siginfolen, siginfooff;
111
112
11.7k
  switch (what)
113
11.7k
    {
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
11.7k
    case KEYBOX_FLAG_SIG_INFO:
125
11.7k
      if (length < 20)
126
0
        return GPG_ERR_INV_OBJ;
127
      /* Key info. */
128
11.7k
      nkeys = get16 (buffer + 16);
129
11.7k
      keyinfolen = get16 (buffer + 18 );
130
11.7k
      if (keyinfolen < 28)
131
0
        return GPG_ERR_INV_OBJ;
132
11.7k
      pos = 20 + keyinfolen*nkeys;
133
11.7k
      if (pos+2 > length)
134
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
135
      /* Serial number. */
136
11.7k
      nserial = get16 (buffer+pos);
137
11.7k
      pos += 2 + nserial;
138
11.7k
      if (pos+4 > length)
139
0
        return GPG_ERR_INV_OBJ; /* Out of bounds. */
140
      /* User IDs. */
141
11.7k
      nuids = get16 (buffer + pos); pos += 2;
142
11.7k
      uidinfolen = get16 (buffer + pos); pos += 2;
143
11.7k
      if (uidinfolen < 12 )
144
0
        return GPG_ERR_INV_OBJ;
145
11.7k
      pos += uidinfolen*nuids;
146
11.7k
      if (pos+4 > length)
147
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
148
      /* Signature info. */
149
11.7k
      siginfooff = pos;
150
11.7k
      nsigs = get16 (buffer + pos); pos += 2;
151
11.7k
      siginfolen = get16 (buffer + pos); pos += 2;
152
11.7k
      if (siginfolen < 4 )
153
0
        return GPG_ERR_INV_OBJ;
154
11.7k
      pos += siginfolen*nsigs;
155
11.7k
      if (pos+1+1+2+4+4+4+4 > length)
156
0
        return GPG_ERR_INV_OBJ ; /* Out of bounds. */
157
11.7k
      *flag_size = 1;
158
11.7k
      *flag_off = pos;
159
11.7k
      switch (what)
160
11.7k
        {
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+1+2+4+4;
167
0
          break;
168
11.7k
        case KEYBOX_FLAG_SIG_INFO:
169
11.7k
          *flag_size = siginfolen * nsigs;
170
11.7k
          *flag_off = siginfooff;
171
11.7k
          break;
172
0
        default:
173
0
          break;
174
11.7k
        }
175
11.7k
      break;
176
177
11.7k
    default:
178
0
      return GPG_ERR_INV_FLAG;
179
11.7k
    }
180
11.7k
  return 0;
181
11.7k
}
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
35.3k
{
247
35.3k
  const unsigned char *buffer;
248
35.3k
  size_t length;
249
35.3k
  size_t pos, off;
250
35.3k
  size_t nkeys, keyinfolen;
251
35.3k
  int idx, fpr32, storedfprlen;
252
253
35.3k
  buffer = _keybox_get_blob_image (blob, &length);
254
35.3k
  if (length < 40)
255
0
    return 0; /* blob too short */
256
35.3k
  fpr32 = buffer[5] == 2;
257
258
  /*keys*/
259
35.3k
  nkeys = get16 (buffer + 16);
260
35.3k
  keyinfolen = get16 (buffer + 18 );
261
35.3k
  if (keyinfolen < (fpr32?56:28))
262
0
    return 0; /* invalid blob */
263
35.3k
  pos = 20;
264
35.3k
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
265
0
    return 0; /* out of bounds */
266
267
296k
  for (idx=0; idx < nkeys; idx++)
268
268k
    {
269
268k
      off = pos + idx*keyinfolen;
270
268k
      if (fpr32)
271
2.92k
        storedfprlen = (get16 (buffer + off + 32) & 0x80)? 32:20;
272
265k
      else
273
265k
        storedfprlen = 20;
274
268k
      if (storedfprlen == fprlen
275
249k
          && !memcmp (buffer + off, fpr, storedfprlen))
276
7.63k
        return idx+1; /* found */
277
268k
    }
278
27.7k
  return 0; /* not found */
279
35.3k
}
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
147k
{
288
147k
  const unsigned char *buffer;
289
147k
  size_t length;
290
147k
  size_t pos, off;
291
147k
  size_t nkeys, keyinfolen;
292
147k
  int idx;
293
147k
  int fpr32;    /* Set if this blob stores all fingerprints as 32 bytes. */
294
295
147k
  buffer = _keybox_get_blob_image (blob, &length);
296
147k
  if (length < 40)
297
0
    return 0; /* blob too short */
298
147k
  fpr32 = buffer[5] == 2;
299
300
  /*keys*/
301
147k
  nkeys = get16 (buffer + 16);
302
147k
  keyinfolen = get16 (buffer + 18 );
303
147k
  if (keyinfolen < (fpr32?56:28))
304
0
    return 0; /* invalid blob */
305
147k
  pos = 20;
306
147k
  if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
307
0
    return 0; /* out of bounds */
308
309
1.08M
  for (idx=0; idx < nkeys; idx++)
310
948k
    {
311
948k
      off = pos + idx*keyinfolen;
312
948k
      if (!fpr32)
313
936k
        {
314
          /* Blob has only 20 fingerprints - use the FPROFF.    */
315
936k
          if (!memcmp (buffer + off + fproff, fpr, fprlen))
316
6.99k
            return idx+1; /* found */
317
936k
        }
318
12.5k
      else if ((buffer[off + 32 + 1] & 0x80))
319
12.5k
        {
320
          /* This (sub)key has a 32 byte fpr -> use 0 as offset. */
321
12.5k
          if (!memcmp (buffer + off, fpr, fprlen))
322
8
            return idx+1; /* found */
323
12.5k
        }
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
948k
    }
331
140k
  return 0; /* not found */
332
147k
}
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
147k
{
717
147k
  size_t length;
718
147k
  unsigned char buf[8];
719
720
147k
  _keybox_get_blob_image (blob, &length);
721
147k
  if (length < 48)
722
0
    return 0; /* blob too short */
723
724
147k
  buf[0] = mkid >> 24;
725
147k
  buf[1] = mkid >> 16;
726
147k
  buf[2] = mkid >> 8;
727
147k
  buf[3] = mkid;
728
147k
  buf[4] = lkid >> 24;
729
147k
  buf[5] = lkid >> 16;
730
147k
  buf[6] = lkid >> 8;
731
147k
  buf[7] = lkid;
732
733
147k
  return blob_cmp_fpr_part (blob, buf, 12, 8);
734
147k
}
735
736
static inline int
737
has_fingerprint (KEYBOXBLOB blob, const unsigned char *fpr, unsigned int fprlen)
738
35.3k
{
739
35.3k
  return blob_cmp_fpr (blob, fpr, fprlen);
740
35.3k
}
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
811k
{
883
811k
  if (!hd)
884
0
    return gpg_error (GPG_ERR_INV_VALUE);
885
886
811k
  if (hd->found.blob)
887
6.65k
    {
888
6.65k
      _keybox_release_blob (hd->found.blob);
889
6.65k
      hd->found.blob = NULL;
890
6.65k
    }
891
892
811k
  if (hd->fp)
893
88.0k
    {
894
88.0k
      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
88.0k
    }
902
811k
  hd->error = 0;
903
811k
  hd->eof = 0;
904
811k
  return 0;
905
811k
}
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
61.0k
{
918
61.0k
  gpg_error_t rc;
919
61.0k
  size_t n;
920
61.0k
  int need_words, any_skip;
921
61.0k
  KEYBOXBLOB blob = NULL;
922
61.0k
  struct sn_array_s *sn_array = NULL;
923
61.0k
  int pk_no, uid_no;
924
61.0k
  off_t lastfoundoff;
925
926
61.0k
  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
61.0k
  if (hd->found.blob)
932
2.98k
    {
933
2.98k
      lastfoundoff = _keybox_get_blob_fileoffset (hd->found.blob);
934
2.98k
      _keybox_release_blob (hd->found.blob);
935
2.98k
      hd->found.blob = NULL;
936
2.98k
    }
937
58.0k
  else
938
58.0k
    lastfoundoff = 0;
939
940
61.0k
  if (hd->error)
941
0
    return hd->error; /* still in error state */
942
61.0k
  if (hd->eof)
943
0
    return -1; /* still EOF */
944
945
  /* figure out what information we need */
946
61.0k
  need_words = any_skip = 0;
947
122k
  for (n=0; n < ndesc; n++)
948
61.0k
    {
949
61.0k
      switch (desc[n].mode)
950
61.0k
        {
951
0
        case KEYDB_SEARCH_MODE_WORDS:
952
0
          need_words = 1;
953
0
          break;
954
36.7k
        case KEYDB_SEARCH_MODE_FIRST:
955
          /* always restart the search in this mode */
956
36.7k
          keybox_search_reset (hd);
957
36.7k
          lastfoundoff = 0;
958
36.7k
          break;
959
24.2k
        default:
960
24.2k
          break;
961
61.0k
  }
962
61.0k
      if (desc[n].skipfnc)
963
0
        any_skip = 1;
964
61.0k
      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
61.0k
    }
971
972
61.0k
  (void)need_words;  /* Not yet implemented.  */
973
974
61.0k
  if (!hd->fp)
975
50.1k
    {
976
50.1k
      rc = _keybox_ll_open (&hd->fp, hd->kb->fname, 0);
977
50.1k
      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
50.1k
      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
50.1k
    }
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
61.0k
  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
61.0k
  pk_no = uid_no = 0;
1072
61.0k
  for (;;)
1073
286k
    {
1074
286k
      unsigned int blobflags;
1075
286k
      int blobtype;
1076
1077
286k
      _keybox_release_blob (blob); blob = NULL;
1078
286k
      rc = _keybox_read_blob (&blob, hd->fp, NULL);
1079
286k
      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
286k
      if (rc)
1087
46.3k
        break;
1088
1089
240k
      blobtype = blob_get_type (blob);
1090
240k
      if (blobtype == KEYBOX_BLOBTYPE_HEADER)
1091
58.0k
        continue;
1092
182k
      if (want_blobtype && blobtype != want_blobtype)
1093
0
        continue;
1094
1095
182k
      blobflags = blob_get_blob_flags (blob);
1096
182k
      if (!hd->ephemeral && (blobflags & 2))
1097
0
        continue; /* Not in ephemeral mode but blob is flagged ephemeral.  */
1098
1099
350k
      for (n=0; n < ndesc; n++)
1100
182k
        {
1101
182k
          switch (desc[n].mode)
1102
182k
            {
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
147k
            case KEYDB_SEARCH_MODE_LONG_KID:
1155
147k
              pk_no = has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1]);
1156
147k
              if (pk_no)
1157
7.00k
                goto found;
1158
140k
              break;
1159
1160
140k
            case KEYDB_SEARCH_MODE_FPR:
1161
35.3k
              pk_no = has_fingerprint (blob, desc[n].u.fpr, desc[n].fprlen);
1162
35.3k
              if (pk_no)
1163
7.63k
                goto found;
1164
27.7k
              break;
1165
1166
27.7k
            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
182k
            }
1184
182k
  }
1185
167k
      continue;
1186
167k
    found:
1187
      /* Record which DESC we matched on.  Note this value is only
1188
   meaningful if this function returns with no errors. */
1189
14.6k
      if(r_descindex)
1190
0
  *r_descindex = n;
1191
14.6k
      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
14.6k
      if (n == ndesc)
1201
14.6k
        break; /* got it */
1202
14.6k
    }
1203
1204
61.0k
  if (!rc)
1205
14.6k
    {
1206
14.6k
      hd->found.blob = blob;
1207
14.6k
      hd->found.pk_no = pk_no;
1208
14.6k
      hd->found.uid_no = uid_no;
1209
14.6k
    }
1210
46.3k
  else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
1211
46.3k
    {
1212
46.3k
      _keybox_release_blob (blob);
1213
46.3k
      hd->eof = 1;
1214
46.3k
    }
1215
0
  else
1216
0
    {
1217
0
      _keybox_release_blob (blob);
1218
0
      hd->error = rc;
1219
0
    }
1220
1221
61.0k
  if (sn_array)
1222
0
    release_sn_array (sn_array, ndesc);
1223
1224
61.0k
  return rc;
1225
61.0k
}
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
11.7k
{
1318
11.7k
  gpg_error_t err;
1319
11.7k
  const unsigned char *buffer;
1320
11.7k
  size_t length;
1321
11.7k
  size_t image_off, image_len;
1322
11.7k
  size_t siginfo_off, siginfo_len;
1323
1324
11.7k
  *r_iobuf = NULL;
1325
1326
11.7k
  if (!hd)
1327
0
    return gpg_error (GPG_ERR_INV_VALUE);
1328
11.7k
  if (!hd->found.blob)
1329
0
    return gpg_error (GPG_ERR_NOTHING_FOUND);
1330
1331
11.7k
  if (blob_get_type (hd->found.blob) != KEYBOX_BLOBTYPE_PGP)
1332
0
    return gpg_error (GPG_ERR_WRONG_BLOB_TYPE);
1333
1334
11.7k
  buffer = _keybox_get_blob_image (hd->found.blob, &length);
1335
11.7k
  if (length < 40)
1336
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1337
11.7k
  image_off = get32 (buffer+8);
1338
11.7k
  image_len = get32 (buffer+12);
1339
11.7k
  if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
1340
0
    return gpg_error (GPG_ERR_TOO_SHORT);
1341
1342
11.7k
  err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
1343
11.7k
                                   &siginfo_off, &siginfo_len);
1344
11.7k
  if (err)
1345
0
    return err;
1346
1347
11.7k
  *r_pk_no  = hd->found.pk_no;
1348
11.7k
  *r_uid_no = hd->found.uid_no;
1349
11.7k
  *r_iobuf = iobuf_temp_with_content (buffer+image_off, image_len);
1350
11.7k
  return 0;
1351
11.7k
}
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
1.66k
{
1454
1.66k
  if (!hd->fp)
1455
0
    return 0;
1456
1.66k
  return es_ftello (hd->fp);
1457
1.66k
}
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
}