Coverage Report

Created: 2026-09-14 07:17

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